[{"data":1,"prerenderedAt":664},["ShallowReactive",2],{"fougere:post.list:{}":3,"docs:\u002Fdocs\u002Fbehaviour\u002Ffinish-a-fact":6,"docs-uses":352,"docs-nav":526},{"items":4,"hasMore":5},[],false,{"id":7,"title":8,"body":9,"description":340,"extension":341,"forms":342,"kind":344,"meta":345,"navigation":113,"path":346,"seo":347,"stem":348,"step":349,"uses":350,"__hash__":351},"docs\u002Fdocs\u002F4.behaviour\u002F2.finish-a-fact.md","Finish a fact",{"type":10,"value":11,"toc":335},"minimark",[12,27,35,40,223,226,230,233,295,298,311,315,322,331],[13,14,15,16,20,21,26],"p",{},"Sometimes a fact must be changed before anyone reads it: an author's id hashed for privacy, a tenant\nlooked up with a service the announcer should not hold. An operation taking ",[17,18,19],"code",{},"Pipe\u003CT>"," does it — it\nreceives the fact, and what it returns is what every ",[22,23,25],"a",{"href":24},"\u002Fdocs\u002Fconcepts\u002Ffact","listener"," reads.",[13,28,29,30,34],{},"To leave a field out, you need no link: a fact is already a cut of an entity, so simply do not\ndeclare the field. A link is for what must be ",[31,32,33],"strong",{},"transformed",".",[36,37,39],"h2",{"id":38},"write-the-link","Write the link",[41,42,47],"pre",{"className":43,"code":44,"language":45,"meta":46,"style":46},"language-ts shiki shiki-themes material-theme-lighter fougere-pastel material-theme-palenight","\u002F\u002F fronds\u002Fprivacy\u002Fhandlers\u002FHashHandler.ts\nexport default class HashHandler {\n  constructor(private salt: Salt) {}\n\n  async set(fact: Pipe\u003CPostPublished>): Promise\u003CPostPublished> {\n    return { ...fact, author: this.salt.hash(fact.author) };\n  }\n}\n","ts","",[17,48,49,58,80,108,115,156,211,217],{"__ignoreMap":46},[50,51,54],"span",{"class":52,"line":53},"line",1,[50,55,57],{"class":56},"skXKP","\u002F\u002F fronds\u002Fprivacy\u002Fhandlers\u002FHashHandler.ts\n",[50,59,61,65,68,72,76],{"class":52,"line":60},2,[50,62,64],{"class":63},"sK6XW","export",[50,66,67],{"class":63}," default",[50,69,71],{"class":70},"s76I7"," class",[50,73,75],{"class":74},"sBZYL"," HashHandler",[50,77,79],{"class":78},"s15xx"," {\n",[50,81,83,86,89,92,96,99,102,105],{"class":52,"line":82},3,[50,84,85],{"class":70},"  constructor",[50,87,88],{"class":78},"(",[50,90,91],{"class":70},"private",[50,93,95],{"class":94},"shDUQ"," salt",[50,97,98],{"class":78},":",[50,100,101],{"class":74}," Salt",[50,103,104],{"class":78},")",[50,106,107],{"class":78}," {}\n",[50,109,111],{"class":52,"line":110},4,[50,112,114],{"emptyLinePlaceholder":113},true,"\n",[50,116,118,121,125,127,130,132,135,138,141,144,147,149,151,154],{"class":52,"line":117},5,[50,119,120],{"class":70},"  async",[50,122,124],{"class":123},"shDkW"," set",[50,126,88],{"class":78},[50,128,129],{"class":94},"fact",[50,131,98],{"class":78},[50,133,134],{"class":74}," Pipe",[50,136,137],{"class":78},"\u003C",[50,139,140],{"class":74},"PostPublished",[50,142,143],{"class":78},">):",[50,145,146],{"class":74}," Promise",[50,148,137],{"class":78},[50,150,140],{"class":74},[50,152,153],{"class":78},">",[50,155,79],{"class":78},[50,157,159,162,165,168,171,174,178,180,184,186,190,192,196,199,201,203,206,208],{"class":52,"line":158},6,[50,160,161],{"class":63},"    return",[50,163,164],{"class":78}," {",[50,166,167],{"class":78}," ...",[50,169,129],{"class":170},"sPEhv",[50,172,173],{"class":78},",",[50,175,177],{"class":176},"sHtqg"," author",[50,179,98],{"class":78},[50,181,183],{"class":182},"sxG60"," this",[50,185,34],{"class":78},[50,187,189],{"class":188},"sy9f4","salt",[50,191,34],{"class":78},[50,193,195],{"class":194},"s4mR9","hash",[50,197,88],{"class":198},"spAFX",[50,200,129],{"class":170},[50,202,34],{"class":78},[50,204,205],{"class":188},"author",[50,207,104],{"class":198},[50,209,210],{"class":78}," };\n",[50,212,214],{"class":52,"line":213},7,[50,215,216],{"class":78},"  }\n",[50,218,220],{"class":52,"line":219},8,[50,221,222],{"class":78},"}\n",[13,224,225],{},"It receives the whole fact and must answer one — a link that answers nothing is refused.",[36,227,229],{"id":228},"order-them-in-the-frond-that-owns-the-fact","Order them, in the frond that owns the fact",[13,231,232],{},"Several links run in an order, each reading what the previous one answered. The order belongs to the\nfrond that owns the fact:",[41,234,236],{"className":43,"code":235,"language":45,"meta":46,"style":46},"\u002F\u002F fronds\u002Fblog\u002Ffrond.config.ts — blog owns postPublished\nexport default { pipes: { postPublished: ['TenantHandler', 'HashHandler'] } };\n",[17,237,238,243],{"__ignoreMap":46},[50,239,240],{"class":52,"line":53},[50,241,242],{"class":56},"\u002F\u002F fronds\u002Fblog\u002Ffrond.config.ts — blog owns postPublished\n",[50,244,245,247,249,251,254,256,258,261,263,267,271,275,277,279,282,285,287,290,293],{"class":52,"line":60},[50,246,64],{"class":63},[50,248,67],{"class":63},[50,250,164],{"class":78},[50,252,253],{"class":176}," pipes",[50,255,98],{"class":78},[50,257,164],{"class":78},[50,259,260],{"class":176}," postPublished",[50,262,98],{"class":78},[50,264,266],{"class":265},"srlTG"," [",[50,268,270],{"class":269},"sDDC1","'",[50,272,274],{"class":273},"sN-8n","TenantHandler",[50,276,270],{"class":269},[50,278,173],{"class":78},[50,280,281],{"class":269}," '",[50,283,284],{"class":273},"HashHandler",[50,286,270],{"class":269},[50,288,289],{"class":265},"]",[50,291,292],{"class":78}," }",[50,294,210],{"class":78},[13,296,297],{},"The boot refuses:",[299,300,301,305,308],"ul",{},[302,303,304],"li",{},"two links with no order, naming both;",[302,306,307],{},"a link the order does not list;",[302,309,310],{},"a frond ordering a fact it does not own.",[36,312,314],{"id":313},"what-it-costs","What it costs",[13,316,317,318,321],{},"A link is a hard dependency, where a listener is not: a listener that throws is logged and the\nannouncement goes on; a link that throws stops it. A link is called, so it has an address — in this\nprocess or in ",[17,319,320],{},"fronds:"," — and cannot sit behind a carrier.",[13,323,324,330],{},[22,325,329],{"href":326,"rel":327},"https:\u002F\u002Fgithub.com\u002Fchok\u002Ffougere\u002Ftree\u002Fmain\u002Fdemos\u002Fpipe-split",[328],"nofollow","pipe-split"," runs it in one process, then split.",[332,333,334],"style",{},"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 .s76I7, html code.shiki .s76I7{--shiki-light:#9C3EDA;--shiki-default:#8FCF86;--shiki-dark:#C792EA}html pre.shiki code .sBZYL, html code.shiki .sBZYL{--shiki-light:#E2931D;--shiki-default:#EFCD8F;--shiki-dark:#FFCB6B}html pre.shiki code .s15xx, html code.shiki .s15xx{--shiki-light:#39ADB5;--shiki-default:#A3B0A5;--shiki-dark:#89DDFF}html pre.shiki code .shDUQ, html code.shiki .shDUQ{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#DDE5DA;--shiki-default-font-style:inherit;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}html pre.shiki code .shDkW, html code.shiki .shDkW{--shiki-light:#E53935;--shiki-default:#C9B6EA;--shiki-dark:#F07178}html pre.shiki code .sPEhv, html code.shiki .sPEhv{--shiki-light:#90A4AE;--shiki-default:#DDE5DA;--shiki-dark:#BABED8}html pre.shiki code .sHtqg, html code.shiki .sHtqg{--shiki-light:#E53935;--shiki-default:#93CFC0;--shiki-dark:#F07178}html pre.shiki code .sxG60, html code.shiki .sxG60{--shiki-light:#39ADB5;--shiki-light-font-style:inherit;--shiki-default:#8FCF86;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:inherit}html pre.shiki code .sy9f4, html code.shiki .sy9f4{--shiki-light:#90A4AE;--shiki-default:#93CFC0;--shiki-dark:#BABED8}html pre.shiki code .s4mR9, html code.shiki .s4mR9{--shiki-light:#6182B8;--shiki-default:#C9B6EA;--shiki-dark:#82AAFF}html pre.shiki code .spAFX, html code.shiki .spAFX{--shiki-light:#E53935;--shiki-default:#A3B0A5;--shiki-dark:#F07178}html .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 .srlTG, html code.shiki .srlTG{--shiki-light:#90A4AE;--shiki-default:#A3B0A5;--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 .sN-8n, html code.shiki .sN-8n{--shiki-light:#91B859;--shiki-default:#EE9F6B;--shiki-dark:#C3E88D}",{"title":46,"searchDepth":60,"depth":60,"links":336},[337,338,339],{"id":38,"depth":60,"text":39},{"id":228,"depth":60,"text":229},{"id":313,"depth":60,"text":314},"Transform a fact before any subscriber reads it.","md",[19,343],"pipes:","task",{},"\u002Fdocs\u002Fbehaviour\u002Ffinish-a-fact",{"title":8,"description":340},"docs\u002F4.behaviour\u002F2.finish-a-fact",null,[129],"D2m5DkVaSMegeJZGR0H6QHi3gQJMqzB-GuGbCC71gi8",[353,356,359,362,365,368,370,373,376,382,388,393,397,401,405,409,413,418,422,426,428,432,437,441,445,449,453,457,461,465,469,473,477,481,485,489,493,496,499,502,505,508,511,514,517,520,523],{"path":354,"title":355,"uses":349},"\u002Fdocs\u002Fconcepts\u002Fentity","Entity",{"path":357,"title":358,"uses":349},"\u002Fdocs\u002Fconcepts\u002Fhandler","Handler",{"path":360,"title":361,"uses":349},"\u002Fdocs\u002Fconcepts\u002Frepository","Repository",{"path":363,"title":364,"uses":349},"\u002Fdocs\u002Fconcepts\u002Ffrond","Frond",{"path":366,"title":367,"uses":349},"\u002Fdocs\u002Fconcepts\u002Ffacade","Facade",{"path":24,"title":369,"uses":349},"Fact",{"path":371,"title":372,"uses":349},"\u002Fdocs\u002Fconcepts\u002Fport","Port",{"path":374,"title":375,"uses":349},"\u002Fdocs\u002Fconcepts\u002Fconfiguration","Configuration",{"path":377,"title":378,"uses":379},"\u002Fdocs\u002Faccess\u002Fauthentication","Authentication",[380,381],"port","frond",{"path":383,"title":384,"uses":385},"\u002Fdocs\u002Faccess\u002Fstate","Keep a caller's state",[386,387],"configuration","handler",{"path":389,"title":390,"uses":391},"\u002Fdocs\u002Fdata\u002Fsql","SQLite or Postgres",[392,386],"entity",{"path":394,"title":395,"uses":396},"\u002Fdocs\u002Fdata\u002Fseveral-databases","Several databases",[386,392],{"path":398,"title":399,"uses":400},"\u002Fdocs\u002Fdata\u002Fcomputed-field","A computed field",[392,380],{"path":402,"title":403,"uses":404},"\u002Fdocs\u002Fdata\u002Fevolve","Evolve a schema",[392],{"path":406,"title":407,"uses":408},"\u002Fdocs\u002Fdata\u002Fseeds","Seed data",[392],{"path":410,"title":411,"uses":412},"\u002Fdocs\u002Fdata\u002Fvalues","Read settings and secrets",[392,386],{"path":414,"title":415,"uses":416},"\u002Fdocs\u002Fdata\u002Fmirror","Mirror a source you cannot query",[417],"repository",{"path":419,"title":420,"uses":421},"\u002Fdocs\u002Fdata\u002Ftogether","Two writes as one",[417],{"path":423,"title":424,"uses":425},"\u002Fdocs\u002Fbehaviour\u002Faround-every-call","Around every call",[380,381],{"path":346,"title":8,"uses":427},[129],{"path":429,"title":430,"uses":431},"\u002Fdocs\u002Fserve\u002Frest-graphql","REST, OpenAPI, GraphQL",[387,386],{"path":433,"title":434,"uses":435},"\u002Fdocs\u002Fserve\u002Fpages","Pages: queries and commands",[387,436],"facade",{"path":438,"title":439,"uses":440},"\u002Fdocs\u002Fserve\u002Fforms","A form",[392],{"path":442,"title":443,"uses":444},"\u002Fdocs\u002Fserve\u002Fadmin","An admin panel",[387],{"path":446,"title":447,"uses":448},"\u002Fdocs\u002Frun\u002Fdeploy","Deploy a split",[386,381],{"path":450,"title":451,"uses":452},"\u002Fdocs\u002Frun\u002Fsecure","Secure calls between processes",[386,381],{"path":454,"title":455,"uses":456},"\u002Fdocs\u002Frun\u002Flifecycle","Reload and shut down",[386],{"path":458,"title":459,"uses":460},"\u002Fdocs\u002Frun\u002Fobserve","Observe",[386,387],{"path":462,"title":463,"uses":464},"\u002Fdocs\u002Frun\u002Fdev-panel","The dev panel",[387],{"path":466,"title":467,"uses":468},"\u002Fdocs\u002Frun\u002Ftest","Test",[392,380],{"path":470,"title":471,"uses":472},"\u002Fdocs\u002Fadopt\u002Fnew-project","Start a project",[381,386],{"path":474,"title":475,"uses":476},"\u002Fdocs\u002Fadopt\u002Fexisting-app","Add Fougere to an existing app",[381,386],{"path":478,"title":479,"uses":480},"\u002Fdocs\u002Fadopt\u002Fbring-your-schema","Bring your schema",[392],{"path":482,"title":483,"uses":484},"\u002Fdocs\u002Fadopt\u002Fhosts","Pick a host",[386],{"path":486,"title":487,"uses":488},"\u002Fdocs\u002Fadopt\u002Fanother-repository","A frond from another repository",[436,381],{"path":490,"title":491,"uses":492},"\u002Fdocs\u002Fadopt\u002Fdemos","Demos",[],{"path":494,"title":495,"uses":349},"\u002Fdocs\u002Fextending\u002Fscan","How the scan reads a project",{"path":497,"title":498,"uses":349},"\u002Fdocs\u002Fextending\u002Fwithout-compiler","Boot without the compiler",{"path":500,"title":501,"uses":349},"\u002Fdocs\u002Fextending\u002Fboot","The boot, step by step",{"path":503,"title":504,"uses":349},"\u002Fdocs\u002Fextending\u002Fcard-and-wire","The card and the wire",{"path":506,"title":507,"uses":349},"\u002Fdocs\u002Fextending\u002Fextension-points","Registries and extension points",{"path":509,"title":510,"uses":349},"\u002Fdocs\u002Fextending\u002Fvocabulary","Teach a word",{"path":512,"title":513,"uses":349},"\u002Fdocs\u002Fextending\u002Fextensions","Run code at boot and shutdown",{"path":515,"title":516,"uses":349},"\u002Fdocs\u002Fextending\u002Fsource-adapter","Write a source adapter",{"path":518,"title":519,"uses":349},"\u002Fdocs\u002Fextending\u002Fsurface","Write a surface",{"path":521,"title":522,"uses":349},"\u002Fdocs\u002Fextending\u002Fforeign-frond","A frond in another language",{"path":524,"title":525,"uses":349},"\u002Fdocs","What is Fougere",[527],{"title":528,"path":524,"stem":529,"children":530,"page":-1},"Docs","docs",[531,533,554,563,584,592,605,622,639],{"title":525,"path":524,"stem":532},"docs\u002Findex",{"title":534,"path":535,"stem":536,"children":537,"page":5},"Concepts","\u002Fdocs\u002Fconcepts","docs\u002F1.concepts",[538,540,542,544,546,548,550,552],{"title":355,"path":354,"stem":539},"docs\u002F1.concepts\u002F1.entity",{"title":358,"path":357,"stem":541},"docs\u002F1.concepts\u002F2.handler",{"title":361,"path":360,"stem":543},"docs\u002F1.concepts\u002F3.repository",{"title":364,"path":363,"stem":545},"docs\u002F1.concepts\u002F4.frond",{"title":367,"path":366,"stem":547},"docs\u002F1.concepts\u002F5.facade",{"title":369,"path":24,"stem":549},"docs\u002F1.concepts\u002F6.fact",{"title":372,"path":371,"stem":551},"docs\u002F1.concepts\u002F7.port",{"title":375,"path":374,"stem":553},"docs\u002F1.concepts\u002F8.configuration",{"title":555,"path":556,"stem":557,"children":558,"page":5},"Access","\u002Fdocs\u002Faccess","docs\u002F2.access",[559,561],{"title":378,"path":377,"stem":560},"docs\u002F2.access\u002F1.authentication",{"title":384,"path":383,"stem":562},"docs\u002F2.access\u002F2.state",{"title":564,"path":565,"stem":566,"children":567,"page":5},"Data","\u002Fdocs\u002Fdata","docs\u002F3.data",[568,570,572,574,576,578,580,582],{"title":390,"path":389,"stem":569},"docs\u002F3.data\u002F1.sql",{"title":395,"path":394,"stem":571},"docs\u002F3.data\u002F2.several-databases",{"title":399,"path":398,"stem":573},"docs\u002F3.data\u002F3.computed-field",{"title":403,"path":402,"stem":575},"docs\u002F3.data\u002F4.evolve",{"title":407,"path":406,"stem":577},"docs\u002F3.data\u002F5.seeds",{"title":411,"path":410,"stem":579},"docs\u002F3.data\u002F6.values",{"title":415,"path":414,"stem":581},"docs\u002F3.data\u002F7.mirror",{"title":420,"path":419,"stem":583},"docs\u002F3.data\u002F8.together",{"title":585,"path":586,"stem":587,"children":588,"page":5},"Behaviour","\u002Fdocs\u002Fbehaviour","docs\u002F4.behaviour",[589,591],{"title":424,"path":423,"stem":590},"docs\u002F4.behaviour\u002F1.around-every-call",{"title":8,"path":346,"stem":348},{"title":593,"path":594,"stem":595,"children":596,"page":5},"Serve","\u002Fdocs\u002Fserve","docs\u002F5.serve",[597,599,601,603],{"title":430,"path":429,"stem":598},"docs\u002F5.serve\u002F1.rest-graphql",{"title":434,"path":433,"stem":600},"docs\u002F5.serve\u002F2.pages",{"title":439,"path":438,"stem":602},"docs\u002F5.serve\u002F3.forms",{"title":443,"path":442,"stem":604},"docs\u002F5.serve\u002F4.admin",{"title":606,"path":607,"stem":608,"children":609,"page":5},"Run","\u002Fdocs\u002Frun","docs\u002F6.run",[610,612,614,616,618,620],{"title":447,"path":446,"stem":611},"docs\u002F6.run\u002F1.deploy",{"title":451,"path":450,"stem":613},"docs\u002F6.run\u002F2.secure",{"title":455,"path":454,"stem":615},"docs\u002F6.run\u002F3.lifecycle",{"title":459,"path":458,"stem":617},"docs\u002F6.run\u002F4.observe",{"title":463,"path":462,"stem":619},"docs\u002F6.run\u002F5.dev-panel",{"title":467,"path":466,"stem":621},"docs\u002F6.run\u002F6.test",{"title":623,"path":624,"stem":625,"children":626,"page":5},"Adopt","\u002Fdocs\u002Fadopt","docs\u002F7.adopt",[627,629,631,633,635,637],{"title":471,"path":470,"stem":628},"docs\u002F7.adopt\u002F1.new-project",{"title":475,"path":474,"stem":630},"docs\u002F7.adopt\u002F2.existing-app",{"title":479,"path":478,"stem":632},"docs\u002F7.adopt\u002F3.bring-your-schema",{"title":483,"path":482,"stem":634},"docs\u002F7.adopt\u002F4.hosts",{"title":487,"path":486,"stem":636},"docs\u002F7.adopt\u002F5.another-repository",{"title":491,"path":490,"stem":638},"docs\u002F7.adopt\u002F6.demos",{"title":640,"path":641,"stem":642,"children":643,"page":5},"Extending","\u002Fdocs\u002Fextending","docs\u002F8.extending",[644,646,648,650,652,654,656,658,660,662],{"title":495,"path":494,"stem":645},"docs\u002F8.extending\u002F1.scan",{"title":498,"path":497,"stem":647},"docs\u002F8.extending\u002F10.without-compiler",{"title":501,"path":500,"stem":649},"docs\u002F8.extending\u002F2.boot",{"title":504,"path":503,"stem":651},"docs\u002F8.extending\u002F3.card-and-wire",{"title":507,"path":506,"stem":653},"docs\u002F8.extending\u002F4.extension-points",{"title":510,"path":509,"stem":655},"docs\u002F8.extending\u002F5.vocabulary",{"title":513,"path":512,"stem":657},"docs\u002F8.extending\u002F6.extensions",{"title":516,"path":515,"stem":659},"docs\u002F8.extending\u002F7.source-adapter",{"title":519,"path":518,"stem":661},"docs\u002F8.extending\u002F8.surface",{"title":522,"path":521,"stem":663},"docs\u002F8.extending\u002F9.foreign-frond",1794396614625]