[{"data":1,"prerenderedAt":618},["ShallowReactive",2],{"docs-nav:fr":3,"docs:\u002Ffr\u002Fdocs\u002Fbusiness\u002Fcollectors":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":80,"body":139,"description":613,"extension":614,"meta":615,"navigation":252,"path":81,"seo":616,"stem":82,"__hash__":617},"docs_fr\u002Ffr\u002Fdocs\u002F4.business\u002F3.collectors.md",{"type":140,"value":141,"toc":608},"minimark",[142,146,155,396,399,479,484,528,532,542,546,549,578,591,597,604],[143,144,80],"h1",{"id":145},"collectors",[147,148,149,150,154],"p",{},"Un collector résout un paramètre de handler ",[151,152,153],"strong",{},"par son type"," à partir du contexte\nd'invocation. Les opérations qui déclarent ce paramètre reçoivent la valeur automatiquement.",[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 { Collector } from '@fougere\u002Fcore';\nimport type { InvocationContext } from '@fougere\u002Fcore';\nimport User from '..\u002F..\u002Fuser\u002Fentities\u002FUser.js';\n\n\u002F**\n * Le middleware auth pose l'user de session sur ctx.state.user —\n * ceci le fait remonter à tout handler qui déclare `user: User | null`.\n *\u002F\nexport default class CurrentUserCollector extends Collector(User) {\n  async collect(ctx: InvocationContext) {\n    return (ctx.state.user ?? null) as User | null;\n  }\n}\n","ts","",[163,164,165,202,227,247,254,261,267,273,279,308,337,384,390],"code",{"__ignoreMap":161},[166,167,170,174,178,182,185,188,192,196,199],"span",{"class":168,"line":169},"line",1,[166,171,173],{"class":172},"sVHd0","import",[166,175,177],{"class":176},"sP7_E"," {",[166,179,181],{"class":180},"su5hD"," Collector",[166,183,184],{"class":176}," }",[166,186,187],{"class":172}," from",[166,189,191],{"class":190},"sjJ54"," '",[166,193,195],{"class":194},"s_sjI","@fougere\u002Fcore",[166,197,198],{"class":190},"'",[166,200,201],{"class":176},";\n",[166,203,205,207,210,212,215,217,219,221,223,225],{"class":168,"line":204},2,[166,206,173],{"class":172},[166,208,209],{"class":172}," type",[166,211,177],{"class":176},[166,213,214],{"class":180}," InvocationContext",[166,216,184],{"class":176},[166,218,187],{"class":172},[166,220,191],{"class":190},[166,222,195],{"class":194},[166,224,198],{"class":190},[166,226,201],{"class":176},[166,228,230,232,235,238,240,243,245],{"class":168,"line":229},3,[166,231,173],{"class":172},[166,233,234],{"class":180}," User ",[166,236,237],{"class":172},"from",[166,239,191],{"class":190},[166,241,242],{"class":194},"..\u002F..\u002Fuser\u002Fentities\u002FUser.js",[166,244,198],{"class":190},[166,246,201],{"class":176},[166,248,250],{"class":168,"line":249},4,[166,251,253],{"emptyLinePlaceholder":252},true,"\n",[166,255,257],{"class":168,"line":256},5,[166,258,260],{"class":259},"sutJx","\u002F**\n",[166,262,264],{"class":168,"line":263},6,[166,265,266],{"class":259}," * Le middleware auth pose l'user de session sur ctx.state.user —\n",[166,268,270],{"class":168,"line":269},7,[166,271,272],{"class":259}," * ceci le fait remonter à tout handler qui déclare `user: User | null`.\n",[166,274,276],{"class":168,"line":275},8,[166,277,278],{"class":259}," *\u002F\n",[166,280,282,285,288,292,296,299,302,305],{"class":168,"line":281},9,[166,283,284],{"class":172},"export",[166,286,287],{"class":172}," default",[166,289,291],{"class":290},"sbsja"," class",[166,293,295],{"class":294},"sbgvK"," CurrentUserCollector",[166,297,298],{"class":290}," extends",[166,300,181],{"class":301},"sGLFI",[166,303,304],{"class":180},"(User) ",[166,306,307],{"class":176},"{\n",[166,309,311,314,318,321,325,329,331,334],{"class":168,"line":310},10,[166,312,313],{"class":290},"  async",[166,315,317],{"class":316},"sVXei"," collect",[166,319,320],{"class":176},"(",[166,322,324],{"class":323},"s99_P","ctx",[166,326,328],{"class":327},"smGrS",":",[166,330,214],{"class":294},[166,332,333],{"class":176},")",[166,335,336],{"class":176}," {\n",[166,338,340,343,347,349,352,355,357,360,363,367,370,373,376,379,382],{"class":168,"line":339},11,[166,341,342],{"class":172},"    return",[166,344,346],{"class":345},"skxfh"," (",[166,348,324],{"class":180},[166,350,351],{"class":176},".",[166,353,354],{"class":180},"state",[166,356,351],{"class":176},[166,358,359],{"class":180},"user",[166,361,362],{"class":327}," ??",[166,364,366],{"class":365},"s39Yj"," null",[166,368,369],{"class":345},") ",[166,371,372],{"class":172},"as",[166,374,375],{"class":294}," User",[166,377,378],{"class":327}," |",[166,380,366],{"class":381},"sZMiF",[166,383,201],{"class":176},[166,385,387],{"class":168,"line":386},12,[166,388,389],{"class":176},"  }\n",[166,391,393],{"class":168,"line":392},13,[166,394,395],{"class":176},"}\n",[147,397,398],{},"Dès lors, dans n'importe quel handler de la Frond :",[156,400,402],{"className":158,"code":401,"language":160,"meta":161,"style":161},"async mine(user: User | null): Promise\u003CPost[]> { … }\nasync publish(id: string, user: User | null): Promise\u003CPost> { … }\n",[163,403,404,442],{"__ignoreMap":161},[166,405,406,409,412,415,418,420,423,426,429,432,435,437,440],{"class":168,"line":169},[166,407,408],{"class":180},"async ",[166,410,411],{"class":301},"mine",[166,413,414],{"class":180},"(user: User ",[166,416,417],{"class":327},"|",[166,419,366],{"class":365},[166,421,422],{"class":180},"): ",[166,424,425],{"class":381},"Promise",[166,427,428],{"class":327},"\u003C",[166,430,431],{"class":180},"Post[]",[166,433,434],{"class":327},">",[166,436,177],{"class":176},[166,438,439],{"class":180}," … ",[166,441,395],{"class":176},[166,443,444,446,449,452,455,458,460,462,464,466,468,471,473,475,477],{"class":168,"line":204},[166,445,408],{"class":180},[166,447,448],{"class":301},"publish",[166,450,451],{"class":180},"(id: string",[166,453,454],{"class":176},",",[166,456,457],{"class":180}," user: User ",[166,459,417],{"class":327},[166,461,366],{"class":365},[166,463,422],{"class":180},[166,465,425],{"class":381},[166,467,428],{"class":327},[166,469,470],{"class":180},"Post",[166,472,434],{"class":327},[166,474,177],{"class":176},[166,476,439],{"class":180},[166,478,395],{"class":176},[480,481,483],"h2",{"id":482},"règles-de-résolution","Règles de résolution",[485,486,487,511,525],"ul",{},[488,489,490,491,494,495,498,499,502,503,506,507,510],"li",{},"Le match est ",[151,492,493],{},"par nom de type d'entité"," : ",[163,496,497],{},"Collector(User)"," résout les paramètres\ntypés ",[163,500,501],{},"User | null"," (ou ",[163,504,505],{},"User","). La classe s'enregistre comme ",[163,508,509],{},"UserCollector"," par\nconvention.",[488,512,513,516,517,520,521,524],{},[151,514,515],{},"Épelez l'union."," Le parser de signatures est AST-only : ",[163,518,519],{},"user: User | null"," matche,\nun alias de type (",[163,522,523],{},"user: CurrentUser",") est invisible et ne lie rien.",[488,526,527],{},"Les collectors sont des classes injectables — déclarez des dépendances de constructeur\ncomme d'habitude.",[480,529,531],{"id":530},"le-state-et-le-gradient","Le state et le gradient",[147,533,534,537,538,541],{},[163,535,536],{},"ctx.state"," est l'état de requête construit par l'application consommatrice, par exemple à\npartir de la session. Lors d'un appel distant, cet état est transmis avec l'invocation :\nle collector reçoit le même ",[163,539,540],{},"ctx.state.user"," qu'en local.",[480,543,545],{"id":544},"un-collector-ne-franchit-pas-la-frontière-dune-frond","Un collector ne franchit pas la frontière d'une Frond",[147,547,548],{},"Placez le collector dans chaque Frond qui le consomme. Ce qui arrive sinon mérite d'être\ndit précisément, parce que ce n'est ni « plus tard » ni « rien » :",[485,550,551,562],{},[488,552,553,556,557,561],{},[151,554,555],{},"ce n'est pas au moment du split."," La liaison est décidée au démarrage, dans un seul\nprocessus, à partir des collectors ",[558,559,560],"em",{},"de la Frond elle-même"," ;",[488,563,564,567,568,571,572,575,576,351],{},[151,565,566],{},"le paramètre n'est pas vide."," Un type que la Frond ne sait pas résoudre tombe dans la\nquatrième règle de binding, ",[163,569,570],{},"body",". Le handler reçoit donc ",[151,573,574],{},"le corps de la requête"," là\noù il attend un ",[163,577,505],{},[147,579,580,581,583,584,586,587,590],{},"Autrement dit, ",[163,582,519],{}," déclaré dans une Frond qui n'a pas de ",[163,585,509],{},"\nreçoit ce que le client a envoyé. Un handler qui juge sur ",[163,588,589],{},"user.role"," juge sur une valeur\nfournie par l'appelant.",[592,593,594],"blockquote",{},[147,595,596],{},"Une version précédente de cette page disait que le collector était « perdu après une\nséparation de processus ». C'était faux deux fois, et la réalité est moins confortable.",[147,598,599,600,603],{},"Suite : ",[601,602,84],"a",{"href":85}," — les erreurs typées entre les couches.",[605,606,607],"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 .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 .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 .sVXei, html code.shiki .sVXei{--shiki-light:#E53935;--shiki-default:#6F42C1;--shiki-dark:#B392F0}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 .smGrS, html code.shiki .smGrS{--shiki-light:#39ADB5;--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .skxfh, html code.shiki .skxfh{--shiki-light:#E53935;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .s39Yj, html code.shiki .s39Yj{--shiki-light:#39ADB5;--shiki-default:#005CC5;--shiki-dark:#79B8FF}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);}",{"title":161,"searchDepth":204,"depth":204,"links":609},[610,611,612],{"id":482,"depth":204,"text":483},{"id":530,"depth":204,"text":531},{"id":544,"depth":204,"text":545},"Résoudre les paramètres de handler par type depuis le contexte d'invocation.","md",{},{"title":80,"description":613},"BO9pVb3tNeJrnWxzywriDKeaSq4M-lOtvzlFy2ymHVs",1786637819909]