[{"data":1,"prerenderedAt":1649},["ShallowReactive",2],{"docs-nav:en":3,"docs:\u002Fdocs\u002Fcli":186},[4],{"title":5,"path":6,"stem":7,"children":8},"Docs","\u002Fdocs","docs",[9,12,16,20,24,28,50,75,120,145],{"title":10,"path":6,"stem":11},"What is Fougere","docs\u002Findex",{"title":13,"path":14,"stem":15},"Getting started","\u002Fdocs\u002Fgetting-started","docs\u002F01.getting-started",{"title":17,"path":18,"stem":19},"An app you already have","\u002Fdocs\u002Fexisting-app","docs\u002F02.existing-app",{"title":21,"path":22,"stem":23},"Bring your schema","\u002Fdocs\u002Fbring-your-schema","docs\u002F03.bring-your-schema",{"title":25,"path":26,"stem":27},"The CLI","\u002Fdocs\u002Fcli","docs\u002F04.cli",{"title":29,"path":30,"stem":31,"children":32,"page":49},"Concepts","\u002Fdocs\u002Fconcepts","docs\u002F2.concepts",[33,37,41,45],{"title":34,"path":35,"stem":36},"Philosophy","\u002Fdocs\u002Fconcepts\u002Fphilosophy","docs\u002F2.concepts\u002F1.philosophy",{"title":38,"path":39,"stem":40},"The Frond","\u002Fdocs\u002Fconcepts\u002Ffrond","docs\u002F2.concepts\u002F2.frond",{"title":42,"path":43,"stem":44},"The shortest path","\u002Fdocs\u002Fconcepts\u002Fshortest-path","docs\u002F2.concepts\u002F3.shortest-path",{"title":46,"path":47,"stem":48},"The base","\u002Fdocs\u002Fconcepts\u002Fthe-base","docs\u002F2.concepts\u002F4.the-base",false,{"title":51,"path":52,"stem":53,"children":54,"page":49},"Schema","\u002Fdocs\u002Fschema","docs\u002F3.schema",[55,59,63,67,71],{"title":56,"path":57,"stem":58},"Entities","\u002Fdocs\u002Fschema\u002Fentities","docs\u002F3.schema\u002F1.entities",{"title":60,"path":61,"stem":62},"Views","\u002Fdocs\u002Fschema\u002Fviews","docs\u002F3.schema\u002F2.views",{"title":64,"path":65,"stem":66},"The identity card","\u002Fdocs\u002Fschema\u002Fcard","docs\u002F3.schema\u002F3.card",{"title":68,"path":69,"stem":70},"Standard Schema","\u002Fdocs\u002Fschema\u002Fstandard-schema","docs\u002F3.schema\u002F4.standard-schema",{"title":72,"path":73,"stem":74},"How a schema moves","\u002Fdocs\u002Fschema\u002Fevolution","docs\u002F3.schema\u002F5.evolution",{"title":76,"path":77,"stem":78,"children":79,"page":49},"Business","\u002Fdocs\u002Fbusiness","docs\u002F4.business",[80,84,88,92,96,100,104,108,112,116],{"title":81,"path":82,"stem":83},"Handlers","\u002Fdocs\u002Fbusiness\u002Fhandlers","docs\u002F4.business\u002F1.handlers",{"title":85,"path":86,"stem":87},"Ports","\u002Fdocs\u002Fbusiness\u002Fports","docs\u002F4.business\u002F10.ports",{"title":89,"path":90,"stem":91},"Presenters","\u002Fdocs\u002Fbusiness\u002Fpresenters","docs\u002F4.business\u002F2.presenters",{"title":93,"path":94,"stem":95},"Collectors","\u002Fdocs\u002Fbusiness\u002Fcollectors","docs\u002F4.business\u002F3.collectors",{"title":97,"path":98,"stem":99},"Errors","\u002Fdocs\u002Fbusiness\u002Ferrors","docs\u002F4.business\u002F4.errors",{"title":101,"path":102,"stem":103},"Seeds","\u002Fdocs\u002Fbusiness\u002Fseeds","docs\u002F4.business\u002F5.seeds",{"title":105,"path":106,"stem":107},"Facts","\u002Fdocs\u002Fbusiness\u002Ffacts","docs\u002F4.business\u002F6.facts",{"title":109,"path":110,"stem":111},"Storage","\u002Fdocs\u002Fbusiness\u002Fstorage","docs\u002F4.business\u002F7.storage",{"title":113,"path":114,"stem":115},"Writes that stand or fall as one","\u002Fdocs\u002Fbusiness\u002Ftogether","docs\u002F4.business\u002F8.together",{"title":117,"path":118,"stem":119},"Repositories","\u002Fdocs\u002Fbusiness\u002Frepositories","docs\u002F4.business\u002F9.repositories",{"title":121,"path":122,"stem":123,"children":124,"page":49},"Client","\u002Fdocs\u002Fclient","docs\u002F5.client",[125,129,133,137,141],{"title":126,"path":127,"stem":128},"Queries & commands","\u002Fdocs\u002Fclient\u002Fqueries-commands","docs\u002F5.client\u002F1.queries-commands",{"title":130,"path":131,"stem":132},"Forms","\u002Fdocs\u002Fclient\u002Fforms","docs\u002F5.client\u002F2.forms",{"title":134,"path":135,"stem":136},"Session","\u002Fdocs\u002Fclient\u002Fsession","docs\u002F5.client\u002F3.session",{"title":138,"path":139,"stem":140},"invoke","\u002Fdocs\u002Fclient\u002Finvoke","docs\u002F5.client\u002F4.invoke",{"title":142,"path":143,"stem":144},"Back-office","\u002Fdocs\u002Fclient\u002Fadmin","docs\u002F5.client\u002F5.admin",{"title":146,"path":147,"stem":148,"children":149,"page":49},"Infrastructure","\u002Fdocs\u002Finfra","docs\u002F6.infra",[150,154,158,162,166,170,174,178,182],{"title":151,"path":152,"stem":153},"The gradient","\u002Fdocs\u002Finfra\u002Fgradient","docs\u002F6.infra\u002F1.gradient",{"title":155,"path":156,"stem":157},"Surfaces — REST & GraphQL","\u002Fdocs\u002Finfra\u002Fsurfaces","docs\u002F6.infra\u002F2.surfaces",{"title":159,"path":160,"stem":161},"Deployment","\u002Fdocs\u002Finfra\u002Fdeployment","docs\u002F6.infra\u002F3.deployment",{"title":163,"path":164,"stem":165},"Hosts","\u002Fdocs\u002Finfra\u002Fhosts","docs\u002F6.infra\u002F4.hosts",{"title":167,"path":168,"stem":169},"Sources","\u002Fdocs\u002Finfra\u002Fsources","docs\u002F6.infra\u002F5.sources",{"title":171,"path":172,"stem":173},"Lifecycle","\u002Fdocs\u002Finfra\u002Flifecycle","docs\u002F6.infra\u002F6.lifecycle",{"title":175,"path":176,"stem":177},"Identity across Fronds","\u002Fdocs\u002Finfra\u002Fidentity","docs\u002F6.infra\u002F7.identity",{"title":179,"path":180,"stem":181},"Observability","\u002Fdocs\u002Finfra\u002Fobservability","docs\u002F6.infra\u002F8.observability",{"title":183,"path":184,"stem":185},"Testing","\u002Fdocs\u002Finfra\u002Ftesting","docs\u002F6.infra\u002F9.testing",{"id":187,"title":25,"body":188,"description":1644,"extension":1645,"meta":1646,"navigation":523,"path":26,"seo":1647,"stem":27,"__hash__":1648},"docs_en\u002Fdocs\u002F04.cli.md",{"type":189,"value":190,"toc":1622},"minimark",[191,195,203,229,237,275,278,286,378,392,443,454,652,655,662,683,697,710,726,733,780,787,794,814,825,947,957,968,1077,1088,1107,1114,1121,1190,1201,1232,1237,1287,1301,1313,1320,1335,1342,1415,1426,1432,1444,1447,1453,1460,1467,1506,1529,1536,1543,1564,1572,1579,1594,1613,1618],[192,193,25],"h1",{"id":194},"the-cli",[196,197,198,202],"p",{},[199,200,201],"code",{},"@fougere\u002Fcli"," creates a workspace, hosts a Frond in a separate process, and invokes an\noperation from a shell. The CLI itself uses entities and handlers, so its options are\nvalidated from their schemas.",[204,205,206],"blockquote",{},[196,207,208,212,213,216,217,220,221,224,225,228],{},[209,210,211],"strong",{},"Alpha."," On npm under the ",[199,214,215],{},"alpha"," tag — ",[199,218,219],{},"npx fougere@alpha"," runs it without\ninstalling, ",[199,222,223],{},"npm create fougere"," enters it at ",[199,226,227],{},"new",". The commands and flags below are\nwhat ships.",[230,231,233,236],"h2",{"id":232},"fougere-new-compose-a-workspace",[199,234,235],{},"fougere new"," — compose a workspace",[238,239,244],"pre",{"className":240,"code":241,"language":242,"meta":243,"style":243},"language-bash shiki shiki-themes material-theme-lighter github-light github-dark","fougere new shop --frond blog --app nuxt\n","bash","",[199,245,246],{"__ignoreMap":243},[247,248,251,255,259,262,266,269,272],"span",{"class":249,"line":250},"line",1,[247,252,254],{"class":253},"sbgvK","fougere",[247,256,258],{"class":257},"s_sjI"," new",[247,260,261],{"class":257}," shop",[247,263,265],{"class":264},"stzsN"," --frond",[247,267,268],{"class":257}," blog",[247,270,271],{"class":264}," --app",[247,273,274],{"class":257}," nuxt\n",[196,276,277],{},"The command creates Fronds first, followed by the apps that consume them. It produces a\npnpm workspace:",[238,279,284],{"className":280,"code":282,"language":283},[281],"language-text","shop\u002F\n  fougere.config.ts          ← db, auth, topology\n  pnpm-workspace.yaml        ← packages: [fronds\u002F*, apps\u002F*]\n  fronds\u002Fblog\u002F               ← the domain\n    entities\u002FPost.ts\n    handlers\u002FPostHandler.ts\n  apps\u002Fnuxt\u002F                 ← the consumer\n    nuxt.config.ts\n    app\u002Fpages\u002Findex.vue\n","text",[199,285,282],{"__ignoreMap":243},[287,288,289,302],"table",{},[290,291,292],"thead",{},[293,294,295,299],"tr",{},[296,297,298],"th",{},"Flag",[296,300,301],{},"What it does",[303,304,305,320,330,340,354,368],"tbody",{},[293,306,307,313],{},[308,309,310],"td",{},[199,311,312],{},"--frond blog,api:catalog",[308,314,315,316,319],{},"Fronds to add — ",[199,317,318],{},"template:name"," renames; the template name is the default name",[293,321,322,327],{},[308,323,324],{},[199,325,326],{},"--app nuxt:web",[308,328,329],{},"same, for apps",[293,331,332,337],{},[308,333,334],{},[199,335,336],{},"--bare",[308,338,339],{},"the empty shell, nothing composed",[293,341,342,347],{},[308,343,344],{},[199,345,346],{},"--flat",[308,348,349,350,353],{},"one domain: no ",[199,351,352],{},"fronds\u002F",", no workspace — the app root is the Frond",[293,355,356,361],{},[308,357,358],{},[199,359,360],{},"--local",[308,362,363,364,367],{},"link ",[199,365,366],{},"@fougere\u002F*"," to a local Fougere checkout (development)",[293,369,370,375],{},[308,371,372],{},[199,373,374],{},"--force",[308,376,377],{},"overwrite an existing directory",[196,379,380,383,384,387,388,391],{},[209,381,382],{},"Arguments or interactive mode."," With ",[199,385,386],{},"--frond"," and ",[199,389,390],{},"--app",", the command asks no\nquestions and can run in a script or CI job. Without these options, it prompts for\ntemplates in a TTY. Interactive mode is not available without a TTY.",[196,393,394,397,398,401,402,404,405,408,409,412,413,418,419,421,422,426,427,430,431,434,435,438,439,442],{},[209,395,396],{},"Flat structure."," ",[199,399,400],{},"fougere new shop --flat --frond blog","\nwrites one Nuxt app whose root carries the domain — no ",[199,403,352],{}," segment, no\n",[199,406,407],{},"pnpm-workspace.yaml",", one ",[199,410,411],{},"pnpm install"," (",[414,415,417],"a",{"href":416},"\u002Fdocs\u002Fgetting-started#one-domain-no-fronds-at-all","the flat\nshape","). ",[199,420,390],{}," is refused with it:\nthe app ",[423,424,425],"em",{},"is"," the root. A second domain later goes to ",[199,428,429],{},"fronds\u002Fbilling\u002F"," and the root Frond\nstays where it is. The generated project also carries a ",[199,432,433],{},"tsconfig.frond.json"," whose\n",[199,436,437],{},"include"," names the convention directories. ",[199,440,441],{},"pnpm typecheck"," can therefore check the\ndomain without loading Nuxt.",[196,444,445,446,449,450,453],{},"The generated Frond contains an entity, two derived views (",[199,447,448],{},"NewPost"," for input and\n",[199,451,452],{},"PostCard"," for list output), and a business operation in addition to CRUD:",[238,455,459],{"className":456,"code":457,"language":458,"meta":243,"style":243},"language-ts shiki shiki-themes material-theme-lighter github-light github-dark","export class NewPost extends Post.pick('title', 'body') {}\n\nexport default class PostHandler extends Crud(Post) {\n  async create(input: NewPost): Promise\u003CPost> { … }\n\n  \u002F** The draft→published transition — an operation, not a field write. *\u002F\n  async publish(id: string): Promise\u003CPost> { … }\n}\n","ts",[199,460,461,518,525,549,598,603,610,647],{"__ignoreMap":243},[247,462,463,467,471,474,477,481,485,489,492,496,499,501,504,507,510,512,515],{"class":249,"line":250},[247,464,466],{"class":465},"sVHd0","export",[247,468,470],{"class":469},"sbsja"," class",[247,472,473],{"class":253}," NewPost",[247,475,476],{"class":469}," extends",[247,478,480],{"class":479},"su5hD"," Post",[247,482,484],{"class":483},"sP7_E",".",[247,486,488],{"class":487},"sGLFI","pick",[247,490,491],{"class":479},"(",[247,493,495],{"class":494},"sjJ54","'",[247,497,498],{"class":257},"title",[247,500,495],{"class":494},[247,502,503],{"class":483},",",[247,505,506],{"class":494}," '",[247,508,509],{"class":257},"body",[247,511,495],{"class":494},[247,513,514],{"class":479},") ",[247,516,517],{"class":483},"{}\n",[247,519,521],{"class":249,"line":520},2,[247,522,524],{"emptyLinePlaceholder":523},true,"\n",[247,526,528,530,533,535,538,540,543,546],{"class":249,"line":527},3,[247,529,466],{"class":465},[247,531,532],{"class":465}," default",[247,534,470],{"class":469},[247,536,537],{"class":253}," PostHandler",[247,539,476],{"class":469},[247,541,542],{"class":487}," Crud",[247,544,545],{"class":479},"(Post) ",[247,547,548],{"class":483},"{\n",[247,550,552,555,559,561,565,569,571,574,576,579,582,585,588,591,595],{"class":249,"line":551},4,[247,553,554],{"class":469},"  async",[247,556,558],{"class":557},"sVXei"," create",[247,560,491],{"class":483},[247,562,564],{"class":563},"s99_P","input",[247,566,568],{"class":567},"smGrS",":",[247,570,473],{"class":253},[247,572,573],{"class":483},")",[247,575,568],{"class":567},[247,577,578],{"class":253}," Promise",[247,580,581],{"class":483},"\u003C",[247,583,584],{"class":253},"Post",[247,586,587],{"class":483},">",[247,589,590],{"class":483}," {",[247,592,594],{"class":593},"skxfh"," … ",[247,596,597],{"class":483},"}\n",[247,599,601],{"class":249,"line":600},5,[247,602,524],{"emptyLinePlaceholder":523},[247,604,606],{"class":249,"line":605},6,[247,607,609],{"class":608},"sutJx","  \u002F** The draft→published transition — an operation, not a field write. *\u002F\n",[247,611,613,615,618,620,623,625,629,631,633,635,637,639,641,643,645],{"class":249,"line":612},7,[247,614,554],{"class":469},[247,616,617],{"class":557}," publish",[247,619,491],{"class":483},[247,621,622],{"class":563},"id",[247,624,568],{"class":567},[247,626,628],{"class":627},"sZMiF"," string",[247,630,573],{"class":483},[247,632,568],{"class":567},[247,634,578],{"class":253},[247,636,581],{"class":483},[247,638,584],{"class":253},[247,640,587],{"class":483},[247,642,590],{"class":483},[247,644,594],{"class":593},[247,646,597],{"class":483},[247,648,650],{"class":249,"line":649},8,[247,651,597],{"class":483},[196,653,654],{},"The views define the input and output contracts for these operations.",[230,656,658,661],{"id":657},"fougere-serve-one-frond-its-own-process",[199,659,660],{},"fougere serve"," — one Frond, its own process",[238,663,665],{"className":240,"code":664,"language":242,"meta":243,"style":243},"fougere serve blog --port 4100\n",[199,666,667],{"__ignoreMap":243},[247,668,669,671,674,676,679],{"class":249,"line":250},[247,670,254],{"class":253},[247,672,673],{"class":257}," serve",[247,675,268],{"class":257},[247,677,678],{"class":264}," --port",[247,680,682],{"class":681},"srdBf"," 4100\n",[196,684,685,686,689,690,693,694,484],{},"Starts that Frond alone and exposes it over JSON-RPC on ",[199,687,688],{},"POST \u002F_fougere\u002Fcall",". The\nconsuming app sets its address in ",[199,691,692],{},"remotes:"," to route calls to that host. See\n",[414,695,696],{"href":152},"the gradient",[196,698,699,700,703,704,706,707,709],{},"It does ",[209,701,702],{},"not"," follow ",[199,705,692],{}," itself: a host ",[423,708,425],{}," the Frond, it does not route back\nout.",[204,711,712],{},[196,713,714,717,718,721,722,725],{},[199,715,716],{},"serve()"," binds ",[199,719,720],{},"127.0.0.1"," unless ",[199,723,724],{},"hosts"," says otherwise: a receiver reads identity\noff the wire, so the default keeps it on the machine and widening it is a decision\nwritten down.",[230,727,729,732],{"id":728},"fougere-call-invoke-an-operation",[199,730,731],{},"fougere call"," — invoke an operation",[238,734,736],{"className":240,"code":735,"language":242,"meta":243,"style":243},"fougere call post.list\nfougere call post.create --title \"Hello\" --body \"…\"\n",[199,737,738,748],{"__ignoreMap":243},[247,739,740,742,745],{"class":249,"line":250},[247,741,254],{"class":253},[247,743,744],{"class":257}," call",[247,746,747],{"class":257}," post.list\n",[247,749,750,752,754,757,760,763,766,769,772,774,777],{"class":249,"line":520},[247,751,254],{"class":253},[247,753,744],{"class":257},[247,755,756],{"class":257}," post.create",[247,758,759],{"class":264}," --title",[247,761,762],{"class":494}," \"",[247,764,765],{"class":257},"Hello",[247,767,768],{"class":494},"\"",[247,770,771],{"class":264}," --body",[247,773,762],{"class":494},[247,775,776],{"class":257},"…",[247,778,779],{"class":494},"\"\n",[196,781,782,783,786],{},"The command uses the same envelope, validation, and typed errors as other clients. A\n",[199,784,785],{},"VALIDATION_FAILED"," error therefore keeps the format received by a page.",[230,788,790,793],{"id":789},"fougere-sync-consume-a-remote-frond",[199,791,792],{},"fougere sync"," — consume a remote Frond",[238,795,797],{"className":240,"code":796,"language":242,"meta":243,"style":243},"fougere sync blog --from http:\u002F\u002Fblog-service:4100\n",[199,798,799],{"__ignoreMap":243},[247,800,801,803,806,808,811],{"class":249,"line":250},[247,802,254],{"class":253},[247,804,805],{"class":257}," sync",[247,807,268],{"class":257},[247,809,810],{"class":264}," --from",[247,812,813],{"class":257}," http:\u002F\u002Fblog-service:4100\n",[196,815,816,817,820,821,824],{},"Asks the host ",[199,818,819],{},"rpc.discover",", and writes local entity files rebuilt from the\n",[414,822,823],{"href":65},"cards"," it answers with:",[238,826,828],{"className":456,"code":827,"language":458,"meta":243,"style":243},"\u002F\u002F .fougere\u002Fremotes\u002Fblog\u002Fentities\u002FPost.ts — generated\nimport { Card } from '@fougere\u002Fschema';\n\nexport class Post extends Card.fromDescriptor\u003C{\n  id: string;\n  title: string;\n  createdAt: Date;\n}>({ \u002F* the card, verbatim *\u002F }).toSchema() {}\n",[199,829,830,835,861,865,885,897,908,920],{"__ignoreMap":243},[247,831,832],{"class":249,"line":250},[247,833,834],{"class":608},"\u002F\u002F .fougere\u002Fremotes\u002Fblog\u002Fentities\u002FPost.ts — generated\n",[247,836,837,840,842,845,848,851,853,856,858],{"class":249,"line":520},[247,838,839],{"class":465},"import",[247,841,590],{"class":483},[247,843,844],{"class":479}," Card",[247,846,847],{"class":483}," }",[247,849,850],{"class":465}," from",[247,852,506],{"class":494},[247,854,855],{"class":257},"@fougere\u002Fschema",[247,857,495],{"class":494},[247,859,860],{"class":483},";\n",[247,862,863],{"class":249,"line":527},[247,864,524],{"emptyLinePlaceholder":523},[247,866,867,869,871,873,875,877,879,882],{"class":249,"line":551},[247,868,466],{"class":465},[247,870,470],{"class":469},[247,872,480],{"class":253},[247,874,476],{"class":469},[247,876,844],{"class":479},[247,878,484],{"class":483},[247,880,881],{"class":487},"fromDescriptor",[247,883,884],{"class":483},"\u003C{\n",[247,886,887,891,893,895],{"class":249,"line":600},[247,888,890],{"class":889},"sucvu","  id",[247,892,568],{"class":567},[247,894,628],{"class":627},[247,896,860],{"class":483},[247,898,899,902,904,906],{"class":249,"line":605},[247,900,901],{"class":889},"  title",[247,903,568],{"class":567},[247,905,628],{"class":627},[247,907,860],{"class":483},[247,909,910,913,915,918],{"class":249,"line":612},[247,911,912],{"class":889},"  createdAt",[247,914,568],{"class":567},[247,916,917],{"class":253}," Date",[247,919,860],{"class":483},[247,921,922,925,927,930,933,935,937,939,942,945],{"class":249,"line":649},[247,923,924],{"class":483},"}>",[247,926,491],{"class":479},[247,928,929],{"class":483},"{",[247,931,932],{"class":608}," \u002F* the card, verbatim *\u002F",[247,934,847],{"class":483},[247,936,573],{"class":479},[247,938,484],{"class":483},[247,940,941],{"class":487},"toSchema",[247,943,944],{"class":479},"() ",[247,946,517],{"class":483},[196,948,949,950,952,953,956],{},"One class, like the one you would have written by hand: ",[199,951,584],{}," is the value — a judge\nthat validates locally, without an additional request to the host — and the type of a row\nit hands back, so ",[199,954,955],{},"post.titel"," does not compile. Both are read off the same card.",[196,958,959,960,963,964,967],{},"Next to it, ",[199,961,962],{},"handlers\u002FPostHandler.ts"," states what the frond serves, so a consumer can\nwrite ",[199,965,966],{},"Facade\u003CPostHandler>"," without holding the handler's code:",[238,969,971],{"className":456,"code":970,"language":458,"meta":243,"style":243},"export interface PostHandler {\n  list(invocation?: Invocation): Promise\u003CPost[] & { total?: number; hasMore?: boolean }>;\n  findById(invocation?: Invocation): Promise\u003CPost | undefined>;\n}\n",[199,972,973,985,1041,1073],{"__ignoreMap":243},[247,974,975,977,980,982],{"class":249,"line":250},[247,976,466],{"class":465},[247,978,979],{"class":469}," interface",[247,981,537],{"class":253},[247,983,984],{"class":483}," {\n",[247,986,987,990,992,995,998,1001,1003,1005,1007,1009,1011,1014,1017,1019,1022,1024,1027,1030,1033,1035,1038],{"class":249,"line":520},[247,988,989],{"class":557},"  list",[247,991,491],{"class":483},[247,993,994],{"class":563},"invocation",[247,996,997],{"class":567},"?:",[247,999,1000],{"class":253}," Invocation",[247,1002,573],{"class":483},[247,1004,568],{"class":567},[247,1006,578],{"class":253},[247,1008,581],{"class":483},[247,1010,584],{"class":253},[247,1012,1013],{"class":479},"[] ",[247,1015,1016],{"class":567},"&",[247,1018,590],{"class":483},[247,1020,1021],{"class":889}," total",[247,1023,997],{"class":567},[247,1025,1026],{"class":627}," number",[247,1028,1029],{"class":483},";",[247,1031,1032],{"class":889}," hasMore",[247,1034,997],{"class":567},[247,1036,1037],{"class":627}," boolean",[247,1039,1040],{"class":483}," }>;\n",[247,1042,1043,1046,1048,1050,1052,1054,1056,1058,1060,1062,1064,1067,1070],{"class":249,"line":527},[247,1044,1045],{"class":557},"  findById",[247,1047,491],{"class":483},[247,1049,994],{"class":563},[247,1051,997],{"class":567},[247,1053,1000],{"class":253},[247,1055,573],{"class":483},[247,1057,568],{"class":567},[247,1059,578],{"class":253},[247,1061,581],{"class":483},[247,1063,584],{"class":253},[247,1065,1066],{"class":567}," |",[247,1068,1069],{"class":627}," undefined",[247,1071,1072],{"class":483},">;\n",[247,1074,1075],{"class":249,"line":551},[247,1076,597],{"class":483},[196,1078,1079,1080,1083,1084,1087],{},"The command also writes ",[199,1081,1082],{},".fougere\u002Fremotes.json",", which the Nuxt module reads to alias\n",[199,1085,1086],{},"@fronds\u002Fblog",". Pages therefore use the same import path for a local or remote entity.",[196,1089,1090,1091,1094,1095,1098,1099,1102,1103,1106],{},"Re-running it ",[209,1092,1093],{},"removes what the host no longer serves",". The barrel loses the export by\nitself, but the file used to stay — and ",[199,1096,1097],{},"exports"," lists ",[199,1100,1101],{},"'.\u002Fentities\u002F*'"," as a wildcard, so\n",[199,1104,1105],{},"@fronds\u002Fblog\u002Fentities\u002FTicket.js"," kept resolving to a class that validates perfectly and\nthat nothing behind it answers for. Only files carrying the generated header are removed;\nanything you put in that folder yourself is left alone.",[196,1108,1109,1110,1113],{},"The host returns entities associated with a façade, and ",[209,1111,1112],{},"the facts its fronds announce",".\nAn entity that is neither is not in the discovery result — a shape nobody exposed and\nnobody declared to leave stays home.",[196,1115,1116,1117,1120],{},"A fact has no operation, so it gets a class and no ",[199,1118,1119],{},"Handler"," interface beside it:",[238,1122,1124],{"className":456,"code":1123,"language":458,"meta":243,"style":243},"\u002F\u002F .fougere\u002Fremotes\u002Fblog\u002Fentities\u002FPostPublished.ts — generated\nexport class PostPublished extends Card.fromDescriptor\u003C{ id: string; title: string; at: Date }>(…).toSchema() {}\n",[199,1125,1126,1131],{"__ignoreMap":243},[247,1127,1128],{"class":249,"line":250},[247,1129,1130],{"class":608},"\u002F\u002F .fougere\u002Fremotes\u002Fblog\u002Fentities\u002FPostPublished.ts — generated\n",[247,1132,1133,1135,1137,1140,1142,1144,1146,1148,1151,1154,1156,1158,1160,1163,1165,1167,1169,1172,1174,1176,1179,1182,1184,1186,1188],{"class":249,"line":520},[247,1134,466],{"class":465},[247,1136,470],{"class":469},[247,1138,1139],{"class":253}," PostPublished",[247,1141,476],{"class":469},[247,1143,844],{"class":479},[247,1145,484],{"class":483},[247,1147,881],{"class":487},[247,1149,1150],{"class":483},"\u003C{",[247,1152,1153],{"class":889}," id",[247,1155,568],{"class":567},[247,1157,628],{"class":627},[247,1159,1029],{"class":483},[247,1161,1162],{"class":889}," title",[247,1164,568],{"class":567},[247,1166,628],{"class":627},[247,1168,1029],{"class":483},[247,1170,1171],{"class":889}," at",[247,1173,568],{"class":567},[247,1175,917],{"class":253},[247,1177,1178],{"class":483}," }>",[247,1180,1181],{"class":479},"(…)",[247,1183,484],{"class":483},[247,1185,941],{"class":487},[247,1187,944],{"class":479},[247,1189,517],{"class":483},[196,1191,1192,1193,1196,1197,1200],{},"To have an arriving fact judged, re-export that class into one of your own fronds — the\nboot validates against an entity of a ",[209,1194,1195],{},"scanned"," frond, and ",[199,1198,1199],{},".fougere\u002Fremotes\u002F"," is a\npackage, not a frond:",[238,1202,1204],{"className":456,"code":1203,"language":458,"meta":243,"style":243},"\u002F\u002F fronds\u002Fsearch\u002Fentities\u002FPostPublished.ts\nexport { default } from '..\u002F..\u002F..\u002F.fougere\u002Fremotes\u002Fblog\u002Fentities\u002FPostPublished.js';\n",[199,1205,1206,1211],{"__ignoreMap":243},[247,1207,1208],{"class":249,"line":250},[247,1209,1210],{"class":608},"\u002F\u002F fronds\u002Fsearch\u002Fentities\u002FPostPublished.ts\n",[247,1212,1213,1215,1217,1219,1221,1223,1225,1228,1230],{"class":249,"line":520},[247,1214,466],{"class":465},[247,1216,590],{"class":483},[247,1218,532],{"class":465},[247,1220,847],{"class":483},[247,1222,850],{"class":465},[247,1224,506],{"class":494},[247,1226,1227],{"class":257},"..\u002F..\u002F..\u002F.fougere\u002Fremotes\u002Fblog\u002Fentities\u002FPostPublished.js",[247,1229,495],{"class":494},[247,1231,860],{"class":483},[1233,1234,1236],"h3",{"id":1235},"the-rules","The rules",[287,1238,1239,1248],{},[290,1240,1241],{},[293,1242,1243,1245],{},[296,1244,199],{},[296,1246,1247],{},"what it means",[303,1249,1250,1267,1277],{},[293,1251,1252,1264],{},[308,1253,1254,1257,1258,1257,1261],{},[199,1255,1256],{},"directory-unreadable",", ",[199,1259,1260],{},"handler-parse-failed",[199,1262,1263],{},"heritage-unresolved",[308,1265,1266],{},"what the scan could not do — a rule about an absence is only sound if the analysis attests it looked",[293,1268,1269,1274],{},[308,1270,1271],{},[199,1272,1273],{},"operation-unbound",[308,1275,1276],{},"an operation declares parameters and has no binding plan: it is served, and it receives none of them",[293,1278,1279,1284],{},[308,1280,1281],{},[199,1282,1283],{},"cross-frond-import",[308,1285,1286],{},"a relative import that resolves into another frond",[196,1288,1289,1290,1293,1294,1297,1298,1300],{},"The last one is a warning, not a refusal — it resolves today and the app runs. What it\nstates is that a ",[209,1291,1292],{},"colocation constraint is holding the app together and nothing declares\nit",": ",[199,1295,1296],{},"'..\u002F..\u002Fuser\u002Fentities\u002FUser.js'"," says these two folders are neighbours, in a string\nthe scan, the identity card and ",[199,1299,692],{}," all ignore. It keeps working right up to the day\nthat folder is not there, and then it fails as a file path rather than as a model.",[196,1302,1303,1306,1307,1312],{},[199,1304,1305],{},"'@fronds\u002Fuser\u002Fentities\u002FUser.js'"," says the same dependency in terms the model reads, and it\nis the form ",[414,1308,1310],{"href":1309},"#fougere-sync--consume-a-remote-frond",[199,1311,792],{}," writes — so it survives\nthe frond moving out. The name resolves the same way whether the frond is local or synced.",[230,1314,1316,1319],{"id":1315},"fougere-check-what-the-scan-could-not-do",[199,1317,1318],{},"fougere check"," — what the scan could not do",[238,1321,1323],{"className":240,"code":1322,"language":242,"meta":243,"style":243},"fougere check                 # from a project root; --root points elsewhere\n",[199,1324,1325],{"__ignoreMap":243},[247,1326,1327,1329,1332],{"class":249,"line":250},[247,1328,254],{"class":253},[247,1330,1331],{"class":257}," check",[247,1333,1334],{"class":608},"                 # from a project root; --root points elsewhere\n",[196,1336,1337,1338,1341],{},"It ",[209,1339,1340],{},"scans without booting",", so it reports on a project it cannot start. Five rules\ntoday, each a stable name shared with the scan's own diagnostics:",[287,1343,1344,1354],{},[290,1345,1346],{},[293,1347,1348,1351],{},[296,1349,1350],{},"finding",[296,1352,1353],{},"means",[303,1355,1356,1373,1382,1392,1401],{},[293,1357,1358,1366],{},[308,1359,1360,1257,1362,1257,1364],{},[199,1361,1256],{},[199,1363,1260],{},[199,1365,1263],{},[308,1367,1368,1369,1372],{},"what the scan could not do — an unreadable directory, a handler that would not parse, an ",[199,1370,1371],{},"extends"," it could not follow",[293,1374,1375,1379],{},[308,1376,1377],{},[199,1378,1273],{},[308,1380,1381],{},"an operation whose parameters have no binding plan: it is served, and it receives nothing",[293,1383,1384,1389],{},[308,1385,1386],{},[199,1387,1388],{},"input-contract-ambiguous",[308,1390,1391],{},"two parameters could be the input contract, so provenance cannot pick one — refused rather than settled by parameter order",[293,1393,1394,1398],{},[308,1395,1396],{},[199,1397,1283],{},[308,1399,1400],{},"a relative import that resolves into another Frond — a colocation constraint nothing declares, which holds until the day that Frond is not on this disk",[293,1402,1403,1408],{},[308,1404,1405],{},[199,1406,1407],{},"frond-holds-several-domains",[308,1409,1410,1411,1414],{},"past six entities, the same threshold ",[199,1412,1413],{},"fougere graph"," uses",[196,1416,1417,1418,1421,1422,1425],{},"Findings are ",[209,1419,1420],{},"blocking"," or ",[209,1423,1424],{},"warning",", and only a blocking one exits non-zero — which is\nwhat makes it usable in CI. An unresolvable base class with no operation is ordinary, and a\ncheck that cries wolf stops being read.",[230,1427,1429,1431],{"id":1428},"fougere-graph-read-the-model",[199,1430,1413],{}," — read the model",[238,1433,1435],{"className":240,"code":1434,"language":242,"meta":243,"style":243},"fougere graph\n",[199,1436,1437],{"__ignoreMap":243},[247,1438,1439,1441],{"class":249,"line":250},[247,1440,254],{"class":253},[247,1442,1443],{"class":257}," graph\n",[196,1445,1446],{},"Prints entities, their references, and the number of incoming references. Beyond six\nentities, the command also suggests clusters calculated from that graph:",[238,1448,1451],{"className":1449,"code":1450,"language":283},[281],"  Post → Author, Category (2 incoming)\n  Author\n",[199,1452,1450],{"__ignoreMap":243},[196,1454,1455,1456,1459],{},"The ",[414,1457,1458],{"href":43},"shortest path"," page covers current and possible future\nuses of this graph.",[230,1461,1463,1466],{"id":1462},"fougere-devtools-what-the-running-apps-are-dispatching",[199,1464,1465],{},"fougere devtools"," — what the running apps are dispatching",[238,1468,1470],{"className":240,"code":1469,"language":242,"meta":243,"style":243},"fougere devtools                      # every address this project declares\nfougere devtools --url http:\u002F\u002F127.0.0.1:4100\nfougere devtools --json               # one page, then stop\n",[199,1471,1472,1482,1494],{"__ignoreMap":243},[247,1473,1474,1476,1479],{"class":249,"line":250},[247,1475,254],{"class":253},[247,1477,1478],{"class":257}," devtools",[247,1480,1481],{"class":608},"                      # every address this project declares\n",[247,1483,1484,1486,1488,1491],{"class":249,"line":520},[247,1485,254],{"class":253},[247,1487,1478],{"class":257},[247,1489,1490],{"class":264}," --url",[247,1492,1493],{"class":257}," http:\u002F\u002F127.0.0.1:4100\n",[247,1495,1496,1498,1500,1503],{"class":249,"line":527},[247,1497,254],{"class":253},[247,1499,1478],{"class":257},[247,1501,1502],{"class":264}," --json",[247,1504,1505],{"class":608},"               # one page, then stop\n",[196,1507,1508,1509,1514,1515,1518,1519,1522,1523,1525,1526,484],{},"Reads the call log an app keeps when it mounted ",[414,1510,1511],{"href":180},[199,1512,1513],{},"@fougere\u002Fcalls",",\nover ",[199,1516,1517],{},"\u002F_fougere\u002Fcall"," like any other consumer. ",[209,1520,1521],{},"The reader pulls",": no app registers\nanywhere, and an app started alone depends on nothing. The price is knowing the addresses,\nand the project already states them — ",[199,1524,692],{}," says where a call goes, so it also says\nwhere the other half of a call can be watched. Without it, the default is\n",[199,1527,1528],{},"http:\u002F\u002F127.0.0.1:3000",[196,1530,1531,1532,1535],{},"An app that never installed the package answers ",[199,1533,1534],{},"Unknown rpc operation 'calls'. It serves discover.",", and that address is reported as a refusal rather than as silence.",[230,1537,1539,1542],{"id":1538},"fougere-completion-shell-completion",[199,1540,1541],{},"fougere completion"," — shell completion",[238,1544,1546],{"className":240,"code":1545,"language":242,"meta":243,"style":243},"fougere completion zsh >> ~\u002F.zshrc\n",[199,1547,1548],{"__ignoreMap":243},[247,1549,1550,1552,1555,1558,1561],{"class":249,"line":250},[247,1551,254],{"class":253},[247,1553,1554],{"class":257}," completion",[247,1556,1557],{"class":257}," zsh",[247,1559,1560],{"class":567}," >>",[247,1562,1563],{"class":257}," ~\u002F.zshrc\n",[196,1565,1566,387,1569,1571],{},[199,1567,1568],{},"zsh",[199,1570,242],{},"; the shell is auto-detected when the argument is absent. The names it\ncompletes come out of the same entities the commands ride on, so a new command needs no\nsecond list.",[230,1573,1575,1578],{"id":1574},"fougere-build-frond-publish-a-fronds-entities",[199,1576,1577],{},"fougere build-frond"," — publish a Frond's entities",[238,1580,1582],{"className":240,"code":1581,"language":242,"meta":243,"style":243},"fougere build-frond blog\n",[199,1583,1584],{"__ignoreMap":243},[247,1585,1586,1588,1591],{"class":249,"line":250},[247,1587,254],{"class":253},[247,1589,1590],{"class":257}," build-frond",[247,1592,1593],{"class":257}," blog\n",[196,1595,1596,1597,1600,1601,1604,1605,1608,1609,484],{},"Compiles ",[199,1598,1599],{},"fronds\u002Fblog\u002Fentities\u002F**"," to ",[199,1602,1603],{},"dist\u002F"," with type declarations and configures the\nFrond's ",[199,1606,1607],{},"package.json",". A consumer in another repository can then install that package.\nSee ",[414,1610,1612],{"href":1611},"\u002Fdocs\u002Finfra\u002Fgradient#where-the-code-lives","where the code lives",[196,1614,1615,1616,484],{},"Next: ",[414,1617,34],{"href":35},[1619,1620,1621],"style",{},"html pre.shiki code .sbgvK, html code.shiki .sbgvK{--shiki-light:#E2931D;--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .s_sjI, html code.shiki .s_sjI{--shiki-light:#91B859;--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .stzsN, html code.shiki .stzsN{--shiki-light:#91B859;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sVHd0, html code.shiki .sVHd0{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#D73A49;--shiki-default-font-style:inherit;--shiki-dark:#F97583;--shiki-dark-font-style:inherit}html pre.shiki code .sbsja, html code.shiki .sbsja{--shiki-light:#9C3EDA;--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .su5hD, html code.shiki .su5hD{--shiki-light:#90A4AE;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sP7_E, html code.shiki .sP7_E{--shiki-light:#39ADB5;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sGLFI, html code.shiki .sGLFI{--shiki-light:#6182B8;--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sjJ54, html code.shiki .sjJ54{--shiki-light:#39ADB5;--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sVXei, html code.shiki .sVXei{--shiki-light:#E53935;--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .s99_P, html code.shiki .s99_P{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#E36209;--shiki-default-font-style:inherit;--shiki-dark:#FFAB70;--shiki-dark-font-style:inherit}html pre.shiki code .smGrS, html code.shiki .smGrS{--shiki-light:#39ADB5;--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .skxfh, html code.shiki .skxfh{--shiki-light:#E53935;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sutJx, html code.shiki .sutJx{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#6A737D;--shiki-default-font-style:inherit;--shiki-dark:#6A737D;--shiki-dark-font-style:inherit}html pre.shiki code .sZMiF, html code.shiki .sZMiF{--shiki-light:#E2931D;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .srdBf, html code.shiki .srdBf{--shiki-light:#F76D47;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sucvu, html code.shiki .sucvu{--shiki-light:#E53935;--shiki-default:#E36209;--shiki-dark:#FFAB70}",{"title":243,"searchDepth":520,"depth":520,"links":1623},[1624,1626,1628,1630,1634,1636,1638,1640,1642],{"id":232,"depth":520,"text":1625},"fougere new — compose a workspace",{"id":657,"depth":520,"text":1627},"fougere serve — one Frond, its own process",{"id":728,"depth":520,"text":1629},"fougere call — invoke an operation",{"id":789,"depth":520,"text":1631,"children":1632},"fougere sync — consume a remote Frond",[1633],{"id":1235,"depth":527,"text":1236},{"id":1315,"depth":520,"text":1635},"fougere check — what the scan could not do",{"id":1428,"depth":520,"text":1637},"fougere graph — read the model",{"id":1462,"depth":520,"text":1639},"fougere devtools — what the running apps are dispatching",{"id":1538,"depth":520,"text":1641},"fougere completion — shell completion",{"id":1574,"depth":520,"text":1643},"fougere build-frond — publish a Frond's entities","fougere new, serve, call, sync, graph — composing a workspace, hosting one Frond, invoking an operation from a shell.","md",{},{"title":25,"description":1644},"oZdKoxFlmBOY4YjlV6lO0poWmiuweKUi65CP9EG2cZg",1788560230169]