[{"data":1,"prerenderedAt":980},["ShallowReactive",2],{"docs-nav:en":3,"docs:\u002Fdocs\u002Fbusiness\u002Fstorage":186},[4],{"title":5,"path":6,"stem":7,"children":8},"Docs","\u002Fdocs","docs",[9,12,16,20,24,28,50,75,120,145],{"title":10,"path":6,"stem":11},"What is Fougere","docs\u002Findex",{"title":13,"path":14,"stem":15},"Getting started","\u002Fdocs\u002Fgetting-started","docs\u002F01.getting-started",{"title":17,"path":18,"stem":19},"An app you already have","\u002Fdocs\u002Fexisting-app","docs\u002F02.existing-app",{"title":21,"path":22,"stem":23},"Bring your schema","\u002Fdocs\u002Fbring-your-schema","docs\u002F03.bring-your-schema",{"title":25,"path":26,"stem":27},"The CLI","\u002Fdocs\u002Fcli","docs\u002F04.cli",{"title":29,"path":30,"stem":31,"children":32,"page":49},"Concepts","\u002Fdocs\u002Fconcepts","docs\u002F2.concepts",[33,37,41,45],{"title":34,"path":35,"stem":36},"Philosophy","\u002Fdocs\u002Fconcepts\u002Fphilosophy","docs\u002F2.concepts\u002F1.philosophy",{"title":38,"path":39,"stem":40},"The Frond","\u002Fdocs\u002Fconcepts\u002Ffrond","docs\u002F2.concepts\u002F2.frond",{"title":42,"path":43,"stem":44},"The shortest path","\u002Fdocs\u002Fconcepts\u002Fshortest-path","docs\u002F2.concepts\u002F3.shortest-path",{"title":46,"path":47,"stem":48},"The base","\u002Fdocs\u002Fconcepts\u002Fthe-base","docs\u002F2.concepts\u002F4.the-base",false,{"title":51,"path":52,"stem":53,"children":54,"page":49},"Schema","\u002Fdocs\u002Fschema","docs\u002F3.schema",[55,59,63,67,71],{"title":56,"path":57,"stem":58},"Entities","\u002Fdocs\u002Fschema\u002Fentities","docs\u002F3.schema\u002F1.entities",{"title":60,"path":61,"stem":62},"Views","\u002Fdocs\u002Fschema\u002Fviews","docs\u002F3.schema\u002F2.views",{"title":64,"path":65,"stem":66},"The identity card","\u002Fdocs\u002Fschema\u002Fcard","docs\u002F3.schema\u002F3.card",{"title":68,"path":69,"stem":70},"Standard Schema","\u002Fdocs\u002Fschema\u002Fstandard-schema","docs\u002F3.schema\u002F4.standard-schema",{"title":72,"path":73,"stem":74},"How a schema moves","\u002Fdocs\u002Fschema\u002Fevolution","docs\u002F3.schema\u002F5.evolution",{"title":76,"path":77,"stem":78,"children":79,"page":49},"Business","\u002Fdocs\u002Fbusiness","docs\u002F4.business",[80,84,88,92,96,100,104,108,112,116],{"title":81,"path":82,"stem":83},"Handlers","\u002Fdocs\u002Fbusiness\u002Fhandlers","docs\u002F4.business\u002F1.handlers",{"title":85,"path":86,"stem":87},"Ports","\u002Fdocs\u002Fbusiness\u002Fports","docs\u002F4.business\u002F10.ports",{"title":89,"path":90,"stem":91},"Presenters","\u002Fdocs\u002Fbusiness\u002Fpresenters","docs\u002F4.business\u002F2.presenters",{"title":93,"path":94,"stem":95},"Collectors","\u002Fdocs\u002Fbusiness\u002Fcollectors","docs\u002F4.business\u002F3.collectors",{"title":97,"path":98,"stem":99},"Errors","\u002Fdocs\u002Fbusiness\u002Ferrors","docs\u002F4.business\u002F4.errors",{"title":101,"path":102,"stem":103},"Seeds","\u002Fdocs\u002Fbusiness\u002Fseeds","docs\u002F4.business\u002F5.seeds",{"title":105,"path":106,"stem":107},"Facts","\u002Fdocs\u002Fbusiness\u002Ffacts","docs\u002F4.business\u002F6.facts",{"title":109,"path":110,"stem":111},"Storage","\u002Fdocs\u002Fbusiness\u002Fstorage","docs\u002F4.business\u002F7.storage",{"title":113,"path":114,"stem":115},"Writes that stand or fall as one","\u002Fdocs\u002Fbusiness\u002Ftogether","docs\u002F4.business\u002F8.together",{"title":117,"path":118,"stem":119},"Repositories","\u002Fdocs\u002Fbusiness\u002Frepositories","docs\u002F4.business\u002F9.repositories",{"title":121,"path":122,"stem":123,"children":124,"page":49},"Client","\u002Fdocs\u002Fclient","docs\u002F5.client",[125,129,133,137,141],{"title":126,"path":127,"stem":128},"Queries & commands","\u002Fdocs\u002Fclient\u002Fqueries-commands","docs\u002F5.client\u002F1.queries-commands",{"title":130,"path":131,"stem":132},"Forms","\u002Fdocs\u002Fclient\u002Fforms","docs\u002F5.client\u002F2.forms",{"title":134,"path":135,"stem":136},"Session","\u002Fdocs\u002Fclient\u002Fsession","docs\u002F5.client\u002F3.session",{"title":138,"path":139,"stem":140},"invoke","\u002Fdocs\u002Fclient\u002Finvoke","docs\u002F5.client\u002F4.invoke",{"title":142,"path":143,"stem":144},"Back-office","\u002Fdocs\u002Fclient\u002Fadmin","docs\u002F5.client\u002F5.admin",{"title":146,"path":147,"stem":148,"children":149,"page":49},"Infrastructure","\u002Fdocs\u002Finfra","docs\u002F6.infra",[150,154,158,162,166,170,174,178,182],{"title":151,"path":152,"stem":153},"The gradient","\u002Fdocs\u002Finfra\u002Fgradient","docs\u002F6.infra\u002F1.gradient",{"title":155,"path":156,"stem":157},"Surfaces — REST & GraphQL","\u002Fdocs\u002Finfra\u002Fsurfaces","docs\u002F6.infra\u002F2.surfaces",{"title":159,"path":160,"stem":161},"Deployment","\u002Fdocs\u002Finfra\u002Fdeployment","docs\u002F6.infra\u002F3.deployment",{"title":163,"path":164,"stem":165},"Hosts","\u002Fdocs\u002Finfra\u002Fhosts","docs\u002F6.infra\u002F4.hosts",{"title":167,"path":168,"stem":169},"Sources","\u002Fdocs\u002Finfra\u002Fsources","docs\u002F6.infra\u002F5.sources",{"title":171,"path":172,"stem":173},"Lifecycle","\u002Fdocs\u002Finfra\u002Flifecycle","docs\u002F6.infra\u002F6.lifecycle",{"title":175,"path":176,"stem":177},"Identity across Fronds","\u002Fdocs\u002Finfra\u002Fidentity","docs\u002F6.infra\u002F7.identity",{"title":179,"path":180,"stem":181},"Observability","\u002Fdocs\u002Finfra\u002Fobservability","docs\u002F6.infra\u002F8.observability",{"title":183,"path":184,"stem":185},"Testing","\u002Fdocs\u002Finfra\u002Ftesting","docs\u002F6.infra\u002F9.testing",{"id":187,"title":109,"body":188,"description":975,"extension":976,"meta":977,"navigation":286,"path":110,"seo":978,"stem":111,"__hash__":979},"docs_en\u002Fdocs\u002F4.business\u002F7.storage.md",{"type":189,"value":190,"toc":967},"minimark",[191,195,208,219,378,396,405,410,583,587,601,721,731,737,802,809,819,823,833,886,889,904,908,919,925,934,949,958,963],[192,193,109],"h1",{"id":194},"storage",[196,197,198,202,203,207],"p",{},[199,200,201],"code",{},"Storage\u003CPost>"," is the set of gestures Post's rows answer. It is a ",[204,205,206],"strong",{},"port",": fixed, with\nno flavour of domain, implemented by whichever storage the app resolved.",[196,209,210,213,214,218],{},[204,211,212],{},"You do not ask for it by name."," A handler, a presenter and a collector reach storage\nthrough a ",[215,216,217],"a",{"href":118},"repository",", which forwards every gesture below and\nis registered whether or not anyone wrote the file:",[220,221,226],"pre",{"className":222,"code":223,"language":224,"meta":225,"style":225},"language-ts shiki shiki-themes material-theme-lighter github-light github-dark","export default class PostHandler {\n  constructor(private posts: PostRepository) {}\n\n  async recent() { return this.posts.list({ orderBy: 'publishedAt', order: 'desc' }); }\n}\n","ts","",[199,227,228,252,281,288,372],{"__ignoreMap":225},[229,230,233,237,240,244,248],"span",{"class":231,"line":232},"line",1,[229,234,236],{"class":235},"sVHd0","export",[229,238,239],{"class":235}," default",[229,241,243],{"class":242},"sbsja"," class",[229,245,247],{"class":246},"sbgvK"," PostHandler",[229,249,251],{"class":250},"sP7_E"," {\n",[229,253,255,258,261,264,268,272,275,278],{"class":231,"line":254},2,[229,256,257],{"class":242},"  constructor",[229,259,260],{"class":250},"(",[229,262,263],{"class":242},"private",[229,265,267],{"class":266},"s99_P"," posts",[229,269,271],{"class":270},"smGrS",":",[229,273,274],{"class":246}," PostRepository",[229,276,277],{"class":250},")",[229,279,280],{"class":250}," {}\n",[229,282,284],{"class":231,"line":283},3,[229,285,287],{"emptyLinePlaceholder":286},true,"\n",[229,289,291,294,298,301,304,307,311,314,318,320,324,327,330,333,335,339,343,346,349,352,354,356,359,361,364,366,369],{"class":231,"line":290},4,[229,292,293],{"class":242},"  async",[229,295,297],{"class":296},"sVXei"," recent",[229,299,300],{"class":250},"()",[229,302,303],{"class":250}," {",[229,305,306],{"class":235}," return",[229,308,310],{"class":309},"s39Yj"," this",[229,312,313],{"class":250},".",[229,315,317],{"class":316},"su5hD","posts",[229,319,313],{"class":250},[229,321,323],{"class":322},"sGLFI","list",[229,325,260],{"class":326},"skxfh",[229,328,329],{"class":250},"{",[229,331,332],{"class":326}," orderBy",[229,334,271],{"class":250},[229,336,338],{"class":337},"sjJ54"," '",[229,340,342],{"class":341},"s_sjI","publishedAt",[229,344,345],{"class":337},"'",[229,347,348],{"class":250},",",[229,350,351],{"class":326}," order",[229,353,271],{"class":250},[229,355,338],{"class":337},[229,357,358],{"class":341},"desc",[229,360,345],{"class":337},[229,362,363],{"class":250}," }",[229,365,277],{"class":326},[229,367,368],{"class":250},";",[229,370,371],{"class":250}," }\n",[229,373,375],{"class":231,"line":374},5,[229,376,377],{"class":250},"}\n",[196,379,380,381,384,385,388,389,395],{},"Naming the port in one of those three is refused at boot. One way in, and one word for it —\nso an entity that later belongs to an ",[215,382,383],{"href":118},"aggregate"," moves no call\nsite. The exception is a ",[204,386,387],{},"holder",": a class a prefab built over its own entity — a\n",[215,390,392],{"href":391},"\u002Fdocs\u002Fconcepts\u002Fthe-base#mirror--a-local-copy-of-rows-you-cannot-query",[199,393,394],{},"Mirror"," — may name that entity's port, because holding\nthe storage is what it is for.",[196,397,398,399,404],{},"A ",[215,400,401],{"href":82},[199,402,403],{},"Crud(Post)"," handler is handed its repository automatically. A\nquery worth a name belongs on that repository rather than spelled at the call site.",[406,407,409],"h2",{"id":408},"the-gestures","The gestures",[411,412,413,424],"table",{},[414,415,416],"thead",{},[417,418,419,422],"tr",{},[420,421],"th",{},[420,423],{},[425,426,427,454,467,481,498,516,526,536,546,559,573],"tbody",{},[417,428,429,435],{},[430,431,432],"td",{},[199,433,434],{},"list(options?)",[430,436,437,438,441,442,441,445,441,448,441,451],{},"a page, with ",[199,439,440],{},"where",", ",[199,443,444],{},"orderBy",[199,446,447],{},"limit",[199,449,450],{},"offset",[199,452,453],{},"count",[417,455,456,461],{},[430,457,458],{},[199,459,460],{},"findById(id)",[430,462,463,464],{},"one row, or ",[199,465,466],{},"undefined",[417,468,469,478],{},[430,470,471,474,475],{},[199,472,473],{},"findBy(criteria)"," \u002F ",[199,476,477],{},"findAllBy(criteria)",[430,479,480],{},"one row, or all of them, matching by equality",[417,482,483,488],{},[430,484,485],{},[199,486,487],{},"findByKeys(ids)",[430,489,490,491,494,495],{},"a ",[204,492,493],{},"set"," of rows by key, as a ",[199,496,497],{},"Map",[417,499,500,505],{},[430,501,502],{},[199,503,504],{},"findAllByKeys(field, keys)",[430,506,507,508,512,513,515],{},"its dual: the rows pointing ",[509,510,511],"em",{},"at"," each key, as a ",[199,514,497],{}," of lists",[417,517,518,523],{},[430,519,520],{},[199,521,522],{},"create(input)",[430,524,525],{},"insert, and hand back the complete row",[417,527,528,533],{},[430,529,530],{},[199,531,532],{},"upsert(input)",[430,534,535],{},"write the row, or make the existing one look like this",[417,537,538,543],{},[430,539,540],{},[199,541,542],{},"upsertAll(inputs)",[430,544,545],{},"a whole page in one statement, answering how many were written",[417,547,548,556],{},[430,549,550,474,553],{},[199,551,552],{},"update(id, input)",[199,554,555],{},"delete(id)",[430,557,558],{},"by key",[417,560,561,566],{},[430,562,563],{},[199,564,565],{},"output(view)",[430,567,568,569,572],{},"a scoped storage whose reads are restricted to a ",[215,570,571],{"href":61},"view","'s fields",[417,574,575,580],{},[430,576,577],{},[199,578,579],{},"client",[430,581,582],{},"what the port wraps — see the warning below",[406,584,586],{"id":585},"reading-a-set-not-a-row-at-a-time","Reading a set, not a row at a time",[196,588,589,592,593,596,597,600],{},[199,590,591],{},"findAllBy"," compares with ",[199,594,595],{},"=",", so a list of ids could not be passed to it: the only way to\nread N rows was ",[199,598,599],{},"list()"," then filter in memory. That is invisible on a local SQLite file\nand it is the whole table the day the rows are not local.",[220,602,604],{"className":222,"code":603,"language":224,"meta":225,"style":225},"const authors = await authorStorage.findByKeys(posts.map((p) => p.authorId));\nreturn posts.map((post) => ({ ...post, author: authors.get(post.authorId) }));\n",[199,605,606,659],{"__ignoreMap":225},[229,607,608,611,615,618,621,624,626,629,632,634,637,639,641,643,645,648,651,653,656],{"class":231,"line":232},[229,609,610],{"class":242},"const",[229,612,614],{"class":613},"s_hVV"," authors",[229,616,617],{"class":270}," =",[229,619,620],{"class":235}," await",[229,622,623],{"class":316}," authorStorage",[229,625,313],{"class":250},[229,627,628],{"class":322},"findByKeys",[229,630,631],{"class":316},"(posts",[229,633,313],{"class":250},[229,635,636],{"class":322},"map",[229,638,260],{"class":316},[229,640,260],{"class":250},[229,642,196],{"class":266},[229,644,277],{"class":250},[229,646,647],{"class":242}," =>",[229,649,650],{"class":316}," p",[229,652,313],{"class":250},[229,654,655],{"class":316},"authorId))",[229,657,658],{"class":250},";\n",[229,660,661,664,666,668,670,672,674,677,679,681,684,686,689,691,693,696,698,700,702,705,708,710,713,716,719],{"class":231,"line":254},[229,662,663],{"class":235},"return",[229,665,267],{"class":316},[229,667,313],{"class":250},[229,669,636],{"class":322},[229,671,260],{"class":316},[229,673,260],{"class":250},[229,675,676],{"class":266},"post",[229,678,277],{"class":250},[229,680,647],{"class":242},[229,682,683],{"class":316}," (",[229,685,329],{"class":250},[229,687,688],{"class":270}," ...",[229,690,676],{"class":316},[229,692,348],{"class":250},[229,694,695],{"class":326}," author",[229,697,271],{"class":250},[229,699,614],{"class":316},[229,701,313],{"class":250},[229,703,704],{"class":322},"get",[229,706,707],{"class":316},"(post",[229,709,313],{"class":250},[229,711,712],{"class":316},"authorId) ",[229,714,715],{"class":250},"}",[229,717,718],{"class":316},"))",[229,720,658],{"class":250},[196,722,723,724,726,727,730],{},"It answers a ",[204,725,497],{},", because the caller holds keys and not positions. A miss is the\nabsence of a key, a repeated key is one entry, and a page zips against it by\n",[199,728,729],{},"get(row.authorId)",". A list could not promise that zip — dropping a miss shifts every\nlater position — so each caller rebuilt the index the implementation had just discarded.",[196,732,733,736],{},[199,734,735],{},"findAllByKeys"," is the other direction of the same relation:",[220,738,740],{"className":222,"code":739,"language":224,"meta":225,"style":225},"\u002F\u002F every comment of every post on this page, in one query\nconst byPost = await commentStorage.findAllByKeys('postId', posts.map((p) => p.id));\n",[199,741,742,748],{"__ignoreMap":225},[229,743,744],{"class":231,"line":232},[229,745,747],{"class":746},"sutJx","\u002F\u002F every comment of every post on this page, in one query\n",[229,749,750,752,755,757,759,762,764,766,768,770,773,775,777,779,781,783,785,787,789,791,793,795,797,800],{"class":231,"line":254},[229,751,610],{"class":242},[229,753,754],{"class":613}," byPost",[229,756,617],{"class":270},[229,758,620],{"class":235},[229,760,761],{"class":316}," commentStorage",[229,763,313],{"class":250},[229,765,735],{"class":322},[229,767,260],{"class":316},[229,769,345],{"class":337},[229,771,772],{"class":341},"postId",[229,774,345],{"class":337},[229,776,348],{"class":250},[229,778,267],{"class":316},[229,780,313],{"class":250},[229,782,636],{"class":322},[229,784,260],{"class":316},[229,786,260],{"class":250},[229,788,196],{"class":266},[229,790,277],{"class":250},[229,792,647],{"class":242},[229,794,650],{"class":316},[229,796,313],{"class":250},[229,798,799],{"class":316},"id))",[229,801,658],{"class":250},[196,803,804,805,808],{},"A key with no rows is simply absent. Together the two cover both sides of a relation, each\nin one query — which is what lets a ",[215,806,807],{"href":90},"presenter"," receive the page\nand issue one read for it.",[810,811,812],"warning",{},[196,813,814,815,818],{},"The shape forces the query, not the body. ",[199,816,817],{},"Promise.all(rows.map(...))"," inside a computed\nfield still issues one read per row, and nothing says so.",[406,820,822],{"id":821},"writing-a-page","Writing a page",[196,824,825,828,829,832],{},[199,826,827],{},"create"," throws on the second run, so re-reading a source meant deleting first. ",[199,830,831],{},"upsert","\nwrites the row or makes the existing one look like this, in one statement:",[220,834,836],{"className":222,"code":835,"language":224,"meta":225,"style":225},"await storage.upsert({ id: 'isbn-9782070423200', title: 'La Peste' });\n",[199,837,838],{"__ignoreMap":225},[229,839,840,843,846,848,850,852,854,857,859,861,864,866,868,871,873,875,878,880,882,884],{"class":231,"line":232},[229,841,842],{"class":235},"await",[229,844,845],{"class":316}," storage",[229,847,313],{"class":250},[229,849,831],{"class":322},[229,851,260],{"class":316},[229,853,329],{"class":250},[229,855,856],{"class":326}," id",[229,858,271],{"class":250},[229,860,338],{"class":337},[229,862,863],{"class":341},"isbn-9782070423200",[229,865,345],{"class":337},[229,867,348],{"class":250},[229,869,870],{"class":326}," title",[229,872,271],{"class":250},[229,874,338],{"class":337},[229,876,877],{"class":341},"La Peste",[229,879,345],{"class":337},[229,881,363],{"class":250},[229,883,277],{"class":316},[229,885,658],{"class":250},[196,887,888],{},"The key and the creation stamps survive an overwrite — a row keeps the moment it appeared.\nAn engine with no upsert clause refuses by name rather than emulating one with a read in\nfront, which would promise an atomicity it has not got.",[196,890,891,894,895,898,899,903],{},[199,892,893],{},"upsertAll"," takes a page and answers ",[204,896,897],{},"how many rows were written",", not the rows: an\nimport acts on none of them, and re-reading a page for a symmetry nobody uses would double\nthe work. It is what ",[215,900,901],{"href":391},[199,902,394],{},"\nwrites through.",[406,905,907],{"id":906},"every-write-through-the-port-is-judged","Every write through the port is judged",[196,909,910,911,914,915,918],{},"A handler writes freely because it is the author, but the port is still a way out: a value\nthe entity forbids is refused here as it is at the façade. Lifecycle rules are realized on\nthe way in — ",[199,912,913],{},"created()"," is stamped, ",[199,916,917],{},"update: 'forbidden'"," is enforced — so a handler never\nfills those by hand.",[406,920,922,924],{"id":921},"client-and-what-it-costs",[199,923,579],{}," — and what it costs",[196,926,927,929,930,933],{},[199,928,579],{}," is the underlying instance: the Kysely one for the SQL adapter, something else\nelsewhere. It is typed ",[199,931,932],{},"unknown"," on purpose — narrowing it is the caller saying out loud\nwhich implementation they are standing on.",[810,935,936],{},[196,937,938,941,942,944,945,948],{},[204,939,940],{},"Every judge sits on the port's own methods."," A statement issued through ",[199,943,579],{}," meets\nnone of them: a value the entity refuses lands in the table without a word. The scope stays\nhonest — ",[199,946,947],{},"productStorage.client"," reaches the products, not the whole database — but the judge\ndoes not run.",[196,950,951,952,957],{},"For \"debit A and credit B, or neither\", reach for\n",[215,953,954],{"href":114},[199,955,956],{},"Together"," instead: it is the same port, judged the same way,\nwith a block for its unit instead of a statement.",[196,959,960,961,313],{},"Next: ",[215,962,113],{"href":114},[964,965,966],"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 .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 .sP7_E, html code.shiki .sP7_E{--shiki-light:#39ADB5;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .s99_P, html code.shiki .s99_P{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#E36209;--shiki-default-font-style:inherit;--shiki-dark:#FFAB70;--shiki-dark-font-style:inherit}html pre.shiki code .smGrS, html code.shiki .smGrS{--shiki-light:#39ADB5;--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sVXei, html code.shiki .sVXei{--shiki-light:#E53935;--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .s39Yj, html code.shiki .s39Yj{--shiki-light:#39ADB5;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .su5hD, html code.shiki .su5hD{--shiki-light:#90A4AE;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sGLFI, html code.shiki .sGLFI{--shiki-light:#6182B8;--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .skxfh, html code.shiki .skxfh{--shiki-light:#E53935;--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 .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 .s_hVV, html code.shiki .s_hVV{--shiki-light:#90A4AE;--shiki-default:#005CC5;--shiki-dark:#79B8FF}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":225,"searchDepth":254,"depth":254,"links":968},[969,970,971,972,973],{"id":408,"depth":254,"text":409},{"id":585,"depth":254,"text":586},{"id":821,"depth":254,"text":822},{"id":906,"depth":254,"text":907},{"id":921,"depth":254,"text":974},"client — and what it costs","Storage — the gestures every storage answers, why a set is read in one query, and the escape hatch that turns the judge off.","md",{},{"title":109,"description":975},"k6m_V5LJwIqAywGo0cmbCC3ThWWKu8aTg1M3XVAlT2k",1788560230773]