[{"data":1,"prerenderedAt":1403},["ShallowReactive",2],{"docs-nav:fr":3,"docs:\u002Ffr\u002Fdocs\u002Fschema\u002Fentities":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":51,"body":139,"description":1398,"extension":1399,"meta":1400,"navigation":267,"path":52,"seo":1401,"stem":53,"__hash__":1402},"docs_fr\u002Ffr\u002Fdocs\u002F3.schema\u002F1.entities.md",{"type":140,"value":141,"toc":1391},"minimark",[142,146,155,532,546,551,554,726,729,811,831,838,945,952,955,994,997,1084,1091,1103,1108,1118,1125,1181,1184,1191,1195,1198,1301,1322,1336,1340,1347,1375,1381,1387],[143,144,51],"h1",{"id":145},"entités",[147,148,149,150,154],"p",{},"Une entité est une classe qui étend la factory ",[151,152,153],"code",{},"entity()",". Elle fournit le type\nTypeScript, la validation et les métadonnées lues par les adapters.",[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 { entity, primary, text, ref, created, oneOf, date, readOnly, optional } from '@fougere\u002Fschema';\nimport Author from '.\u002FAuthor.js';\n\nexport default class Post extends entity({\n  id: primary(),\n  slug: text({ min: 1, max: 80 }),\n  title: text({ min: 1, max: 160 }),\n  body: optional(text()),\n  authorId: ref(Author),\n  createdAt: created(),\n  status: readOnly(oneOf('draft', 'published', { default: 'draft' })),\n  publishedAt: readOnly(optional(date())),\n}) {}\n","ts","",[151,163,164,242,262,269,298,316,357,392,412,427,441,495,520],{"__ignoreMap":161},[165,166,169,173,177,181,184,187,189,192,194,197,199,202,204,207,209,212,214,217,219,222,225,228,232,236,239],"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"," entity",[165,182,183],{"class":175},",",[165,185,186],{"class":179}," primary",[165,188,183],{"class":175},[165,190,191],{"class":179}," text",[165,193,183],{"class":175},[165,195,196],{"class":179}," ref",[165,198,183],{"class":175},[165,200,201],{"class":179}," created",[165,203,183],{"class":175},[165,205,206],{"class":179}," oneOf",[165,208,183],{"class":175},[165,210,211],{"class":179}," date",[165,213,183],{"class":175},[165,215,216],{"class":179}," readOnly",[165,218,183],{"class":175},[165,220,221],{"class":179}," optional",[165,223,224],{"class":175}," }",[165,226,227],{"class":171}," from",[165,229,231],{"class":230},"sjJ54"," '",[165,233,235],{"class":234},"s_sjI","@fougere\u002Fschema",[165,237,238],{"class":230},"'",[165,240,241],{"class":175},";\n",[165,243,245,247,250,253,255,258,260],{"class":167,"line":244},2,[165,246,172],{"class":171},[165,248,249],{"class":179}," Author ",[165,251,252],{"class":171},"from",[165,254,231],{"class":230},[165,256,257],{"class":234},".\u002FAuthor.js",[165,259,238],{"class":230},[165,261,241],{"class":175},[165,263,265],{"class":167,"line":264},3,[165,266,268],{"emptyLinePlaceholder":267},true,"\n",[165,270,272,275,278,282,286,289,292,295],{"class":167,"line":271},4,[165,273,274],{"class":171},"export",[165,276,277],{"class":171}," default",[165,279,281],{"class":280},"sbsja"," class",[165,283,285],{"class":284},"sbgvK"," Post",[165,287,288],{"class":280}," extends",[165,290,180],{"class":291},"sGLFI",[165,293,294],{"class":179},"(",[165,296,297],{"class":175},"{\n",[165,299,301,305,308,310,313],{"class":167,"line":300},5,[165,302,304],{"class":303},"skxfh","  id",[165,306,307],{"class":175},":",[165,309,186],{"class":291},[165,311,312],{"class":179},"()",[165,314,315],{"class":175},",\n",[165,317,319,322,324,326,328,331,334,336,340,342,345,347,350,352,355],{"class":167,"line":318},6,[165,320,321],{"class":303},"  slug",[165,323,307],{"class":175},[165,325,191],{"class":291},[165,327,294],{"class":179},[165,329,330],{"class":175},"{",[165,332,333],{"class":303}," min",[165,335,307],{"class":175},[165,337,339],{"class":338},"srdBf"," 1",[165,341,183],{"class":175},[165,343,344],{"class":303}," max",[165,346,307],{"class":175},[165,348,349],{"class":338}," 80",[165,351,224],{"class":175},[165,353,354],{"class":179},")",[165,356,315],{"class":175},[165,358,360,363,365,367,369,371,373,375,377,379,381,383,386,388,390],{"class":167,"line":359},7,[165,361,362],{"class":303},"  title",[165,364,307],{"class":175},[165,366,191],{"class":291},[165,368,294],{"class":179},[165,370,330],{"class":175},[165,372,333],{"class":303},[165,374,307],{"class":175},[165,376,339],{"class":338},[165,378,183],{"class":175},[165,380,344],{"class":303},[165,382,307],{"class":175},[165,384,385],{"class":338}," 160",[165,387,224],{"class":175},[165,389,354],{"class":179},[165,391,315],{"class":175},[165,393,395,398,400,402,404,407,410],{"class":167,"line":394},8,[165,396,397],{"class":303},"  body",[165,399,307],{"class":175},[165,401,221],{"class":291},[165,403,294],{"class":179},[165,405,406],{"class":291},"text",[165,408,409],{"class":179},"())",[165,411,315],{"class":175},[165,413,415,418,420,422,425],{"class":167,"line":414},9,[165,416,417],{"class":303},"  authorId",[165,419,307],{"class":175},[165,421,196],{"class":291},[165,423,424],{"class":179},"(Author)",[165,426,315],{"class":175},[165,428,430,433,435,437,439],{"class":167,"line":429},10,[165,431,432],{"class":303},"  createdAt",[165,434,307],{"class":175},[165,436,201],{"class":291},[165,438,312],{"class":179},[165,440,315],{"class":175},[165,442,444,447,449,451,453,456,458,460,463,465,467,469,472,474,476,478,480,482,484,486,488,490,493],{"class":167,"line":443},11,[165,445,446],{"class":303},"  status",[165,448,307],{"class":175},[165,450,216],{"class":291},[165,452,294],{"class":179},[165,454,455],{"class":291},"oneOf",[165,457,294],{"class":179},[165,459,238],{"class":230},[165,461,462],{"class":234},"draft",[165,464,238],{"class":230},[165,466,183],{"class":175},[165,468,231],{"class":230},[165,470,471],{"class":234},"published",[165,473,238],{"class":230},[165,475,183],{"class":175},[165,477,176],{"class":175},[165,479,277],{"class":303},[165,481,307],{"class":175},[165,483,231],{"class":230},[165,485,462],{"class":234},[165,487,238],{"class":230},[165,489,224],{"class":175},[165,491,492],{"class":179},"))",[165,494,315],{"class":175},[165,496,498,501,503,505,507,510,512,515,518],{"class":167,"line":497},12,[165,499,500],{"class":303},"  publishedAt",[165,502,307],{"class":175},[165,504,216],{"class":291},[165,506,294],{"class":179},[165,508,509],{"class":291},"optional",[165,511,294],{"class":179},[165,513,514],{"class":291},"date",[165,516,517],{"class":179},"()))",[165,519,315],{"class":175},[165,521,523,526,529],{"class":167,"line":522},13,[165,524,525],{"class":175},"}",[165,527,528],{"class":179},") ",[165,530,531],{"class":175},"{}\n",[147,533,534,535,538,539,542,543,545],{},"Le nom de classe sert d'identité : ",[151,536,537],{},"Post.name"," nomme la table SQLite, le type GraphQL, la\nclé d'enregistrement (",[151,540,541],{},"post",") et le match DI. ",[151,544,153],{}," ne prend pas de nom séparé.",[547,548,550],"h2",{"id":549},"le-vocabulaire-des-champs","Le vocabulaire des champs",[147,552,553],{},"Champs de valeur :",[555,556,557,573],"table",{},[558,559,560],"thead",{},[561,562,563,567,570],"tr",{},[564,565,566],"th",{},"Helper",[564,568,569],{},"Type",[564,571,572],{},"Options",[574,575,576,607,626,643,666,682,697,711],"tbody",{},[561,577,578,584,589],{},[579,580,581],"td",{},[151,582,583],{},"text(opts?)",[579,585,586],{},[151,587,588],{},"string",[579,590,591,594,595,594,598,594,601,594,604],{},[151,592,593],{},"min",", ",[151,596,597],{},"max",[151,599,600],{},"pattern",[151,602,603],{},"format",[151,605,606],{},"default",[561,608,609,614,618],{},[579,610,611],{},[151,612,613],{},"email(opts?)",[579,615,616],{},[151,617,588],{},[579,619,620,621,623,624],{},"options de ",[151,622,406],{}," sans ",[151,625,603],{},[561,627,628,633,637],{},[579,629,630],{},[151,631,632],{},"url(opts?)",[579,634,635],{},[151,636,588],{},[579,638,620,639,623,641],{},[151,640,406],{},[151,642,603],{},[561,644,645,650,655],{},[579,646,647],{},[151,648,649],{},"number(opts?)",[579,651,652],{},[151,653,654],{},"number",[579,656,657,594,659,594,661,594,664],{},[151,658,593],{},[151,660,597],{},[151,662,663],{},"integer",[151,665,606],{},[561,667,668,673,678],{},[579,669,670],{},[151,671,672],{},"bool(opts?)",[579,674,675],{},[151,676,677],{},"boolean",[579,679,680],{},[151,681,606],{},[561,683,684,689,694],{},[579,685,686],{},[151,687,688],{},"date()",[579,690,691],{},[151,692,693],{},"Date",[579,695,696],{},"—",[561,698,699,704,707],{},[579,700,701],{},[151,702,703],{},"oneOf(...valeurs, opts?)",[579,705,706],{},"union de littéraux",[579,708,709],{},[151,710,606],{},[561,712,713,718,723],{},[579,714,715],{},[151,716,717],{},"list(item, opts?)",[579,719,720],{},[151,721,722],{},"T[]",[579,724,725],{},"item = n'importe quel champ",[147,727,728],{},"Champs de rôle :",[555,730,731,740],{},[558,732,733],{},[561,734,735,737],{},[564,736,566],{},[564,738,739],{},"Sens",[574,741,742,755,772,782,797],{},[561,743,744,749],{},[579,745,746],{},[151,747,748],{},"primary()",[579,750,751,752],{},"clé primaire, générée — s'applique aussi à un champ : ",[151,753,754],{},"primary(text())",[561,756,757,762],{},[579,758,759],{},[151,760,761],{},"ref(Entity)",[579,763,764,765,767,768,771],{},"clé étrangère (",[151,766,588],{},") ; accepte ",[151,769,770],{},"() => Entity"," pour les cycles",[561,773,774,779],{},[579,775,776],{},[151,777,778],{},"many(Entity)",[579,780,781],{},"one-to-many — rôle seul, pas de colonne",[561,783,784,789],{},[579,785,786],{},[151,787,788],{},"unique(f)",[579,790,791,792,796],{},"deux lignes ne portent pas la même valeur — une contrainte que la ",[793,794,795],"strong",{},"base"," applique",[561,798,799,804],{},[579,800,801],{},[151,802,803],{},"indexed(f)",[579,805,806,807,810],{},"les lectures filtrent souvent dessus — émet ",[151,808,809],{},"CREATE INDEX",", ne change aucune réponse",[147,812,813,814,594,816,818,819,821,822,825,826,818,828,830],{},"Les règles ",[151,815,455],{},[151,817,593],{}," et ",[151,820,597],{}," sont aussi émises en contraintes ",[151,823,824],{},"CHECK",". Elles\ns'appliquent donc aux écritures qui ne passent pas par la façade, par exemple une requête\nSQL directe ou un autre processus. ",[151,827,600],{},[151,829,603],{}," restent validés à la façade, car\nles dialectes d'expressions régulières diffèrent selon les bases.",[147,832,833,834,837],{},"Certains faits portent sur une paire, pas sur un champ. « Un livre apparaît une fois\ndans une liste » est vrai de ",[151,835,836],{},"(listId, docId)"," et d'aucun des deux seul, donc il se\ndéclare sur l'entité :",[156,839,841],{"className":158,"code":840,"language":160,"meta":161,"style":161},"class ListBook extends entity({\n  id: primary(),\n  listId: ref(List),\n  docId: text(),\n}, {\n  unique: [['listId', 'docId']],\n}) {}\n",[151,842,843,859,871,885,898,906,937],{"__ignoreMap":161},[165,844,845,848,851,853,855,857],{"class":167,"line":168},[165,846,847],{"class":280},"class",[165,849,850],{"class":284}," ListBook",[165,852,288],{"class":280},[165,854,180],{"class":291},[165,856,294],{"class":179},[165,858,297],{"class":175},[165,860,861,863,865,867,869],{"class":167,"line":244},[165,862,304],{"class":303},[165,864,307],{"class":175},[165,866,186],{"class":291},[165,868,312],{"class":179},[165,870,315],{"class":175},[165,872,873,876,878,880,883],{"class":167,"line":264},[165,874,875],{"class":303},"  listId",[165,877,307],{"class":175},[165,879,196],{"class":291},[165,881,882],{"class":179},"(List)",[165,884,315],{"class":175},[165,886,887,890,892,894,896],{"class":167,"line":271},[165,888,889],{"class":303},"  docId",[165,891,307],{"class":175},[165,893,191],{"class":291},[165,895,312],{"class":179},[165,897,315],{"class":175},[165,899,900,903],{"class":167,"line":300},[165,901,902],{"class":175},"},",[165,904,905],{"class":175}," {\n",[165,907,908,911,913,916,918,921,923,925,927,930,932,935],{"class":167,"line":318},[165,909,910],{"class":303},"  unique",[165,912,307],{"class":175},[165,914,915],{"class":179}," [[",[165,917,238],{"class":230},[165,919,920],{"class":234},"listId",[165,922,238],{"class":230},[165,924,183],{"class":175},[165,926,231],{"class":230},[165,928,929],{"class":234},"docId",[165,931,238],{"class":230},[165,933,934],{"class":179},"]]",[165,936,315],{"class":175},[165,938,939,941,943],{"class":167,"line":359},[165,940,525],{"class":175},[165,942,528],{"class":179},[165,944,531],{"class":175},[147,946,947,948,951],{},"La base applique cette contrainte afin de couvrir aussi les écritures concurrentes. Une\ndérivation qui retire un membre du groupe retire également le groupe : conserver seulement\n",[151,949,950],{},"(listId)"," changerait la règle déclarée.",[147,953,954],{},"Champs de lifecycle :",[555,956,957,965],{},[558,958,959],{},[561,960,961,963],{},[564,962,566],{},[564,964,739],{},[574,966,967,981],{},[561,968,969,974],{},[579,970,971],{},[151,972,973],{},"created()",[579,975,976,977,980],{},"tamponné à la création (",[151,978,979],{},"createdAt",") — jamais écrit par un client",[561,982,983,988],{},[579,984,985],{},[151,986,987],{},"updated()",[579,989,990,991,354],{},"re-tamponné à chaque mise à jour (",[151,992,993],{},"updatedAt",[147,995,996],{},"Wrappers (se composent autour de n'importe quel champ) :",[555,998,999,1012],{},[558,1000,1001],{},[561,1002,1003,1006,1009],{},[564,1004,1005],{},"Wrapper",[564,1007,1008],{},"Axe",[564,1010,1011],{},"Effet",[574,1013,1014,1030,1046,1059,1072],{},[561,1015,1016,1021,1024],{},[579,1017,1018],{},[151,1019,1020],{},"optional(f)",[579,1022,1023],{},"shape",[579,1025,1026,1027],{},"peut être absent ; ",[151,1028,1029],{},"T | null",[561,1031,1032,1037,1039],{},[579,1033,1034],{},[151,1035,1036],{},"nullable(f)",[579,1038,1023],{},[579,1040,1041,1042,1045],{},"peut être ",[151,1043,1044],{},"null",", doit être présent",[561,1047,1048,1053,1056],{},[579,1049,1050],{},[151,1051,1052],{},"immutable(f)",[579,1054,1055],{},"lifecycle",[579,1057,1058],{},"écrivable à la création, interdit en mise à jour",[561,1060,1061,1066,1069],{},[579,1062,1063],{},[151,1064,1065],{},"readOnly(f)",[579,1067,1068],{},"boundary",[579,1070,1071],{},"ne traverse jamais vers l'intérieur — sortie seule",[561,1073,1074,1079,1081],{},[579,1075,1076],{},[151,1077,1078],{},"writeOnly(f)",[579,1080,1068],{},[579,1082,1083],{},"ne traverse jamais vers l'extérieur — entrée seule (mots de passe)",[147,1085,1086,1087,1090],{},"Les wrappers s'emboîtent : ",[151,1088,1089],{},"readOnly(optional(date()))"," est une date possédée par le\nserveur, possiblement absente.",[1092,1093,1094],"blockquote",{},[147,1095,1096,1099,1100,1102],{},[151,1097,1098],{},"Post.validate()"," ne voit que l'entrée courante et ne peut donc pas vérifier l'unicité\nparmi les lignes existantes. La base applique cette règle et renvoie alors une erreur de\ndriver plutôt qu'une erreur de champ. Un champ ",[151,1101,748],{}," est déjà unique.",[1104,1105,1107],"h3",{"id":1106},"les-deux-écritures-une-seule-forme","Les deux écritures, une seule forme",[147,1109,1110,1113,1114,1117],{},[151,1111,1112],{},"unique(slug)"," déclare une contrainte sur un champ ; ",[151,1115,1116],{},"unique: [['listId','docId']]"," en\ndéclare une sur plusieurs champs. Dans les deux cas, la représentation interne est une\nliste de groupes de champs.",[147,1119,1120,1121,1124],{},"L'axe ",[151,1122,1123],{},"role"," de chaque champ contient les contraintes dont il est membre :",[156,1126,1128],{"className":158,"code":1127,"language":160,"meta":161,"style":161},"slug.role.unique   \u002F\u002F [['slug']]                — l'ensemble d'un membre\nlistId.role.unique \u002F\u002F [['listId', 'docId']]     — la paire, portée par chaque membre\ndocId.role.unique  \u002F\u002F [['listId', 'docId']]\n",[151,1129,1130,1149,1165],{"__ignoreMap":161},[165,1131,1132,1135,1138,1140,1142,1145],{"class":167,"line":168},[165,1133,1134],{"class":179},"slug",[165,1136,1137],{"class":175},".",[165,1139,1123],{"class":179},[165,1141,1137],{"class":175},[165,1143,1144],{"class":179},"unique   ",[165,1146,1148],{"class":1147},"sutJx","\u002F\u002F [['slug']]                — l'ensemble d'un membre\n",[165,1150,1151,1153,1155,1157,1159,1162],{"class":167,"line":244},[165,1152,920],{"class":179},[165,1154,1137],{"class":175},[165,1156,1123],{"class":179},[165,1158,1137],{"class":175},[165,1160,1161],{"class":179},"unique ",[165,1163,1164],{"class":1147},"\u002F\u002F [['listId', 'docId']]     — la paire, portée par chaque membre\n",[165,1166,1167,1169,1171,1173,1175,1178],{"class":167,"line":264},[165,1168,929],{"class":179},[165,1170,1137],{"class":175},[165,1172,1123],{"class":179},[165,1174,1137],{"class":175},[165,1176,1177],{"class":179},"unique  ",[165,1179,1180],{"class":1147},"\u002F\u002F [['listId', 'docId']]\n",[147,1182,1183],{},"Un champ appartenant à deux contraintes porte deux entrées. Chaque membre contient le\ngroupe entier, ce qui permet à un consommateur dans un autre langage de reconstruire une\ncontrainte composée.",[147,1185,1186,1187,1190],{},"Une dérivation qui retire un membre retire le groupe : ",[151,1188,1189],{},"Post.pick('listId')"," ne conserve\npas la contrainte composée.",[547,1192,1194],{"id":1193},"les-quatre-axes","Les quatre axes",[147,1196,1197],{},"Chaque champ porte quatre axes orthogonaux — c'est le modèle que tous les adapters lisent :",[555,1199,1200,1212],{},[558,1201,1202],{},[561,1203,1204,1206,1209],{},[564,1205,1008],{},[564,1207,1208],{},"Question",[564,1210,1211],{},"Lu par",[574,1213,1214,1231,1255,1276],{},[561,1215,1216,1220,1228],{},[579,1217,1218],{},[793,1219,1023],{},[579,1221,1222,1223,1227],{},"quelles valeurs sont valides ? (le shape ",[1224,1225,1226],"em",{},"est"," du JSON Schema)",[579,1229,1230],{},"validation, formulaires, colonne SQL, scalar GraphQL",[561,1232,1233,1237,1252],{},[579,1234,1235],{},[793,1236,1123],{},[579,1238,1239,1240,594,1243,594,1246,594,1249,354],{},"quel rôle joue-t-il ? (",[151,1241,1242],{},"primary",[151,1244,1245],{},"ref",[151,1247,1248],{},"many",[151,1250,1251],{},"unique",[579,1253,1254],{},"DDL (PK\u002FFK, contraintes), relations, carte",[561,1256,1257,1261,1273],{},[579,1258,1259],{},[793,1260,1055],{},[579,1262,1263,1264,594,1267,594,1270,354],{},"qui l'écrit, quand ? (",[151,1265,1266],{},"auto",[151,1268,1269],{},"updated",[151,1271,1272],{},"immutable",[579,1274,1275],{},"réalisation ORM, détente du constructeur",[561,1277,1278,1282,1291],{},[579,1279,1280],{},[793,1281,1068],{},[579,1283,1284,1285,594,1288,354],{},"dans quel sens traverse-t-il l'API ? (",[151,1286,1287],{},"readOnly",[151,1289,1290],{},"writeOnly",[579,1292,1293,1294,1297,1298],{},"projections io ",[151,1295,1296],{},"inputFields"," \u002F ",[151,1299,1300],{},"outputFields",[147,1302,1303,1304,818,1306,1308,1309,1311,1312,1315,1316,1318,1319,1321],{},"La façade valide l'entrée client avec les axes ",[151,1305,1023],{},[151,1307,1068],{}," : écrire un champ\n",[151,1310,1287],{}," comme ",[151,1313,1314],{},"status"," est refusé. L'ORM applique ensuite l'axe ",[151,1317,1055],{},", par exemple\nen renseignant ",[151,1320,979],{}," et les valeurs par défaut.",[1092,1323,1324],{},[147,1325,1326,1327,1330,1331,1335],{},"La validation refuse les clés inconnues avec ",[151,1328,1329],{},"Unknown field"," au lieu de les retirer.\nUne entrée acceptée correspond donc exactement au contrat (voir\n",[1332,1333,72],"a",{"href":1334},"\u002Ffr\u002Fdocs\u002Fbusiness\u002Fhandlers#les-cl%C3%A9s-inconnues-sont-refus%C3%A9es",").",[547,1337,1339],{"id":1338},"entityvalidate","Entity.validate",[147,1341,1342,1343,1346],{},"Le moteur de validation est edge-safe (",[151,1344,1345],{},"@cfworker\u002Fjson-schema","). La même fonction peut\nêtre utilisée dans le navigateur et dans le handler :",[156,1348,1350],{"className":158,"code":1349,"language":160,"meta":161,"style":161},"Post.validate(input)\n\u002F\u002F → { success: true, data }                                    valide\n\u002F\u002F → { success: false, errors: [{ path: 'title', message }] }   invalide, par champ\n",[151,1351,1352,1365,1370],{"__ignoreMap":161},[165,1353,1354,1357,1359,1362],{"class":167,"line":168},[165,1355,1356],{"class":179},"Post",[165,1358,1137],{"class":175},[165,1360,1361],{"class":291},"validate",[165,1363,1364],{"class":179},"(input)\n",[165,1366,1367],{"class":167,"line":244},[165,1368,1369],{"class":1147},"\u002F\u002F → { success: true, data }                                    valide\n",[165,1371,1372],{"class":167,"line":264},[165,1373,1374],{"class":1147},"\u002F\u002F → { success: false, errors: [{ path: 'title', message }] }   invalide, par champ\n",[147,1376,1377,1380],{},[151,1378,1379],{},"new Post(data)"," construit une instance sans validation. Les champs générés ou automatiques\nsont optionnels pour le constructeur, mais restent présents dans le type résultant.",[147,1382,1383,1384,1386],{},"Suite : ",[1332,1385,55],{"href":56}," — dériver les contrats depuis le schéma.",[1388,1389,1390],"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 .skxfh, html code.shiki .skxfh{--shiki-light:#E53935;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .srdBf, html code.shiki .srdBf{--shiki-light:#F76D47;--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 .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}",{"title":161,"searchDepth":244,"depth":244,"links":1392},[1393,1396,1397],{"id":549,"depth":244,"text":550,"children":1394},[1395],{"id":1106,"depth":264,"text":1107},{"id":1193,"depth":244,"text":1194},{"id":1338,"depth":244,"text":1339},"Le vocabulaire des champs, les quatre axes, et Entity.validate.","md",{},{"title":51,"description":1398},"1lId9AmP0Iz5XS6bfmaltSWZvbs6kYV3EHqLzaNVZSs",1786637819747]