[{"data":1,"prerenderedAt":1388},["ShallowReactive",2],{"fougere:post.list:{}":3,"docs:\u002Fdocs\u002Fdata\u002Ftogether":6,"docs-uses":1081,"docs-nav":1250},{"items":4,"hasMore":5},[],false,{"id":7,"title":8,"body":9,"description":1069,"extension":1070,"forms":1071,"kind":1073,"meta":1074,"navigation":114,"path":1075,"seo":1076,"stem":1077,"step":1078,"uses":1079,"__hash__":1080},"docs\u002Fdocs\u002F3.data\u002F8.together.md","Two writes as one",{"type":10,"value":11,"toc":1062},"minimark",[12,16,29,328,339,349,354,360,501,508,511,591,594,604,608,624,632,638,644,716,719,734,753,757,782,926,939,942,946,949,1000,1003,1009,1023,1041,1045,1052,1058],[13,14,15],"p",{},"Two writes that must both land, or neither: a debit and its ledger line, an order and its stock.",[13,17,18,19,23,24,28],{},"Each write through a repository is one statement, and one statement is atomic in every engine.\n",[20,21,22],"code",{},"Together"," makes a ",[25,26,27],"strong",{},"block"," atomic: what the callback did happens entirely, or not at all.",[30,31,36],"pre",{"className":32,"code":33,"language":34,"meta":35,"style":35},"language-ts shiki shiki-themes material-theme-lighter fougere-pastel material-theme-palenight","export default class TransferHandler {\n  constructor(private together: Together\u003C[Account, Ledger]>) {}\n\n  async move(from: string, to: string, amount: number) {\n    return this.together.run(async ([accounts, ledger]) => {\n      await accounts.update(from, (account) => ({ balance: account.balance - amount }));\n      await ledger.create({ from, to, amount });\n    });\n  }\n}\n","ts","",[20,37,38,62,109,116,160,209,273,306,316,322],{"__ignoreMap":35},[39,40,43,47,50,54,58],"span",{"class":41,"line":42},"line",1,[39,44,46],{"class":45},"sK6XW","export",[39,48,49],{"class":45}," default",[39,51,53],{"class":52},"s76I7"," class",[39,55,57],{"class":56},"sBZYL"," TransferHandler",[39,59,61],{"class":60},"s15xx"," {\n",[39,63,65,68,71,74,78,81,84,87,91,94,97,100,103,106],{"class":41,"line":64},2,[39,66,67],{"class":52},"  constructor",[39,69,70],{"class":60},"(",[39,72,73],{"class":52},"private",[39,75,77],{"class":76},"shDUQ"," together",[39,79,80],{"class":60},":",[39,82,83],{"class":56}," Together",[39,85,86],{"class":60},"\u003C",[39,88,90],{"class":89},"srlTG","[",[39,92,93],{"class":56},"Account",[39,95,96],{"class":60},",",[39,98,99],{"class":56}," Ledger",[39,101,102],{"class":89},"]",[39,104,105],{"class":60},">)",[39,107,108],{"class":60}," {}\n",[39,110,112],{"class":41,"line":111},3,[39,113,115],{"emptyLinePlaceholder":114},true,"\n",[39,117,119,122,126,128,131,133,136,138,141,143,145,147,150,152,155,158],{"class":41,"line":118},4,[39,120,121],{"class":52},"  async",[39,123,125],{"class":124},"shDkW"," move",[39,127,70],{"class":60},[39,129,130],{"class":76},"from",[39,132,80],{"class":60},[39,134,135],{"class":56}," string",[39,137,96],{"class":60},[39,139,140],{"class":76}," to",[39,142,80],{"class":60},[39,144,135],{"class":56},[39,146,96],{"class":60},[39,148,149],{"class":76}," amount",[39,151,80],{"class":60},[39,153,154],{"class":56}," number",[39,156,157],{"class":60},")",[39,159,61],{"class":60},[39,161,163,166,170,173,177,179,183,186,189,192,195,197,200,203,207],{"class":41,"line":162},5,[39,164,165],{"class":45},"    return",[39,167,169],{"class":168},"sxG60"," this",[39,171,172],{"class":60},".",[39,174,176],{"class":175},"sy9f4","together",[39,178,172],{"class":60},[39,180,182],{"class":181},"s4mR9","run",[39,184,70],{"class":185},"spAFX",[39,187,188],{"class":52},"async",[39,190,191],{"class":60}," ([",[39,193,194],{"class":76},"accounts",[39,196,96],{"class":60},[39,198,199],{"class":76}," ledger",[39,201,202],{"class":60},"])",[39,204,206],{"class":205},"scTuO"," =>",[39,208,61],{"class":60},[39,210,212,215,219,221,224,226,228,230,233,236,238,240,242,245,249,251,254,256,259,262,264,267,270],{"class":41,"line":211},6,[39,213,214],{"class":45},"      await",[39,216,218],{"class":217},"sPEhv"," accounts",[39,220,172],{"class":60},[39,222,223],{"class":181},"update",[39,225,70],{"class":185},[39,227,130],{"class":217},[39,229,96],{"class":60},[39,231,232],{"class":60}," (",[39,234,235],{"class":76},"account",[39,237,157],{"class":60},[39,239,206],{"class":205},[39,241,232],{"class":185},[39,243,244],{"class":60},"{",[39,246,248],{"class":247},"sHtqg"," balance",[39,250,80],{"class":60},[39,252,253],{"class":217}," account",[39,255,172],{"class":60},[39,257,258],{"class":175},"balance",[39,260,261],{"class":60}," -",[39,263,149],{"class":217},[39,265,266],{"class":60}," }",[39,268,269],{"class":185},"))",[39,271,272],{"class":60},";\n",[39,274,276,278,280,282,285,287,289,292,294,296,298,300,302,304],{"class":41,"line":275},7,[39,277,214],{"class":45},[39,279,199],{"class":217},[39,281,172],{"class":60},[39,283,284],{"class":181},"create",[39,286,70],{"class":185},[39,288,244],{"class":60},[39,290,291],{"class":217}," from",[39,293,96],{"class":60},[39,295,140],{"class":217},[39,297,96],{"class":60},[39,299,149],{"class":217},[39,301,266],{"class":60},[39,303,157],{"class":185},[39,305,272],{"class":60},[39,307,309,312,314],{"class":41,"line":308},8,[39,310,311],{"class":60},"    }",[39,313,157],{"class":185},[39,315,272],{"class":60},[39,317,319],{"class":41,"line":318},9,[39,320,321],{"class":60},"  }\n",[39,323,325],{"class":41,"line":324},10,[39,326,327],{"class":60},"}\n",[13,329,330,331,334,335,338],{},"It is asked for by type, like ",[20,332,333],{},"Repository\u003CE>"," or ",[20,336,337],{},"Facade\u003CH>",": nothing to register. Nothing makes\nan ordinary write transactional behind your back either — the block is visible where you read it.",[13,340,341,342,344,345,348],{},"Inside, you are in the ordinary vocabulary. ",[20,343,194],{}," and ",[20,346,347],{},"ledger"," are the same guarded\nentity ports that repositories forward, and every validator still runs: a value the entity\nrefuses is refused here too.",[350,351,353],"h2",{"id":352},"a-value-computed-from-what-is-there","A value computed from what is there",[13,355,356,359],{},[20,357,358],{},"update(id, (row) => …)"," takes the row as it stands and writes what the function answers. No other\nwrite reaches that row between the read and the write, so two transfers from one account both\ncount, and a check inside the function sees the balance it is about to change:",[30,361,363],{"className":32,"code":362,"language":34,"meta":35,"style":35},"await accounts.update(from, (account) => {\n  if (account.balance \u003C amount) throw new FougereError({ code: ErrorCode.CONFLICT, message: 'Insufficient funds' });\n\n  return { balance: account.balance - amount };\n});\n",[20,364,365,392,463,467,492],{"__ignoreMap":35},[39,366,367,370,372,374,376,378,380,382,384,386,388,390],{"class":41,"line":42},[39,368,369],{"class":45},"await",[39,371,218],{"class":217},[39,373,172],{"class":60},[39,375,223],{"class":181},[39,377,70],{"class":89},[39,379,130],{"class":217},[39,381,96],{"class":60},[39,383,232],{"class":60},[39,385,235],{"class":76},[39,387,157],{"class":60},[39,389,206],{"class":205},[39,391,61],{"class":60},[39,393,394,397,399,401,403,405,408,410,412,415,418,422,424,426,429,431,434,436,439,441,444,446,450,454,457,459,461],{"class":41,"line":64},[39,395,396],{"class":45},"  if",[39,398,232],{"class":185},[39,400,235],{"class":217},[39,402,172],{"class":60},[39,404,258],{"class":175},[39,406,407],{"class":60}," \u003C",[39,409,149],{"class":217},[39,411,157],{"class":185},[39,413,414],{"class":45}," throw",[39,416,417],{"class":60}," new",[39,419,421],{"class":420},"sgjsB"," FougereError",[39,423,70],{"class":185},[39,425,244],{"class":60},[39,427,428],{"class":247}," code",[39,430,80],{"class":60},[39,432,433],{"class":217}," ErrorCode",[39,435,172],{"class":60},[39,437,438],{"class":175},"CONFLICT",[39,440,96],{"class":60},[39,442,443],{"class":247}," message",[39,445,80],{"class":60},[39,447,449],{"class":448},"sDDC1"," '",[39,451,453],{"class":452},"sN-8n","Insufficient funds",[39,455,456],{"class":448},"'",[39,458,266],{"class":60},[39,460,157],{"class":185},[39,462,272],{"class":60},[39,464,465],{"class":41,"line":111},[39,466,115],{"emptyLinePlaceholder":114},[39,468,469,472,475,477,479,481,483,485,487,489],{"class":41,"line":118},[39,470,471],{"class":45},"  return",[39,473,474],{"class":60}," {",[39,476,248],{"class":247},[39,478,80],{"class":60},[39,480,253],{"class":217},[39,482,172],{"class":60},[39,484,258],{"class":175},[39,486,261],{"class":60},[39,488,149],{"class":217},[39,490,491],{"class":60}," };\n",[39,493,494,497,499],{"class":41,"line":162},[39,495,496],{"class":60},"}",[39,498,157],{"class":89},[39,500,272],{"class":60},[13,502,503,504,507],{},"Reading with ",[20,505,506],{},"findById"," and writing a value computed from it does not hold: two calls read the same\nbalance, and the second write erases the first. Atomic is not isolated — the frame undoes a half\nblock, and says nothing of who else wrote meanwhile.",[13,509,510],{},"A block that changes several rows of one entity hands them over together, and gets them back by key:",[30,512,514],{"className":32,"code":513,"language":34,"meta":35,"style":35},"await stocks.updateByKeys(productIds, (stock) => ({ units: stock.units - wanted.get(stock.sku)! }));\n",[20,515,516],{"__ignoreMap":35},[39,517,518,520,523,525,528,530,533,535,537,540,542,544,546,548,551,553,556,558,561,563,566,568,571,573,575,577,580,582,585,587,589],{"class":41,"line":42},[39,519,369],{"class":45},[39,521,522],{"class":217}," stocks",[39,524,172],{"class":60},[39,526,527],{"class":181},"updateByKeys",[39,529,70],{"class":89},[39,531,532],{"class":217},"productIds",[39,534,96],{"class":60},[39,536,232],{"class":60},[39,538,539],{"class":76},"stock",[39,541,157],{"class":60},[39,543,206],{"class":205},[39,545,232],{"class":89},[39,547,244],{"class":60},[39,549,550],{"class":247}," units",[39,552,80],{"class":60},[39,554,555],{"class":217}," stock",[39,557,172],{"class":60},[39,559,560],{"class":175},"units",[39,562,261],{"class":60},[39,564,565],{"class":217}," wanted",[39,567,172],{"class":60},[39,569,570],{"class":181},"get",[39,572,70],{"class":89},[39,574,539],{"class":217},[39,576,172],{"class":60},[39,578,579],{"class":175},"sku",[39,581,157],{"class":89},[39,583,584],{"class":60},"!",[39,586,266],{"class":60},[39,588,269],{"class":89},[39,590,272],{"class":60},[13,592,593],{},"Every row is held by one read, taken in key order: two blocks asking for the same rows queue rather\nthan each holding one, so they cannot stop each other, and a key with no row refuses the whole set\nbefore anything is written.",[13,595,596,597,600,601,603],{},"SQL reads the row ",[20,598,599],{},"FOR UPDATE"," on Postgres and MySQL, and writes it onto itself first on SQLite and\nSQL Server, which every engine locks; the lock lasts until the transaction ends. A Map or a file\ntakes the writes on one key one after the other. Two blocks that take the same rows in opposite\norders may stop each other: the engine gives up on one, which answers ",[20,602,438],{}," — taking rows in a\nfixed order, by key, avoids it.",[350,605,607],{"id":606},"two-realizations-and-the-boot-says-which","Two realizations, and the boot says which",[13,609,610,611,615,616,623],{},"The declaration names its members. Where those members ",[612,613,614],"em",{},"live"," is a\n",[617,618,620],"a",{"href":619},"\u002Fdocs\u002Fdata\u002Fsql",[20,621,622],{},"sources:"," decision, and it decides what the frame can promise:",[30,625,630],{"className":626,"code":628,"language":629},[627],"language-text","Together\u003C[Account, Ledger]> — transaction, source 'main'\nTogether\u003C[Account, Ledger]> — compensated: account in 'main', ledger in 'accounting' — no isolation\n","text",[20,631,628],{"__ignoreMap":35},[13,633,634,637],{},[25,635,636],{},"One engine"," — the members are rebuilt over a real transaction. The engine gives the\nunwind and the isolation, and it costs nothing.",[13,639,640,643],{},[25,641,642],{},"Several engines"," — a transaction reaches one engine only, so there is none. The frame keeps\nwhat each row was before every write, and undoes the writes in reverse order. The port has a\nfixed set of gestures, which is what makes an inverse derivable rather than declared:",[645,646,647,660],"table",{},[648,649,650],"thead",{},[651,652,653,657],"tr",{},[654,655,656],"th",{},"write",[654,658,659],{},"its inverse",[661,662,663,677,694,706],"tbody",{},[651,664,665,671],{},[666,667,668],"td",{},[20,669,670],{},"create(x)",[666,672,673,676],{},[20,674,675],{},"delete(x.id)"," — the row is handed back, so it costs nothing",[651,678,679,688],{},[666,680,681,684,685],{},[20,682,683],{},"update(id, patch)",", ",[20,686,687],{},"update(id, change)",[666,689,690,693],{},[20,691,692],{},"update(id, before)"," — one read first",[651,695,696,701],{},[666,697,698],{},[20,699,700],{},"delete(id)",[666,702,703,693],{},[20,704,705],{},"create(row)",[651,707,708,713],{},[666,709,710],{},[20,711,712],{},"upsertAll(page)",[666,714,715],{},"restore what was there, delete what was not — one read for the page",[13,717,718],{},"So you write no undo step: the writes are a fixed set of gestures, and each one's inverse is known.",[720,721,722,728,731],"warning",{},[13,723,724,727],{},[25,725,726],{},"All-or-nothing holds either way — while the process lives. Isolation does not."," Under a\ntransaction, nobody outside can see the block half-done. Compensated, they can: between two\nwrites a reader sees the half, and the unwind puts it back afterwards.",[13,729,730],{},"And the unwind is held in memory, so a compensated frame whose process dies mid-block leaves\nwhat it had written. A transaction does not: its engine rolls back without anyone asking.",[13,732,733],{},"The boot states which realization it built rather than letting you assume the stronger one.",[720,735,736],{},[13,737,738,741,742,745,746,741,749,752],{},[25,739,740],{},"A fact announced inside a frame is not covered."," ",[20,743,744],{},"Emit\u003CT>"," resolves outside the block,\nso an announcement leaves the moment it is made — including from a frame that then unwinds.\nSubscribers will have acted on something that did not happen. Announce ",[25,747,748],{},"after",[20,750,751],{},"run()","\nreturns, where the block has already stood.",[350,754,756],{"id":755},"covering-what-a-collaborator-writes","Covering what a collaborator writes",[13,758,759,760,763,764,767,768,772,773,777,778,781],{},"A member list of entities covers what ",[612,761,762],{},"your"," block writes. A second list names ",[25,765,766],{},"providers","\n— a service, a ",[617,769,771],{"href":770},"\u002Fdocs\u002Fconcepts\u002Frepository","repository",", a\n",[617,774,776],{"href":775},"\u002Fdocs\u002Fdata\u002Fmirror","mirror"," — rebuilt\ninside the frame so that what ",[612,779,780],{},"they"," write is covered too:",[30,783,785],{"className":32,"code":784,"language":34,"meta":35,"style":35},"constructor(private together: Together\u003C[RateCard, Ledger], [RateMirror]>) {}\n\nawait this.together.run(async ([rates, ledger], [mirror]) => {\n  await mirror.refresh();          \u002F\u002F its pages are under the same unwind\n  await ledger.create({ … });\n});\n",[20,786,787,827,831,871,894,918],{"__ignoreMap":35},[39,788,789,792,794,797,799,801,804,806,808,810,812,815,818,820,823,825],{"class":41,"line":42},[39,790,791],{"class":181},"constructor",[39,793,70],{"class":89},[39,795,796],{"class":217},"private together: Together",[39,798,86],{"class":60},[39,800,90],{"class":89},[39,802,803],{"class":217},"RateCard",[39,805,96],{"class":60},[39,807,99],{"class":217},[39,809,102],{"class":89},[39,811,96],{"class":60},[39,813,814],{"class":89}," [",[39,816,817],{"class":217},"RateMirror",[39,819,102],{"class":89},[39,821,822],{"class":60},">",[39,824,157],{"class":89},[39,826,108],{"class":60},[39,828,829],{"class":41,"line":64},[39,830,115],{"emptyLinePlaceholder":114},[39,832,833,835,837,839,841,843,845,847,849,851,854,856,858,861,863,865,867,869],{"class":41,"line":111},[39,834,369],{"class":45},[39,836,169],{"class":168},[39,838,172],{"class":60},[39,840,176],{"class":175},[39,842,172],{"class":60},[39,844,182],{"class":181},[39,846,70],{"class":89},[39,848,188],{"class":52},[39,850,191],{"class":60},[39,852,853],{"class":76},"rates",[39,855,96],{"class":60},[39,857,199],{"class":76},[39,859,860],{"class":60},"],",[39,862,814],{"class":60},[39,864,776],{"class":76},[39,866,202],{"class":60},[39,868,206],{"class":205},[39,870,61],{"class":60},[39,872,873,876,879,881,884,887,890],{"class":41,"line":118},[39,874,875],{"class":45},"  await",[39,877,878],{"class":217}," mirror",[39,880,172],{"class":60},[39,882,883],{"class":181},"refresh",[39,885,886],{"class":185},"()",[39,888,889],{"class":60},";",[39,891,893],{"class":892},"skXKP","          \u002F\u002F its pages are under the same unwind\n",[39,895,896,898,900,902,904,906,908,912,914,916],{"class":41,"line":162},[39,897,875],{"class":45},[39,899,199],{"class":217},[39,901,172],{"class":60},[39,903,284],{"class":181},[39,905,70],{"class":185},[39,907,244],{"class":60},[39,909,911],{"class":910},"ssXpW"," … ",[39,913,496],{"class":60},[39,915,157],{"class":185},[39,917,272],{"class":60},[39,919,920,922,924],{"class":41,"line":211},[39,921,496],{"class":60},[39,923,157],{"class":89},[39,925,272],{"class":60},[13,927,928,930,931,934,935,938],{},[20,929,817],{}," writes through ",[20,932,933],{},"Storage\u003CRateCard>",", so it receives the framed storage through\nits ordinary constructor. Not one line of ",[20,936,937],{},"Mirror"," knows a frame exists.",[13,940,941],{},"Two lists rather than one, because in a signature an entity and a class are both written as\na name and their types do not separate them. They are two different facts anyway: what the\nunwind covers, and what is rebuilt to make that true.",[350,943,945],{"id":944},"what-a-frame-refuses","What a frame refuses",[13,947,948],{},"At boot, so you never discover it at the first call:",[645,950,951,959],{},[648,952,953],{},[651,954,955,957],{},[654,956],{},[654,958],{},[661,960,961,972,980,988],{},[651,962,963,969],{},[666,964,965,966],{},"a member whose frond is declared in ",[20,967,968],{},"fronds:",[666,970,971],{},"it registers no storage here — nothing to record, nothing to undo",[651,973,974,977],{},[666,975,976],{},"a name that resolves to nothing",[666,978,979],{},"a typo, whose only other symptom is a frame quietly one member short",[651,981,982,985],{},[666,983,984],{},"a provider writing an entity absent from the first list",[666,986,987],{},"its writes would escape the unwind",[651,989,990,997],{},[666,991,992,993,996],{},"a member an ",[617,994,995],{"href":770},"aggregate"," owns, outside that aggregate",[666,998,999],{},"only its owner writes it — a frame elsewhere would be a second way in",[13,1001,1002],{},"Two more at the call:",[13,1004,1005,1008],{},[25,1006,1007],{},"A frame opened inside another."," On one engine the second transaction waits for the first, so\nthe call hangs; split across engines the same code returns. Two frames that must both hold are one frame, and its member list is the\nunion.",[13,1010,1011,1019,1020,1022],{},[25,1012,1013,1014,1018],{},"A ",[617,1015,1017],{"href":1016},"\u002Fdocs\u002Fconcepts\u002Ffact","fact"," announced from inside a frame"," — see the warning above: announce\nafter ",[20,1021,751],{}," returns.",[13,1024,1025,1026,1029,1030,1036,1037,1040],{},"And in a compensated frame only: ",[20,1027,1028],{},"upsert"," on an entity that declares a\n",[617,1031,1033],{"href":1032},"\u002Fdocs\u002Fconcepts\u002Fentity",[20,1034,1035],{},"unique"," constraint besides its key. The inverse of an\nupsert is derivable exactly when the conflict is the key; MySQL's ",[20,1038,1039],{},"ON DUPLICATE KEY UPDATE","\nfires on any unique constraint, so the question is asked of your declaration and never of\nthe engine.",[350,1042,1044],{"id":1043},"where-the-gradient-stops","Where the gradient stops",[13,1046,1047,1048,1051],{},"Declaring ",[20,1049,1050],{},"Together\u003C[Account, Ledger]>"," says these two may not be separated by a change of\ntopology. That is a real cost, and it is the point: it is the one place where moving a\nboundary is refused out loud instead of quietly weakening a guarantee.",[13,1053,1054,1055,1057],{},"When two things genuinely live apart and must both end up written, that is not a frame —\nit is a ",[617,1056,1017],{"href":1016},": commit one half, announce, and let the subscriber\ncommit the other. You then own the compensation, and the framework does not pretend\notherwise.",[1059,1060,1061],"style",{},"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 .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 .srlTG, html code.shiki .srlTG{--shiki-light:#90A4AE;--shiki-default:#A3B0A5;--shiki-dark:#BABED8}html pre.shiki code .shDkW, html code.shiki .shDkW{--shiki-light:#E53935;--shiki-default:#C9B6EA;--shiki-dark:#F07178}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 .sy9f4, html code.shiki .sy9f4{--shiki-light:#90A4AE;--shiki-default:#93CFC0;--shiki-dark:#BABED8}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 .scTuO, html code.shiki .scTuO{--shiki-light:#9C3EDA;--shiki-default:#A3B0A5;--shiki-dark:#C792EA}html pre.shiki code .sPEhv, html code.shiki .sPEhv{--shiki-light:#90A4AE;--shiki-default:#DDE5DA;--shiki-dark:#BABED8}html pre.shiki code .sHtqg, html code.shiki .sHtqg{--shiki-light:#E53935;--shiki-default:#93CFC0;--shiki-dark:#F07178}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 .sgjsB, html code.shiki .sgjsB{--shiki-light:#6182B8;--shiki-default:#EFCD8F;--shiki-dark:#82AAFF}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 .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 .ssXpW, html code.shiki .ssXpW{--shiki-light:#E53935;--shiki-default:#DDE5DA;--shiki-dark:#F07178}",{"title":35,"searchDepth":64,"depth":64,"links":1063},[1064,1065,1066,1067,1068],{"id":352,"depth":64,"text":353},{"id":606,"depth":64,"text":607},{"id":755,"depth":64,"text":756},{"id":944,"depth":64,"text":945},{"id":1043,"depth":64,"text":1044},"Writes that stand or fall together.","md",[1072],"Together\u003C[A, B]>","task",{},"\u002Fdocs\u002Fdata\u002Ftogether",{"title":8,"description":1069},"docs\u002F3.data\u002F8.together",null,[771],"FihmhQX0HDxS6Rf4M7Bn3anadHEyzYlvzPH-0sFjdUc",[1082,1084,1087,1089,1092,1095,1097,1100,1103,1109,1115,1119,1123,1127,1131,1135,1139,1142,1144,1148,1152,1156,1161,1165,1169,1173,1177,1181,1185,1189,1193,1197,1201,1205,1209,1213,1217,1220,1223,1226,1229,1232,1235,1238,1241,1244,1247],{"path":1032,"title":1083,"uses":1078},"Entity",{"path":1085,"title":1086,"uses":1078},"\u002Fdocs\u002Fconcepts\u002Fhandler","Handler",{"path":770,"title":1088,"uses":1078},"Repository",{"path":1090,"title":1091,"uses":1078},"\u002Fdocs\u002Fconcepts\u002Ffrond","Frond",{"path":1093,"title":1094,"uses":1078},"\u002Fdocs\u002Fconcepts\u002Ffacade","Facade",{"path":1016,"title":1096,"uses":1078},"Fact",{"path":1098,"title":1099,"uses":1078},"\u002Fdocs\u002Fconcepts\u002Fport","Port",{"path":1101,"title":1102,"uses":1078},"\u002Fdocs\u002Fconcepts\u002Fconfiguration","Configuration",{"path":1104,"title":1105,"uses":1106},"\u002Fdocs\u002Faccess\u002Fauthentication","Authentication",[1107,1108],"port","frond",{"path":1110,"title":1111,"uses":1112},"\u002Fdocs\u002Faccess\u002Fstate","Keep a caller's state",[1113,1114],"configuration","handler",{"path":619,"title":1116,"uses":1117},"SQLite or Postgres",[1118,1113],"entity",{"path":1120,"title":1121,"uses":1122},"\u002Fdocs\u002Fdata\u002Fseveral-databases","Several databases",[1113,1118],{"path":1124,"title":1125,"uses":1126},"\u002Fdocs\u002Fdata\u002Fcomputed-field","A computed field",[1118,1107],{"path":1128,"title":1129,"uses":1130},"\u002Fdocs\u002Fdata\u002Fevolve","Evolve a schema",[1118],{"path":1132,"title":1133,"uses":1134},"\u002Fdocs\u002Fdata\u002Fseeds","Seed data",[1118],{"path":1136,"title":1137,"uses":1138},"\u002Fdocs\u002Fdata\u002Fvalues","Read settings and secrets",[1118,1113],{"path":775,"title":1140,"uses":1141},"Mirror a source you cannot query",[771],{"path":1075,"title":8,"uses":1143},[771],{"path":1145,"title":1146,"uses":1147},"\u002Fdocs\u002Fbehaviour\u002Faround-every-call","Around every call",[1107,1108],{"path":1149,"title":1150,"uses":1151},"\u002Fdocs\u002Fbehaviour\u002Ffinish-a-fact","Finish a fact",[1017],{"path":1153,"title":1154,"uses":1155},"\u002Fdocs\u002Fserve\u002Frest-graphql","REST, OpenAPI, GraphQL",[1114,1113],{"path":1157,"title":1158,"uses":1159},"\u002Fdocs\u002Fserve\u002Fpages","Pages: queries and commands",[1114,1160],"facade",{"path":1162,"title":1163,"uses":1164},"\u002Fdocs\u002Fserve\u002Fforms","A form",[1118],{"path":1166,"title":1167,"uses":1168},"\u002Fdocs\u002Fserve\u002Fadmin","An admin panel",[1114],{"path":1170,"title":1171,"uses":1172},"\u002Fdocs\u002Frun\u002Fdeploy","Deploy a split",[1113,1108],{"path":1174,"title":1175,"uses":1176},"\u002Fdocs\u002Frun\u002Fsecure","Secure calls between processes",[1113,1108],{"path":1178,"title":1179,"uses":1180},"\u002Fdocs\u002Frun\u002Flifecycle","Reload and shut down",[1113],{"path":1182,"title":1183,"uses":1184},"\u002Fdocs\u002Frun\u002Fobserve","Observe",[1113,1114],{"path":1186,"title":1187,"uses":1188},"\u002Fdocs\u002Frun\u002Fdev-panel","The dev panel",[1114],{"path":1190,"title":1191,"uses":1192},"\u002Fdocs\u002Frun\u002Ftest","Test",[1118,1107],{"path":1194,"title":1195,"uses":1196},"\u002Fdocs\u002Fadopt\u002Fnew-project","Start a project",[1108,1113],{"path":1198,"title":1199,"uses":1200},"\u002Fdocs\u002Fadopt\u002Fexisting-app","Add Fougere to an existing app",[1108,1113],{"path":1202,"title":1203,"uses":1204},"\u002Fdocs\u002Fadopt\u002Fbring-your-schema","Bring your schema",[1118],{"path":1206,"title":1207,"uses":1208},"\u002Fdocs\u002Fadopt\u002Fhosts","Pick a host",[1113],{"path":1210,"title":1211,"uses":1212},"\u002Fdocs\u002Fadopt\u002Fanother-repository","A frond from another repository",[1160,1108],{"path":1214,"title":1215,"uses":1216},"\u002Fdocs\u002Fadopt\u002Fdemos","Demos",[],{"path":1218,"title":1219,"uses":1078},"\u002Fdocs\u002Fextending\u002Fscan","How the scan reads a project",{"path":1221,"title":1222,"uses":1078},"\u002Fdocs\u002Fextending\u002Fwithout-compiler","Boot without the compiler",{"path":1224,"title":1225,"uses":1078},"\u002Fdocs\u002Fextending\u002Fboot","The boot, step by step",{"path":1227,"title":1228,"uses":1078},"\u002Fdocs\u002Fextending\u002Fcard-and-wire","The card and the wire",{"path":1230,"title":1231,"uses":1078},"\u002Fdocs\u002Fextending\u002Fextension-points","Registries and extension points",{"path":1233,"title":1234,"uses":1078},"\u002Fdocs\u002Fextending\u002Fvocabulary","Teach a word",{"path":1236,"title":1237,"uses":1078},"\u002Fdocs\u002Fextending\u002Fextensions","Run code at boot and shutdown",{"path":1239,"title":1240,"uses":1078},"\u002Fdocs\u002Fextending\u002Fsource-adapter","Write a source adapter",{"path":1242,"title":1243,"uses":1078},"\u002Fdocs\u002Fextending\u002Fsurface","Write a surface",{"path":1245,"title":1246,"uses":1078},"\u002Fdocs\u002Fextending\u002Fforeign-frond","A frond in another language",{"path":1248,"title":1249,"uses":1078},"\u002Fdocs","What is Fougere",[1251],{"title":1252,"path":1248,"stem":1253,"children":1254,"page":-1},"Docs","docs",[1255,1257,1278,1287,1307,1316,1329,1346,1363],{"title":1249,"path":1248,"stem":1256},"docs\u002Findex",{"title":1258,"path":1259,"stem":1260,"children":1261,"page":5},"Concepts","\u002Fdocs\u002Fconcepts","docs\u002F1.concepts",[1262,1264,1266,1268,1270,1272,1274,1276],{"title":1083,"path":1032,"stem":1263},"docs\u002F1.concepts\u002F1.entity",{"title":1086,"path":1085,"stem":1265},"docs\u002F1.concepts\u002F2.handler",{"title":1088,"path":770,"stem":1267},"docs\u002F1.concepts\u002F3.repository",{"title":1091,"path":1090,"stem":1269},"docs\u002F1.concepts\u002F4.frond",{"title":1094,"path":1093,"stem":1271},"docs\u002F1.concepts\u002F5.facade",{"title":1096,"path":1016,"stem":1273},"docs\u002F1.concepts\u002F6.fact",{"title":1099,"path":1098,"stem":1275},"docs\u002F1.concepts\u002F7.port",{"title":1102,"path":1101,"stem":1277},"docs\u002F1.concepts\u002F8.configuration",{"title":1279,"path":1280,"stem":1281,"children":1282,"page":5},"Access","\u002Fdocs\u002Faccess","docs\u002F2.access",[1283,1285],{"title":1105,"path":1104,"stem":1284},"docs\u002F2.access\u002F1.authentication",{"title":1111,"path":1110,"stem":1286},"docs\u002F2.access\u002F2.state",{"title":1288,"path":1289,"stem":1290,"children":1291,"page":5},"Data","\u002Fdocs\u002Fdata","docs\u002F3.data",[1292,1294,1296,1298,1300,1302,1304,1306],{"title":1116,"path":619,"stem":1293},"docs\u002F3.data\u002F1.sql",{"title":1121,"path":1120,"stem":1295},"docs\u002F3.data\u002F2.several-databases",{"title":1125,"path":1124,"stem":1297},"docs\u002F3.data\u002F3.computed-field",{"title":1129,"path":1128,"stem":1299},"docs\u002F3.data\u002F4.evolve",{"title":1133,"path":1132,"stem":1301},"docs\u002F3.data\u002F5.seeds",{"title":1137,"path":1136,"stem":1303},"docs\u002F3.data\u002F6.values",{"title":1140,"path":775,"stem":1305},"docs\u002F3.data\u002F7.mirror",{"title":8,"path":1075,"stem":1077},{"title":1308,"path":1309,"stem":1310,"children":1311,"page":5},"Behaviour","\u002Fdocs\u002Fbehaviour","docs\u002F4.behaviour",[1312,1314],{"title":1146,"path":1145,"stem":1313},"docs\u002F4.behaviour\u002F1.around-every-call",{"title":1150,"path":1149,"stem":1315},"docs\u002F4.behaviour\u002F2.finish-a-fact",{"title":1317,"path":1318,"stem":1319,"children":1320,"page":5},"Serve","\u002Fdocs\u002Fserve","docs\u002F5.serve",[1321,1323,1325,1327],{"title":1154,"path":1153,"stem":1322},"docs\u002F5.serve\u002F1.rest-graphql",{"title":1158,"path":1157,"stem":1324},"docs\u002F5.serve\u002F2.pages",{"title":1163,"path":1162,"stem":1326},"docs\u002F5.serve\u002F3.forms",{"title":1167,"path":1166,"stem":1328},"docs\u002F5.serve\u002F4.admin",{"title":1330,"path":1331,"stem":1332,"children":1333,"page":5},"Run","\u002Fdocs\u002Frun","docs\u002F6.run",[1334,1336,1338,1340,1342,1344],{"title":1171,"path":1170,"stem":1335},"docs\u002F6.run\u002F1.deploy",{"title":1175,"path":1174,"stem":1337},"docs\u002F6.run\u002F2.secure",{"title":1179,"path":1178,"stem":1339},"docs\u002F6.run\u002F3.lifecycle",{"title":1183,"path":1182,"stem":1341},"docs\u002F6.run\u002F4.observe",{"title":1187,"path":1186,"stem":1343},"docs\u002F6.run\u002F5.dev-panel",{"title":1191,"path":1190,"stem":1345},"docs\u002F6.run\u002F6.test",{"title":1347,"path":1348,"stem":1349,"children":1350,"page":5},"Adopt","\u002Fdocs\u002Fadopt","docs\u002F7.adopt",[1351,1353,1355,1357,1359,1361],{"title":1195,"path":1194,"stem":1352},"docs\u002F7.adopt\u002F1.new-project",{"title":1199,"path":1198,"stem":1354},"docs\u002F7.adopt\u002F2.existing-app",{"title":1203,"path":1202,"stem":1356},"docs\u002F7.adopt\u002F3.bring-your-schema",{"title":1207,"path":1206,"stem":1358},"docs\u002F7.adopt\u002F4.hosts",{"title":1211,"path":1210,"stem":1360},"docs\u002F7.adopt\u002F5.another-repository",{"title":1215,"path":1214,"stem":1362},"docs\u002F7.adopt\u002F6.demos",{"title":1364,"path":1365,"stem":1366,"children":1367,"page":5},"Extending","\u002Fdocs\u002Fextending","docs\u002F8.extending",[1368,1370,1372,1374,1376,1378,1380,1382,1384,1386],{"title":1219,"path":1218,"stem":1369},"docs\u002F8.extending\u002F1.scan",{"title":1222,"path":1221,"stem":1371},"docs\u002F8.extending\u002F10.without-compiler",{"title":1225,"path":1224,"stem":1373},"docs\u002F8.extending\u002F2.boot",{"title":1228,"path":1227,"stem":1375},"docs\u002F8.extending\u002F3.card-and-wire",{"title":1231,"path":1230,"stem":1377},"docs\u002F8.extending\u002F4.extension-points",{"title":1234,"path":1233,"stem":1379},"docs\u002F8.extending\u002F5.vocabulary",{"title":1237,"path":1236,"stem":1381},"docs\u002F8.extending\u002F6.extensions",{"title":1240,"path":1239,"stem":1383},"docs\u002F8.extending\u002F7.source-adapter",{"title":1243,"path":1242,"stem":1385},"docs\u002F8.extending\u002F8.surface",{"title":1246,"path":1245,"stem":1387},"docs\u002F8.extending\u002F9.foreign-frond",1794396614603]