[{"data":1,"prerenderedAt":1452},["ShallowReactive",2],{"fougere:post.list:{}":3,"docs:\u002Fdocs\u002Fconcepts\u002Frepository":6,"docs-uses":1142,"docs-nav":1314},{"items":4,"hasMore":5},[],false,{"id":7,"title":8,"body":9,"description":1133,"extension":1134,"forms":1135,"kind":1136,"meta":1137,"navigation":206,"path":1138,"seo":1139,"stem":1140,"step":30,"uses":1135,"__hash__":1141},"docs\u002Fdocs\u002F1.concepts\u002F3.repository.md","Repository",{"type":10,"value":11,"toc":1127},"minimark",[12,16,153,156,284,295,300,310,337,346,384,537,541,548,556,575,578,582,592,857,860,889,897,1096,1107,1111,1123],[13,14,15],"p",{},"A repository holds the rows of one entity, and gives a name to the questions your domain asks of\nthem. \"The loud readings\" is not a gesture any storage knows; without a home, that query ends up\nspelled in the middle of the code that needs it. A repository is its home:",[17,18,23],"pre",{"className":19,"code":20,"language":21,"meta":22,"style":22},"language-ts shiki shiki-themes material-theme-lighter fougere-pastel material-theme-palenight","\u002F\u002F services\u002FReadingRepository.ts\nexport default class ReadingRepository extends Repository\u003CReading> {\n  loud(): Promise\u003CReading[]> {\n    return this.findAllBy({ loud: true });\n  }\n}\n","ts","",[24,25,26,35,72,97,141,147],"code",{"__ignoreMap":22},[27,28,31],"span",{"class":29,"line":30},"line",1,[27,32,34],{"class":33},"skXKP","\u002F\u002F services\u002FReadingRepository.ts\n",[27,36,38,42,45,49,53,56,59,63,66,69],{"class":29,"line":37},2,[27,39,41],{"class":40},"sK6XW","export",[27,43,44],{"class":40}," default",[27,46,48],{"class":47},"s76I7"," class",[27,50,52],{"class":51},"sBZYL"," ReadingRepository",[27,54,55],{"class":47}," extends",[27,57,58],{"class":51}," Repository",[27,60,62],{"class":61},"s15xx","\u003C",[27,64,65],{"class":51},"Reading",[27,67,68],{"class":61},">",[27,70,71],{"class":61}," {\n",[27,73,75,79,82,85,87,89,93,95],{"class":29,"line":74},3,[27,76,78],{"class":77},"shDkW","  loud",[27,80,81],{"class":61},"():",[27,83,84],{"class":51}," Promise",[27,86,62],{"class":61},[27,88,65],{"class":51},[27,90,92],{"class":91},"srlTG","[]",[27,94,68],{"class":61},[27,96,71],{"class":61},[27,98,100,103,107,110,114,118,121,125,128,132,135,138],{"class":29,"line":99},4,[27,101,102],{"class":40},"    return",[27,104,106],{"class":105},"sxG60"," this",[27,108,109],{"class":61},".",[27,111,113],{"class":112},"s4mR9","findAllBy",[27,115,117],{"class":116},"spAFX","(",[27,119,120],{"class":61},"{",[27,122,124],{"class":123},"sHtqg"," loud",[27,126,127],{"class":61},":",[27,129,131],{"class":130},"slmMI"," true",[27,133,134],{"class":61}," }",[27,136,137],{"class":116},")",[27,139,140],{"class":61},";\n",[27,142,144],{"class":29,"line":143},5,[27,145,146],{"class":61},"  }\n",[27,148,150],{"class":29,"line":149},6,[27,151,152],{"class":61},"}\n",[13,154,155],{},"The handler asks the question and never spells the storage:",[17,157,159],{"className":19,"code":158,"language":21,"meta":22,"style":22},"\u002F\u002F handlers\u002FReadingHandler.ts\nexport default class ReadingHandler {\n  constructor(private readings: ReadingRepository) {}\n\n  async loud() { return this.readings.loud(); }\n  async all()  { return this.readings.list(); }   \u002F\u002F every gesture of the rows is there too\n}\n",[24,160,161,166,179,202,208,245,279],{"__ignoreMap":22},[27,162,163],{"class":29,"line":30},[27,164,165],{"class":33},"\u002F\u002F handlers\u002FReadingHandler.ts\n",[27,167,168,170,172,174,177],{"class":29,"line":37},[27,169,41],{"class":40},[27,171,44],{"class":40},[27,173,48],{"class":47},[27,175,176],{"class":51}," ReadingHandler",[27,178,71],{"class":61},[27,180,181,184,186,189,193,195,197,199],{"class":29,"line":74},[27,182,183],{"class":47},"  constructor",[27,185,117],{"class":61},[27,187,188],{"class":47},"private",[27,190,192],{"class":191},"shDUQ"," readings",[27,194,127],{"class":61},[27,196,52],{"class":51},[27,198,137],{"class":61},[27,200,201],{"class":61}," {}\n",[27,203,204],{"class":29,"line":99},[27,205,207],{"emptyLinePlaceholder":206},true,"\n",[27,209,210,213,215,218,221,224,226,228,232,234,237,239,242],{"class":29,"line":143},[27,211,212],{"class":47},"  async",[27,214,124],{"class":77},[27,216,217],{"class":61},"()",[27,219,220],{"class":61}," {",[27,222,223],{"class":40}," return",[27,225,106],{"class":105},[27,227,109],{"class":61},[27,229,231],{"class":230},"sy9f4","readings",[27,233,109],{"class":61},[27,235,236],{"class":112},"loud",[27,238,217],{"class":116},[27,240,241],{"class":61},";",[27,243,244],{"class":61}," }\n",[27,246,247,249,252,254,257,259,261,263,265,267,270,272,274,276],{"class":29,"line":149},[27,248,212],{"class":47},[27,250,251],{"class":77}," all",[27,253,217],{"class":61},[27,255,256],{"class":61},"  {",[27,258,223],{"class":40},[27,260,106],{"class":105},[27,262,109],{"class":61},[27,264,231],{"class":230},[27,266,109],{"class":61},[27,268,269],{"class":112},"list",[27,271,217],{"class":116},[27,273,241],{"class":61},[27,275,134],{"class":61},[27,277,278],{"class":33},"   \u002F\u002F every gesture of the rows is there too\n",[27,280,282],{"class":29,"line":281},7,[27,283,152],{"class":61},[13,285,286,287,290,291,294],{},"A repository lives in ",[24,288,289],{},"services\u002F","; ",[24,292,293],{},"extends Repository\u003CReading>"," is what makes it one.",[296,297,299],"h2",{"id":298},"every-entity-has-one","Every entity has one",[13,301,302,303,306,307,309],{},"You do not have to write the file. A class asking for ",[24,304,305],{},"Repository\u003CReading>"," receives the rows of\n",[24,308,65],{},", guarded:",[17,311,313],{"className":19,"code":312,"language":21,"meta":22,"style":22},"constructor(private nodes: Repository\u003CNode>) {}\n",[24,314,315],{"__ignoreMap":22},[27,316,317,320,322,326,328,331,333,335],{"class":29,"line":30},[27,318,319],{"class":112},"constructor",[27,321,117],{"class":91},[27,323,325],{"class":324},"sPEhv","private nodes: Repository",[27,327,62],{"class":61},[27,329,330],{"class":324},"Node",[27,332,68],{"class":61},[27,334,137],{"class":91},[27,336,201],{"class":61},[13,338,339,340,342,343,345],{},"Write the class later and no call site changes: a class extending ",[24,341,305],{}," answers\n",[24,344,305],{},", whatever its name — and its own name too, which is where TypeScript sees its\nqueries. Two classes extending it refuse the boot, naming both.",[13,347,348,349,352,353,352,356,359,360,352,363,366,367,352,370,352,373,352,376,379,380,383],{},"What a repository can do: reads — ",[24,350,351],{},"list(options?)",", ",[24,354,355],{},"findById(id)",[24,357,358],{},"findBy(criteria)",",\n",[24,361,362],{},"findAllBy(criteria)",[24,364,365],{},"findByKeys(keys)","; writes — ",[24,368,369],{},"create",[24,371,372],{},"update",[24,374,375],{},"upsert",[24,377,378],{},"delete",".\n",[24,381,382],{},"output(view)"," gives the same rows, cut to a view's fields.",[17,385,387],{"className":19,"code":386,"language":21,"meta":22,"style":22},"await this.posts.findBy({ slug });                    \u002F\u002F the one row matching\nawait this.posts.findAllBy({ authorId: user.id });    \u002F\u002F every row matching\nawait this.posts.list({ where: { status: 'published' }, limit: 20, orderBy: 'createdAt' });\n",[24,388,389,423,463],{"__ignoreMap":22},[27,390,391,394,396,398,401,403,406,408,410,413,416,418,420],{"class":29,"line":30},[27,392,393],{"class":40},"await",[27,395,106],{"class":105},[27,397,109],{"class":61},[27,399,400],{"class":230},"posts",[27,402,109],{"class":61},[27,404,405],{"class":112},"findBy",[27,407,117],{"class":91},[27,409,120],{"class":61},[27,411,412],{"class":324}," slug ",[27,414,415],{"class":61},"}",[27,417,137],{"class":91},[27,419,241],{"class":61},[27,421,422],{"class":33},"                    \u002F\u002F the one row matching\n",[27,424,425,427,429,431,433,435,437,439,441,444,446,449,451,454,456,458,460],{"class":29,"line":37},[27,426,393],{"class":40},[27,428,106],{"class":105},[27,430,109],{"class":61},[27,432,400],{"class":230},[27,434,109],{"class":61},[27,436,113],{"class":112},[27,438,117],{"class":91},[27,440,120],{"class":61},[27,442,443],{"class":123}," authorId",[27,445,127],{"class":61},[27,447,448],{"class":324}," user",[27,450,109],{"class":61},[27,452,453],{"class":230},"id",[27,455,134],{"class":61},[27,457,137],{"class":91},[27,459,241],{"class":61},[27,461,462],{"class":33},"    \u002F\u002F every row matching\n",[27,464,465,467,469,471,473,475,477,479,481,484,486,488,491,493,497,501,504,507,510,512,516,519,522,524,526,529,531,533,535],{"class":29,"line":74},[27,466,393],{"class":40},[27,468,106],{"class":105},[27,470,109],{"class":61},[27,472,400],{"class":230},[27,474,109],{"class":61},[27,476,269],{"class":112},[27,478,117],{"class":91},[27,480,120],{"class":61},[27,482,483],{"class":123}," where",[27,485,127],{"class":61},[27,487,220],{"class":61},[27,489,490],{"class":123}," status",[27,492,127],{"class":61},[27,494,496],{"class":495},"sDDC1"," '",[27,498,500],{"class":499},"sN-8n","published",[27,502,503],{"class":495},"'",[27,505,506],{"class":61}," },",[27,508,509],{"class":123}," limit",[27,511,127],{"class":61},[27,513,515],{"class":514},"s3dPA"," 20",[27,517,518],{"class":61},",",[27,520,521],{"class":123}," orderBy",[27,523,127],{"class":61},[27,525,496],{"class":495},[27,527,528],{"class":499},"createdAt",[27,530,503],{"class":495},[27,532,134],{"class":61},[27,534,137],{"class":91},[27,536,140],{"class":61},[296,538,540],{"id":539},"one-way-to-the-rows","One way to the rows",[13,542,543,544,547],{},"Underneath is ",[24,545,546],{},"Storage\u003CPost>",", the gestures Post's rows answer in whichever engine holds them. A\nhandler, a presenter or a collector never asks for it; the boot refuses it and points at the\nrepository:",[17,549,554],{"className":550,"code":552,"language":553},[551],"language-text","[storage-outside-repository] PostHandler asks for Storage\u003CPost>. Ask for the repository instead:\n  constructor(private post: Repository\u003CPost>) {}.\n","text",[24,555,552],{"__ignoreMap":22},[13,557,558,559,562,563,566,567,574],{},"One way in means that the day an entity joins an aggregate (below), no call site moves. The one\nclass that may name ",[24,560,561],{},"Storage\u003CE>"," is a class built on ",[24,564,565],{},"E"," — a repository, a\n",[568,569,571],"a",{"href":570},"\u002Fdocs\u002Fdata\u002Fmirror",[24,572,573],{},"Mirror"," — because it holds those rows.",[13,576,577],{},"Writes through a repository are still checked: a value the entity forbids is refused whoever wrote it.",[296,579,581],{"id":580},"two-entities-one-owner","Two entities, one owner",[13,583,584,587,588,591],{},[24,585,586],{},"balance"," and the sum of a ledger's ",[24,589,590],{},"amount"," are one fact, and no single row can say so: debit 100,\njournal 50, and the database takes both. What makes the rule hold is having one way in. Name both\nentities, and the repository becomes their only owner:",[17,593,595],{"className":19,"code":594,"language":21,"meta":22,"style":22},"\u002F\u002F services\u002FAccountRepository.ts\nexport default class AccountRepository extends Repository\u003CAccount, Ledger> {\n  async withdraw(id: string, amount: number) {\n    const [accounts, ledger] = this.storages;\n    await accounts.update(id, (account) => {\n      if (account.balance \u003C amount) throw new Error('insufficient funds');\n\n      return { balance: account.balance - amount };\n    });\n    await ledger.create({ account: id, amount: -amount });\n  }\n}\n",[24,596,597,602,631,661,692,724,767,771,799,809,847,852],{"__ignoreMap":22},[27,598,599],{"class":29,"line":30},[27,600,601],{"class":33},"\u002F\u002F services\u002FAccountRepository.ts\n",[27,603,604,606,608,610,613,615,617,619,622,624,627,629],{"class":29,"line":37},[27,605,41],{"class":40},[27,607,44],{"class":40},[27,609,48],{"class":47},[27,611,612],{"class":51}," AccountRepository",[27,614,55],{"class":47},[27,616,58],{"class":51},[27,618,62],{"class":61},[27,620,621],{"class":51},"Account",[27,623,518],{"class":61},[27,625,626],{"class":51}," Ledger",[27,628,68],{"class":61},[27,630,71],{"class":61},[27,632,633,635,638,640,642,644,647,649,652,654,657,659],{"class":29,"line":74},[27,634,212],{"class":47},[27,636,637],{"class":77}," withdraw",[27,639,117],{"class":61},[27,641,453],{"class":191},[27,643,127],{"class":61},[27,645,646],{"class":51}," string",[27,648,518],{"class":61},[27,650,651],{"class":191}," amount",[27,653,127],{"class":61},[27,655,656],{"class":51}," number",[27,658,137],{"class":61},[27,660,71],{"class":61},[27,662,663,666,669,672,674,677,680,683,685,687,690],{"class":29,"line":99},[27,664,665],{"class":47},"    const",[27,667,668],{"class":61}," [",[27,670,671],{"class":324},"accounts",[27,673,518],{"class":61},[27,675,676],{"class":324}," ledger",[27,678,679],{"class":61},"]",[27,681,682],{"class":61}," =",[27,684,106],{"class":105},[27,686,109],{"class":61},[27,688,689],{"class":230},"storages",[27,691,140],{"class":61},[27,693,694,697,700,702,704,706,708,710,713,716,718,722],{"class":29,"line":143},[27,695,696],{"class":40},"    await",[27,698,699],{"class":324}," accounts",[27,701,109],{"class":61},[27,703,372],{"class":112},[27,705,117],{"class":116},[27,707,453],{"class":324},[27,709,518],{"class":61},[27,711,712],{"class":61}," (",[27,714,715],{"class":191},"account",[27,717,137],{"class":61},[27,719,721],{"class":720},"scTuO"," =>",[27,723,71],{"class":61},[27,725,726,729,731,733,735,737,740,742,744,747,750,754,756,758,761,763,765],{"class":29,"line":149},[27,727,728],{"class":40},"      if",[27,730,712],{"class":116},[27,732,715],{"class":324},[27,734,109],{"class":61},[27,736,586],{"class":230},[27,738,739],{"class":61}," \u003C",[27,741,651],{"class":324},[27,743,137],{"class":116},[27,745,746],{"class":40}," throw",[27,748,749],{"class":61}," new",[27,751,753],{"class":752},"sgjsB"," Error",[27,755,117],{"class":116},[27,757,503],{"class":495},[27,759,760],{"class":499},"insufficient funds",[27,762,503],{"class":495},[27,764,137],{"class":116},[27,766,140],{"class":61},[27,768,769],{"class":29,"line":281},[27,770,207],{"emptyLinePlaceholder":206},[27,772,774,777,779,782,784,787,789,791,794,796],{"class":29,"line":773},8,[27,775,776],{"class":40},"      return",[27,778,220],{"class":61},[27,780,781],{"class":123}," balance",[27,783,127],{"class":61},[27,785,786],{"class":324}," account",[27,788,109],{"class":61},[27,790,586],{"class":230},[27,792,793],{"class":61}," -",[27,795,651],{"class":324},[27,797,798],{"class":61}," };\n",[27,800,802,805,807],{"class":29,"line":801},9,[27,803,804],{"class":61},"    }",[27,806,137],{"class":116},[27,808,140],{"class":61},[27,810,812,814,816,818,820,822,824,826,828,831,833,835,837,839,841,843,845],{"class":29,"line":811},10,[27,813,696],{"class":40},[27,815,676],{"class":324},[27,817,109],{"class":61},[27,819,369],{"class":112},[27,821,117],{"class":116},[27,823,120],{"class":61},[27,825,786],{"class":123},[27,827,127],{"class":61},[27,829,830],{"class":324}," id",[27,832,518],{"class":61},[27,834,651],{"class":123},[27,836,127],{"class":61},[27,838,793],{"class":61},[27,840,590],{"class":324},[27,842,134],{"class":61},[27,844,137],{"class":116},[27,846,140],{"class":61},[27,848,850],{"class":29,"line":849},11,[27,851,146],{"class":61},[27,853,855],{"class":29,"line":854},12,[27,856,152],{"class":61},[13,858,859],{},"The rule is ordinary TypeScript in the method that writes. The number of entities is the whole\ndeclaration: one is a place to name queries, two to four make an owner. From two on:",[861,862,863,874,883],"ul",{},[864,865,866,870,871,241],"li",{},[867,868,869],"strong",{},"no default repository"," exists for a member — nothing can ask for ",[24,872,873],{},"Repository\u003CLedger>",[864,875,876,879,880,882],{},[867,877,878],{},"no gesture is forwarded"," — which table would ",[24,881,369],{}," write to? — so an owned entity has no\nautomatic CRUD, and the boot says so rather than failing at the first request;",[864,884,885,888],{},[867,886,887],{},"two owners cannot claim one entity"," — the boot refuses both, by name.",[13,890,891,892,896],{},"An owner says the rules of these entities hold together. That their writes land together is a\nsecond statement, a ",[568,893,895],{"href":894},"\u002Fdocs\u002Fdata\u002Ftogether","frame",", asked for like anywhere else:",[17,898,900],{"className":19,"code":899,"language":21,"meta":22,"style":22},"export default class AccountRepository extends Repository\u003CAccount, Ledger> {\n  constructor(\n    accounts: Storage\u003CAccount>,\n    ledger: Storage\u003CLedger>,\n    private frame: Together\u003C[Account, Ledger]>,\n  ) { super(); }\n\n  async withdraw(id: string, amount: number) {\n    return this.frame.run(async ([accounts, ledger]) => { \u002F* both, or neither *\u002F });\n  }\n}\n",[24,901,902,928,935,952,968,996,1013,1017,1043,1088,1092],{"__ignoreMap":22},[27,903,904,906,908,910,912,914,916,918,920,922,924,926],{"class":29,"line":30},[27,905,41],{"class":40},[27,907,44],{"class":40},[27,909,48],{"class":47},[27,911,612],{"class":51},[27,913,55],{"class":47},[27,915,58],{"class":51},[27,917,62],{"class":61},[27,919,621],{"class":51},[27,921,518],{"class":61},[27,923,626],{"class":51},[27,925,68],{"class":61},[27,927,71],{"class":61},[27,929,930,932],{"class":29,"line":37},[27,931,183],{"class":47},[27,933,934],{"class":61},"(\n",[27,936,937,940,942,945,947,949],{"class":29,"line":74},[27,938,939],{"class":191},"    accounts",[27,941,127],{"class":61},[27,943,944],{"class":51}," Storage",[27,946,62],{"class":61},[27,948,621],{"class":51},[27,950,951],{"class":61},">,\n",[27,953,954,957,959,961,963,966],{"class":29,"line":99},[27,955,956],{"class":191},"    ledger",[27,958,127],{"class":61},[27,960,944],{"class":51},[27,962,62],{"class":61},[27,964,965],{"class":51},"Ledger",[27,967,951],{"class":61},[27,969,970,973,976,978,981,983,986,988,990,992,994],{"class":29,"line":143},[27,971,972],{"class":47},"    private",[27,974,975],{"class":191}," frame",[27,977,127],{"class":61},[27,979,980],{"class":51}," Together",[27,982,62],{"class":61},[27,984,985],{"class":91},"[",[27,987,621],{"class":51},[27,989,518],{"class":61},[27,991,626],{"class":51},[27,993,679],{"class":91},[27,995,951],{"class":61},[27,997,998,1001,1003,1007,1009,1011],{"class":29,"line":149},[27,999,1000],{"class":61},"  )",[27,1002,220],{"class":61},[27,1004,1006],{"class":1005},"sTljH"," super",[27,1008,217],{"class":116},[27,1010,241],{"class":61},[27,1012,244],{"class":61},[27,1014,1015],{"class":29,"line":281},[27,1016,207],{"emptyLinePlaceholder":206},[27,1018,1019,1021,1023,1025,1027,1029,1031,1033,1035,1037,1039,1041],{"class":29,"line":773},[27,1020,212],{"class":47},[27,1022,637],{"class":77},[27,1024,117],{"class":61},[27,1026,453],{"class":191},[27,1028,127],{"class":61},[27,1030,646],{"class":51},[27,1032,518],{"class":61},[27,1034,651],{"class":191},[27,1036,127],{"class":61},[27,1038,656],{"class":51},[27,1040,137],{"class":61},[27,1042,71],{"class":61},[27,1044,1045,1047,1049,1051,1053,1055,1058,1060,1063,1066,1068,1070,1072,1075,1077,1079,1082,1084,1086],{"class":29,"line":801},[27,1046,102],{"class":40},[27,1048,106],{"class":105},[27,1050,109],{"class":61},[27,1052,895],{"class":230},[27,1054,109],{"class":61},[27,1056,1057],{"class":112},"run",[27,1059,117],{"class":116},[27,1061,1062],{"class":47},"async",[27,1064,1065],{"class":61}," ([",[27,1067,671],{"class":191},[27,1069,518],{"class":61},[27,1071,676],{"class":191},[27,1073,1074],{"class":61},"])",[27,1076,721],{"class":720},[27,1078,220],{"class":61},[27,1080,1081],{"class":33}," \u002F* both, or neither *\u002F",[27,1083,134],{"class":61},[27,1085,137],{"class":116},[27,1087,140],{"class":61},[27,1089,1090],{"class":29,"line":811},[27,1091,146],{"class":61},[27,1093,1094],{"class":29,"line":849},[27,1095,152],{"class":61},[13,1097,1098,1099,1102,1103,1106],{},"A ",[24,1100,1101],{},"Together"," naming an owned entity is refused anywhere but in its owner (",[24,1104,1105],{},"aggregate-storage-reached",").",[296,1108,1110],{"id":1109},"not-a-facade","Not a facade",[13,1112,1113,1114,1117,1118,1122],{},"Nothing outside the process can call a repository, which is why it may hold anything the domain\nneeds. It is also why rules about ",[867,1115,1116],{},"who may act"," belong in the ",[568,1119,1121],{"href":1120},"\u002Fdocs\u002Fconcepts\u002Fhandler","handler",",\nthe one place a call cannot go around. A repository holds the other kind: what the data may be.",[1124,1125,1126],"style",{},"html pre.shiki code .skXKP, html code.shiki .skXKP{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#7D8C80;--shiki-default-font-style:inherit;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .sK6XW, html code.shiki .sK6XW{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#8FCF86;--shiki-default-font-style:inherit;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .s76I7, html code.shiki .s76I7{--shiki-light:#9C3EDA;--shiki-default:#8FCF86;--shiki-dark:#C792EA}html pre.shiki code .sBZYL, html code.shiki .sBZYL{--shiki-light:#E2931D;--shiki-default:#EFCD8F;--shiki-dark:#FFCB6B}html pre.shiki code .s15xx, html code.shiki .s15xx{--shiki-light:#39ADB5;--shiki-default:#A3B0A5;--shiki-dark:#89DDFF}html pre.shiki code .shDkW, html code.shiki .shDkW{--shiki-light:#E53935;--shiki-default:#C9B6EA;--shiki-dark:#F07178}html pre.shiki code .srlTG, html code.shiki .srlTG{--shiki-light:#90A4AE;--shiki-default:#A3B0A5;--shiki-dark:#BABED8}html pre.shiki code .sxG60, html code.shiki .sxG60{--shiki-light:#39ADB5;--shiki-light-font-style:inherit;--shiki-default:#8FCF86;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:inherit}html pre.shiki code .s4mR9, html code.shiki .s4mR9{--shiki-light:#6182B8;--shiki-default:#C9B6EA;--shiki-dark:#82AAFF}html pre.shiki code .spAFX, html code.shiki .spAFX{--shiki-light:#E53935;--shiki-default:#A3B0A5;--shiki-dark:#F07178}html pre.shiki code .sHtqg, html code.shiki .sHtqg{--shiki-light:#E53935;--shiki-default:#93CFC0;--shiki-dark:#F07178}html pre.shiki code .slmMI, html code.shiki .slmMI{--shiki-light:#FF5370;--shiki-default:#EE9F6B;--shiki-dark:#FF9CAC}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 .shDUQ, html code.shiki .shDUQ{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#DDE5DA;--shiki-default-font-style:inherit;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}html pre.shiki code .sy9f4, html code.shiki .sy9f4{--shiki-light:#90A4AE;--shiki-default:#93CFC0;--shiki-dark:#BABED8}html pre.shiki code .sPEhv, html code.shiki .sPEhv{--shiki-light:#90A4AE;--shiki-default:#DDE5DA;--shiki-dark:#BABED8}html pre.shiki code .sDDC1, html code.shiki .sDDC1{--shiki-light:#39ADB5;--shiki-default:#EE9F6B;--shiki-dark:#89DDFF}html pre.shiki code .sN-8n, html code.shiki .sN-8n{--shiki-light:#91B859;--shiki-default:#EE9F6B;--shiki-dark:#C3E88D}html pre.shiki code .s3dPA, html code.shiki .s3dPA{--shiki-light:#F76D47;--shiki-default:#EE9F6B;--shiki-dark:#F78C6C}html pre.shiki code .scTuO, html code.shiki .scTuO{--shiki-light:#9C3EDA;--shiki-default:#A3B0A5;--shiki-dark:#C792EA}html pre.shiki code .sgjsB, html code.shiki .sgjsB{--shiki-light:#6182B8;--shiki-default:#EFCD8F;--shiki-dark:#82AAFF}html pre.shiki code .sTljH, html code.shiki .sTljH{--shiki-light:#90A4AE;--shiki-light-font-style:inherit;--shiki-default:#8FCF86;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:inherit}",{"title":22,"searchDepth":37,"depth":37,"links":1128},[1129,1130,1131,1132],{"id":298,"depth":37,"text":299},{"id":539,"depth":37,"text":540},{"id":580,"depth":37,"text":581},{"id":1109,"depth":37,"text":1110},"The rows of an entity, and the queries that deserve a name.","md",null,"concept",{},"\u002Fdocs\u002Fconcepts\u002Frepository",{"title":8,"description":1133},"docs\u002F1.concepts\u002F3.repository","4ccLE-YkIcCwESd8KBGZsv8s3T5dBlNxpWTHy4Y8CJ4",[1143,1146,1148,1149,1152,1155,1158,1161,1164,1170,1175,1180,1184,1188,1192,1196,1200,1204,1207,1211,1216,1220,1225,1229,1233,1237,1241,1245,1249,1253,1257,1261,1265,1269,1273,1277,1281,1284,1287,1290,1293,1296,1299,1302,1305,1308,1311],{"path":1144,"title":1145,"uses":1135},"\u002Fdocs\u002Fconcepts\u002Fentity","Entity",{"path":1120,"title":1147,"uses":1135},"Handler",{"path":1138,"title":8,"uses":1135},{"path":1150,"title":1151,"uses":1135},"\u002Fdocs\u002Fconcepts\u002Ffrond","Frond",{"path":1153,"title":1154,"uses":1135},"\u002Fdocs\u002Fconcepts\u002Ffacade","Facade",{"path":1156,"title":1157,"uses":1135},"\u002Fdocs\u002Fconcepts\u002Ffact","Fact",{"path":1159,"title":1160,"uses":1135},"\u002Fdocs\u002Fconcepts\u002Fport","Port",{"path":1162,"title":1163,"uses":1135},"\u002Fdocs\u002Fconcepts\u002Fconfiguration","Configuration",{"path":1165,"title":1166,"uses":1167},"\u002Fdocs\u002Faccess\u002Fauthentication","Authentication",[1168,1169],"port","frond",{"path":1171,"title":1172,"uses":1173},"\u002Fdocs\u002Faccess\u002Fstate","Keep a caller's state",[1174,1121],"configuration",{"path":1176,"title":1177,"uses":1178},"\u002Fdocs\u002Fdata\u002Fsql","SQLite or Postgres",[1179,1174],"entity",{"path":1181,"title":1182,"uses":1183},"\u002Fdocs\u002Fdata\u002Fseveral-databases","Several databases",[1174,1179],{"path":1185,"title":1186,"uses":1187},"\u002Fdocs\u002Fdata\u002Fcomputed-field","A computed field",[1179,1168],{"path":1189,"title":1190,"uses":1191},"\u002Fdocs\u002Fdata\u002Fevolve","Evolve a schema",[1179],{"path":1193,"title":1194,"uses":1195},"\u002Fdocs\u002Fdata\u002Fseeds","Seed data",[1179],{"path":1197,"title":1198,"uses":1199},"\u002Fdocs\u002Fdata\u002Fvalues","Read settings and secrets",[1179,1174],{"path":570,"title":1201,"uses":1202},"Mirror a source you cannot query",[1203],"repository",{"path":894,"title":1205,"uses":1206},"Two writes as one",[1203],{"path":1208,"title":1209,"uses":1210},"\u002Fdocs\u002Fbehaviour\u002Faround-every-call","Around every call",[1168,1169],{"path":1212,"title":1213,"uses":1214},"\u002Fdocs\u002Fbehaviour\u002Ffinish-a-fact","Finish a fact",[1215],"fact",{"path":1217,"title":1218,"uses":1219},"\u002Fdocs\u002Fserve\u002Frest-graphql","REST, OpenAPI, GraphQL",[1121,1174],{"path":1221,"title":1222,"uses":1223},"\u002Fdocs\u002Fserve\u002Fpages","Pages: queries and commands",[1121,1224],"facade",{"path":1226,"title":1227,"uses":1228},"\u002Fdocs\u002Fserve\u002Fforms","A form",[1179],{"path":1230,"title":1231,"uses":1232},"\u002Fdocs\u002Fserve\u002Fadmin","An admin panel",[1121],{"path":1234,"title":1235,"uses":1236},"\u002Fdocs\u002Frun\u002Fdeploy","Deploy a split",[1174,1169],{"path":1238,"title":1239,"uses":1240},"\u002Fdocs\u002Frun\u002Fsecure","Secure calls between processes",[1174,1169],{"path":1242,"title":1243,"uses":1244},"\u002Fdocs\u002Frun\u002Flifecycle","Reload and shut down",[1174],{"path":1246,"title":1247,"uses":1248},"\u002Fdocs\u002Frun\u002Fobserve","Observe",[1174,1121],{"path":1250,"title":1251,"uses":1252},"\u002Fdocs\u002Frun\u002Fdev-panel","The dev panel",[1121],{"path":1254,"title":1255,"uses":1256},"\u002Fdocs\u002Frun\u002Ftest","Test",[1179,1168],{"path":1258,"title":1259,"uses":1260},"\u002Fdocs\u002Fadopt\u002Fnew-project","Start a project",[1169,1174],{"path":1262,"title":1263,"uses":1264},"\u002Fdocs\u002Fadopt\u002Fexisting-app","Add Fougere to an existing app",[1169,1174],{"path":1266,"title":1267,"uses":1268},"\u002Fdocs\u002Fadopt\u002Fbring-your-schema","Bring your schema",[1179],{"path":1270,"title":1271,"uses":1272},"\u002Fdocs\u002Fadopt\u002Fhosts","Pick a host",[1174],{"path":1274,"title":1275,"uses":1276},"\u002Fdocs\u002Fadopt\u002Fanother-repository","A frond from another repository",[1224,1169],{"path":1278,"title":1279,"uses":1280},"\u002Fdocs\u002Fadopt\u002Fdemos","Demos",[],{"path":1282,"title":1283,"uses":1135},"\u002Fdocs\u002Fextending\u002Fscan","How the scan reads a project",{"path":1285,"title":1286,"uses":1135},"\u002Fdocs\u002Fextending\u002Fwithout-compiler","Boot without the compiler",{"path":1288,"title":1289,"uses":1135},"\u002Fdocs\u002Fextending\u002Fboot","The boot, step by step",{"path":1291,"title":1292,"uses":1135},"\u002Fdocs\u002Fextending\u002Fcard-and-wire","The card and the wire",{"path":1294,"title":1295,"uses":1135},"\u002Fdocs\u002Fextending\u002Fextension-points","Registries and extension points",{"path":1297,"title":1298,"uses":1135},"\u002Fdocs\u002Fextending\u002Fvocabulary","Teach a word",{"path":1300,"title":1301,"uses":1135},"\u002Fdocs\u002Fextending\u002Fextensions","Run code at boot and shutdown",{"path":1303,"title":1304,"uses":1135},"\u002Fdocs\u002Fextending\u002Fsource-adapter","Write a source adapter",{"path":1306,"title":1307,"uses":1135},"\u002Fdocs\u002Fextending\u002Fsurface","Write a surface",{"path":1309,"title":1310,"uses":1135},"\u002Fdocs\u002Fextending\u002Fforeign-frond","A frond in another language",{"path":1312,"title":1313,"uses":1135},"\u002Fdocs","What is Fougere",[1315],{"title":1316,"path":1312,"stem":1317,"children":1318,"page":-1},"Docs","docs",[1319,1321,1341,1350,1371,1380,1393,1410,1427],{"title":1313,"path":1312,"stem":1320},"docs\u002Findex",{"title":1322,"path":1323,"stem":1324,"children":1325,"page":5},"Concepts","\u002Fdocs\u002Fconcepts","docs\u002F1.concepts",[1326,1328,1330,1331,1333,1335,1337,1339],{"title":1145,"path":1144,"stem":1327},"docs\u002F1.concepts\u002F1.entity",{"title":1147,"path":1120,"stem":1329},"docs\u002F1.concepts\u002F2.handler",{"title":8,"path":1138,"stem":1140},{"title":1151,"path":1150,"stem":1332},"docs\u002F1.concepts\u002F4.frond",{"title":1154,"path":1153,"stem":1334},"docs\u002F1.concepts\u002F5.facade",{"title":1157,"path":1156,"stem":1336},"docs\u002F1.concepts\u002F6.fact",{"title":1160,"path":1159,"stem":1338},"docs\u002F1.concepts\u002F7.port",{"title":1163,"path":1162,"stem":1340},"docs\u002F1.concepts\u002F8.configuration",{"title":1342,"path":1343,"stem":1344,"children":1345,"page":5},"Access","\u002Fdocs\u002Faccess","docs\u002F2.access",[1346,1348],{"title":1166,"path":1165,"stem":1347},"docs\u002F2.access\u002F1.authentication",{"title":1172,"path":1171,"stem":1349},"docs\u002F2.access\u002F2.state",{"title":1351,"path":1352,"stem":1353,"children":1354,"page":5},"Data","\u002Fdocs\u002Fdata","docs\u002F3.data",[1355,1357,1359,1361,1363,1365,1367,1369],{"title":1177,"path":1176,"stem":1356},"docs\u002F3.data\u002F1.sql",{"title":1182,"path":1181,"stem":1358},"docs\u002F3.data\u002F2.several-databases",{"title":1186,"path":1185,"stem":1360},"docs\u002F3.data\u002F3.computed-field",{"title":1190,"path":1189,"stem":1362},"docs\u002F3.data\u002F4.evolve",{"title":1194,"path":1193,"stem":1364},"docs\u002F3.data\u002F5.seeds",{"title":1198,"path":1197,"stem":1366},"docs\u002F3.data\u002F6.values",{"title":1201,"path":570,"stem":1368},"docs\u002F3.data\u002F7.mirror",{"title":1205,"path":894,"stem":1370},"docs\u002F3.data\u002F8.together",{"title":1372,"path":1373,"stem":1374,"children":1375,"page":5},"Behaviour","\u002Fdocs\u002Fbehaviour","docs\u002F4.behaviour",[1376,1378],{"title":1209,"path":1208,"stem":1377},"docs\u002F4.behaviour\u002F1.around-every-call",{"title":1213,"path":1212,"stem":1379},"docs\u002F4.behaviour\u002F2.finish-a-fact",{"title":1381,"path":1382,"stem":1383,"children":1384,"page":5},"Serve","\u002Fdocs\u002Fserve","docs\u002F5.serve",[1385,1387,1389,1391],{"title":1218,"path":1217,"stem":1386},"docs\u002F5.serve\u002F1.rest-graphql",{"title":1222,"path":1221,"stem":1388},"docs\u002F5.serve\u002F2.pages",{"title":1227,"path":1226,"stem":1390},"docs\u002F5.serve\u002F3.forms",{"title":1231,"path":1230,"stem":1392},"docs\u002F5.serve\u002F4.admin",{"title":1394,"path":1395,"stem":1396,"children":1397,"page":5},"Run","\u002Fdocs\u002Frun","docs\u002F6.run",[1398,1400,1402,1404,1406,1408],{"title":1235,"path":1234,"stem":1399},"docs\u002F6.run\u002F1.deploy",{"title":1239,"path":1238,"stem":1401},"docs\u002F6.run\u002F2.secure",{"title":1243,"path":1242,"stem":1403},"docs\u002F6.run\u002F3.lifecycle",{"title":1247,"path":1246,"stem":1405},"docs\u002F6.run\u002F4.observe",{"title":1251,"path":1250,"stem":1407},"docs\u002F6.run\u002F5.dev-panel",{"title":1255,"path":1254,"stem":1409},"docs\u002F6.run\u002F6.test",{"title":1411,"path":1412,"stem":1413,"children":1414,"page":5},"Adopt","\u002Fdocs\u002Fadopt","docs\u002F7.adopt",[1415,1417,1419,1421,1423,1425],{"title":1259,"path":1258,"stem":1416},"docs\u002F7.adopt\u002F1.new-project",{"title":1263,"path":1262,"stem":1418},"docs\u002F7.adopt\u002F2.existing-app",{"title":1267,"path":1266,"stem":1420},"docs\u002F7.adopt\u002F3.bring-your-schema",{"title":1271,"path":1270,"stem":1422},"docs\u002F7.adopt\u002F4.hosts",{"title":1275,"path":1274,"stem":1424},"docs\u002F7.adopt\u002F5.another-repository",{"title":1279,"path":1278,"stem":1426},"docs\u002F7.adopt\u002F6.demos",{"title":1428,"path":1429,"stem":1430,"children":1431,"page":5},"Extending","\u002Fdocs\u002Fextending","docs\u002F8.extending",[1432,1434,1436,1438,1440,1442,1444,1446,1448,1450],{"title":1283,"path":1282,"stem":1433},"docs\u002F8.extending\u002F1.scan",{"title":1286,"path":1285,"stem":1435},"docs\u002F8.extending\u002F10.without-compiler",{"title":1289,"path":1288,"stem":1437},"docs\u002F8.extending\u002F2.boot",{"title":1292,"path":1291,"stem":1439},"docs\u002F8.extending\u002F3.card-and-wire",{"title":1295,"path":1294,"stem":1441},"docs\u002F8.extending\u002F4.extension-points",{"title":1298,"path":1297,"stem":1443},"docs\u002F8.extending\u002F5.vocabulary",{"title":1301,"path":1300,"stem":1445},"docs\u002F8.extending\u002F6.extensions",{"title":1304,"path":1303,"stem":1447},"docs\u002F8.extending\u002F7.source-adapter",{"title":1307,"path":1306,"stem":1449},"docs\u002F8.extending\u002F8.surface",{"title":1310,"path":1309,"stem":1451},"docs\u002F8.extending\u002F9.foreign-frond",1794396613913]