[{"data":1,"prerenderedAt":2227},["ShallowReactive",2],{"docs-nav:fr":3,"docs:\u002Ffr\u002Fdocs\u002Fbusiness\u002Fhandlers":137},[4],{"title":5,"path":6,"stem":7,"children":8,"page":44},"Fr","\u002Ffr","fr",[9],{"title":10,"path":11,"stem":12,"children":13},"Qu'est-ce que Fougere","\u002Ffr\u002Fdocs","fr\u002Fdocs\u002Findex",[14,15,19,23,27,45,66,95,116],{"title":10,"path":11,"stem":12},{"title":16,"path":17,"stem":18},"Démarrer","\u002Ffr\u002Fdocs\u002Fgetting-started","fr\u002Fdocs\u002F01.getting-started",{"title":20,"path":21,"stem":22},"App Nuxt existante","\u002Ffr\u002Fdocs\u002Fexisting-app","fr\u002Fdocs\u002F02.existing-app",{"title":24,"path":25,"stem":26},"La CLI","\u002Ffr\u002Fdocs\u002Fcli","fr\u002Fdocs\u002F03.cli",{"title":28,"path":29,"stem":30,"children":31,"page":44},"Concepts","\u002Ffr\u002Fdocs\u002Fconcepts","fr\u002Fdocs\u002F2.concepts",[32,36,40],{"title":33,"path":34,"stem":35},"Philosophie","\u002Ffr\u002Fdocs\u002Fconcepts\u002Fphilosophy","fr\u002Fdocs\u002F2.concepts\u002F1.philosophy",{"title":37,"path":38,"stem":39},"La Frond","\u002Ffr\u002Fdocs\u002Fconcepts\u002Ffrond","fr\u002Fdocs\u002F2.concepts\u002F2.frond",{"title":41,"path":42,"stem":43},"Le chemin le plus court","\u002Ffr\u002Fdocs\u002Fconcepts\u002Fshortest-path","fr\u002Fdocs\u002F2.concepts\u002F3.shortest-path",false,{"title":46,"path":47,"stem":48,"children":49,"page":44},"Schéma","\u002Ffr\u002Fdocs\u002Fschema","fr\u002Fdocs\u002F3.schema",[50,54,58,62],{"title":51,"path":52,"stem":53},"Entités","\u002Ffr\u002Fdocs\u002Fschema\u002Fentities","fr\u002Fdocs\u002F3.schema\u002F1.entities",{"title":55,"path":56,"stem":57},"Vues","\u002Ffr\u002Fdocs\u002Fschema\u002Fviews","fr\u002Fdocs\u002F3.schema\u002F2.views",{"title":59,"path":60,"stem":61},"La carte d'identité","\u002Ffr\u002Fdocs\u002Fschema\u002Fcard","fr\u002Fdocs\u002F3.schema\u002F3.card",{"title":63,"path":64,"stem":65},"Standard Schema","\u002Ffr\u002Fdocs\u002Fschema\u002Fstandard-schema","fr\u002Fdocs\u002F3.schema\u002F4.standard-schema",{"title":67,"path":68,"stem":69,"children":70,"page":44},"Métier","\u002Ffr\u002Fdocs\u002Fbusiness","fr\u002Fdocs\u002F4.business",[71,75,79,83,87,91],{"title":72,"path":73,"stem":74},"Handlers","\u002Ffr\u002Fdocs\u002Fbusiness\u002Fhandlers","fr\u002Fdocs\u002F4.business\u002F1.handlers",{"title":76,"path":77,"stem":78},"Presenters","\u002Ffr\u002Fdocs\u002Fbusiness\u002Fpresenters","fr\u002Fdocs\u002F4.business\u002F2.presenters",{"title":80,"path":81,"stem":82},"Collectors","\u002Ffr\u002Fdocs\u002Fbusiness\u002Fcollectors","fr\u002Fdocs\u002F4.business\u002F3.collectors",{"title":84,"path":85,"stem":86},"Erreurs","\u002Ffr\u002Fdocs\u002Fbusiness\u002Ferrors","fr\u002Fdocs\u002F4.business\u002F4.errors",{"title":88,"path":89,"stem":90},"Seeds","\u002Ffr\u002Fdocs\u002Fbusiness\u002Fseeds","fr\u002Fdocs\u002F4.business\u002F5.seeds",{"title":92,"path":93,"stem":94},"Les faits","\u002Ffr\u002Fdocs\u002Fbusiness\u002Ffacts","fr\u002Fdocs\u002F4.business\u002F6.facts",{"title":96,"path":97,"stem":98,"children":99,"page":44},"Client","\u002Ffr\u002Fdocs\u002Fclient","fr\u002Fdocs\u002F5.client",[100,104,108,112],{"title":101,"path":102,"stem":103},"Queries & commands","\u002Ffr\u002Fdocs\u002Fclient\u002Fqueries-commands","fr\u002Fdocs\u002F5.client\u002F1.queries-commands",{"title":105,"path":106,"stem":107},"Formulaires","\u002Ffr\u002Fdocs\u002Fclient\u002Fforms","fr\u002Fdocs\u002F5.client\u002F2.forms",{"title":109,"path":110,"stem":111},"Session","\u002Ffr\u002Fdocs\u002Fclient\u002Fsession","fr\u002Fdocs\u002F5.client\u002F3.session",{"title":113,"path":114,"stem":115},"invoke","\u002Ffr\u002Fdocs\u002Fclient\u002Finvoke","fr\u002Fdocs\u002F5.client\u002F4.invoke",{"title":117,"path":118,"stem":119,"children":120,"page":44},"Infrastructure","\u002Ffr\u002Fdocs\u002Finfra","fr\u002Fdocs\u002F6.infra",[121,125,129,133],{"title":122,"path":123,"stem":124},"Le gradient","\u002Ffr\u002Fdocs\u002Finfra\u002Fgradient","fr\u002Fdocs\u002F6.infra\u002F1.gradient",{"title":126,"path":127,"stem":128},"Surfaces — REST & GraphQL","\u002Ffr\u002Fdocs\u002Finfra\u002Fsurfaces","fr\u002Fdocs\u002F6.infra\u002F2.surfaces",{"title":130,"path":131,"stem":132},"Déploiement","\u002Ffr\u002Fdocs\u002Finfra\u002Fdeployment","fr\u002Fdocs\u002F6.infra\u002F3.deployment",{"title":134,"path":135,"stem":136},"Hôtes","\u002Ffr\u002Fdocs\u002Finfra\u002Fhosts","fr\u002Fdocs\u002F6.infra\u002F4.hosts",{"id":138,"title":72,"body":139,"description":2222,"extension":2223,"meta":2224,"navigation":256,"path":73,"seo":2225,"stem":74,"__hash__":2226},"docs_fr\u002Ffr\u002Fdocs\u002F4.business\u002F1.handlers.md",{"type":140,"value":141,"toc":2210},"minimark",[142,146,155,946,949,987,1132,1135,1140,1149,1243,1324,1339,1346,1350,1353,1452,1455,1496,1500,1511,1516,1536,1540,1546,1609,1784,1845,1856,1860,1866,1911,1914,1925,1929,1940,2111,2114,2166,2176,2180,2194,2200,2206],[143,144,72],"h1",{"id":145},"handlers",[147,148,149,150,154],"p",{},"Un handler regroupe les opérations d'une entité. ",[151,152,153],"code",{},"Crud(Entity)"," fournit les cinq opérations\nCRUD. Chaque méthode publique supplémentaire devient une opération.",[156,157,162],"pre",{"className":158,"code":159,"language":160,"meta":161,"style":161},"language-ts shiki shiki-themes material-theme-lighter github-light github-dark","import { Crud, FougereError, ErrorCode } from '@fougere\u002Fcore';\nimport Post from '..\u002Fentities\u002FPost.js';\nimport User from '..\u002F..\u002Fuser\u002Fentities\u002FUser.js';\n\nexport default class PostHandler extends Crud(Post) {\n  \u002F** Lecture publique : publiés seulement. *\u002F\n  async list(): Promise\u003CPostCard[]> {\n    const all = await this.orm.list();\n    return all.filter((p) => p.status === 'published') \u002F* … *\u002F;\n  }\n\n  \u002F** La transition draft→published — une opération, pas une écriture de champ. *\u002F\n  async publish(id: string, user: User | null): Promise\u003CPost> {\n    if (!user) throw new FougereError({ code: ErrorCode.UNAUTHORIZED, message: 'Connectez-vous pour publier', entity: 'post', operation: 'publish' });\n    const post = await this.orm.findById(id);\n    if (!post) throw new FougereError({ code: ErrorCode.NOT_FOUND, message: `Post '${id}' introuvable`, entity: 'post', operation: 'publish' });\n    if (post.authorId !== user.id) throw new FougereError({ code: ErrorCode.FORBIDDEN, message: 'Seul l’auteur peut publier', entity: 'post', operation: 'publish' });\n    if (post.status === 'published') throw new FougereError({ code: ErrorCode.CONFLICT, message: 'Déjà publié', entity: 'post', operation: 'publish' });\n    return this.orm.update(id, { status: 'published', publishedAt: new Date().toISOString() });\n  }\n}\n","ts","",[151,163,164,212,232,251,258,287,294,329,365,418,424,429,435,485,575,606,696,785,872,935,940],{"__ignoreMap":161},[165,166,169,173,177,181,184,187,189,192,195,198,202,206,209],"span",{"class":167,"line":168},"line",1,[165,170,172],{"class":171},"sVHd0","import",[165,174,176],{"class":175},"sP7_E"," {",[165,178,180],{"class":179},"su5hD"," Crud",[165,182,183],{"class":175},",",[165,185,186],{"class":179}," FougereError",[165,188,183],{"class":175},[165,190,191],{"class":179}," ErrorCode",[165,193,194],{"class":175}," }",[165,196,197],{"class":171}," from",[165,199,201],{"class":200},"sjJ54"," '",[165,203,205],{"class":204},"s_sjI","@fougere\u002Fcore",[165,207,208],{"class":200},"'",[165,210,211],{"class":175},";\n",[165,213,215,217,220,223,225,228,230],{"class":167,"line":214},2,[165,216,172],{"class":171},[165,218,219],{"class":179}," Post ",[165,221,222],{"class":171},"from",[165,224,201],{"class":200},[165,226,227],{"class":204},"..\u002Fentities\u002FPost.js",[165,229,208],{"class":200},[165,231,211],{"class":175},[165,233,235,237,240,242,244,247,249],{"class":167,"line":234},3,[165,236,172],{"class":171},[165,238,239],{"class":179}," User ",[165,241,222],{"class":171},[165,243,201],{"class":200},[165,245,246],{"class":204},"..\u002F..\u002Fuser\u002Fentities\u002FUser.js",[165,248,208],{"class":200},[165,250,211],{"class":175},[165,252,254],{"class":167,"line":253},4,[165,255,257],{"emptyLinePlaceholder":256},true,"\n",[165,259,261,264,267,271,275,278,281,284],{"class":167,"line":260},5,[165,262,263],{"class":171},"export",[165,265,266],{"class":171}," default",[165,268,270],{"class":269},"sbsja"," class",[165,272,274],{"class":273},"sbgvK"," PostHandler",[165,276,277],{"class":269}," extends",[165,279,180],{"class":280},"sGLFI",[165,282,283],{"class":179},"(Post) ",[165,285,286],{"class":175},"{\n",[165,288,290],{"class":167,"line":289},6,[165,291,293],{"class":292},"sutJx","  \u002F** Lecture publique : publiés seulement. *\u002F\n",[165,295,297,300,304,307,311,314,317,320,323,326],{"class":167,"line":296},7,[165,298,299],{"class":269},"  async",[165,301,303],{"class":302},"sVXei"," list",[165,305,306],{"class":175},"()",[165,308,310],{"class":309},"smGrS",":",[165,312,313],{"class":273}," Promise",[165,315,316],{"class":175},"\u003C",[165,318,319],{"class":273},"PostCard",[165,321,322],{"class":179},"[]",[165,324,325],{"class":175},">",[165,327,328],{"class":175}," {\n",[165,330,332,335,339,342,345,349,352,355,357,360,363],{"class":167,"line":331},8,[165,333,334],{"class":269},"    const",[165,336,338],{"class":337},"s_hVV"," all",[165,340,341],{"class":309}," =",[165,343,344],{"class":171}," await",[165,346,348],{"class":347},"s39Yj"," this",[165,350,351],{"class":175},".",[165,353,354],{"class":179},"orm",[165,356,351],{"class":175},[165,358,359],{"class":280},"list",[165,361,306],{"class":362},"skxfh",[165,364,211],{"class":175},[165,366,368,371,373,375,378,381,383,386,389,392,395,397,400,403,405,408,410,413,416],{"class":167,"line":367},9,[165,369,370],{"class":171},"    return",[165,372,338],{"class":179},[165,374,351],{"class":175},[165,376,377],{"class":280},"filter",[165,379,380],{"class":362},"(",[165,382,380],{"class":175},[165,384,147],{"class":385},"s99_P",[165,387,388],{"class":175},")",[165,390,391],{"class":269}," =>",[165,393,394],{"class":179}," p",[165,396,351],{"class":175},[165,398,399],{"class":179},"status",[165,401,402],{"class":309}," ===",[165,404,201],{"class":200},[165,406,407],{"class":204},"published",[165,409,208],{"class":200},[165,411,412],{"class":362},") ",[165,414,415],{"class":292},"\u002F* … *\u002F",[165,417,211],{"class":175},[165,419,421],{"class":167,"line":420},10,[165,422,423],{"class":175},"  }\n",[165,425,427],{"class":167,"line":426},11,[165,428,257],{"emptyLinePlaceholder":256},[165,430,432],{"class":167,"line":431},12,[165,433,434],{"class":292},"  \u002F** La transition draft→published — une opération, pas une écriture de champ. *\u002F\n",[165,436,438,440,443,445,448,450,454,456,459,461,464,467,470,472,474,476,478,481,483],{"class":167,"line":437},13,[165,439,299],{"class":269},[165,441,442],{"class":302}," publish",[165,444,380],{"class":175},[165,446,447],{"class":385},"id",[165,449,310],{"class":309},[165,451,453],{"class":452},"sZMiF"," string",[165,455,183],{"class":175},[165,457,458],{"class":385}," user",[165,460,310],{"class":309},[165,462,463],{"class":273}," User",[165,465,466],{"class":309}," |",[165,468,469],{"class":452}," null",[165,471,388],{"class":175},[165,473,310],{"class":309},[165,475,313],{"class":273},[165,477,316],{"class":175},[165,479,480],{"class":273},"Post",[165,482,325],{"class":175},[165,484,328],{"class":175},[165,486,488,491,494,497,500,502,505,508,510,512,515,518,520,522,524,527,529,532,534,536,539,541,543,546,548,550,553,555,557,560,562,564,567,569,571,573],{"class":167,"line":487},14,[165,489,490],{"class":171},"    if",[165,492,493],{"class":362}," (",[165,495,496],{"class":309},"!",[165,498,499],{"class":179},"user",[165,501,412],{"class":362},[165,503,504],{"class":171},"throw",[165,506,507],{"class":309}," new",[165,509,186],{"class":280},[165,511,380],{"class":362},[165,513,514],{"class":175},"{",[165,516,517],{"class":362}," code",[165,519,310],{"class":175},[165,521,191],{"class":179},[165,523,351],{"class":175},[165,525,526],{"class":337},"UNAUTHORIZED",[165,528,183],{"class":175},[165,530,531],{"class":362}," message",[165,533,310],{"class":175},[165,535,201],{"class":200},[165,537,538],{"class":204},"Connectez-vous pour publier",[165,540,208],{"class":200},[165,542,183],{"class":175},[165,544,545],{"class":362}," entity",[165,547,310],{"class":175},[165,549,201],{"class":200},[165,551,552],{"class":204},"post",[165,554,208],{"class":200},[165,556,183],{"class":175},[165,558,559],{"class":362}," operation",[165,561,310],{"class":175},[165,563,201],{"class":200},[165,565,566],{"class":204},"publish",[165,568,208],{"class":200},[165,570,194],{"class":175},[165,572,388],{"class":362},[165,574,211],{"class":175},[165,576,578,580,583,585,587,589,591,593,595,598,600,602,604],{"class":167,"line":577},15,[165,579,334],{"class":269},[165,581,582],{"class":337}," post",[165,584,341],{"class":309},[165,586,344],{"class":171},[165,588,348],{"class":347},[165,590,351],{"class":175},[165,592,354],{"class":179},[165,594,351],{"class":175},[165,596,597],{"class":280},"findById",[165,599,380],{"class":362},[165,601,447],{"class":179},[165,603,388],{"class":362},[165,605,211],{"class":175},[165,607,609,611,613,615,617,619,621,623,625,627,629,631,633,635,637,640,642,644,646,649,652,655,657,660,663,666,668,670,672,674,676,678,680,682,684,686,688,690,692,694],{"class":167,"line":608},16,[165,610,490],{"class":171},[165,612,493],{"class":362},[165,614,496],{"class":309},[165,616,552],{"class":179},[165,618,412],{"class":362},[165,620,504],{"class":171},[165,622,507],{"class":309},[165,624,186],{"class":280},[165,626,380],{"class":362},[165,628,514],{"class":175},[165,630,517],{"class":362},[165,632,310],{"class":175},[165,634,191],{"class":179},[165,636,351],{"class":175},[165,638,639],{"class":337},"NOT_FOUND",[165,641,183],{"class":175},[165,643,531],{"class":362},[165,645,310],{"class":175},[165,647,648],{"class":200}," `",[165,650,651],{"class":204},"Post '",[165,653,654],{"class":200},"${",[165,656,447],{"class":179},[165,658,659],{"class":200},"}",[165,661,662],{"class":204},"' introuvable",[165,664,665],{"class":200},"`",[165,667,183],{"class":175},[165,669,545],{"class":362},[165,671,310],{"class":175},[165,673,201],{"class":200},[165,675,552],{"class":204},[165,677,208],{"class":200},[165,679,183],{"class":175},[165,681,559],{"class":362},[165,683,310],{"class":175},[165,685,201],{"class":200},[165,687,566],{"class":204},[165,689,208],{"class":200},[165,691,194],{"class":175},[165,693,388],{"class":362},[165,695,211],{"class":175},[165,697,699,701,703,705,707,710,713,715,717,719,721,723,725,727,729,731,733,735,737,739,742,744,746,748,750,753,755,757,759,761,763,765,767,769,771,773,775,777,779,781,783],{"class":167,"line":698},17,[165,700,490],{"class":171},[165,702,493],{"class":362},[165,704,552],{"class":179},[165,706,351],{"class":175},[165,708,709],{"class":179},"authorId",[165,711,712],{"class":309}," !==",[165,714,458],{"class":179},[165,716,351],{"class":175},[165,718,447],{"class":179},[165,720,412],{"class":362},[165,722,504],{"class":171},[165,724,507],{"class":309},[165,726,186],{"class":280},[165,728,380],{"class":362},[165,730,514],{"class":175},[165,732,517],{"class":362},[165,734,310],{"class":175},[165,736,191],{"class":179},[165,738,351],{"class":175},[165,740,741],{"class":337},"FORBIDDEN",[165,743,183],{"class":175},[165,745,531],{"class":362},[165,747,310],{"class":175},[165,749,201],{"class":200},[165,751,752],{"class":204},"Seul l’auteur peut publier",[165,754,208],{"class":200},[165,756,183],{"class":175},[165,758,545],{"class":362},[165,760,310],{"class":175},[165,762,201],{"class":200},[165,764,552],{"class":204},[165,766,208],{"class":200},[165,768,183],{"class":175},[165,770,559],{"class":362},[165,772,310],{"class":175},[165,774,201],{"class":200},[165,776,566],{"class":204},[165,778,208],{"class":200},[165,780,194],{"class":175},[165,782,388],{"class":362},[165,784,211],{"class":175},[165,786,788,790,792,794,796,798,800,802,804,806,808,810,812,814,816,818,820,822,824,826,829,831,833,835,837,840,842,844,846,848,850,852,854,856,858,860,862,864,866,868,870],{"class":167,"line":787},18,[165,789,490],{"class":171},[165,791,493],{"class":362},[165,793,552],{"class":179},[165,795,351],{"class":175},[165,797,399],{"class":179},[165,799,402],{"class":309},[165,801,201],{"class":200},[165,803,407],{"class":204},[165,805,208],{"class":200},[165,807,412],{"class":362},[165,809,504],{"class":171},[165,811,507],{"class":309},[165,813,186],{"class":280},[165,815,380],{"class":362},[165,817,514],{"class":175},[165,819,517],{"class":362},[165,821,310],{"class":175},[165,823,191],{"class":179},[165,825,351],{"class":175},[165,827,828],{"class":337},"CONFLICT",[165,830,183],{"class":175},[165,832,531],{"class":362},[165,834,310],{"class":175},[165,836,201],{"class":200},[165,838,839],{"class":204},"Déjà publié",[165,841,208],{"class":200},[165,843,183],{"class":175},[165,845,545],{"class":362},[165,847,310],{"class":175},[165,849,201],{"class":200},[165,851,552],{"class":204},[165,853,208],{"class":200},[165,855,183],{"class":175},[165,857,559],{"class":362},[165,859,310],{"class":175},[165,861,201],{"class":200},[165,863,566],{"class":204},[165,865,208],{"class":200},[165,867,194],{"class":175},[165,869,388],{"class":362},[165,871,211],{"class":175},[165,873,875,877,879,881,883,885,888,890,892,894,896,899,901,903,905,907,909,912,914,916,919,921,923,926,929,931,933],{"class":167,"line":874},19,[165,876,370],{"class":171},[165,878,348],{"class":347},[165,880,351],{"class":175},[165,882,354],{"class":179},[165,884,351],{"class":175},[165,886,887],{"class":280},"update",[165,889,380],{"class":362},[165,891,447],{"class":179},[165,893,183],{"class":175},[165,895,176],{"class":175},[165,897,898],{"class":362}," status",[165,900,310],{"class":175},[165,902,201],{"class":200},[165,904,407],{"class":204},[165,906,208],{"class":200},[165,908,183],{"class":175},[165,910,911],{"class":362}," publishedAt",[165,913,310],{"class":175},[165,915,507],{"class":309},[165,917,918],{"class":280}," Date",[165,920,306],{"class":362},[165,922,351],{"class":175},[165,924,925],{"class":280},"toISOString",[165,927,928],{"class":362},"() ",[165,930,659],{"class":175},[165,932,388],{"class":362},[165,934,211],{"class":175},[165,936,938],{"class":167,"line":937},20,[165,939,423],{"class":175},[165,941,943],{"class":167,"line":942},21,[165,944,945],{"class":175},"}\n",[147,947,948],{},"Fougere n'impose pas de couche service. Un handler peut contenir directement la logique\nd'une opération ou déléguer à un service selon les besoins du domaine.",[147,950,951,954,955,958,959,962,963,962,966,962,969,972,973,962,976,962,979,982,983,986],{},[151,952,953],{},"this.orm"," est l'accès aux données limité à l'entité (",[151,956,957],{},"EntityOrm","). Lectures :\n",[151,960,961],{},"list(options?)",", ",[151,964,965],{},"findById(id)",[151,967,968],{},"findBy(criteria)",[151,970,971],{},"findAllBy(criteria)",". Écritures :\n",[151,974,975],{},"create(input)",[151,977,978],{},"update(id, input)",[151,980,981],{},"delete(id)",". ",[151,984,985],{},"output(vue)"," rend un ORM scopé aux\nchamps d'une vue.",[156,988,990],{"className":158,"code":989,"language":160,"meta":161,"style":161},"await this.orm.findBy({ slug });                    \u002F\u002F la ligne qui correspond\nawait this.orm.findAllBy({ authorId: user.id });    \u002F\u002F toutes celles qui correspondent\nawait this.orm.list({ where: { status: 'published' }, limit: 20, orderBy: 'createdAt' });\n",[151,991,992,1025,1065],{"__ignoreMap":161},[165,993,994,997,999,1001,1003,1005,1008,1010,1012,1015,1017,1019,1022],{"class":167,"line":168},[165,995,996],{"class":171},"await",[165,998,348],{"class":347},[165,1000,351],{"class":175},[165,1002,354],{"class":179},[165,1004,351],{"class":175},[165,1006,1007],{"class":280},"findBy",[165,1009,380],{"class":179},[165,1011,514],{"class":175},[165,1013,1014],{"class":179}," slug ",[165,1016,659],{"class":175},[165,1018,388],{"class":179},[165,1020,1021],{"class":175},";",[165,1023,1024],{"class":292},"                    \u002F\u002F la ligne qui correspond\n",[165,1026,1027,1029,1031,1033,1035,1037,1040,1042,1044,1047,1049,1051,1053,1056,1058,1060,1062],{"class":167,"line":214},[165,1028,996],{"class":171},[165,1030,348],{"class":347},[165,1032,351],{"class":175},[165,1034,354],{"class":179},[165,1036,351],{"class":175},[165,1038,1039],{"class":280},"findAllBy",[165,1041,380],{"class":179},[165,1043,514],{"class":175},[165,1045,1046],{"class":362}," authorId",[165,1048,310],{"class":175},[165,1050,458],{"class":179},[165,1052,351],{"class":175},[165,1054,1055],{"class":179},"id ",[165,1057,659],{"class":175},[165,1059,388],{"class":179},[165,1061,1021],{"class":175},[165,1063,1064],{"class":292},"    \u002F\u002F toutes celles qui correspondent\n",[165,1066,1067,1069,1071,1073,1075,1077,1079,1081,1083,1086,1088,1090,1092,1094,1096,1098,1100,1103,1106,1108,1112,1114,1117,1119,1121,1124,1126,1128,1130],{"class":167,"line":234},[165,1068,996],{"class":171},[165,1070,348],{"class":347},[165,1072,351],{"class":175},[165,1074,354],{"class":179},[165,1076,351],{"class":175},[165,1078,359],{"class":280},[165,1080,380],{"class":179},[165,1082,514],{"class":175},[165,1084,1085],{"class":362}," where",[165,1087,310],{"class":175},[165,1089,176],{"class":175},[165,1091,898],{"class":362},[165,1093,310],{"class":175},[165,1095,201],{"class":200},[165,1097,407],{"class":204},[165,1099,208],{"class":200},[165,1101,1102],{"class":175}," },",[165,1104,1105],{"class":362}," limit",[165,1107,310],{"class":175},[165,1109,1111],{"class":1110},"srdBf"," 20",[165,1113,183],{"class":175},[165,1115,1116],{"class":362}," orderBy",[165,1118,310],{"class":175},[165,1120,201],{"class":200},[165,1122,1123],{"class":204},"createdAt",[165,1125,208],{"class":200},[165,1127,194],{"class":175},[165,1129,388],{"class":179},[165,1131,211],{"class":175},[147,1133,1134],{},"La façade valide l'entrée avant d'appeler la méthode. L'ORM applique ensuite les règles de\ncycle de vie, comme les valeurs automatiques et les défauts. La valeur renvoyée par le\nhandler est projetée et validée avant de quitter la façade.",[1136,1137,1139],"h2",{"id":1138},"où-vit-une-requête-nommée","Où vit une requête nommée",[147,1141,1142,1144,1145,1148],{},[151,1143,957],{}," est un port : cinq gestes génériques, aucun parfum de domaine. « Les relevés\nbruyants » n'en est pas un, donc cette requête finit épelée sur place, au milieu du calcul\nqu'elle alimente. ",[151,1146,1147],{},"Repository(Entity)"," lui donne un endroit :",[156,1150,1152],{"className":158,"code":1151,"language":160,"meta":161,"style":161},"\u002F\u002F repositories\u002FReadingRepository.ts\nexport default class ReadingRepository extends Repository(Reading) {\n  loud(): Promise\u003CReading[]> {\n    return this.orm.findAllBy({ loud: true });\n  }\n}\n",[151,1153,1154,1159,1180,1202,1235,1239],{"__ignoreMap":161},[165,1155,1156],{"class":167,"line":168},[165,1157,1158],{"class":292},"\u002F\u002F repositories\u002FReadingRepository.ts\n",[165,1160,1161,1163,1165,1167,1170,1172,1175,1178],{"class":167,"line":214},[165,1162,263],{"class":171},[165,1164,266],{"class":171},[165,1166,270],{"class":269},[165,1168,1169],{"class":273}," ReadingRepository",[165,1171,277],{"class":269},[165,1173,1174],{"class":280}," Repository",[165,1176,1177],{"class":179},"(Reading) ",[165,1179,286],{"class":175},[165,1181,1182,1185,1187,1189,1191,1193,1196,1198,1200],{"class":167,"line":234},[165,1183,1184],{"class":302},"  loud",[165,1186,306],{"class":175},[165,1188,310],{"class":309},[165,1190,313],{"class":273},[165,1192,316],{"class":175},[165,1194,1195],{"class":273},"Reading",[165,1197,322],{"class":179},[165,1199,325],{"class":175},[165,1201,328],{"class":175},[165,1203,1204,1206,1208,1210,1212,1214,1216,1218,1220,1223,1225,1229,1231,1233],{"class":167,"line":253},[165,1205,370],{"class":171},[165,1207,348],{"class":347},[165,1209,351],{"class":175},[165,1211,354],{"class":179},[165,1213,351],{"class":175},[165,1215,1039],{"class":280},[165,1217,380],{"class":362},[165,1219,514],{"class":175},[165,1221,1222],{"class":362}," loud",[165,1224,310],{"class":175},[165,1226,1228],{"class":1227},"syTEX"," true",[165,1230,194],{"class":175},[165,1232,388],{"class":362},[165,1234,211],{"class":175},[165,1236,1237],{"class":167,"line":260},[165,1238,423],{"class":175},[165,1240,1241],{"class":167,"line":289},[165,1242,945],{"class":175},[156,1244,1246],{"className":158,"code":1245,"language":160,"meta":161,"style":161},"\u002F\u002F handlers\u002FReadingHandler.ts — pose la question, n'épelle jamais le stockage\nexport default class ReadingHandler {\n  constructor(private readingRepository: ReadingRepository) {}\n  async loud() { return this.readingRepository.loud(); }\n}\n",[151,1247,1248,1253,1266,1288,1320],{"__ignoreMap":161},[165,1249,1250],{"class":167,"line":168},[165,1251,1252],{"class":292},"\u002F\u002F handlers\u002FReadingHandler.ts — pose la question, n'épelle jamais le stockage\n",[165,1254,1255,1257,1259,1261,1264],{"class":167,"line":214},[165,1256,263],{"class":171},[165,1258,266],{"class":171},[165,1260,270],{"class":269},[165,1262,1263],{"class":273}," ReadingHandler",[165,1265,328],{"class":175},[165,1267,1268,1271,1273,1276,1279,1281,1283,1285],{"class":167,"line":234},[165,1269,1270],{"class":269},"  constructor",[165,1272,380],{"class":175},[165,1274,1275],{"class":269},"private",[165,1277,1278],{"class":385}," readingRepository",[165,1280,310],{"class":309},[165,1282,1169],{"class":273},[165,1284,388],{"class":175},[165,1286,1287],{"class":175}," {}\n",[165,1289,1290,1292,1294,1296,1298,1301,1303,1305,1308,1310,1313,1315,1317],{"class":167,"line":253},[165,1291,299],{"class":269},[165,1293,1222],{"class":302},[165,1295,306],{"class":175},[165,1297,176],{"class":175},[165,1299,1300],{"class":171}," return",[165,1302,348],{"class":347},[165,1304,351],{"class":175},[165,1306,1307],{"class":179},"readingRepository",[165,1309,351],{"class":175},[165,1311,1312],{"class":280},"loud",[165,1314,306],{"class":362},[165,1316,1021],{"class":175},[165,1318,1319],{"class":175}," }\n",[165,1321,1322],{"class":167,"line":260},[165,1323,945],{"class":175},[147,1325,1326,1330,1331,1334,1335,1338],{},[1327,1328,1329],"strong",{},"N'en écrivez aucun et vous ne perdez rien."," Le bootstrap enregistre un repository par\ndéfaut pour chaque entité — l'ORM gardé lui-même — donc ",[151,1332,1333],{},"ReadingRepository"," se résout que\nle fichier existe ou non. En déclarer un l'emporte, exactement comme une opération ",[151,1336,1337],{},"Crud","\nredéfinie dans la sous-classe l'emporte sur celle du prefab.",[147,1340,1341,1342,1345],{},"Ce n'est ",[1327,1343,1344],{},"pas une porte"," : un repository n'a pas de façade, donc rien de ce qu'il porte\nn'est joignable depuis le fil. Le juge reste dans le handler, seul endroit où un refus ne\nse contourne pas.",[1136,1347,1349],{"id":1348},"les-quatre-règles-de-binding","Les quatre règles de binding",[147,1351,1352],{},"Fougere lit votre signature (parse AST au boot) et lie chaque paramètre depuis\nl'invocation — dans cet ordre :",[1354,1355,1356,1372],"table",{},[1357,1358,1359],"thead",{},[1360,1361,1362,1366,1369],"tr",{},[1363,1364,1365],"th",{},"#",[1363,1367,1368],{},"Le paramètre ressemble à",[1363,1370,1371],{},"Lié depuis",[1373,1374,1375,1398,1411,1435],"tbody",{},[1360,1376,1377,1381,1391],{},[1378,1379,1380],"td",{},"1",[1378,1382,1383,1384,493,1388,388],{},"un type qui a un ",[1385,1386,1387],"a",{"href":81},"Collector",[151,1389,1390],{},"user: User | null",[1378,1392,1393,1394,1397],{},"le ",[151,1395,1396],{},"collect(ctx)"," du collector",[1360,1399,1400,1403,1408],{},[1378,1401,1402],{},"2",[1378,1404,1405],{},[151,1406,1407],{},"ctx: InvocationContext",[1378,1409,1410],{},"l'invocation entière",[1360,1412,1413,1416,1425],{},[1378,1414,1415],{},"3",[1378,1417,1418,1419,962,1422,388],{},"un primitif (",[151,1420,1421],{},"id: string",[151,1423,1424],{},"page: number",[1378,1426,1427,1430,1431,1434],{},[151,1428,1429],{},"params[nom]",", puis ",[151,1432,1433],{},"query[nom]"," — coercé en number\u002Fboolean",[1360,1436,1437,1440,1446],{},[1378,1438,1439],{},"4",[1378,1441,1442,1443,388],{},"tout le reste (",[151,1444,1445],{},"input: PostDraft",[1378,1447,1393,1448,1451],{},[151,1449,1450],{},"body"," de la requête",[147,1453,1454],{},"Deux conséquences du parser AST-only (pas de type checker) :",[1456,1457,1458,1472],"ul",{},[1459,1460,1461,1464,1465,1467,1468,1471],"li",{},[1327,1462,1463],{},"Épelez les types."," ",[151,1466,1390],{}," se lie ; ",[151,1469,1470],{},"user: CurrentUser"," (un alias) est\ninvisible et ne lie rien.",[1459,1473,1474,1477,1478,1480,1481,1484,1485,962,1488,1491,1492,1495],{},[1327,1475,1476],{},"La porte est ce que vous déclarez public."," Une méthode ",[151,1479,1275],{}," ou ",[151,1482,1483],{},"protected"," n'est\npas une opération : le scan la saute, parce que TypeScript a déjà le mot pour ça. Un\nhelper que le handler nomme par intention (",[151,1486,1487],{},"mustOwn",[151,1489,1490],{},"refuse",") reste donc un helper, à\nl'intérieur de la classe. ",[151,1493,1494],{},"#nom"," fonctionne aussi.",[1136,1497,1499],{"id":1498},"validation-des-entrées","Validation des entrées",[147,1501,1502,1503,1506,1507,1510],{},"Quand le type d'un paramètre est une classe de schéma (entité ou vue), la façade valide\nle body avant d'appeler la méthode. Une entrée invalide produit ",[151,1504,1505],{},"VALIDATION_FAILED"," avec\nles détails par champ. Une vue ",[151,1508,1509],{},"partial()"," utilise le mode patch.",[1512,1513,1515],"h3",{"id":1514},"les-clés-inconnues-sont-refusées","Les clés inconnues sont refusées",[147,1517,1518,1519,1522,1523,1525,1526,493,1528,1531,1532,1535],{},"Une clé hors contrat produit une erreur au lieu d'être retirée silencieusement : un body\n",[151,1520,1521],{},"{ …, status: 'published' }"," contre une vue qui ne déclare pas ",[151,1524,399],{}," ressort en\n",[151,1527,1505],{},[151,1529,1530],{},"status: Unknown field",") avant votre méthode. Une entrée acceptée peut\ndonc être transmise à l'ORM sans projection préalable. ",[151,1533,1534],{},"useFormFor"," applique la même\nvalidation dans le navigateur avant l'appel réseau.",[1136,1537,1539],{"id":1538},"un-état-change-par-une-opération-jamais-par-une-écriture-de-champ","Un état change par une opération, jamais par une écriture de champ",[147,1541,1542,1545],{},[151,1543,1544],{},"publish()"," illustre une transition d'état explicite pour une commande, un abonnement ou\nun ticket. Elle combine les règles suivantes :",[156,1547,1549],{"className":158,"code":1548,"language":160,"meta":161,"style":161},"\u002F\u002F l'entité — le jeu de valeurs, et celle avec laquelle elle naît\nstatus: readOnly(oneOf('draft', 'published', { default: 'draft' })),\n",[151,1550,1551,1556],{"__ignoreMap":161},[165,1552,1553],{"class":167,"line":168},[165,1554,1555],{"class":292},"\u002F\u002F l'entité — le jeu de valeurs, et celle avec laquelle elle naît\n",[165,1557,1558,1560,1562,1565,1567,1570,1572,1574,1577,1579,1581,1583,1585,1587,1589,1591,1593,1595,1597,1599,1601,1603,1606],{"class":167,"line":214},[165,1559,399],{"class":273},[165,1561,310],{"class":175},[165,1563,1564],{"class":280}," readOnly",[165,1566,380],{"class":179},[165,1568,1569],{"class":280},"oneOf",[165,1571,380],{"class":179},[165,1573,208],{"class":200},[165,1575,1576],{"class":204},"draft",[165,1578,208],{"class":200},[165,1580,183],{"class":175},[165,1582,201],{"class":200},[165,1584,407],{"class":204},[165,1586,208],{"class":200},[165,1588,183],{"class":175},[165,1590,176],{"class":175},[165,1592,266],{"class":362},[165,1594,310],{"class":175},[165,1596,201],{"class":200},[165,1598,1576],{"class":204},[165,1600,208],{"class":200},[165,1602,194],{"class":175},[165,1604,1605],{"class":179},"))",[165,1607,1608],{"class":175},",\n",[156,1610,1612],{"className":158,"code":1611,"language":160,"meta":161,"style":161},"\u002F\u002F le handler — le passage, et le refus\nasync publish(id: string): Promise\u003CPost> {\n  const post = await this.orm.findById(id);\n  if (post.status === 'published') {\n    throw new FougereError({ code: ErrorCode.CONFLICT, message: 'Already published',\n      entity: 'post', operation: 'publish' });\n  }\n  return this.orm.update(id, { status: 'published' });\n}\n",[151,1613,1614,1619,1640,1663,1683,1721,1752,1756,1780],{"__ignoreMap":161},[165,1615,1616],{"class":167,"line":168},[165,1617,1618],{"class":292},"\u002F\u002F le handler — le passage, et le refus\n",[165,1620,1621,1624,1626,1629,1632,1634,1636,1638],{"class":167,"line":214},[165,1622,1623],{"class":179},"async ",[165,1625,566],{"class":280},[165,1627,1628],{"class":179},"(id: string): ",[165,1630,1631],{"class":452},"Promise",[165,1633,316],{"class":309},[165,1635,480],{"class":179},[165,1637,325],{"class":309},[165,1639,328],{"class":175},[165,1641,1642,1645,1648,1650,1652,1654,1656,1658,1660],{"class":167,"line":234},[165,1643,1644],{"class":179},"  const post ",[165,1646,1647],{"class":309},"=",[165,1649,344],{"class":171},[165,1651,348],{"class":347},[165,1653,351],{"class":175},[165,1655,354],{"class":179},[165,1657,351],{"class":175},[165,1659,597],{"class":280},[165,1661,1662],{"class":179},"(id);\n",[165,1664,1665,1668,1670,1673,1675,1677,1679,1681],{"class":167,"line":253},[165,1666,1667],{"class":302},"  if",[165,1669,493],{"class":175},[165,1671,1672],{"class":179},"post.status === ",[165,1674,208],{"class":200},[165,1676,407],{"class":204},[165,1678,208],{"class":200},[165,1680,388],{"class":175},[165,1682,328],{"class":175},[165,1684,1685,1688,1690,1692,1694,1696,1698,1700,1702,1704,1706,1708,1710,1712,1714,1717,1719],{"class":167,"line":260},[165,1686,1687],{"class":171},"    throw",[165,1689,507],{"class":309},[165,1691,186],{"class":280},[165,1693,380],{"class":362},[165,1695,514],{"class":175},[165,1697,517],{"class":362},[165,1699,310],{"class":175},[165,1701,191],{"class":179},[165,1703,351],{"class":175},[165,1705,828],{"class":337},[165,1707,183],{"class":175},[165,1709,531],{"class":362},[165,1711,310],{"class":175},[165,1713,201],{"class":200},[165,1715,1716],{"class":204},"Already published",[165,1718,208],{"class":200},[165,1720,1608],{"class":175},[165,1722,1723,1726,1728,1730,1732,1734,1736,1738,1740,1742,1744,1746,1748,1750],{"class":167,"line":289},[165,1724,1725],{"class":362},"      entity",[165,1727,310],{"class":175},[165,1729,201],{"class":200},[165,1731,552],{"class":204},[165,1733,208],{"class":200},[165,1735,183],{"class":175},[165,1737,559],{"class":362},[165,1739,310],{"class":175},[165,1741,201],{"class":200},[165,1743,566],{"class":204},[165,1745,208],{"class":200},[165,1747,194],{"class":175},[165,1749,388],{"class":362},[165,1751,211],{"class":175},[165,1753,1754],{"class":167,"line":296},[165,1755,423],{"class":175},[165,1757,1758,1761,1763,1765,1767,1769,1771,1773,1775,1777],{"class":167,"line":331},[165,1759,1760],{"class":179},"  return this.orm.update(id",[165,1762,183],{"class":175},[165,1764,176],{"class":175},[165,1766,898],{"class":273},[165,1768,310],{"class":175},[165,1770,201],{"class":200},[165,1772,407],{"class":204},[165,1774,208],{"class":200},[165,1776,194],{"class":175},[165,1778,1779],{"class":179},");\n",[165,1781,1782],{"class":167,"line":367},[165,1783,945],{"class":175},[1456,1785,1786,1801,1813,1832],{},[1459,1787,1788,1792,1793,1796,1797,1800],{},[1327,1789,1790],{},[151,1791,1569],{}," limite les valeurs. Le formulaire peut produire un ",[151,1794,1795],{},"\u003Cselect>",", le DDL émet\n",[151,1798,1799],{},"CHECK status in (…)"," et GraphQL déclare un type enum.",[1459,1802,1803,1808,1809,1812],{},[1327,1804,1805],{},[151,1806,1807],{},"{ default: 'draft' }"," est l'état initial — une règle de création sur\n",[1385,1810,1811],{"href":52},"l'axe lifecycle",", donc personne ne le fournit.",[1459,1814,1815,1820,1821,1824,1825,1828,1829,1831],{},[1327,1816,1817],{},[151,1818,1819],{},"readOnly"," interdit l'écriture du champ par les clients : ",[151,1822,1823],{},"boundary.in"," vaut ",[151,1826,1827],{},"closed",", donc ",[151,1830,399],{},"\nest absent de toute vue d'entrée. Un corps qui le porte est refusé en clé inconnue.",[1459,1833,1834,1837,1838,1840,1841,1844],{},[1327,1835,1836],{},"L'opération nommée"," porte la transition et renvoie ",[151,1839,828],{},", projeté en\n",[1385,1842,1843],{"href":85},"409",", lorsque l'état courant l'interdit.",[147,1846,1847,1848,1851,1852,1855],{},"La méthode est seule responsable de l'ordre des transitions. Une mise à jour SQL directe,\nou un autre handler qui appelle ",[151,1849,1850],{},"this.orm.update(id, { status })",", peut la contourner tant\nque la valeur respecte le ",[151,1853,1854],{},"CHECK",". Fougere ne fournit pas de graphe d'états : le champ\ndéclare les valeurs possibles et l'opération contrôle le passage de l'une à l'autre.",[1136,1857,1859],{"id":1858},"vue-de-sortie","Vue de sortie",[147,1861,1862,1863,1865],{},"Le deuxième argument de ",[151,1864,1337],{}," sélectionne la vue de sortie. Deux formes sont disponibles :",[156,1867,1869],{"className":158,"code":1868,"language":160,"meta":161,"style":161},"Crud(Post, { list: PostCard })   \u002F\u002F list rend des cartes, le reste rend Post\nCrud(Post, PostPublic)           \u002F\u002F tout le handler rend PostPublic\n",[151,1870,1871,1897],{"__ignoreMap":161},[165,1872,1873,1875,1878,1880,1882,1884,1886,1889,1891,1894],{"class":167,"line":168},[165,1874,1337],{"class":280},[165,1876,1877],{"class":179},"(Post",[165,1879,183],{"class":175},[165,1881,176],{"class":175},[165,1883,303],{"class":362},[165,1885,310],{"class":175},[165,1887,1888],{"class":179}," PostCard ",[165,1890,659],{"class":175},[165,1892,1893],{"class":179},")   ",[165,1895,1896],{"class":292},"\u002F\u002F list rend des cartes, le reste rend Post\n",[165,1898,1899,1901,1903,1905,1908],{"class":167,"line":214},[165,1900,1337],{"class":280},[165,1902,1877],{"class":179},[165,1904,183],{"class":175},[165,1906,1907],{"class":179}," PostPublic)           ",[165,1909,1910],{"class":292},"\u002F\u002F tout le handler rend PostPublic\n",[147,1912,1913],{},"Avec une configuration par opération, l'ORM renvoie la ligne entière et la façade applique\nla vue à la sortie. Les autres opérations conservent leur propre vue.",[147,1915,1916,1917,1920,1921,1924],{},"Avec une vue pour tout le handler, l'ORM injecté est lui-même restreint. Un second fichier\nde handler peut ainsi définir une autre audience : ",[151,1918,1919],{},"handlers\u002FPostHandler.ts"," (complet) et\n",[151,1922,1923],{},"handlers\u002Fpublic\u002FPostHandler.ts"," (restreint).",[1136,1926,1928],{"id":1927},"atteindre-une-autre-frond","Atteindre une autre Frond",[147,1930,1931,1932,1935,1936,1939],{},"Une Frond n'importe pas les fichiers d'une autre : elle passe par sa porte. ",[151,1933,1934],{},"Facade\u003CT>"," est\nle deuxième port du framework, lu comme le premier (",[151,1937,1938],{},"EntityOrm\u003CPost>",") :",[156,1941,1943],{"className":158,"code":1942,"language":160,"meta":161,"style":161},"import type { Facade } from '@fougere\u002Fcore';\nimport type ArticleHandler from '@frond\u002Fstock\u002Fhandlers\u002FArticleHandler';\n\nexport default class CommandeHandler {\n  constructor(private articleFacade: Facade\u003CArticleHandler>) {}\n\n  \u002F** Cette commande est-elle servable depuis l'étagère ? *\u002F\n  async servable(): Promise\u003Cboolean> {\n    const onHand = await this.articleFacade.onHand();\n    return onHand > 0;\n  }\n}\n",[151,1944,1945,1969,1989,1993,2006,2031,2035,2040,2062,2089,2103,2107],{"__ignoreMap":161},[165,1946,1947,1949,1952,1954,1957,1959,1961,1963,1965,1967],{"class":167,"line":168},[165,1948,172],{"class":171},[165,1950,1951],{"class":171}," type",[165,1953,176],{"class":175},[165,1955,1956],{"class":179}," Facade",[165,1958,194],{"class":175},[165,1960,197],{"class":171},[165,1962,201],{"class":200},[165,1964,205],{"class":204},[165,1966,208],{"class":200},[165,1968,211],{"class":175},[165,1970,1971,1973,1975,1978,1980,1982,1985,1987],{"class":167,"line":214},[165,1972,172],{"class":171},[165,1974,1951],{"class":171},[165,1976,1977],{"class":179}," ArticleHandler ",[165,1979,222],{"class":171},[165,1981,201],{"class":200},[165,1983,1984],{"class":204},"@frond\u002Fstock\u002Fhandlers\u002FArticleHandler",[165,1986,208],{"class":200},[165,1988,211],{"class":175},[165,1990,1991],{"class":167,"line":234},[165,1992,257],{"emptyLinePlaceholder":256},[165,1994,1995,1997,1999,2001,2004],{"class":167,"line":253},[165,1996,263],{"class":171},[165,1998,266],{"class":171},[165,2000,270],{"class":269},[165,2002,2003],{"class":273}," CommandeHandler",[165,2005,328],{"class":175},[165,2007,2008,2010,2012,2014,2017,2019,2021,2023,2026,2029],{"class":167,"line":260},[165,2009,1270],{"class":269},[165,2011,380],{"class":175},[165,2013,1275],{"class":269},[165,2015,2016],{"class":385}," articleFacade",[165,2018,310],{"class":309},[165,2020,1956],{"class":273},[165,2022,316],{"class":175},[165,2024,2025],{"class":273},"ArticleHandler",[165,2027,2028],{"class":175},">)",[165,2030,1287],{"class":175},[165,2032,2033],{"class":167,"line":289},[165,2034,257],{"emptyLinePlaceholder":256},[165,2036,2037],{"class":167,"line":296},[165,2038,2039],{"class":292},"  \u002F** Cette commande est-elle servable depuis l'étagère ? *\u002F\n",[165,2041,2042,2044,2047,2049,2051,2053,2055,2058,2060],{"class":167,"line":331},[165,2043,299],{"class":269},[165,2045,2046],{"class":302}," servable",[165,2048,306],{"class":175},[165,2050,310],{"class":309},[165,2052,313],{"class":273},[165,2054,316],{"class":175},[165,2056,2057],{"class":452},"boolean",[165,2059,325],{"class":175},[165,2061,328],{"class":175},[165,2063,2064,2066,2069,2071,2073,2075,2077,2080,2082,2085,2087],{"class":167,"line":367},[165,2065,334],{"class":269},[165,2067,2068],{"class":337}," onHand",[165,2070,341],{"class":309},[165,2072,344],{"class":171},[165,2074,348],{"class":347},[165,2076,351],{"class":175},[165,2078,2079],{"class":179},"articleFacade",[165,2081,351],{"class":175},[165,2083,2084],{"class":280},"onHand",[165,2086,306],{"class":362},[165,2088,211],{"class":175},[165,2090,2091,2093,2095,2098,2101],{"class":167,"line":420},[165,2092,370],{"class":171},[165,2094,2068],{"class":179},[165,2096,2097],{"class":309}," >",[165,2099,2100],{"class":1110}," 0",[165,2102,211],{"class":175},[165,2104,2105],{"class":167,"line":426},[165,2106,423],{"class":175},[165,2108,2109],{"class":167,"line":431},[165,2110,945],{"class":175},[147,2112,2113],{},"Trois choses à voir :",[1456,2115,2116,2128,2152],{},[1459,2117,2118,2121,2122,2124,2125,351],{},[1327,2119,2120],{},"C'est la porte, pas le handler."," Personne n'injecte un handler — ses méthodes prennent\ndes arguments positionnels. La façade prend l'invocation : chaque opération de\n",[151,2123,1934],{}," a la signature ",[151,2126,2127],{},"(invocation?) => Promise\u003C…>",[1459,2129,2130,2136,2137,2139,2140,2142,2143,2147,2148,2151],{},[1327,2131,2132,2135],{},[151,2133,2134],{},"keyof T"," est exactement la bonne liste."," Le scan saute ",[151,2138,1275],{}," et ",[151,2141,1483],{},", donc\nles méthodes publiques d'un handler ",[2144,2145,2146],"em",{},"sont"," ses opérations — et ",[151,2149,2150],{},"keyof"," exclut le reste\npour la même raison.",[1459,2153,2154,2157,2158,2161,2162,2165],{},[1327,2155,2156],{},"La signature ne dit pas où l'autre Frond tourne."," Le même type résout la façade locale\nou une doublure. Déclarer ",[151,2159,2160],{},"stock"," dans ",[151,2163,2164],{},"remotes:"," ne change pas cette ligne.",[147,2167,2168,2169,2172,2173,2175],{},"Ce qui ne voyage pas tout seul, c'est l'",[1327,2170,2171],{},"identité",". L'opération appelée reçoit\nl'invocation que vous lui passez, et rien d'autre : pour qu'un collector d'en face voie le\nmême utilisateur, déclarez ",[151,2174,1407],{}," (règle de binding 2) et transmettez-le.",[1512,2177,2179],{"id":2178},"annoncer-un-fait","Annoncer un fait",[147,2181,2182,2183,982,2186,2189,2190,2193],{},"Un appel nomme un destinataire ; une émission nomme un ",[1327,2184,2185],{},"sujet",[151,2187,2188],{},"Emit\u003CT>"," est une\ndépendance de constructeur comme une autre, et accepter un ",[151,2191,2192],{},"Fact\u003CT>"," EST l'abonnement —\npas de topic, pas d'appel d'inscription.",[147,2195,2196,2197,2199],{},"Voir ",[1385,2198,92],{"href":93}," — le résolveur, ce qui traverse un processus, et\nquoi faire quand la forme d'un fait bouge.",[147,2201,2202,2203,2205],{},"Suite : ",[1385,2204,76],{"href":77}," — les champs calculés ajoutés à la sortie d'une entité.",[2207,2208,2209],"style",{},"html pre.shiki code .sVHd0, html code.shiki .sVHd0{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#D73A49;--shiki-default-font-style:inherit;--shiki-dark:#F97583;--shiki-dark-font-style:inherit}html pre.shiki code .sP7_E, html code.shiki .sP7_E{--shiki-light:#39ADB5;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .su5hD, html code.shiki .su5hD{--shiki-light:#90A4AE;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sjJ54, html code.shiki .sjJ54{--shiki-light:#39ADB5;--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .s_sjI, html code.shiki .s_sjI{--shiki-light:#91B859;--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sbsja, html code.shiki .sbsja{--shiki-light:#9C3EDA;--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sbgvK, html code.shiki .sbgvK{--shiki-light:#E2931D;--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sGLFI, html code.shiki .sGLFI{--shiki-light:#6182B8;--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sutJx, html code.shiki .sutJx{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#6A737D;--shiki-default-font-style:inherit;--shiki-dark:#6A737D;--shiki-dark-font-style:inherit}html pre.shiki code .sVXei, html code.shiki .sVXei{--shiki-light:#E53935;--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .smGrS, html code.shiki .smGrS{--shiki-light:#39ADB5;--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .s_hVV, html code.shiki .s_hVV{--shiki-light:#90A4AE;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .s39Yj, html code.shiki .s39Yj{--shiki-light:#39ADB5;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .skxfh, html code.shiki .skxfh{--shiki-light:#E53935;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .s99_P, html code.shiki .s99_P{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#E36209;--shiki-default-font-style:inherit;--shiki-dark:#FFAB70;--shiki-dark-font-style:inherit}html pre.shiki code .sZMiF, html code.shiki .sZMiF{--shiki-light:#E2931D;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .srdBf, html code.shiki .srdBf{--shiki-light:#F76D47;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .syTEX, html code.shiki .syTEX{--shiki-light:#FF5370;--shiki-default:#005CC5;--shiki-dark:#79B8FF}",{"title":161,"searchDepth":214,"depth":214,"links":2211},[2212,2213,2214,2217,2218,2219],{"id":1138,"depth":214,"text":1139},{"id":1348,"depth":214,"text":1349},{"id":1498,"depth":214,"text":1499,"children":2215},[2216],{"id":1514,"depth":234,"text":1515},{"id":1538,"depth":214,"text":1539},{"id":1858,"depth":214,"text":1859},{"id":1927,"depth":214,"text":1928,"children":2220},[2221],{"id":2178,"depth":234,"text":2179},"Crud(Entity), les opérations, les quatre règles de binding, la vue de sortie.","md",{},{"title":72,"description":2222},"Jxp91bQWv-2I_CpPywBW3EX-mx2FLA8XFQVrXZgZOKw",1786637819897]