@aglyn/tenant-runtime 1.0.0-beta.220 → 1.0.0-beta.221
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aglyn/tenant-runtime",
|
|
3
|
-
"version": "1.0.0-beta.
|
|
3
|
+
"version": "1.0.0-beta.221",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"homepage": "https://aglyn.com",
|
|
6
6
|
"repository": {
|
|
@@ -25,8 +25,8 @@
|
|
|
25
25
|
"./package.json": "./package.json"
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@aglyn/aglyn": "1.0.0-beta.
|
|
29
|
-
"@aglyn/tenant-data-admin": "1.0.0-beta.
|
|
28
|
+
"@aglyn/aglyn": "1.0.0-beta.221",
|
|
29
|
+
"@aglyn/tenant-data-admin": "1.0.0-beta.221",
|
|
30
30
|
"@swc/helpers": "0.5.23"
|
|
31
31
|
},
|
|
32
32
|
"peerDependencies": {
|
|
@@ -16,6 +16,7 @@ import { _ as _extends } from "@swc/helpers/_/_extends";
|
|
|
16
16
|
* limitations under the License.
|
|
17
17
|
*/ import * as Aglyn from "@aglyn/aglyn/server";
|
|
18
18
|
import { getHostDocAdmin, getOrgForHost } from "@aglyn/tenant-data-admin";
|
|
19
|
+
import { leavingNoticeSignatures } from "@aglyn/tenant-data-admin/server/leaving-notice";
|
|
19
20
|
/**
|
|
20
21
|
* Where the entries a gated tree links to are served (AGL-3118), or
|
|
21
22
|
* `undefined` when it names none that are live.
|
|
@@ -121,9 +122,23 @@ import { getHostDocAdmin, getOrgForHost } from "@aglyn/tenant-data-admin";
|
|
|
121
122
|
nodes
|
|
122
123
|
});
|
|
123
124
|
const entryRoutes = await entryRoutesPromise;
|
|
124
|
-
|
|
125
|
+
// The leaving notice's signatures for this tree (AGL-3452): the page was
|
|
126
|
+
// signed before the gate opened, from a payload that had no tree, so the
|
|
127
|
+
// outside links the visitor just unlocked are signed here.
|
|
128
|
+
const leavingSignatures = leavingNoticeSignatures({
|
|
129
|
+
hostId,
|
|
130
|
+
site: host,
|
|
131
|
+
org: orgRes == null ? void 0 : orgRes.org,
|
|
132
|
+
content: {
|
|
133
|
+
nodes,
|
|
134
|
+
enriched: enriched.props
|
|
135
|
+
}
|
|
136
|
+
});
|
|
137
|
+
return _extends({}, enriched.props, entryRoutes ? {
|
|
125
138
|
entryRoutes
|
|
126
|
-
}
|
|
139
|
+
} : {}, leavingSignatures ? {
|
|
140
|
+
leavingSignatures
|
|
141
|
+
} : {});
|
|
127
142
|
} catch (error) {
|
|
128
143
|
console.error('gated page enrichment failed', error);
|
|
129
144
|
return {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../libs/tenant/runtime/src/lib/enrich-gated-page.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport * as Aglyn from '@aglyn/aglyn/server'\nimport { getHostDocAdmin, getOrgForHost } from '@aglyn/tenant-data-admin'\n\n/**\n * Where the entries a gated tree links to are served (AGL-3118), or\n * `undefined` when it names none that are live.\n *\n * The page's routing map was built before the gate opened, from a tree it\n * did not have, so it holds no entry a gated page links to; these travel\n * with the nodes for the reason the enricher slice does. A tree that names\n * no entry costs no read.\n *\n * Never rejects, so the caller can start it early and abandon it on a\n * failure of its own.\n *\n * The two readers it needs are loaded HERE rather than imported at the top of\n * this file. Both reach `withRenderCache` and through it `next/cache`, which\n * drags Next's server runtime into the module graph of everything that\n * imports this enricher — including the commerce plugin, whose specs then\n * fail to load at all. Loading them inside the one branch that reads also\n * means a gated tree naming no entry pays for neither.\n */\nasync function gatedEntryLinkRoutes(\n hostId: string,\n nodes: unknown,\n): Promise<Record<string, string> | undefined> {\n try {\n const refs = Aglyn.collectEntryLinkRefs({\n nodes: [nodes as Record<string, unknown> | null],\n })\n if (!refs.length) return undefined\n const [{ getTemplateScreenRouting }, { resolveEntryLinkRoutes }] =\n await Promise.all([\n import('./template-screens'),\n import('./entry-link-routes'),\n ])\n const routing = await getTemplateScreenRouting({ hostId })\n const routes = await resolveEntryLinkRoutes({\n hostId,\n refs,\n collectionSlugs: routing.collectionListings,\n })\n return Object.keys(routes).length ? routes : undefined\n } catch (error) {\n console.error('gated page entry links failed', error)\n return undefined\n }\n}\n\n/**\n * The enricher slice for a screen whose nodes are withheld from the page and\n * fetched after a gate opens (AGL-2510) — a password-protected screen\n * (AGL-87) and a members-only one (AGL-109).\n *\n * ## Why these two need their own call\n *\n * Every other rendered page gets its enricher props from the loader, but\n * these two deliberately ship `nodes: null`: embedding a gated tree in static\n * HTML would publish the very content the gate exists to withhold. So the\n * page arrives with the built-in prompt and no site chrome at all, and the\n * composed tree — the site's shared layout, nav and footer included — is\n * swapped in by the client once the visitor gets past the gate. A nav menu\n * built from primitives opens through `clientAutomations`, which is enricher\n * output, so without this the unlocked page renders the site's nav and none\n * of its behavior.\n *\n * Delivering it WITH the nodes is what keeps the gate honest. The slice is\n * derived from the withheld tree and describes its structure; shipping it in\n * the public HTML alongside `nodes: null` would leak an outline of the page\n * to anyone who never answers the prompt.\n *\n * ## The path\n *\n * Taken from the host's own routing map rather than from the caller, because\n * both callers are POST endpoints a visitor controls: a supplied path would\n * let anyone pick which overlays and path-scoped automations a gated page\n * runs. A screen missing from the map (never routed) gets the site root,\n * which is what an unrouted screen's own address would be.\n *\n * ## The entry links\n *\n * `entryRoutes` rides along when the tree links to a live content entry\n * (AGL-3118), and the client adds those keys to the page's routing map — see\n * {@link gatedEntryLinkRoutes}.\n *\n * Fail-open to `{}` — an enricher slice is behavior on top of a page, and no\n * failure here may cost a visitor the content they just unlocked.\n */\nexport async function enrichGatedScreenPage(options: {\n hostId: string\n screenId: string\n screen: any\n nodes: any\n /**\n * The site document, when the caller already read it to compose `nodes`\n * (AGL-2883). Read here when absent.\n */\n host?: Record<string, unknown> | null\n}): Promise<Record<string, unknown>> {\n const { hostId, screenId, screen, nodes } = options\n try {\n // Started first: its reads share nothing with the enrichers'.\n const entryRoutesPromise = gatedEntryLinkRoutes(hostId, nodes)\n const [host, orgRes] = await Promise.all([\n options.host !== undefined ? options.host : getHostDocAdmin(hostId),\n getOrgForHost(hostId),\n ])\n const routing = ((host as { screens?: Record<string, string> })?.screens ??\n {}) as Record<string, string>\n const path = routing[screenId] || Aglyn.SCREEN_ROOT_PATH\n const enriched = await Aglyn.runSitePageEnrichers({\n hostId,\n host,\n org: orgRes?.org,\n path,\n slugSegments: path.split('/').filter(Boolean),\n screenId,\n screen,\n nodes,\n })\n const entryRoutes = await entryRoutesPromise\n
|
|
1
|
+
{"version":3,"sources":["../../../../../../libs/tenant/runtime/src/lib/enrich-gated-page.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport * as Aglyn from '@aglyn/aglyn/server'\nimport { getHostDocAdmin, getOrgForHost } from '@aglyn/tenant-data-admin'\nimport { leavingNoticeSignatures } from '@aglyn/tenant-data-admin/server/leaving-notice'\n\n/**\n * Where the entries a gated tree links to are served (AGL-3118), or\n * `undefined` when it names none that are live.\n *\n * The page's routing map was built before the gate opened, from a tree it\n * did not have, so it holds no entry a gated page links to; these travel\n * with the nodes for the reason the enricher slice does. A tree that names\n * no entry costs no read.\n *\n * Never rejects, so the caller can start it early and abandon it on a\n * failure of its own.\n *\n * The two readers it needs are loaded HERE rather than imported at the top of\n * this file. Both reach `withRenderCache` and through it `next/cache`, which\n * drags Next's server runtime into the module graph of everything that\n * imports this enricher — including the commerce plugin, whose specs then\n * fail to load at all. Loading them inside the one branch that reads also\n * means a gated tree naming no entry pays for neither.\n */\nasync function gatedEntryLinkRoutes(\n hostId: string,\n nodes: unknown,\n): Promise<Record<string, string> | undefined> {\n try {\n const refs = Aglyn.collectEntryLinkRefs({\n nodes: [nodes as Record<string, unknown> | null],\n })\n if (!refs.length) return undefined\n const [{ getTemplateScreenRouting }, { resolveEntryLinkRoutes }] =\n await Promise.all([\n import('./template-screens'),\n import('./entry-link-routes'),\n ])\n const routing = await getTemplateScreenRouting({ hostId })\n const routes = await resolveEntryLinkRoutes({\n hostId,\n refs,\n collectionSlugs: routing.collectionListings,\n })\n return Object.keys(routes).length ? routes : undefined\n } catch (error) {\n console.error('gated page entry links failed', error)\n return undefined\n }\n}\n\n/**\n * The enricher slice for a screen whose nodes are withheld from the page and\n * fetched after a gate opens (AGL-2510) — a password-protected screen\n * (AGL-87) and a members-only one (AGL-109).\n *\n * ## Why these two need their own call\n *\n * Every other rendered page gets its enricher props from the loader, but\n * these two deliberately ship `nodes: null`: embedding a gated tree in static\n * HTML would publish the very content the gate exists to withhold. So the\n * page arrives with the built-in prompt and no site chrome at all, and the\n * composed tree — the site's shared layout, nav and footer included — is\n * swapped in by the client once the visitor gets past the gate. A nav menu\n * built from primitives opens through `clientAutomations`, which is enricher\n * output, so without this the unlocked page renders the site's nav and none\n * of its behavior.\n *\n * Delivering it WITH the nodes is what keeps the gate honest. The slice is\n * derived from the withheld tree and describes its structure; shipping it in\n * the public HTML alongside `nodes: null` would leak an outline of the page\n * to anyone who never answers the prompt.\n *\n * ## The path\n *\n * Taken from the host's own routing map rather than from the caller, because\n * both callers are POST endpoints a visitor controls: a supplied path would\n * let anyone pick which overlays and path-scoped automations a gated page\n * runs. A screen missing from the map (never routed) gets the site root,\n * which is what an unrouted screen's own address would be.\n *\n * ## The entry links\n *\n * `entryRoutes` rides along when the tree links to a live content entry\n * (AGL-3118), and the client adds those keys to the page's routing map — see\n * {@link gatedEntryLinkRoutes}.\n *\n * Fail-open to `{}` — an enricher slice is behavior on top of a page, and no\n * failure here may cost a visitor the content they just unlocked.\n */\nexport async function enrichGatedScreenPage(options: {\n hostId: string\n screenId: string\n screen: any\n nodes: any\n /**\n * The site document, when the caller already read it to compose `nodes`\n * (AGL-2883). Read here when absent.\n */\n host?: Record<string, unknown> | null\n}): Promise<Record<string, unknown>> {\n const { hostId, screenId, screen, nodes } = options\n try {\n // Started first: its reads share nothing with the enrichers'.\n const entryRoutesPromise = gatedEntryLinkRoutes(hostId, nodes)\n const [host, orgRes] = await Promise.all([\n options.host !== undefined ? options.host : getHostDocAdmin(hostId),\n getOrgForHost(hostId),\n ])\n const routing = ((host as { screens?: Record<string, string> })?.screens ??\n {}) as Record<string, string>\n const path = routing[screenId] || Aglyn.SCREEN_ROOT_PATH\n const enriched = await Aglyn.runSitePageEnrichers({\n hostId,\n host,\n org: orgRes?.org,\n path,\n slugSegments: path.split('/').filter(Boolean),\n screenId,\n screen,\n nodes,\n })\n const entryRoutes = await entryRoutesPromise\n // The leaving notice's signatures for this tree (AGL-3452): the page was\n // signed before the gate opened, from a payload that had no tree, so the\n // outside links the visitor just unlocked are signed here.\n const leavingSignatures = leavingNoticeSignatures({\n hostId,\n site: host as { subdomain?: string | null; cname?: string | null } | null,\n org: orgRes?.org,\n content: { nodes, enriched: enriched.props },\n })\n return {\n ...enriched.props,\n ...(entryRoutes ? { entryRoutes } : {}),\n ...(leavingSignatures ? { leavingSignatures } : {}),\n }\n } catch (error) {\n console.error('gated page enrichment failed', error)\n return {}\n }\n}\n\nexport default enrichGatedScreenPage\n"],"names":["Aglyn","getHostDocAdmin","getOrgForHost","leavingNoticeSignatures","gatedEntryLinkRoutes","hostId","nodes","refs","collectEntryLinkRefs","length","undefined","getTemplateScreenRouting","resolveEntryLinkRoutes","Promise","all","routing","routes","collectionSlugs","collectionListings","Object","keys","error","console","enrichGatedScreenPage","options","screenId","screen","entryRoutesPromise","host","orgRes","screens","path","SCREEN_ROOT_PATH","enriched","runSitePageEnrichers","org","slugSegments","split","filter","Boolean","entryRoutes","leavingSignatures","site","content","props"],"mappings":";AAAA;;;;;;;;;;;;;;;CAeC,GAED,YAAYA,WAAW,sBAAqB;AAC5C,SAASC,eAAe,EAAEC,aAAa,QAAQ,2BAA0B;AACzE,SAASC,uBAAuB,QAAQ,iDAAgD;AAExF;;;;;;;;;;;;;;;;;;CAkBC,GACD,eAAeC,qBACbC,MAAc,EACdC,KAAc;IAEd,IAAI;QACF,MAAMC,OAAOP,MAAMQ,oBAAoB,CAAC;YACtCF,OAAO;gBAACA;aAAwC;QAClD;QACA,IAAI,CAACC,KAAKE,MAAM,EAAE,OAAOC;QACzB,MAAM,CAAC,EAAEC,wBAAwB,EAAE,EAAE,EAAEC,sBAAsB,EAAE,CAAC,GAC9D,MAAMC,QAAQC,GAAG,CAAC;YAChB,MAAM,CAAC;YACP,MAAM,CAAC;SACR;QACH,MAAMC,UAAU,MAAMJ,yBAAyB;YAAEN;QAAO;QACxD,MAAMW,SAAS,MAAMJ,uBAAuB;YAC1CP;YACAE;YACAU,iBAAiBF,QAAQG,kBAAkB;QAC7C;QACA,OAAOC,OAAOC,IAAI,CAACJ,QAAQP,MAAM,GAAGO,SAASN;IAC/C,EAAE,OAAOW,OAAO;QACdC,QAAQD,KAAK,CAAC,iCAAiCA;QAC/C,OAAOX;IACT;AACF;AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAsCC,GACD,OAAO,eAAea,sBAAsBC,OAU3C;IACC,MAAM,EAAEnB,MAAM,EAAEoB,QAAQ,EAAEC,MAAM,EAAEpB,KAAK,EAAE,GAAGkB;IAC5C,IAAI;;QACF,8DAA8D;QAC9D,MAAMG,qBAAqBvB,qBAAqBC,QAAQC;QACxD,MAAM,CAACsB,MAAMC,OAAO,GAAG,MAAMhB,QAAQC,GAAG,CAAC;YACvCU,QAAQI,IAAI,KAAKlB,YAAYc,QAAQI,IAAI,GAAG3B,gBAAgBI;YAC5DH,cAAcG;SACf;QACD,MAAMU,kBAAYa,wBAAD,AAACA,KAA+CE,OAAO,mBACtE,CAAC;QACH,MAAMC,OAAOhB,OAAO,CAACU,SAAS,IAAIzB,MAAMgC,gBAAgB;QACxD,MAAMC,WAAW,MAAMjC,MAAMkC,oBAAoB,CAAC;YAChD7B;YACAuB;YACAO,GAAG,EAAEN,0BAAAA,OAAQM,GAAG;YAChBJ;YACAK,cAAcL,KAAKM,KAAK,CAAC,KAAKC,MAAM,CAACC;YACrCd;YACAC;YACApB;QACF;QACA,MAAMkC,cAAc,MAAMb;QAC1B,yEAAyE;QACzE,yEAAyE;QACzE,2DAA2D;QAC3D,MAAMc,oBAAoBtC,wBAAwB;YAChDE;YACAqC,MAAMd;YACNO,GAAG,EAAEN,0BAAAA,OAAQM,GAAG;YAChBQ,SAAS;gBAAErC;gBAAO2B,UAAUA,SAASW,KAAK;YAAC;QAC7C;QACA,OAAO,aACFX,SAASW,KAAK,EACbJ,cAAc;YAAEA;QAAY,IAAI,CAAC,GACjCC,oBAAoB;YAAEA;QAAkB,IAAI,CAAC;IAErD,EAAE,OAAOpB,OAAO;QACdC,QAAQD,KAAK,CAAC,gCAAgCA;QAC9C,OAAO,CAAC;IACV;AACF;AAEA,eAAeE,sBAAqB"}
|