[{"data":1,"prerenderedAt":12973},["ShallowReactive",2],{"fougere:post.list:{}":3,"docs:\u002Fdocs\u002Frun\u002Ftest":6,"docs-uses":2049,"docs-nav":2220,"demo:test-gradient":2358},{"items":4,"hasMore":5},[],false,{"id":7,"title":8,"body":9,"description":2036,"extension":2037,"forms":2038,"kind":2040,"meta":2041,"navigation":184,"path":2042,"seo":2043,"stem":2044,"step":2045,"uses":2046,"__hash__":2048},"docs\u002Fdocs\u002F6.run\u002F6.test.md","Test",{"type":10,"value":11,"toc":2021},"minimark",[12,21,32,47,132,204,209,217,232,332,350,375,379,436,442,448,471,478,488,514,519,545,549,632,670,681,684,688,696,867,878,885,895,1012,1019,1023,1050,1053,1056,1063,1089,1093,1188,1203,1210,1280,1284,1291,1364,1379,1382,1386,1389,1414,1494,1507,1524,1528,1532,1552,1623,1633,1637,1774,1789,1800,1807,1810,1814,1817,1881,1899,1902,1990,1995,2017],[13,14,15,16,20],"p",{},"Most of what a test of a Fougere app checks is already declared: the entity says what it refuses, a\nport says what can be replaced, the topology says what is real. ",[17,18,19],"code",{},"@fougere\u002Ftesting"," reads those\ndeclarations, so you write the tests only you can write. It rests on two ideas.",[13,22,23,27,28,31],{},[24,25,26],"strong",{},"Part of a test suite has no reason to be written."," ",[17,29,30],{},"InputRefusal"," has a closed list of\nrefusals — unknown field, missing field, read-only, immutable, the shape, a named codec —\nand the four axes say who writes what and when. So the cases can be computed from the\nentity. A test typed by hand becomes false the day the entity moves and nobody hears\nabout it; a derived one moves with it.",[13,33,34,37,38,41,42,46],{},[24,35,36],{},"A test's level of reality does not belong to it."," That is the gesture Fougere already\napplies to topology: ",[17,39,40],{},"fronds:"," sits outside the frond, and the same code runs in-process\nor behind JSON-RPC. Here, what is real and where it runs are stated ",[43,44,45],"em",{},"outside"," the test\nfile, which says only what it expects.",[48,49,53,82,99,116],"code-group",{"className":50,"sync":52},[51],"managers","pm",[54,55,61],"pre",{"className":56,"code":57,"filename":58,"language":59,"meta":60,"style":60},"language-bash shiki shiki-themes material-theme-lighter fougere-pastel material-theme-palenight","npm install -D @fougere\u002Ftesting\n","npm","bash","",[17,62,63],{"__ignoreMap":60},[64,65,68,71,75,79],"span",{"class":66,"line":67},"line",1,[64,69,58],{"class":70},"sV8pK",[64,72,74],{"class":73},"sN-8n"," install",[64,76,78],{"class":77},"svHQO"," -D",[64,80,81],{"class":73}," @fougere\u002Ftesting\n",[54,83,86],{"className":56,"code":84,"filename":85,"language":59,"meta":60,"style":60},"pnpm add -D @fougere\u002Ftesting\n","pnpm",[17,87,88],{"__ignoreMap":60},[64,89,90,92,95,97],{"class":66,"line":67},[64,91,85],{"class":70},[64,93,94],{"class":73}," add",[64,96,78],{"class":77},[64,98,81],{"class":73},[54,100,103],{"className":56,"code":101,"filename":102,"language":59,"meta":60,"style":60},"bun add -d @fougere\u002Ftesting\n","bun",[17,104,105],{"__ignoreMap":60},[64,106,107,109,111,114],{"class":66,"line":67},[64,108,102],{"class":70},[64,110,94],{"class":73},[64,112,113],{"class":77}," -d",[64,115,81],{"class":73},[54,117,120],{"className":56,"code":118,"filename":119,"language":59,"meta":60,"style":60},"yarn add -D @fougere\u002Ftesting\n","yarn",[17,121,122],{"__ignoreMap":60},[64,123,124,126,128,130],{"class":66,"line":67},[64,125,119],{"class":70},[64,127,94],{"class":73},[64,129,78],{"class":77},[64,131,81],{"class":73},[54,133,137],{"className":134,"code":135,"language":136,"meta":60,"style":60},"language-ts shiki shiki-themes material-theme-lighter fougere-pastel material-theme-palenight","\u002F\u002F vitest.config.ts — the whole file\nimport { fougereTest } from '@fougere\u002Ftesting\u002Fvitest';\n\nexport default fougereTest();\n","ts",[17,138,139,145,179,186],{"__ignoreMap":60},[64,140,141],{"class":66,"line":67},[64,142,144],{"class":143},"skXKP","\u002F\u002F vitest.config.ts — the whole file\n",[64,146,148,152,156,160,163,166,170,173,176],{"class":66,"line":147},2,[64,149,151],{"class":150},"sK6XW","import",[64,153,155],{"class":154},"s15xx"," {",[64,157,159],{"class":158},"sPEhv"," fougereTest",[64,161,162],{"class":154}," }",[64,164,165],{"class":150}," from",[64,167,169],{"class":168},"sDDC1"," '",[64,171,172],{"class":73},"@fougere\u002Ftesting\u002Fvitest",[64,174,175],{"class":168},"'",[64,177,178],{"class":154},";\n",[64,180,182],{"class":66,"line":181},3,[64,183,185],{"emptyLinePlaceholder":184},true,"\n",[64,187,189,192,195,198,202],{"class":66,"line":188},4,[64,190,191],{"class":150},"export",[64,193,194],{"class":150}," default",[64,196,159],{"class":197},"s4mR9",[64,199,201],{"class":200},"srlTG","()",[64,203,178],{"class":154},[205,206,208],"h2",{"id":207},"where-a-test-sits-says-what-it-is-about","Where a test sits says what it is about",[54,210,215],{"className":211,"code":213,"language":214},[212],"language-text","fronds\u002Fcatalog\u002Ftests\u002Fpricing.test.ts    catalog is real, its neighbours are not\ntests\u002Fcontracts.test.ts                 every frond is real, together\n","text",[17,216,213],{"__ignoreMap":60},[13,218,219,220,223,224,227,228,231],{},"A directory is a declaration — the reading the scan already performs on ",[17,221,222],{},"entities\u002F"," and\n",[17,225,226],{},"handlers\u002F",". So ",[17,229,230],{},"testApp()"," takes no argument at all:",[54,233,235],{"className":134,"code":234,"language":136,"meta":60,"style":60},"await using app = await testApp();\n\nexpect(app.fronds.map((frond) => frond.name)).toEqual(['catalog']);\n",[17,236,237,259,263],{"__ignoreMap":60},[64,238,239,243,246,249,252,255,257],{"class":66,"line":67},[64,240,242],{"class":241},"s76I7","await using",[64,244,245],{"class":158}," app ",[64,247,248],{"class":154},"=",[64,250,251],{"class":150}," await",[64,253,254],{"class":197}," testApp",[64,256,201],{"class":200},[64,258,178],{"class":154},[64,260,261],{"class":66,"line":147},[64,262,185],{"emptyLinePlaceholder":184},[64,264,265,268,271,274,277,281,283,286,288,290,294,297,301,304,306,309,312,314,317,320,322,325,327,330],{"class":66,"line":181},[64,266,267],{"class":197},"expect",[64,269,270],{"class":200},"(",[64,272,273],{"class":158},"app",[64,275,276],{"class":154},".",[64,278,280],{"class":279},"sy9f4","fronds",[64,282,276],{"class":154},[64,284,285],{"class":197},"map",[64,287,270],{"class":200},[64,289,270],{"class":154},[64,291,293],{"class":292},"shDUQ","frond",[64,295,296],{"class":154},")",[64,298,300],{"class":299},"scTuO"," =>",[64,302,303],{"class":158}," frond",[64,305,276],{"class":154},[64,307,308],{"class":279},"name",[64,310,311],{"class":200},"))",[64,313,276],{"class":154},[64,315,316],{"class":197},"toEqual",[64,318,319],{"class":200},"([",[64,321,175],{"class":168},[64,323,324],{"class":73},"catalog",[64,326,175],{"class":168},[64,328,329],{"class":200},"])",[64,331,178],{"class":154},[13,333,334,335,338,339,342,343,345,346,349],{},"The project starts at the first ancestor holding a ",[17,336,337],{},"fougere.config.ts"," or a ",[17,340,341],{},"fronds\u002F",", and\nthe subject is the segment after ",[17,344,341],{},". A sub-directory below ",[17,347,348],{},"tests\u002F"," carries nothing,\nand neither does a test's title: what a test boots is decided by where the file sits, never by\nwords in its name.",[13,351,352,353,356,357,360,361,363,364,367,368,371,372,374],{},"Rows live in SQLite ",[17,354,355],{},":memory:"," — a real engine, so the DDL runs, the ",[17,358,359],{},"CHECK"," constraints\nexist and transactions are real, and each call gets a database of its own. That database is\nborn with the test, so ",[17,362,230],{}," writes its schema itself — the one kind of boot that does,\nwith ",[17,365,366],{},"migrating(storage.migrate)","; an app booted by hand in a test states the same. Stating ",[17,369,370],{},"root","\nor ",[17,373,280],{}," yourself wins over the position, the same precedence a config key has over a\nconvention everywhere else.",[205,376,378],{"id":377},"the-cases-come-from-the-entity","The cases come from the entity",[54,380,382],{"className":134,"code":381,"language":136,"meta":60,"style":60},"\u002F\u002F tests\u002Fcontracts.test.ts — the whole file\nimport { testApp, checkAll } from '@fougere\u002Ftesting';\n\ncheckAll(await testApp());\n",[17,383,384,389,415,419],{"__ignoreMap":60},[64,385,386],{"class":66,"line":67},[64,387,388],{"class":143},"\u002F\u002F tests\u002Fcontracts.test.ts — the whole file\n",[64,390,391,393,395,397,400,403,405,407,409,411,413],{"class":66,"line":147},[64,392,151],{"class":150},[64,394,155],{"class":154},[64,396,254],{"class":158},[64,398,399],{"class":154},",",[64,401,402],{"class":158}," checkAll",[64,404,162],{"class":154},[64,406,165],{"class":150},[64,408,169],{"class":168},[64,410,19],{"class":73},[64,412,175],{"class":168},[64,414,178],{"class":154},[64,416,417],{"class":66,"line":181},[64,418,185],{"emptyLinePlaceholder":184},[64,420,421,424,426,429,431,434],{"class":66,"line":188},[64,422,423],{"class":197},"checkAll",[64,425,270],{"class":200},[64,427,428],{"class":150},"await",[64,430,254],{"class":197},[64,432,433],{"class":200},"())",[64,435,178],{"class":154},[13,437,438,439,276],{},"It names no entity: the list comes from the scan. A list of imports is a second copy of\nwhat the project already declares, and it goes stale the day an entity is added — silently,\nbecause a missing test cannot fail. One entity at a time reads\n",[17,440,441],{},"checkContract(app, Product)",[54,443,446],{"className":444,"code":445,"language":214},[212],"✓ Product — the contract it declares\n  ✓ a valid body            ✓ sku shorter than min      ✓ cents below minimum\n  ✓ a key outside the contract  ✓ sku longer than max   ✓ cents above maximum\n  ✓ not an object at all    ✓ name absent               ✓ status outside the stated set\n  ✓ sku absent              ✓ name of the wrong type    ✓ createdAt supplied on an update\n",[17,447,445],{"__ignoreMap":60},[13,449,450,451,454,455,458,459,462,463,466,467,470],{},"Not one case is written. They are enumerated from five readings that already exist —\n",[17,452,453],{},"Visibility.input"," for what may come in, ",[17,456,457],{},"InputValidator.onAbsent"," for what is required,\n",[17,460,461],{},"Lifecycle.of(field).immutable()"," for patch mode, the ",[17,464,465],{},"shape"," for the bounds, and the key\noutside the contract. Change a ",[17,468,469],{},"min:"," in the entity and the cases follow.",[13,472,473,474,477],{},"A case carries the ",[24,475,476],{},"path"," of the field at fault and never the message: we know which\nfield must be refused because we are the ones who broke it, and naming the message would\nmake the list a second validator to keep in step by hand.",[13,479,480,483,484,487],{},[17,481,482],{},"checkOutput"," costs nothing to state — ",[17,485,486],{},"Visibility.output"," already answers it, so a field the\nboundary closes has no business in any response:",[54,489,491],{"className":134,"code":490,"language":136,"meta":60,"style":60},"password: writeOnly(text())   \u002F\u002F in, never out\n",[17,492,493],{"__ignoreMap":60},[64,494,495,499,502,505,507,509,511],{"class":66,"line":67},[64,496,498],{"class":497},"sWI7z","password",[64,500,501],{"class":154},":",[64,503,504],{"class":197}," writeOnly",[64,506,270],{"class":200},[64,508,214],{"class":197},[64,510,433],{"class":200},[64,512,513],{"class":143},"   \u002F\u002F in, never out\n",[515,516,518],"h3",{"id":517},"what-it-does-not-prove","What it does not prove",[13,520,521,522,525,526,528,529,532,533,540,541,544],{},"A test derived from ",[17,523,524],{},"Post"," can never say that ",[17,527,524],{}," is wrong. It proves the\n",[24,530,531],{},"realizations agree",". What must break when the declaration moves is elsewhere and\nalready built: ",[534,535,537],"a",{"href":536},"\u002Fdocs\u002Fdata\u002Fevolve",[17,538,539],{},"fougere migrate",". And business intent —\n",[43,542,543],{},"publishing sets the status to published"," — is always written by hand.",[205,546,548],{"id":547},"sampling-a-valid-body","Sampling a valid body",[54,550,552],{"className":134,"code":551,"language":136,"meta":60,"style":60},"sampleInput(Product)                          \u002F\u002F → { sku: 'gDXv8gBIU', name: '…', cents: 750868 }\nsampleInput(Product, { sku: 'ABC-01' })       \u002F\u002F what you impose, verbatim\nsampleInput(Product, {}, { seed: 7 })         \u002F\u002F pinned\n",[17,553,554,569,601],{"__ignoreMap":60},[64,555,556,559,561,564,566],{"class":66,"line":67},[64,557,558],{"class":197},"sampleInput",[64,560,270],{"class":200},[64,562,563],{"class":158},"Product",[64,565,296],{"class":200},[64,567,568],{"class":143},"                          \u002F\u002F → { sku: 'gDXv8gBIU', name: '…', cents: 750868 }\n",[64,570,571,573,575,577,579,581,585,587,589,592,594,596,598],{"class":66,"line":147},[64,572,558],{"class":197},[64,574,270],{"class":200},[64,576,563],{"class":158},[64,578,399],{"class":154},[64,580,155],{"class":154},[64,582,584],{"class":583},"sHtqg"," sku",[64,586,501],{"class":154},[64,588,169],{"class":168},[64,590,591],{"class":73},"ABC-01",[64,593,175],{"class":168},[64,595,162],{"class":154},[64,597,296],{"class":200},[64,599,600],{"class":143},"       \u002F\u002F what you impose, verbatim\n",[64,602,603,605,607,609,611,614,616,619,621,625,627,629],{"class":66,"line":181},[64,604,558],{"class":197},[64,606,270],{"class":200},[64,608,563],{"class":158},[64,610,399],{"class":154},[64,612,613],{"class":154}," {},",[64,615,155],{"class":154},[64,617,618],{"class":583}," seed",[64,620,501],{"class":154},[64,622,624],{"class":623},"s3dPA"," 7",[64,626,162],{"class":154},[64,628,296],{"class":200},[64,630,631],{"class":143},"         \u002F\u002F pinned\n",[13,633,634,635,27,637,640,641,644,645,648,649,648,652,648,655,658,659,662,663,666,667,669],{},"The value itself is not ours to invent: a ",[17,636,465],{},[24,638,639],{},"is"," JSON Schema, so\n",[17,642,643],{},"json-schema-faker"," honours ",[17,646,647],{},"minLength",", ",[17,650,651],{},"enum",[17,653,654],{},"format",[17,656,657],{},"pattern"," and ",[17,660,661],{},"items",". What is\nours is ",[43,664,665],{},"which"," fields belong in a body — ",[17,668,453],{},", the one reader of the boundary\nand lifecycle axes the facade and the form already stand on.",[13,671,672,673,676,677,680],{},"The seed defaults to a value derived from the entity name, so two runs agree and a failure\ncan be replayed. A ",[17,674,675],{},"ref()"," is ",[24,678,679],{},"refused by name"," rather than generated: it points at a row\nthat must exist, and a made-up id points at nothing.",[13,682,683],{},"The same function seeds a dev database and sets the scene for a browser scenario.",[205,685,687],{"id":686},"doubles","Doubles",[13,689,690,691,695],{},"Only what is already declared replaceable can be stood in for — a\n",[534,692,694],{"href":693},"\u002Fdocs\u002Fconcepts\u002Fport","port",". \"I need a mock here\" becomes a design signal rather than a\nreflex.",[54,697,699],{"className":134,"code":698,"language":136,"meta":60,"style":60},"await using app = await testApp({ stub: [Pricing] });\napp.stub(Pricing).total.mockReturnValue(4242);\n\nawait run({ address: 'product', op: 'quote' }, invocation);\n\nexpect(app.stub(Pricing).total).toHaveBeenCalledWith(1000);\n",[17,700,701,738,772,776,823,828],{"__ignoreMap":60},[64,702,703,705,707,709,711,713,715,718,721,723,726,729,732,734,736],{"class":66,"line":67},[64,704,242],{"class":241},[64,706,245],{"class":158},[64,708,248],{"class":154},[64,710,251],{"class":150},[64,712,254],{"class":197},[64,714,270],{"class":200},[64,716,717],{"class":154},"{",[64,719,720],{"class":583}," stub",[64,722,501],{"class":154},[64,724,725],{"class":200}," [",[64,727,728],{"class":158},"Pricing",[64,730,731],{"class":200},"]",[64,733,162],{"class":154},[64,735,296],{"class":200},[64,737,178],{"class":154},[64,739,740,742,744,747,749,751,753,755,758,760,763,765,768,770],{"class":66,"line":147},[64,741,273],{"class":158},[64,743,276],{"class":154},[64,745,746],{"class":197},"stub",[64,748,270],{"class":200},[64,750,728],{"class":158},[64,752,296],{"class":200},[64,754,276],{"class":154},[64,756,757],{"class":279},"total",[64,759,276],{"class":154},[64,761,762],{"class":197},"mockReturnValue",[64,764,270],{"class":200},[64,766,767],{"class":623},"4242",[64,769,296],{"class":200},[64,771,178],{"class":154},[64,773,774],{"class":66,"line":181},[64,775,185],{"emptyLinePlaceholder":184},[64,777,778,780,783,785,787,790,792,794,797,799,801,804,806,808,811,813,816,819,821],{"class":66,"line":188},[64,779,428],{"class":150},[64,781,782],{"class":197}," run",[64,784,270],{"class":200},[64,786,717],{"class":154},[64,788,789],{"class":583}," address",[64,791,501],{"class":154},[64,793,169],{"class":168},[64,795,796],{"class":73},"product",[64,798,175],{"class":168},[64,800,399],{"class":154},[64,802,803],{"class":583}," op",[64,805,501],{"class":154},[64,807,169],{"class":168},[64,809,810],{"class":73},"quote",[64,812,175],{"class":168},[64,814,815],{"class":154}," },",[64,817,818],{"class":158}," invocation",[64,820,296],{"class":200},[64,822,178],{"class":154},[64,824,826],{"class":66,"line":825},5,[64,827,185],{"emptyLinePlaceholder":184},[64,829,831,833,835,837,839,841,843,845,847,849,851,853,855,858,860,863,865],{"class":66,"line":830},6,[64,832,267],{"class":197},[64,834,270],{"class":200},[64,836,273],{"class":158},[64,838,276],{"class":154},[64,840,746],{"class":197},[64,842,270],{"class":200},[64,844,728],{"class":158},[64,846,296],{"class":200},[64,848,276],{"class":154},[64,850,757],{"class":279},[64,852,296],{"class":200},[64,854,276],{"class":154},[64,856,857],{"class":197},"toHaveBeenCalledWith",[64,859,270],{"class":200},[64,861,862],{"class":623},"1000",[64,864,296],{"class":200},[64,866,178],{"class":154},[13,868,869,870,873,874,877],{},"The double is ",[24,871,872],{},"proposed, not written",": its methods are read from the port's prototype, so\nit carries exactly what the port carries and gains a new one the day the port does. What\nit ",[43,875,876],{},"returns"," is yours to state — a service's return type is a bare TypeScript type, erased\nat runtime, with no declared fields to build from. That is the line the whole package sits\non: what Fougere's vocabulary declares can be derived, arbitrary code cannot.",[13,879,880,881,884],{},"A port nobody answers under is refused by name, for the reason ",[17,882,883],{},"ports:"," refuses a key that\nmatched nothing.",[13,886,887,888,891,892,276],{},"Outside an app — a unit test of one class — ",[17,889,890],{},"stubOf(Pricing)"," builds the same double on its own:\nevery method of the port is a ",[17,893,894],{},"vi.fn()",[54,896,898],{"className":134,"code":897,"language":136,"meta":60,"style":60},"import { stubOf } from '@fougere\u002Ftesting';\n\nconst pricing = stubOf\u003CPricing>(Pricing);\npricing.total.mockReturnValue(4242);\nconst quote = new QuoteService(pricing as unknown as Pricing);\n",[17,899,900,921,925,954,975],{"__ignoreMap":60},[64,901,902,904,906,909,911,913,915,917,919],{"class":66,"line":67},[64,903,151],{"class":150},[64,905,155],{"class":154},[64,907,908],{"class":158}," stubOf",[64,910,162],{"class":154},[64,912,165],{"class":150},[64,914,169],{"class":168},[64,916,19],{"class":73},[64,918,175],{"class":168},[64,920,178],{"class":154},[64,922,923],{"class":66,"line":147},[64,924,185],{"emptyLinePlaceholder":184},[64,926,927,930,933,935,937,940,943,946,948,950,952],{"class":66,"line":181},[64,928,929],{"class":241},"const",[64,931,932],{"class":158}," pricing ",[64,934,248],{"class":154},[64,936,908],{"class":197},[64,938,939],{"class":154},"\u003C",[64,941,728],{"class":942},"sBZYL",[64,944,945],{"class":154},">",[64,947,270],{"class":200},[64,949,728],{"class":158},[64,951,296],{"class":200},[64,953,178],{"class":154},[64,955,956,959,961,963,965,967,969,971,973],{"class":66,"line":188},[64,957,958],{"class":158},"pricing",[64,960,276],{"class":154},[64,962,757],{"class":279},[64,964,276],{"class":154},[64,966,762],{"class":197},[64,968,270],{"class":200},[64,970,767],{"class":623},[64,972,296],{"class":200},[64,974,178],{"class":154},[64,976,977,979,982,984,987,991,993,996,999,1002,1005,1008,1010],{"class":66,"line":825},[64,978,929],{"class":241},[64,980,981],{"class":158}," quote ",[64,983,248],{"class":154},[64,985,986],{"class":154}," new",[64,988,990],{"class":989},"sgjsB"," QuoteService",[64,992,270],{"class":200},[64,994,995],{"class":158},"pricing ",[64,997,998],{"class":150},"as",[64,1000,1001],{"class":942}," unknown",[64,1003,1004],{"class":150}," as",[64,1006,1007],{"class":942}," Pricing",[64,1009,296],{"class":200},[64,1011,178],{"class":154},[13,1013,1014,1015,1018],{},"Nothing can stand in for what a handler fetches itself — a ",[17,1016,1017],{},"fetch",", a library imported at\nthe top of the file, the clock. Fougere resolves by the signature, so it replaces only\nwhat the signature declares, and the model's answer for an outside call is already to make\nit a port.",[205,1020,1022],{"id":1021},"the-facades-agree","The facades agree",[54,1024,1026],{"className":134,"code":1025,"language":136,"meta":60,"style":60},"checkDoors(app, Product);   \u002F\u002F local · REST · GraphQL · RPC\n",[17,1027,1028],{"__ignoreMap":60},[64,1029,1030,1033,1035,1037,1039,1042,1044,1047],{"class":66,"line":67},[64,1031,1032],{"class":197},"checkDoors",[64,1034,270],{"class":200},[64,1036,273],{"class":158},[64,1038,399],{"class":154},[64,1040,1041],{"class":158}," Product",[64,1043,296],{"class":200},[64,1045,1046],{"class":154},";",[64,1048,1049],{"class":143},"   \u002F\u002F local · REST · GraphQL · RPC\n",[13,1051,1052],{},"The five CRUD operations, reads and writes. A write creates a different row at each facade,\nso what is compared is what the caller SENT — comparing values would compare clocks.",[13,1054,1055],{},"REST, GraphQL and RPC are meant to be three doors onto one contract. This is what checks it, on\nthe rows and on the refusals both — a refusal is\nwhere facades diverge most, and where each is most tempted to answer in its own words.",[13,1057,1058,1059,1062],{},"Each facade's envelope is taken off before comparing: they wrap differently by construction,\nand comparing wrappers would compare protocols. The GraphQL field is not recomputed but\n",[24,1060,1061],{},"asked of the schema"," — a list is the field whose type is the entity's list type, a find\nis the one of the entity's own type that takes an id.",[13,1064,1065,1066,1069,1070,1073,1074,648,1077,1080,1081,1084,1085,1088],{},"For a handler-specific invariant, ",[17,1067,1068],{},"checkDoorContract(app, Entity, cases)"," runs the same\nhand-written cases through all four facades. Fougere uses it to pin optional-input semantics:\nomitted ",[17,1071,1072],{},"foo?: T"," arrives as ",[17,1075,1076],{},"undefined",[17,1078,1079],{},"foo: T | null"," keeps explicit ",[17,1082,1083],{},"null",", and\n",[17,1086,1087],{},"foo?: T | null"," keeps those two states distinct.",[205,1090,1092],{"id":1091},"facts","Facts",[54,1094,1096],{"className":134,"code":1095,"language":136,"meta":60,"style":60},"await run({ address: 'post', op: 'publish' }, invocation);\n\nexpect(app.announced(PostPublished)).toMatchObject([{ id, title }]);\n",[17,1097,1098,1140,1144],{"__ignoreMap":60},[64,1099,1100,1102,1104,1106,1108,1110,1112,1114,1117,1119,1121,1123,1125,1127,1130,1132,1134,1136,1138],{"class":66,"line":67},[64,1101,428],{"class":150},[64,1103,782],{"class":197},[64,1105,270],{"class":200},[64,1107,717],{"class":154},[64,1109,789],{"class":583},[64,1111,501],{"class":154},[64,1113,169],{"class":168},[64,1115,1116],{"class":73},"post",[64,1118,175],{"class":168},[64,1120,399],{"class":154},[64,1122,803],{"class":583},[64,1124,501],{"class":154},[64,1126,169],{"class":168},[64,1128,1129],{"class":73},"publish",[64,1131,175],{"class":168},[64,1133,815],{"class":154},[64,1135,818],{"class":158},[64,1137,296],{"class":200},[64,1139,178],{"class":154},[64,1141,1142],{"class":66,"line":147},[64,1143,185],{"emptyLinePlaceholder":184},[64,1145,1146,1148,1150,1152,1154,1157,1159,1162,1164,1166,1169,1171,1173,1176,1178,1181,1184,1186],{"class":66,"line":181},[64,1147,267],{"class":197},[64,1149,270],{"class":200},[64,1151,273],{"class":158},[64,1153,276],{"class":154},[64,1155,1156],{"class":197},"announced",[64,1158,270],{"class":200},[64,1160,1161],{"class":158},"PostPublished",[64,1163,311],{"class":200},[64,1165,276],{"class":154},[64,1167,1168],{"class":197},"toMatchObject",[64,1170,319],{"class":200},[64,1172,717],{"class":154},[64,1174,1175],{"class":158}," id",[64,1177,399],{"class":154},[64,1179,1180],{"class":158}," title ",[64,1182,1183],{"class":154},"}",[64,1185,329],{"class":200},[64,1187,178],{"class":154},[13,1189,1190,1191,1194,1195,1198,1199,1202],{},"Watching costs nothing: ",[17,1192,1193],{},"Emissions.announce"," hands every fact to the carrier, so a test\nsits in the carrier's seat and adds no second dispatcher — the one thing ",[17,1196,1197],{},"Emissions","\nrefuses to become. A fact travels under its registration key (",[17,1200,1201],{},"postPublished","), and both\nspellings are accepted.",[13,1204,1205,1206,1209],{},"Its dual needed nothing at all — ",[17,1207,1208],{},"app.deliver"," is already the carrier's facade, and it waits\nfor every subscriber and rejects if one refuses:",[54,1211,1213],{"className":134,"code":1212,"language":136,"meta":60,"style":60},"await app.deliver('postPublished', { id: 'p1', title: 'Delivered', at: … });\n",[17,1214,1215],{"__ignoreMap":60},[64,1216,1217,1219,1222,1224,1227,1229,1231,1233,1235,1237,1239,1241,1243,1245,1248,1250,1252,1255,1257,1259,1262,1264,1266,1269,1271,1274,1276,1278],{"class":66,"line":67},[64,1218,428],{"class":150},[64,1220,1221],{"class":158}," app",[64,1223,276],{"class":154},[64,1225,1226],{"class":197},"deliver",[64,1228,270],{"class":200},[64,1230,175],{"class":168},[64,1232,1201],{"class":73},[64,1234,175],{"class":168},[64,1236,399],{"class":154},[64,1238,155],{"class":154},[64,1240,1175],{"class":583},[64,1242,501],{"class":154},[64,1244,169],{"class":168},[64,1246,1247],{"class":73},"p1",[64,1249,175],{"class":168},[64,1251,399],{"class":154},[64,1253,1254],{"class":583}," title",[64,1256,501],{"class":154},[64,1258,169],{"class":168},[64,1260,1261],{"class":73},"Delivered",[64,1263,175],{"class":168},[64,1265,399],{"class":154},[64,1267,1268],{"class":583}," at",[64,1270,501],{"class":154},[64,1272,1273],{"class":158}," … ",[64,1275,1183],{"class":154},[64,1277,296],{"class":200},[64,1279,178],{"class":154},[205,1281,1283],{"id":1282},"drift-between-fronds","Drift between fronds",[13,1285,1286,1287,1290],{},"The code is identical in one process and split — but across repositories one side may have aged. ",[17,1288,1289],{},"fougere sync"," wrote the consumer's copy three weeks ago, the\nproducer moved on, and it still compiles.",[54,1292,1294],{"className":134,"code":1293,"language":136,"meta":60,"style":60},"const drift = driftOf(mine, theirs, 'blog');\n\nexplain(drift);\n\u002F\u002F blog.post — gone: publish\n\u002F\u002F blog.post — title: its bounds moved\n\u002F\u002F postPublished — + authorId (required) → re-sync and deploy the readers, THEN the sender\n",[17,1295,1296,1331,1335,1349,1354,1359],{"__ignoreMap":60},[64,1297,1298,1300,1303,1305,1308,1310,1313,1315,1318,1320,1322,1325,1327,1329],{"class":66,"line":67},[64,1299,929],{"class":241},[64,1301,1302],{"class":158}," drift ",[64,1304,248],{"class":154},[64,1306,1307],{"class":197}," driftOf",[64,1309,270],{"class":200},[64,1311,1312],{"class":158},"mine",[64,1314,399],{"class":154},[64,1316,1317],{"class":158}," theirs",[64,1319,399],{"class":154},[64,1321,169],{"class":168},[64,1323,1324],{"class":73},"blog",[64,1326,175],{"class":168},[64,1328,296],{"class":200},[64,1330,178],{"class":154},[64,1332,1333],{"class":66,"line":147},[64,1334,185],{"emptyLinePlaceholder":184},[64,1336,1337,1340,1342,1345,1347],{"class":66,"line":181},[64,1338,1339],{"class":197},"explain",[64,1341,270],{"class":200},[64,1343,1344],{"class":158},"drift",[64,1346,296],{"class":200},[64,1348,178],{"class":154},[64,1350,1351],{"class":66,"line":188},[64,1352,1353],{"class":143},"\u002F\u002F blog.post — gone: publish\n",[64,1355,1356],{"class":66,"line":825},[64,1357,1358],{"class":143},"\u002F\u002F blog.post — title: its bounds moved\n",[64,1360,1361],{"class":66,"line":830},[64,1362,1363],{"class":143},"\u002F\u002F postPublished — + authorId (required) → re-sync and deploy the readers, THEN the sender\n",[13,1365,1366,1367,1370,1371,1374,1375,1378],{},"Both cards come from ",[17,1368,1369],{},"rpc.discover",", and ",[17,1372,1373],{},"diff"," names what separates them. Read in one\ndirection on purpose: a producer serving ",[43,1376,1377],{},"more"," than the consumer knows is not drift, it\nis a producer that moved forward without breaking anyone.",[13,1380,1381],{},"On facts the line says the order out loud, because a fact is validated strictly: a reader\nthat has not been re-synced refuses what the sender now announces.",[205,1383,1385],{"id":1384},"the-browser","The browser",[13,1387,1388],{},"What no test in one process can show: a form that states no rule of its own.",[54,1390,1392],{"className":134,"code":1391,"language":136,"meta":60,"style":60},"formFieldsOf(Product, 'product')\n",[17,1393,1394],{"__ignoreMap":60},[64,1395,1396,1399,1401,1403,1405,1407,1409,1411],{"class":66,"line":67},[64,1397,1398],{"class":197},"formFieldsOf",[64,1400,270],{"class":200},[64,1402,563],{"class":158},[64,1404,399],{"class":154},[64,1406,169],{"class":168},[64,1408,796],{"class":73},[64,1410,175],{"class":168},[64,1412,1413],{"class":200},")\n",[54,1415,1419],{"className":1416,"code":1417,"language":1418,"meta":60,"style":60},"language-html shiki shiki-themes material-theme-lighter fougere-pastel material-theme-palenight","\u003Cinput id=\"sku\" name=\"sku\" type=\"text\" required minlength=\"3\" maxlength=\"12\">\n","html",[17,1420,1421],{"__ignoreMap":60},[64,1422,1423,1425,1429,1432,1434,1437,1440,1442,1445,1447,1449,1451,1453,1456,1458,1460,1462,1464,1467,1470,1472,1474,1477,1479,1482,1484,1486,1489,1491],{"class":66,"line":67},[64,1424,939],{"class":154},[64,1426,1428],{"class":1427},"s687E","input",[64,1430,1175],{"class":1431},"s8ClO",[64,1433,248],{"class":154},[64,1435,1436],{"class":168},"\"",[64,1438,1439],{"class":73},"sku",[64,1441,1436],{"class":168},[64,1443,1444],{"class":1431}," name",[64,1446,248],{"class":154},[64,1448,1436],{"class":168},[64,1450,1439],{"class":73},[64,1452,1436],{"class":168},[64,1454,1455],{"class":1431}," type",[64,1457,248],{"class":154},[64,1459,1436],{"class":168},[64,1461,214],{"class":73},[64,1463,1436],{"class":168},[64,1465,1466],{"class":1431}," required",[64,1468,1469],{"class":1431}," minlength",[64,1471,248],{"class":154},[64,1473,1436],{"class":168},[64,1475,1476],{"class":73},"3",[64,1478,1436],{"class":168},[64,1480,1481],{"class":1431}," maxlength",[64,1483,248],{"class":154},[64,1485,1436],{"class":168},[64,1487,1488],{"class":73},"12",[64,1490,1436],{"class":168},[64,1492,1493],{"class":154},">\n",[13,1495,1496,1497,1499,1500,1502,1503,1506],{},"Membership comes from ",[17,1498,453],{},", requiredness from the lifecycle axis, and the bounds\nfrom the shape — under the names the browser already enforces. So the page contains no\nvalidation code at all: the browser refuses a two-character ",[17,1501,1439],{},", and the same body sent\nstraight to the facade is refused by the validator. ",[43,1504,1505],{},"Local validator = remote validator"," is watched here\nrather than argued; every other rung can only simulate it inside one process.",[13,1508,1509,1510,1513,1514,1517,1518,648,1521,276],{},"Playwright drives it and starts the server itself (",[17,1511,1512],{},"webServer"," in ",[17,1515,1516],{},"playwright.config.ts",").\nA worked example: ",[17,1519,1520],{},"demos\u002Ftest-gradient",[17,1522,1523],{},"pnpm e2e",[1525,1526],"demo",{"name":1527},"test-gradient",[205,1529,1531],{"id":1530},"a-frozen-clock","A frozen clock",[13,1533,1534,648,1537,658,1540,1543,1544,1547,1548,1551],{},[17,1535,1536],{},"created()",[17,1538,1539],{},"updated()",[17,1541,1542],{},"create: 'now'"," are realized in one place —\n",[17,1545,1546],{},"applyCreate","\u002F",[17,1549,1550],{},"applyUpdate"," — which reads the system clock at the write. Freezing time the way\nany project does is therefore enough:",[54,1553,1555],{"className":134,"code":1554,"language":136,"meta":60,"style":60},"vi.useFakeTimers({ toFake: ['Date'] });\nvi.setSystemTime(new Date('2026-01-02T03:04:05Z'));\n",[17,1556,1557,1593],{"__ignoreMap":60},[64,1558,1559,1562,1564,1567,1569,1571,1574,1576,1578,1580,1583,1585,1587,1589,1591],{"class":66,"line":67},[64,1560,1561],{"class":158},"vi",[64,1563,276],{"class":154},[64,1565,1566],{"class":197},"useFakeTimers",[64,1568,270],{"class":200},[64,1570,717],{"class":154},[64,1572,1573],{"class":583}," toFake",[64,1575,501],{"class":154},[64,1577,725],{"class":200},[64,1579,175],{"class":168},[64,1581,1582],{"class":73},"Date",[64,1584,175],{"class":168},[64,1586,731],{"class":200},[64,1588,162],{"class":154},[64,1590,296],{"class":200},[64,1592,178],{"class":154},[64,1594,1595,1597,1599,1602,1604,1607,1610,1612,1614,1617,1619,1621],{"class":66,"line":147},[64,1596,1561],{"class":158},[64,1598,276],{"class":154},[64,1600,1601],{"class":197},"setSystemTime",[64,1603,270],{"class":200},[64,1605,1606],{"class":154},"new",[64,1608,1609],{"class":989}," Date",[64,1611,270],{"class":200},[64,1613,175],{"class":168},[64,1615,1616],{"class":73},"2026-01-02T03:04:05Z",[64,1618,175],{"class":168},[64,1620,311],{"class":200},[64,1622,178],{"class":154},[13,1624,1625,1628,1629,1632],{},[17,1626,1627],{},"toFake: ['Date']"," leaves ",[17,1630,1631],{},"setTimeout"," and promises running: only the dates hold still.",[205,1634,1636],{"id":1635},"load","Load",[54,1638,1640],{"className":134,"code":1639,"language":136,"meta":60,"style":60},"\u002F\u002F scripts\u002Fload.ts\nimport { writeFileSync } from 'node:fs';\nimport { testApp, loadScript } from '@fougere\u002Ftesting';\n\nconst app = await testApp();\nwriteFileSync('load.js', loadScript(app, { facade: 'http:\u002F\u002F127.0.0.1:3000\u002F_fougere\u002Fcall' }));\nawait app.dispose();\n",[17,1641,1642,1647,1669,1694,1698,1714,1758],{"__ignoreMap":60},[64,1643,1644],{"class":66,"line":67},[64,1645,1646],{"class":143},"\u002F\u002F scripts\u002Fload.ts\n",[64,1648,1649,1651,1653,1656,1658,1660,1662,1665,1667],{"class":66,"line":147},[64,1650,151],{"class":150},[64,1652,155],{"class":154},[64,1654,1655],{"class":158}," writeFileSync",[64,1657,162],{"class":154},[64,1659,165],{"class":150},[64,1661,169],{"class":168},[64,1663,1664],{"class":73},"node:fs",[64,1666,175],{"class":168},[64,1668,178],{"class":154},[64,1670,1671,1673,1675,1677,1679,1682,1684,1686,1688,1690,1692],{"class":66,"line":181},[64,1672,151],{"class":150},[64,1674,155],{"class":154},[64,1676,254],{"class":158},[64,1678,399],{"class":154},[64,1680,1681],{"class":158}," loadScript",[64,1683,162],{"class":154},[64,1685,165],{"class":150},[64,1687,169],{"class":168},[64,1689,19],{"class":73},[64,1691,175],{"class":168},[64,1693,178],{"class":154},[64,1695,1696],{"class":66,"line":188},[64,1697,185],{"emptyLinePlaceholder":184},[64,1699,1700,1702,1704,1706,1708,1710,1712],{"class":66,"line":825},[64,1701,929],{"class":241},[64,1703,245],{"class":158},[64,1705,248],{"class":154},[64,1707,251],{"class":150},[64,1709,254],{"class":197},[64,1711,201],{"class":200},[64,1713,178],{"class":154},[64,1715,1716,1719,1721,1723,1726,1728,1730,1732,1734,1736,1738,1740,1743,1745,1747,1750,1752,1754,1756],{"class":66,"line":830},[64,1717,1718],{"class":197},"writeFileSync",[64,1720,270],{"class":200},[64,1722,175],{"class":168},[64,1724,1725],{"class":73},"load.js",[64,1727,175],{"class":168},[64,1729,399],{"class":154},[64,1731,1681],{"class":197},[64,1733,270],{"class":200},[64,1735,273],{"class":158},[64,1737,399],{"class":154},[64,1739,155],{"class":154},[64,1741,1742],{"class":583}," facade",[64,1744,501],{"class":154},[64,1746,169],{"class":168},[64,1748,1749],{"class":73},"http:\u002F\u002F127.0.0.1:3000\u002F_fougere\u002Fcall",[64,1751,175],{"class":168},[64,1753,162],{"class":154},[64,1755,311],{"class":200},[64,1757,178],{"class":154},[64,1759,1761,1763,1765,1767,1770,1772],{"class":66,"line":1760},7,[64,1762,428],{"class":150},[64,1764,1221],{"class":158},[64,1766,276],{"class":154},[64,1768,1769],{"class":197},"dispose",[64,1771,201],{"class":200},[64,1773,178],{"class":154},[54,1775,1777],{"className":56,"code":1776,"language":59,"meta":60,"style":60},"k6 run load.js\n",[17,1778,1779],{"__ignoreMap":60},[64,1780,1781,1784,1786],{"class":66,"line":67},[64,1782,1783],{"class":70},"k6",[64,1785,782],{"class":73},[64,1787,1788],{"class":73}," load.js\n",[13,1790,1791,1792,1795,1796,1799],{},"The generated scenario covers ",[24,1793,1794],{},"every"," operation the app serves, with a valid body for\neach, and its JSON-RPC envelope comes from ",[17,1797,1798],{},"frameCall"," rather than a hand copy that will\ngo on claiming to be JSON-RPC the day the format moves.",[13,1801,1802,1803,1806],{},"What stays yours: the weights, the stages and the thresholds. The scan knows which\noperations exist; it knows nothing about the traffic they receive. An operation given\n",[17,1804,1805],{},"weight: 0"," becomes a decision visible in the file instead of an omission nobody can see.",[13,1808,1809],{},"Regenerate rather than patch.",[205,1811,1813],{"id":1812},"what-a-call-cost","What a call cost",[13,1815,1816],{},"A performance test asserts a number of milliseconds and breaks on someone else's laptop.\nThese two ask about structure instead, and structure does not change with the machine.",[54,1818,1820],{"className":134,"code":1819,"language":136,"meta":60,"style":60},"const ran = await statementsOf(() => facade.list());\nexpect(ran).toHaveLength(1);          \u002F\u002F not one per row\n",[17,1821,1822,1853],{"__ignoreMap":60},[64,1823,1824,1826,1829,1831,1833,1836,1838,1840,1842,1844,1846,1849,1851],{"class":66,"line":67},[64,1825,929],{"class":241},[64,1827,1828],{"class":158}," ran ",[64,1830,248],{"class":154},[64,1832,251],{"class":150},[64,1834,1835],{"class":197}," statementsOf",[64,1837,270],{"class":200},[64,1839,201],{"class":154},[64,1841,300],{"class":299},[64,1843,1742],{"class":158},[64,1845,276],{"class":154},[64,1847,1848],{"class":197},"list",[64,1850,433],{"class":200},[64,1852,178],{"class":154},[64,1854,1855,1857,1859,1862,1864,1866,1869,1871,1874,1876,1878],{"class":66,"line":147},[64,1856,267],{"class":197},[64,1858,270],{"class":200},[64,1860,1861],{"class":158},"ran",[64,1863,296],{"class":200},[64,1865,276],{"class":154},[64,1867,1868],{"class":197},"toHaveLength",[64,1870,270],{"class":200},[64,1872,1873],{"class":623},"1",[64,1875,296],{"class":200},[64,1877,1046],{"class":154},[64,1879,1880],{"class":143},"          \u002F\u002F not one per row\n",[13,1882,1883,1886,1887,1890,1891,1894,1895,1898],{},[17,1884,1885],{},"statementsOf"," returns every statement the block ran, in order. ",[17,1888,1889],{},"testApp"," boots on real\nSQLite, so this is what the handler actually asked the database — and one query per row is\nthe shape of an N+1. The facade hands a presenter the whole ",[24,1892,1893],{},"page"," precisely so a lookup\ncan be done once; nothing refuses ",[17,1896,1897],{},"Promise.all(rows.map(…))"," inside the field body, and this\nis what notices.",[13,1900,1901],{},"Its dual reads the call itself:",[54,1903,1905],{"className":134,"code":1904,"language":136,"meta":60,"style":60},"const [op] = await spansOf(app, () => facade.checkout());\nexpect(op.selfMs).toBeLessThan(0.1 * op.ms);   \u002F\u002F it delegates, it does not work\n",[17,1906,1907,1948],{"__ignoreMap":60},[64,1908,1909,1911,1913,1916,1918,1921,1923,1926,1928,1930,1932,1935,1937,1939,1941,1944,1946],{"class":66,"line":67},[64,1910,929],{"class":241},[64,1912,725],{"class":154},[64,1914,1915],{"class":158},"op",[64,1917,731],{"class":154},[64,1919,1920],{"class":154}," =",[64,1922,251],{"class":150},[64,1924,1925],{"class":197}," spansOf",[64,1927,270],{"class":200},[64,1929,273],{"class":158},[64,1931,399],{"class":154},[64,1933,1934],{"class":154}," ()",[64,1936,300],{"class":299},[64,1938,1742],{"class":158},[64,1940,276],{"class":154},[64,1942,1943],{"class":197},"checkout",[64,1945,433],{"class":200},[64,1947,178],{"class":154},[64,1949,1950,1952,1954,1956,1958,1961,1963,1965,1968,1970,1973,1976,1978,1980,1983,1985,1987],{"class":66,"line":147},[64,1951,267],{"class":197},[64,1953,270],{"class":200},[64,1955,1915],{"class":158},[64,1957,276],{"class":154},[64,1959,1960],{"class":279},"selfMs",[64,1962,296],{"class":200},[64,1964,276],{"class":154},[64,1966,1967],{"class":197},"toBeLessThan",[64,1969,270],{"class":200},[64,1971,1972],{"class":623},"0.1",[64,1974,1975],{"class":154}," *",[64,1977,803],{"class":158},[64,1979,276],{"class":154},[64,1981,1982],{"class":279},"ms",[64,1984,296],{"class":200},[64,1986,1046],{"class":154},[64,1988,1989],{"class":143},"   \u002F\u002F it delegates, it does not work\n",[13,1991,1992,1994],{},[17,1993,1960],{}," is the duration minus what ran under it, so the assertion states that an op\ndelegates rather than works. A ratio survives a slow machine; a threshold in milliseconds\ntests the machine.",[1996,1997,1998],"note",{},[13,1999,2000,2002,2003,658,2006,2002,2009,2012,2013,2016],{},[17,2001,1885],{}," needs ",[17,2004,2005],{},"@fougere\u002Fadapter-sql",[17,2007,2008],{},"spansOf",[17,2010,2011],{},"@fougere\u002Fobservability",".\nBoth ",[24,2014,2015],{},"refuse"," when it is missing rather than returning nothing: zero is what a passing\nassertion looks like, and a test that cannot fail is worse than no test.",[2018,2019,2020],"style",{},"html pre.shiki code .sV8pK, html code.shiki .sV8pK{--shiki-light:#E2931D;--shiki-default:#C9B6EA;--shiki-dark:#FFCB6B}html pre.shiki code .sN-8n, html code.shiki .sN-8n{--shiki-light:#91B859;--shiki-default:#EE9F6B;--shiki-dark:#C3E88D}html pre.shiki code .svHQO, html code.shiki .svHQO{--shiki-light:#91B859;--shiki-default:#8FCF86;--shiki-dark:#C3E88D}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 .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 .s15xx, html code.shiki .s15xx{--shiki-light:#39ADB5;--shiki-default:#A3B0A5;--shiki-dark:#89DDFF}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 .s4mR9, html code.shiki .s4mR9{--shiki-light:#6182B8;--shiki-default:#C9B6EA;--shiki-dark:#82AAFF}html pre.shiki code .srlTG, html code.shiki .srlTG{--shiki-light:#90A4AE;--shiki-default:#A3B0A5;--shiki-dark:#BABED8}html pre.shiki code .s76I7, html code.shiki .s76I7{--shiki-light:#9C3EDA;--shiki-default:#8FCF86;--shiki-dark:#C792EA}html pre.shiki code .sy9f4, html code.shiki .sy9f4{--shiki-light:#90A4AE;--shiki-default:#93CFC0;--shiki-dark:#BABED8}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 .scTuO, html code.shiki .scTuO{--shiki-light:#9C3EDA;--shiki-default:#A3B0A5;--shiki-dark:#C792EA}html pre.shiki code .sWI7z, html code.shiki .sWI7z{--shiki-light:#E2931D;--shiki-default:#93CFC0;--shiki-dark:#FFCB6B}html pre.shiki code .sHtqg, html code.shiki .sHtqg{--shiki-light:#E53935;--shiki-default:#93CFC0;--shiki-dark:#F07178}html pre.shiki code .s3dPA, html code.shiki .s3dPA{--shiki-light:#F76D47;--shiki-default:#EE9F6B;--shiki-dark:#F78C6C}html pre.shiki code .sBZYL, html code.shiki .sBZYL{--shiki-light:#E2931D;--shiki-default:#EFCD8F;--shiki-dark:#FFCB6B}html pre.shiki code .sgjsB, html code.shiki .sgjsB{--shiki-light:#6182B8;--shiki-default:#EFCD8F;--shiki-dark:#82AAFF}html pre.shiki code .s687E, html code.shiki .s687E{--shiki-light:#E53935;--shiki-default:#8FCF86;--shiki-dark:#F07178}html pre.shiki code .s8ClO, html code.shiki .s8ClO{--shiki-light:#9C3EDA;--shiki-default:#93CFC0;--shiki-dark:#C792EA}",{"title":60,"searchDepth":147,"depth":147,"links":2022},[2023,2024,2027,2028,2029,2030,2031,2032,2033,2034,2035],{"id":207,"depth":147,"text":208},{"id":377,"depth":147,"text":378,"children":2025},[2026],{"id":517,"depth":181,"text":518},{"id":547,"depth":147,"text":548},{"id":686,"depth":147,"text":687},{"id":1021,"depth":147,"text":1022},{"id":1091,"depth":147,"text":1092},{"id":1282,"depth":147,"text":1283},{"id":1384,"depth":147,"text":1385},{"id":1530,"depth":147,"text":1531},{"id":1635,"depth":147,"text":1636},{"id":1812,"depth":147,"text":1813},"Cases derived from an entity, doubles from a port, and the four rungs a test runs at.","md",[1889,2039,423],"stubOf","task",{},"\u002Fdocs\u002Frun\u002Ftest",{"title":8,"description":2036},"docs\u002F6.run\u002F6.test",null,[2047,694],"entity","guVooKoI1eQilTQMDTa1vqjC7iTmoBH9YNOpOVXCuWM",[2050,2053,2056,2059,2062,2065,2068,2070,2073,2077,2083,2087,2091,2095,2098,2102,2106,2111,2115,2119,2124,2128,2133,2137,2141,2145,2149,2153,2157,2161,2163,2167,2171,2175,2179,2183,2187,2190,2193,2196,2199,2202,2205,2208,2211,2214,2217],{"path":2051,"title":2052,"uses":2045},"\u002Fdocs\u002Fconcepts\u002Fentity","Entity",{"path":2054,"title":2055,"uses":2045},"\u002Fdocs\u002Fconcepts\u002Fhandler","Handler",{"path":2057,"title":2058,"uses":2045},"\u002Fdocs\u002Fconcepts\u002Frepository","Repository",{"path":2060,"title":2061,"uses":2045},"\u002Fdocs\u002Fconcepts\u002Ffrond","Frond",{"path":2063,"title":2064,"uses":2045},"\u002Fdocs\u002Fconcepts\u002Ffacade","Facade",{"path":2066,"title":2067,"uses":2045},"\u002Fdocs\u002Fconcepts\u002Ffact","Fact",{"path":693,"title":2069,"uses":2045},"Port",{"path":2071,"title":2072,"uses":2045},"\u002Fdocs\u002Fconcepts\u002Fconfiguration","Configuration",{"path":2074,"title":2075,"uses":2076},"\u002Fdocs\u002Faccess\u002Fauthentication","Authentication",[694,293],{"path":2078,"title":2079,"uses":2080},"\u002Fdocs\u002Faccess\u002Fstate","Keep a caller's state",[2081,2082],"configuration","handler",{"path":2084,"title":2085,"uses":2086},"\u002Fdocs\u002Fdata\u002Fsql","SQLite or Postgres",[2047,2081],{"path":2088,"title":2089,"uses":2090},"\u002Fdocs\u002Fdata\u002Fseveral-databases","Several databases",[2081,2047],{"path":2092,"title":2093,"uses":2094},"\u002Fdocs\u002Fdata\u002Fcomputed-field","A computed field",[2047,694],{"path":536,"title":2096,"uses":2097},"Evolve a schema",[2047],{"path":2099,"title":2100,"uses":2101},"\u002Fdocs\u002Fdata\u002Fseeds","Seed data",[2047],{"path":2103,"title":2104,"uses":2105},"\u002Fdocs\u002Fdata\u002Fvalues","Read settings and secrets",[2047,2081],{"path":2107,"title":2108,"uses":2109},"\u002Fdocs\u002Fdata\u002Fmirror","Mirror a source you cannot query",[2110],"repository",{"path":2112,"title":2113,"uses":2114},"\u002Fdocs\u002Fdata\u002Ftogether","Two writes as one",[2110],{"path":2116,"title":2117,"uses":2118},"\u002Fdocs\u002Fbehaviour\u002Faround-every-call","Around every call",[694,293],{"path":2120,"title":2121,"uses":2122},"\u002Fdocs\u002Fbehaviour\u002Ffinish-a-fact","Finish a fact",[2123],"fact",{"path":2125,"title":2126,"uses":2127},"\u002Fdocs\u002Fserve\u002Frest-graphql","REST, OpenAPI, GraphQL",[2082,2081],{"path":2129,"title":2130,"uses":2131},"\u002Fdocs\u002Fserve\u002Fpages","Pages: queries and commands",[2082,2132],"facade",{"path":2134,"title":2135,"uses":2136},"\u002Fdocs\u002Fserve\u002Fforms","A form",[2047],{"path":2138,"title":2139,"uses":2140},"\u002Fdocs\u002Fserve\u002Fadmin","An admin panel",[2082],{"path":2142,"title":2143,"uses":2144},"\u002Fdocs\u002Frun\u002Fdeploy","Deploy a split",[2081,293],{"path":2146,"title":2147,"uses":2148},"\u002Fdocs\u002Frun\u002Fsecure","Secure calls between processes",[2081,293],{"path":2150,"title":2151,"uses":2152},"\u002Fdocs\u002Frun\u002Flifecycle","Reload and shut down",[2081],{"path":2154,"title":2155,"uses":2156},"\u002Fdocs\u002Frun\u002Fobserve","Observe",[2081,2082],{"path":2158,"title":2159,"uses":2160},"\u002Fdocs\u002Frun\u002Fdev-panel","The dev panel",[2082],{"path":2042,"title":8,"uses":2162},[2047,694],{"path":2164,"title":2165,"uses":2166},"\u002Fdocs\u002Fadopt\u002Fnew-project","Start a project",[293,2081],{"path":2168,"title":2169,"uses":2170},"\u002Fdocs\u002Fadopt\u002Fexisting-app","Add Fougere to an existing app",[293,2081],{"path":2172,"title":2173,"uses":2174},"\u002Fdocs\u002Fadopt\u002Fbring-your-schema","Bring your schema",[2047],{"path":2176,"title":2177,"uses":2178},"\u002Fdocs\u002Fadopt\u002Fhosts","Pick a host",[2081],{"path":2180,"title":2181,"uses":2182},"\u002Fdocs\u002Fadopt\u002Fanother-repository","A frond from another repository",[2132,293],{"path":2184,"title":2185,"uses":2186},"\u002Fdocs\u002Fadopt\u002Fdemos","Demos",[],{"path":2188,"title":2189,"uses":2045},"\u002Fdocs\u002Fextending\u002Fscan","How the scan reads a project",{"path":2191,"title":2192,"uses":2045},"\u002Fdocs\u002Fextending\u002Fwithout-compiler","Boot without the compiler",{"path":2194,"title":2195,"uses":2045},"\u002Fdocs\u002Fextending\u002Fboot","The boot, step by step",{"path":2197,"title":2198,"uses":2045},"\u002Fdocs\u002Fextending\u002Fcard-and-wire","The card and the wire",{"path":2200,"title":2201,"uses":2045},"\u002Fdocs\u002Fextending\u002Fextension-points","Registries and extension points",{"path":2203,"title":2204,"uses":2045},"\u002Fdocs\u002Fextending\u002Fvocabulary","Teach a word",{"path":2206,"title":2207,"uses":2045},"\u002Fdocs\u002Fextending\u002Fextensions","Run code at boot and shutdown",{"path":2209,"title":2210,"uses":2045},"\u002Fdocs\u002Fextending\u002Fsource-adapter","Write a source adapter",{"path":2212,"title":2213,"uses":2045},"\u002Fdocs\u002Fextending\u002Fsurface","Write a surface",{"path":2215,"title":2216,"uses":2045},"\u002Fdocs\u002Fextending\u002Fforeign-frond","A frond in another language",{"path":2218,"title":2219,"uses":2045},"\u002Fdocs","What is Fougere",[2221],{"title":2222,"path":2218,"stem":2223,"children":2224,"page":-1},"Docs","docs",[2225,2227,2248,2257,2278,2287,2300,2316,2333],{"title":2219,"path":2218,"stem":2226},"docs\u002Findex",{"title":2228,"path":2229,"stem":2230,"children":2231,"page":5},"Concepts","\u002Fdocs\u002Fconcepts","docs\u002F1.concepts",[2232,2234,2236,2238,2240,2242,2244,2246],{"title":2052,"path":2051,"stem":2233},"docs\u002F1.concepts\u002F1.entity",{"title":2055,"path":2054,"stem":2235},"docs\u002F1.concepts\u002F2.handler",{"title":2058,"path":2057,"stem":2237},"docs\u002F1.concepts\u002F3.repository",{"title":2061,"path":2060,"stem":2239},"docs\u002F1.concepts\u002F4.frond",{"title":2064,"path":2063,"stem":2241},"docs\u002F1.concepts\u002F5.facade",{"title":2067,"path":2066,"stem":2243},"docs\u002F1.concepts\u002F6.fact",{"title":2069,"path":693,"stem":2245},"docs\u002F1.concepts\u002F7.port",{"title":2072,"path":2071,"stem":2247},"docs\u002F1.concepts\u002F8.configuration",{"title":2249,"path":2250,"stem":2251,"children":2252,"page":5},"Access","\u002Fdocs\u002Faccess","docs\u002F2.access",[2253,2255],{"title":2075,"path":2074,"stem":2254},"docs\u002F2.access\u002F1.authentication",{"title":2079,"path":2078,"stem":2256},"docs\u002F2.access\u002F2.state",{"title":2258,"path":2259,"stem":2260,"children":2261,"page":5},"Data","\u002Fdocs\u002Fdata","docs\u002F3.data",[2262,2264,2266,2268,2270,2272,2274,2276],{"title":2085,"path":2084,"stem":2263},"docs\u002F3.data\u002F1.sql",{"title":2089,"path":2088,"stem":2265},"docs\u002F3.data\u002F2.several-databases",{"title":2093,"path":2092,"stem":2267},"docs\u002F3.data\u002F3.computed-field",{"title":2096,"path":536,"stem":2269},"docs\u002F3.data\u002F4.evolve",{"title":2100,"path":2099,"stem":2271},"docs\u002F3.data\u002F5.seeds",{"title":2104,"path":2103,"stem":2273},"docs\u002F3.data\u002F6.values",{"title":2108,"path":2107,"stem":2275},"docs\u002F3.data\u002F7.mirror",{"title":2113,"path":2112,"stem":2277},"docs\u002F3.data\u002F8.together",{"title":2279,"path":2280,"stem":2281,"children":2282,"page":5},"Behaviour","\u002Fdocs\u002Fbehaviour","docs\u002F4.behaviour",[2283,2285],{"title":2117,"path":2116,"stem":2284},"docs\u002F4.behaviour\u002F1.around-every-call",{"title":2121,"path":2120,"stem":2286},"docs\u002F4.behaviour\u002F2.finish-a-fact",{"title":2288,"path":2289,"stem":2290,"children":2291,"page":5},"Serve","\u002Fdocs\u002Fserve","docs\u002F5.serve",[2292,2294,2296,2298],{"title":2126,"path":2125,"stem":2293},"docs\u002F5.serve\u002F1.rest-graphql",{"title":2130,"path":2129,"stem":2295},"docs\u002F5.serve\u002F2.pages",{"title":2135,"path":2134,"stem":2297},"docs\u002F5.serve\u002F3.forms",{"title":2139,"path":2138,"stem":2299},"docs\u002F5.serve\u002F4.admin",{"title":2301,"path":2302,"stem":2303,"children":2304,"page":5},"Run","\u002Fdocs\u002Frun","docs\u002F6.run",[2305,2307,2309,2311,2313,2315],{"title":2143,"path":2142,"stem":2306},"docs\u002F6.run\u002F1.deploy",{"title":2147,"path":2146,"stem":2308},"docs\u002F6.run\u002F2.secure",{"title":2151,"path":2150,"stem":2310},"docs\u002F6.run\u002F3.lifecycle",{"title":2155,"path":2154,"stem":2312},"docs\u002F6.run\u002F4.observe",{"title":2159,"path":2158,"stem":2314},"docs\u002F6.run\u002F5.dev-panel",{"title":8,"path":2042,"stem":2044},{"title":2317,"path":2318,"stem":2319,"children":2320,"page":5},"Adopt","\u002Fdocs\u002Fadopt","docs\u002F7.adopt",[2321,2323,2325,2327,2329,2331],{"title":2165,"path":2164,"stem":2322},"docs\u002F7.adopt\u002F1.new-project",{"title":2169,"path":2168,"stem":2324},"docs\u002F7.adopt\u002F2.existing-app",{"title":2173,"path":2172,"stem":2326},"docs\u002F7.adopt\u002F3.bring-your-schema",{"title":2177,"path":2176,"stem":2328},"docs\u002F7.adopt\u002F4.hosts",{"title":2181,"path":2180,"stem":2330},"docs\u002F7.adopt\u002F5.another-repository",{"title":2185,"path":2184,"stem":2332},"docs\u002F7.adopt\u002F6.demos",{"title":2334,"path":2335,"stem":2336,"children":2337,"page":5},"Extending","\u002Fdocs\u002Fextending","docs\u002F8.extending",[2338,2340,2342,2344,2346,2348,2350,2352,2354,2356],{"title":2189,"path":2188,"stem":2339},"docs\u002F8.extending\u002F1.scan",{"title":2192,"path":2191,"stem":2341},"docs\u002F8.extending\u002F10.without-compiler",{"title":2195,"path":2194,"stem":2343},"docs\u002F8.extending\u002F2.boot",{"title":2198,"path":2197,"stem":2345},"docs\u002F8.extending\u002F3.card-and-wire",{"title":2201,"path":2200,"stem":2347},"docs\u002F8.extending\u002F4.extension-points",{"title":2204,"path":2203,"stem":2349},"docs\u002F8.extending\u002F5.vocabulary",{"title":2207,"path":2206,"stem":2351},"docs\u002F8.extending\u002F6.extensions",{"title":2210,"path":2209,"stem":2353},"docs\u002F8.extending\u002F7.source-adapter",{"title":2213,"path":2212,"stem":2355},"docs\u002F8.extending\u002F8.surface",{"title":2216,"path":2215,"stem":2357},"docs\u002F8.extending\u002F9.foreign-frond",{"id":2359,"title":1527,"body":2360,"count":2505,"description":60,"entry":2365,"extension":2037,"meta":12968,"name":1527,"navigation":184,"path":12969,"runnable":5,"seo":12970,"stem":12971,"__hash__":12972},"demo\u002Fdemo\u002Ftest-gradient.md",{"type":10,"value":2361,"toc":12966},[2362,12963],[2363,2364,2366,3398,4713,4895,5159,5411,5487,5582,6403,6574,6646,6893,8808,9382,9549,11790,11869,12778,12921],"code-tree",{"default-value":2365},"fronds\u002Fcatalog\u002Fentities\u002FProduct.ts",[54,2367,2371],{"className":2368,"code":2369,"filename":2370,"language":2037,"meta":60,"style":60},"language-md shiki shiki-themes material-theme-lighter fougere-pastel material-theme-palenight","# test-gradient\n\nCe que la déclaration écrit toute seule, et les trois crans où on l'exécute.\n\n```bash\npnpm test          # les trois premiers crans\npnpm e2e           # le quatrième : un vrai navigateur (playwright démarre le serveur)\npnpm migrate       # le démarrage ne fait que lire le schéma\npnpm dev           # la page seule, sur :4300\npnpm load:gen      # réécrit load.js depuis ce que l'app répond\nk6 run load.js     # si k6 est installé\n```\n\n**40 tests.** Trente-cinq d'entre eux viennent d'un fichier de **huit lignes** ; les cinq\nautres sont les seuls écrits à la main, et ils disent ce qu'aucune déclaration ne peut\ndeviner — ce que fait un handler, et ce qu'un port bouché doit répondre.\n\n## Cran 1 — un frond\n\n`fronds\u002Fcatalog\u002Ftests\u002Fpricing.test.ts`. Le fichier est dans le frond, et ça suffit :\n\n```ts\nawait using app = await testApp()          \u002F\u002F aucun argument\nexpect(app.fronds.map(f => f.name)).toEqual(['catalog'])\n```\n\nLa position dit le projet et dit le sujet, comme `entities\u002F` dit déjà ce qu'un dossier\ncontient. Le frond `orders` n'est pas monté — le même énoncé que `remotes:` en production.\n\nC'est aussi le cran où un port se bouche, parce qu'un taux est un fait sur le monde\nextérieur et pas sur le catalogue :\n\n```ts\nawait using app = await testApp({ stub: [Pricing] })\napp.stub(Pricing).total.mockReturnValue(4242)\n```\n\nLes méthodes du bouchon viennent du prototype du port, jamais d'une liste écrite à la\nmain. Ce qu'il RENVOIE, en revanche, est à toi : le type de retour d'un service est un\ntype TypeScript nu, effacé à l'exécution.\n\n## Cran 2 — plusieurs fronds\n\n`tests\u002Fcontracts.test.ts`, au-dessus des fronds, donc les deux sont réels. Le fichier\nentier :\n\n```ts\nconst app = await testApp()\ncheckContract(app, Product); checkOutput(app, Product)\ncheckContract(app, Order);   checkOutput(app, Order)\n```\n\nAucun cas n'est écrit. Ils sont énumérés depuis les champs — `sku trop court`,\n`cents au-dessus du maximum`, `status hors de l'ensemble`, `clé hors contrat`,\n`corps qui n'est pas un objet`. Tu changes un `min:` dans l'entité, les cas suivent.\n\nÇa marche parce que le juge a une liste **fermée** de refus : champ inconnu, champ\nmanquant, lecture seule, immuable, la forme, un codec nommé. Avec un validateur où l'on\nécrit du code de règle libre, c'est impossible.\n\n## Cran 3 — l'app dans son process\n\n`tests\u002Fsplit.test.ts`. Le test parle par le transport qui fait déjà marcher un frond\ndéplacé — il devient un consommateur, comme un navigateur posé à côté.\n\nPlaywright n'a pas d'objet ici : cette démo n'a pas de front. Le cran navigateur se\nmontre là où il y a des pages.\n\n## La charge\n\n`load.js` est **généré**, pas écrit. Il couvre les onze opérations que l'app répond, avec\nun corps valide pour chacune, et son enveloppe JSON-RPC vient de `frameCall` — pas d'une\ncopie qui mentira le jour où le format bouge.\n\nCe qui reste à écrire : les poids, les paliers et les seuils. Le scan sait quelles\nopérations existent ; il ne sait rien du trafic qu'elles reçoivent.\n\n## Cran 4 — un navigateur\n\n`e2e\u002Fcatalog.spec.ts` et `server.ts`. Le formulaire n'est écrit nulle part :\n`formFieldsOf` le dérive de `Product`, avec ses contraintes sous les noms que le navigateur\nconnaît déjà.\n\n```html\n\u003Cinput id=\"sku\" name=\"sku\" type=\"text\" required minlength=\"3\" maxlength=\"12\">\n\u003Cselect id=\"status\">\u003Coption>draft\u003C\u002Foption>\u003Coption>listed\u003C\u002Foption>\u003Coption>withdrawn\u003C\u002Foption>\u003C\u002Fselect>\n```\n\nCe que ce cran prouve et qu'aucun autre ne peut : **la page n'énonce aucune règle de son\ncôté.** Elle ne contient pas une ligne de validation — un `sku` de deux caractères est\nrefusé par le navigateur, et le même corps envoyé directement à la porte est refusé par le\njuge. « Juge local = juge distant » se regarde ici au lieu de se plaider ; les autres crans\nne peuvent que le simuler dans un seul process.\n\n","README.md",[17,2372,2373,2383,2387,2392,2396,2406,2411,2416,2422,2428,2434,2440,2446,2451,2477,2483,2489,2494,2503,2508,2522,2527,2535,2553,2601,2606,2611,2626,2652,2657,2663,2669,2674,2681,2712,2741,2746,2751,2757,2763,2769,2774,2782,2787,2800,2806,2811,2818,2834,2865,2896,2901,2906,2922,2952,2974,2979,2995,3001,3007,3012,3020,3025,3038,3044,3049,3055,3061,3066,3074,3079,3101,3116,3122,3127,3133,3139,3144,3152,3157,3180,3201,3207,3212,3220,3281,3349,3354,3359,3365,3380,3386,3392],{"__ignoreMap":60},[64,2374,2375,2379],{"class":66,"line":67},[64,2376,2378],{"class":2377},"sd7zb","#",[64,2380,2382],{"class":2381},"sLf9K"," test-gradient\n",[64,2384,2385],{"class":66,"line":147},[64,2386,185],{"emptyLinePlaceholder":184},[64,2388,2389],{"class":66,"line":181},[64,2390,2391],{"class":158},"Ce que la déclaration écrit toute seule, et les trois crans où on l'exécute.\n",[64,2393,2394],{"class":66,"line":188},[64,2395,185],{"emptyLinePlaceholder":184},[64,2397,2398,2402],{"class":66,"line":825},[64,2399,2401],{"class":2400},"siB6D","```",[64,2403,2405],{"class":2404},"sYNOY","bash\n",[64,2407,2408],{"class":66,"line":830},[64,2409,2410],{"class":2404},"pnpm test          # les trois premiers crans\n",[64,2412,2413],{"class":66,"line":1760},[64,2414,2415],{"class":2404},"pnpm e2e           # le quatrième : un vrai navigateur (playwright démarre le serveur)\n",[64,2417,2419],{"class":66,"line":2418},8,[64,2420,2421],{"class":2404},"pnpm migrate       # le démarrage ne fait que lire le schéma\n",[64,2423,2425],{"class":66,"line":2424},9,[64,2426,2427],{"class":2404},"pnpm dev           # la page seule, sur :4300\n",[64,2429,2431],{"class":66,"line":2430},10,[64,2432,2433],{"class":2404},"pnpm load:gen      # réécrit load.js depuis ce que l'app répond\n",[64,2435,2437],{"class":66,"line":2436},11,[64,2438,2439],{"class":2404},"k6 run load.js     # si k6 est installé\n",[64,2441,2443],{"class":66,"line":2442},12,[64,2444,2445],{"class":2400},"```\n",[64,2447,2449],{"class":66,"line":2448},13,[64,2450,185],{"emptyLinePlaceholder":184},[64,2452,2454,2458,2462,2464,2467,2469,2472,2474],{"class":66,"line":2453},14,[64,2455,2457],{"class":2456},"sHaeK","**",[64,2459,2461],{"class":2460},"s7rwI","40 tests.",[64,2463,2457],{"class":2456},[64,2465,2466],{"class":158}," Trente-cinq d'entre eux viennent d'un fichier de ",[64,2468,2457],{"class":2456},[64,2470,2471],{"class":2460},"huit lignes",[64,2473,2457],{"class":2456},[64,2475,2476],{"class":158}," ; les cinq\n",[64,2478,2480],{"class":66,"line":2479},15,[64,2481,2482],{"class":158},"autres sont les seuls écrits à la main, et ils disent ce qu'aucune déclaration ne peut\n",[64,2484,2486],{"class":66,"line":2485},16,[64,2487,2488],{"class":158},"deviner — ce que fait un handler, et ce qu'un port bouché doit répondre.\n",[64,2490,2492],{"class":66,"line":2491},17,[64,2493,185],{"emptyLinePlaceholder":184},[64,2495,2497,2500],{"class":66,"line":2496},18,[64,2498,2499],{"class":2377},"##",[64,2501,2502],{"class":2381}," Cran 1 — un frond\n",[64,2504,2506],{"class":66,"line":2505},19,[64,2507,185],{"emptyLinePlaceholder":184},[64,2509,2511,2514,2517,2519],{"class":66,"line":2510},20,[64,2512,2513],{"class":154},"`",[64,2515,2516],{"class":73},"fronds\u002Fcatalog\u002Ftests\u002Fpricing.test.ts",[64,2518,2513],{"class":154},[64,2520,2521],{"class":158},". Le fichier est dans le frond, et ça suffit :\n",[64,2523,2525],{"class":66,"line":2524},21,[64,2526,185],{"emptyLinePlaceholder":184},[64,2528,2530,2532],{"class":66,"line":2529},22,[64,2531,2401],{"class":2400},[64,2533,2534],{"class":2404},"ts\n",[64,2536,2538,2540,2542,2544,2546,2548,2550],{"class":66,"line":2537},23,[64,2539,242],{"class":241},[64,2541,245],{"class":158},[64,2543,248],{"class":154},[64,2545,251],{"class":150},[64,2547,254],{"class":197},[64,2549,201],{"class":200},[64,2551,2552],{"class":143},"          \u002F\u002F aucun argument\n",[64,2554,2556,2558,2560,2562,2564,2566,2568,2570,2572,2575,2577,2580,2582,2584,2586,2588,2590,2592,2594,2596,2598],{"class":66,"line":2555},24,[64,2557,267],{"class":197},[64,2559,270],{"class":200},[64,2561,273],{"class":158},[64,2563,276],{"class":154},[64,2565,280],{"class":279},[64,2567,276],{"class":154},[64,2569,285],{"class":197},[64,2571,270],{"class":200},[64,2573,2574],{"class":292},"f",[64,2576,300],{"class":299},[64,2578,2579],{"class":158}," f",[64,2581,276],{"class":154},[64,2583,308],{"class":279},[64,2585,311],{"class":200},[64,2587,276],{"class":154},[64,2589,316],{"class":197},[64,2591,319],{"class":200},[64,2593,175],{"class":168},[64,2595,324],{"class":73},[64,2597,175],{"class":168},[64,2599,2600],{"class":200},"])\n",[64,2602,2604],{"class":66,"line":2603},25,[64,2605,2445],{"class":2400},[64,2607,2609],{"class":66,"line":2608},26,[64,2610,185],{"emptyLinePlaceholder":184},[64,2612,2614,2617,2619,2621,2623],{"class":66,"line":2613},27,[64,2615,2616],{"class":158},"La position dit le projet et dit le sujet, comme ",[64,2618,2513],{"class":154},[64,2620,222],{"class":73},[64,2622,2513],{"class":154},[64,2624,2625],{"class":158}," dit déjà ce qu'un dossier\n",[64,2627,2629,2632,2634,2637,2639,2642,2644,2647,2649],{"class":66,"line":2628},28,[64,2630,2631],{"class":158},"contient. Le frond ",[64,2633,2513],{"class":154},[64,2635,2636],{"class":73},"orders",[64,2638,2513],{"class":154},[64,2640,2641],{"class":158}," n'est pas monté — le même énoncé que ",[64,2643,2513],{"class":154},[64,2645,2646],{"class":73},"remotes:",[64,2648,2513],{"class":154},[64,2650,2651],{"class":158}," en production.\n",[64,2653,2655],{"class":66,"line":2654},29,[64,2656,185],{"emptyLinePlaceholder":184},[64,2658,2660],{"class":66,"line":2659},30,[64,2661,2662],{"class":158},"C'est aussi le cran où un port se bouche, parce qu'un taux est un fait sur le monde\n",[64,2664,2666],{"class":66,"line":2665},31,[64,2667,2668],{"class":158},"extérieur et pas sur le catalogue :\n",[64,2670,2672],{"class":66,"line":2671},32,[64,2673,185],{"emptyLinePlaceholder":184},[64,2675,2677,2679],{"class":66,"line":2676},33,[64,2678,2401],{"class":2400},[64,2680,2534],{"class":2404},[64,2682,2684,2686,2688,2690,2692,2694,2696,2698,2700,2702,2704,2706,2708,2710],{"class":66,"line":2683},34,[64,2685,242],{"class":241},[64,2687,245],{"class":158},[64,2689,248],{"class":154},[64,2691,251],{"class":150},[64,2693,254],{"class":197},[64,2695,270],{"class":200},[64,2697,717],{"class":154},[64,2699,720],{"class":583},[64,2701,501],{"class":154},[64,2703,725],{"class":200},[64,2705,728],{"class":158},[64,2707,731],{"class":200},[64,2709,162],{"class":154},[64,2711,1413],{"class":200},[64,2713,2715,2717,2719,2721,2723,2725,2727,2729,2731,2733,2735,2737,2739],{"class":66,"line":2714},35,[64,2716,273],{"class":158},[64,2718,276],{"class":154},[64,2720,746],{"class":197},[64,2722,270],{"class":200},[64,2724,728],{"class":158},[64,2726,296],{"class":200},[64,2728,276],{"class":154},[64,2730,757],{"class":279},[64,2732,276],{"class":154},[64,2734,762],{"class":197},[64,2736,270],{"class":200},[64,2738,767],{"class":623},[64,2740,1413],{"class":200},[64,2742,2744],{"class":66,"line":2743},36,[64,2745,2445],{"class":2400},[64,2747,2749],{"class":66,"line":2748},37,[64,2750,185],{"emptyLinePlaceholder":184},[64,2752,2754],{"class":66,"line":2753},38,[64,2755,2756],{"class":158},"Les méthodes du bouchon viennent du prototype du port, jamais d'une liste écrite à la\n",[64,2758,2760],{"class":66,"line":2759},39,[64,2761,2762],{"class":158},"main. Ce qu'il RENVOIE, en revanche, est à toi : le type de retour d'un service est un\n",[64,2764,2766],{"class":66,"line":2765},40,[64,2767,2768],{"class":158},"type TypeScript nu, effacé à l'exécution.\n",[64,2770,2772],{"class":66,"line":2771},41,[64,2773,185],{"emptyLinePlaceholder":184},[64,2775,2777,2779],{"class":66,"line":2776},42,[64,2778,2499],{"class":2377},[64,2780,2781],{"class":2381}," Cran 2 — plusieurs fronds\n",[64,2783,2785],{"class":66,"line":2784},43,[64,2786,185],{"emptyLinePlaceholder":184},[64,2788,2790,2792,2795,2797],{"class":66,"line":2789},44,[64,2791,2513],{"class":154},[64,2793,2794],{"class":73},"tests\u002Fcontracts.test.ts",[64,2796,2513],{"class":154},[64,2798,2799],{"class":158},", au-dessus des fronds, donc les deux sont réels. Le fichier\n",[64,2801,2803],{"class":66,"line":2802},45,[64,2804,2805],{"class":158},"entier :\n",[64,2807,2809],{"class":66,"line":2808},46,[64,2810,185],{"emptyLinePlaceholder":184},[64,2812,2814,2816],{"class":66,"line":2813},47,[64,2815,2401],{"class":2400},[64,2817,2534],{"class":2404},[64,2819,2821,2823,2825,2827,2829,2831],{"class":66,"line":2820},48,[64,2822,929],{"class":241},[64,2824,245],{"class":158},[64,2826,248],{"class":154},[64,2828,251],{"class":150},[64,2830,254],{"class":197},[64,2832,2833],{"class":200},"()\n",[64,2835,2837,2840,2842,2844,2846,2848,2850,2852,2855,2857,2859,2861,2863],{"class":66,"line":2836},49,[64,2838,2839],{"class":197},"checkContract",[64,2841,270],{"class":200},[64,2843,273],{"class":158},[64,2845,399],{"class":154},[64,2847,1041],{"class":158},[64,2849,296],{"class":200},[64,2851,1046],{"class":154},[64,2853,2854],{"class":197}," checkOutput",[64,2856,270],{"class":200},[64,2858,273],{"class":158},[64,2860,399],{"class":154},[64,2862,1041],{"class":158},[64,2864,1413],{"class":200},[64,2866,2868,2870,2872,2874,2876,2879,2881,2883,2886,2888,2890,2892,2894],{"class":66,"line":2867},50,[64,2869,2839],{"class":197},[64,2871,270],{"class":200},[64,2873,273],{"class":158},[64,2875,399],{"class":154},[64,2877,2878],{"class":158}," Order",[64,2880,296],{"class":200},[64,2882,1046],{"class":154},[64,2884,2885],{"class":197},"   checkOutput",[64,2887,270],{"class":200},[64,2889,273],{"class":158},[64,2891,399],{"class":154},[64,2893,2878],{"class":158},[64,2895,1413],{"class":200},[64,2897,2899],{"class":66,"line":2898},51,[64,2900,2445],{"class":2400},[64,2902,2904],{"class":66,"line":2903},52,[64,2905,185],{"emptyLinePlaceholder":184},[64,2907,2909,2912,2914,2917,2919],{"class":66,"line":2908},53,[64,2910,2911],{"class":158},"Aucun cas n'est écrit. Ils sont énumérés depuis les champs — ",[64,2913,2513],{"class":154},[64,2915,2916],{"class":73},"sku trop court",[64,2918,2513],{"class":154},[64,2920,2921],{"class":158},",\n",[64,2923,2925,2927,2930,2932,2934,2936,2939,2941,2943,2945,2948,2950],{"class":66,"line":2924},54,[64,2926,2513],{"class":154},[64,2928,2929],{"class":73},"cents au-dessus du maximum",[64,2931,2513],{"class":154},[64,2933,648],{"class":158},[64,2935,2513],{"class":154},[64,2937,2938],{"class":73},"status hors de l'ensemble",[64,2940,2513],{"class":154},[64,2942,648],{"class":158},[64,2944,2513],{"class":154},[64,2946,2947],{"class":73},"clé hors contrat",[64,2949,2513],{"class":154},[64,2951,2921],{"class":158},[64,2953,2955,2957,2960,2962,2965,2967,2969,2971],{"class":66,"line":2954},55,[64,2956,2513],{"class":154},[64,2958,2959],{"class":73},"corps qui n'est pas un objet",[64,2961,2513],{"class":154},[64,2963,2964],{"class":158},". Tu changes un ",[64,2966,2513],{"class":154},[64,2968,469],{"class":73},[64,2970,2513],{"class":154},[64,2972,2973],{"class":158}," dans l'entité, les cas suivent.\n",[64,2975,2977],{"class":66,"line":2976},56,[64,2978,185],{"emptyLinePlaceholder":184},[64,2980,2982,2985,2987,2990,2992],{"class":66,"line":2981},57,[64,2983,2984],{"class":158},"Ça marche parce que le juge a une liste ",[64,2986,2457],{"class":2456},[64,2988,2989],{"class":2460},"fermée",[64,2991,2457],{"class":2456},[64,2993,2994],{"class":158}," de refus : champ inconnu, champ\n",[64,2996,2998],{"class":66,"line":2997},58,[64,2999,3000],{"class":158},"manquant, lecture seule, immuable, la forme, un codec nommé. Avec un validateur où l'on\n",[64,3002,3004],{"class":66,"line":3003},59,[64,3005,3006],{"class":158},"écrit du code de règle libre, c'est impossible.\n",[64,3008,3010],{"class":66,"line":3009},60,[64,3011,185],{"emptyLinePlaceholder":184},[64,3013,3015,3017],{"class":66,"line":3014},61,[64,3016,2499],{"class":2377},[64,3018,3019],{"class":2381}," Cran 3 — l'app dans son process\n",[64,3021,3023],{"class":66,"line":3022},62,[64,3024,185],{"emptyLinePlaceholder":184},[64,3026,3028,3030,3033,3035],{"class":66,"line":3027},63,[64,3029,2513],{"class":154},[64,3031,3032],{"class":73},"tests\u002Fsplit.test.ts",[64,3034,2513],{"class":154},[64,3036,3037],{"class":158},". Le test parle par le transport qui fait déjà marcher un frond\n",[64,3039,3041],{"class":66,"line":3040},64,[64,3042,3043],{"class":158},"déplacé — il devient un consommateur, comme un navigateur posé à côté.\n",[64,3045,3047],{"class":66,"line":3046},65,[64,3048,185],{"emptyLinePlaceholder":184},[64,3050,3052],{"class":66,"line":3051},66,[64,3053,3054],{"class":158},"Playwright n'a pas d'objet ici : cette démo n'a pas de front. Le cran navigateur se\n",[64,3056,3058],{"class":66,"line":3057},67,[64,3059,3060],{"class":158},"montre là où il y a des pages.\n",[64,3062,3064],{"class":66,"line":3063},68,[64,3065,185],{"emptyLinePlaceholder":184},[64,3067,3069,3071],{"class":66,"line":3068},69,[64,3070,2499],{"class":2377},[64,3072,3073],{"class":2381}," La charge\n",[64,3075,3077],{"class":66,"line":3076},70,[64,3078,185],{"emptyLinePlaceholder":184},[64,3080,3082,3084,3086,3088,3091,3093,3096,3098],{"class":66,"line":3081},71,[64,3083,2513],{"class":154},[64,3085,1725],{"class":73},[64,3087,2513],{"class":154},[64,3089,3090],{"class":158}," est ",[64,3092,2457],{"class":2456},[64,3094,3095],{"class":2460},"généré",[64,3097,2457],{"class":2456},[64,3099,3100],{"class":158},", pas écrit. Il couvre les onze opérations que l'app répond, avec\n",[64,3102,3104,3107,3109,3111,3113],{"class":66,"line":3103},72,[64,3105,3106],{"class":158},"un corps valide pour chacune, et son enveloppe JSON-RPC vient de ",[64,3108,2513],{"class":154},[64,3110,1798],{"class":73},[64,3112,2513],{"class":154},[64,3114,3115],{"class":158}," — pas d'une\n",[64,3117,3119],{"class":66,"line":3118},73,[64,3120,3121],{"class":158},"copie qui mentira le jour où le format bouge.\n",[64,3123,3125],{"class":66,"line":3124},74,[64,3126,185],{"emptyLinePlaceholder":184},[64,3128,3130],{"class":66,"line":3129},75,[64,3131,3132],{"class":158},"Ce qui reste à écrire : les poids, les paliers et les seuils. Le scan sait quelles\n",[64,3134,3136],{"class":66,"line":3135},76,[64,3137,3138],{"class":158},"opérations existent ; il ne sait rien du trafic qu'elles reçoivent.\n",[64,3140,3142],{"class":66,"line":3141},77,[64,3143,185],{"emptyLinePlaceholder":184},[64,3145,3147,3149],{"class":66,"line":3146},78,[64,3148,2499],{"class":2377},[64,3150,3151],{"class":2381}," Cran 4 — un navigateur\n",[64,3153,3155],{"class":66,"line":3154},79,[64,3156,185],{"emptyLinePlaceholder":184},[64,3158,3160,3162,3165,3167,3170,3172,3175,3177],{"class":66,"line":3159},80,[64,3161,2513],{"class":154},[64,3163,3164],{"class":73},"e2e\u002Fcatalog.spec.ts",[64,3166,2513],{"class":154},[64,3168,3169],{"class":158}," et ",[64,3171,2513],{"class":154},[64,3173,3174],{"class":73},"server.ts",[64,3176,2513],{"class":154},[64,3178,3179],{"class":158},". Le formulaire n'est écrit nulle part :\n",[64,3181,3183,3185,3187,3189,3192,3194,3196,3198],{"class":66,"line":3182},81,[64,3184,2513],{"class":154},[64,3186,1398],{"class":73},[64,3188,2513],{"class":154},[64,3190,3191],{"class":158}," le dérive de ",[64,3193,2513],{"class":154},[64,3195,563],{"class":73},[64,3197,2513],{"class":154},[64,3199,3200],{"class":158},", avec ses contraintes sous les noms que le navigateur\n",[64,3202,3204],{"class":66,"line":3203},82,[64,3205,3206],{"class":158},"connaît déjà.\n",[64,3208,3210],{"class":66,"line":3209},83,[64,3211,185],{"emptyLinePlaceholder":184},[64,3213,3215,3217],{"class":66,"line":3214},84,[64,3216,2401],{"class":2400},[64,3218,3219],{"class":2404},"html\n",[64,3221,3223,3225,3227,3229,3231,3233,3235,3237,3239,3241,3243,3245,3247,3249,3251,3253,3255,3257,3259,3261,3263,3265,3267,3269,3271,3273,3275,3277,3279],{"class":66,"line":3222},85,[64,3224,939],{"class":154},[64,3226,1428],{"class":1427},[64,3228,1175],{"class":1431},[64,3230,248],{"class":154},[64,3232,1436],{"class":168},[64,3234,1439],{"class":73},[64,3236,1436],{"class":168},[64,3238,1444],{"class":1431},[64,3240,248],{"class":154},[64,3242,1436],{"class":168},[64,3244,1439],{"class":73},[64,3246,1436],{"class":168},[64,3248,1455],{"class":1431},[64,3250,248],{"class":154},[64,3252,1436],{"class":168},[64,3254,214],{"class":73},[64,3256,1436],{"class":168},[64,3258,1466],{"class":1431},[64,3260,1469],{"class":1431},[64,3262,248],{"class":154},[64,3264,1436],{"class":168},[64,3266,1476],{"class":73},[64,3268,1436],{"class":168},[64,3270,1481],{"class":1431},[64,3272,248],{"class":154},[64,3274,1436],{"class":168},[64,3276,1488],{"class":73},[64,3278,1436],{"class":168},[64,3280,1493],{"class":154},[64,3282,3284,3286,3289,3291,3293,3295,3298,3300,3303,3306,3308,3311,3314,3316,3318,3320,3322,3325,3327,3329,3331,3333,3335,3338,3340,3342,3345,3347],{"class":66,"line":3283},86,[64,3285,939],{"class":154},[64,3287,3288],{"class":1427},"select",[64,3290,1175],{"class":1431},[64,3292,248],{"class":154},[64,3294,1436],{"class":168},[64,3296,3297],{"class":73},"status",[64,3299,1436],{"class":168},[64,3301,3302],{"class":154},">\u003C",[64,3304,3305],{"class":1427},"option",[64,3307,945],{"class":154},[64,3309,3310],{"class":158},"draft",[64,3312,3313],{"class":154},"\u003C\u002F",[64,3315,3305],{"class":1427},[64,3317,3302],{"class":154},[64,3319,3305],{"class":1427},[64,3321,945],{"class":154},[64,3323,3324],{"class":158},"listed",[64,3326,3313],{"class":154},[64,3328,3305],{"class":1427},[64,3330,3302],{"class":154},[64,3332,3305],{"class":1427},[64,3334,945],{"class":154},[64,3336,3337],{"class":158},"withdrawn",[64,3339,3313],{"class":154},[64,3341,3305],{"class":1427},[64,3343,3344],{"class":154},">\u003C\u002F",[64,3346,3288],{"class":1427},[64,3348,1493],{"class":154},[64,3350,3352],{"class":66,"line":3351},87,[64,3353,2445],{"class":2400},[64,3355,3357],{"class":66,"line":3356},88,[64,3358,185],{"emptyLinePlaceholder":184},[64,3360,3362],{"class":66,"line":3361},89,[64,3363,3364],{"class":158},"Ce que ce cran prouve et qu'aucun autre ne peut : **la page n'énonce aucune règle de son\n",[64,3366,3368,3371,3373,3375,3377],{"class":66,"line":3367},90,[64,3369,3370],{"class":158},"côté.** Elle ne contient pas une ligne de validation — un ",[64,3372,2513],{"class":154},[64,3374,1439],{"class":73},[64,3376,2513],{"class":154},[64,3378,3379],{"class":158}," de deux caractères est\n",[64,3381,3383],{"class":66,"line":3382},91,[64,3384,3385],{"class":158},"refusé par le navigateur, et le même corps envoyé directement à la porte est refusé par le\n",[64,3387,3389],{"class":66,"line":3388},92,[64,3390,3391],{"class":158},"juge. « Juge local = juge distant » se regarde ici au lieu de se plaider ; les autres crans\n",[64,3393,3395],{"class":66,"line":3394},93,[64,3396,3397],{"class":158},"ne peuvent que le simuler dans un seul process.\n",[54,3399,3401],{"className":134,"code":3400,"filename":3164,"language":136,"meta":60,"style":60},"\u002F**\n * CRAN 4 — un vrai navigateur, une vraie app.\n *\n * Ce que ce cran prouve et qu'aucun autre ne peut : le formulaire n'énonce aucune règle\n * de son côté. Ses contraintes sont celles de `Product`, sous les noms que le navigateur\n * connaît déjà, et le serveur refuse exactement ce que la balise refuse. « Juge local =\n * juge distant » se regarde ici au lieu de se plaider.\n *\u002F\nimport { test, expect } from '@playwright\u002Ftest';\n\ntest('le formulaire porte les contraintes que Product déclare', async ({ page }) => {\n  await page.goto('\u002F');\n\n  \u002F\u002F Rien de tout cela n'est écrit dans la page : `formFieldsOf` le dérive de l'entité.\n  await expect(page.locator('#sku')).toHaveAttribute('minlength', '3');\n  await expect(page.locator('#sku')).toHaveAttribute('maxlength', '12');\n  await expect(page.locator('#cents')).toHaveAttribute('max', '1000000');\n  await expect(page.locator('#status')).toHaveValue('draft');\n  await expect(page.locator('#status option')).toHaveCount(3);\n});\n\ntest('le navigateur refuse ce que le serveur refuserait', async ({ page }) => {\n  await page.goto('\u002F');\n  await page.fill('#sku', 'AB');           \u002F\u002F sous le minimum déclaré\n  await page.fill('#name', 'Une lampe');\n  await page.fill('#cents', '1000');\n  await page.click('button[type=submit]');\n\n  \u002F\u002F La page n'a envoyé aucune requête : la contrainte vient de l'entité, et c'est le\n  \u002F\u002F navigateur qui l'applique. Aucun code de validation dans la page.\n  await expect(page.locator('#sku')).toBeFocused();\n  await expect(page.locator('#products li')).toHaveCount(0);\n});\n\ntest('un corps valide traverse la porte et la ligne apparaît', async ({ page }) => {\n  await page.goto('\u002F');\n  await page.fill('#sku', 'LAMP-01');\n  await page.fill('#name', 'Une lampe');\n  await page.fill('#cents', '4990');\n  await page.click('button[type=submit]');\n\n  await expect(page.locator('#products li[data-sku=\"LAMP-01\"]')).toHaveText('Une lampe');\n});\n\ntest('le serveur refuse ce que le navigateur a laissé passer', async ({ page }) => {\n  await page.goto('\u002F');\n  \u002F\u002F La balise ne connaît pas la casse ni l'unicité — mais le juge, lui, refuse une clé\n  \u002F\u002F hors contrat. Le formulaire est contourné exprès, comme le ferait un client écrit.\n  const answer = await page.evaluate(async () => {\n    const response = await fetch('\u002F_fougere\u002Fcall', {\n      method: 'POST',\n      headers: { 'content-type': 'application\u002Fjson' },\n      body: JSON.stringify({ jsonrpc: '2.0', id: 1, method: 'product.create',\n        params: { params: {}, query: {}, input: { sku: 'LAMP-02', name: 'x', cents: 1, status: 'draft', couleur: 'rouge' }, state: {} } }),\n    });\n\n    return response.json();\n  }) as { error?: { message: string } };\n\n  expect(answer.error?.message).toContain('Unknown field');\n});\n\n",[17,3402,3403,3408,3413,3418,3423,3428,3433,3438,3443,3470,3474,3507,3532,3536,3541,3593,3642,3693,3735,3773,3781,3785,3812,3834,3869,3901,3931,3955,3959,3964,3969,4002,4040,4048,4052,4079,4101,4132,4162,4193,4215,4219,4261,4269,4273,4300,4322,4327,4332,4362,4390,4406,4435,4491,4599,4608,4612,4628,4660,4664,4705],{"__ignoreMap":60},[64,3404,3405],{"class":66,"line":67},[64,3406,3407],{"class":143},"\u002F**\n",[64,3409,3410],{"class":66,"line":147},[64,3411,3412],{"class":143}," * CRAN 4 — un vrai navigateur, une vraie app.\n",[64,3414,3415],{"class":66,"line":181},[64,3416,3417],{"class":143}," *\n",[64,3419,3420],{"class":66,"line":188},[64,3421,3422],{"class":143}," * Ce que ce cran prouve et qu'aucun autre ne peut : le formulaire n'énonce aucune règle\n",[64,3424,3425],{"class":66,"line":825},[64,3426,3427],{"class":143}," * de son côté. Ses contraintes sont celles de `Product`, sous les noms que le navigateur\n",[64,3429,3430],{"class":66,"line":830},[64,3431,3432],{"class":143}," * connaît déjà, et le serveur refuse exactement ce que la balise refuse. « Juge local =\n",[64,3434,3435],{"class":66,"line":1760},[64,3436,3437],{"class":143}," * juge distant » se regarde ici au lieu de se plaider.\n",[64,3439,3440],{"class":66,"line":2418},[64,3441,3442],{"class":143}," *\u002F\n",[64,3444,3445,3447,3449,3452,3454,3457,3459,3461,3463,3466,3468],{"class":66,"line":2424},[64,3446,151],{"class":150},[64,3448,155],{"class":154},[64,3450,3451],{"class":158}," test",[64,3453,399],{"class":154},[64,3455,3456],{"class":158}," expect",[64,3458,162],{"class":154},[64,3460,165],{"class":150},[64,3462,169],{"class":168},[64,3464,3465],{"class":73},"@playwright\u002Ftest",[64,3467,175],{"class":168},[64,3469,178],{"class":154},[64,3471,3472],{"class":66,"line":2430},[64,3473,185],{"emptyLinePlaceholder":184},[64,3475,3476,3479,3481,3483,3486,3488,3490,3493,3496,3499,3502,3504],{"class":66,"line":2436},[64,3477,3478],{"class":197},"test",[64,3480,270],{"class":200},[64,3482,175],{"class":168},[64,3484,3485],{"class":73},"le formulaire porte les contraintes que Product déclare",[64,3487,175],{"class":168},[64,3489,399],{"class":154},[64,3491,3492],{"class":241}," async",[64,3494,3495],{"class":154}," ({",[64,3497,3498],{"class":292}," page",[64,3500,3501],{"class":154}," })",[64,3503,300],{"class":299},[64,3505,3506],{"class":154}," {\n",[64,3508,3509,3512,3514,3516,3519,3522,3524,3526,3528,3530],{"class":66,"line":2442},[64,3510,3511],{"class":150},"  await",[64,3513,3498],{"class":158},[64,3515,276],{"class":154},[64,3517,3518],{"class":197},"goto",[64,3520,270],{"class":3521},"spAFX",[64,3523,175],{"class":168},[64,3525,1547],{"class":73},[64,3527,175],{"class":168},[64,3529,296],{"class":3521},[64,3531,178],{"class":154},[64,3533,3534],{"class":66,"line":2448},[64,3535,185],{"emptyLinePlaceholder":184},[64,3537,3538],{"class":66,"line":2453},[64,3539,3540],{"class":143},"  \u002F\u002F Rien de tout cela n'est écrit dans la page : `formFieldsOf` le dérive de l'entité.\n",[64,3542,3543,3545,3547,3549,3551,3553,3556,3558,3560,3563,3565,3567,3569,3572,3574,3576,3579,3581,3583,3585,3587,3589,3591],{"class":66,"line":2479},[64,3544,3511],{"class":150},[64,3546,3456],{"class":197},[64,3548,270],{"class":3521},[64,3550,1893],{"class":158},[64,3552,276],{"class":154},[64,3554,3555],{"class":197},"locator",[64,3557,270],{"class":3521},[64,3559,175],{"class":168},[64,3561,3562],{"class":73},"#sku",[64,3564,175],{"class":168},[64,3566,311],{"class":3521},[64,3568,276],{"class":154},[64,3570,3571],{"class":197},"toHaveAttribute",[64,3573,270],{"class":3521},[64,3575,175],{"class":168},[64,3577,3578],{"class":73},"minlength",[64,3580,175],{"class":168},[64,3582,399],{"class":154},[64,3584,169],{"class":168},[64,3586,1476],{"class":73},[64,3588,175],{"class":168},[64,3590,296],{"class":3521},[64,3592,178],{"class":154},[64,3594,3595,3597,3599,3601,3603,3605,3607,3609,3611,3613,3615,3617,3619,3621,3623,3625,3628,3630,3632,3634,3636,3638,3640],{"class":66,"line":2485},[64,3596,3511],{"class":150},[64,3598,3456],{"class":197},[64,3600,270],{"class":3521},[64,3602,1893],{"class":158},[64,3604,276],{"class":154},[64,3606,3555],{"class":197},[64,3608,270],{"class":3521},[64,3610,175],{"class":168},[64,3612,3562],{"class":73},[64,3614,175],{"class":168},[64,3616,311],{"class":3521},[64,3618,276],{"class":154},[64,3620,3571],{"class":197},[64,3622,270],{"class":3521},[64,3624,175],{"class":168},[64,3626,3627],{"class":73},"maxlength",[64,3629,175],{"class":168},[64,3631,399],{"class":154},[64,3633,169],{"class":168},[64,3635,1488],{"class":73},[64,3637,175],{"class":168},[64,3639,296],{"class":3521},[64,3641,178],{"class":154},[64,3643,3644,3646,3648,3650,3652,3654,3656,3658,3660,3663,3665,3667,3669,3671,3673,3675,3678,3680,3682,3684,3687,3689,3691],{"class":66,"line":2491},[64,3645,3511],{"class":150},[64,3647,3456],{"class":197},[64,3649,270],{"class":3521},[64,3651,1893],{"class":158},[64,3653,276],{"class":154},[64,3655,3555],{"class":197},[64,3657,270],{"class":3521},[64,3659,175],{"class":168},[64,3661,3662],{"class":73},"#cents",[64,3664,175],{"class":168},[64,3666,311],{"class":3521},[64,3668,276],{"class":154},[64,3670,3571],{"class":197},[64,3672,270],{"class":3521},[64,3674,175],{"class":168},[64,3676,3677],{"class":73},"max",[64,3679,175],{"class":168},[64,3681,399],{"class":154},[64,3683,169],{"class":168},[64,3685,3686],{"class":73},"1000000",[64,3688,175],{"class":168},[64,3690,296],{"class":3521},[64,3692,178],{"class":154},[64,3694,3695,3697,3699,3701,3703,3705,3707,3709,3711,3714,3716,3718,3720,3723,3725,3727,3729,3731,3733],{"class":66,"line":2496},[64,3696,3511],{"class":150},[64,3698,3456],{"class":197},[64,3700,270],{"class":3521},[64,3702,1893],{"class":158},[64,3704,276],{"class":154},[64,3706,3555],{"class":197},[64,3708,270],{"class":3521},[64,3710,175],{"class":168},[64,3712,3713],{"class":73},"#status",[64,3715,175],{"class":168},[64,3717,311],{"class":3521},[64,3719,276],{"class":154},[64,3721,3722],{"class":197},"toHaveValue",[64,3724,270],{"class":3521},[64,3726,175],{"class":168},[64,3728,3310],{"class":73},[64,3730,175],{"class":168},[64,3732,296],{"class":3521},[64,3734,178],{"class":154},[64,3736,3737,3739,3741,3743,3745,3747,3749,3751,3753,3756,3758,3760,3762,3765,3767,3769,3771],{"class":66,"line":2505},[64,3738,3511],{"class":150},[64,3740,3456],{"class":197},[64,3742,270],{"class":3521},[64,3744,1893],{"class":158},[64,3746,276],{"class":154},[64,3748,3555],{"class":197},[64,3750,270],{"class":3521},[64,3752,175],{"class":168},[64,3754,3755],{"class":73},"#status option",[64,3757,175],{"class":168},[64,3759,311],{"class":3521},[64,3761,276],{"class":154},[64,3763,3764],{"class":197},"toHaveCount",[64,3766,270],{"class":3521},[64,3768,1476],{"class":623},[64,3770,296],{"class":3521},[64,3772,178],{"class":154},[64,3774,3775,3777,3779],{"class":66,"line":2510},[64,3776,1183],{"class":154},[64,3778,296],{"class":200},[64,3780,178],{"class":154},[64,3782,3783],{"class":66,"line":2524},[64,3784,185],{"emptyLinePlaceholder":184},[64,3786,3787,3789,3791,3793,3796,3798,3800,3802,3804,3806,3808,3810],{"class":66,"line":2529},[64,3788,3478],{"class":197},[64,3790,270],{"class":200},[64,3792,175],{"class":168},[64,3794,3795],{"class":73},"le navigateur refuse ce que le serveur refuserait",[64,3797,175],{"class":168},[64,3799,399],{"class":154},[64,3801,3492],{"class":241},[64,3803,3495],{"class":154},[64,3805,3498],{"class":292},[64,3807,3501],{"class":154},[64,3809,300],{"class":299},[64,3811,3506],{"class":154},[64,3813,3814,3816,3818,3820,3822,3824,3826,3828,3830,3832],{"class":66,"line":2537},[64,3815,3511],{"class":150},[64,3817,3498],{"class":158},[64,3819,276],{"class":154},[64,3821,3518],{"class":197},[64,3823,270],{"class":3521},[64,3825,175],{"class":168},[64,3827,1547],{"class":73},[64,3829,175],{"class":168},[64,3831,296],{"class":3521},[64,3833,178],{"class":154},[64,3835,3836,3838,3840,3842,3845,3847,3849,3851,3853,3855,3857,3860,3862,3864,3866],{"class":66,"line":2555},[64,3837,3511],{"class":150},[64,3839,3498],{"class":158},[64,3841,276],{"class":154},[64,3843,3844],{"class":197},"fill",[64,3846,270],{"class":3521},[64,3848,175],{"class":168},[64,3850,3562],{"class":73},[64,3852,175],{"class":168},[64,3854,399],{"class":154},[64,3856,169],{"class":168},[64,3858,3859],{"class":73},"AB",[64,3861,175],{"class":168},[64,3863,296],{"class":3521},[64,3865,1046],{"class":154},[64,3867,3868],{"class":143},"           \u002F\u002F sous le minimum déclaré\n",[64,3870,3871,3873,3875,3877,3879,3881,3883,3886,3888,3890,3892,3895,3897,3899],{"class":66,"line":2603},[64,3872,3511],{"class":150},[64,3874,3498],{"class":158},[64,3876,276],{"class":154},[64,3878,3844],{"class":197},[64,3880,270],{"class":3521},[64,3882,175],{"class":168},[64,3884,3885],{"class":73},"#name",[64,3887,175],{"class":168},[64,3889,399],{"class":154},[64,3891,169],{"class":168},[64,3893,3894],{"class":73},"Une lampe",[64,3896,175],{"class":168},[64,3898,296],{"class":3521},[64,3900,178],{"class":154},[64,3902,3903,3905,3907,3909,3911,3913,3915,3917,3919,3921,3923,3925,3927,3929],{"class":66,"line":2608},[64,3904,3511],{"class":150},[64,3906,3498],{"class":158},[64,3908,276],{"class":154},[64,3910,3844],{"class":197},[64,3912,270],{"class":3521},[64,3914,175],{"class":168},[64,3916,3662],{"class":73},[64,3918,175],{"class":168},[64,3920,399],{"class":154},[64,3922,169],{"class":168},[64,3924,862],{"class":73},[64,3926,175],{"class":168},[64,3928,296],{"class":3521},[64,3930,178],{"class":154},[64,3932,3933,3935,3937,3939,3942,3944,3946,3949,3951,3953],{"class":66,"line":2613},[64,3934,3511],{"class":150},[64,3936,3498],{"class":158},[64,3938,276],{"class":154},[64,3940,3941],{"class":197},"click",[64,3943,270],{"class":3521},[64,3945,175],{"class":168},[64,3947,3948],{"class":73},"button[type=submit]",[64,3950,175],{"class":168},[64,3952,296],{"class":3521},[64,3954,178],{"class":154},[64,3956,3957],{"class":66,"line":2628},[64,3958,185],{"emptyLinePlaceholder":184},[64,3960,3961],{"class":66,"line":2654},[64,3962,3963],{"class":143},"  \u002F\u002F La page n'a envoyé aucune requête : la contrainte vient de l'entité, et c'est le\n",[64,3965,3966],{"class":66,"line":2659},[64,3967,3968],{"class":143},"  \u002F\u002F navigateur qui l'applique. Aucun code de validation dans la page.\n",[64,3970,3971,3973,3975,3977,3979,3981,3983,3985,3987,3989,3991,3993,3995,3998,4000],{"class":66,"line":2665},[64,3972,3511],{"class":150},[64,3974,3456],{"class":197},[64,3976,270],{"class":3521},[64,3978,1893],{"class":158},[64,3980,276],{"class":154},[64,3982,3555],{"class":197},[64,3984,270],{"class":3521},[64,3986,175],{"class":168},[64,3988,3562],{"class":73},[64,3990,175],{"class":168},[64,3992,311],{"class":3521},[64,3994,276],{"class":154},[64,3996,3997],{"class":197},"toBeFocused",[64,3999,201],{"class":3521},[64,4001,178],{"class":154},[64,4003,4004,4006,4008,4010,4012,4014,4016,4018,4020,4023,4025,4027,4029,4031,4033,4036,4038],{"class":66,"line":2671},[64,4005,3511],{"class":150},[64,4007,3456],{"class":197},[64,4009,270],{"class":3521},[64,4011,1893],{"class":158},[64,4013,276],{"class":154},[64,4015,3555],{"class":197},[64,4017,270],{"class":3521},[64,4019,175],{"class":168},[64,4021,4022],{"class":73},"#products li",[64,4024,175],{"class":168},[64,4026,311],{"class":3521},[64,4028,276],{"class":154},[64,4030,3764],{"class":197},[64,4032,270],{"class":3521},[64,4034,4035],{"class":623},"0",[64,4037,296],{"class":3521},[64,4039,178],{"class":154},[64,4041,4042,4044,4046],{"class":66,"line":2676},[64,4043,1183],{"class":154},[64,4045,296],{"class":200},[64,4047,178],{"class":154},[64,4049,4050],{"class":66,"line":2683},[64,4051,185],{"emptyLinePlaceholder":184},[64,4053,4054,4056,4058,4060,4063,4065,4067,4069,4071,4073,4075,4077],{"class":66,"line":2714},[64,4055,3478],{"class":197},[64,4057,270],{"class":200},[64,4059,175],{"class":168},[64,4061,4062],{"class":73},"un corps valide traverse la porte et la ligne apparaît",[64,4064,175],{"class":168},[64,4066,399],{"class":154},[64,4068,3492],{"class":241},[64,4070,3495],{"class":154},[64,4072,3498],{"class":292},[64,4074,3501],{"class":154},[64,4076,300],{"class":299},[64,4078,3506],{"class":154},[64,4080,4081,4083,4085,4087,4089,4091,4093,4095,4097,4099],{"class":66,"line":2743},[64,4082,3511],{"class":150},[64,4084,3498],{"class":158},[64,4086,276],{"class":154},[64,4088,3518],{"class":197},[64,4090,270],{"class":3521},[64,4092,175],{"class":168},[64,4094,1547],{"class":73},[64,4096,175],{"class":168},[64,4098,296],{"class":3521},[64,4100,178],{"class":154},[64,4102,4103,4105,4107,4109,4111,4113,4115,4117,4119,4121,4123,4126,4128,4130],{"class":66,"line":2748},[64,4104,3511],{"class":150},[64,4106,3498],{"class":158},[64,4108,276],{"class":154},[64,4110,3844],{"class":197},[64,4112,270],{"class":3521},[64,4114,175],{"class":168},[64,4116,3562],{"class":73},[64,4118,175],{"class":168},[64,4120,399],{"class":154},[64,4122,169],{"class":168},[64,4124,4125],{"class":73},"LAMP-01",[64,4127,175],{"class":168},[64,4129,296],{"class":3521},[64,4131,178],{"class":154},[64,4133,4134,4136,4138,4140,4142,4144,4146,4148,4150,4152,4154,4156,4158,4160],{"class":66,"line":2753},[64,4135,3511],{"class":150},[64,4137,3498],{"class":158},[64,4139,276],{"class":154},[64,4141,3844],{"class":197},[64,4143,270],{"class":3521},[64,4145,175],{"class":168},[64,4147,3885],{"class":73},[64,4149,175],{"class":168},[64,4151,399],{"class":154},[64,4153,169],{"class":168},[64,4155,3894],{"class":73},[64,4157,175],{"class":168},[64,4159,296],{"class":3521},[64,4161,178],{"class":154},[64,4163,4164,4166,4168,4170,4172,4174,4176,4178,4180,4182,4184,4187,4189,4191],{"class":66,"line":2759},[64,4165,3511],{"class":150},[64,4167,3498],{"class":158},[64,4169,276],{"class":154},[64,4171,3844],{"class":197},[64,4173,270],{"class":3521},[64,4175,175],{"class":168},[64,4177,3662],{"class":73},[64,4179,175],{"class":168},[64,4181,399],{"class":154},[64,4183,169],{"class":168},[64,4185,4186],{"class":73},"4990",[64,4188,175],{"class":168},[64,4190,296],{"class":3521},[64,4192,178],{"class":154},[64,4194,4195,4197,4199,4201,4203,4205,4207,4209,4211,4213],{"class":66,"line":2765},[64,4196,3511],{"class":150},[64,4198,3498],{"class":158},[64,4200,276],{"class":154},[64,4202,3941],{"class":197},[64,4204,270],{"class":3521},[64,4206,175],{"class":168},[64,4208,3948],{"class":73},[64,4210,175],{"class":168},[64,4212,296],{"class":3521},[64,4214,178],{"class":154},[64,4216,4217],{"class":66,"line":2771},[64,4218,185],{"emptyLinePlaceholder":184},[64,4220,4221,4223,4225,4227,4229,4231,4233,4235,4237,4240,4242,4244,4246,4249,4251,4253,4255,4257,4259],{"class":66,"line":2776},[64,4222,3511],{"class":150},[64,4224,3456],{"class":197},[64,4226,270],{"class":3521},[64,4228,1893],{"class":158},[64,4230,276],{"class":154},[64,4232,3555],{"class":197},[64,4234,270],{"class":3521},[64,4236,175],{"class":168},[64,4238,4239],{"class":73},"#products li[data-sku=\"LAMP-01\"]",[64,4241,175],{"class":168},[64,4243,311],{"class":3521},[64,4245,276],{"class":154},[64,4247,4248],{"class":197},"toHaveText",[64,4250,270],{"class":3521},[64,4252,175],{"class":168},[64,4254,3894],{"class":73},[64,4256,175],{"class":168},[64,4258,296],{"class":3521},[64,4260,178],{"class":154},[64,4262,4263,4265,4267],{"class":66,"line":2784},[64,4264,1183],{"class":154},[64,4266,296],{"class":200},[64,4268,178],{"class":154},[64,4270,4271],{"class":66,"line":2789},[64,4272,185],{"emptyLinePlaceholder":184},[64,4274,4275,4277,4279,4281,4284,4286,4288,4290,4292,4294,4296,4298],{"class":66,"line":2802},[64,4276,3478],{"class":197},[64,4278,270],{"class":200},[64,4280,175],{"class":168},[64,4282,4283],{"class":73},"le serveur refuse ce que le navigateur a laissé passer",[64,4285,175],{"class":168},[64,4287,399],{"class":154},[64,4289,3492],{"class":241},[64,4291,3495],{"class":154},[64,4293,3498],{"class":292},[64,4295,3501],{"class":154},[64,4297,300],{"class":299},[64,4299,3506],{"class":154},[64,4301,4302,4304,4306,4308,4310,4312,4314,4316,4318,4320],{"class":66,"line":2808},[64,4303,3511],{"class":150},[64,4305,3498],{"class":158},[64,4307,276],{"class":154},[64,4309,3518],{"class":197},[64,4311,270],{"class":3521},[64,4313,175],{"class":168},[64,4315,1547],{"class":73},[64,4317,175],{"class":168},[64,4319,296],{"class":3521},[64,4321,178],{"class":154},[64,4323,4324],{"class":66,"line":2813},[64,4325,4326],{"class":143},"  \u002F\u002F La balise ne connaît pas la casse ni l'unicité — mais le juge, lui, refuse une clé\n",[64,4328,4329],{"class":66,"line":2820},[64,4330,4331],{"class":143},"  \u002F\u002F hors contrat. Le formulaire est contourné exprès, comme le ferait un client écrit.\n",[64,4333,4334,4337,4340,4342,4344,4346,4348,4351,4353,4356,4358,4360],{"class":66,"line":2836},[64,4335,4336],{"class":241},"  const",[64,4338,4339],{"class":158}," answer",[64,4341,1920],{"class":154},[64,4343,251],{"class":150},[64,4345,3498],{"class":158},[64,4347,276],{"class":154},[64,4349,4350],{"class":197},"evaluate",[64,4352,270],{"class":3521},[64,4354,4355],{"class":241},"async",[64,4357,1934],{"class":154},[64,4359,300],{"class":299},[64,4361,3506],{"class":154},[64,4363,4364,4367,4370,4372,4374,4377,4379,4381,4384,4386,4388],{"class":66,"line":2867},[64,4365,4366],{"class":241},"    const",[64,4368,4369],{"class":158}," response",[64,4371,1920],{"class":154},[64,4373,251],{"class":150},[64,4375,4376],{"class":197}," fetch",[64,4378,270],{"class":3521},[64,4380,175],{"class":168},[64,4382,4383],{"class":73},"\u002F_fougere\u002Fcall",[64,4385,175],{"class":168},[64,4387,399],{"class":154},[64,4389,3506],{"class":154},[64,4391,4392,4395,4397,4399,4402,4404],{"class":66,"line":2898},[64,4393,4394],{"class":583},"      method",[64,4396,501],{"class":154},[64,4398,169],{"class":168},[64,4400,4401],{"class":73},"POST",[64,4403,175],{"class":168},[64,4405,2921],{"class":154},[64,4407,4408,4411,4413,4415,4417,4421,4423,4425,4427,4430,4432],{"class":66,"line":2903},[64,4409,4410],{"class":583},"      headers",[64,4412,501],{"class":154},[64,4414,155],{"class":154},[64,4416,169],{"class":168},[64,4418,4420],{"class":4419},"sK7Y8","content-type",[64,4422,175],{"class":168},[64,4424,501],{"class":154},[64,4426,169],{"class":168},[64,4428,4429],{"class":73},"application\u002Fjson",[64,4431,175],{"class":168},[64,4433,4434],{"class":154}," },\n",[64,4436,4437,4440,4442,4445,4447,4450,4452,4454,4457,4459,4461,4464,4466,4468,4470,4472,4475,4477,4480,4482,4484,4487,4489],{"class":66,"line":2908},[64,4438,4439],{"class":583},"      body",[64,4441,501],{"class":154},[64,4443,4444],{"class":158}," JSON",[64,4446,276],{"class":154},[64,4448,4449],{"class":197},"stringify",[64,4451,270],{"class":3521},[64,4453,717],{"class":154},[64,4455,4456],{"class":583}," jsonrpc",[64,4458,501],{"class":154},[64,4460,169],{"class":168},[64,4462,4463],{"class":73},"2.0",[64,4465,175],{"class":168},[64,4467,399],{"class":154},[64,4469,1175],{"class":583},[64,4471,501],{"class":154},[64,4473,4474],{"class":623}," 1",[64,4476,399],{"class":154},[64,4478,4479],{"class":583}," method",[64,4481,501],{"class":154},[64,4483,169],{"class":168},[64,4485,4486],{"class":73},"product.create",[64,4488,175],{"class":168},[64,4490,2921],{"class":154},[64,4492,4493,4496,4498,4500,4503,4505,4507,4510,4512,4514,4517,4519,4521,4523,4525,4527,4530,4532,4534,4536,4538,4540,4543,4545,4547,4550,4552,4554,4556,4559,4561,4563,4565,4567,4569,4572,4574,4576,4579,4581,4583,4586,4588,4591,4593,4595,4597],{"class":66,"line":2924},[64,4494,4495],{"class":583},"        params",[64,4497,501],{"class":154},[64,4499,155],{"class":154},[64,4501,4502],{"class":583}," params",[64,4504,501],{"class":154},[64,4506,613],{"class":154},[64,4508,4509],{"class":583}," query",[64,4511,501],{"class":154},[64,4513,613],{"class":154},[64,4515,4516],{"class":583}," input",[64,4518,501],{"class":154},[64,4520,155],{"class":154},[64,4522,584],{"class":583},[64,4524,501],{"class":154},[64,4526,169],{"class":168},[64,4528,4529],{"class":73},"LAMP-02",[64,4531,175],{"class":168},[64,4533,399],{"class":154},[64,4535,1444],{"class":583},[64,4537,501],{"class":154},[64,4539,169],{"class":168},[64,4541,4542],{"class":73},"x",[64,4544,175],{"class":168},[64,4546,399],{"class":154},[64,4548,4549],{"class":583}," cents",[64,4551,501],{"class":154},[64,4553,4474],{"class":623},[64,4555,399],{"class":154},[64,4557,4558],{"class":583}," status",[64,4560,501],{"class":154},[64,4562,169],{"class":168},[64,4564,3310],{"class":73},[64,4566,175],{"class":168},[64,4568,399],{"class":154},[64,4570,4571],{"class":583}," couleur",[64,4573,501],{"class":154},[64,4575,169],{"class":168},[64,4577,4578],{"class":73},"rouge",[64,4580,175],{"class":168},[64,4582,815],{"class":154},[64,4584,4585],{"class":583}," state",[64,4587,501],{"class":154},[64,4589,4590],{"class":154}," {}",[64,4592,162],{"class":154},[64,4594,162],{"class":154},[64,4596,296],{"class":3521},[64,4598,2921],{"class":154},[64,4600,4601,4604,4606],{"class":66,"line":2954},[64,4602,4603],{"class":154},"    }",[64,4605,296],{"class":3521},[64,4607,178],{"class":154},[64,4609,4610],{"class":66,"line":2976},[64,4611,185],{"emptyLinePlaceholder":184},[64,4613,4614,4617,4619,4621,4624,4626],{"class":66,"line":2981},[64,4615,4616],{"class":150},"    return",[64,4618,4369],{"class":158},[64,4620,276],{"class":154},[64,4622,4623],{"class":197},"json",[64,4625,201],{"class":3521},[64,4627,178],{"class":154},[64,4629,4630,4633,4635,4637,4639,4642,4645,4647,4650,4652,4655,4657],{"class":66,"line":2997},[64,4631,4632],{"class":154},"  }",[64,4634,296],{"class":3521},[64,4636,1004],{"class":150},[64,4638,155],{"class":154},[64,4640,4641],{"class":583}," error",[64,4643,4644],{"class":154},"?:",[64,4646,155],{"class":154},[64,4648,4649],{"class":583}," message",[64,4651,501],{"class":154},[64,4653,4654],{"class":942}," string",[64,4656,162],{"class":154},[64,4658,4659],{"class":154}," };\n",[64,4661,4662],{"class":66,"line":3003},[64,4663,185],{"emptyLinePlaceholder":184},[64,4665,4666,4669,4671,4674,4676,4679,4682,4685,4687,4689,4692,4694,4696,4699,4701,4703],{"class":66,"line":3009},[64,4667,4668],{"class":197},"  expect",[64,4670,270],{"class":3521},[64,4672,4673],{"class":158},"answer",[64,4675,276],{"class":154},[64,4677,4678],{"class":279},"error",[64,4680,4681],{"class":154},"?.",[64,4683,4684],{"class":279},"message",[64,4686,296],{"class":3521},[64,4688,276],{"class":154},[64,4690,4691],{"class":197},"toContain",[64,4693,270],{"class":3521},[64,4695,175],{"class":168},[64,4697,4698],{"class":73},"Unknown field",[64,4700,175],{"class":168},[64,4702,296],{"class":3521},[64,4704,178],{"class":154},[64,4706,4707,4709,4711],{"class":66,"line":3014},[64,4708,1183],{"class":154},[64,4710,296],{"class":200},[64,4712,178],{"class":154},[54,4714,4716],{"className":134,"code":4715,"filename":337,"language":136,"meta":60,"style":60},"import '@fougere\u002Fadapter-rest';\nimport '@fougere\u002Fadapter-graphql';\nimport '@fougere\u002Fadapter-sql';\nimport { defineFougere } from '@fougere\u002Fcore';\n\nexport default defineFougere({\n  sources: { main: { type: 'sqlite', path: 'fougere.db' } },\n  protocols: { rest: {}, graphql: {} },\n  fronds: { '@fougere\u002Flog': {} },\n});\n\n",[17,4717,4718,4731,4744,4756,4778,4782,4795,4840,4865,4887],{"__ignoreMap":60},[64,4719,4720,4722,4724,4727,4729],{"class":66,"line":67},[64,4721,151],{"class":150},[64,4723,169],{"class":168},[64,4725,4726],{"class":73},"@fougere\u002Fadapter-rest",[64,4728,175],{"class":168},[64,4730,178],{"class":154},[64,4732,4733,4735,4737,4740,4742],{"class":66,"line":147},[64,4734,151],{"class":150},[64,4736,169],{"class":168},[64,4738,4739],{"class":73},"@fougere\u002Fadapter-graphql",[64,4741,175],{"class":168},[64,4743,178],{"class":154},[64,4745,4746,4748,4750,4752,4754],{"class":66,"line":181},[64,4747,151],{"class":150},[64,4749,169],{"class":168},[64,4751,2005],{"class":73},[64,4753,175],{"class":168},[64,4755,178],{"class":154},[64,4757,4758,4760,4762,4765,4767,4769,4771,4774,4776],{"class":66,"line":188},[64,4759,151],{"class":150},[64,4761,155],{"class":154},[64,4763,4764],{"class":158}," defineFougere",[64,4766,162],{"class":154},[64,4768,165],{"class":150},[64,4770,169],{"class":168},[64,4772,4773],{"class":73},"@fougere\u002Fcore",[64,4775,175],{"class":168},[64,4777,178],{"class":154},[64,4779,4780],{"class":66,"line":825},[64,4781,185],{"emptyLinePlaceholder":184},[64,4783,4784,4786,4788,4790,4792],{"class":66,"line":830},[64,4785,191],{"class":150},[64,4787,194],{"class":150},[64,4789,4764],{"class":197},[64,4791,270],{"class":200},[64,4793,4794],{"class":154},"{\n",[64,4796,4797,4800,4802,4804,4807,4809,4811,4813,4815,4817,4820,4822,4824,4827,4829,4831,4834,4836,4838],{"class":66,"line":1760},[64,4798,4799],{"class":583},"  sources",[64,4801,501],{"class":154},[64,4803,155],{"class":154},[64,4805,4806],{"class":583}," main",[64,4808,501],{"class":154},[64,4810,155],{"class":154},[64,4812,1455],{"class":583},[64,4814,501],{"class":154},[64,4816,169],{"class":168},[64,4818,4819],{"class":73},"sqlite",[64,4821,175],{"class":168},[64,4823,399],{"class":154},[64,4825,4826],{"class":583}," path",[64,4828,501],{"class":154},[64,4830,169],{"class":168},[64,4832,4833],{"class":73},"fougere.db",[64,4835,175],{"class":168},[64,4837,162],{"class":154},[64,4839,4434],{"class":154},[64,4841,4842,4845,4847,4849,4852,4854,4856,4859,4861,4863],{"class":66,"line":2418},[64,4843,4844],{"class":583},"  protocols",[64,4846,501],{"class":154},[64,4848,155],{"class":154},[64,4850,4851],{"class":583}," rest",[64,4853,501],{"class":154},[64,4855,613],{"class":154},[64,4857,4858],{"class":583}," graphql",[64,4860,501],{"class":154},[64,4862,4590],{"class":154},[64,4864,4434],{"class":154},[64,4866,4867,4870,4872,4874,4876,4879,4881,4883,4885],{"class":66,"line":2424},[64,4868,4869],{"class":583},"  fronds",[64,4871,501],{"class":154},[64,4873,155],{"class":154},[64,4875,169],{"class":168},[64,4877,4878],{"class":4419},"@fougere\u002Flog",[64,4880,175],{"class":168},[64,4882,501],{"class":154},[64,4884,4590],{"class":154},[64,4886,4434],{"class":154},[64,4888,4889,4891,4893],{"class":66,"line":2430},[64,4890,1183],{"class":154},[64,4892,296],{"class":200},[64,4894,178],{"class":154},[54,4896,4898],{"className":134,"code":4897,"filename":2365,"language":136,"meta":60,"style":60},"import { entity, primary, text, number, oneOf, created } from '@fougere\u002Fschema';\n\nexport default class Product extends entity({\n  id: primary(),\n  sku: text({ min: 3, max: 12 }),\n  name: text({ min: 1, max: 60 }),\n  cents: number({ integer: true, min: 1, max: 1_000_000 }),\n  status: oneOf('draft', 'listed', 'withdrawn'),\n  createdAt: created(),\n}) {}\n\n",[17,4899,4900,4947,4951,4971,4984,5021,5055,5100,5137,5150],{"__ignoreMap":60},[64,4901,4902,4904,4906,4909,4911,4914,4916,4919,4921,4924,4926,4929,4931,4934,4936,4938,4940,4943,4945],{"class":66,"line":67},[64,4903,151],{"class":150},[64,4905,155],{"class":154},[64,4907,4908],{"class":158}," entity",[64,4910,399],{"class":154},[64,4912,4913],{"class":158}," primary",[64,4915,399],{"class":154},[64,4917,4918],{"class":158}," text",[64,4920,399],{"class":154},[64,4922,4923],{"class":158}," number",[64,4925,399],{"class":154},[64,4927,4928],{"class":158}," oneOf",[64,4930,399],{"class":154},[64,4932,4933],{"class":158}," created",[64,4935,162],{"class":154},[64,4937,165],{"class":150},[64,4939,169],{"class":168},[64,4941,4942],{"class":73},"@fougere\u002Fschema",[64,4944,175],{"class":168},[64,4946,178],{"class":154},[64,4948,4949],{"class":66,"line":147},[64,4950,185],{"emptyLinePlaceholder":184},[64,4952,4953,4955,4957,4960,4962,4965,4967,4969],{"class":66,"line":181},[64,4954,191],{"class":150},[64,4956,194],{"class":150},[64,4958,4959],{"class":241}," class",[64,4961,1041],{"class":942},[64,4963,4964],{"class":241}," extends",[64,4966,4908],{"class":197},[64,4968,270],{"class":200},[64,4970,4794],{"class":154},[64,4972,4973,4976,4978,4980,4982],{"class":66,"line":188},[64,4974,4975],{"class":583},"  id",[64,4977,501],{"class":154},[64,4979,4913],{"class":197},[64,4981,201],{"class":200},[64,4983,2921],{"class":154},[64,4985,4986,4989,4991,4993,4995,4997,5000,5002,5005,5007,5010,5012,5015,5017,5019],{"class":66,"line":825},[64,4987,4988],{"class":583},"  sku",[64,4990,501],{"class":154},[64,4992,4918],{"class":197},[64,4994,270],{"class":200},[64,4996,717],{"class":154},[64,4998,4999],{"class":583}," min",[64,5001,501],{"class":154},[64,5003,5004],{"class":623}," 3",[64,5006,399],{"class":154},[64,5008,5009],{"class":583}," max",[64,5011,501],{"class":154},[64,5013,5014],{"class":623}," 12",[64,5016,162],{"class":154},[64,5018,296],{"class":200},[64,5020,2921],{"class":154},[64,5022,5023,5026,5028,5030,5032,5034,5036,5038,5040,5042,5044,5046,5049,5051,5053],{"class":66,"line":830},[64,5024,5025],{"class":583},"  name",[64,5027,501],{"class":154},[64,5029,4918],{"class":197},[64,5031,270],{"class":200},[64,5033,717],{"class":154},[64,5035,4999],{"class":583},[64,5037,501],{"class":154},[64,5039,4474],{"class":623},[64,5041,399],{"class":154},[64,5043,5009],{"class":583},[64,5045,501],{"class":154},[64,5047,5048],{"class":623}," 60",[64,5050,162],{"class":154},[64,5052,296],{"class":200},[64,5054,2921],{"class":154},[64,5056,5057,5060,5062,5064,5066,5068,5071,5073,5077,5079,5081,5083,5085,5087,5089,5091,5094,5096,5098],{"class":66,"line":1760},[64,5058,5059],{"class":583},"  cents",[64,5061,501],{"class":154},[64,5063,4923],{"class":197},[64,5065,270],{"class":200},[64,5067,717],{"class":154},[64,5069,5070],{"class":583}," integer",[64,5072,501],{"class":154},[64,5074,5076],{"class":5075},"slmMI"," true",[64,5078,399],{"class":154},[64,5080,4999],{"class":583},[64,5082,501],{"class":154},[64,5084,4474],{"class":623},[64,5086,399],{"class":154},[64,5088,5009],{"class":583},[64,5090,501],{"class":154},[64,5092,5093],{"class":623}," 1_000_000",[64,5095,162],{"class":154},[64,5097,296],{"class":200},[64,5099,2921],{"class":154},[64,5101,5102,5105,5107,5109,5111,5113,5115,5117,5119,5121,5123,5125,5127,5129,5131,5133,5135],{"class":66,"line":2418},[64,5103,5104],{"class":583},"  status",[64,5106,501],{"class":154},[64,5108,4928],{"class":197},[64,5110,270],{"class":200},[64,5112,175],{"class":168},[64,5114,3310],{"class":73},[64,5116,175],{"class":168},[64,5118,399],{"class":154},[64,5120,169],{"class":168},[64,5122,3324],{"class":73},[64,5124,175],{"class":168},[64,5126,399],{"class":154},[64,5128,169],{"class":168},[64,5130,3337],{"class":73},[64,5132,175],{"class":168},[64,5134,296],{"class":200},[64,5136,2921],{"class":154},[64,5138,5139,5142,5144,5146,5148],{"class":66,"line":2424},[64,5140,5141],{"class":583},"  createdAt",[64,5143,501],{"class":154},[64,5145,4933],{"class":197},[64,5147,201],{"class":200},[64,5149,2921],{"class":154},[64,5151,5152,5154,5156],{"class":66,"line":2430},[64,5153,1183],{"class":154},[64,5155,296],{"class":200},[64,5157,5158],{"class":154}," {}\n",[54,5160,5163],{"className":134,"code":5161,"filename":5162,"language":136,"meta":60,"style":60},"import { Repository } from '@fougere\u002Fcore';\nimport Product from '..\u002Fentities\u002FProduct.js';\nimport Pricing from '..\u002Fservices\u002FPricing.js';\n\nexport default class ProductHandler extends Repository\u003CProduct> {\n  constructor(products: Repository\u003CProduct>, private pricing: Pricing) {\n    super();\n  }\n\n  \u002F** The price a buyer pays, rate included. *\u002F\n  async quote(input: Product): Promise\u003C{ sku: string; total: number }> {\n    return { sku: input.sku, total: this.pricing.total(input.cents) };\n  }\n}\n\n","fronds\u002Fcatalog\u002Fhandlers\u002FProductHandler.ts",[17,5164,5165,5186,5205,5223,5227,5250,5285,5295,5300,5304,5309,5355,5402,5406],{"__ignoreMap":60},[64,5166,5167,5169,5171,5174,5176,5178,5180,5182,5184],{"class":66,"line":67},[64,5168,151],{"class":150},[64,5170,155],{"class":154},[64,5172,5173],{"class":158}," Repository",[64,5175,162],{"class":154},[64,5177,165],{"class":150},[64,5179,169],{"class":168},[64,5181,4773],{"class":73},[64,5183,175],{"class":168},[64,5185,178],{"class":154},[64,5187,5188,5190,5193,5196,5198,5201,5203],{"class":66,"line":147},[64,5189,151],{"class":150},[64,5191,5192],{"class":158}," Product ",[64,5194,5195],{"class":150},"from",[64,5197,169],{"class":168},[64,5199,5200],{"class":73},"..\u002Fentities\u002FProduct.js",[64,5202,175],{"class":168},[64,5204,178],{"class":154},[64,5206,5207,5209,5212,5214,5216,5219,5221],{"class":66,"line":181},[64,5208,151],{"class":150},[64,5210,5211],{"class":158}," Pricing ",[64,5213,5195],{"class":150},[64,5215,169],{"class":168},[64,5217,5218],{"class":73},"..\u002Fservices\u002FPricing.js",[64,5220,175],{"class":168},[64,5222,178],{"class":154},[64,5224,5225],{"class":66,"line":188},[64,5226,185],{"emptyLinePlaceholder":184},[64,5228,5229,5231,5233,5235,5238,5240,5242,5244,5246,5248],{"class":66,"line":825},[64,5230,191],{"class":150},[64,5232,194],{"class":150},[64,5234,4959],{"class":241},[64,5236,5237],{"class":942}," ProductHandler",[64,5239,4964],{"class":241},[64,5241,5173],{"class":942},[64,5243,939],{"class":154},[64,5245,563],{"class":942},[64,5247,945],{"class":154},[64,5249,3506],{"class":154},[64,5251,5252,5255,5257,5260,5262,5264,5266,5268,5271,5274,5277,5279,5281,5283],{"class":66,"line":830},[64,5253,5254],{"class":241},"  constructor",[64,5256,270],{"class":154},[64,5258,5259],{"class":292},"products",[64,5261,501],{"class":154},[64,5263,5173],{"class":942},[64,5265,939],{"class":154},[64,5267,563],{"class":942},[64,5269,5270],{"class":154},">,",[64,5272,5273],{"class":241}," private",[64,5275,5276],{"class":292}," pricing",[64,5278,501],{"class":154},[64,5280,1007],{"class":942},[64,5282,296],{"class":154},[64,5284,3506],{"class":154},[64,5286,5287,5291,5293],{"class":66,"line":1760},[64,5288,5290],{"class":5289},"sTljH","    super",[64,5292,201],{"class":3521},[64,5294,178],{"class":154},[64,5296,5297],{"class":66,"line":2418},[64,5298,5299],{"class":154},"  }\n",[64,5301,5302],{"class":66,"line":2424},[64,5303,185],{"emptyLinePlaceholder":184},[64,5305,5306],{"class":66,"line":2430},[64,5307,5308],{"class":143},"  \u002F** The price a buyer pays, rate included. *\u002F\n",[64,5310,5311,5314,5318,5320,5322,5324,5326,5329,5332,5335,5337,5339,5341,5343,5346,5348,5350,5353],{"class":66,"line":2436},[64,5312,5313],{"class":241},"  async",[64,5315,5317],{"class":5316},"shDkW"," quote",[64,5319,270],{"class":154},[64,5321,1428],{"class":292},[64,5323,501],{"class":154},[64,5325,1041],{"class":942},[64,5327,5328],{"class":154},"):",[64,5330,5331],{"class":942}," Promise",[64,5333,5334],{"class":154},"\u003C{",[64,5336,584],{"class":583},[64,5338,501],{"class":154},[64,5340,4654],{"class":942},[64,5342,1046],{"class":154},[64,5344,5345],{"class":583}," total",[64,5347,501],{"class":154},[64,5349,4923],{"class":942},[64,5351,5352],{"class":154}," }>",[64,5354,3506],{"class":154},[64,5356,5357,5359,5361,5363,5365,5367,5369,5371,5373,5375,5377,5381,5383,5385,5387,5389,5391,5393,5395,5398,5400],{"class":66,"line":2442},[64,5358,4616],{"class":150},[64,5360,155],{"class":154},[64,5362,584],{"class":583},[64,5364,501],{"class":154},[64,5366,4516],{"class":158},[64,5368,276],{"class":154},[64,5370,1439],{"class":279},[64,5372,399],{"class":154},[64,5374,5345],{"class":583},[64,5376,501],{"class":154},[64,5378,5380],{"class":5379},"sxG60"," this",[64,5382,276],{"class":154},[64,5384,958],{"class":279},[64,5386,276],{"class":154},[64,5388,757],{"class":197},[64,5390,270],{"class":3521},[64,5392,1428],{"class":158},[64,5394,276],{"class":154},[64,5396,5397],{"class":279},"cents",[64,5399,296],{"class":3521},[64,5401,4659],{"class":154},[64,5403,5404],{"class":66,"line":2448},[64,5405,5299],{"class":154},[64,5407,5408],{"class":66,"line":2453},[64,5409,5410],{"class":154},"}\n",[54,5412,5415],{"className":134,"code":5413,"filename":5414,"language":136,"meta":60,"style":60},"\u002F**\n * The port. Nothing declares it as one — `class VatPricing extends Pricing` does.\n * In a test it is the one thing worth standing in for: a rate is a fact about the\n * outside world, not about the catalog.\n *\u002F\nexport default class Pricing {\n  total(cents: number): number {\n    return cents;\n  }\n}\n\n","fronds\u002Fcatalog\u002Fservices\u002FPricing.ts",[17,5416,5417,5421,5426,5431,5436,5440,5452,5471,5479,5483],{"__ignoreMap":60},[64,5418,5419],{"class":66,"line":67},[64,5420,3407],{"class":143},[64,5422,5423],{"class":66,"line":147},[64,5424,5425],{"class":143}," * The port. Nothing declares it as one — `class VatPricing extends Pricing` does.\n",[64,5427,5428],{"class":66,"line":181},[64,5429,5430],{"class":143}," * In a test it is the one thing worth standing in for: a rate is a fact about the\n",[64,5432,5433],{"class":66,"line":188},[64,5434,5435],{"class":143}," * outside world, not about the catalog.\n",[64,5437,5438],{"class":66,"line":825},[64,5439,3442],{"class":143},[64,5441,5442,5444,5446,5448,5450],{"class":66,"line":830},[64,5443,191],{"class":150},[64,5445,194],{"class":150},[64,5447,4959],{"class":241},[64,5449,1007],{"class":942},[64,5451,3506],{"class":154},[64,5453,5454,5457,5459,5461,5463,5465,5467,5469],{"class":66,"line":1760},[64,5455,5456],{"class":5316},"  total",[64,5458,270],{"class":154},[64,5460,5397],{"class":292},[64,5462,501],{"class":154},[64,5464,4923],{"class":942},[64,5466,5328],{"class":154},[64,5468,4923],{"class":942},[64,5470,3506],{"class":154},[64,5472,5473,5475,5477],{"class":66,"line":2418},[64,5474,4616],{"class":150},[64,5476,4549],{"class":158},[64,5478,178],{"class":154},[64,5480,5481],{"class":66,"line":2424},[64,5482,5299],{"class":154},[64,5484,5485],{"class":66,"line":2430},[64,5486,5410],{"class":154},[54,5488,5491],{"className":134,"code":5489,"filename":5490,"language":136,"meta":60,"style":60},"import Pricing from '.\u002FPricing.js';\n\nexport default class VatPricing extends Pricing {\n  total(cents: number): number {\n    return Math.round(cents * 1.2);\n  }\n}\n\n","fronds\u002Fcatalog\u002Fservices\u002FVatPricing.ts",[17,5492,5493,5510,5514,5531,5549,5574,5578],{"__ignoreMap":60},[64,5494,5495,5497,5499,5501,5503,5506,5508],{"class":66,"line":67},[64,5496,151],{"class":150},[64,5498,5211],{"class":158},[64,5500,5195],{"class":150},[64,5502,169],{"class":168},[64,5504,5505],{"class":73},".\u002FPricing.js",[64,5507,175],{"class":168},[64,5509,178],{"class":154},[64,5511,5512],{"class":66,"line":147},[64,5513,185],{"emptyLinePlaceholder":184},[64,5515,5516,5518,5520,5522,5525,5527,5529],{"class":66,"line":181},[64,5517,191],{"class":150},[64,5519,194],{"class":150},[64,5521,4959],{"class":241},[64,5523,5524],{"class":942}," VatPricing",[64,5526,4964],{"class":241},[64,5528,1007],{"class":942},[64,5530,3506],{"class":154},[64,5532,5533,5535,5537,5539,5541,5543,5545,5547],{"class":66,"line":188},[64,5534,5456],{"class":5316},[64,5536,270],{"class":154},[64,5538,5397],{"class":292},[64,5540,501],{"class":154},[64,5542,4923],{"class":942},[64,5544,5328],{"class":154},[64,5546,4923],{"class":942},[64,5548,3506],{"class":154},[64,5550,5551,5553,5556,5558,5561,5563,5565,5567,5570,5572],{"class":66,"line":825},[64,5552,4616],{"class":150},[64,5554,5555],{"class":158}," Math",[64,5557,276],{"class":154},[64,5559,5560],{"class":197},"round",[64,5562,270],{"class":3521},[64,5564,5397],{"class":158},[64,5566,1975],{"class":154},[64,5568,5569],{"class":623}," 1.2",[64,5571,296],{"class":3521},[64,5573,178],{"class":154},[64,5575,5576],{"class":66,"line":830},[64,5577,5299],{"class":154},[64,5579,5580],{"class":66,"line":1760},[64,5581,5410],{"class":154},[54,5583,5585],{"className":134,"code":5584,"filename":2516,"language":136,"meta":60,"style":60},"\u002F**\n * CRAN 1 — un frond.\n *\n * Ce fichier est dans `fronds\u002Fcatalog\u002Ftests\u002F`, et ça suffit : `testApp()` ne reçoit\n * aucun argument. La position dit le projet et dit le sujet, exactement comme\n * `entities\u002F` dit à la lecture ce qu'un dossier contient. Le frond `orders` n'est pas\n * monté — même énoncé que `remotes:` en production.\n *\u002F\nimport { describe, it, expect } from 'vitest';\nimport { createLocalRunner } from '@fougere\u002Fcore';\nimport { Invocation } from '@fougere\u002Fcore\u002Fcontract';\nimport { testApp, sampleInput } from '@fougere\u002Ftesting';\nimport Product from '..\u002Fentities\u002FProduct.js';\nimport Pricing from '..\u002Fservices\u002FPricing.js';\n\ndescribe('le frond catalog, seul', () => {\n  it('ne monte que lui', async () => {\n    await using app = await testApp();\n\n    expect(app.fronds.map((frond) => frond.name)).toEqual(['catalog']);\n  });\n\n  it('facture au tarif que la réalisation applique', async () => {\n    await using app = await testApp();\n\n    const quote = await createLocalRunner(app)({ address: 'product', op: 'quote' }, {\n      ...Invocation.empty,\n      input: sampleInput(Product, { sku: 'ABC-01', cents: 1000 }),\n    });\n\n    \u002F\u002F `class VatPricing extends Pricing` EST l'enregistrement : personne ne le câble.\n    expect(quote).toEqual({ sku: 'ABC-01', total: 1200 });\n  });\n\n  it('facture ce que le test décide, quand le tarif est bouché', async () => {\n    await using app = await testApp({ stub: [Pricing] });\n    app.stub(Pricing).total.mockReturnValue(4242);\n\n    const quote = await createLocalRunner(app)({ address: 'product', op: 'quote' }, {\n      ...Invocation.empty,\n      input: sampleInput(Product, { sku: 'ABC-01', cents: 1000 }),\n    });\n\n    expect(quote).toEqual({ sku: 'ABC-01', total: 4242 });\n    expect(app.stub(Pricing).total).toHaveBeenCalledWith(1000);\n  });\n});\n\n",[17,5586,5587,5591,5596,5600,5605,5610,5615,5620,5624,5655,5676,5698,5723,5739,5755,5759,5781,5805,5822,5826,5877,5885,5889,5912,5928,5932,5979,5994,6036,6044,6048,6053,6096,6104,6108,6131,6163,6194,6198,6244,6256,6296,6304,6308,6351,6387,6395],{"__ignoreMap":60},[64,5588,5589],{"class":66,"line":67},[64,5590,3407],{"class":143},[64,5592,5593],{"class":66,"line":147},[64,5594,5595],{"class":143}," * CRAN 1 — un frond.\n",[64,5597,5598],{"class":66,"line":181},[64,5599,3417],{"class":143},[64,5601,5602],{"class":66,"line":188},[64,5603,5604],{"class":143}," * Ce fichier est dans `fronds\u002Fcatalog\u002Ftests\u002F`, et ça suffit : `testApp()` ne reçoit\n",[64,5606,5607],{"class":66,"line":825},[64,5608,5609],{"class":143}," * aucun argument. La position dit le projet et dit le sujet, exactement comme\n",[64,5611,5612],{"class":66,"line":830},[64,5613,5614],{"class":143}," * `entities\u002F` dit à la lecture ce qu'un dossier contient. Le frond `orders` n'est pas\n",[64,5616,5617],{"class":66,"line":1760},[64,5618,5619],{"class":143}," * monté — même énoncé que `remotes:` en production.\n",[64,5621,5622],{"class":66,"line":2418},[64,5623,3442],{"class":143},[64,5625,5626,5628,5630,5633,5635,5638,5640,5642,5644,5646,5648,5651,5653],{"class":66,"line":2424},[64,5627,151],{"class":150},[64,5629,155],{"class":154},[64,5631,5632],{"class":158}," describe",[64,5634,399],{"class":154},[64,5636,5637],{"class":158}," it",[64,5639,399],{"class":154},[64,5641,3456],{"class":158},[64,5643,162],{"class":154},[64,5645,165],{"class":150},[64,5647,169],{"class":168},[64,5649,5650],{"class":73},"vitest",[64,5652,175],{"class":168},[64,5654,178],{"class":154},[64,5656,5657,5659,5661,5664,5666,5668,5670,5672,5674],{"class":66,"line":2430},[64,5658,151],{"class":150},[64,5660,155],{"class":154},[64,5662,5663],{"class":158}," createLocalRunner",[64,5665,162],{"class":154},[64,5667,165],{"class":150},[64,5669,169],{"class":168},[64,5671,4773],{"class":73},[64,5673,175],{"class":168},[64,5675,178],{"class":154},[64,5677,5678,5680,5682,5685,5687,5689,5691,5694,5696],{"class":66,"line":2436},[64,5679,151],{"class":150},[64,5681,155],{"class":154},[64,5683,5684],{"class":158}," Invocation",[64,5686,162],{"class":154},[64,5688,165],{"class":150},[64,5690,169],{"class":168},[64,5692,5693],{"class":73},"@fougere\u002Fcore\u002Fcontract",[64,5695,175],{"class":168},[64,5697,178],{"class":154},[64,5699,5700,5702,5704,5706,5708,5711,5713,5715,5717,5719,5721],{"class":66,"line":2442},[64,5701,151],{"class":150},[64,5703,155],{"class":154},[64,5705,254],{"class":158},[64,5707,399],{"class":154},[64,5709,5710],{"class":158}," sampleInput",[64,5712,162],{"class":154},[64,5714,165],{"class":150},[64,5716,169],{"class":168},[64,5718,19],{"class":73},[64,5720,175],{"class":168},[64,5722,178],{"class":154},[64,5724,5725,5727,5729,5731,5733,5735,5737],{"class":66,"line":2448},[64,5726,151],{"class":150},[64,5728,5192],{"class":158},[64,5730,5195],{"class":150},[64,5732,169],{"class":168},[64,5734,5200],{"class":73},[64,5736,175],{"class":168},[64,5738,178],{"class":154},[64,5740,5741,5743,5745,5747,5749,5751,5753],{"class":66,"line":2453},[64,5742,151],{"class":150},[64,5744,5211],{"class":158},[64,5746,5195],{"class":150},[64,5748,169],{"class":168},[64,5750,5218],{"class":73},[64,5752,175],{"class":168},[64,5754,178],{"class":154},[64,5756,5757],{"class":66,"line":2479},[64,5758,185],{"emptyLinePlaceholder":184},[64,5760,5761,5764,5766,5768,5771,5773,5775,5777,5779],{"class":66,"line":2485},[64,5762,5763],{"class":197},"describe",[64,5765,270],{"class":200},[64,5767,175],{"class":168},[64,5769,5770],{"class":73},"le frond catalog, seul",[64,5772,175],{"class":168},[64,5774,399],{"class":154},[64,5776,1934],{"class":154},[64,5778,300],{"class":299},[64,5780,3506],{"class":154},[64,5782,5783,5786,5788,5790,5793,5795,5797,5799,5801,5803],{"class":66,"line":2491},[64,5784,5785],{"class":197},"  it",[64,5787,270],{"class":3521},[64,5789,175],{"class":168},[64,5791,5792],{"class":73},"ne monte que lui",[64,5794,175],{"class":168},[64,5796,399],{"class":154},[64,5798,3492],{"class":241},[64,5800,1934],{"class":154},[64,5802,300],{"class":299},[64,5804,3506],{"class":154},[64,5806,5807,5810,5812,5814,5816,5818,5820],{"class":66,"line":2496},[64,5808,5809],{"class":241},"    await using",[64,5811,1221],{"class":158},[64,5813,1920],{"class":154},[64,5815,251],{"class":150},[64,5817,254],{"class":197},[64,5819,201],{"class":3521},[64,5821,178],{"class":154},[64,5823,5824],{"class":66,"line":2505},[64,5825,185],{"emptyLinePlaceholder":184},[64,5827,5828,5831,5833,5835,5837,5839,5841,5843,5845,5847,5849,5851,5853,5855,5857,5859,5861,5863,5865,5867,5869,5871,5873,5875],{"class":66,"line":2510},[64,5829,5830],{"class":197},"    expect",[64,5832,270],{"class":3521},[64,5834,273],{"class":158},[64,5836,276],{"class":154},[64,5838,280],{"class":279},[64,5840,276],{"class":154},[64,5842,285],{"class":197},[64,5844,270],{"class":3521},[64,5846,270],{"class":154},[64,5848,293],{"class":292},[64,5850,296],{"class":154},[64,5852,300],{"class":299},[64,5854,303],{"class":158},[64,5856,276],{"class":154},[64,5858,308],{"class":279},[64,5860,311],{"class":3521},[64,5862,276],{"class":154},[64,5864,316],{"class":197},[64,5866,319],{"class":3521},[64,5868,175],{"class":168},[64,5870,324],{"class":73},[64,5872,175],{"class":168},[64,5874,329],{"class":3521},[64,5876,178],{"class":154},[64,5878,5879,5881,5883],{"class":66,"line":2524},[64,5880,4632],{"class":154},[64,5882,296],{"class":3521},[64,5884,178],{"class":154},[64,5886,5887],{"class":66,"line":2529},[64,5888,185],{"emptyLinePlaceholder":184},[64,5890,5891,5893,5895,5897,5900,5902,5904,5906,5908,5910],{"class":66,"line":2537},[64,5892,5785],{"class":197},[64,5894,270],{"class":3521},[64,5896,175],{"class":168},[64,5898,5899],{"class":73},"facture au tarif que la réalisation applique",[64,5901,175],{"class":168},[64,5903,399],{"class":154},[64,5905,3492],{"class":241},[64,5907,1934],{"class":154},[64,5909,300],{"class":299},[64,5911,3506],{"class":154},[64,5913,5914,5916,5918,5920,5922,5924,5926],{"class":66,"line":2555},[64,5915,5809],{"class":241},[64,5917,1221],{"class":158},[64,5919,1920],{"class":154},[64,5921,251],{"class":150},[64,5923,254],{"class":197},[64,5925,201],{"class":3521},[64,5927,178],{"class":154},[64,5929,5930],{"class":66,"line":2603},[64,5931,185],{"emptyLinePlaceholder":184},[64,5933,5934,5936,5938,5940,5942,5944,5946,5948,5951,5953,5955,5957,5959,5961,5963,5965,5967,5969,5971,5973,5975,5977],{"class":66,"line":2608},[64,5935,4366],{"class":241},[64,5937,5317],{"class":158},[64,5939,1920],{"class":154},[64,5941,251],{"class":150},[64,5943,5663],{"class":197},[64,5945,270],{"class":3521},[64,5947,273],{"class":158},[64,5949,5950],{"class":3521},")(",[64,5952,717],{"class":154},[64,5954,789],{"class":583},[64,5956,501],{"class":154},[64,5958,169],{"class":168},[64,5960,796],{"class":73},[64,5962,175],{"class":168},[64,5964,399],{"class":154},[64,5966,803],{"class":583},[64,5968,501],{"class":154},[64,5970,169],{"class":168},[64,5972,810],{"class":73},[64,5974,175],{"class":168},[64,5976,815],{"class":154},[64,5978,3506],{"class":154},[64,5980,5981,5984,5987,5989,5992],{"class":66,"line":2613},[64,5982,5983],{"class":154},"      ...",[64,5985,5986],{"class":158},"Invocation",[64,5988,276],{"class":154},[64,5990,5991],{"class":279},"empty",[64,5993,2921],{"class":154},[64,5995,5996,5999,6001,6003,6005,6007,6009,6011,6013,6015,6017,6019,6021,6023,6025,6027,6030,6032,6034],{"class":66,"line":2628},[64,5997,5998],{"class":583},"      input",[64,6000,501],{"class":154},[64,6002,5710],{"class":197},[64,6004,270],{"class":3521},[64,6006,563],{"class":158},[64,6008,399],{"class":154},[64,6010,155],{"class":154},[64,6012,584],{"class":583},[64,6014,501],{"class":154},[64,6016,169],{"class":168},[64,6018,591],{"class":73},[64,6020,175],{"class":168},[64,6022,399],{"class":154},[64,6024,4549],{"class":583},[64,6026,501],{"class":154},[64,6028,6029],{"class":623}," 1000",[64,6031,162],{"class":154},[64,6033,296],{"class":3521},[64,6035,2921],{"class":154},[64,6037,6038,6040,6042],{"class":66,"line":2654},[64,6039,4603],{"class":154},[64,6041,296],{"class":3521},[64,6043,178],{"class":154},[64,6045,6046],{"class":66,"line":2659},[64,6047,185],{"emptyLinePlaceholder":184},[64,6049,6050],{"class":66,"line":2665},[64,6051,6052],{"class":143},"    \u002F\u002F `class VatPricing extends Pricing` EST l'enregistrement : personne ne le câble.\n",[64,6054,6055,6057,6059,6061,6063,6065,6067,6069,6071,6073,6075,6077,6079,6081,6083,6085,6087,6090,6092,6094],{"class":66,"line":2671},[64,6056,5830],{"class":197},[64,6058,270],{"class":3521},[64,6060,810],{"class":158},[64,6062,296],{"class":3521},[64,6064,276],{"class":154},[64,6066,316],{"class":197},[64,6068,270],{"class":3521},[64,6070,717],{"class":154},[64,6072,584],{"class":583},[64,6074,501],{"class":154},[64,6076,169],{"class":168},[64,6078,591],{"class":73},[64,6080,175],{"class":168},[64,6082,399],{"class":154},[64,6084,5345],{"class":583},[64,6086,501],{"class":154},[64,6088,6089],{"class":623}," 1200",[64,6091,162],{"class":154},[64,6093,296],{"class":3521},[64,6095,178],{"class":154},[64,6097,6098,6100,6102],{"class":66,"line":2676},[64,6099,4632],{"class":154},[64,6101,296],{"class":3521},[64,6103,178],{"class":154},[64,6105,6106],{"class":66,"line":2683},[64,6107,185],{"emptyLinePlaceholder":184},[64,6109,6110,6112,6114,6116,6119,6121,6123,6125,6127,6129],{"class":66,"line":2714},[64,6111,5785],{"class":197},[64,6113,270],{"class":3521},[64,6115,175],{"class":168},[64,6117,6118],{"class":73},"facture ce que le test décide, quand le tarif est bouché",[64,6120,175],{"class":168},[64,6122,399],{"class":154},[64,6124,3492],{"class":241},[64,6126,1934],{"class":154},[64,6128,300],{"class":299},[64,6130,3506],{"class":154},[64,6132,6133,6135,6137,6139,6141,6143,6145,6147,6149,6151,6153,6155,6157,6159,6161],{"class":66,"line":2743},[64,6134,5809],{"class":241},[64,6136,1221],{"class":158},[64,6138,1920],{"class":154},[64,6140,251],{"class":150},[64,6142,254],{"class":197},[64,6144,270],{"class":3521},[64,6146,717],{"class":154},[64,6148,720],{"class":583},[64,6150,501],{"class":154},[64,6152,725],{"class":3521},[64,6154,728],{"class":158},[64,6156,731],{"class":3521},[64,6158,162],{"class":154},[64,6160,296],{"class":3521},[64,6162,178],{"class":154},[64,6164,6165,6168,6170,6172,6174,6176,6178,6180,6182,6184,6186,6188,6190,6192],{"class":66,"line":2748},[64,6166,6167],{"class":158},"    app",[64,6169,276],{"class":154},[64,6171,746],{"class":197},[64,6173,270],{"class":3521},[64,6175,728],{"class":158},[64,6177,296],{"class":3521},[64,6179,276],{"class":154},[64,6181,757],{"class":279},[64,6183,276],{"class":154},[64,6185,762],{"class":197},[64,6187,270],{"class":3521},[64,6189,767],{"class":623},[64,6191,296],{"class":3521},[64,6193,178],{"class":154},[64,6195,6196],{"class":66,"line":2753},[64,6197,185],{"emptyLinePlaceholder":184},[64,6199,6200,6202,6204,6206,6208,6210,6212,6214,6216,6218,6220,6222,6224,6226,6228,6230,6232,6234,6236,6238,6240,6242],{"class":66,"line":2759},[64,6201,4366],{"class":241},[64,6203,5317],{"class":158},[64,6205,1920],{"class":154},[64,6207,251],{"class":150},[64,6209,5663],{"class":197},[64,6211,270],{"class":3521},[64,6213,273],{"class":158},[64,6215,5950],{"class":3521},[64,6217,717],{"class":154},[64,6219,789],{"class":583},[64,6221,501],{"class":154},[64,6223,169],{"class":168},[64,6225,796],{"class":73},[64,6227,175],{"class":168},[64,6229,399],{"class":154},[64,6231,803],{"class":583},[64,6233,501],{"class":154},[64,6235,169],{"class":168},[64,6237,810],{"class":73},[64,6239,175],{"class":168},[64,6241,815],{"class":154},[64,6243,3506],{"class":154},[64,6245,6246,6248,6250,6252,6254],{"class":66,"line":2765},[64,6247,5983],{"class":154},[64,6249,5986],{"class":158},[64,6251,276],{"class":154},[64,6253,5991],{"class":279},[64,6255,2921],{"class":154},[64,6257,6258,6260,6262,6264,6266,6268,6270,6272,6274,6276,6278,6280,6282,6284,6286,6288,6290,6292,6294],{"class":66,"line":2771},[64,6259,5998],{"class":583},[64,6261,501],{"class":154},[64,6263,5710],{"class":197},[64,6265,270],{"class":3521},[64,6267,563],{"class":158},[64,6269,399],{"class":154},[64,6271,155],{"class":154},[64,6273,584],{"class":583},[64,6275,501],{"class":154},[64,6277,169],{"class":168},[64,6279,591],{"class":73},[64,6281,175],{"class":168},[64,6283,399],{"class":154},[64,6285,4549],{"class":583},[64,6287,501],{"class":154},[64,6289,6029],{"class":623},[64,6291,162],{"class":154},[64,6293,296],{"class":3521},[64,6295,2921],{"class":154},[64,6297,6298,6300,6302],{"class":66,"line":2776},[64,6299,4603],{"class":154},[64,6301,296],{"class":3521},[64,6303,178],{"class":154},[64,6305,6306],{"class":66,"line":2784},[64,6307,185],{"emptyLinePlaceholder":184},[64,6309,6310,6312,6314,6316,6318,6320,6322,6324,6326,6328,6330,6332,6334,6336,6338,6340,6342,6345,6347,6349],{"class":66,"line":2789},[64,6311,5830],{"class":197},[64,6313,270],{"class":3521},[64,6315,810],{"class":158},[64,6317,296],{"class":3521},[64,6319,276],{"class":154},[64,6321,316],{"class":197},[64,6323,270],{"class":3521},[64,6325,717],{"class":154},[64,6327,584],{"class":583},[64,6329,501],{"class":154},[64,6331,169],{"class":168},[64,6333,591],{"class":73},[64,6335,175],{"class":168},[64,6337,399],{"class":154},[64,6339,5345],{"class":583},[64,6341,501],{"class":154},[64,6343,6344],{"class":623}," 4242",[64,6346,162],{"class":154},[64,6348,296],{"class":3521},[64,6350,178],{"class":154},[64,6352,6353,6355,6357,6359,6361,6363,6365,6367,6369,6371,6373,6375,6377,6379,6381,6383,6385],{"class":66,"line":2802},[64,6354,5830],{"class":197},[64,6356,270],{"class":3521},[64,6358,273],{"class":158},[64,6360,276],{"class":154},[64,6362,746],{"class":197},[64,6364,270],{"class":3521},[64,6366,728],{"class":158},[64,6368,296],{"class":3521},[64,6370,276],{"class":154},[64,6372,757],{"class":279},[64,6374,296],{"class":3521},[64,6376,276],{"class":154},[64,6378,857],{"class":197},[64,6380,270],{"class":3521},[64,6382,862],{"class":623},[64,6384,296],{"class":3521},[64,6386,178],{"class":154},[64,6388,6389,6391,6393],{"class":66,"line":2808},[64,6390,4632],{"class":154},[64,6392,296],{"class":3521},[64,6394,178],{"class":154},[64,6396,6397,6399,6401],{"class":66,"line":2813},[64,6398,1183],{"class":154},[64,6400,296],{"class":200},[64,6402,178],{"class":154},[54,6404,6407],{"className":134,"code":6405,"filename":6406,"language":136,"meta":60,"style":60},"import { entity, primary, text, number, created } from '@fougere\u002Fschema';\n\nexport default class Order extends entity({\n  id: primary(),\n  sku: text({ min: 3, max: 12 }),\n  quantity: number({ integer: true, min: 1, max: 99 }),\n  placedAt: created(),\n}) {}\n\n","fronds\u002Forders\u002Fentities\u002FOrder.ts",[17,6408,6409,6445,6449,6467,6479,6511,6553,6566],{"__ignoreMap":60},[64,6410,6411,6413,6415,6417,6419,6421,6423,6425,6427,6429,6431,6433,6435,6437,6439,6441,6443],{"class":66,"line":67},[64,6412,151],{"class":150},[64,6414,155],{"class":154},[64,6416,4908],{"class":158},[64,6418,399],{"class":154},[64,6420,4913],{"class":158},[64,6422,399],{"class":154},[64,6424,4918],{"class":158},[64,6426,399],{"class":154},[64,6428,4923],{"class":158},[64,6430,399],{"class":154},[64,6432,4933],{"class":158},[64,6434,162],{"class":154},[64,6436,165],{"class":150},[64,6438,169],{"class":168},[64,6440,4942],{"class":73},[64,6442,175],{"class":168},[64,6444,178],{"class":154},[64,6446,6447],{"class":66,"line":147},[64,6448,185],{"emptyLinePlaceholder":184},[64,6450,6451,6453,6455,6457,6459,6461,6463,6465],{"class":66,"line":181},[64,6452,191],{"class":150},[64,6454,194],{"class":150},[64,6456,4959],{"class":241},[64,6458,2878],{"class":942},[64,6460,4964],{"class":241},[64,6462,4908],{"class":197},[64,6464,270],{"class":200},[64,6466,4794],{"class":154},[64,6468,6469,6471,6473,6475,6477],{"class":66,"line":188},[64,6470,4975],{"class":583},[64,6472,501],{"class":154},[64,6474,4913],{"class":197},[64,6476,201],{"class":200},[64,6478,2921],{"class":154},[64,6480,6481,6483,6485,6487,6489,6491,6493,6495,6497,6499,6501,6503,6505,6507,6509],{"class":66,"line":825},[64,6482,4988],{"class":583},[64,6484,501],{"class":154},[64,6486,4918],{"class":197},[64,6488,270],{"class":200},[64,6490,717],{"class":154},[64,6492,4999],{"class":583},[64,6494,501],{"class":154},[64,6496,5004],{"class":623},[64,6498,399],{"class":154},[64,6500,5009],{"class":583},[64,6502,501],{"class":154},[64,6504,5014],{"class":623},[64,6506,162],{"class":154},[64,6508,296],{"class":200},[64,6510,2921],{"class":154},[64,6512,6513,6516,6518,6520,6522,6524,6526,6528,6530,6532,6534,6536,6538,6540,6542,6544,6547,6549,6551],{"class":66,"line":830},[64,6514,6515],{"class":583},"  quantity",[64,6517,501],{"class":154},[64,6519,4923],{"class":197},[64,6521,270],{"class":200},[64,6523,717],{"class":154},[64,6525,5070],{"class":583},[64,6527,501],{"class":154},[64,6529,5076],{"class":5075},[64,6531,399],{"class":154},[64,6533,4999],{"class":583},[64,6535,501],{"class":154},[64,6537,4474],{"class":623},[64,6539,399],{"class":154},[64,6541,5009],{"class":583},[64,6543,501],{"class":154},[64,6545,6546],{"class":623}," 99",[64,6548,162],{"class":154},[64,6550,296],{"class":200},[64,6552,2921],{"class":154},[64,6554,6555,6558,6560,6562,6564],{"class":66,"line":1760},[64,6556,6557],{"class":583},"  placedAt",[64,6559,501],{"class":154},[64,6561,4933],{"class":197},[64,6563,201],{"class":200},[64,6565,2921],{"class":154},[64,6567,6568,6570,6572],{"class":66,"line":2418},[64,6569,1183],{"class":154},[64,6571,296],{"class":200},[64,6573,5158],{"class":154},[54,6575,6578],{"className":134,"code":6576,"filename":6577,"language":136,"meta":60,"style":60},"import { Repository } from '@fougere\u002Fcore';\nimport Order from '..\u002Fentities\u002FOrder.js';\n\nexport default class OrderHandler extends Repository\u003COrder> {}\n\n","fronds\u002Forders\u002Fhandlers\u002FOrderHandler.ts",[17,6579,6580,6600,6618,6622],{"__ignoreMap":60},[64,6581,6582,6584,6586,6588,6590,6592,6594,6596,6598],{"class":66,"line":67},[64,6583,151],{"class":150},[64,6585,155],{"class":154},[64,6587,5173],{"class":158},[64,6589,162],{"class":154},[64,6591,165],{"class":150},[64,6593,169],{"class":168},[64,6595,4773],{"class":73},[64,6597,175],{"class":168},[64,6599,178],{"class":154},[64,6601,6602,6604,6607,6609,6611,6614,6616],{"class":66,"line":147},[64,6603,151],{"class":150},[64,6605,6606],{"class":158}," Order ",[64,6608,5195],{"class":150},[64,6610,169],{"class":168},[64,6612,6613],{"class":73},"..\u002Fentities\u002FOrder.js",[64,6615,175],{"class":168},[64,6617,178],{"class":154},[64,6619,6620],{"class":66,"line":181},[64,6621,185],{"emptyLinePlaceholder":184},[64,6623,6624,6626,6628,6630,6633,6635,6637,6639,6642,6644],{"class":66,"line":188},[64,6625,191],{"class":150},[64,6627,194],{"class":150},[64,6629,4959],{"class":241},[64,6631,6632],{"class":942}," OrderHandler",[64,6634,4964],{"class":241},[64,6636,5173],{"class":942},[64,6638,939],{"class":154},[64,6640,6641],{"class":942},"Order",[64,6643,945],{"class":154},[64,6645,5158],{"class":154},[54,6647,6650],{"className":134,"code":6648,"filename":6649,"language":136,"meta":60,"style":60},"\u002F**\n * CRAN 3 — la charge.\n *\n * `pnpm load:gen` réécrit `load.js`. Le régénérer plutôt que le rapiécer : tout ce qu'il\n * contient est lu de ce que l'app répond, sauf les poids, les paliers et les seuils.\n *\u002F\nimport { writeFileSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { testApp, loadScript } from '@fougere\u002Ftesting';\n\nconst app = await testApp({ root: import.meta.dirname });\nwriteFileSync(join(import.meta.dirname, 'load.js'), loadScript(app, {\n  facade: 'http:\u002F\u002F127.0.0.1:4300\u002F_fougere\u002Fcall',\n}));\nawait app.dispose();\nconsole.log('✓ load.js');\n\n","gen-load.ts",[17,6651,6652,6656,6661,6665,6670,6675,6679,6699,6721,6745,6749,6789,6832,6848,6856,6870],{"__ignoreMap":60},[64,6653,6654],{"class":66,"line":67},[64,6655,3407],{"class":143},[64,6657,6658],{"class":66,"line":147},[64,6659,6660],{"class":143}," * CRAN 3 — la charge.\n",[64,6662,6663],{"class":66,"line":181},[64,6664,3417],{"class":143},[64,6666,6667],{"class":66,"line":188},[64,6668,6669],{"class":143}," * `pnpm load:gen` réécrit `load.js`. Le régénérer plutôt que le rapiécer : tout ce qu'il\n",[64,6671,6672],{"class":66,"line":825},[64,6673,6674],{"class":143}," * contient est lu de ce que l'app répond, sauf les poids, les paliers et les seuils.\n",[64,6676,6677],{"class":66,"line":830},[64,6678,3442],{"class":143},[64,6680,6681,6683,6685,6687,6689,6691,6693,6695,6697],{"class":66,"line":1760},[64,6682,151],{"class":150},[64,6684,155],{"class":154},[64,6686,1655],{"class":158},[64,6688,162],{"class":154},[64,6690,165],{"class":150},[64,6692,169],{"class":168},[64,6694,1664],{"class":73},[64,6696,175],{"class":168},[64,6698,178],{"class":154},[64,6700,6701,6703,6705,6708,6710,6712,6714,6717,6719],{"class":66,"line":2418},[64,6702,151],{"class":150},[64,6704,155],{"class":154},[64,6706,6707],{"class":158}," join",[64,6709,162],{"class":154},[64,6711,165],{"class":150},[64,6713,169],{"class":168},[64,6715,6716],{"class":73},"node:path",[64,6718,175],{"class":168},[64,6720,178],{"class":154},[64,6722,6723,6725,6727,6729,6731,6733,6735,6737,6739,6741,6743],{"class":66,"line":2424},[64,6724,151],{"class":150},[64,6726,155],{"class":154},[64,6728,254],{"class":158},[64,6730,399],{"class":154},[64,6732,1681],{"class":158},[64,6734,162],{"class":154},[64,6736,165],{"class":150},[64,6738,169],{"class":168},[64,6740,19],{"class":73},[64,6742,175],{"class":168},[64,6744,178],{"class":154},[64,6746,6747],{"class":66,"line":2430},[64,6748,185],{"emptyLinePlaceholder":184},[64,6750,6751,6753,6755,6757,6759,6761,6763,6765,6768,6770,6773,6775,6778,6780,6783,6785,6787],{"class":66,"line":2436},[64,6752,929],{"class":241},[64,6754,245],{"class":158},[64,6756,248],{"class":154},[64,6758,251],{"class":150},[64,6760,254],{"class":197},[64,6762,270],{"class":200},[64,6764,717],{"class":154},[64,6766,6767],{"class":583}," root",[64,6769,501],{"class":154},[64,6771,6772],{"class":150}," import",[64,6774,276],{"class":154},[64,6776,6777],{"class":279},"meta",[64,6779,276],{"class":154},[64,6781,6782],{"class":279},"dirname",[64,6784,162],{"class":154},[64,6786,296],{"class":200},[64,6788,178],{"class":154},[64,6790,6791,6793,6795,6798,6800,6802,6804,6806,6808,6810,6812,6814,6816,6818,6820,6822,6824,6826,6828,6830],{"class":66,"line":2442},[64,6792,1718],{"class":197},[64,6794,270],{"class":200},[64,6796,6797],{"class":197},"join",[64,6799,270],{"class":200},[64,6801,151],{"class":150},[64,6803,276],{"class":154},[64,6805,6777],{"class":279},[64,6807,276],{"class":154},[64,6809,6782],{"class":279},[64,6811,399],{"class":154},[64,6813,169],{"class":168},[64,6815,1725],{"class":73},[64,6817,175],{"class":168},[64,6819,296],{"class":200},[64,6821,399],{"class":154},[64,6823,1681],{"class":197},[64,6825,270],{"class":200},[64,6827,273],{"class":158},[64,6829,399],{"class":154},[64,6831,3506],{"class":154},[64,6833,6834,6837,6839,6841,6844,6846],{"class":66,"line":2448},[64,6835,6836],{"class":583},"  facade",[64,6838,501],{"class":154},[64,6840,169],{"class":168},[64,6842,6843],{"class":73},"http:\u002F\u002F127.0.0.1:4300\u002F_fougere\u002Fcall",[64,6845,175],{"class":168},[64,6847,2921],{"class":154},[64,6849,6850,6852,6854],{"class":66,"line":2453},[64,6851,1183],{"class":154},[64,6853,311],{"class":200},[64,6855,178],{"class":154},[64,6857,6858,6860,6862,6864,6866,6868],{"class":66,"line":2479},[64,6859,428],{"class":150},[64,6861,1221],{"class":158},[64,6863,276],{"class":154},[64,6865,1769],{"class":197},[64,6867,201],{"class":200},[64,6869,178],{"class":154},[64,6871,6872,6875,6877,6880,6882,6884,6887,6889,6891],{"class":66,"line":2485},[64,6873,6874],{"class":158},"console",[64,6876,276],{"class":154},[64,6878,6879],{"class":197},"log",[64,6881,270],{"class":200},[64,6883,175],{"class":168},[64,6885,6886],{"class":73},"✓ load.js",[64,6888,175],{"class":168},[64,6890,296],{"class":200},[64,6892,178],{"class":154},[54,6894,6898],{"className":6895,"code":6896,"filename":1725,"language":6897,"meta":60,"style":60},"language-js shiki shiki-themes material-theme-lighter fougere-pastel material-theme-palenight","\u002F\u002F Generated by `fougere load` — edit the weights, the stages and the thresholds.\n\u002F\u002F Everything else is read from what the app answers: regenerate rather than patch.\nimport http from 'k6\u002Fhttp';\nimport { check } from 'k6';\n\nconst DOOR = \"http:\u002F\u002F127.0.0.1:4300\u002F_fougere\u002Fcall\";\n\n\u002F\u002F Every operation the app serves. A weight of 0 takes one out, visibly.\nconst OPS = [\n  {\n    \"method\": \"product.list\",\n    \"hops\": 0,\n    \"weight\": 1\n  },\n  {\n    \"method\": \"product.findById\",\n    \"hops\": 0,\n    \"weight\": 1\n  },\n  {\n    \"method\": \"product.create\",\n    \"input\": {\n      \"sku\": \"gDXv8gBIU\",\n      \"name\": \"MCNJHiFxGrbDH\",\n      \"cents\": 750868,\n      \"status\": \"draft\"\n    },\n    \"hops\": 0,\n    \"weight\": 1\n  },\n  {\n    \"method\": \"product.update\",\n    \"input\": {\n      \"sku\": \"LKJ66\",\n      \"name\": \"HpiCnX3geczfAAEpYaVsuxZNyUigJfBw2kpP\",\n      \"cents\": 496626,\n      \"status\": \"listed\"\n    },\n    \"hops\": 0,\n    \"weight\": 1\n  },\n  {\n    \"method\": \"product.delete\",\n    \"hops\": 0,\n    \"weight\": 1\n  },\n  {\n    \"method\": \"product.quote\",\n    \"input\": {\n      \"sku\": \"gDXv8gBIU\",\n      \"name\": \"MCNJHiFxGrbDH\",\n      \"cents\": 750868,\n      \"status\": \"draft\"\n    },\n    \"hops\": 0,\n    \"weight\": 1\n  },\n  {\n    \"method\": \"order.list\",\n    \"hops\": 0,\n    \"weight\": 1\n  },\n  {\n    \"method\": \"order.findById\",\n    \"hops\": 0,\n    \"weight\": 1\n  },\n  {\n    \"method\": \"order.create\",\n    \"input\": {\n      \"sku\": \"GZA\",\n      \"quantity\": 68\n    },\n    \"hops\": 0,\n    \"weight\": 1\n  },\n  {\n    \"method\": \"order.update\",\n    \"input\": {\n      \"sku\": \"LKJ66\",\n      \"quantity\": 59\n    },\n    \"hops\": 0,\n    \"weight\": 1\n  },\n  {\n    \"method\": \"order.delete\",\n    \"hops\": 0,\n    \"weight\": 1\n  }\n];\n\n\u002F\u002F Yours: how long an op may take here, and what one process boundary is allowed to add. Two\n\u002F\u002F numbers instead of one, because an op that crosses nothing and an op that crosses twice were\n\u002F\u002F never the same subject — hops above is read from the code, these two are facts about your\n\u002F\u002F network.\nconst BUDGET = { base: 300, perHop: 200 };\n\nexport const options = {\n  \u002F\u002F Yours: a flat rate draws flat lines and there is nothing to read in them.\n  stages: [\n    { duration: '30s', target: 5 },\n    { duration: '45s', target: 5 },\n    { duration: '30s', target: 0 },\n  ],\n  \u002F\u002F Yours: the shape of the run.\n  \u002F\u002F Derived from BUDGET and each op's hops — an op that crosses two processes is not held to\n  \u002F\u002F the same figure as one that never leaves. k6 reads a threshold per tag, and every call\n  \u002F\u002F below is tagged with the op it made.\n  thresholds: {\n    http_req_failed: ['rate\u003C0.01'],\n    ...Object.fromEntries(OPS.map((op) => [\n      `http_req_duration{op:${op.method}}`,\n      [`p(95)\u003C${BUDGET.base + op.hops * BUDGET.perHop}`],\n    ])),\n  },\n};\n\nconst TOTAL = OPS.reduce((sum, op) => sum + op.weight, 0);\nlet id = 0;\n\nfunction pick() {\n  let roll = Math.random() * TOTAL;\n  for (const op of OPS) if ((roll -= op.weight) \u003C 0) return op;\n\n  return OPS[OPS.length - 1];\n}\n\nexport default function () {\n  const op = pick();\n  const payload = {\"jsonrpc\":\"2.0\"};\n  const response = http.post(\n    DOOR,\n    JSON.stringify({ ...payload, id: ++id, method: op.method, params: { params: {}, query: {}, input: op.input, state: {} } }),\n    { headers: { 'content-type': 'application\u002Fjson' }, tags: { op: op.method } },\n  );\n  check(response, { 'answered': (r) => r.status === 200 });\n}\n\n","js",[17,6899,6900,6905,6910,6928,6949,6953,6971,6975,6980,6992,6997,7018,7034,7048,7053,7057,7076,7090,7102,7106,7110,7128,7140,7160,7179,7194,7211,7216,7230,7242,7246,7250,7269,7281,7300,7319,7334,7350,7354,7368,7380,7384,7388,7407,7421,7433,7437,7441,7460,7472,7490,7508,7522,7538,7542,7556,7568,7572,7576,7595,7609,7621,7625,7629,7648,7662,7674,7678,7682,7701,7713,7732,7746,7750,7764,7776,7780,7784,7803,7815,7833,7846,7850,7864,7876,7880,7884,7903,7917,7929,7933,7939,7943,7948,7954,7960,7966,7998,8003,8018,8024,8034,8064,8090,8115,8123,8129,8135,8141,8147,8157,8178,8213,8239,8287,8295,8300,8306,8311,8364,8379,8384,8397,8424,8478,8483,8510,8515,8520,8534,8549,8578,8597,8605,8695,8744,8752,8803],{"__ignoreMap":60},[64,6901,6902],{"class":66,"line":67},[64,6903,6904],{"class":143},"\u002F\u002F Generated by `fougere load` — edit the weights, the stages and the thresholds.\n",[64,6906,6907],{"class":66,"line":147},[64,6908,6909],{"class":143},"\u002F\u002F Everything else is read from what the app answers: regenerate rather than patch.\n",[64,6911,6912,6914,6917,6919,6921,6924,6926],{"class":66,"line":181},[64,6913,151],{"class":150},[64,6915,6916],{"class":158}," http ",[64,6918,5195],{"class":150},[64,6920,169],{"class":168},[64,6922,6923],{"class":73},"k6\u002Fhttp",[64,6925,175],{"class":168},[64,6927,178],{"class":154},[64,6929,6930,6932,6934,6937,6939,6941,6943,6945,6947],{"class":66,"line":188},[64,6931,151],{"class":150},[64,6933,155],{"class":154},[64,6935,6936],{"class":158}," check",[64,6938,162],{"class":154},[64,6940,165],{"class":150},[64,6942,169],{"class":168},[64,6944,1783],{"class":73},[64,6946,175],{"class":168},[64,6948,178],{"class":154},[64,6950,6951],{"class":66,"line":825},[64,6952,185],{"emptyLinePlaceholder":184},[64,6954,6955,6957,6960,6962,6965,6967,6969],{"class":66,"line":830},[64,6956,929],{"class":241},[64,6958,6959],{"class":158}," DOOR ",[64,6961,248],{"class":154},[64,6963,6964],{"class":168}," \"",[64,6966,6843],{"class":73},[64,6968,1436],{"class":168},[64,6970,178],{"class":154},[64,6972,6973],{"class":66,"line":1760},[64,6974,185],{"emptyLinePlaceholder":184},[64,6976,6977],{"class":66,"line":2418},[64,6978,6979],{"class":143},"\u002F\u002F Every operation the app serves. A weight of 0 takes one out, visibly.\n",[64,6981,6982,6984,6987,6989],{"class":66,"line":2424},[64,6983,929],{"class":241},[64,6985,6986],{"class":158}," OPS ",[64,6988,248],{"class":154},[64,6990,6991],{"class":200}," [\n",[64,6993,6994],{"class":66,"line":2430},[64,6995,6996],{"class":154},"  {\n",[64,6998,6999,7002,7005,7007,7009,7011,7014,7016],{"class":66,"line":2436},[64,7000,7001],{"class":168},"    \"",[64,7003,7004],{"class":4419},"method",[64,7006,1436],{"class":168},[64,7008,501],{"class":154},[64,7010,6964],{"class":168},[64,7012,7013],{"class":73},"product.list",[64,7015,1436],{"class":168},[64,7017,2921],{"class":154},[64,7019,7020,7022,7025,7027,7029,7032],{"class":66,"line":2442},[64,7021,7001],{"class":168},[64,7023,7024],{"class":4419},"hops",[64,7026,1436],{"class":168},[64,7028,501],{"class":154},[64,7030,7031],{"class":623}," 0",[64,7033,2921],{"class":154},[64,7035,7036,7038,7041,7043,7045],{"class":66,"line":2448},[64,7037,7001],{"class":168},[64,7039,7040],{"class":4419},"weight",[64,7042,1436],{"class":168},[64,7044,501],{"class":154},[64,7046,7047],{"class":623}," 1\n",[64,7049,7050],{"class":66,"line":2453},[64,7051,7052],{"class":154},"  },\n",[64,7054,7055],{"class":66,"line":2479},[64,7056,6996],{"class":154},[64,7058,7059,7061,7063,7065,7067,7069,7072,7074],{"class":66,"line":2485},[64,7060,7001],{"class":168},[64,7062,7004],{"class":4419},[64,7064,1436],{"class":168},[64,7066,501],{"class":154},[64,7068,6964],{"class":168},[64,7070,7071],{"class":73},"product.findById",[64,7073,1436],{"class":168},[64,7075,2921],{"class":154},[64,7077,7078,7080,7082,7084,7086,7088],{"class":66,"line":2491},[64,7079,7001],{"class":168},[64,7081,7024],{"class":4419},[64,7083,1436],{"class":168},[64,7085,501],{"class":154},[64,7087,7031],{"class":623},[64,7089,2921],{"class":154},[64,7091,7092,7094,7096,7098,7100],{"class":66,"line":2496},[64,7093,7001],{"class":168},[64,7095,7040],{"class":4419},[64,7097,1436],{"class":168},[64,7099,501],{"class":154},[64,7101,7047],{"class":623},[64,7103,7104],{"class":66,"line":2505},[64,7105,7052],{"class":154},[64,7107,7108],{"class":66,"line":2510},[64,7109,6996],{"class":154},[64,7111,7112,7114,7116,7118,7120,7122,7124,7126],{"class":66,"line":2524},[64,7113,7001],{"class":168},[64,7115,7004],{"class":4419},[64,7117,1436],{"class":168},[64,7119,501],{"class":154},[64,7121,6964],{"class":168},[64,7123,4486],{"class":73},[64,7125,1436],{"class":168},[64,7127,2921],{"class":154},[64,7129,7130,7132,7134,7136,7138],{"class":66,"line":2529},[64,7131,7001],{"class":168},[64,7133,1428],{"class":4419},[64,7135,1436],{"class":168},[64,7137,501],{"class":154},[64,7139,3506],{"class":154},[64,7141,7142,7145,7147,7149,7151,7153,7156,7158],{"class":66,"line":2537},[64,7143,7144],{"class":168},"      \"",[64,7146,1439],{"class":4419},[64,7148,1436],{"class":168},[64,7150,501],{"class":154},[64,7152,6964],{"class":168},[64,7154,7155],{"class":73},"gDXv8gBIU",[64,7157,1436],{"class":168},[64,7159,2921],{"class":154},[64,7161,7162,7164,7166,7168,7170,7172,7175,7177],{"class":66,"line":2555},[64,7163,7144],{"class":168},[64,7165,308],{"class":4419},[64,7167,1436],{"class":168},[64,7169,501],{"class":154},[64,7171,6964],{"class":168},[64,7173,7174],{"class":73},"MCNJHiFxGrbDH",[64,7176,1436],{"class":168},[64,7178,2921],{"class":154},[64,7180,7181,7183,7185,7187,7189,7192],{"class":66,"line":2603},[64,7182,7144],{"class":168},[64,7184,5397],{"class":4419},[64,7186,1436],{"class":168},[64,7188,501],{"class":154},[64,7190,7191],{"class":623}," 750868",[64,7193,2921],{"class":154},[64,7195,7196,7198,7200,7202,7204,7206,7208],{"class":66,"line":2608},[64,7197,7144],{"class":168},[64,7199,3297],{"class":4419},[64,7201,1436],{"class":168},[64,7203,501],{"class":154},[64,7205,6964],{"class":168},[64,7207,3310],{"class":73},[64,7209,7210],{"class":168},"\"\n",[64,7212,7213],{"class":66,"line":2613},[64,7214,7215],{"class":154},"    },\n",[64,7217,7218,7220,7222,7224,7226,7228],{"class":66,"line":2628},[64,7219,7001],{"class":168},[64,7221,7024],{"class":4419},[64,7223,1436],{"class":168},[64,7225,501],{"class":154},[64,7227,7031],{"class":623},[64,7229,2921],{"class":154},[64,7231,7232,7234,7236,7238,7240],{"class":66,"line":2654},[64,7233,7001],{"class":168},[64,7235,7040],{"class":4419},[64,7237,1436],{"class":168},[64,7239,501],{"class":154},[64,7241,7047],{"class":623},[64,7243,7244],{"class":66,"line":2659},[64,7245,7052],{"class":154},[64,7247,7248],{"class":66,"line":2665},[64,7249,6996],{"class":154},[64,7251,7252,7254,7256,7258,7260,7262,7265,7267],{"class":66,"line":2671},[64,7253,7001],{"class":168},[64,7255,7004],{"class":4419},[64,7257,1436],{"class":168},[64,7259,501],{"class":154},[64,7261,6964],{"class":168},[64,7263,7264],{"class":73},"product.update",[64,7266,1436],{"class":168},[64,7268,2921],{"class":154},[64,7270,7271,7273,7275,7277,7279],{"class":66,"line":2676},[64,7272,7001],{"class":168},[64,7274,1428],{"class":4419},[64,7276,1436],{"class":168},[64,7278,501],{"class":154},[64,7280,3506],{"class":154},[64,7282,7283,7285,7287,7289,7291,7293,7296,7298],{"class":66,"line":2683},[64,7284,7144],{"class":168},[64,7286,1439],{"class":4419},[64,7288,1436],{"class":168},[64,7290,501],{"class":154},[64,7292,6964],{"class":168},[64,7294,7295],{"class":73},"LKJ66",[64,7297,1436],{"class":168},[64,7299,2921],{"class":154},[64,7301,7302,7304,7306,7308,7310,7312,7315,7317],{"class":66,"line":2714},[64,7303,7144],{"class":168},[64,7305,308],{"class":4419},[64,7307,1436],{"class":168},[64,7309,501],{"class":154},[64,7311,6964],{"class":168},[64,7313,7314],{"class":73},"HpiCnX3geczfAAEpYaVsuxZNyUigJfBw2kpP",[64,7316,1436],{"class":168},[64,7318,2921],{"class":154},[64,7320,7321,7323,7325,7327,7329,7332],{"class":66,"line":2743},[64,7322,7144],{"class":168},[64,7324,5397],{"class":4419},[64,7326,1436],{"class":168},[64,7328,501],{"class":154},[64,7330,7331],{"class":623}," 496626",[64,7333,2921],{"class":154},[64,7335,7336,7338,7340,7342,7344,7346,7348],{"class":66,"line":2748},[64,7337,7144],{"class":168},[64,7339,3297],{"class":4419},[64,7341,1436],{"class":168},[64,7343,501],{"class":154},[64,7345,6964],{"class":168},[64,7347,3324],{"class":73},[64,7349,7210],{"class":168},[64,7351,7352],{"class":66,"line":2753},[64,7353,7215],{"class":154},[64,7355,7356,7358,7360,7362,7364,7366],{"class":66,"line":2759},[64,7357,7001],{"class":168},[64,7359,7024],{"class":4419},[64,7361,1436],{"class":168},[64,7363,501],{"class":154},[64,7365,7031],{"class":623},[64,7367,2921],{"class":154},[64,7369,7370,7372,7374,7376,7378],{"class":66,"line":2765},[64,7371,7001],{"class":168},[64,7373,7040],{"class":4419},[64,7375,1436],{"class":168},[64,7377,501],{"class":154},[64,7379,7047],{"class":623},[64,7381,7382],{"class":66,"line":2771},[64,7383,7052],{"class":154},[64,7385,7386],{"class":66,"line":2776},[64,7387,6996],{"class":154},[64,7389,7390,7392,7394,7396,7398,7400,7403,7405],{"class":66,"line":2784},[64,7391,7001],{"class":168},[64,7393,7004],{"class":4419},[64,7395,1436],{"class":168},[64,7397,501],{"class":154},[64,7399,6964],{"class":168},[64,7401,7402],{"class":73},"product.delete",[64,7404,1436],{"class":168},[64,7406,2921],{"class":154},[64,7408,7409,7411,7413,7415,7417,7419],{"class":66,"line":2789},[64,7410,7001],{"class":168},[64,7412,7024],{"class":4419},[64,7414,1436],{"class":168},[64,7416,501],{"class":154},[64,7418,7031],{"class":623},[64,7420,2921],{"class":154},[64,7422,7423,7425,7427,7429,7431],{"class":66,"line":2802},[64,7424,7001],{"class":168},[64,7426,7040],{"class":4419},[64,7428,1436],{"class":168},[64,7430,501],{"class":154},[64,7432,7047],{"class":623},[64,7434,7435],{"class":66,"line":2808},[64,7436,7052],{"class":154},[64,7438,7439],{"class":66,"line":2813},[64,7440,6996],{"class":154},[64,7442,7443,7445,7447,7449,7451,7453,7456,7458],{"class":66,"line":2820},[64,7444,7001],{"class":168},[64,7446,7004],{"class":4419},[64,7448,1436],{"class":168},[64,7450,501],{"class":154},[64,7452,6964],{"class":168},[64,7454,7455],{"class":73},"product.quote",[64,7457,1436],{"class":168},[64,7459,2921],{"class":154},[64,7461,7462,7464,7466,7468,7470],{"class":66,"line":2836},[64,7463,7001],{"class":168},[64,7465,1428],{"class":4419},[64,7467,1436],{"class":168},[64,7469,501],{"class":154},[64,7471,3506],{"class":154},[64,7473,7474,7476,7478,7480,7482,7484,7486,7488],{"class":66,"line":2867},[64,7475,7144],{"class":168},[64,7477,1439],{"class":4419},[64,7479,1436],{"class":168},[64,7481,501],{"class":154},[64,7483,6964],{"class":168},[64,7485,7155],{"class":73},[64,7487,1436],{"class":168},[64,7489,2921],{"class":154},[64,7491,7492,7494,7496,7498,7500,7502,7504,7506],{"class":66,"line":2898},[64,7493,7144],{"class":168},[64,7495,308],{"class":4419},[64,7497,1436],{"class":168},[64,7499,501],{"class":154},[64,7501,6964],{"class":168},[64,7503,7174],{"class":73},[64,7505,1436],{"class":168},[64,7507,2921],{"class":154},[64,7509,7510,7512,7514,7516,7518,7520],{"class":66,"line":2903},[64,7511,7144],{"class":168},[64,7513,5397],{"class":4419},[64,7515,1436],{"class":168},[64,7517,501],{"class":154},[64,7519,7191],{"class":623},[64,7521,2921],{"class":154},[64,7523,7524,7526,7528,7530,7532,7534,7536],{"class":66,"line":2908},[64,7525,7144],{"class":168},[64,7527,3297],{"class":4419},[64,7529,1436],{"class":168},[64,7531,501],{"class":154},[64,7533,6964],{"class":168},[64,7535,3310],{"class":73},[64,7537,7210],{"class":168},[64,7539,7540],{"class":66,"line":2924},[64,7541,7215],{"class":154},[64,7543,7544,7546,7548,7550,7552,7554],{"class":66,"line":2954},[64,7545,7001],{"class":168},[64,7547,7024],{"class":4419},[64,7549,1436],{"class":168},[64,7551,501],{"class":154},[64,7553,7031],{"class":623},[64,7555,2921],{"class":154},[64,7557,7558,7560,7562,7564,7566],{"class":66,"line":2976},[64,7559,7001],{"class":168},[64,7561,7040],{"class":4419},[64,7563,1436],{"class":168},[64,7565,501],{"class":154},[64,7567,7047],{"class":623},[64,7569,7570],{"class":66,"line":2981},[64,7571,7052],{"class":154},[64,7573,7574],{"class":66,"line":2997},[64,7575,6996],{"class":154},[64,7577,7578,7580,7582,7584,7586,7588,7591,7593],{"class":66,"line":3003},[64,7579,7001],{"class":168},[64,7581,7004],{"class":4419},[64,7583,1436],{"class":168},[64,7585,501],{"class":154},[64,7587,6964],{"class":168},[64,7589,7590],{"class":73},"order.list",[64,7592,1436],{"class":168},[64,7594,2921],{"class":154},[64,7596,7597,7599,7601,7603,7605,7607],{"class":66,"line":3009},[64,7598,7001],{"class":168},[64,7600,7024],{"class":4419},[64,7602,1436],{"class":168},[64,7604,501],{"class":154},[64,7606,7031],{"class":623},[64,7608,2921],{"class":154},[64,7610,7611,7613,7615,7617,7619],{"class":66,"line":3014},[64,7612,7001],{"class":168},[64,7614,7040],{"class":4419},[64,7616,1436],{"class":168},[64,7618,501],{"class":154},[64,7620,7047],{"class":623},[64,7622,7623],{"class":66,"line":3022},[64,7624,7052],{"class":154},[64,7626,7627],{"class":66,"line":3027},[64,7628,6996],{"class":154},[64,7630,7631,7633,7635,7637,7639,7641,7644,7646],{"class":66,"line":3040},[64,7632,7001],{"class":168},[64,7634,7004],{"class":4419},[64,7636,1436],{"class":168},[64,7638,501],{"class":154},[64,7640,6964],{"class":168},[64,7642,7643],{"class":73},"order.findById",[64,7645,1436],{"class":168},[64,7647,2921],{"class":154},[64,7649,7650,7652,7654,7656,7658,7660],{"class":66,"line":3046},[64,7651,7001],{"class":168},[64,7653,7024],{"class":4419},[64,7655,1436],{"class":168},[64,7657,501],{"class":154},[64,7659,7031],{"class":623},[64,7661,2921],{"class":154},[64,7663,7664,7666,7668,7670,7672],{"class":66,"line":3051},[64,7665,7001],{"class":168},[64,7667,7040],{"class":4419},[64,7669,1436],{"class":168},[64,7671,501],{"class":154},[64,7673,7047],{"class":623},[64,7675,7676],{"class":66,"line":3057},[64,7677,7052],{"class":154},[64,7679,7680],{"class":66,"line":3063},[64,7681,6996],{"class":154},[64,7683,7684,7686,7688,7690,7692,7694,7697,7699],{"class":66,"line":3068},[64,7685,7001],{"class":168},[64,7687,7004],{"class":4419},[64,7689,1436],{"class":168},[64,7691,501],{"class":154},[64,7693,6964],{"class":168},[64,7695,7696],{"class":73},"order.create",[64,7698,1436],{"class":168},[64,7700,2921],{"class":154},[64,7702,7703,7705,7707,7709,7711],{"class":66,"line":3076},[64,7704,7001],{"class":168},[64,7706,1428],{"class":4419},[64,7708,1436],{"class":168},[64,7710,501],{"class":154},[64,7712,3506],{"class":154},[64,7714,7715,7717,7719,7721,7723,7725,7728,7730],{"class":66,"line":3081},[64,7716,7144],{"class":168},[64,7718,1439],{"class":4419},[64,7720,1436],{"class":168},[64,7722,501],{"class":154},[64,7724,6964],{"class":168},[64,7726,7727],{"class":73},"GZA",[64,7729,1436],{"class":168},[64,7731,2921],{"class":154},[64,7733,7734,7736,7739,7741,7743],{"class":66,"line":3103},[64,7735,7144],{"class":168},[64,7737,7738],{"class":4419},"quantity",[64,7740,1436],{"class":168},[64,7742,501],{"class":154},[64,7744,7745],{"class":623}," 68\n",[64,7747,7748],{"class":66,"line":3118},[64,7749,7215],{"class":154},[64,7751,7752,7754,7756,7758,7760,7762],{"class":66,"line":3124},[64,7753,7001],{"class":168},[64,7755,7024],{"class":4419},[64,7757,1436],{"class":168},[64,7759,501],{"class":154},[64,7761,7031],{"class":623},[64,7763,2921],{"class":154},[64,7765,7766,7768,7770,7772,7774],{"class":66,"line":3129},[64,7767,7001],{"class":168},[64,7769,7040],{"class":4419},[64,7771,1436],{"class":168},[64,7773,501],{"class":154},[64,7775,7047],{"class":623},[64,7777,7778],{"class":66,"line":3135},[64,7779,7052],{"class":154},[64,7781,7782],{"class":66,"line":3141},[64,7783,6996],{"class":154},[64,7785,7786,7788,7790,7792,7794,7796,7799,7801],{"class":66,"line":3146},[64,7787,7001],{"class":168},[64,7789,7004],{"class":4419},[64,7791,1436],{"class":168},[64,7793,501],{"class":154},[64,7795,6964],{"class":168},[64,7797,7798],{"class":73},"order.update",[64,7800,1436],{"class":168},[64,7802,2921],{"class":154},[64,7804,7805,7807,7809,7811,7813],{"class":66,"line":3154},[64,7806,7001],{"class":168},[64,7808,1428],{"class":4419},[64,7810,1436],{"class":168},[64,7812,501],{"class":154},[64,7814,3506],{"class":154},[64,7816,7817,7819,7821,7823,7825,7827,7829,7831],{"class":66,"line":3159},[64,7818,7144],{"class":168},[64,7820,1439],{"class":4419},[64,7822,1436],{"class":168},[64,7824,501],{"class":154},[64,7826,6964],{"class":168},[64,7828,7295],{"class":73},[64,7830,1436],{"class":168},[64,7832,2921],{"class":154},[64,7834,7835,7837,7839,7841,7843],{"class":66,"line":3182},[64,7836,7144],{"class":168},[64,7838,7738],{"class":4419},[64,7840,1436],{"class":168},[64,7842,501],{"class":154},[64,7844,7845],{"class":623}," 59\n",[64,7847,7848],{"class":66,"line":3203},[64,7849,7215],{"class":154},[64,7851,7852,7854,7856,7858,7860,7862],{"class":66,"line":3209},[64,7853,7001],{"class":168},[64,7855,7024],{"class":4419},[64,7857,1436],{"class":168},[64,7859,501],{"class":154},[64,7861,7031],{"class":623},[64,7863,2921],{"class":154},[64,7865,7866,7868,7870,7872,7874],{"class":66,"line":3214},[64,7867,7001],{"class":168},[64,7869,7040],{"class":4419},[64,7871,1436],{"class":168},[64,7873,501],{"class":154},[64,7875,7047],{"class":623},[64,7877,7878],{"class":66,"line":3222},[64,7879,7052],{"class":154},[64,7881,7882],{"class":66,"line":3283},[64,7883,6996],{"class":154},[64,7885,7886,7888,7890,7892,7894,7896,7899,7901],{"class":66,"line":3351},[64,7887,7001],{"class":168},[64,7889,7004],{"class":4419},[64,7891,1436],{"class":168},[64,7893,501],{"class":154},[64,7895,6964],{"class":168},[64,7897,7898],{"class":73},"order.delete",[64,7900,1436],{"class":168},[64,7902,2921],{"class":154},[64,7904,7905,7907,7909,7911,7913,7915],{"class":66,"line":3356},[64,7906,7001],{"class":168},[64,7908,7024],{"class":4419},[64,7910,1436],{"class":168},[64,7912,501],{"class":154},[64,7914,7031],{"class":623},[64,7916,2921],{"class":154},[64,7918,7919,7921,7923,7925,7927],{"class":66,"line":3361},[64,7920,7001],{"class":168},[64,7922,7040],{"class":4419},[64,7924,1436],{"class":168},[64,7926,501],{"class":154},[64,7928,7047],{"class":623},[64,7930,7931],{"class":66,"line":3367},[64,7932,5299],{"class":154},[64,7934,7935,7937],{"class":66,"line":3382},[64,7936,731],{"class":200},[64,7938,178],{"class":154},[64,7940,7941],{"class":66,"line":3388},[64,7942,185],{"emptyLinePlaceholder":184},[64,7944,7945],{"class":66,"line":3394},[64,7946,7947],{"class":143},"\u002F\u002F Yours: how long an op may take here, and what one process boundary is allowed to add. Two\n",[64,7949,7951],{"class":66,"line":7950},94,[64,7952,7953],{"class":143},"\u002F\u002F numbers instead of one, because an op that crosses nothing and an op that crosses twice were\n",[64,7955,7957],{"class":66,"line":7956},95,[64,7958,7959],{"class":143},"\u002F\u002F never the same subject — hops above is read from the code, these two are facts about your\n",[64,7961,7963],{"class":66,"line":7962},96,[64,7964,7965],{"class":143},"\u002F\u002F network.\n",[64,7967,7969,7971,7974,7976,7978,7981,7983,7986,7988,7991,7993,7996],{"class":66,"line":7968},97,[64,7970,929],{"class":241},[64,7972,7973],{"class":158}," BUDGET ",[64,7975,248],{"class":154},[64,7977,155],{"class":154},[64,7979,7980],{"class":583}," base",[64,7982,501],{"class":154},[64,7984,7985],{"class":623}," 300",[64,7987,399],{"class":154},[64,7989,7990],{"class":583}," perHop",[64,7992,501],{"class":154},[64,7994,7995],{"class":623}," 200",[64,7997,4659],{"class":154},[64,7999,8001],{"class":66,"line":8000},98,[64,8002,185],{"emptyLinePlaceholder":184},[64,8004,8006,8008,8011,8014,8016],{"class":66,"line":8005},99,[64,8007,191],{"class":150},[64,8009,8010],{"class":241}," const",[64,8012,8013],{"class":158}," options ",[64,8015,248],{"class":154},[64,8017,3506],{"class":154},[64,8019,8021],{"class":66,"line":8020},100,[64,8022,8023],{"class":143},"  \u002F\u002F Yours: a flat rate draws flat lines and there is nothing to read in them.\n",[64,8025,8027,8030,8032],{"class":66,"line":8026},101,[64,8028,8029],{"class":583},"  stages",[64,8031,501],{"class":154},[64,8033,6991],{"class":200},[64,8035,8037,8040,8043,8045,8047,8050,8052,8054,8057,8059,8062],{"class":66,"line":8036},102,[64,8038,8039],{"class":154},"    {",[64,8041,8042],{"class":583}," duration",[64,8044,501],{"class":154},[64,8046,169],{"class":168},[64,8048,8049],{"class":73},"30s",[64,8051,175],{"class":168},[64,8053,399],{"class":154},[64,8055,8056],{"class":583}," target",[64,8058,501],{"class":154},[64,8060,8061],{"class":623}," 5",[64,8063,4434],{"class":154},[64,8065,8067,8069,8071,8073,8075,8078,8080,8082,8084,8086,8088],{"class":66,"line":8066},103,[64,8068,8039],{"class":154},[64,8070,8042],{"class":583},[64,8072,501],{"class":154},[64,8074,169],{"class":168},[64,8076,8077],{"class":73},"45s",[64,8079,175],{"class":168},[64,8081,399],{"class":154},[64,8083,8056],{"class":583},[64,8085,501],{"class":154},[64,8087,8061],{"class":623},[64,8089,4434],{"class":154},[64,8091,8093,8095,8097,8099,8101,8103,8105,8107,8109,8111,8113],{"class":66,"line":8092},104,[64,8094,8039],{"class":154},[64,8096,8042],{"class":583},[64,8098,501],{"class":154},[64,8100,169],{"class":168},[64,8102,8049],{"class":73},[64,8104,175],{"class":168},[64,8106,399],{"class":154},[64,8108,8056],{"class":583},[64,8110,501],{"class":154},[64,8112,7031],{"class":623},[64,8114,4434],{"class":154},[64,8116,8118,8121],{"class":66,"line":8117},105,[64,8119,8120],{"class":200},"  ]",[64,8122,2921],{"class":154},[64,8124,8126],{"class":66,"line":8125},106,[64,8127,8128],{"class":143},"  \u002F\u002F Yours: the shape of the run.\n",[64,8130,8132],{"class":66,"line":8131},107,[64,8133,8134],{"class":143},"  \u002F\u002F Derived from BUDGET and each op's hops — an op that crosses two processes is not held to\n",[64,8136,8138],{"class":66,"line":8137},108,[64,8139,8140],{"class":143},"  \u002F\u002F the same figure as one that never leaves. k6 reads a threshold per tag, and every call\n",[64,8142,8144],{"class":66,"line":8143},109,[64,8145,8146],{"class":143},"  \u002F\u002F below is tagged with the op it made.\n",[64,8148,8150,8153,8155],{"class":66,"line":8149},110,[64,8151,8152],{"class":583},"  thresholds",[64,8154,501],{"class":154},[64,8156,3506],{"class":154},[64,8158,8160,8163,8165,8167,8169,8172,8174,8176],{"class":66,"line":8159},111,[64,8161,8162],{"class":583},"    http_req_failed",[64,8164,501],{"class":154},[64,8166,725],{"class":200},[64,8168,175],{"class":168},[64,8170,8171],{"class":73},"rate\u003C0.01",[64,8173,175],{"class":168},[64,8175,731],{"class":200},[64,8177,2921],{"class":154},[64,8179,8181,8184,8187,8189,8192,8194,8197,8199,8201,8203,8205,8207,8209,8211],{"class":66,"line":8180},112,[64,8182,8183],{"class":154},"    ...",[64,8185,8186],{"class":158},"Object",[64,8188,276],{"class":154},[64,8190,8191],{"class":197},"fromEntries",[64,8193,270],{"class":200},[64,8195,8196],{"class":158},"OPS",[64,8198,276],{"class":154},[64,8200,285],{"class":197},[64,8202,270],{"class":200},[64,8204,270],{"class":154},[64,8206,1915],{"class":292},[64,8208,296],{"class":154},[64,8210,300],{"class":299},[64,8212,6991],{"class":200},[64,8214,8216,8219,8222,8225,8227,8229,8231,8233,8235,8237],{"class":66,"line":8215},113,[64,8217,8218],{"class":168},"      `",[64,8220,8221],{"class":73},"http_req_duration{op:",[64,8223,8224],{"class":154},"${",[64,8226,1915],{"class":158},[64,8228,276],{"class":154},[64,8230,7004],{"class":279},[64,8232,1183],{"class":154},[64,8234,1183],{"class":73},[64,8236,2513],{"class":168},[64,8238,2921],{"class":154},[64,8240,8242,8245,8247,8250,8252,8255,8257,8260,8263,8265,8267,8269,8271,8274,8276,8279,8281,8283,8285],{"class":66,"line":8241},114,[64,8243,8244],{"class":200},"      [",[64,8246,2513],{"class":168},[64,8248,8249],{"class":73},"p(95)\u003C",[64,8251,8224],{"class":154},[64,8253,8254],{"class":158},"BUDGET",[64,8256,276],{"class":154},[64,8258,8259],{"class":279},"base",[64,8261,8262],{"class":154}," +",[64,8264,803],{"class":158},[64,8266,276],{"class":154},[64,8268,7024],{"class":279},[64,8270,1975],{"class":154},[64,8272,8273],{"class":158}," BUDGET",[64,8275,276],{"class":154},[64,8277,8278],{"class":279},"perHop",[64,8280,1183],{"class":154},[64,8282,2513],{"class":168},[64,8284,731],{"class":200},[64,8286,2921],{"class":154},[64,8288,8290,8293],{"class":66,"line":8289},115,[64,8291,8292],{"class":200},"    ]))",[64,8294,2921],{"class":154},[64,8296,8298],{"class":66,"line":8297},116,[64,8299,7052],{"class":154},[64,8301,8303],{"class":66,"line":8302},117,[64,8304,8305],{"class":154},"};\n",[64,8307,8309],{"class":66,"line":8308},118,[64,8310,185],{"emptyLinePlaceholder":184},[64,8312,8314,8316,8319,8321,8324,8326,8329,8331,8333,8336,8338,8340,8342,8344,8347,8350,8352,8354,8356,8358,8360,8362],{"class":66,"line":8313},119,[64,8315,929],{"class":241},[64,8317,8318],{"class":158}," TOTAL ",[64,8320,248],{"class":154},[64,8322,8323],{"class":158}," OPS",[64,8325,276],{"class":154},[64,8327,8328],{"class":197},"reduce",[64,8330,270],{"class":200},[64,8332,270],{"class":154},[64,8334,8335],{"class":292},"sum",[64,8337,399],{"class":154},[64,8339,803],{"class":292},[64,8341,296],{"class":154},[64,8343,300],{"class":299},[64,8345,8346],{"class":158}," sum ",[64,8348,8349],{"class":154},"+",[64,8351,803],{"class":158},[64,8353,276],{"class":154},[64,8355,7040],{"class":279},[64,8357,399],{"class":154},[64,8359,7031],{"class":623},[64,8361,296],{"class":200},[64,8363,178],{"class":154},[64,8365,8367,8370,8373,8375,8377],{"class":66,"line":8366},120,[64,8368,8369],{"class":241},"let",[64,8371,8372],{"class":158}," id ",[64,8374,248],{"class":154},[64,8376,7031],{"class":623},[64,8378,178],{"class":154},[64,8380,8382],{"class":66,"line":8381},121,[64,8383,185],{"emptyLinePlaceholder":184},[64,8385,8387,8390,8393,8395],{"class":66,"line":8386},122,[64,8388,8389],{"class":241},"function",[64,8391,8392],{"class":197}," pick",[64,8394,201],{"class":154},[64,8396,3506],{"class":154},[64,8398,8400,8403,8406,8408,8410,8412,8415,8417,8419,8422],{"class":66,"line":8399},123,[64,8401,8402],{"class":241},"  let",[64,8404,8405],{"class":158}," roll",[64,8407,1920],{"class":154},[64,8409,5555],{"class":158},[64,8411,276],{"class":154},[64,8413,8414],{"class":197},"random",[64,8416,201],{"class":3521},[64,8418,1975],{"class":154},[64,8420,8421],{"class":158}," TOTAL",[64,8423,178],{"class":154},[64,8425,8427,8430,8433,8435,8437,8440,8442,8444,8447,8450,8453,8456,8458,8460,8462,8464,8467,8469,8471,8474,8476],{"class":66,"line":8426},124,[64,8428,8429],{"class":150},"  for",[64,8431,8432],{"class":3521}," (",[64,8434,929],{"class":241},[64,8436,803],{"class":158},[64,8438,8439],{"class":154}," of",[64,8441,8323],{"class":158},[64,8443,296],{"class":3521},[64,8445,8446],{"class":150}," if",[64,8448,8449],{"class":3521}," ((",[64,8451,8452],{"class":158},"roll",[64,8454,8455],{"class":154}," -=",[64,8457,803],{"class":158},[64,8459,276],{"class":154},[64,8461,7040],{"class":279},[64,8463,296],{"class":3521},[64,8465,8466],{"class":154}," \u003C",[64,8468,7031],{"class":623},[64,8470,296],{"class":3521},[64,8472,8473],{"class":150}," return",[64,8475,803],{"class":158},[64,8477,178],{"class":154},[64,8479,8481],{"class":66,"line":8480},125,[64,8482,185],{"emptyLinePlaceholder":184},[64,8484,8486,8489,8491,8494,8496,8498,8501,8504,8506,8508],{"class":66,"line":8485},126,[64,8487,8488],{"class":150},"  return",[64,8490,8323],{"class":158},[64,8492,8493],{"class":3521},"[",[64,8495,8196],{"class":158},[64,8497,276],{"class":154},[64,8499,8500],{"class":279},"length",[64,8502,8503],{"class":154}," -",[64,8505,4474],{"class":623},[64,8507,731],{"class":3521},[64,8509,178],{"class":154},[64,8511,8513],{"class":66,"line":8512},127,[64,8514,5410],{"class":154},[64,8516,8518],{"class":66,"line":8517},128,[64,8519,185],{"emptyLinePlaceholder":184},[64,8521,8523,8525,8527,8530,8532],{"class":66,"line":8522},129,[64,8524,191],{"class":150},[64,8526,194],{"class":150},[64,8528,8529],{"class":241}," function",[64,8531,1934],{"class":154},[64,8533,3506],{"class":154},[64,8535,8537,8539,8541,8543,8545,8547],{"class":66,"line":8536},130,[64,8538,4336],{"class":241},[64,8540,803],{"class":158},[64,8542,1920],{"class":154},[64,8544,8392],{"class":197},[64,8546,201],{"class":3521},[64,8548,178],{"class":154},[64,8550,8552,8554,8557,8559,8561,8563,8566,8568,8570,8572,8574,8576],{"class":66,"line":8551},131,[64,8553,4336],{"class":241},[64,8555,8556],{"class":158}," payload",[64,8558,1920],{"class":154},[64,8560,155],{"class":154},[64,8562,1436],{"class":168},[64,8564,8565],{"class":4419},"jsonrpc",[64,8567,1436],{"class":168},[64,8569,501],{"class":154},[64,8571,1436],{"class":168},[64,8573,4463],{"class":73},[64,8575,1436],{"class":168},[64,8577,8305],{"class":154},[64,8579,8581,8583,8585,8587,8590,8592,8594],{"class":66,"line":8580},132,[64,8582,4336],{"class":241},[64,8584,4369],{"class":158},[64,8586,1920],{"class":154},[64,8588,8589],{"class":158}," http",[64,8591,276],{"class":154},[64,8593,1116],{"class":197},[64,8595,8596],{"class":3521},"(\n",[64,8598,8600,8603],{"class":66,"line":8599},133,[64,8601,8602],{"class":158},"    DOOR",[64,8604,2921],{"class":154},[64,8606,8608,8611,8613,8615,8617,8619,8622,8625,8627,8629,8631,8634,8637,8639,8641,8643,8645,8647,8649,8651,8653,8655,8657,8659,8661,8663,8665,8667,8669,8671,8673,8675,8677,8679,8681,8683,8685,8687,8689,8691,8693],{"class":66,"line":8607},134,[64,8609,8610],{"class":158},"    JSON",[64,8612,276],{"class":154},[64,8614,4449],{"class":197},[64,8616,270],{"class":3521},[64,8618,717],{"class":154},[64,8620,8621],{"class":154}," ...",[64,8623,8624],{"class":158},"payload",[64,8626,399],{"class":154},[64,8628,1175],{"class":583},[64,8630,501],{"class":154},[64,8632,8633],{"class":154}," ++",[64,8635,8636],{"class":158},"id",[64,8638,399],{"class":154},[64,8640,4479],{"class":583},[64,8642,501],{"class":154},[64,8644,803],{"class":158},[64,8646,276],{"class":154},[64,8648,7004],{"class":279},[64,8650,399],{"class":154},[64,8652,4502],{"class":583},[64,8654,501],{"class":154},[64,8656,155],{"class":154},[64,8658,4502],{"class":583},[64,8660,501],{"class":154},[64,8662,613],{"class":154},[64,8664,4509],{"class":583},[64,8666,501],{"class":154},[64,8668,613],{"class":154},[64,8670,4516],{"class":583},[64,8672,501],{"class":154},[64,8674,803],{"class":158},[64,8676,276],{"class":154},[64,8678,1428],{"class":279},[64,8680,399],{"class":154},[64,8682,4585],{"class":583},[64,8684,501],{"class":154},[64,8686,4590],{"class":154},[64,8688,162],{"class":154},[64,8690,162],{"class":154},[64,8692,296],{"class":3521},[64,8694,2921],{"class":154},[64,8696,8698,8700,8703,8705,8707,8709,8711,8713,8715,8717,8719,8721,8723,8726,8728,8730,8732,8734,8736,8738,8740,8742],{"class":66,"line":8697},135,[64,8699,8039],{"class":154},[64,8701,8702],{"class":583}," headers",[64,8704,501],{"class":154},[64,8706,155],{"class":154},[64,8708,169],{"class":168},[64,8710,4420],{"class":4419},[64,8712,175],{"class":168},[64,8714,501],{"class":154},[64,8716,169],{"class":168},[64,8718,4429],{"class":73},[64,8720,175],{"class":168},[64,8722,815],{"class":154},[64,8724,8725],{"class":583}," tags",[64,8727,501],{"class":154},[64,8729,155],{"class":154},[64,8731,803],{"class":583},[64,8733,501],{"class":154},[64,8735,803],{"class":158},[64,8737,276],{"class":154},[64,8739,7004],{"class":279},[64,8741,162],{"class":154},[64,8743,4434],{"class":154},[64,8745,8747,8750],{"class":66,"line":8746},136,[64,8748,8749],{"class":3521},"  )",[64,8751,178],{"class":154},[64,8753,8755,8758,8760,8763,8765,8767,8769,8772,8774,8776,8778,8781,8783,8785,8788,8790,8792,8795,8797,8799,8801],{"class":66,"line":8754},137,[64,8756,8757],{"class":197},"  check",[64,8759,270],{"class":3521},[64,8761,8762],{"class":158},"response",[64,8764,399],{"class":154},[64,8766,155],{"class":154},[64,8768,169],{"class":168},[64,8770,8771],{"class":4419},"answered",[64,8773,175],{"class":168},[64,8775,501],{"class":154},[64,8777,8432],{"class":154},[64,8779,8780],{"class":292},"r",[64,8782,296],{"class":154},[64,8784,300],{"class":299},[64,8786,8787],{"class":158}," r",[64,8789,276],{"class":154},[64,8791,3297],{"class":279},[64,8793,8794],{"class":154}," ===",[64,8796,7995],{"class":623},[64,8798,162],{"class":154},[64,8800,296],{"class":3521},[64,8802,178],{"class":154},[64,8804,8806],{"class":66,"line":8805},138,[64,8807,5410],{"class":154},[54,8809,8813],{"className":8810,"code":8811,"filename":8812,"language":4623,"meta":60,"style":60},"language-json shiki shiki-themes material-theme-lighter fougere-pastel material-theme-palenight","{\n  \"name\": \"@fougere\u002Fdemo-test-gradient\",\n  \"private\": true,\n  \"type\": \"module\",\n  \"scripts\": {\n    \"test\": \"vitest run\",\n    \"test:watch\": \"vitest\",\n    \"typecheck\": \"tsc --noEmit -p .\",\n    \"load:gen\": \"tsx gen-load.ts\",\n    \"e2e\": \"playwright test\",\n    \"dev\": \"tsx server.ts\",\n    \"migrate\": \"fougere migrate --latest --apply\"\n  },\n  \"dependencies\": {\n    \"@fougere\u002Fadapter-rest\": \"^0.30.0-alpha.5\",\n    \"@fougere\u002Fadapter-sql\": \"^0.30.0-alpha.5\",\n    \"@fougere\u002Fcore\": \"^0.30.0-alpha.5\",\n    \"@fougere\u002Flog\": \"^0.30.0-alpha.5\",\n    \"@fougere\u002Fschema\": \"^0.30.0-alpha.5\",\n    \"better-sqlite3\": \"^13.0.3\"\n  },\n  \"devDependencies\": {\n    \"@fougere\u002Ftesting\": \"^0.30.0-alpha.5\",\n    \"vitest\": \"^4.1.0\",\n    \"tsx\": \"^4.20.6\",\n    \"@fougere\u002Ftransport-http\": \"^0.30.0-alpha.5\",\n    \"@fougere\u002Fcontainer\": \"^0.30.0-alpha.5\",\n    \"@fougere\u002Fapp\": \"^0.30.0-alpha.5\",\n    \"@fougere\u002Fadapter-graphql\": \"^0.30.0-alpha.5\",\n    \"@pothos\u002Fcore\": \"^4.12.0\",\n    \"graphql\": \"^16.13.1\",\n    \"@playwright\u002Ftest\": \"^1.50.0\",\n    \"@fougere\u002Fcli\": \"^0.30.0-alpha.5\"\n  }\n}\n\n","package.json",[17,8814,8815,8819,8839,8854,8874,8887,8906,8925,8945,8965,8985,9005,9023,9027,9040,9059,9077,9095,9113,9131,9149,9153,9166,9184,9203,9223,9242,9261,9280,9298,9318,9338,9357,9374,9378],{"__ignoreMap":60},[64,8816,8817],{"class":66,"line":67},[64,8818,4794],{"class":154},[64,8820,8821,8824,8826,8828,8830,8832,8835,8837],{"class":66,"line":147},[64,8822,8823],{"class":154},"  \"",[64,8825,308],{"class":1431},[64,8827,1436],{"class":154},[64,8829,501],{"class":154},[64,8831,6964],{"class":168},[64,8833,8834],{"class":73},"@fougere\u002Fdemo-test-gradient",[64,8836,1436],{"class":168},[64,8838,2921],{"class":154},[64,8840,8841,8843,8846,8848,8850,8852],{"class":66,"line":181},[64,8842,8823],{"class":154},[64,8844,8845],{"class":1431},"private",[64,8847,1436],{"class":154},[64,8849,501],{"class":154},[64,8851,5076],{"class":168},[64,8853,2921],{"class":154},[64,8855,8856,8858,8861,8863,8865,8867,8870,8872],{"class":66,"line":188},[64,8857,8823],{"class":154},[64,8859,8860],{"class":1431},"type",[64,8862,1436],{"class":154},[64,8864,501],{"class":154},[64,8866,6964],{"class":168},[64,8868,8869],{"class":73},"module",[64,8871,1436],{"class":168},[64,8873,2921],{"class":154},[64,8875,8876,8878,8881,8883,8885],{"class":66,"line":825},[64,8877,8823],{"class":154},[64,8879,8880],{"class":1431},"scripts",[64,8882,1436],{"class":154},[64,8884,501],{"class":154},[64,8886,3506],{"class":154},[64,8888,8889,8891,8893,8895,8897,8899,8902,8904],{"class":66,"line":830},[64,8890,7001],{"class":154},[64,8892,3478],{"class":497},[64,8894,1436],{"class":154},[64,8896,501],{"class":154},[64,8898,6964],{"class":168},[64,8900,8901],{"class":73},"vitest run",[64,8903,1436],{"class":168},[64,8905,2921],{"class":154},[64,8907,8908,8910,8913,8915,8917,8919,8921,8923],{"class":66,"line":1760},[64,8909,7001],{"class":154},[64,8911,8912],{"class":497},"test:watch",[64,8914,1436],{"class":154},[64,8916,501],{"class":154},[64,8918,6964],{"class":168},[64,8920,5650],{"class":73},[64,8922,1436],{"class":168},[64,8924,2921],{"class":154},[64,8926,8927,8929,8932,8934,8936,8938,8941,8943],{"class":66,"line":2418},[64,8928,7001],{"class":154},[64,8930,8931],{"class":497},"typecheck",[64,8933,1436],{"class":154},[64,8935,501],{"class":154},[64,8937,6964],{"class":168},[64,8939,8940],{"class":73},"tsc --noEmit -p .",[64,8942,1436],{"class":168},[64,8944,2921],{"class":154},[64,8946,8947,8949,8952,8954,8956,8958,8961,8963],{"class":66,"line":2424},[64,8948,7001],{"class":154},[64,8950,8951],{"class":497},"load:gen",[64,8953,1436],{"class":154},[64,8955,501],{"class":154},[64,8957,6964],{"class":168},[64,8959,8960],{"class":73},"tsx gen-load.ts",[64,8962,1436],{"class":168},[64,8964,2921],{"class":154},[64,8966,8967,8969,8972,8974,8976,8978,8981,8983],{"class":66,"line":2430},[64,8968,7001],{"class":154},[64,8970,8971],{"class":497},"e2e",[64,8973,1436],{"class":154},[64,8975,501],{"class":154},[64,8977,6964],{"class":168},[64,8979,8980],{"class":73},"playwright test",[64,8982,1436],{"class":168},[64,8984,2921],{"class":154},[64,8986,8987,8989,8992,8994,8996,8998,9001,9003],{"class":66,"line":2436},[64,8988,7001],{"class":154},[64,8990,8991],{"class":497},"dev",[64,8993,1436],{"class":154},[64,8995,501],{"class":154},[64,8997,6964],{"class":168},[64,8999,9000],{"class":73},"tsx server.ts",[64,9002,1436],{"class":168},[64,9004,2921],{"class":154},[64,9006,9007,9009,9012,9014,9016,9018,9021],{"class":66,"line":2442},[64,9008,7001],{"class":154},[64,9010,9011],{"class":497},"migrate",[64,9013,1436],{"class":154},[64,9015,501],{"class":154},[64,9017,6964],{"class":168},[64,9019,9020],{"class":73},"fougere migrate --latest --apply",[64,9022,7210],{"class":168},[64,9024,9025],{"class":66,"line":2448},[64,9026,7052],{"class":154},[64,9028,9029,9031,9034,9036,9038],{"class":66,"line":2453},[64,9030,8823],{"class":154},[64,9032,9033],{"class":1431},"dependencies",[64,9035,1436],{"class":154},[64,9037,501],{"class":154},[64,9039,3506],{"class":154},[64,9041,9042,9044,9046,9048,9050,9052,9055,9057],{"class":66,"line":2479},[64,9043,7001],{"class":154},[64,9045,4726],{"class":497},[64,9047,1436],{"class":154},[64,9049,501],{"class":154},[64,9051,6964],{"class":168},[64,9053,9054],{"class":73},"^0.30.0-alpha.5",[64,9056,1436],{"class":168},[64,9058,2921],{"class":154},[64,9060,9061,9063,9065,9067,9069,9071,9073,9075],{"class":66,"line":2485},[64,9062,7001],{"class":154},[64,9064,2005],{"class":497},[64,9066,1436],{"class":154},[64,9068,501],{"class":154},[64,9070,6964],{"class":168},[64,9072,9054],{"class":73},[64,9074,1436],{"class":168},[64,9076,2921],{"class":154},[64,9078,9079,9081,9083,9085,9087,9089,9091,9093],{"class":66,"line":2491},[64,9080,7001],{"class":154},[64,9082,4773],{"class":497},[64,9084,1436],{"class":154},[64,9086,501],{"class":154},[64,9088,6964],{"class":168},[64,9090,9054],{"class":73},[64,9092,1436],{"class":168},[64,9094,2921],{"class":154},[64,9096,9097,9099,9101,9103,9105,9107,9109,9111],{"class":66,"line":2496},[64,9098,7001],{"class":154},[64,9100,4878],{"class":497},[64,9102,1436],{"class":154},[64,9104,501],{"class":154},[64,9106,6964],{"class":168},[64,9108,9054],{"class":73},[64,9110,1436],{"class":168},[64,9112,2921],{"class":154},[64,9114,9115,9117,9119,9121,9123,9125,9127,9129],{"class":66,"line":2505},[64,9116,7001],{"class":154},[64,9118,4942],{"class":497},[64,9120,1436],{"class":154},[64,9122,501],{"class":154},[64,9124,6964],{"class":168},[64,9126,9054],{"class":73},[64,9128,1436],{"class":168},[64,9130,2921],{"class":154},[64,9132,9133,9135,9138,9140,9142,9144,9147],{"class":66,"line":2510},[64,9134,7001],{"class":154},[64,9136,9137],{"class":497},"better-sqlite3",[64,9139,1436],{"class":154},[64,9141,501],{"class":154},[64,9143,6964],{"class":168},[64,9145,9146],{"class":73},"^13.0.3",[64,9148,7210],{"class":168},[64,9150,9151],{"class":66,"line":2524},[64,9152,7052],{"class":154},[64,9154,9155,9157,9160,9162,9164],{"class":66,"line":2529},[64,9156,8823],{"class":154},[64,9158,9159],{"class":1431},"devDependencies",[64,9161,1436],{"class":154},[64,9163,501],{"class":154},[64,9165,3506],{"class":154},[64,9167,9168,9170,9172,9174,9176,9178,9180,9182],{"class":66,"line":2537},[64,9169,7001],{"class":154},[64,9171,19],{"class":497},[64,9173,1436],{"class":154},[64,9175,501],{"class":154},[64,9177,6964],{"class":168},[64,9179,9054],{"class":73},[64,9181,1436],{"class":168},[64,9183,2921],{"class":154},[64,9185,9186,9188,9190,9192,9194,9196,9199,9201],{"class":66,"line":2555},[64,9187,7001],{"class":154},[64,9189,5650],{"class":497},[64,9191,1436],{"class":154},[64,9193,501],{"class":154},[64,9195,6964],{"class":168},[64,9197,9198],{"class":73},"^4.1.0",[64,9200,1436],{"class":168},[64,9202,2921],{"class":154},[64,9204,9205,9207,9210,9212,9214,9216,9219,9221],{"class":66,"line":2603},[64,9206,7001],{"class":154},[64,9208,9209],{"class":497},"tsx",[64,9211,1436],{"class":154},[64,9213,501],{"class":154},[64,9215,6964],{"class":168},[64,9217,9218],{"class":73},"^4.20.6",[64,9220,1436],{"class":168},[64,9222,2921],{"class":154},[64,9224,9225,9227,9230,9232,9234,9236,9238,9240],{"class":66,"line":2608},[64,9226,7001],{"class":154},[64,9228,9229],{"class":497},"@fougere\u002Ftransport-http",[64,9231,1436],{"class":154},[64,9233,501],{"class":154},[64,9235,6964],{"class":168},[64,9237,9054],{"class":73},[64,9239,1436],{"class":168},[64,9241,2921],{"class":154},[64,9243,9244,9246,9249,9251,9253,9255,9257,9259],{"class":66,"line":2613},[64,9245,7001],{"class":154},[64,9247,9248],{"class":497},"@fougere\u002Fcontainer",[64,9250,1436],{"class":154},[64,9252,501],{"class":154},[64,9254,6964],{"class":168},[64,9256,9054],{"class":73},[64,9258,1436],{"class":168},[64,9260,2921],{"class":154},[64,9262,9263,9265,9268,9270,9272,9274,9276,9278],{"class":66,"line":2628},[64,9264,7001],{"class":154},[64,9266,9267],{"class":497},"@fougere\u002Fapp",[64,9269,1436],{"class":154},[64,9271,501],{"class":154},[64,9273,6964],{"class":168},[64,9275,9054],{"class":73},[64,9277,1436],{"class":168},[64,9279,2921],{"class":154},[64,9281,9282,9284,9286,9288,9290,9292,9294,9296],{"class":66,"line":2654},[64,9283,7001],{"class":154},[64,9285,4739],{"class":497},[64,9287,1436],{"class":154},[64,9289,501],{"class":154},[64,9291,6964],{"class":168},[64,9293,9054],{"class":73},[64,9295,1436],{"class":168},[64,9297,2921],{"class":154},[64,9299,9300,9302,9305,9307,9309,9311,9314,9316],{"class":66,"line":2659},[64,9301,7001],{"class":154},[64,9303,9304],{"class":497},"@pothos\u002Fcore",[64,9306,1436],{"class":154},[64,9308,501],{"class":154},[64,9310,6964],{"class":168},[64,9312,9313],{"class":73},"^4.12.0",[64,9315,1436],{"class":168},[64,9317,2921],{"class":154},[64,9319,9320,9322,9325,9327,9329,9331,9334,9336],{"class":66,"line":2665},[64,9321,7001],{"class":154},[64,9323,9324],{"class":497},"graphql",[64,9326,1436],{"class":154},[64,9328,501],{"class":154},[64,9330,6964],{"class":168},[64,9332,9333],{"class":73},"^16.13.1",[64,9335,1436],{"class":168},[64,9337,2921],{"class":154},[64,9339,9340,9342,9344,9346,9348,9350,9353,9355],{"class":66,"line":2671},[64,9341,7001],{"class":154},[64,9343,3465],{"class":497},[64,9345,1436],{"class":154},[64,9347,501],{"class":154},[64,9349,6964],{"class":168},[64,9351,9352],{"class":73},"^1.50.0",[64,9354,1436],{"class":168},[64,9356,2921],{"class":154},[64,9358,9359,9361,9364,9366,9368,9370,9372],{"class":66,"line":2676},[64,9360,7001],{"class":154},[64,9362,9363],{"class":497},"@fougere\u002Fcli",[64,9365,1436],{"class":154},[64,9367,501],{"class":154},[64,9369,6964],{"class":168},[64,9371,9054],{"class":73},[64,9373,7210],{"class":168},[64,9375,9376],{"class":66,"line":2683},[64,9377,5299],{"class":154},[64,9379,9380],{"class":66,"line":2714},[64,9381,5410],{"class":154},[54,9383,9385],{"className":134,"code":9384,"filename":1516,"language":136,"meta":60,"style":60},"import { defineConfig } from '@playwright\u002Ftest';\n\nexport default defineConfig({\n  testDir: '.\u002Fe2e',\n  \u002F\u002F Playwright démarre le serveur lui-même : rien à lancer à côté, et le port est celui\n  \u002F\u002F que le serveur annonce.\n  webServer: {\n    command: 'tsx server.ts',\n    url: 'http:\u002F\u002F127.0.0.1:4300',\n    reuseExistingServer: !process.env.CI,\n  },\n  use: { baseURL: 'http:\u002F\u002F127.0.0.1:4300' },\n});\n\n",[17,9386,9387,9408,9412,9424,9440,9445,9450,9459,9474,9490,9515,9519,9541],{"__ignoreMap":60},[64,9388,9389,9391,9393,9396,9398,9400,9402,9404,9406],{"class":66,"line":67},[64,9390,151],{"class":150},[64,9392,155],{"class":154},[64,9394,9395],{"class":158}," defineConfig",[64,9397,162],{"class":154},[64,9399,165],{"class":150},[64,9401,169],{"class":168},[64,9403,3465],{"class":73},[64,9405,175],{"class":168},[64,9407,178],{"class":154},[64,9409,9410],{"class":66,"line":147},[64,9411,185],{"emptyLinePlaceholder":184},[64,9413,9414,9416,9418,9420,9422],{"class":66,"line":181},[64,9415,191],{"class":150},[64,9417,194],{"class":150},[64,9419,9395],{"class":197},[64,9421,270],{"class":200},[64,9423,4794],{"class":154},[64,9425,9426,9429,9431,9433,9436,9438],{"class":66,"line":188},[64,9427,9428],{"class":583},"  testDir",[64,9430,501],{"class":154},[64,9432,169],{"class":168},[64,9434,9435],{"class":73},".\u002Fe2e",[64,9437,175],{"class":168},[64,9439,2921],{"class":154},[64,9441,9442],{"class":66,"line":825},[64,9443,9444],{"class":143},"  \u002F\u002F Playwright démarre le serveur lui-même : rien à lancer à côté, et le port est celui\n",[64,9446,9447],{"class":66,"line":830},[64,9448,9449],{"class":143},"  \u002F\u002F que le serveur annonce.\n",[64,9451,9452,9455,9457],{"class":66,"line":1760},[64,9453,9454],{"class":583},"  webServer",[64,9456,501],{"class":154},[64,9458,3506],{"class":154},[64,9460,9461,9464,9466,9468,9470,9472],{"class":66,"line":2418},[64,9462,9463],{"class":583},"    command",[64,9465,501],{"class":154},[64,9467,169],{"class":168},[64,9469,9000],{"class":73},[64,9471,175],{"class":168},[64,9473,2921],{"class":154},[64,9475,9476,9479,9481,9483,9486,9488],{"class":66,"line":2424},[64,9477,9478],{"class":583},"    url",[64,9480,501],{"class":154},[64,9482,169],{"class":168},[64,9484,9485],{"class":73},"http:\u002F\u002F127.0.0.1:4300",[64,9487,175],{"class":168},[64,9489,2921],{"class":154},[64,9491,9492,9495,9497,9500,9503,9505,9508,9510,9513],{"class":66,"line":2430},[64,9493,9494],{"class":583},"    reuseExistingServer",[64,9496,501],{"class":154},[64,9498,9499],{"class":154}," !",[64,9501,9502],{"class":158},"process",[64,9504,276],{"class":154},[64,9506,9507],{"class":279},"env",[64,9509,276],{"class":154},[64,9511,9512],{"class":279},"CI",[64,9514,2921],{"class":154},[64,9516,9517],{"class":66,"line":2436},[64,9518,7052],{"class":154},[64,9520,9521,9524,9526,9528,9531,9533,9535,9537,9539],{"class":66,"line":2442},[64,9522,9523],{"class":583},"  use",[64,9525,501],{"class":154},[64,9527,155],{"class":154},[64,9529,9530],{"class":583}," baseURL",[64,9532,501],{"class":154},[64,9534,169],{"class":168},[64,9536,9485],{"class":73},[64,9538,175],{"class":168},[64,9540,4434],{"class":154},[64,9542,9543,9545,9547],{"class":66,"line":2448},[64,9544,1183],{"class":154},[64,9546,296],{"class":200},[64,9548,178],{"class":154},[54,9550,9552],{"className":134,"code":9551,"filename":3174,"language":136,"meta":60,"style":60},"\u002F**\n * CRAN 4 — l'app, avec des pages.\n *\n * Le formulaire n'est écrit nulle part : `formFieldsOf` le dérive de `Product`, avec ses\n * contraintes sous les noms que le navigateur connaît déjà (`minlength`, `max`, `required`).\n * La page n'énonce donc aucune règle de son côté — c'est le sens de « juge local = juge\n * distant », et c'est le seul cran où on peut le voir plutôt que le plaider.\n *\n *   pnpm dev     puis http:\u002F\u002F127.0.0.1:4300\n *\u002F\nimport { createServer } from 'node:http';\nimport { createLocalRunner, type Page } from '@fougere\u002Fcore';\nimport { Invocation } from '@fougere\u002Fcore\u002Fcontract';\nimport { formFieldsOf, payloadOf } from '@fougere\u002Fapp';\nimport { answer } from '@fougere\u002Fapp\u002Fanswer';\nimport { testApp } from '@fougere\u002Ftesting';\nimport Product from '.\u002Ffronds\u002Fcatalog\u002Fentities\u002FProduct.js';\n\nconst app = await testApp({ root: import.meta.dirname });\nconst run = createLocalRunner(app);\nconst port = Number(process.env.PORT ?? 4300);\n\nconst escape = (value: unknown) =>\n  String(value).replace(\u002F[&\u003C>\"]\u002Fg, (c) => ({ '&': '&amp;', '\u003C': '&lt;', '>': '&gt;', '\"': '&quot;' }[c]!));\n\n\u002F** One input per declared field, and nothing this page decided on its own. *\u002F\nfunction inputFor(field: ReturnType\u003Ctypeof formFieldsOf>[number]): string {\n  const attrs = Object.entries(field.attrs ?? {})\n    .map(([name, value]) => `${name}=\"${escape(value)}\"`).join(' ');\n  const label = `\u003Clabel for=\"${field.name}\">${escape(field.label)}\u003C\u002Flabel>`;\n\n  if (field.control === 'select') {\n    const options = (field.options ?? []).map((one) => `\u003Coption value=\"${escape(one)}\">${escape(one)}\u003C\u002Foption>`).join('');\n\n    return `${label}\u003Cselect id=\"${field.name}\" name=\"${field.name}\" ${attrs}>${options}\u003C\u002Fselect>`;\n  }\n  \u002F\u002F `attrs` porte déjà `type` quand la forme le décide : ne pas le réécrire, sinon la\n  \u002F\u002F balise en a deux et c'est la page qui a tranché.\n  const type = 'type' in (field.attrs ?? {}) ? ''\n    : ` type=\"${field.control === 'boolean' ? 'checkbox' : field.control === 'reference' ? 'text' : field.control}\"`;\n\n  return `${label}\u003Cinput id=\"${field.name}\" name=\"${field.name}\"${type} ${attrs}>`;\n}\n\nasync function page(): Promise\u003Cstring> {\n  const { items } = await run({ address: 'product', op: 'list' }, Invocation.empty) as Page\u003CProduct>;\n  const fields = formFieldsOf(Product, 'product');\n\n  return `\u003C!doctype html>\u003Cmeta charset=\"utf-8\">\u003Ctitle>test-gradient\u003C\u002Ftitle>\n\u003Ch1>Catalogue\u003C\u002Fh1>\n\u003Cul id=\"products\">${items.map((row) => `\u003Cli data-sku=\"${escape(row.sku)}\">${escape(row.name)}\u003C\u002Fli>`).join('')}\u003C\u002Ful>\n\u003Cform id=\"new-product\">${fields.map(inputFor).join('')}\u003Cbutton type=\"submit\">Ajouter\u003C\u002Fbutton>\u003C\u002Fform>\n\u003Cp id=\"error\" hidden>\u003C\u002Fp>\n\u003Cscript type=\"module\">\nconst form = document.querySelector('#new-product');\nconst error = document.querySelector('#error');\nform.addEventListener('submit', async (event) => {\n  event.preventDefault();\n  error.hidden = true;\n  \u002F\u002F Le texte du formulaire, tel quel : c'est le serveur, comme useFormFor, qui le lit selon\n  \u002F\u002F la forme de Product. La page ne nomme aucun champ.\n  const response = await fetch('\u002Fform\u002Fproduct', {\n    method: 'POST',\n    headers: { 'content-type': 'application\u002Fjson' },\n    body: JSON.stringify(Object.fromEntries(new FormData(form))),\n  });\n  const answer = await response.json();\n  if (answer.error) { error.textContent = answer.error.message; error.hidden = false; return; }\n  location.reload();\n});\n\u003C\u002Fscript>`;\n}\n\nasync function bodyOf(request: AsyncIterable\u003Cunknown>): Promise\u003Cunknown> {\n  const chunks: Buffer[] = [];\n  for await (const chunk of request) chunks.push(chunk as Buffer);\n\n  return JSON.parse(Buffer.concat(chunks).toString());\n}\n\nasync function called(body: unknown): Promise\u003Cstring> {\n  const answered = await answer(app, new Request('http:\u002F\u002Flocalhost\u002F_fougere\u002Fcall', { method: 'POST', body: JSON.stringify(body) }), { state: {} });\n\n  return answered!.text();\n}\n\ncreateServer(async (request, response) => {\n  if (request.url === '\u002F' ) {\n    response.writeHead(200, { 'content-type': 'text\u002Fhtml; charset=utf-8' });\n    response.end(await page());\n\n    return;\n  }\n  if (request.method === 'POST' && request.url === '\u002F_fougere\u002Fcall') {\n    response.writeHead(200, { 'content-type': 'application\u002Fjson' });\n    response.end(await called(await bodyOf(request)));\n\n    return;\n  }\n  \u002F\u002F Ce que fait useFormFor dans un hôte : le texte d'un formulaire, lu selon la forme de\n  \u002F\u002F l'entité, puis la même porte. `\u002F_fougere\u002Fcall` reste strict pour un client JSON.\n  if (request.method === 'POST' && request.url === '\u002Fform\u002Fproduct') {\n    const input = payloadOf(Product, await bodyOf(request) as Record\u003Cstring, unknown>);\n    response.writeHead(200, { 'content-type': 'application\u002Fjson' });\n    response.end(await called({ jsonrpc: '2.0', id: 1, method: 'product.create', params: { params: {}, query: {}, input, state: {} } }));\n\n    return;\n  }\n  response.writeHead(404).end();\n}).listen(port, '127.0.0.1', () => console.log(`http:\u002F\u002F127.0.0.1:${port}`));\n\n",[17,9553,9554,9558,9563,9567,9572,9577,9582,9587,9591,9596,9600,9622,9649,9669,9695,9716,9736,9753,9757,9793,9812,9847,9851,9875,10005,10009,10014,10051,10083,10150,10201,10205,10231,10320,10324,10386,10390,10395,10400,10437,10516,10520,10578,10582,10586,10608,10672,10699,10703,10712,10717,10802,10838,10843,10848,10853,10858,10863,10868,10873,10878,10883,10888,10893,10898,10903,10908,10913,10918,10923,10928,10937,10941,10945,10982,11004,11044,11048,11085,11089,11093,11123,11209,11213,11228,11232,11236,11259,11285,11325,11344,11348,11354,11358,11399,11435,11464,11468,11474,11478,11483,11488,11529,11574,11610,11696,11700,11706,11710,11734],{"__ignoreMap":60},[64,9555,9556],{"class":66,"line":67},[64,9557,3407],{"class":143},[64,9559,9560],{"class":66,"line":147},[64,9561,9562],{"class":143}," * CRAN 4 — l'app, avec des pages.\n",[64,9564,9565],{"class":66,"line":181},[64,9566,3417],{"class":143},[64,9568,9569],{"class":66,"line":188},[64,9570,9571],{"class":143}," * Le formulaire n'est écrit nulle part : `formFieldsOf` le dérive de `Product`, avec ses\n",[64,9573,9574],{"class":66,"line":825},[64,9575,9576],{"class":143}," * contraintes sous les noms que le navigateur connaît déjà (`minlength`, `max`, `required`).\n",[64,9578,9579],{"class":66,"line":830},[64,9580,9581],{"class":143}," * La page n'énonce donc aucune règle de son côté — c'est le sens de « juge local = juge\n",[64,9583,9584],{"class":66,"line":1760},[64,9585,9586],{"class":143}," * distant », et c'est le seul cran où on peut le voir plutôt que le plaider.\n",[64,9588,9589],{"class":66,"line":2418},[64,9590,3417],{"class":143},[64,9592,9593],{"class":66,"line":2424},[64,9594,9595],{"class":143}," *   pnpm dev     puis http:\u002F\u002F127.0.0.1:4300\n",[64,9597,9598],{"class":66,"line":2430},[64,9599,3442],{"class":143},[64,9601,9602,9604,9606,9609,9611,9613,9615,9618,9620],{"class":66,"line":2436},[64,9603,151],{"class":150},[64,9605,155],{"class":154},[64,9607,9608],{"class":158}," createServer",[64,9610,162],{"class":154},[64,9612,165],{"class":150},[64,9614,169],{"class":168},[64,9616,9617],{"class":73},"node:http",[64,9619,175],{"class":168},[64,9621,178],{"class":154},[64,9623,9624,9626,9628,9630,9632,9634,9637,9639,9641,9643,9645,9647],{"class":66,"line":2442},[64,9625,151],{"class":150},[64,9627,155],{"class":154},[64,9629,5663],{"class":158},[64,9631,399],{"class":154},[64,9633,1455],{"class":150},[64,9635,9636],{"class":158}," Page",[64,9638,162],{"class":154},[64,9640,165],{"class":150},[64,9642,169],{"class":168},[64,9644,4773],{"class":73},[64,9646,175],{"class":168},[64,9648,178],{"class":154},[64,9650,9651,9653,9655,9657,9659,9661,9663,9665,9667],{"class":66,"line":2448},[64,9652,151],{"class":150},[64,9654,155],{"class":154},[64,9656,5684],{"class":158},[64,9658,162],{"class":154},[64,9660,165],{"class":150},[64,9662,169],{"class":168},[64,9664,5693],{"class":73},[64,9666,175],{"class":168},[64,9668,178],{"class":154},[64,9670,9671,9673,9675,9678,9680,9683,9685,9687,9689,9691,9693],{"class":66,"line":2453},[64,9672,151],{"class":150},[64,9674,155],{"class":154},[64,9676,9677],{"class":158}," formFieldsOf",[64,9679,399],{"class":154},[64,9681,9682],{"class":158}," payloadOf",[64,9684,162],{"class":154},[64,9686,165],{"class":150},[64,9688,169],{"class":168},[64,9690,9267],{"class":73},[64,9692,175],{"class":168},[64,9694,178],{"class":154},[64,9696,9697,9699,9701,9703,9705,9707,9709,9712,9714],{"class":66,"line":2479},[64,9698,151],{"class":150},[64,9700,155],{"class":154},[64,9702,4339],{"class":158},[64,9704,162],{"class":154},[64,9706,165],{"class":150},[64,9708,169],{"class":168},[64,9710,9711],{"class":73},"@fougere\u002Fapp\u002Fanswer",[64,9713,175],{"class":168},[64,9715,178],{"class":154},[64,9717,9718,9720,9722,9724,9726,9728,9730,9732,9734],{"class":66,"line":2485},[64,9719,151],{"class":150},[64,9721,155],{"class":154},[64,9723,254],{"class":158},[64,9725,162],{"class":154},[64,9727,165],{"class":150},[64,9729,169],{"class":168},[64,9731,19],{"class":73},[64,9733,175],{"class":168},[64,9735,178],{"class":154},[64,9737,9738,9740,9742,9744,9746,9749,9751],{"class":66,"line":2491},[64,9739,151],{"class":150},[64,9741,5192],{"class":158},[64,9743,5195],{"class":150},[64,9745,169],{"class":168},[64,9747,9748],{"class":73},".\u002Ffronds\u002Fcatalog\u002Fentities\u002FProduct.js",[64,9750,175],{"class":168},[64,9752,178],{"class":154},[64,9754,9755],{"class":66,"line":2496},[64,9756,185],{"emptyLinePlaceholder":184},[64,9758,9759,9761,9763,9765,9767,9769,9771,9773,9775,9777,9779,9781,9783,9785,9787,9789,9791],{"class":66,"line":2505},[64,9760,929],{"class":241},[64,9762,245],{"class":158},[64,9764,248],{"class":154},[64,9766,251],{"class":150},[64,9768,254],{"class":197},[64,9770,270],{"class":200},[64,9772,717],{"class":154},[64,9774,6767],{"class":583},[64,9776,501],{"class":154},[64,9778,6772],{"class":150},[64,9780,276],{"class":154},[64,9782,6777],{"class":279},[64,9784,276],{"class":154},[64,9786,6782],{"class":279},[64,9788,162],{"class":154},[64,9790,296],{"class":200},[64,9792,178],{"class":154},[64,9794,9795,9797,9800,9802,9804,9806,9808,9810],{"class":66,"line":2510},[64,9796,929],{"class":241},[64,9798,9799],{"class":158}," run ",[64,9801,248],{"class":154},[64,9803,5663],{"class":197},[64,9805,270],{"class":200},[64,9807,273],{"class":158},[64,9809,296],{"class":200},[64,9811,178],{"class":154},[64,9813,9814,9816,9819,9821,9824,9826,9828,9830,9832,9834,9837,9840,9843,9845],{"class":66,"line":2524},[64,9815,929],{"class":241},[64,9817,9818],{"class":158}," port ",[64,9820,248],{"class":154},[64,9822,9823],{"class":197}," Number",[64,9825,270],{"class":200},[64,9827,9502],{"class":158},[64,9829,276],{"class":154},[64,9831,9507],{"class":279},[64,9833,276],{"class":154},[64,9835,9836],{"class":279},"PORT",[64,9838,9839],{"class":154}," ??",[64,9841,9842],{"class":623}," 4300",[64,9844,296],{"class":200},[64,9846,178],{"class":154},[64,9848,9849],{"class":66,"line":2529},[64,9850,185],{"emptyLinePlaceholder":184},[64,9852,9853,9855,9859,9861,9863,9866,9868,9870,9872],{"class":66,"line":2537},[64,9854,929],{"class":241},[64,9856,9858],{"class":9857},"slP7D"," escape",[64,9860,1920],{"class":154},[64,9862,8432],{"class":154},[64,9864,9865],{"class":292},"value",[64,9867,501],{"class":154},[64,9869,1001],{"class":942},[64,9871,296],{"class":154},[64,9873,9874],{"class":299}," =>\n",[64,9876,9877,9880,9882,9884,9886,9888,9891,9893,9895,9897,9900,9902,9904,9908,9910,9912,9915,9917,9919,9921,9923,9925,9928,9930,9932,9934,9937,9939,9941,9943,9945,9947,9949,9951,9954,9956,9958,9960,9962,9964,9966,9968,9971,9973,9975,9977,9979,9981,9983,9985,9988,9990,9992,9994,9996,9998,10001,10003],{"class":66,"line":2555},[64,9878,9879],{"class":197},"  String",[64,9881,270],{"class":200},[64,9883,9865],{"class":158},[64,9885,296],{"class":200},[64,9887,276],{"class":154},[64,9889,9890],{"class":197},"replace",[64,9892,270],{"class":200},[64,9894,1547],{"class":168},[64,9896,8493],{"class":154},[64,9898,9899],{"class":73},"&\u003C>\"",[64,9901,731],{"class":154},[64,9903,1547],{"class":168},[64,9905,9907],{"class":9906},"sWPpw","g",[64,9909,399],{"class":154},[64,9911,8432],{"class":154},[64,9913,9914],{"class":292},"c",[64,9916,296],{"class":154},[64,9918,300],{"class":299},[64,9920,8432],{"class":200},[64,9922,717],{"class":154},[64,9924,169],{"class":168},[64,9926,9927],{"class":4419},"&",[64,9929,175],{"class":168},[64,9931,501],{"class":154},[64,9933,169],{"class":168},[64,9935,9936],{"class":73},"&amp;",[64,9938,175],{"class":168},[64,9940,399],{"class":154},[64,9942,169],{"class":168},[64,9944,939],{"class":4419},[64,9946,175],{"class":168},[64,9948,501],{"class":154},[64,9950,169],{"class":168},[64,9952,9953],{"class":73},"&lt;",[64,9955,175],{"class":168},[64,9957,399],{"class":154},[64,9959,169],{"class":168},[64,9961,945],{"class":4419},[64,9963,175],{"class":168},[64,9965,501],{"class":154},[64,9967,169],{"class":168},[64,9969,9970],{"class":73},"&gt;",[64,9972,175],{"class":168},[64,9974,399],{"class":154},[64,9976,169],{"class":168},[64,9978,1436],{"class":4419},[64,9980,175],{"class":168},[64,9982,501],{"class":154},[64,9984,169],{"class":168},[64,9986,9987],{"class":73},"&quot;",[64,9989,175],{"class":168},[64,9991,162],{"class":154},[64,9993,8493],{"class":200},[64,9995,9914],{"class":158},[64,9997,731],{"class":200},[64,9999,10000],{"class":154},"!",[64,10002,311],{"class":200},[64,10004,178],{"class":154},[64,10006,10007],{"class":66,"line":2603},[64,10008,185],{"emptyLinePlaceholder":184},[64,10010,10011],{"class":66,"line":2608},[64,10012,10013],{"class":143},"\u002F** One input per declared field, and nothing this page decided on its own. *\u002F\n",[64,10015,10016,10018,10021,10023,10026,10028,10031,10034,10036,10038,10040,10043,10045,10047,10049],{"class":66,"line":2613},[64,10017,8389],{"class":241},[64,10019,10020],{"class":197}," inputFor",[64,10022,270],{"class":154},[64,10024,10025],{"class":292},"field",[64,10027,501],{"class":154},[64,10029,10030],{"class":942}," ReturnType",[64,10032,10033],{"class":154},"\u003Ctypeof",[64,10035,9677],{"class":158},[64,10037,945],{"class":154},[64,10039,8493],{"class":200},[64,10041,10042],{"class":942},"number",[64,10044,731],{"class":200},[64,10046,5328],{"class":154},[64,10048,4654],{"class":942},[64,10050,3506],{"class":154},[64,10052,10053,10055,10058,10060,10063,10065,10068,10070,10072,10074,10077,10079,10081],{"class":66,"line":2628},[64,10054,4336],{"class":241},[64,10056,10057],{"class":158}," attrs",[64,10059,1920],{"class":154},[64,10061,10062],{"class":158}," Object",[64,10064,276],{"class":154},[64,10066,10067],{"class":197},"entries",[64,10069,270],{"class":3521},[64,10071,10025],{"class":158},[64,10073,276],{"class":154},[64,10075,10076],{"class":279},"attrs",[64,10078,9839],{"class":154},[64,10080,4590],{"class":154},[64,10082,1413],{"class":3521},[64,10084,10085,10088,10090,10092,10094,10096,10098,10101,10103,10105,10108,10110,10112,10114,10117,10119,10122,10124,10126,10128,10130,10132,10134,10136,10138,10140,10142,10144,10146,10148],{"class":66,"line":2654},[64,10086,10087],{"class":154},"    .",[64,10089,285],{"class":197},[64,10091,270],{"class":3521},[64,10093,319],{"class":154},[64,10095,308],{"class":292},[64,10097,399],{"class":154},[64,10099,10100],{"class":292}," value",[64,10102,329],{"class":154},[64,10104,300],{"class":299},[64,10106,10107],{"class":168}," `",[64,10109,8224],{"class":154},[64,10111,308],{"class":158},[64,10113,1183],{"class":154},[64,10115,10116],{"class":73},"=\"",[64,10118,8224],{"class":154},[64,10120,10121],{"class":197},"escape",[64,10123,270],{"class":200},[64,10125,9865],{"class":158},[64,10127,296],{"class":200},[64,10129,1183],{"class":154},[64,10131,1436],{"class":73},[64,10133,2513],{"class":168},[64,10135,296],{"class":3521},[64,10137,276],{"class":154},[64,10139,6797],{"class":197},[64,10141,270],{"class":3521},[64,10143,175],{"class":168},[64,10145,169],{"class":168},[64,10147,296],{"class":3521},[64,10149,178],{"class":154},[64,10151,10152,10154,10157,10159,10161,10164,10166,10168,10170,10172,10174,10177,10179,10181,10183,10185,10187,10190,10192,10194,10197,10199],{"class":66,"line":2659},[64,10153,4336],{"class":241},[64,10155,10156],{"class":158}," label",[64,10158,1920],{"class":154},[64,10160,10107],{"class":168},[64,10162,10163],{"class":73},"\u003Clabel for=\"",[64,10165,8224],{"class":154},[64,10167,10025],{"class":158},[64,10169,276],{"class":154},[64,10171,308],{"class":279},[64,10173,1183],{"class":154},[64,10175,10176],{"class":73},"\">",[64,10178,8224],{"class":154},[64,10180,10121],{"class":197},[64,10182,270],{"class":200},[64,10184,10025],{"class":158},[64,10186,276],{"class":154},[64,10188,10189],{"class":279},"label",[64,10191,296],{"class":200},[64,10193,1183],{"class":154},[64,10195,10196],{"class":73},"\u003C\u002Flabel>",[64,10198,2513],{"class":168},[64,10200,178],{"class":154},[64,10202,10203],{"class":66,"line":2665},[64,10204,185],{"emptyLinePlaceholder":184},[64,10206,10207,10210,10212,10214,10216,10219,10221,10223,10225,10227,10229],{"class":66,"line":2671},[64,10208,10209],{"class":150},"  if",[64,10211,8432],{"class":3521},[64,10213,10025],{"class":158},[64,10215,276],{"class":154},[64,10217,10218],{"class":279},"control",[64,10220,8794],{"class":154},[64,10222,169],{"class":168},[64,10224,3288],{"class":73},[64,10226,175],{"class":168},[64,10228,296],{"class":3521},[64,10230,3506],{"class":154},[64,10232,10233,10235,10238,10240,10242,10244,10246,10249,10251,10254,10256,10258,10260,10262,10265,10267,10269,10271,10274,10276,10278,10280,10282,10284,10286,10288,10290,10292,10294,10296,10298,10300,10303,10305,10307,10309,10311,10313,10316,10318],{"class":66,"line":2676},[64,10234,4366],{"class":241},[64,10236,10237],{"class":158}," options",[64,10239,1920],{"class":154},[64,10241,8432],{"class":3521},[64,10243,10025],{"class":158},[64,10245,276],{"class":154},[64,10247,10248],{"class":279},"options",[64,10250,9839],{"class":154},[64,10252,10253],{"class":3521}," [])",[64,10255,276],{"class":154},[64,10257,285],{"class":197},[64,10259,270],{"class":3521},[64,10261,270],{"class":154},[64,10263,10264],{"class":292},"one",[64,10266,296],{"class":154},[64,10268,300],{"class":299},[64,10270,10107],{"class":168},[64,10272,10273],{"class":73},"\u003Coption value=\"",[64,10275,8224],{"class":154},[64,10277,10121],{"class":197},[64,10279,270],{"class":200},[64,10281,10264],{"class":158},[64,10283,296],{"class":200},[64,10285,1183],{"class":154},[64,10287,10176],{"class":73},[64,10289,8224],{"class":154},[64,10291,10121],{"class":197},[64,10293,270],{"class":200},[64,10295,10264],{"class":158},[64,10297,296],{"class":200},[64,10299,1183],{"class":154},[64,10301,10302],{"class":73},"\u003C\u002Foption>",[64,10304,2513],{"class":168},[64,10306,296],{"class":3521},[64,10308,276],{"class":154},[64,10310,6797],{"class":197},[64,10312,270],{"class":3521},[64,10314,10315],{"class":168},"''",[64,10317,296],{"class":3521},[64,10319,178],{"class":154},[64,10321,10322],{"class":66,"line":2683},[64,10323,185],{"emptyLinePlaceholder":184},[64,10325,10326,10328,10330,10332,10334,10336,10339,10341,10343,10345,10347,10349,10352,10354,10356,10358,10360,10362,10365,10367,10369,10371,10373,10375,10377,10379,10382,10384],{"class":66,"line":2714},[64,10327,4616],{"class":150},[64,10329,10107],{"class":168},[64,10331,8224],{"class":154},[64,10333,10189],{"class":158},[64,10335,1183],{"class":154},[64,10337,10338],{"class":73},"\u003Cselect id=\"",[64,10340,8224],{"class":154},[64,10342,10025],{"class":158},[64,10344,276],{"class":154},[64,10346,308],{"class":279},[64,10348,1183],{"class":154},[64,10350,10351],{"class":73},"\" name=\"",[64,10353,8224],{"class":154},[64,10355,10025],{"class":158},[64,10357,276],{"class":154},[64,10359,308],{"class":279},[64,10361,1183],{"class":154},[64,10363,10364],{"class":73},"\" ",[64,10366,8224],{"class":154},[64,10368,10076],{"class":158},[64,10370,1183],{"class":154},[64,10372,945],{"class":73},[64,10374,8224],{"class":154},[64,10376,10248],{"class":158},[64,10378,1183],{"class":154},[64,10380,10381],{"class":73},"\u003C\u002Fselect>",[64,10383,2513],{"class":168},[64,10385,178],{"class":154},[64,10387,10388],{"class":66,"line":2743},[64,10389,5299],{"class":154},[64,10391,10392],{"class":66,"line":2748},[64,10393,10394],{"class":143},"  \u002F\u002F `attrs` porte déjà `type` quand la forme le décide : ne pas le réécrire, sinon la\n",[64,10396,10397],{"class":66,"line":2753},[64,10398,10399],{"class":143},"  \u002F\u002F balise en a deux et c'est la page qui a tranché.\n",[64,10401,10402,10404,10406,10408,10410,10412,10414,10417,10419,10421,10423,10425,10427,10429,10431,10434],{"class":66,"line":2759},[64,10403,4336],{"class":241},[64,10405,1455],{"class":158},[64,10407,1920],{"class":154},[64,10409,169],{"class":168},[64,10411,8860],{"class":73},[64,10413,175],{"class":168},[64,10415,10416],{"class":154}," in",[64,10418,8432],{"class":3521},[64,10420,10025],{"class":158},[64,10422,276],{"class":154},[64,10424,10076],{"class":279},[64,10426,9839],{"class":154},[64,10428,4590],{"class":154},[64,10430,296],{"class":3521},[64,10432,10433],{"class":154}," ?",[64,10435,10436],{"class":168}," ''\n",[64,10438,10439,10442,10444,10447,10449,10451,10453,10455,10457,10459,10462,10464,10466,10468,10471,10473,10476,10479,10481,10483,10485,10487,10490,10492,10494,10496,10498,10500,10502,10504,10506,10508,10510,10512,10514],{"class":66,"line":2765},[64,10440,10441],{"class":154},"    :",[64,10443,10107],{"class":168},[64,10445,10446],{"class":73}," type=\"",[64,10448,8224],{"class":154},[64,10450,10025],{"class":158},[64,10452,276],{"class":154},[64,10454,10218],{"class":279},[64,10456,8794],{"class":154},[64,10458,169],{"class":168},[64,10460,10461],{"class":73},"boolean",[64,10463,175],{"class":168},[64,10465,10433],{"class":154},[64,10467,169],{"class":168},[64,10469,10470],{"class":73},"checkbox",[64,10472,175],{"class":168},[64,10474,10475],{"class":154}," :",[64,10477,10478],{"class":158}," field",[64,10480,276],{"class":154},[64,10482,10218],{"class":279},[64,10484,8794],{"class":154},[64,10486,169],{"class":168},[64,10488,10489],{"class":73},"reference",[64,10491,175],{"class":168},[64,10493,10433],{"class":154},[64,10495,169],{"class":168},[64,10497,214],{"class":73},[64,10499,175],{"class":168},[64,10501,10475],{"class":154},[64,10503,10478],{"class":158},[64,10505,276],{"class":154},[64,10507,10218],{"class":279},[64,10509,1183],{"class":154},[64,10511,1436],{"class":73},[64,10513,2513],{"class":168},[64,10515,178],{"class":154},[64,10517,10518],{"class":66,"line":2771},[64,10519,185],{"emptyLinePlaceholder":184},[64,10521,10522,10524,10526,10528,10530,10532,10535,10537,10539,10541,10543,10545,10547,10549,10551,10553,10555,10557,10559,10561,10563,10565,10568,10570,10572,10574,10576],{"class":66,"line":2776},[64,10523,8488],{"class":150},[64,10525,10107],{"class":168},[64,10527,8224],{"class":154},[64,10529,10189],{"class":158},[64,10531,1183],{"class":154},[64,10533,10534],{"class":73},"\u003Cinput id=\"",[64,10536,8224],{"class":154},[64,10538,10025],{"class":158},[64,10540,276],{"class":154},[64,10542,308],{"class":279},[64,10544,1183],{"class":154},[64,10546,10351],{"class":73},[64,10548,8224],{"class":154},[64,10550,10025],{"class":158},[64,10552,276],{"class":154},[64,10554,308],{"class":279},[64,10556,1183],{"class":154},[64,10558,1436],{"class":73},[64,10560,8224],{"class":154},[64,10562,8860],{"class":158},[64,10564,1183],{"class":154},[64,10566,10567],{"class":154}," ${",[64,10569,10076],{"class":158},[64,10571,1183],{"class":154},[64,10573,945],{"class":73},[64,10575,2513],{"class":168},[64,10577,178],{"class":154},[64,10579,10580],{"class":66,"line":2784},[64,10581,5410],{"class":154},[64,10583,10584],{"class":66,"line":2789},[64,10585,185],{"emptyLinePlaceholder":184},[64,10587,10588,10590,10592,10594,10597,10599,10601,10604,10606],{"class":66,"line":2802},[64,10589,4355],{"class":241},[64,10591,8529],{"class":241},[64,10593,3498],{"class":197},[64,10595,10596],{"class":154},"():",[64,10598,5331],{"class":942},[64,10600,939],{"class":154},[64,10602,10603],{"class":942},"string",[64,10605,945],{"class":154},[64,10607,3506],{"class":154},[64,10609,10610,10612,10614,10617,10619,10621,10623,10625,10627,10629,10631,10633,10635,10637,10639,10641,10643,10645,10647,10649,10651,10653,10655,10657,10659,10661,10663,10665,10667,10669],{"class":66,"line":2808},[64,10611,4336],{"class":241},[64,10613,155],{"class":154},[64,10615,10616],{"class":158}," items",[64,10618,162],{"class":154},[64,10620,1920],{"class":154},[64,10622,251],{"class":150},[64,10624,782],{"class":197},[64,10626,270],{"class":3521},[64,10628,717],{"class":154},[64,10630,789],{"class":583},[64,10632,501],{"class":154},[64,10634,169],{"class":168},[64,10636,796],{"class":73},[64,10638,175],{"class":168},[64,10640,399],{"class":154},[64,10642,803],{"class":583},[64,10644,501],{"class":154},[64,10646,169],{"class":168},[64,10648,1848],{"class":73},[64,10650,175],{"class":168},[64,10652,815],{"class":154},[64,10654,5684],{"class":158},[64,10656,276],{"class":154},[64,10658,5991],{"class":279},[64,10660,296],{"class":3521},[64,10662,1004],{"class":150},[64,10664,9636],{"class":942},[64,10666,939],{"class":154},[64,10668,563],{"class":942},[64,10670,10671],{"class":154},">;\n",[64,10673,10674,10676,10679,10681,10683,10685,10687,10689,10691,10693,10695,10697],{"class":66,"line":2813},[64,10675,4336],{"class":241},[64,10677,10678],{"class":158}," fields",[64,10680,1920],{"class":154},[64,10682,9677],{"class":197},[64,10684,270],{"class":3521},[64,10686,563],{"class":158},[64,10688,399],{"class":154},[64,10690,169],{"class":168},[64,10692,796],{"class":73},[64,10694,175],{"class":168},[64,10696,296],{"class":3521},[64,10698,178],{"class":154},[64,10700,10701],{"class":66,"line":2820},[64,10702,185],{"emptyLinePlaceholder":184},[64,10704,10705,10707,10709],{"class":66,"line":2836},[64,10706,8488],{"class":150},[64,10708,10107],{"class":168},[64,10710,10711],{"class":73},"\u003C!doctype html>\u003Cmeta charset=\"utf-8\">\u003Ctitle>test-gradient\u003C\u002Ftitle>\n",[64,10713,10714],{"class":66,"line":2867},[64,10715,10716],{"class":73},"\u003Ch1>Catalogue\u003C\u002Fh1>\n",[64,10718,10719,10722,10724,10726,10728,10730,10732,10734,10737,10739,10741,10743,10746,10748,10750,10752,10754,10756,10758,10760,10762,10764,10766,10768,10770,10772,10774,10776,10778,10780,10783,10785,10787,10789,10791,10793,10795,10797,10799],{"class":66,"line":2898},[64,10720,10721],{"class":73},"\u003Cul id=\"products\">",[64,10723,8224],{"class":154},[64,10725,661],{"class":158},[64,10727,276],{"class":154},[64,10729,285],{"class":197},[64,10731,270],{"class":200},[64,10733,270],{"class":154},[64,10735,10736],{"class":292},"row",[64,10738,296],{"class":154},[64,10740,300],{"class":299},[64,10742,10107],{"class":168},[64,10744,10745],{"class":73},"\u003Cli data-sku=\"",[64,10747,8224],{"class":154},[64,10749,10121],{"class":197},[64,10751,270],{"class":200},[64,10753,10736],{"class":158},[64,10755,276],{"class":154},[64,10757,1439],{"class":279},[64,10759,296],{"class":200},[64,10761,1183],{"class":154},[64,10763,10176],{"class":73},[64,10765,8224],{"class":154},[64,10767,10121],{"class":197},[64,10769,270],{"class":200},[64,10771,10736],{"class":158},[64,10773,276],{"class":154},[64,10775,308],{"class":279},[64,10777,296],{"class":200},[64,10779,1183],{"class":154},[64,10781,10782],{"class":73},"\u003C\u002Fli>",[64,10784,2513],{"class":168},[64,10786,296],{"class":200},[64,10788,276],{"class":154},[64,10790,6797],{"class":197},[64,10792,270],{"class":200},[64,10794,10315],{"class":168},[64,10796,296],{"class":200},[64,10798,1183],{"class":154},[64,10800,10801],{"class":73},"\u003C\u002Ful>\n",[64,10803,10804,10807,10809,10812,10814,10816,10818,10821,10823,10825,10827,10829,10831,10833,10835],{"class":66,"line":2903},[64,10805,10806],{"class":73},"\u003Cform id=\"new-product\">",[64,10808,8224],{"class":154},[64,10810,10811],{"class":158},"fields",[64,10813,276],{"class":154},[64,10815,285],{"class":197},[64,10817,270],{"class":200},[64,10819,10820],{"class":158},"inputFor",[64,10822,296],{"class":200},[64,10824,276],{"class":154},[64,10826,6797],{"class":197},[64,10828,270],{"class":200},[64,10830,10315],{"class":168},[64,10832,296],{"class":200},[64,10834,1183],{"class":154},[64,10836,10837],{"class":73},"\u003Cbutton type=\"submit\">Ajouter\u003C\u002Fbutton>\u003C\u002Fform>\n",[64,10839,10840],{"class":66,"line":2908},[64,10841,10842],{"class":73},"\u003Cp id=\"error\" hidden>\u003C\u002Fp>\n",[64,10844,10845],{"class":66,"line":2924},[64,10846,10847],{"class":73},"\u003Cscript type=\"module\">\n",[64,10849,10850],{"class":66,"line":2954},[64,10851,10852],{"class":73},"const form = document.querySelector('#new-product');\n",[64,10854,10855],{"class":66,"line":2976},[64,10856,10857],{"class":73},"const error = document.querySelector('#error');\n",[64,10859,10860],{"class":66,"line":2981},[64,10861,10862],{"class":73},"form.addEventListener('submit', async (event) => {\n",[64,10864,10865],{"class":66,"line":2997},[64,10866,10867],{"class":73},"  event.preventDefault();\n",[64,10869,10870],{"class":66,"line":3003},[64,10871,10872],{"class":73},"  error.hidden = true;\n",[64,10874,10875],{"class":66,"line":3009},[64,10876,10877],{"class":73},"  \u002F\u002F Le texte du formulaire, tel quel : c'est le serveur, comme useFormFor, qui le lit selon\n",[64,10879,10880],{"class":66,"line":3014},[64,10881,10882],{"class":73},"  \u002F\u002F la forme de Product. La page ne nomme aucun champ.\n",[64,10884,10885],{"class":66,"line":3022},[64,10886,10887],{"class":73},"  const response = await fetch('\u002Fform\u002Fproduct', {\n",[64,10889,10890],{"class":66,"line":3027},[64,10891,10892],{"class":73},"    method: 'POST',\n",[64,10894,10895],{"class":66,"line":3040},[64,10896,10897],{"class":73},"    headers: { 'content-type': 'application\u002Fjson' },\n",[64,10899,10900],{"class":66,"line":3046},[64,10901,10902],{"class":73},"    body: JSON.stringify(Object.fromEntries(new FormData(form))),\n",[64,10904,10905],{"class":66,"line":3051},[64,10906,10907],{"class":73},"  });\n",[64,10909,10910],{"class":66,"line":3057},[64,10911,10912],{"class":73},"  const answer = await response.json();\n",[64,10914,10915],{"class":66,"line":3063},[64,10916,10917],{"class":73},"  if (answer.error) { error.textContent = answer.error.message; error.hidden = false; return; }\n",[64,10919,10920],{"class":66,"line":3068},[64,10921,10922],{"class":73},"  location.reload();\n",[64,10924,10925],{"class":66,"line":3076},[64,10926,10927],{"class":73},"});\n",[64,10929,10930,10933,10935],{"class":66,"line":3081},[64,10931,10932],{"class":73},"\u003C\u002Fscript>",[64,10934,2513],{"class":168},[64,10936,178],{"class":154},[64,10938,10939],{"class":66,"line":3103},[64,10940,5410],{"class":154},[64,10942,10943],{"class":66,"line":3118},[64,10944,185],{"emptyLinePlaceholder":184},[64,10946,10947,10949,10951,10954,10956,10959,10961,10964,10966,10969,10972,10974,10976,10978,10980],{"class":66,"line":3124},[64,10948,4355],{"class":241},[64,10950,8529],{"class":241},[64,10952,10953],{"class":197}," bodyOf",[64,10955,270],{"class":154},[64,10957,10958],{"class":292},"request",[64,10960,501],{"class":154},[64,10962,10963],{"class":942}," AsyncIterable",[64,10965,939],{"class":154},[64,10967,10968],{"class":942},"unknown",[64,10970,10971],{"class":154},">):",[64,10973,5331],{"class":942},[64,10975,939],{"class":154},[64,10977,10968],{"class":942},[64,10979,945],{"class":154},[64,10981,3506],{"class":154},[64,10983,10984,10986,10989,10991,10994,10997,10999,11002],{"class":66,"line":3129},[64,10985,4336],{"class":241},[64,10987,10988],{"class":158}," chunks",[64,10990,501],{"class":154},[64,10992,10993],{"class":942}," Buffer",[64,10995,10996],{"class":3521},"[]",[64,10998,1920],{"class":154},[64,11000,11001],{"class":3521}," []",[64,11003,178],{"class":154},[64,11005,11006,11008,11010,11012,11014,11017,11019,11022,11024,11026,11028,11031,11033,11036,11038,11040,11042],{"class":66,"line":3135},[64,11007,8429],{"class":150},[64,11009,251],{"class":150},[64,11011,8432],{"class":3521},[64,11013,929],{"class":241},[64,11015,11016],{"class":158}," chunk",[64,11018,8439],{"class":154},[64,11020,11021],{"class":158}," request",[64,11023,296],{"class":3521},[64,11025,10988],{"class":158},[64,11027,276],{"class":154},[64,11029,11030],{"class":197},"push",[64,11032,270],{"class":3521},[64,11034,11035],{"class":158},"chunk",[64,11037,1004],{"class":150},[64,11039,10993],{"class":942},[64,11041,296],{"class":3521},[64,11043,178],{"class":154},[64,11045,11046],{"class":66,"line":3141},[64,11047,185],{"emptyLinePlaceholder":184},[64,11049,11050,11052,11054,11056,11059,11061,11064,11066,11069,11071,11074,11076,11078,11081,11083],{"class":66,"line":3146},[64,11051,8488],{"class":150},[64,11053,4444],{"class":158},[64,11055,276],{"class":154},[64,11057,11058],{"class":197},"parse",[64,11060,270],{"class":3521},[64,11062,11063],{"class":158},"Buffer",[64,11065,276],{"class":154},[64,11067,11068],{"class":197},"concat",[64,11070,270],{"class":3521},[64,11072,11073],{"class":158},"chunks",[64,11075,296],{"class":3521},[64,11077,276],{"class":154},[64,11079,11080],{"class":197},"toString",[64,11082,433],{"class":3521},[64,11084,178],{"class":154},[64,11086,11087],{"class":66,"line":3154},[64,11088,5410],{"class":154},[64,11090,11091],{"class":66,"line":3159},[64,11092,185],{"emptyLinePlaceholder":184},[64,11094,11095,11097,11099,11102,11104,11107,11109,11111,11113,11115,11117,11119,11121],{"class":66,"line":3182},[64,11096,4355],{"class":241},[64,11098,8529],{"class":241},[64,11100,11101],{"class":197}," called",[64,11103,270],{"class":154},[64,11105,11106],{"class":292},"body",[64,11108,501],{"class":154},[64,11110,1001],{"class":942},[64,11112,5328],{"class":154},[64,11114,5331],{"class":942},[64,11116,939],{"class":154},[64,11118,10603],{"class":942},[64,11120,945],{"class":154},[64,11122,3506],{"class":154},[64,11124,11125,11127,11130,11132,11134,11136,11138,11140,11142,11144,11147,11149,11151,11154,11156,11158,11160,11162,11164,11166,11168,11170,11172,11175,11177,11179,11181,11183,11185,11187,11189,11191,11193,11195,11197,11199,11201,11203,11205,11207],{"class":66,"line":3203},[64,11126,4336],{"class":241},[64,11128,11129],{"class":158}," answered",[64,11131,1920],{"class":154},[64,11133,251],{"class":150},[64,11135,4339],{"class":197},[64,11137,270],{"class":3521},[64,11139,273],{"class":158},[64,11141,399],{"class":154},[64,11143,986],{"class":154},[64,11145,11146],{"class":989}," Request",[64,11148,270],{"class":3521},[64,11150,175],{"class":168},[64,11152,11153],{"class":73},"http:\u002F\u002Flocalhost\u002F_fougere\u002Fcall",[64,11155,175],{"class":168},[64,11157,399],{"class":154},[64,11159,155],{"class":154},[64,11161,4479],{"class":583},[64,11163,501],{"class":154},[64,11165,169],{"class":168},[64,11167,4401],{"class":73},[64,11169,175],{"class":168},[64,11171,399],{"class":154},[64,11173,11174],{"class":583}," body",[64,11176,501],{"class":154},[64,11178,4444],{"class":158},[64,11180,276],{"class":154},[64,11182,4449],{"class":989},[64,11184,270],{"class":3521},[64,11186,11106],{"class":158},[64,11188,296],{"class":3521},[64,11190,162],{"class":154},[64,11192,296],{"class":3521},[64,11194,399],{"class":154},[64,11196,155],{"class":154},[64,11198,4585],{"class":583},[64,11200,501],{"class":154},[64,11202,4590],{"class":154},[64,11204,162],{"class":154},[64,11206,296],{"class":3521},[64,11208,178],{"class":154},[64,11210,11211],{"class":66,"line":3209},[64,11212,185],{"emptyLinePlaceholder":184},[64,11214,11215,11217,11219,11222,11224,11226],{"class":66,"line":3214},[64,11216,8488],{"class":150},[64,11218,11129],{"class":158},[64,11220,11221],{"class":154},"!.",[64,11223,214],{"class":197},[64,11225,201],{"class":3521},[64,11227,178],{"class":154},[64,11229,11230],{"class":66,"line":3222},[64,11231,5410],{"class":154},[64,11233,11234],{"class":66,"line":3283},[64,11235,185],{"emptyLinePlaceholder":184},[64,11237,11238,11241,11243,11245,11247,11249,11251,11253,11255,11257],{"class":66,"line":3351},[64,11239,11240],{"class":197},"createServer",[64,11242,270],{"class":200},[64,11244,4355],{"class":241},[64,11246,8432],{"class":154},[64,11248,10958],{"class":292},[64,11250,399],{"class":154},[64,11252,4369],{"class":292},[64,11254,296],{"class":154},[64,11256,300],{"class":299},[64,11258,3506],{"class":154},[64,11260,11261,11263,11265,11267,11269,11272,11274,11276,11278,11280,11283],{"class":66,"line":3356},[64,11262,10209],{"class":150},[64,11264,8432],{"class":3521},[64,11266,10958],{"class":158},[64,11268,276],{"class":154},[64,11270,11271],{"class":279},"url",[64,11273,8794],{"class":154},[64,11275,169],{"class":168},[64,11277,1547],{"class":73},[64,11279,175],{"class":168},[64,11281,11282],{"class":3521}," )",[64,11284,3506],{"class":154},[64,11286,11287,11290,11292,11295,11297,11300,11302,11304,11306,11308,11310,11312,11314,11317,11319,11321,11323],{"class":66,"line":3361},[64,11288,11289],{"class":158},"    response",[64,11291,276],{"class":154},[64,11293,11294],{"class":197},"writeHead",[64,11296,270],{"class":3521},[64,11298,11299],{"class":623},"200",[64,11301,399],{"class":154},[64,11303,155],{"class":154},[64,11305,169],{"class":168},[64,11307,4420],{"class":4419},[64,11309,175],{"class":168},[64,11311,501],{"class":154},[64,11313,169],{"class":168},[64,11315,11316],{"class":73},"text\u002Fhtml; charset=utf-8",[64,11318,175],{"class":168},[64,11320,162],{"class":154},[64,11322,296],{"class":3521},[64,11324,178],{"class":154},[64,11326,11327,11329,11331,11334,11336,11338,11340,11342],{"class":66,"line":3367},[64,11328,11289],{"class":158},[64,11330,276],{"class":154},[64,11332,11333],{"class":197},"end",[64,11335,270],{"class":3521},[64,11337,428],{"class":150},[64,11339,3498],{"class":197},[64,11341,433],{"class":3521},[64,11343,178],{"class":154},[64,11345,11346],{"class":66,"line":3382},[64,11347,185],{"emptyLinePlaceholder":184},[64,11349,11350,11352],{"class":66,"line":3388},[64,11351,4616],{"class":150},[64,11353,178],{"class":154},[64,11355,11356],{"class":66,"line":3394},[64,11357,5299],{"class":154},[64,11359,11360,11362,11364,11366,11368,11370,11372,11374,11376,11378,11381,11383,11385,11387,11389,11391,11393,11395,11397],{"class":66,"line":7950},[64,11361,10209],{"class":150},[64,11363,8432],{"class":3521},[64,11365,10958],{"class":158},[64,11367,276],{"class":154},[64,11369,7004],{"class":279},[64,11371,8794],{"class":154},[64,11373,169],{"class":168},[64,11375,4401],{"class":73},[64,11377,175],{"class":168},[64,11379,11380],{"class":154}," &&",[64,11382,11021],{"class":158},[64,11384,276],{"class":154},[64,11386,11271],{"class":279},[64,11388,8794],{"class":154},[64,11390,169],{"class":168},[64,11392,4383],{"class":73},[64,11394,175],{"class":168},[64,11396,296],{"class":3521},[64,11398,3506],{"class":154},[64,11400,11401,11403,11405,11407,11409,11411,11413,11415,11417,11419,11421,11423,11425,11427,11429,11431,11433],{"class":66,"line":7956},[64,11402,11289],{"class":158},[64,11404,276],{"class":154},[64,11406,11294],{"class":197},[64,11408,270],{"class":3521},[64,11410,11299],{"class":623},[64,11412,399],{"class":154},[64,11414,155],{"class":154},[64,11416,169],{"class":168},[64,11418,4420],{"class":4419},[64,11420,175],{"class":168},[64,11422,501],{"class":154},[64,11424,169],{"class":168},[64,11426,4429],{"class":73},[64,11428,175],{"class":168},[64,11430,162],{"class":154},[64,11432,296],{"class":3521},[64,11434,178],{"class":154},[64,11436,11437,11439,11441,11443,11445,11447,11449,11451,11453,11455,11457,11459,11462],{"class":66,"line":7962},[64,11438,11289],{"class":158},[64,11440,276],{"class":154},[64,11442,11333],{"class":197},[64,11444,270],{"class":3521},[64,11446,428],{"class":150},[64,11448,11101],{"class":197},[64,11450,270],{"class":3521},[64,11452,428],{"class":150},[64,11454,10953],{"class":197},[64,11456,270],{"class":3521},[64,11458,10958],{"class":158},[64,11460,11461],{"class":3521},")))",[64,11463,178],{"class":154},[64,11465,11466],{"class":66,"line":7968},[64,11467,185],{"emptyLinePlaceholder":184},[64,11469,11470,11472],{"class":66,"line":8000},[64,11471,4616],{"class":150},[64,11473,178],{"class":154},[64,11475,11476],{"class":66,"line":8005},[64,11477,5299],{"class":154},[64,11479,11480],{"class":66,"line":8020},[64,11481,11482],{"class":143},"  \u002F\u002F Ce que fait useFormFor dans un hôte : le texte d'un formulaire, lu selon la forme de\n",[64,11484,11485],{"class":66,"line":8026},[64,11486,11487],{"class":143},"  \u002F\u002F l'entité, puis la même porte. `\u002F_fougere\u002Fcall` reste strict pour un client JSON.\n",[64,11489,11490,11492,11494,11496,11498,11500,11502,11504,11506,11508,11510,11512,11514,11516,11518,11520,11523,11525,11527],{"class":66,"line":8036},[64,11491,10209],{"class":150},[64,11493,8432],{"class":3521},[64,11495,10958],{"class":158},[64,11497,276],{"class":154},[64,11499,7004],{"class":279},[64,11501,8794],{"class":154},[64,11503,169],{"class":168},[64,11505,4401],{"class":73},[64,11507,175],{"class":168},[64,11509,11380],{"class":154},[64,11511,11021],{"class":158},[64,11513,276],{"class":154},[64,11515,11271],{"class":279},[64,11517,8794],{"class":154},[64,11519,169],{"class":168},[64,11521,11522],{"class":73},"\u002Fform\u002Fproduct",[64,11524,175],{"class":168},[64,11526,296],{"class":3521},[64,11528,3506],{"class":154},[64,11530,11531,11533,11535,11537,11539,11541,11543,11545,11547,11549,11551,11553,11555,11557,11560,11562,11564,11566,11568,11570,11572],{"class":66,"line":8066},[64,11532,4366],{"class":241},[64,11534,4516],{"class":158},[64,11536,1920],{"class":154},[64,11538,9682],{"class":197},[64,11540,270],{"class":3521},[64,11542,563],{"class":158},[64,11544,399],{"class":154},[64,11546,251],{"class":150},[64,11548,10953],{"class":197},[64,11550,270],{"class":3521},[64,11552,10958],{"class":158},[64,11554,296],{"class":3521},[64,11556,1004],{"class":150},[64,11558,11559],{"class":942}," Record",[64,11561,939],{"class":154},[64,11563,10603],{"class":942},[64,11565,399],{"class":154},[64,11567,1001],{"class":942},[64,11569,945],{"class":154},[64,11571,296],{"class":3521},[64,11573,178],{"class":154},[64,11575,11576,11578,11580,11582,11584,11586,11588,11590,11592,11594,11596,11598,11600,11602,11604,11606,11608],{"class":66,"line":8092},[64,11577,11289],{"class":158},[64,11579,276],{"class":154},[64,11581,11294],{"class":197},[64,11583,270],{"class":3521},[64,11585,11299],{"class":623},[64,11587,399],{"class":154},[64,11589,155],{"class":154},[64,11591,169],{"class":168},[64,11593,4420],{"class":4419},[64,11595,175],{"class":168},[64,11597,501],{"class":154},[64,11599,169],{"class":168},[64,11601,4429],{"class":73},[64,11603,175],{"class":168},[64,11605,162],{"class":154},[64,11607,296],{"class":3521},[64,11609,178],{"class":154},[64,11611,11612,11614,11616,11618,11620,11622,11624,11626,11628,11630,11632,11634,11636,11638,11640,11642,11644,11646,11648,11650,11652,11654,11656,11658,11660,11662,11664,11666,11668,11670,11672,11674,11676,11678,11680,11682,11684,11686,11688,11690,11692,11694],{"class":66,"line":8117},[64,11613,11289],{"class":158},[64,11615,276],{"class":154},[64,11617,11333],{"class":197},[64,11619,270],{"class":3521},[64,11621,428],{"class":150},[64,11623,11101],{"class":197},[64,11625,270],{"class":3521},[64,11627,717],{"class":154},[64,11629,4456],{"class":583},[64,11631,501],{"class":154},[64,11633,169],{"class":168},[64,11635,4463],{"class":73},[64,11637,175],{"class":168},[64,11639,399],{"class":154},[64,11641,1175],{"class":583},[64,11643,501],{"class":154},[64,11645,4474],{"class":623},[64,11647,399],{"class":154},[64,11649,4479],{"class":583},[64,11651,501],{"class":154},[64,11653,169],{"class":168},[64,11655,4486],{"class":73},[64,11657,175],{"class":168},[64,11659,399],{"class":154},[64,11661,4502],{"class":583},[64,11663,501],{"class":154},[64,11665,155],{"class":154},[64,11667,4502],{"class":583},[64,11669,501],{"class":154},[64,11671,613],{"class":154},[64,11673,4509],{"class":583},[64,11675,501],{"class":154},[64,11677,613],{"class":154},[64,11679,4516],{"class":158},[64,11681,399],{"class":154},[64,11683,4585],{"class":583},[64,11685,501],{"class":154},[64,11687,4590],{"class":154},[64,11689,162],{"class":154},[64,11691,162],{"class":154},[64,11693,311],{"class":3521},[64,11695,178],{"class":154},[64,11697,11698],{"class":66,"line":8125},[64,11699,185],{"emptyLinePlaceholder":184},[64,11701,11702,11704],{"class":66,"line":8131},[64,11703,4616],{"class":150},[64,11705,178],{"class":154},[64,11707,11708],{"class":66,"line":8137},[64,11709,5299],{"class":154},[64,11711,11712,11715,11717,11719,11721,11724,11726,11728,11730,11732],{"class":66,"line":8143},[64,11713,11714],{"class":158},"  response",[64,11716,276],{"class":154},[64,11718,11294],{"class":197},[64,11720,270],{"class":3521},[64,11722,11723],{"class":623},"404",[64,11725,296],{"class":3521},[64,11727,276],{"class":154},[64,11729,11333],{"class":197},[64,11731,201],{"class":3521},[64,11733,178],{"class":154},[64,11735,11736,11738,11740,11742,11745,11747,11749,11751,11753,11756,11758,11760,11762,11764,11767,11769,11771,11773,11775,11778,11780,11782,11784,11786,11788],{"class":66,"line":8149},[64,11737,1183],{"class":154},[64,11739,296],{"class":200},[64,11741,276],{"class":154},[64,11743,11744],{"class":197},"listen",[64,11746,270],{"class":200},[64,11748,694],{"class":158},[64,11750,399],{"class":154},[64,11752,169],{"class":168},[64,11754,11755],{"class":73},"127.0.0.1",[64,11757,175],{"class":168},[64,11759,399],{"class":154},[64,11761,1934],{"class":154},[64,11763,300],{"class":299},[64,11765,11766],{"class":158}," console",[64,11768,276],{"class":154},[64,11770,6879],{"class":197},[64,11772,270],{"class":200},[64,11774,2513],{"class":168},[64,11776,11777],{"class":73},"http:\u002F\u002F127.0.0.1:",[64,11779,8224],{"class":154},[64,11781,694],{"class":158},[64,11783,1183],{"class":154},[64,11785,2513],{"class":168},[64,11787,311],{"class":200},[64,11789,178],{"class":154},[54,11791,11793],{"className":134,"code":11792,"filename":2794,"language":136,"meta":60,"style":60},"\u002F**\n * CRAN 2 — plusieurs fronds, ensemble. Le fichier entier.\n *\n * Aucune entité n'est nommée : la liste vient du scan. Une liste d'imports serait une\n * seconde copie de ce que le projet déclare déjà, et elle périmerait le jour où une entité\n * est ajoutée — en silence, parce qu'un test absent ne peut pas échouer.\n *\u002F\nimport { testApp, checkAll } from '@fougere\u002Ftesting';\n\ncheckAll(await testApp());\n\n",[17,11794,11795,11799,11804,11808,11813,11818,11823,11827,11851,11855],{"__ignoreMap":60},[64,11796,11797],{"class":66,"line":67},[64,11798,3407],{"class":143},[64,11800,11801],{"class":66,"line":147},[64,11802,11803],{"class":143}," * CRAN 2 — plusieurs fronds, ensemble. Le fichier entier.\n",[64,11805,11806],{"class":66,"line":181},[64,11807,3417],{"class":143},[64,11809,11810],{"class":66,"line":188},[64,11811,11812],{"class":143}," * Aucune entité n'est nommée : la liste vient du scan. Une liste d'imports serait une\n",[64,11814,11815],{"class":66,"line":825},[64,11816,11817],{"class":143}," * seconde copie de ce que le projet déclare déjà, et elle périmerait le jour où une entité\n",[64,11819,11820],{"class":66,"line":830},[64,11821,11822],{"class":143}," * est ajoutée — en silence, parce qu'un test absent ne peut pas échouer.\n",[64,11824,11825],{"class":66,"line":1760},[64,11826,3442],{"class":143},[64,11828,11829,11831,11833,11835,11837,11839,11841,11843,11845,11847,11849],{"class":66,"line":2418},[64,11830,151],{"class":150},[64,11832,155],{"class":154},[64,11834,254],{"class":158},[64,11836,399],{"class":154},[64,11838,402],{"class":158},[64,11840,162],{"class":154},[64,11842,165],{"class":150},[64,11844,169],{"class":168},[64,11846,19],{"class":73},[64,11848,175],{"class":168},[64,11850,178],{"class":154},[64,11852,11853],{"class":66,"line":2424},[64,11854,185],{"emptyLinePlaceholder":184},[64,11856,11857,11859,11861,11863,11865,11867],{"class":66,"line":2430},[64,11858,423],{"class":197},[64,11860,270],{"class":200},[64,11862,428],{"class":150},[64,11864,254],{"class":197},[64,11866,433],{"class":200},[64,11868,178],{"class":154},[54,11870,11872],{"className":134,"code":11871,"filename":3032,"language":136,"meta":60,"style":60},"\u002F**\n * CRAN 3 — l'app dans son process, le test en client.\n *\n * Rien de neuf n'est inventé ici : le test parle par le transport qui fait déjà marcher\n * un frond déplacé. C'est le gradient appliqué au test lui-même — il devient un\n * consommateur, exactement comme un navigateur posé à côté.\n *\n * Playwright n'a pas d'objet dans cette démo : elle n'a pas de front. Le cran navigateur\n * se montre là où il y a des pages.\n *\u002F\nimport { describe, it, expect, beforeAll, afterAll } from 'vitest';\nimport { createLocalRunner, type App } from '@fougere\u002Fcore';\nimport { serve, createHttpTransport, type RunningReceiver } from '@fougere\u002Ftransport-http';\nimport { testApp, sampleInput } from '@fougere\u002Ftesting';\nimport Product from '..\u002Ffronds\u002Fcatalog\u002Fentities\u002FProduct.js';\n\nlet app: App;\nlet receiver: RunningReceiver;\nlet call: ReturnType\u003Ctypeof createHttpTransport>;\n\nbeforeAll(async () => {\n  app = await testApp({ root: import.meta.dirname.replace(\u002F\\\u002Ftests$\u002F, '') });\n  \u002F\u002F Port 0 : le système en choisit un libre, donc deux runs en parallèle ne se marchent\n  \u002F\u002F pas dessus — la même raison qui fait qu'une base de test est jetable par run.\n  receiver = await serve(createLocalRunner(app), { port: 0 });\n  \u002F\u002F L'adresse de base, comme `remotes: { blog: 'http:\u002F\u002F127.0.0.1:4100' }` — le\n  \u002F\u002F transport connaît son propre chemin.\n  call = createHttpTransport(`http:\u002F\u002F127.0.0.1:${receiver.port}`);\n});\n\nafterAll(async () => {\n  await receiver.close();\n  await app.dispose();\n});\n\ndescribe('une app derrière sa porte', () => {\n  it('accepte une ligne semée par le fil', async () => {\n    const created = await call(\n      { address: 'product', op: 'create' },\n      { params: {}, query: {}, input: sampleInput(Product, { sku: 'WIRE-1' }), state: {} },\n    ) as { sku: string; id: string };\n\n    expect(created.sku).toBe('WIRE-1');\n    expect(created.id).toBeTruthy();\n  });\n\n  it('refuse par le fil ce que le juge refuse en mémoire', async () => {\n    const bad = { ...sampleInput(Product, { sku: 'WIRE-2' }), cents: -1 };\n\n    await expect(call(\n      { address: 'product', op: 'create' },\n      { params: {}, query: {}, input: bad, state: {} },\n    )).rejects.toThrow(\u002Fcents\u002F);\n  });\n});\n\n",[17,11873,11874,11878,11883,11887,11892,11897,11902,11906,11911,11916,11920,11958,11985,12018,12042,12059,12063,12075,12088,12105,12109,12124,12186,12191,12196,12235,12240,12245,12277,12285,12289,12304,12319,12333,12341,12345,12366,12389,12403,12433,12488,12513,12517,12549,12572,12580,12584,12607,12657,12661,12675,12703,12735,12762,12770],{"__ignoreMap":60},[64,11875,11876],{"class":66,"line":67},[64,11877,3407],{"class":143},[64,11879,11880],{"class":66,"line":147},[64,11881,11882],{"class":143}," * CRAN 3 — l'app dans son process, le test en client.\n",[64,11884,11885],{"class":66,"line":181},[64,11886,3417],{"class":143},[64,11888,11889],{"class":66,"line":188},[64,11890,11891],{"class":143}," * Rien de neuf n'est inventé ici : le test parle par le transport qui fait déjà marcher\n",[64,11893,11894],{"class":66,"line":825},[64,11895,11896],{"class":143}," * un frond déplacé. C'est le gradient appliqué au test lui-même — il devient un\n",[64,11898,11899],{"class":66,"line":830},[64,11900,11901],{"class":143}," * consommateur, exactement comme un navigateur posé à côté.\n",[64,11903,11904],{"class":66,"line":1760},[64,11905,3417],{"class":143},[64,11907,11908],{"class":66,"line":2418},[64,11909,11910],{"class":143}," * Playwright n'a pas d'objet dans cette démo : elle n'a pas de front. Le cran navigateur\n",[64,11912,11913],{"class":66,"line":2424},[64,11914,11915],{"class":143}," * se montre là où il y a des pages.\n",[64,11917,11918],{"class":66,"line":2430},[64,11919,3442],{"class":143},[64,11921,11922,11924,11926,11928,11930,11932,11934,11936,11938,11941,11943,11946,11948,11950,11952,11954,11956],{"class":66,"line":2436},[64,11923,151],{"class":150},[64,11925,155],{"class":154},[64,11927,5632],{"class":158},[64,11929,399],{"class":154},[64,11931,5637],{"class":158},[64,11933,399],{"class":154},[64,11935,3456],{"class":158},[64,11937,399],{"class":154},[64,11939,11940],{"class":158}," beforeAll",[64,11942,399],{"class":154},[64,11944,11945],{"class":158}," afterAll",[64,11947,162],{"class":154},[64,11949,165],{"class":150},[64,11951,169],{"class":168},[64,11953,5650],{"class":73},[64,11955,175],{"class":168},[64,11957,178],{"class":154},[64,11959,11960,11962,11964,11966,11968,11970,11973,11975,11977,11979,11981,11983],{"class":66,"line":2442},[64,11961,151],{"class":150},[64,11963,155],{"class":154},[64,11965,5663],{"class":158},[64,11967,399],{"class":154},[64,11969,1455],{"class":150},[64,11971,11972],{"class":158}," App",[64,11974,162],{"class":154},[64,11976,165],{"class":150},[64,11978,169],{"class":168},[64,11980,4773],{"class":73},[64,11982,175],{"class":168},[64,11984,178],{"class":154},[64,11986,11987,11989,11991,11994,11996,11999,12001,12003,12006,12008,12010,12012,12014,12016],{"class":66,"line":2448},[64,11988,151],{"class":150},[64,11990,155],{"class":154},[64,11992,11993],{"class":158}," serve",[64,11995,399],{"class":154},[64,11997,11998],{"class":158}," createHttpTransport",[64,12000,399],{"class":154},[64,12002,1455],{"class":150},[64,12004,12005],{"class":158}," RunningReceiver",[64,12007,162],{"class":154},[64,12009,165],{"class":150},[64,12011,169],{"class":168},[64,12013,9229],{"class":73},[64,12015,175],{"class":168},[64,12017,178],{"class":154},[64,12019,12020,12022,12024,12026,12028,12030,12032,12034,12036,12038,12040],{"class":66,"line":2453},[64,12021,151],{"class":150},[64,12023,155],{"class":154},[64,12025,254],{"class":158},[64,12027,399],{"class":154},[64,12029,5710],{"class":158},[64,12031,162],{"class":154},[64,12033,165],{"class":150},[64,12035,169],{"class":168},[64,12037,19],{"class":73},[64,12039,175],{"class":168},[64,12041,178],{"class":154},[64,12043,12044,12046,12048,12050,12052,12055,12057],{"class":66,"line":2479},[64,12045,151],{"class":150},[64,12047,5192],{"class":158},[64,12049,5195],{"class":150},[64,12051,169],{"class":168},[64,12053,12054],{"class":73},"..\u002Ffronds\u002Fcatalog\u002Fentities\u002FProduct.js",[64,12056,175],{"class":168},[64,12058,178],{"class":154},[64,12060,12061],{"class":66,"line":2485},[64,12062,185],{"emptyLinePlaceholder":184},[64,12064,12065,12067,12069,12071,12073],{"class":66,"line":2491},[64,12066,8369],{"class":241},[64,12068,1221],{"class":158},[64,12070,501],{"class":154},[64,12072,11972],{"class":942},[64,12074,178],{"class":154},[64,12076,12077,12079,12082,12084,12086],{"class":66,"line":2496},[64,12078,8369],{"class":241},[64,12080,12081],{"class":158}," receiver",[64,12083,501],{"class":154},[64,12085,12005],{"class":942},[64,12087,178],{"class":154},[64,12089,12090,12092,12095,12097,12099,12101,12103],{"class":66,"line":2505},[64,12091,8369],{"class":241},[64,12093,12094],{"class":158}," call",[64,12096,501],{"class":154},[64,12098,10030],{"class":942},[64,12100,10033],{"class":154},[64,12102,11998],{"class":158},[64,12104,10671],{"class":154},[64,12106,12107],{"class":66,"line":2510},[64,12108,185],{"emptyLinePlaceholder":184},[64,12110,12111,12114,12116,12118,12120,12122],{"class":66,"line":2524},[64,12112,12113],{"class":197},"beforeAll",[64,12115,270],{"class":200},[64,12117,4355],{"class":241},[64,12119,1934],{"class":154},[64,12121,300],{"class":299},[64,12123,3506],{"class":154},[64,12125,12126,12129,12131,12133,12135,12137,12139,12141,12143,12145,12147,12149,12151,12153,12155,12157,12159,12161,12165,12168,12171,12173,12175,12178,12180,12182,12184],{"class":66,"line":2529},[64,12127,12128],{"class":158},"  app",[64,12130,1920],{"class":154},[64,12132,251],{"class":150},[64,12134,254],{"class":197},[64,12136,270],{"class":3521},[64,12138,717],{"class":154},[64,12140,6767],{"class":583},[64,12142,501],{"class":154},[64,12144,6772],{"class":150},[64,12146,276],{"class":154},[64,12148,6777],{"class":279},[64,12150,276],{"class":154},[64,12152,6782],{"class":279},[64,12154,276],{"class":154},[64,12156,9890],{"class":197},[64,12158,270],{"class":3521},[64,12160,1547],{"class":168},[64,12162,12164],{"class":12163},"sfnqo","\\\u002F",[64,12166,12167],{"class":73},"tests",[64,12169,12170],{"class":150},"$",[64,12172,1547],{"class":168},[64,12174,399],{"class":154},[64,12176,12177],{"class":168}," ''",[64,12179,296],{"class":3521},[64,12181,162],{"class":154},[64,12183,296],{"class":3521},[64,12185,178],{"class":154},[64,12187,12188],{"class":66,"line":2537},[64,12189,12190],{"class":143},"  \u002F\u002F Port 0 : le système en choisit un libre, donc deux runs en parallèle ne se marchent\n",[64,12192,12193],{"class":66,"line":2555},[64,12194,12195],{"class":143},"  \u002F\u002F pas dessus — la même raison qui fait qu'une base de test est jetable par run.\n",[64,12197,12198,12201,12203,12205,12207,12209,12212,12214,12216,12218,12220,12222,12225,12227,12229,12231,12233],{"class":66,"line":2603},[64,12199,12200],{"class":158},"  receiver",[64,12202,1920],{"class":154},[64,12204,251],{"class":150},[64,12206,11993],{"class":197},[64,12208,270],{"class":3521},[64,12210,12211],{"class":197},"createLocalRunner",[64,12213,270],{"class":3521},[64,12215,273],{"class":158},[64,12217,296],{"class":3521},[64,12219,399],{"class":154},[64,12221,155],{"class":154},[64,12223,12224],{"class":583}," port",[64,12226,501],{"class":154},[64,12228,7031],{"class":623},[64,12230,162],{"class":154},[64,12232,296],{"class":3521},[64,12234,178],{"class":154},[64,12236,12237],{"class":66,"line":2608},[64,12238,12239],{"class":143},"  \u002F\u002F L'adresse de base, comme `remotes: { blog: 'http:\u002F\u002F127.0.0.1:4100' }` — le\n",[64,12241,12242],{"class":66,"line":2613},[64,12243,12244],{"class":143},"  \u002F\u002F transport connaît son propre chemin.\n",[64,12246,12247,12250,12252,12254,12256,12258,12260,12262,12265,12267,12269,12271,12273,12275],{"class":66,"line":2628},[64,12248,12249],{"class":158},"  call",[64,12251,1920],{"class":154},[64,12253,11998],{"class":197},[64,12255,270],{"class":3521},[64,12257,2513],{"class":168},[64,12259,11777],{"class":73},[64,12261,8224],{"class":154},[64,12263,12264],{"class":158},"receiver",[64,12266,276],{"class":154},[64,12268,694],{"class":279},[64,12270,1183],{"class":154},[64,12272,2513],{"class":168},[64,12274,296],{"class":3521},[64,12276,178],{"class":154},[64,12278,12279,12281,12283],{"class":66,"line":2654},[64,12280,1183],{"class":154},[64,12282,296],{"class":200},[64,12284,178],{"class":154},[64,12286,12287],{"class":66,"line":2659},[64,12288,185],{"emptyLinePlaceholder":184},[64,12290,12291,12294,12296,12298,12300,12302],{"class":66,"line":2665},[64,12292,12293],{"class":197},"afterAll",[64,12295,270],{"class":200},[64,12297,4355],{"class":241},[64,12299,1934],{"class":154},[64,12301,300],{"class":299},[64,12303,3506],{"class":154},[64,12305,12306,12308,12310,12312,12315,12317],{"class":66,"line":2671},[64,12307,3511],{"class":150},[64,12309,12081],{"class":158},[64,12311,276],{"class":154},[64,12313,12314],{"class":197},"close",[64,12316,201],{"class":3521},[64,12318,178],{"class":154},[64,12320,12321,12323,12325,12327,12329,12331],{"class":66,"line":2676},[64,12322,3511],{"class":150},[64,12324,1221],{"class":158},[64,12326,276],{"class":154},[64,12328,1769],{"class":197},[64,12330,201],{"class":3521},[64,12332,178],{"class":154},[64,12334,12335,12337,12339],{"class":66,"line":2683},[64,12336,1183],{"class":154},[64,12338,296],{"class":200},[64,12340,178],{"class":154},[64,12342,12343],{"class":66,"line":2714},[64,12344,185],{"emptyLinePlaceholder":184},[64,12346,12347,12349,12351,12353,12356,12358,12360,12362,12364],{"class":66,"line":2743},[64,12348,5763],{"class":197},[64,12350,270],{"class":200},[64,12352,175],{"class":168},[64,12354,12355],{"class":73},"une app derrière sa porte",[64,12357,175],{"class":168},[64,12359,399],{"class":154},[64,12361,1934],{"class":154},[64,12363,300],{"class":299},[64,12365,3506],{"class":154},[64,12367,12368,12370,12372,12374,12377,12379,12381,12383,12385,12387],{"class":66,"line":2748},[64,12369,5785],{"class":197},[64,12371,270],{"class":3521},[64,12373,175],{"class":168},[64,12375,12376],{"class":73},"accepte une ligne semée par le fil",[64,12378,175],{"class":168},[64,12380,399],{"class":154},[64,12382,3492],{"class":241},[64,12384,1934],{"class":154},[64,12386,300],{"class":299},[64,12388,3506],{"class":154},[64,12390,12391,12393,12395,12397,12399,12401],{"class":66,"line":2753},[64,12392,4366],{"class":241},[64,12394,4933],{"class":158},[64,12396,1920],{"class":154},[64,12398,251],{"class":150},[64,12400,12094],{"class":197},[64,12402,8596],{"class":3521},[64,12404,12405,12408,12410,12412,12414,12416,12418,12420,12422,12424,12426,12429,12431],{"class":66,"line":2759},[64,12406,12407],{"class":154},"      {",[64,12409,789],{"class":583},[64,12411,501],{"class":154},[64,12413,169],{"class":168},[64,12415,796],{"class":73},[64,12417,175],{"class":168},[64,12419,399],{"class":154},[64,12421,803],{"class":583},[64,12423,501],{"class":154},[64,12425,169],{"class":168},[64,12427,12428],{"class":73},"create",[64,12430,175],{"class":168},[64,12432,4434],{"class":154},[64,12434,12435,12437,12439,12441,12443,12445,12447,12449,12451,12453,12455,12457,12459,12461,12463,12465,12467,12469,12472,12474,12476,12478,12480,12482,12484,12486],{"class":66,"line":2765},[64,12436,12407],{"class":154},[64,12438,4502],{"class":583},[64,12440,501],{"class":154},[64,12442,613],{"class":154},[64,12444,4509],{"class":583},[64,12446,501],{"class":154},[64,12448,613],{"class":154},[64,12450,4516],{"class":583},[64,12452,501],{"class":154},[64,12454,5710],{"class":197},[64,12456,270],{"class":3521},[64,12458,563],{"class":158},[64,12460,399],{"class":154},[64,12462,155],{"class":154},[64,12464,584],{"class":583},[64,12466,501],{"class":154},[64,12468,169],{"class":168},[64,12470,12471],{"class":73},"WIRE-1",[64,12473,175],{"class":168},[64,12475,162],{"class":154},[64,12477,296],{"class":3521},[64,12479,399],{"class":154},[64,12481,4585],{"class":583},[64,12483,501],{"class":154},[64,12485,4590],{"class":154},[64,12487,4434],{"class":154},[64,12489,12490,12493,12495,12497,12499,12501,12503,12505,12507,12509,12511],{"class":66,"line":2771},[64,12491,12492],{"class":3521},"    )",[64,12494,1004],{"class":150},[64,12496,155],{"class":154},[64,12498,584],{"class":583},[64,12500,501],{"class":154},[64,12502,4654],{"class":942},[64,12504,1046],{"class":154},[64,12506,1175],{"class":583},[64,12508,501],{"class":154},[64,12510,4654],{"class":942},[64,12512,4659],{"class":154},[64,12514,12515],{"class":66,"line":2776},[64,12516,185],{"emptyLinePlaceholder":184},[64,12518,12519,12521,12523,12526,12528,12530,12532,12534,12537,12539,12541,12543,12545,12547],{"class":66,"line":2784},[64,12520,5830],{"class":197},[64,12522,270],{"class":3521},[64,12524,12525],{"class":158},"created",[64,12527,276],{"class":154},[64,12529,1439],{"class":279},[64,12531,296],{"class":3521},[64,12533,276],{"class":154},[64,12535,12536],{"class":197},"toBe",[64,12538,270],{"class":3521},[64,12540,175],{"class":168},[64,12542,12471],{"class":73},[64,12544,175],{"class":168},[64,12546,296],{"class":3521},[64,12548,178],{"class":154},[64,12550,12551,12553,12555,12557,12559,12561,12563,12565,12568,12570],{"class":66,"line":2789},[64,12552,5830],{"class":197},[64,12554,270],{"class":3521},[64,12556,12525],{"class":158},[64,12558,276],{"class":154},[64,12560,8636],{"class":279},[64,12562,296],{"class":3521},[64,12564,276],{"class":154},[64,12566,12567],{"class":197},"toBeTruthy",[64,12569,201],{"class":3521},[64,12571,178],{"class":154},[64,12573,12574,12576,12578],{"class":66,"line":2802},[64,12575,4632],{"class":154},[64,12577,296],{"class":3521},[64,12579,178],{"class":154},[64,12581,12582],{"class":66,"line":2808},[64,12583,185],{"emptyLinePlaceholder":184},[64,12585,12586,12588,12590,12592,12595,12597,12599,12601,12603,12605],{"class":66,"line":2813},[64,12587,5785],{"class":197},[64,12589,270],{"class":3521},[64,12591,175],{"class":168},[64,12593,12594],{"class":73},"refuse par le fil ce que le juge refuse en mémoire",[64,12596,175],{"class":168},[64,12598,399],{"class":154},[64,12600,3492],{"class":241},[64,12602,1934],{"class":154},[64,12604,300],{"class":299},[64,12606,3506],{"class":154},[64,12608,12609,12611,12614,12616,12618,12620,12622,12624,12626,12628,12630,12632,12634,12636,12639,12641,12643,12645,12647,12649,12651,12653,12655],{"class":66,"line":2820},[64,12610,4366],{"class":241},[64,12612,12613],{"class":158}," bad",[64,12615,1920],{"class":154},[64,12617,155],{"class":154},[64,12619,8621],{"class":154},[64,12621,558],{"class":197},[64,12623,270],{"class":3521},[64,12625,563],{"class":158},[64,12627,399],{"class":154},[64,12629,155],{"class":154},[64,12631,584],{"class":583},[64,12633,501],{"class":154},[64,12635,169],{"class":168},[64,12637,12638],{"class":73},"WIRE-2",[64,12640,175],{"class":168},[64,12642,162],{"class":154},[64,12644,296],{"class":3521},[64,12646,399],{"class":154},[64,12648,4549],{"class":583},[64,12650,501],{"class":154},[64,12652,8503],{"class":154},[64,12654,1873],{"class":623},[64,12656,4659],{"class":154},[64,12658,12659],{"class":66,"line":2836},[64,12660,185],{"emptyLinePlaceholder":184},[64,12662,12663,12666,12668,12670,12673],{"class":66,"line":2867},[64,12664,12665],{"class":150},"    await",[64,12667,3456],{"class":197},[64,12669,270],{"class":3521},[64,12671,12672],{"class":197},"call",[64,12674,8596],{"class":3521},[64,12676,12677,12679,12681,12683,12685,12687,12689,12691,12693,12695,12697,12699,12701],{"class":66,"line":2898},[64,12678,12407],{"class":154},[64,12680,789],{"class":583},[64,12682,501],{"class":154},[64,12684,169],{"class":168},[64,12686,796],{"class":73},[64,12688,175],{"class":168},[64,12690,399],{"class":154},[64,12692,803],{"class":583},[64,12694,501],{"class":154},[64,12696,169],{"class":168},[64,12698,12428],{"class":73},[64,12700,175],{"class":168},[64,12702,4434],{"class":154},[64,12704,12705,12707,12709,12711,12713,12715,12717,12719,12721,12723,12725,12727,12729,12731,12733],{"class":66,"line":2903},[64,12706,12407],{"class":154},[64,12708,4502],{"class":583},[64,12710,501],{"class":154},[64,12712,613],{"class":154},[64,12714,4509],{"class":583},[64,12716,501],{"class":154},[64,12718,613],{"class":154},[64,12720,4516],{"class":583},[64,12722,501],{"class":154},[64,12724,12613],{"class":158},[64,12726,399],{"class":154},[64,12728,4585],{"class":583},[64,12730,501],{"class":154},[64,12732,4590],{"class":154},[64,12734,4434],{"class":154},[64,12736,12737,12740,12742,12745,12747,12750,12752,12754,12756,12758,12760],{"class":66,"line":2908},[64,12738,12739],{"class":3521},"    ))",[64,12741,276],{"class":154},[64,12743,12744],{"class":279},"rejects",[64,12746,276],{"class":154},[64,12748,12749],{"class":197},"toThrow",[64,12751,270],{"class":3521},[64,12753,1547],{"class":168},[64,12755,5397],{"class":73},[64,12757,1547],{"class":168},[64,12759,296],{"class":3521},[64,12761,178],{"class":154},[64,12763,12764,12766,12768],{"class":66,"line":2924},[64,12765,4632],{"class":154},[64,12767,296],{"class":3521},[64,12769,178],{"class":154},[64,12771,12772,12774,12776],{"class":66,"line":2954},[64,12773,1183],{"class":154},[64,12775,296],{"class":200},[64,12777,178],{"class":154},[54,12779,12782],{"className":8810,"code":12780,"filename":12781,"language":4623,"meta":60,"style":60},"{\n  \"extends\": [\"@fougere\u002Fcore\u002Ftsconfig\", \"..\u002F..\u002Ftsconfig.base.json\"],\n  \"compilerOptions\": {\n    \"noEmit\": true,\n    \"rootDir\": \".\"\n  },\n  \"include\": [\"fronds\", \"tests\", \"*.ts\", \".fougere\u002Fnames.generated.d.ts\"]\n}\n\n","tsconfig.json",[17,12783,12784,12788,12820,12833,12848,12865,12869,12917],{"__ignoreMap":60},[64,12785,12786],{"class":66,"line":67},[64,12787,4794],{"class":154},[64,12789,12790,12792,12795,12797,12799,12801,12803,12806,12808,12810,12812,12815,12817],{"class":66,"line":147},[64,12791,8823],{"class":154},[64,12793,12794],{"class":1431},"extends",[64,12796,1436],{"class":154},[64,12798,501],{"class":154},[64,12800,725],{"class":154},[64,12802,1436],{"class":168},[64,12804,12805],{"class":73},"@fougere\u002Fcore\u002Ftsconfig",[64,12807,1436],{"class":168},[64,12809,399],{"class":154},[64,12811,6964],{"class":168},[64,12813,12814],{"class":73},"..\u002F..\u002Ftsconfig.base.json",[64,12816,1436],{"class":168},[64,12818,12819],{"class":154},"],\n",[64,12821,12822,12824,12827,12829,12831],{"class":66,"line":181},[64,12823,8823],{"class":154},[64,12825,12826],{"class":1431},"compilerOptions",[64,12828,1436],{"class":154},[64,12830,501],{"class":154},[64,12832,3506],{"class":154},[64,12834,12835,12837,12840,12842,12844,12846],{"class":66,"line":188},[64,12836,7001],{"class":154},[64,12838,12839],{"class":497},"noEmit",[64,12841,1436],{"class":154},[64,12843,501],{"class":154},[64,12845,5076],{"class":168},[64,12847,2921],{"class":154},[64,12849,12850,12852,12855,12857,12859,12861,12863],{"class":66,"line":825},[64,12851,7001],{"class":154},[64,12853,12854],{"class":497},"rootDir",[64,12856,1436],{"class":154},[64,12858,501],{"class":154},[64,12860,6964],{"class":168},[64,12862,276],{"class":73},[64,12864,7210],{"class":168},[64,12866,12867],{"class":66,"line":830},[64,12868,7052],{"class":154},[64,12870,12871,12873,12876,12878,12880,12882,12884,12886,12888,12890,12892,12894,12896,12898,12900,12903,12905,12907,12909,12912,12914],{"class":66,"line":1760},[64,12872,8823],{"class":154},[64,12874,12875],{"class":1431},"include",[64,12877,1436],{"class":154},[64,12879,501],{"class":154},[64,12881,725],{"class":154},[64,12883,1436],{"class":168},[64,12885,280],{"class":73},[64,12887,1436],{"class":168},[64,12889,399],{"class":154},[64,12891,6964],{"class":168},[64,12893,12167],{"class":73},[64,12895,1436],{"class":168},[64,12897,399],{"class":154},[64,12899,6964],{"class":168},[64,12901,12902],{"class":73},"*.ts",[64,12904,1436],{"class":168},[64,12906,399],{"class":154},[64,12908,6964],{"class":168},[64,12910,12911],{"class":73},".fougere\u002Fnames.generated.d.ts",[64,12913,1436],{"class":168},[64,12915,12916],{"class":154},"]\n",[64,12918,12919],{"class":66,"line":2418},[64,12920,5410],{"class":154},[54,12922,12925],{"className":134,"code":12923,"filename":12924,"language":136,"meta":60,"style":60},"import { fougereTest } from '@fougere\u002Ftesting\u002Fvitest';\n\nexport default fougereTest();\n\n","vitest.config.ts",[17,12926,12927,12947,12951],{"__ignoreMap":60},[64,12928,12929,12931,12933,12935,12937,12939,12941,12943,12945],{"class":66,"line":67},[64,12930,151],{"class":150},[64,12932,155],{"class":154},[64,12934,159],{"class":158},[64,12936,162],{"class":154},[64,12938,165],{"class":150},[64,12940,169],{"class":168},[64,12942,172],{"class":73},[64,12944,175],{"class":168},[64,12946,178],{"class":154},[64,12948,12949],{"class":66,"line":147},[64,12950,185],{"emptyLinePlaceholder":184},[64,12952,12953,12955,12957,12959,12961],{"class":66,"line":181},[64,12954,191],{"class":150},[64,12956,194],{"class":150},[64,12958,159],{"class":197},[64,12960,201],{"class":200},[64,12962,178],{"class":154},[2018,12964,12965],{},"html pre.shiki code .sd7zb, html code.shiki .sd7zb{--shiki-light:#39ADB5;--shiki-light-font-weight:inherit;--shiki-default:#A3B0A5;--shiki-default-font-weight:bold;--shiki-dark:#89DDFF;--shiki-dark-font-weight:inherit}html pre.shiki code .sLf9K, html code.shiki .sLf9K{--shiki-light:#E2931D;--shiki-light-font-weight:inherit;--shiki-default:#8FCF86;--shiki-default-font-weight:bold;--shiki-dark:#FFCB6B;--shiki-dark-font-weight:inherit}html pre.shiki code .sPEhv, html code.shiki .sPEhv{--shiki-light:#90A4AE;--shiki-default:#DDE5DA;--shiki-dark:#BABED8}html pre.shiki code .siB6D, html code.shiki .siB6D{--shiki-light:#91B859;--shiki-default:#A3B0A5;--shiki-dark:#C3E88D}html pre.shiki code .sYNOY, html code.shiki .sYNOY{--shiki-light:#90A4AE90;--shiki-default:#DDE5DA;--shiki-dark:#BABED890}html pre.shiki code .sHaeK, html code.shiki .sHaeK{--shiki-light:#39ADB5;--shiki-light-font-weight:bold;--shiki-default:#A3B0A5;--shiki-default-font-weight:inherit;--shiki-dark:#89DDFF;--shiki-dark-font-weight:bold}html pre.shiki code .s7rwI, html code.shiki .s7rwI{--shiki-light:#E53935;--shiki-light-font-weight:bold;--shiki-default:#DDE5DA;--shiki-default-font-weight:inherit;--shiki-dark:#F07178;--shiki-dark-font-weight:bold}html pre.shiki code .s15xx, html code.shiki .s15xx{--shiki-light:#39ADB5;--shiki-default:#A3B0A5;--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 .s76I7, html code.shiki .s76I7{--shiki-light:#9C3EDA;--shiki-default:#8FCF86;--shiki-dark:#C792EA}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 .s4mR9, html code.shiki .s4mR9{--shiki-light:#6182B8;--shiki-default:#C9B6EA;--shiki-dark:#82AAFF}html pre.shiki code .srlTG, html code.shiki .srlTG{--shiki-light:#90A4AE;--shiki-default:#A3B0A5;--shiki-dark:#BABED8}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 .sy9f4, html code.shiki .sy9f4{--shiki-light:#90A4AE;--shiki-default:#93CFC0;--shiki-dark:#BABED8}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 .scTuO, html code.shiki .scTuO{--shiki-light:#9C3EDA;--shiki-default:#A3B0A5;--shiki-dark:#C792EA}html pre.shiki code .sDDC1, html code.shiki .sDDC1{--shiki-light:#39ADB5;--shiki-default:#EE9F6B;--shiki-dark:#89DDFF}html pre.shiki code .sHtqg, html code.shiki .sHtqg{--shiki-light:#E53935;--shiki-default:#93CFC0;--shiki-dark:#F07178}html pre.shiki code .s3dPA, html code.shiki .s3dPA{--shiki-light:#F76D47;--shiki-default:#EE9F6B;--shiki-dark:#F78C6C}html pre.shiki code .s687E, html code.shiki .s687E{--shiki-light:#E53935;--shiki-default:#8FCF86;--shiki-dark:#F07178}html pre.shiki code .s8ClO, html code.shiki .s8ClO{--shiki-light:#9C3EDA;--shiki-default:#93CFC0;--shiki-dark:#C792EA}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 .spAFX, html code.shiki .spAFX{--shiki-light:#E53935;--shiki-default:#A3B0A5;--shiki-dark:#F07178}html pre.shiki code .sK7Y8, html code.shiki .sK7Y8{--shiki-light:#E53935;--shiki-default:#EE9F6B;--shiki-dark:#F07178}html pre.shiki code .sBZYL, html code.shiki .sBZYL{--shiki-light:#E2931D;--shiki-default:#EFCD8F;--shiki-dark:#FFCB6B}html pre.shiki code .slmMI, html code.shiki .slmMI{--shiki-light:#FF5370;--shiki-default:#EE9F6B;--shiki-dark:#FF9CAC}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}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 .sWI7z, html code.shiki .sWI7z{--shiki-light:#E2931D;--shiki-default:#93CFC0;--shiki-dark:#FFCB6B}html pre.shiki code .slP7D, html code.shiki .slP7D{--shiki-light:#90A4AE;--shiki-default:#C9B6EA;--shiki-dark:#BABED8}html pre.shiki code .sWPpw, html code.shiki .sWPpw{--shiki-light:#F76D47;--shiki-default:#8FCF86;--shiki-dark:#F78C6C}html pre.shiki code .sgjsB, html code.shiki .sgjsB{--shiki-light:#6182B8;--shiki-default:#EFCD8F;--shiki-dark:#82AAFF}html pre.shiki code .sfnqo, html code.shiki .sfnqo{--shiki-light:#90A4AE;--shiki-default:#EE9F6B;--shiki-dark:#BABED8}",{"title":60,"searchDepth":147,"depth":147,"links":12967},[],{},"\u002Fdemo\u002Ftest-gradient",{"title":1527,"description":60},"demo\u002Ftest-gradient","0J7DZMIrcFWgBBJUxTBPSf3JvwvqxK9h9Q2pDVX0ZNs",1794396613879]