[{"data":1,"prerenderedAt":2221},["ShallowReactive",2],{"docs-nav:en":3,"docs:\u002Fdocs\u002Fbusiness\u002Fhandlers":134},[4],{"title":5,"path":6,"stem":7,"children":8},"Docs","\u002Fdocs","docs",[9,12,16,20,24,42,63,92,113],{"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},"Existing Nuxt app","\u002Fdocs\u002Fexisting-app","docs\u002F02.existing-app",{"title":21,"path":22,"stem":23},"The CLI","\u002Fdocs\u002Fcli","docs\u002F03.cli",{"title":25,"path":26,"stem":27,"children":28,"page":41},"Concepts","\u002Fdocs\u002Fconcepts","docs\u002F2.concepts",[29,33,37],{"title":30,"path":31,"stem":32},"Philosophy","\u002Fdocs\u002Fconcepts\u002Fphilosophy","docs\u002F2.concepts\u002F1.philosophy",{"title":34,"path":35,"stem":36},"The Frond","\u002Fdocs\u002Fconcepts\u002Ffrond","docs\u002F2.concepts\u002F2.frond",{"title":38,"path":39,"stem":40},"The shortest path","\u002Fdocs\u002Fconcepts\u002Fshortest-path","docs\u002F2.concepts\u002F3.shortest-path",false,{"title":43,"path":44,"stem":45,"children":46,"page":41},"Schema","\u002Fdocs\u002Fschema","docs\u002F3.schema",[47,51,55,59],{"title":48,"path":49,"stem":50},"Entities","\u002Fdocs\u002Fschema\u002Fentities","docs\u002F3.schema\u002F1.entities",{"title":52,"path":53,"stem":54},"Views","\u002Fdocs\u002Fschema\u002Fviews","docs\u002F3.schema\u002F2.views",{"title":56,"path":57,"stem":58},"The identity card","\u002Fdocs\u002Fschema\u002Fcard","docs\u002F3.schema\u002F3.card",{"title":60,"path":61,"stem":62},"Standard Schema","\u002Fdocs\u002Fschema\u002Fstandard-schema","docs\u002F3.schema\u002F4.standard-schema",{"title":64,"path":65,"stem":66,"children":67,"page":41},"Business","\u002Fdocs\u002Fbusiness","docs\u002F4.business",[68,72,76,80,84,88],{"title":69,"path":70,"stem":71},"Handlers","\u002Fdocs\u002Fbusiness\u002Fhandlers","docs\u002F4.business\u002F1.handlers",{"title":73,"path":74,"stem":75},"Presenters","\u002Fdocs\u002Fbusiness\u002Fpresenters","docs\u002F4.business\u002F2.presenters",{"title":77,"path":78,"stem":79},"Collectors","\u002Fdocs\u002Fbusiness\u002Fcollectors","docs\u002F4.business\u002F3.collectors",{"title":81,"path":82,"stem":83},"Errors","\u002Fdocs\u002Fbusiness\u002Ferrors","docs\u002F4.business\u002F4.errors",{"title":85,"path":86,"stem":87},"Seeds","\u002Fdocs\u002Fbusiness\u002Fseeds","docs\u002F4.business\u002F5.seeds",{"title":89,"path":90,"stem":91},"Facts","\u002Fdocs\u002Fbusiness\u002Ffacts","docs\u002F4.business\u002F6.facts",{"title":93,"path":94,"stem":95,"children":96,"page":41},"Client","\u002Fdocs\u002Fclient","docs\u002F5.client",[97,101,105,109],{"title":98,"path":99,"stem":100},"Queries & commands","\u002Fdocs\u002Fclient\u002Fqueries-commands","docs\u002F5.client\u002F1.queries-commands",{"title":102,"path":103,"stem":104},"Forms","\u002Fdocs\u002Fclient\u002Fforms","docs\u002F5.client\u002F2.forms",{"title":106,"path":107,"stem":108},"Session","\u002Fdocs\u002Fclient\u002Fsession","docs\u002F5.client\u002F3.session",{"title":110,"path":111,"stem":112},"invoke","\u002Fdocs\u002Fclient\u002Finvoke","docs\u002F5.client\u002F4.invoke",{"title":114,"path":115,"stem":116,"children":117,"page":41},"Infrastructure","\u002Fdocs\u002Finfra","docs\u002F6.infra",[118,122,126,130],{"title":119,"path":120,"stem":121},"The gradient","\u002Fdocs\u002Finfra\u002Fgradient","docs\u002F6.infra\u002F1.gradient",{"title":123,"path":124,"stem":125},"Surfaces — REST & GraphQL","\u002Fdocs\u002Finfra\u002Fsurfaces","docs\u002F6.infra\u002F2.surfaces",{"title":127,"path":128,"stem":129},"Deployment","\u002Fdocs\u002Finfra\u002Fdeployment","docs\u002F6.infra\u002F3.deployment",{"title":131,"path":132,"stem":133},"Hosts","\u002Fdocs\u002Finfra\u002Fhosts","docs\u002F6.infra\u002F4.hosts",{"id":135,"title":69,"body":136,"description":2216,"extension":2217,"meta":2218,"navigation":253,"path":70,"seo":2219,"stem":71,"__hash__":2220},"docs_en\u002Fdocs\u002F4.business\u002F1.handlers.md",{"type":137,"value":138,"toc":2204},"minimark",[139,143,152,943,946,984,1129,1132,1137,1146,1240,1321,1336,1343,1347,1350,1448,1451,1492,1496,1507,1512,1532,1536,1542,1605,1779,1840,1851,1855,1860,1905,1908,1919,1923,1934,2105,2108,2160,2170,2174,2188,2194,2200],[140,141,69],"h1",{"id":142},"handlers",[144,145,146,147,151],"p",{},"A handler groups the operations of one entity. ",[148,149,150],"code",{},"Crud(Entity)"," provides the five CRUD\noperations. Each additional public method becomes an operation.",[153,154,159],"pre",{"className":155,"code":156,"language":157,"meta":158,"style":158},"language-ts shiki shiki-themes material-theme-lighter github-light github-dark","import { Crud, FougereError, ErrorCode } from '@fougere\u002Fcore';\nimport Post from '..\u002Fentities\u002FPost.js';\nimport User from '..\u002F..\u002Fuser\u002Fentities\u002FUser.js';\n\nexport default class PostHandler extends Crud(Post) {\n  \u002F** Public reading: published only. *\u002F\n  async list(): Promise\u003CPostCard[]> {\n    const all = await this.orm.list();\n    return all.filter((p) => p.status === 'published') \u002F* … *\u002F;\n  }\n\n  \u002F** The draft→published transition — an operation, not a field write. *\u002F\n  async publish(id: string, user: User | null): Promise\u003CPost> {\n    if (!user) throw new FougereError({ code: ErrorCode.UNAUTHORIZED, message: 'Sign in to publish', entity: 'post', operation: 'publish' });\n    const post = await this.orm.findById(id);\n    if (!post) throw new FougereError({ code: ErrorCode.NOT_FOUND, message: `Post '${id}' not found`, entity: 'post', operation: 'publish' });\n    if (post.authorId !== user.id) throw new FougereError({ code: ErrorCode.FORBIDDEN, message: 'Only the author can publish', entity: 'post', operation: 'publish' });\n    if (post.status === 'published') throw new FougereError({ code: ErrorCode.CONFLICT, message: 'Already published', entity: 'post', operation: 'publish' });\n    return this.orm.update(id, { status: 'published', publishedAt: new Date().toISOString() });\n  }\n}\n","ts","",[148,160,161,209,229,248,255,284,291,326,362,415,421,426,432,482,572,603,693,782,869,932,937],{"__ignoreMap":158},[162,163,166,170,174,178,181,184,186,189,192,195,199,203,206],"span",{"class":164,"line":165},"line",1,[162,167,169],{"class":168},"sVHd0","import",[162,171,173],{"class":172},"sP7_E"," {",[162,175,177],{"class":176},"su5hD"," Crud",[162,179,180],{"class":172},",",[162,182,183],{"class":176}," FougereError",[162,185,180],{"class":172},[162,187,188],{"class":176}," ErrorCode",[162,190,191],{"class":172}," }",[162,193,194],{"class":168}," from",[162,196,198],{"class":197},"sjJ54"," '",[162,200,202],{"class":201},"s_sjI","@fougere\u002Fcore",[162,204,205],{"class":197},"'",[162,207,208],{"class":172},";\n",[162,210,212,214,217,220,222,225,227],{"class":164,"line":211},2,[162,213,169],{"class":168},[162,215,216],{"class":176}," Post ",[162,218,219],{"class":168},"from",[162,221,198],{"class":197},[162,223,224],{"class":201},"..\u002Fentities\u002FPost.js",[162,226,205],{"class":197},[162,228,208],{"class":172},[162,230,232,234,237,239,241,244,246],{"class":164,"line":231},3,[162,233,169],{"class":168},[162,235,236],{"class":176}," User ",[162,238,219],{"class":168},[162,240,198],{"class":197},[162,242,243],{"class":201},"..\u002F..\u002Fuser\u002Fentities\u002FUser.js",[162,245,205],{"class":197},[162,247,208],{"class":172},[162,249,251],{"class":164,"line":250},4,[162,252,254],{"emptyLinePlaceholder":253},true,"\n",[162,256,258,261,264,268,272,275,278,281],{"class":164,"line":257},5,[162,259,260],{"class":168},"export",[162,262,263],{"class":168}," default",[162,265,267],{"class":266},"sbsja"," class",[162,269,271],{"class":270},"sbgvK"," PostHandler",[162,273,274],{"class":266}," extends",[162,276,177],{"class":277},"sGLFI",[162,279,280],{"class":176},"(Post) ",[162,282,283],{"class":172},"{\n",[162,285,287],{"class":164,"line":286},6,[162,288,290],{"class":289},"sutJx","  \u002F** Public reading: published only. *\u002F\n",[162,292,294,297,301,304,308,311,314,317,320,323],{"class":164,"line":293},7,[162,295,296],{"class":266},"  async",[162,298,300],{"class":299},"sVXei"," list",[162,302,303],{"class":172},"()",[162,305,307],{"class":306},"smGrS",":",[162,309,310],{"class":270}," Promise",[162,312,313],{"class":172},"\u003C",[162,315,316],{"class":270},"PostCard",[162,318,319],{"class":176},"[]",[162,321,322],{"class":172},">",[162,324,325],{"class":172}," {\n",[162,327,329,332,336,339,342,346,349,352,354,357,360],{"class":164,"line":328},8,[162,330,331],{"class":266},"    const",[162,333,335],{"class":334},"s_hVV"," all",[162,337,338],{"class":306}," =",[162,340,341],{"class":168}," await",[162,343,345],{"class":344},"s39Yj"," this",[162,347,348],{"class":172},".",[162,350,351],{"class":176},"orm",[162,353,348],{"class":172},[162,355,356],{"class":277},"list",[162,358,303],{"class":359},"skxfh",[162,361,208],{"class":172},[162,363,365,368,370,372,375,378,380,383,386,389,392,394,397,400,402,405,407,410,413],{"class":164,"line":364},9,[162,366,367],{"class":168},"    return",[162,369,335],{"class":176},[162,371,348],{"class":172},[162,373,374],{"class":277},"filter",[162,376,377],{"class":359},"(",[162,379,377],{"class":172},[162,381,144],{"class":382},"s99_P",[162,384,385],{"class":172},")",[162,387,388],{"class":266}," =>",[162,390,391],{"class":176}," p",[162,393,348],{"class":172},[162,395,396],{"class":176},"status",[162,398,399],{"class":306}," ===",[162,401,198],{"class":197},[162,403,404],{"class":201},"published",[162,406,205],{"class":197},[162,408,409],{"class":359},") ",[162,411,412],{"class":289},"\u002F* … *\u002F",[162,414,208],{"class":172},[162,416,418],{"class":164,"line":417},10,[162,419,420],{"class":172},"  }\n",[162,422,424],{"class":164,"line":423},11,[162,425,254],{"emptyLinePlaceholder":253},[162,427,429],{"class":164,"line":428},12,[162,430,431],{"class":289},"  \u002F** The draft→published transition — an operation, not a field write. *\u002F\n",[162,433,435,437,440,442,445,447,451,453,456,458,461,464,467,469,471,473,475,478,480],{"class":164,"line":434},13,[162,436,296],{"class":266},[162,438,439],{"class":299}," publish",[162,441,377],{"class":172},[162,443,444],{"class":382},"id",[162,446,307],{"class":306},[162,448,450],{"class":449},"sZMiF"," string",[162,452,180],{"class":172},[162,454,455],{"class":382}," user",[162,457,307],{"class":306},[162,459,460],{"class":270}," User",[162,462,463],{"class":306}," |",[162,465,466],{"class":449}," null",[162,468,385],{"class":172},[162,470,307],{"class":306},[162,472,310],{"class":270},[162,474,313],{"class":172},[162,476,477],{"class":270},"Post",[162,479,322],{"class":172},[162,481,325],{"class":172},[162,483,485,488,491,494,497,499,502,505,507,509,512,515,517,519,521,524,526,529,531,533,536,538,540,543,545,547,550,552,554,557,559,561,564,566,568,570],{"class":164,"line":484},14,[162,486,487],{"class":168},"    if",[162,489,490],{"class":359}," (",[162,492,493],{"class":306},"!",[162,495,496],{"class":176},"user",[162,498,409],{"class":359},[162,500,501],{"class":168},"throw",[162,503,504],{"class":306}," new",[162,506,183],{"class":277},[162,508,377],{"class":359},[162,510,511],{"class":172},"{",[162,513,514],{"class":359}," code",[162,516,307],{"class":172},[162,518,188],{"class":176},[162,520,348],{"class":172},[162,522,523],{"class":334},"UNAUTHORIZED",[162,525,180],{"class":172},[162,527,528],{"class":359}," message",[162,530,307],{"class":172},[162,532,198],{"class":197},[162,534,535],{"class":201},"Sign in to publish",[162,537,205],{"class":197},[162,539,180],{"class":172},[162,541,542],{"class":359}," entity",[162,544,307],{"class":172},[162,546,198],{"class":197},[162,548,549],{"class":201},"post",[162,551,205],{"class":197},[162,553,180],{"class":172},[162,555,556],{"class":359}," operation",[162,558,307],{"class":172},[162,560,198],{"class":197},[162,562,563],{"class":201},"publish",[162,565,205],{"class":197},[162,567,191],{"class":172},[162,569,385],{"class":359},[162,571,208],{"class":172},[162,573,575,577,580,582,584,586,588,590,592,595,597,599,601],{"class":164,"line":574},15,[162,576,331],{"class":266},[162,578,579],{"class":334}," post",[162,581,338],{"class":306},[162,583,341],{"class":168},[162,585,345],{"class":344},[162,587,348],{"class":172},[162,589,351],{"class":176},[162,591,348],{"class":172},[162,593,594],{"class":277},"findById",[162,596,377],{"class":359},[162,598,444],{"class":176},[162,600,385],{"class":359},[162,602,208],{"class":172},[162,604,606,608,610,612,614,616,618,620,622,624,626,628,630,632,634,637,639,641,643,646,649,652,654,657,660,663,665,667,669,671,673,675,677,679,681,683,685,687,689,691],{"class":164,"line":605},16,[162,607,487],{"class":168},[162,609,490],{"class":359},[162,611,493],{"class":306},[162,613,549],{"class":176},[162,615,409],{"class":359},[162,617,501],{"class":168},[162,619,504],{"class":306},[162,621,183],{"class":277},[162,623,377],{"class":359},[162,625,511],{"class":172},[162,627,514],{"class":359},[162,629,307],{"class":172},[162,631,188],{"class":176},[162,633,348],{"class":172},[162,635,636],{"class":334},"NOT_FOUND",[162,638,180],{"class":172},[162,640,528],{"class":359},[162,642,307],{"class":172},[162,644,645],{"class":197}," `",[162,647,648],{"class":201},"Post '",[162,650,651],{"class":197},"${",[162,653,444],{"class":176},[162,655,656],{"class":197},"}",[162,658,659],{"class":201},"' not found",[162,661,662],{"class":197},"`",[162,664,180],{"class":172},[162,666,542],{"class":359},[162,668,307],{"class":172},[162,670,198],{"class":197},[162,672,549],{"class":201},[162,674,205],{"class":197},[162,676,180],{"class":172},[162,678,556],{"class":359},[162,680,307],{"class":172},[162,682,198],{"class":197},[162,684,563],{"class":201},[162,686,205],{"class":197},[162,688,191],{"class":172},[162,690,385],{"class":359},[162,692,208],{"class":172},[162,694,696,698,700,702,704,707,710,712,714,716,718,720,722,724,726,728,730,732,734,736,739,741,743,745,747,750,752,754,756,758,760,762,764,766,768,770,772,774,776,778,780],{"class":164,"line":695},17,[162,697,487],{"class":168},[162,699,490],{"class":359},[162,701,549],{"class":176},[162,703,348],{"class":172},[162,705,706],{"class":176},"authorId",[162,708,709],{"class":306}," !==",[162,711,455],{"class":176},[162,713,348],{"class":172},[162,715,444],{"class":176},[162,717,409],{"class":359},[162,719,501],{"class":168},[162,721,504],{"class":306},[162,723,183],{"class":277},[162,725,377],{"class":359},[162,727,511],{"class":172},[162,729,514],{"class":359},[162,731,307],{"class":172},[162,733,188],{"class":176},[162,735,348],{"class":172},[162,737,738],{"class":334},"FORBIDDEN",[162,740,180],{"class":172},[162,742,528],{"class":359},[162,744,307],{"class":172},[162,746,198],{"class":197},[162,748,749],{"class":201},"Only the author can publish",[162,751,205],{"class":197},[162,753,180],{"class":172},[162,755,542],{"class":359},[162,757,307],{"class":172},[162,759,198],{"class":197},[162,761,549],{"class":201},[162,763,205],{"class":197},[162,765,180],{"class":172},[162,767,556],{"class":359},[162,769,307],{"class":172},[162,771,198],{"class":197},[162,773,563],{"class":201},[162,775,205],{"class":197},[162,777,191],{"class":172},[162,779,385],{"class":359},[162,781,208],{"class":172},[162,783,785,787,789,791,793,795,797,799,801,803,805,807,809,811,813,815,817,819,821,823,826,828,830,832,834,837,839,841,843,845,847,849,851,853,855,857,859,861,863,865,867],{"class":164,"line":784},18,[162,786,487],{"class":168},[162,788,490],{"class":359},[162,790,549],{"class":176},[162,792,348],{"class":172},[162,794,396],{"class":176},[162,796,399],{"class":306},[162,798,198],{"class":197},[162,800,404],{"class":201},[162,802,205],{"class":197},[162,804,409],{"class":359},[162,806,501],{"class":168},[162,808,504],{"class":306},[162,810,183],{"class":277},[162,812,377],{"class":359},[162,814,511],{"class":172},[162,816,514],{"class":359},[162,818,307],{"class":172},[162,820,188],{"class":176},[162,822,348],{"class":172},[162,824,825],{"class":334},"CONFLICT",[162,827,180],{"class":172},[162,829,528],{"class":359},[162,831,307],{"class":172},[162,833,198],{"class":197},[162,835,836],{"class":201},"Already published",[162,838,205],{"class":197},[162,840,180],{"class":172},[162,842,542],{"class":359},[162,844,307],{"class":172},[162,846,198],{"class":197},[162,848,549],{"class":201},[162,850,205],{"class":197},[162,852,180],{"class":172},[162,854,556],{"class":359},[162,856,307],{"class":172},[162,858,198],{"class":197},[162,860,563],{"class":201},[162,862,205],{"class":197},[162,864,191],{"class":172},[162,866,385],{"class":359},[162,868,208],{"class":172},[162,870,872,874,876,878,880,882,885,887,889,891,893,896,898,900,902,904,906,909,911,913,916,918,920,923,926,928,930],{"class":164,"line":871},19,[162,873,367],{"class":168},[162,875,345],{"class":344},[162,877,348],{"class":172},[162,879,351],{"class":176},[162,881,348],{"class":172},[162,883,884],{"class":277},"update",[162,886,377],{"class":359},[162,888,444],{"class":176},[162,890,180],{"class":172},[162,892,173],{"class":172},[162,894,895],{"class":359}," status",[162,897,307],{"class":172},[162,899,198],{"class":197},[162,901,404],{"class":201},[162,903,205],{"class":197},[162,905,180],{"class":172},[162,907,908],{"class":359}," publishedAt",[162,910,307],{"class":172},[162,912,504],{"class":306},[162,914,915],{"class":277}," Date",[162,917,303],{"class":359},[162,919,348],{"class":172},[162,921,922],{"class":277},"toISOString",[162,924,925],{"class":359},"() ",[162,927,656],{"class":172},[162,929,385],{"class":359},[162,931,208],{"class":172},[162,933,935],{"class":164,"line":934},20,[162,936,420],{"class":172},[162,938,940],{"class":164,"line":939},21,[162,941,942],{"class":172},"}\n",[144,944,945],{},"Fougere does not require a service layer. A handler can contain an operation's logic\ndirectly or delegate to a service when the domain needs it.",[144,947,948,951,952,955,956,959,960,959,963,959,966,969,970,959,973,959,976,979,980,983],{},[148,949,950],{},"this.orm"," is data access scoped to the entity (",[148,953,954],{},"EntityOrm","). Reads:\n",[148,957,958],{},"list(options?)",", ",[148,961,962],{},"findById(id)",[148,964,965],{},"findBy(criteria)",[148,967,968],{},"findAllBy(criteria)",". Writes:\n",[148,971,972],{},"create(input)",[148,974,975],{},"update(id, input)",[148,977,978],{},"delete(id)",". ",[148,981,982],{},"output(view)"," returns an ORM scoped\nto a view's fields.",[153,985,987],{"className":155,"code":986,"language":157,"meta":158,"style":158},"await this.orm.findBy({ slug });                    \u002F\u002F the one row matching\nawait this.orm.findAllBy({ authorId: user.id });    \u002F\u002F every row matching\nawait this.orm.list({ where: { status: 'published' }, limit: 20, orderBy: 'createdAt' });\n",[148,988,989,1022,1062],{"__ignoreMap":158},[162,990,991,994,996,998,1000,1002,1005,1007,1009,1012,1014,1016,1019],{"class":164,"line":165},[162,992,993],{"class":168},"await",[162,995,345],{"class":344},[162,997,348],{"class":172},[162,999,351],{"class":176},[162,1001,348],{"class":172},[162,1003,1004],{"class":277},"findBy",[162,1006,377],{"class":176},[162,1008,511],{"class":172},[162,1010,1011],{"class":176}," slug ",[162,1013,656],{"class":172},[162,1015,385],{"class":176},[162,1017,1018],{"class":172},";",[162,1020,1021],{"class":289},"                    \u002F\u002F the one row matching\n",[162,1023,1024,1026,1028,1030,1032,1034,1037,1039,1041,1044,1046,1048,1050,1053,1055,1057,1059],{"class":164,"line":211},[162,1025,993],{"class":168},[162,1027,345],{"class":344},[162,1029,348],{"class":172},[162,1031,351],{"class":176},[162,1033,348],{"class":172},[162,1035,1036],{"class":277},"findAllBy",[162,1038,377],{"class":176},[162,1040,511],{"class":172},[162,1042,1043],{"class":359}," authorId",[162,1045,307],{"class":172},[162,1047,455],{"class":176},[162,1049,348],{"class":172},[162,1051,1052],{"class":176},"id ",[162,1054,656],{"class":172},[162,1056,385],{"class":176},[162,1058,1018],{"class":172},[162,1060,1061],{"class":289},"    \u002F\u002F every row matching\n",[162,1063,1064,1066,1068,1070,1072,1074,1076,1078,1080,1083,1085,1087,1089,1091,1093,1095,1097,1100,1103,1105,1109,1111,1114,1116,1118,1121,1123,1125,1127],{"class":164,"line":231},[162,1065,993],{"class":168},[162,1067,345],{"class":344},[162,1069,348],{"class":172},[162,1071,351],{"class":176},[162,1073,348],{"class":172},[162,1075,356],{"class":277},[162,1077,377],{"class":176},[162,1079,511],{"class":172},[162,1081,1082],{"class":359}," where",[162,1084,307],{"class":172},[162,1086,173],{"class":172},[162,1088,895],{"class":359},[162,1090,307],{"class":172},[162,1092,198],{"class":197},[162,1094,404],{"class":201},[162,1096,205],{"class":197},[162,1098,1099],{"class":172}," },",[162,1101,1102],{"class":359}," limit",[162,1104,307],{"class":172},[162,1106,1108],{"class":1107},"srdBf"," 20",[162,1110,180],{"class":172},[162,1112,1113],{"class":359}," orderBy",[162,1115,307],{"class":172},[162,1117,198],{"class":197},[162,1119,1120],{"class":201},"createdAt",[162,1122,205],{"class":197},[162,1124,191],{"class":172},[162,1126,385],{"class":176},[162,1128,208],{"class":172},[144,1130,1131],{},"The façade validates input before calling the method. The ORM then applies lifecycle rules\nsuch as automatic values and defaults. The handler's return value is projected and\nvalidated before leaving the façade.",[1133,1134,1136],"h2",{"id":1135},"where-a-named-query-lives","Where a named query lives",[144,1138,1139,1141,1142,1145],{},[148,1140,954],{}," is a port: five generic gestures, no flavour of domain. \"The loud readings\" is\nnot one of them, so that query ends up spelled at the call site, in the middle of the\ncalculation it feeds. ",[148,1143,1144],{},"Repository(Entity)"," gives it a home:",[153,1147,1149],{"className":155,"code":1148,"language":157,"meta":158,"style":158},"\u002F\u002F repositories\u002FReadingRepository.ts\nexport default class ReadingRepository extends Repository(Reading) {\n  loud(): Promise\u003CReading[]> {\n    return this.orm.findAllBy({ loud: true });\n  }\n}\n",[148,1150,1151,1156,1177,1199,1232,1236],{"__ignoreMap":158},[162,1152,1153],{"class":164,"line":165},[162,1154,1155],{"class":289},"\u002F\u002F repositories\u002FReadingRepository.ts\n",[162,1157,1158,1160,1162,1164,1167,1169,1172,1175],{"class":164,"line":211},[162,1159,260],{"class":168},[162,1161,263],{"class":168},[162,1163,267],{"class":266},[162,1165,1166],{"class":270}," ReadingRepository",[162,1168,274],{"class":266},[162,1170,1171],{"class":277}," Repository",[162,1173,1174],{"class":176},"(Reading) ",[162,1176,283],{"class":172},[162,1178,1179,1182,1184,1186,1188,1190,1193,1195,1197],{"class":164,"line":231},[162,1180,1181],{"class":299},"  loud",[162,1183,303],{"class":172},[162,1185,307],{"class":306},[162,1187,310],{"class":270},[162,1189,313],{"class":172},[162,1191,1192],{"class":270},"Reading",[162,1194,319],{"class":176},[162,1196,322],{"class":172},[162,1198,325],{"class":172},[162,1200,1201,1203,1205,1207,1209,1211,1213,1215,1217,1220,1222,1226,1228,1230],{"class":164,"line":250},[162,1202,367],{"class":168},[162,1204,345],{"class":344},[162,1206,348],{"class":172},[162,1208,351],{"class":176},[162,1210,348],{"class":172},[162,1212,1036],{"class":277},[162,1214,377],{"class":359},[162,1216,511],{"class":172},[162,1218,1219],{"class":359}," loud",[162,1221,307],{"class":172},[162,1223,1225],{"class":1224},"syTEX"," true",[162,1227,191],{"class":172},[162,1229,385],{"class":359},[162,1231,208],{"class":172},[162,1233,1234],{"class":164,"line":257},[162,1235,420],{"class":172},[162,1237,1238],{"class":164,"line":286},[162,1239,942],{"class":172},[153,1241,1243],{"className":155,"code":1242,"language":157,"meta":158,"style":158},"\u002F\u002F handlers\u002FReadingHandler.ts — asks the question, never spells the storage\nexport default class ReadingHandler {\n  constructor(private readingRepository: ReadingRepository) {}\n  async loud() { return this.readingRepository.loud(); }\n}\n",[148,1244,1245,1250,1263,1285,1317],{"__ignoreMap":158},[162,1246,1247],{"class":164,"line":165},[162,1248,1249],{"class":289},"\u002F\u002F handlers\u002FReadingHandler.ts — asks the question, never spells the storage\n",[162,1251,1252,1254,1256,1258,1261],{"class":164,"line":211},[162,1253,260],{"class":168},[162,1255,263],{"class":168},[162,1257,267],{"class":266},[162,1259,1260],{"class":270}," ReadingHandler",[162,1262,325],{"class":172},[162,1264,1265,1268,1270,1273,1276,1278,1280,1282],{"class":164,"line":231},[162,1266,1267],{"class":266},"  constructor",[162,1269,377],{"class":172},[162,1271,1272],{"class":266},"private",[162,1274,1275],{"class":382}," readingRepository",[162,1277,307],{"class":306},[162,1279,1166],{"class":270},[162,1281,385],{"class":172},[162,1283,1284],{"class":172}," {}\n",[162,1286,1287,1289,1291,1293,1295,1298,1300,1302,1305,1307,1310,1312,1314],{"class":164,"line":250},[162,1288,296],{"class":266},[162,1290,1219],{"class":299},[162,1292,303],{"class":172},[162,1294,173],{"class":172},[162,1296,1297],{"class":168}," return",[162,1299,345],{"class":344},[162,1301,348],{"class":172},[162,1303,1304],{"class":176},"readingRepository",[162,1306,348],{"class":172},[162,1308,1309],{"class":277},"loud",[162,1311,303],{"class":359},[162,1313,1018],{"class":172},[162,1315,1316],{"class":172}," }\n",[162,1318,1319],{"class":164,"line":257},[162,1320,942],{"class":172},[144,1322,1323,1327,1328,1331,1332,1335],{},[1324,1325,1326],"strong",{},"Write none and you lose nothing."," The bootstrap registers a default repository for every\nentity — the guarded ORM itself — so ",[148,1329,1330],{},"ReadingRepository"," resolves whether or not the file\nexists. Declaring one wins, exactly as a ",[148,1333,1334],{},"Crud"," operation redefined in the subclass wins\nover the prefab's.",[144,1337,1338,1339,1342],{},"It is ",[1324,1340,1341],{},"not a door",": a repository has no façade, so nothing it carries is reachable from\nthe wire. The judge stays in the handler, the one place a refusal cannot be walked around.",[1133,1344,1346],{"id":1345},"the-four-binding-rules","The four binding rules",[144,1348,1349],{},"Fougere reads your method signature (AST parse at boot) and binds each parameter from the\ninvocation — in this order:",[1351,1352,1353,1369],"table",{},[1354,1355,1356],"thead",{},[1357,1358,1359,1363,1366],"tr",{},[1360,1361,1362],"th",{},"#",[1360,1364,1365],{},"Parameter looks like",[1360,1367,1368],{},"Bound from",[1370,1371,1372,1394,1407,1431],"tbody",{},[1357,1373,1374,1378,1388],{},[1375,1376,1377],"td",{},"1",[1375,1379,1380,1381,490,1385,385],{},"a type with a ",[1382,1383,1384],"a",{"href":78},"Collector",[148,1386,1387],{},"user: User | null",[1375,1389,1390,1391],{},"the collector's ",[148,1392,1393],{},"collect(ctx)",[1357,1395,1396,1399,1404],{},[1375,1397,1398],{},"2",[1375,1400,1401],{},[148,1402,1403],{},"ctx: InvocationContext",[1375,1405,1406],{},"the whole invocation",[1357,1408,1409,1412,1421],{},[1375,1410,1411],{},"3",[1375,1413,1414,1415,959,1418,385],{},"a primitive (",[148,1416,1417],{},"id: string",[148,1419,1420],{},"page: number",[1375,1422,1423,1426,1427,1430],{},[148,1424,1425],{},"params[name]",", then ",[148,1428,1429],{},"query[name]"," — coerced to number\u002Fboolean",[1357,1432,1433,1436,1442],{},[1375,1434,1435],{},"4",[1375,1437,1438,1439,385],{},"anything else (",[148,1440,1441],{},"input: PostDraft",[1375,1443,1444,1445],{},"the request ",[148,1446,1447],{},"body",[144,1449,1450],{},"Two consequences of the parser being AST-only (no type checker):",[1452,1453,1454,1468],"ul",{},[1455,1456,1457,1460,1461,1463,1464,1467],"li",{},[1324,1458,1459],{},"Spell types out."," ",[148,1462,1387],{}," binds; ",[148,1465,1466],{},"user: CurrentUser"," (a type alias) is\ninvisible and binds nothing.",[1455,1469,1470,1473,1474,1476,1477,1480,1481,959,1484,1487,1488,1491],{},[1324,1471,1472],{},"The door is what you declare public."," A ",[148,1475,1272],{}," or ",[148,1478,1479],{},"protected"," method is not an\noperation: the scan skips it, because TypeScript already has the word for it. A helper\nthe handler names by intent (",[148,1482,1483],{},"mustOwn",[148,1485,1486],{},"refuse",") therefore stays a helper, inside the\nclass. ",[148,1489,1490],{},"#name"," works too.",[1133,1493,1495],{"id":1494},"input-validation","Input validation",[144,1497,1498,1499,1502,1503,1506],{},"When a parameter's type is a schema class (entity or view), the façade validates the body\nbefore calling the method. Invalid input produces ",[148,1500,1501],{},"VALIDATION_FAILED"," with per-field\ndetails. A ",[148,1504,1505],{},"partial()"," view uses patch mode.",[1508,1509,1511],"h3",{"id":1510},"unknown-keys-are-refused","Unknown keys are refused",[144,1513,1514,1515,1518,1519,1521,1522,490,1524,1527,1528,1531],{},"A key outside the contract produces an error instead of being silently dropped: a body\n",[148,1516,1517],{},"{ …, status: 'published' }"," against a view that does not declare ",[148,1520,396],{}," comes back as\n",[148,1523,1501],{},[148,1525,1526],{},"status: Unknown field",") before the method runs. Accepted input can\ntherefore be passed to the ORM without another projection. ",[148,1529,1530],{},"useFormFor"," applies the same\nvalidation in the browser before the network request.",[1133,1533,1535],{"id":1534},"a-state-changes-through-an-operation-never-through-a-field-write","A state changes through an operation, never through a field write",[144,1537,1538,1541],{},[148,1539,1540],{},"publish()"," illustrates an explicit state transition for an order, subscription, or\nticket. It combines the following rules:",[153,1543,1545],{"className":155,"code":1544,"language":157,"meta":158,"style":158},"\u002F\u002F the entity — the set of values, and the one it is born with\nstatus: readOnly(oneOf('draft', 'published', { default: 'draft' })),\n",[148,1546,1547,1552],{"__ignoreMap":158},[162,1548,1549],{"class":164,"line":165},[162,1550,1551],{"class":289},"\u002F\u002F the entity — the set of values, and the one it is born with\n",[162,1553,1554,1556,1558,1561,1563,1566,1568,1570,1573,1575,1577,1579,1581,1583,1585,1587,1589,1591,1593,1595,1597,1599,1602],{"class":164,"line":211},[162,1555,396],{"class":270},[162,1557,307],{"class":172},[162,1559,1560],{"class":277}," readOnly",[162,1562,377],{"class":176},[162,1564,1565],{"class":277},"oneOf",[162,1567,377],{"class":176},[162,1569,205],{"class":197},[162,1571,1572],{"class":201},"draft",[162,1574,205],{"class":197},[162,1576,180],{"class":172},[162,1578,198],{"class":197},[162,1580,404],{"class":201},[162,1582,205],{"class":197},[162,1584,180],{"class":172},[162,1586,173],{"class":172},[162,1588,263],{"class":359},[162,1590,307],{"class":172},[162,1592,198],{"class":197},[162,1594,1572],{"class":201},[162,1596,205],{"class":197},[162,1598,191],{"class":172},[162,1600,1601],{"class":176},"))",[162,1603,1604],{"class":172},",\n",[153,1606,1608],{"className":155,"code":1607,"language":157,"meta":158,"style":158},"\u002F\u002F the handler — the passage, and the refusal\nasync publish(id: string): Promise\u003CPost> {\n  const post = await this.orm.findById(id);\n  if (post.status === 'published') {\n    throw new FougereError({ code: ErrorCode.CONFLICT, message: 'Already published',\n      entity: 'post', operation: 'publish' });\n  }\n  return this.orm.update(id, { status: 'published' });\n}\n",[148,1609,1610,1615,1636,1659,1679,1716,1747,1751,1775],{"__ignoreMap":158},[162,1611,1612],{"class":164,"line":165},[162,1613,1614],{"class":289},"\u002F\u002F the handler — the passage, and the refusal\n",[162,1616,1617,1620,1622,1625,1628,1630,1632,1634],{"class":164,"line":211},[162,1618,1619],{"class":176},"async ",[162,1621,563],{"class":277},[162,1623,1624],{"class":176},"(id: string): ",[162,1626,1627],{"class":449},"Promise",[162,1629,313],{"class":306},[162,1631,477],{"class":176},[162,1633,322],{"class":306},[162,1635,325],{"class":172},[162,1637,1638,1641,1644,1646,1648,1650,1652,1654,1656],{"class":164,"line":231},[162,1639,1640],{"class":176},"  const post ",[162,1642,1643],{"class":306},"=",[162,1645,341],{"class":168},[162,1647,345],{"class":344},[162,1649,348],{"class":172},[162,1651,351],{"class":176},[162,1653,348],{"class":172},[162,1655,594],{"class":277},[162,1657,1658],{"class":176},"(id);\n",[162,1660,1661,1664,1666,1669,1671,1673,1675,1677],{"class":164,"line":250},[162,1662,1663],{"class":299},"  if",[162,1665,490],{"class":172},[162,1667,1668],{"class":176},"post.status === ",[162,1670,205],{"class":197},[162,1672,404],{"class":201},[162,1674,205],{"class":197},[162,1676,385],{"class":172},[162,1678,325],{"class":172},[162,1680,1681,1684,1686,1688,1690,1692,1694,1696,1698,1700,1702,1704,1706,1708,1710,1712,1714],{"class":164,"line":257},[162,1682,1683],{"class":168},"    throw",[162,1685,504],{"class":306},[162,1687,183],{"class":277},[162,1689,377],{"class":359},[162,1691,511],{"class":172},[162,1693,514],{"class":359},[162,1695,307],{"class":172},[162,1697,188],{"class":176},[162,1699,348],{"class":172},[162,1701,825],{"class":334},[162,1703,180],{"class":172},[162,1705,528],{"class":359},[162,1707,307],{"class":172},[162,1709,198],{"class":197},[162,1711,836],{"class":201},[162,1713,205],{"class":197},[162,1715,1604],{"class":172},[162,1717,1718,1721,1723,1725,1727,1729,1731,1733,1735,1737,1739,1741,1743,1745],{"class":164,"line":286},[162,1719,1720],{"class":359},"      entity",[162,1722,307],{"class":172},[162,1724,198],{"class":197},[162,1726,549],{"class":201},[162,1728,205],{"class":197},[162,1730,180],{"class":172},[162,1732,556],{"class":359},[162,1734,307],{"class":172},[162,1736,198],{"class":197},[162,1738,563],{"class":201},[162,1740,205],{"class":197},[162,1742,191],{"class":172},[162,1744,385],{"class":359},[162,1746,208],{"class":172},[162,1748,1749],{"class":164,"line":293},[162,1750,420],{"class":172},[162,1752,1753,1756,1758,1760,1762,1764,1766,1768,1770,1772],{"class":164,"line":328},[162,1754,1755],{"class":176},"  return this.orm.update(id",[162,1757,180],{"class":172},[162,1759,173],{"class":172},[162,1761,895],{"class":270},[162,1763,307],{"class":172},[162,1765,198],{"class":197},[162,1767,404],{"class":201},[162,1769,205],{"class":197},[162,1771,191],{"class":172},[162,1773,1774],{"class":176},");\n",[162,1776,1777],{"class":164,"line":364},[162,1778,942],{"class":172},[1452,1780,1781,1796,1808,1827],{},[1455,1782,1783,1787,1788,1791,1792,1795],{},[1324,1784,1785],{},[148,1786,1565],{}," limits the values. A form can render a ",[148,1789,1790],{},"\u003Cselect>",", the DDL emits\n",[148,1793,1794],{},"CHECK status in (…)",", and GraphQL declares an enum type.",[1455,1797,1798,1803,1804,1807],{},[1324,1799,1800],{},[148,1801,1802],{},"{ default: 'draft' }"," is the initial state — a create rule on the\n",[1382,1805,1806],{"href":49},"lifecycle axis",", so nobody supplies it.",[1455,1809,1810,1815,1816,1819,1820,1823,1824,1826],{},[1324,1811,1812],{},[148,1813,1814],{},"readOnly"," prevents clients from writing the field: ",[148,1817,1818],{},"boundary.in"," is ",[148,1821,1822],{},"closed",", so ",[148,1825,396],{}," is\nabsent from every input view. A body carrying it is refused as an unknown key.",[1455,1828,1829,1832,1833,1835,1836,1839],{},[1324,1830,1831],{},"The named operation"," owns the transition and returns ",[148,1834,825],{},", projected as\n",[1382,1837,1838],{"href":82},"409",", when the current state prevents it.",[144,1841,1842,1843,1846,1847,1850],{},"The method alone controls the transition order. A direct SQL update, or another handler\ncalling ",[148,1844,1845],{},"this.orm.update(id, { status })",", can bypass it as long as the value satisfies the\n",[148,1848,1849],{},"CHECK",". Fougere does not provide a state graph: the field declares possible values and\nthe operation controls transitions between them.",[1133,1852,1854],{"id":1853},"output-view","Output view",[144,1856,1857,1859],{},[148,1858,1334],{},"'s second argument selects the output view. Two forms are available:",[153,1861,1863],{"className":155,"code":1862,"language":157,"meta":158,"style":158},"Crud(Post, { list: PostCard })   \u002F\u002F list returns cards, the rest return Post\nCrud(Post, PostPublic)           \u002F\u002F the whole handler returns PostPublic\n",[148,1864,1865,1891],{"__ignoreMap":158},[162,1866,1867,1869,1872,1874,1876,1878,1880,1883,1885,1888],{"class":164,"line":165},[162,1868,1334],{"class":277},[162,1870,1871],{"class":176},"(Post",[162,1873,180],{"class":172},[162,1875,173],{"class":172},[162,1877,300],{"class":359},[162,1879,307],{"class":172},[162,1881,1882],{"class":176}," PostCard ",[162,1884,656],{"class":172},[162,1886,1887],{"class":176},")   ",[162,1889,1890],{"class":289},"\u002F\u002F list returns cards, the rest return Post\n",[162,1892,1893,1895,1897,1899,1902],{"class":164,"line":211},[162,1894,1334],{"class":277},[162,1896,1871],{"class":176},[162,1898,180],{"class":172},[162,1900,1901],{"class":176}," PostPublic)           ",[162,1903,1904],{"class":289},"\u002F\u002F the whole handler returns PostPublic\n",[144,1906,1907],{},"With per-operation configuration, the ORM returns the whole row and the façade applies the\nview to the output. Other operations keep their own views.",[144,1909,1910,1911,1914,1915,1918],{},"With a view for the whole handler, the injected ORM itself is restricted. A second handler\nfile can therefore define another audience: ",[148,1912,1913],{},"handlers\u002FPostHandler.ts"," (full) and\n",[148,1916,1917],{},"handlers\u002Fpublic\u002FPostHandler.ts"," (restricted).",[1133,1920,1922],{"id":1921},"reaching-another-frond","Reaching another Frond",[144,1924,1925,1926,1929,1930,1933],{},"A Frond does not import another's files: it goes through its door. ",[148,1927,1928],{},"Facade\u003CT>"," is the\nframework's second port, read like the first (",[148,1931,1932],{},"EntityOrm\u003CPost>","):",[153,1935,1937],{"className":155,"code":1936,"language":157,"meta":158,"style":158},"import type { Facade } from '@fougere\u002Fcore';\nimport type ArticleHandler from '@frond\u002Fstock\u002Fhandlers\u002FArticleHandler';\n\nexport default class CommandeHandler {\n  constructor(private articleFacade: Facade\u003CArticleHandler>) {}\n\n  \u002F** Can this order be served from the shelf? *\u002F\n  async servable(): Promise\u003Cboolean> {\n    const onHand = await this.articleFacade.onHand();\n    return onHand > 0;\n  }\n}\n",[148,1938,1939,1963,1983,1987,2000,2025,2029,2034,2056,2083,2097,2101],{"__ignoreMap":158},[162,1940,1941,1943,1946,1948,1951,1953,1955,1957,1959,1961],{"class":164,"line":165},[162,1942,169],{"class":168},[162,1944,1945],{"class":168}," type",[162,1947,173],{"class":172},[162,1949,1950],{"class":176}," Facade",[162,1952,191],{"class":172},[162,1954,194],{"class":168},[162,1956,198],{"class":197},[162,1958,202],{"class":201},[162,1960,205],{"class":197},[162,1962,208],{"class":172},[162,1964,1965,1967,1969,1972,1974,1976,1979,1981],{"class":164,"line":211},[162,1966,169],{"class":168},[162,1968,1945],{"class":168},[162,1970,1971],{"class":176}," ArticleHandler ",[162,1973,219],{"class":168},[162,1975,198],{"class":197},[162,1977,1978],{"class":201},"@frond\u002Fstock\u002Fhandlers\u002FArticleHandler",[162,1980,205],{"class":197},[162,1982,208],{"class":172},[162,1984,1985],{"class":164,"line":231},[162,1986,254],{"emptyLinePlaceholder":253},[162,1988,1989,1991,1993,1995,1998],{"class":164,"line":250},[162,1990,260],{"class":168},[162,1992,263],{"class":168},[162,1994,267],{"class":266},[162,1996,1997],{"class":270}," CommandeHandler",[162,1999,325],{"class":172},[162,2001,2002,2004,2006,2008,2011,2013,2015,2017,2020,2023],{"class":164,"line":257},[162,2003,1267],{"class":266},[162,2005,377],{"class":172},[162,2007,1272],{"class":266},[162,2009,2010],{"class":382}," articleFacade",[162,2012,307],{"class":306},[162,2014,1950],{"class":270},[162,2016,313],{"class":172},[162,2018,2019],{"class":270},"ArticleHandler",[162,2021,2022],{"class":172},">)",[162,2024,1284],{"class":172},[162,2026,2027],{"class":164,"line":286},[162,2028,254],{"emptyLinePlaceholder":253},[162,2030,2031],{"class":164,"line":293},[162,2032,2033],{"class":289},"  \u002F** Can this order be served from the shelf? *\u002F\n",[162,2035,2036,2038,2041,2043,2045,2047,2049,2052,2054],{"class":164,"line":328},[162,2037,296],{"class":266},[162,2039,2040],{"class":299}," servable",[162,2042,303],{"class":172},[162,2044,307],{"class":306},[162,2046,310],{"class":270},[162,2048,313],{"class":172},[162,2050,2051],{"class":449},"boolean",[162,2053,322],{"class":172},[162,2055,325],{"class":172},[162,2057,2058,2060,2063,2065,2067,2069,2071,2074,2076,2079,2081],{"class":164,"line":364},[162,2059,331],{"class":266},[162,2061,2062],{"class":334}," onHand",[162,2064,338],{"class":306},[162,2066,341],{"class":168},[162,2068,345],{"class":344},[162,2070,348],{"class":172},[162,2072,2073],{"class":176},"articleFacade",[162,2075,348],{"class":172},[162,2077,2078],{"class":277},"onHand",[162,2080,303],{"class":359},[162,2082,208],{"class":172},[162,2084,2085,2087,2089,2092,2095],{"class":164,"line":417},[162,2086,367],{"class":168},[162,2088,2062],{"class":176},[162,2090,2091],{"class":306}," >",[162,2093,2094],{"class":1107}," 0",[162,2096,208],{"class":172},[162,2098,2099],{"class":164,"line":423},[162,2100,420],{"class":172},[162,2102,2103],{"class":164,"line":428},[162,2104,942],{"class":172},[144,2106,2107],{},"Three things to see:",[1452,2109,2110,2122,2146],{},[1455,2111,2112,2115,2116,2118,2119,348],{},[1324,2113,2114],{},"It is the door, not the handler."," Nobody injects a handler — its methods take\npositional arguments. The façade takes the invocation: every operation on ",[148,2117,1928],{}," has\nthe signature ",[148,2120,2121],{},"(invocation?) => Promise\u003C…>",[1455,2123,2124,2130,2131,2133,2134,2136,2137,2141,2142,2145],{},[1324,2125,2126,2129],{},[148,2127,2128],{},"keyof T"," is exactly the right set."," The scan skips ",[148,2132,1272],{}," and ",[148,2135,1479],{},", so a\nhandler's public methods ",[2138,2139,2140],"em",{},"are"," its operations — and ",[148,2143,2144],{},"keyof"," excludes the rest for the\nsame reason.",[1455,2147,2148,2151,2152,2155,2156,2159],{},[1324,2149,2150],{},"The signature says nothing about where the other Frond runs."," The same type resolves\nthe local façade or a doublure. Declaring ",[148,2153,2154],{},"stock"," in ",[148,2157,2158],{},"remotes:"," does not change this line.",[144,2161,2162,2163,2166,2167,2169],{},"What does not travel on its own is ",[1324,2164,2165],{},"identity",". The called operation receives the\ninvocation you hand it and nothing else: for a collector on the far side to see the same\nuser, declare ",[148,2168,1403],{}," (binding rule 2) and pass it through.",[1508,2171,2173],{"id":2172},"announcing-a-fact","Announcing a fact",[144,2175,2176,2177,979,2180,2183,2184,2187],{},"A call names one recipient; an emission names a ",[1324,2178,2179],{},"subject",[148,2181,2182],{},"Emit\u003CT>"," is a constructor\ndependency like any other, and accepting a ",[148,2185,2186],{},"Fact\u003CT>"," IS the subscription — no topic, no\nregister call.",[144,2189,2190,2191,2193],{},"See ",[1382,2192,89],{"href":90}," — the resolver, what crosses a process, and what to do\nwhen a fact's shape moves.",[144,2195,2196,2197,2199],{},"Next: ",[1382,2198,73],{"href":74}," — computed fields added to an entity's output.",[2201,2202,2203],"style",{},"html pre.shiki code .sVHd0, html code.shiki .sVHd0{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#D73A49;--shiki-default-font-style:inherit;--shiki-dark:#F97583;--shiki-dark-font-style:inherit}html pre.shiki code .sP7_E, html code.shiki .sP7_E{--shiki-light:#39ADB5;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .su5hD, html code.shiki .su5hD{--shiki-light:#90A4AE;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sjJ54, html code.shiki .sjJ54{--shiki-light:#39ADB5;--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .s_sjI, html code.shiki .s_sjI{--shiki-light:#91B859;--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sbsja, html code.shiki .sbsja{--shiki-light:#9C3EDA;--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sbgvK, html code.shiki .sbgvK{--shiki-light:#E2931D;--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sGLFI, html code.shiki .sGLFI{--shiki-light:#6182B8;--shiki-default:#6F42C1;--shiki-dark:#B392F0}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 .sVXei, html code.shiki .sVXei{--shiki-light:#E53935;--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .smGrS, html code.shiki .smGrS{--shiki-light:#39ADB5;--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .s_hVV, html code.shiki .s_hVV{--shiki-light:#90A4AE;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .s39Yj, html code.shiki .s39Yj{--shiki-light:#39ADB5;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .skxfh, html code.shiki .skxfh{--shiki-light:#E53935;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .s99_P, html code.shiki .s99_P{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#E36209;--shiki-default-font-style:inherit;--shiki-dark:#FFAB70;--shiki-dark-font-style:inherit}html pre.shiki code .sZMiF, html code.shiki .sZMiF{--shiki-light:#E2931D;--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 .srdBf, html code.shiki .srdBf{--shiki-light:#F76D47;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .syTEX, html code.shiki .syTEX{--shiki-light:#FF5370;--shiki-default:#005CC5;--shiki-dark:#79B8FF}",{"title":158,"searchDepth":211,"depth":211,"links":2205},[2206,2207,2208,2211,2212,2213],{"id":1135,"depth":211,"text":1136},{"id":1345,"depth":211,"text":1346},{"id":1494,"depth":211,"text":1495,"children":2209},[2210],{"id":1510,"depth":231,"text":1511},{"id":1534,"depth":211,"text":1535},{"id":1853,"depth":211,"text":1854},{"id":1921,"depth":211,"text":1922,"children":2214},[2215],{"id":2172,"depth":231,"text":2173},"Crud(Entity), operations, the four binding rules, the output view.","md",{},{"title":69,"description":2216},"UmEzJ4X-fDU13iH-2b3zQjKQc9K_jLFOfeVVHoK5VnY",1786637819127]