[{"data":1,"prerenderedAt":723},["ShallowReactive",2],{"docs-nav:fr":3,"docs:\u002Ffr\u002Fdocs\u002Fschema\u002Fviews":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":55,"body":139,"description":718,"extension":719,"meta":720,"navigation":252,"path":56,"seo":721,"stem":57,"__hash__":722},"docs_fr\u002Ffr\u002Fdocs\u002F3.schema\u002F2.views.md",{"type":140,"value":141,"toc":712},"minimark",[142,146,150,365,379,384,451,458,462,503,507,510,551,565,569,585,607,610,638,641,688,702,708],[143,144,55],"h1",{"id":145},"vues",[147,148,149],"p",{},"Une vue est une classe de schéma créée à partir d'une entité :",[151,152,157],"pre",{"className":153,"code":154,"language":155,"meta":156,"style":156},"language-ts shiki shiki-themes material-theme-lighter github-light github-dark","\u002F** Ce qu'un auteur peut écrire. *\u002F\nexport class PostDraft extends Post.pick('slug', 'title', 'summary', 'body') {}\n\n\u002F** Ce que l'index public montre — pas de body. *\u002F\nexport class PostCard extends Post.pick('id', 'slug', 'title', 'summary', 'publishedAt') {}\n\n\u002F** L'entrée d'une opération de lecture custom. *\u002F\nexport class BySlugInput extends Post.pick('slug') {}\n","ts","",[158,159,160,169,247,254,260,324,329,335],"code",{"__ignoreMap":156},[161,162,165],"span",{"class":163,"line":164},"line",1,[161,166,168],{"class":167},"sutJx","\u002F** Ce qu'un auteur peut écrire. *\u002F\n",[161,170,172,176,180,184,187,191,195,199,202,206,210,212,215,218,221,223,225,227,230,232,234,236,239,241,244],{"class":163,"line":171},2,[161,173,175],{"class":174},"sVHd0","export",[161,177,179],{"class":178},"sbsja"," class",[161,181,183],{"class":182},"sbgvK"," PostDraft",[161,185,186],{"class":178}," extends",[161,188,190],{"class":189},"su5hD"," Post",[161,192,194],{"class":193},"sP7_E",".",[161,196,198],{"class":197},"sGLFI","pick",[161,200,201],{"class":189},"(",[161,203,205],{"class":204},"sjJ54","'",[161,207,209],{"class":208},"s_sjI","slug",[161,211,205],{"class":204},[161,213,214],{"class":193},",",[161,216,217],{"class":204}," '",[161,219,220],{"class":208},"title",[161,222,205],{"class":204},[161,224,214],{"class":193},[161,226,217],{"class":204},[161,228,229],{"class":208},"summary",[161,231,205],{"class":204},[161,233,214],{"class":193},[161,235,217],{"class":204},[161,237,238],{"class":208},"body",[161,240,205],{"class":204},[161,242,243],{"class":189},") ",[161,245,246],{"class":193},"{}\n",[161,248,250],{"class":163,"line":249},3,[161,251,253],{"emptyLinePlaceholder":252},true,"\n",[161,255,257],{"class":163,"line":256},4,[161,258,259],{"class":167},"\u002F** Ce que l'index public montre — pas de body. *\u002F\n",[161,261,263,265,267,270,272,274,276,278,280,282,285,287,289,291,293,295,297,299,301,303,305,307,309,311,313,315,318,320,322],{"class":163,"line":262},5,[161,264,175],{"class":174},[161,266,179],{"class":178},[161,268,269],{"class":182}," PostCard",[161,271,186],{"class":178},[161,273,190],{"class":189},[161,275,194],{"class":193},[161,277,198],{"class":197},[161,279,201],{"class":189},[161,281,205],{"class":204},[161,283,284],{"class":208},"id",[161,286,205],{"class":204},[161,288,214],{"class":193},[161,290,217],{"class":204},[161,292,209],{"class":208},[161,294,205],{"class":204},[161,296,214],{"class":193},[161,298,217],{"class":204},[161,300,220],{"class":208},[161,302,205],{"class":204},[161,304,214],{"class":193},[161,306,217],{"class":204},[161,308,229],{"class":208},[161,310,205],{"class":204},[161,312,214],{"class":193},[161,314,217],{"class":204},[161,316,317],{"class":208},"publishedAt",[161,319,205],{"class":204},[161,321,243],{"class":189},[161,323,246],{"class":193},[161,325,327],{"class":163,"line":326},6,[161,328,253],{"emptyLinePlaceholder":252},[161,330,332],{"class":163,"line":331},7,[161,333,334],{"class":167},"\u002F** L'entrée d'une opération de lecture custom. *\u002F\n",[161,336,338,340,342,345,347,349,351,353,355,357,359,361,363],{"class":163,"line":337},8,[161,339,175],{"class":174},[161,341,179],{"class":178},[161,343,344],{"class":182}," BySlugInput",[161,346,186],{"class":178},[161,348,190],{"class":189},[161,350,194],{"class":193},[161,352,198],{"class":197},[161,354,201],{"class":189},[161,356,205],{"class":204},[161,358,209],{"class":208},[161,360,205],{"class":204},[161,362,243],{"class":189},[161,364,246],{"class":193},[147,366,367,368,371,372,375,376,194],{},"Une vue est une classe de schéma complète : elle a ",[158,369,370],{},"getFields()",", ",[158,373,374],{},"validate()",", et\ns'utilise comme type TypeScript. Les vues se chaînent : ",[158,377,378],{},"Post.pick(…).partial()",[380,381,383],"h2",{"id":382},"les-quatre-dérivations","Les quatre dérivations",[385,386,387,400],"table",{},[388,389,390],"thead",{},[391,392,393,397],"tr",{},[394,395,396],"th",{},"Dérivation",[394,398,399],{},"Produit",[401,402,403,414,424,434],"tbody",{},[391,404,405,411],{},[406,407,408],"td",{},[158,409,410],{},"Post.pick('a', 'b')",[406,412,413],{},"ces champs seulement",[391,415,416,421],{},[406,417,418],{},[158,419,420],{},"Post.omit('a')",[406,422,423],{},"tous les champs sauf ceux-là",[391,425,426,431],{},[406,427,428],{},[158,429,430],{},"Post.partial()",[406,432,433],{},"chaque champ optionnel : un champ absent n'est pas mis à jour",[391,435,436,441],{},[406,437,438],{},[158,439,440],{},"Post.extend({ extra: text() })",[406,442,443,444,447,448],{},"l'entité plus des champs — c'est ainsi que ",[158,445,446],{},"User"," étend ",[158,449,450],{},"AuthUser",[147,452,453,454,457],{},"Le mode ",[158,455,456],{},"partial"," est conservé lorsque la vue est utilisée comme entrée d'une opération.",[380,459,461],{"id":460},"où-les-vues-se-branchent","Où les vues se branchent",[463,464,465,477,493],"ul",{},[466,467,468,472,473,476],"li",{},[469,470,471],"strong",{},"Entrées de handler"," — déclarez la vue comme type du paramètre ; la façade valide le\nbody du fil contre elle avant votre code (",[474,475,72],"a",{"href":73},").",[466,478,479,482,483,486,487,490,491,476],{},[469,480,481],{},"Sorties de handler"," — ",[158,484,485],{},"Crud(Post, { list: PostCard })"," nomme la vue d'une opération ;\n",[158,488,489],{},"Crud(Post, PostPublic)"," restreint tout le handler (",[474,492,72],{"href":73},[466,494,495,482,497,500,501,476],{},[469,496,105],{},[158,498,499],{},"useFormFor(PostDraft)"," dérive ses champs de la vue (",[474,502,105],{"href":106},[380,504,506],{"id":505},"les-projections-io","Les projections io",[147,508,509],{},"L'axe boundary dérive deux ensembles de champs que toutes les surfaces utilisent :",[151,511,513],{"className":153,"code":512,"language":155,"meta":156,"style":156},"inputFields(Post.getFields())    \u002F\u002F les champs qu'un client peut ÉCRIRE — readOnly exclus\noutputFields(Post.getFields())   \u002F\u002F les champs qu'un client peut LIRE  — writeOnly exclus\n",[158,514,515,534],{"__ignoreMap":156},[161,516,517,520,523,525,528,531],{"class":163,"line":164},[161,518,519],{"class":197},"inputFields",[161,521,522],{"class":189},"(Post",[161,524,194],{"class":193},[161,526,527],{"class":197},"getFields",[161,529,530],{"class":189},"())    ",[161,532,533],{"class":167},"\u002F\u002F les champs qu'un client peut ÉCRIRE — readOnly exclus\n",[161,535,536,539,541,543,545,548],{"class":163,"line":171},[161,537,538],{"class":197},"outputFields",[161,540,522],{"class":189},[161,542,194],{"class":193},[161,544,527],{"class":197},[161,546,547],{"class":189},"())   ",[161,549,550],{"class":167},"\u002F\u002F les champs qu'un client peut LIRE  — writeOnly exclus\n",[147,552,553,554,557,558,561,562,564],{},"C'est pourquoi un formulaire bâti sur ",[158,555,556],{},"Post"," n'affiche pas d'inputs ",[158,559,560],{},"status"," ou\n",[158,563,317],{},", sans configuration supplémentaire par formulaire.",[380,566,568],{"id":567},"choisir-entre-un-champ-et-une-vue","Choisir entre un champ et une vue",[147,570,571,574,575,578,579,574,581,584],{},[158,572,573],{},"readOnly"," \u002F ",[158,576,577],{},"writeOnly"," et ",[158,580,198],{},[158,582,583],{},"omit"," peuvent tous retirer un champ d'une surface,\nmais leur portée diffère.",[463,586,587,597],{},[466,588,589,592,593,596],{},[469,590,591],{},"boundary"," (sur le champ) définit une règle globale. Avec ",[158,594,595],{},"writeOnly(password)",", le mot\nde passe est exclu de toutes les sorties.",[466,598,599,602,603,606],{},[469,600,601],{},"pick \u002F omit"," (sur une vue) choisit les champs d'un usage précis. Par exemple,\n",[158,604,605],{},"Post.pick('id', 'title')"," définit la réponse de l'index public.",[147,608,609],{},"Ces deux mécanismes sont complémentaires.",[463,611,612,622],{},[466,613,614,615,617,618,621],{},"Sans ",[158,616,577],{}," sur le champ, chaque vue de sortie devrait penser à omettre ",[158,619,620],{},"password",".\nLa règle globale évite cet oubli.",[466,623,624,625,371,627,629,630,633,634,637],{},"Une réponse publique (",[158,626,284],{},[158,628,220],{},") et une réponse admin (",[158,631,632],{},"+ authorEmail",") ont en revanche\nbesoin de vues différentes : ",[158,635,636],{},"authorEmail"," est inclus ou exclu selon l'usage.",[147,639,640],{},"Le critère est la portée de la règle : globale ou propre à un usage.",[385,642,643,656],{},[388,644,645],{},[391,646,647,650,653],{},[394,648,649],{},"Le fait est…",[394,651,652],{},"Il vit…",[394,654,655],{},"Exemple",[401,657,658,673],{},[391,659,660,663,670],{},[406,661,662],{},"vrai partout (invariant)",[406,664,665,666,574,668],{},"sur le champ — ",[158,667,573],{},[158,669,577],{},[406,671,672],{},"un mot de passe ne sort jamais",[391,674,675,678,685],{},[406,676,677],{},"vrai pour un usage (local)",[406,679,680,681,574,683],{},"en dérivation — ",[158,682,198],{},[158,684,583],{},[406,686,687],{},"cet endpoint ne renvoie que id + titre",[147,689,690,691,693,694,697,698,701],{},"Une règle ",[158,692,591],{}," est sérialisée dans la ",[474,695,696],{"href":60},"carte"," sous\n",[158,699,700],{},"x-fougere.boundary",". Un consommateur dans un autre langage peut donc l'appliquer. Une vue\ndérivée en TypeScript n'est pas sérialisée.",[147,703,704,705,707],{},"Suite : ",[474,706,59],{"href":60}," — la forme portable du schéma.",[709,710,711],"style",{},"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 .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 .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 .su5hD, html code.shiki .su5hD{--shiki-light:#90A4AE;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sP7_E, html code.shiki .sP7_E{--shiki-light:#39ADB5;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sGLFI, html code.shiki .sGLFI{--shiki-light:#6182B8;--shiki-default:#6F42C1;--shiki-dark:#B392F0}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 .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":156,"searchDepth":171,"depth":171,"links":713},[714,715,716,717],{"id":382,"depth":171,"text":383},{"id":460,"depth":171,"text":461},{"id":505,"depth":171,"text":506},{"id":567,"depth":171,"text":568},"Créer des schémas d'entrée et de sortie avec pick, omit, partial et extend.","md",{},{"title":55,"description":718},"FzopEElpR9eAxgAbaeQWWLshFqU8n9g_it4GoQXwqh4",1786637819776]