@kywi-software/core 0.15.0 → 0.15.1
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/AGENT-PATTERNS.md +47 -0
- package/dist/admin/audience-editor.d.ts +2 -0
- package/dist/admin/audience-editor.d.ts.map +1 -1
- package/dist/admin/audience-editor.js +4 -2
- package/dist/admin/audience-editor.js.map +1 -1
- package/dist/admin/condition-builder.d.ts.map +1 -1
- package/dist/admin/condition-builder.js +16 -3
- package/dist/admin/condition-builder.js.map +1 -1
- package/dist/admin/rule-tester.d.ts +1 -0
- package/dist/admin/rule-tester.d.ts.map +1 -1
- package/dist/admin/rule-tester.js +7 -4
- package/dist/admin/rule-tester.js.map +1 -1
- package/dist/admin/signal-options.d.ts +17 -0
- package/dist/admin/signal-options.d.ts.map +1 -1
- package/dist/admin/signal-options.js +28 -0
- package/dist/admin/signal-options.js.map +1 -1
- package/dist/admin/surfaces/audiences/audiences-data.d.ts +5 -0
- package/dist/admin/surfaces/audiences/audiences-data.d.ts.map +1 -1
- package/dist/admin/surfaces/audiences/audiences-data.js +3 -0
- package/dist/admin/surfaces/audiences/audiences-data.js.map +1 -1
- package/dist/api/api-key-routes.js +2 -2
- package/dist/api/api-key-routes.js.map +1 -1
- package/dist/api/audience-routes.d.ts.map +1 -1
- package/dist/api/audience-routes.js +10 -4
- package/dist/api/audience-routes.js.map +1 -1
- package/dist/api/audience-runtime-routes.d.ts +17 -0
- package/dist/api/audience-runtime-routes.d.ts.map +1 -1
- package/dist/api/audience-runtime-routes.js +474 -23
- package/dist/api/audience-runtime-routes.js.map +1 -1
- package/dist/api/ax-routes.d.ts.map +1 -1
- package/dist/api/ax-routes.js +7 -3
- package/dist/api/ax-routes.js.map +1 -1
- package/dist/api/category-routes.js +3 -3
- package/dist/api/category-routes.js.map +1 -1
- package/dist/api/changeset-routes.js +2 -2
- package/dist/api/changeset-routes.js.map +1 -1
- package/dist/api/comment-routes.js +4 -4
- package/dist/api/comment-routes.js.map +1 -1
- package/dist/api/component-routes.js +3 -3
- package/dist/api/component-routes.js.map +1 -1
- package/dist/api/config-routes.js +4 -4
- package/dist/api/config-routes.js.map +1 -1
- package/dist/api/content-permission-routes.js +2 -2
- package/dist/api/content-permission-routes.js.map +1 -1
- package/dist/api/content-routes.d.ts.map +1 -1
- package/dist/api/content-routes.js +8 -3
- package/dist/api/content-routes.js.map +1 -1
- package/dist/api/content-type-routes.js +3 -3
- package/dist/api/content-type-routes.js.map +1 -1
- package/dist/api/experiment-routes.js +2 -2
- package/dist/api/experiment-routes.js.map +1 -1
- package/dist/api/extension-routes.js +4 -4
- package/dist/api/extension-routes.js.map +1 -1
- package/dist/api/feed-routes.js +2 -2
- package/dist/api/feed-routes.js.map +1 -1
- package/dist/api/form-routes.js +2 -2
- package/dist/api/form-routes.js.map +1 -1
- package/dist/api/group-routes.js +3 -3
- package/dist/api/group-routes.js.map +1 -1
- package/dist/api/index.d.ts.map +1 -1
- package/dist/api/index.js +4 -1
- package/dist/api/index.js.map +1 -1
- package/dist/api/layout-routes.d.ts +19 -1
- package/dist/api/layout-routes.d.ts.map +1 -1
- package/dist/api/layout-routes.js +65 -5
- package/dist/api/layout-routes.js.map +1 -1
- package/dist/api/layout-write-guard.d.ts +3 -2
- package/dist/api/layout-write-guard.d.ts.map +1 -1
- package/dist/api/layout-write-guard.js +12 -4
- package/dist/api/layout-write-guard.js.map +1 -1
- package/dist/api/media-routes.d.ts.map +1 -1
- package/dist/api/media-routes.js +50 -9
- package/dist/api/media-routes.js.map +1 -1
- package/dist/api/menu-routes.js +2 -2
- package/dist/api/menu-routes.js.map +1 -1
- package/dist/api/nav-routes.js +3 -3
- package/dist/api/nav-routes.js.map +1 -1
- package/dist/api/oauth-routes.js +2 -2
- package/dist/api/oauth-routes.js.map +1 -1
- package/dist/api/openapi.d.ts.map +1 -1
- package/dist/api/openapi.js +14 -1
- package/dist/api/openapi.js.map +1 -1
- package/dist/api/pagination.d.ts +10 -0
- package/dist/api/pagination.d.ts.map +1 -1
- package/dist/api/pagination.js +7 -1
- package/dist/api/pagination.js.map +1 -1
- package/dist/api/response.d.ts +29 -0
- package/dist/api/response.d.ts.map +1 -1
- package/dist/api/response.js +23 -3
- package/dist/api/response.js.map +1 -1
- package/dist/api/search-routes.d.ts.map +1 -1
- package/dist/api/search-routes.js +17 -3
- package/dist/api/search-routes.js.map +1 -1
- package/dist/api/section-template-routes.js +2 -2
- package/dist/api/section-template-routes.js.map +1 -1
- package/dist/api/site-routes.js +2 -2
- package/dist/api/site-routes.js.map +1 -1
- package/dist/api/tag-routes.d.ts.map +1 -1
- package/dist/api/tag-routes.js +2 -2
- package/dist/api/tag-routes.js.map +1 -1
- package/dist/api/user-routes.js +2 -2
- package/dist/api/user-routes.js.map +1 -1
- package/dist/api/version-routes.js +2 -2
- package/dist/api/version-routes.js.map +1 -1
- package/dist/api/webhook-routes.js +3 -3
- package/dist/api/webhook-routes.js.map +1 -1
- package/dist/api/workflow-routes.d.ts.map +1 -1
- package/dist/api/workflow-routes.js +15 -6
- package/dist/api/workflow-routes.js.map +1 -1
- package/dist/audiences/collectors/index.d.ts +8 -4
- package/dist/audiences/collectors/index.d.ts.map +1 -1
- package/dist/audiences/collectors/index.js +17 -4
- package/dist/audiences/collectors/index.js.map +1 -1
- package/dist/audiences/collectors/selfid.d.ts +25 -0
- package/dist/audiences/collectors/selfid.d.ts.map +1 -0
- package/dist/audiences/collectors/selfid.js +46 -0
- package/dist/audiences/collectors/selfid.js.map +1 -0
- package/dist/audiences/collectors/session.d.ts +41 -0
- package/dist/audiences/collectors/session.d.ts.map +1 -0
- package/dist/audiences/collectors/session.js +50 -0
- package/dist/audiences/collectors/session.js.map +1 -0
- package/dist/audiences/consent.d.ts +13 -0
- package/dist/audiences/consent.d.ts.map +1 -1
- package/dist/audiences/consent.js +13 -0
- package/dist/audiences/consent.js.map +1 -1
- package/dist/audiences/cookies.d.ts +21 -0
- package/dist/audiences/cookies.d.ts.map +1 -1
- package/dist/audiences/cookies.js +26 -0
- package/dist/audiences/cookies.js.map +1 -1
- package/dist/audiences/engine.d.ts.map +1 -1
- package/dist/audiences/engine.js +1 -0
- package/dist/audiences/engine.js.map +1 -1
- package/dist/audiences/entry-page.d.ts +89 -0
- package/dist/audiences/entry-page.d.ts.map +1 -0
- package/dist/audiences/entry-page.js +116 -0
- package/dist/audiences/entry-page.js.map +1 -0
- package/dist/audiences/evaluator/instant-match.d.ts.map +1 -1
- package/dist/audiences/evaluator/instant-match.js +7 -0
- package/dist/audiences/evaluator/instant-match.js.map +1 -1
- package/dist/audiences/index.d.ts +3 -2
- package/dist/audiences/index.d.ts.map +1 -1
- package/dist/audiences/index.js +6 -2
- package/dist/audiences/index.js.map +1 -1
- package/dist/audiences/queries.d.ts +16 -0
- package/dist/audiences/queries.d.ts.map +1 -1
- package/dist/audiences/queries.js +28 -1
- package/dist/audiences/queries.js.map +1 -1
- package/dist/audiences/schema.d.ts +17 -0
- package/dist/audiences/schema.d.ts.map +1 -1
- package/dist/audiences/schema.js +7 -0
- package/dist/audiences/schema.js.map +1 -1
- package/dist/audiences/server-eval.d.ts +19 -0
- package/dist/audiences/server-eval.d.ts.map +1 -1
- package/dist/audiences/server-eval.js +17 -1
- package/dist/audiences/server-eval.js.map +1 -1
- package/dist/audiences/types.d.ts +22 -1
- package/dist/audiences/types.d.ts.map +1 -1
- package/dist/audiences/types.js +1 -0
- package/dist/audiences/types.js.map +1 -1
- package/dist/ax/content-source.d.ts +10 -2
- package/dist/ax/content-source.d.ts.map +1 -1
- package/dist/ax/content-source.js +81 -5
- package/dist/ax/content-source.js.map +1 -1
- package/dist/ax/effective-body.d.ts +28 -0
- package/dist/ax/effective-body.d.ts.map +1 -0
- package/dist/ax/effective-body.js +47 -0
- package/dist/ax/effective-body.js.map +1 -0
- package/dist/ax/index.d.ts +3 -1
- package/dist/ax/index.d.ts.map +1 -1
- package/dist/ax/index.js +2 -0
- package/dist/ax/index.js.map +1 -1
- package/dist/ax/jsonld.d.ts +31 -1
- package/dist/ax/jsonld.d.ts.map +1 -1
- package/dist/ax/jsonld.js +35 -22
- package/dist/ax/jsonld.js.map +1 -1
- package/dist/ax/layout-to-html.d.ts +127 -0
- package/dist/ax/layout-to-html.d.ts.map +1 -0
- package/dist/ax/layout-to-html.js +545 -0
- package/dist/ax/layout-to-html.js.map +1 -0
- package/dist/ax/llms-full-txt.d.ts +3 -1
- package/dist/ax/llms-full-txt.d.ts.map +1 -1
- package/dist/ax/llms-full-txt.js +5 -2
- package/dist/ax/llms-full-txt.js.map +1 -1
- package/dist/ax/page-markdown.d.ts +10 -2
- package/dist/ax/page-markdown.d.ts.map +1 -1
- package/dist/ax/page-markdown.js +16 -3
- package/dist/ax/page-markdown.js.map +1 -1
- package/dist/ax/summary.d.ts +4 -0
- package/dist/ax/summary.d.ts.map +1 -1
- package/dist/ax/summary.js +6 -1
- package/dist/ax/summary.js.map +1 -1
- package/dist/ax/types.d.ts +24 -0
- package/dist/ax/types.d.ts.map +1 -1
- package/dist/cache/content-invalidation.d.ts.map +1 -1
- package/dist/cache/content-invalidation.js +11 -0
- package/dist/cache/content-invalidation.js.map +1 -1
- package/dist/db/apply-snapshot.d.ts +7 -0
- package/dist/db/apply-snapshot.d.ts.map +1 -1
- package/dist/db/apply-snapshot.js +7 -0
- package/dist/db/apply-snapshot.js.map +1 -1
- package/dist/db/ax-queries.d.ts +6 -0
- package/dist/db/ax-queries.d.ts.map +1 -1
- package/dist/db/ax-queries.js +6 -0
- package/dist/db/ax-queries.js.map +1 -1
- package/dist/db/content-queries.d.ts.map +1 -1
- package/dist/db/content-queries.js +8 -0
- package/dist/db/content-queries.js.map +1 -1
- package/dist/db/layout-queries.d.ts +19 -2
- package/dist/db/layout-queries.d.ts.map +1 -1
- package/dist/db/layout-queries.js +11 -3
- package/dist/db/layout-queries.js.map +1 -1
- package/dist/db/search-queries.d.ts.map +1 -1
- package/dist/db/search-queries.js +24 -1
- package/dist/db/search-queries.js.map +1 -1
- package/dist/hooks/ax-invalidation.d.ts.map +1 -1
- package/dist/hooks/ax-invalidation.js +4 -0
- package/dist/hooks/ax-invalidation.js.map +1 -1
- package/dist/layout/index.d.ts +3 -1
- package/dist/layout/index.d.ts.map +1 -1
- package/dist/layout/index.js +3 -1
- package/dist/layout/index.js.map +1 -1
- package/dist/layout/module-permissions.d.ts.map +1 -1
- package/dist/layout/module-permissions.js +2 -38
- package/dist/layout/module-permissions.js.map +1 -1
- package/dist/layout/seed-defaults.d.ts +45 -0
- package/dist/layout/seed-defaults.d.ts.map +1 -0
- package/dist/layout/seed-defaults.js +75 -0
- package/dist/layout/seed-defaults.js.map +1 -0
- package/dist/layout/walk.d.ts +14 -0
- package/dist/layout/walk.d.ts.map +1 -0
- package/dist/layout/walk.js +49 -0
- package/dist/layout/walk.js.map +1 -0
- package/dist/media/index.d.ts +1 -1
- package/dist/media/index.d.ts.map +1 -1
- package/dist/media/index.js +1 -1
- package/dist/media/index.js.map +1 -1
- package/dist/media/upload-allowlist.d.ts +23 -0
- package/dist/media/upload-allowlist.d.ts.map +1 -1
- package/dist/media/upload-allowlist.js +29 -0
- package/dist/media/upload-allowlist.js.map +1 -1
- package/dist/schema/mysql-tables.d.ts +17 -0
- package/dist/schema/mysql-tables.d.ts.map +1 -1
- package/dist/schema/mysql-tables.js +2 -0
- package/dist/schema/mysql-tables.js.map +1 -1
- package/dist/scope/jsonld.d.ts +18 -3
- package/dist/scope/jsonld.d.ts.map +1 -1
- package/dist/scope/jsonld.js +6 -4
- package/dist/scope/jsonld.js.map +1 -1
- package/package.json +6 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"layout-queries.d.ts","sourceRoot":"","sources":["../../src/db/layout-queries.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AACzC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAA;AAQxD;;;GAGG;AACH,wBAAsB,gBAAgB,CACpC,EAAE,EAAE,MAAM,EACV,SAAS,EAAE,MAAM,EACjB,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAahC;AAcD
|
|
1
|
+
{"version":3,"file":"layout-queries.d.ts","sourceRoot":"","sources":["../../src/db/layout-queries.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AACzC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAA;AAQxD;;;GAGG;AACH,wBAAsB,gBAAgB,CACpC,EAAE,EAAE,MAAM,EACV,SAAS,EAAE,MAAM,EACjB,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAahC;AAcD;;;;;;;;;;GAUG;AACH,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,MAAM,CAAA;IACZ,eAAe,EAAE,MAAM,CAAA;CACxB;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,gBAAgB,CACpC,EAAE,EAAE,MAAM,EACV,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,cAAc,GAAG,IAAI,EAC7B,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAuCnC"}
|
|
@@ -36,7 +36,8 @@ async function runInTransaction(db, fn) {
|
|
|
36
36
|
}
|
|
37
37
|
/**
|
|
38
38
|
* Persist a LayoutDocument to the layout JSONB column for a content node.
|
|
39
|
-
* Returns
|
|
39
|
+
* Returns the written row's identity, or null when no row matched the
|
|
40
|
+
* (id, siteId) scope.
|
|
40
41
|
*
|
|
41
42
|
* This is the one and only PAGE layout write path (a blueprint's goes through
|
|
42
43
|
* `setSectionTemplateDefinition`, kywi-cms#156), which is why it also maintains
|
|
@@ -60,6 +61,9 @@ export async function setContentLayout(db, contentId, layout, siteId) {
|
|
|
60
61
|
.select({
|
|
61
62
|
siteId: kywiContent.siteId,
|
|
62
63
|
contentTypeName: kywiContent.contentTypeName,
|
|
64
|
+
// Read for the CALLER's cache invalidation, not for this write — see
|
|
65
|
+
// LayoutWriteResult.
|
|
66
|
+
slug: kywiContent.slug,
|
|
63
67
|
layout: kywiContent.layout,
|
|
64
68
|
})
|
|
65
69
|
.from(kywiContent)
|
|
@@ -67,7 +71,7 @@ export async function setContentLayout(db, contentId, layout, siteId) {
|
|
|
67
71
|
.for('update')
|
|
68
72
|
.limit(1);
|
|
69
73
|
if (!existing)
|
|
70
|
-
return
|
|
74
|
+
return null;
|
|
71
75
|
await tx
|
|
72
76
|
.update(kywiContent)
|
|
73
77
|
.set({ layout: (layout ?? null), updatedAt: new Date() })
|
|
@@ -78,7 +82,11 @@ export async function setContentLayout(db, contentId, layout, siteId) {
|
|
|
78
82
|
before: (existing.layout ?? null),
|
|
79
83
|
after: layout,
|
|
80
84
|
});
|
|
81
|
-
return
|
|
85
|
+
return {
|
|
86
|
+
siteId: existing.siteId,
|
|
87
|
+
slug: existing.slug ?? '',
|
|
88
|
+
contentTypeName: existing.contentTypeName,
|
|
89
|
+
};
|
|
82
90
|
});
|
|
83
91
|
}
|
|
84
92
|
//# sourceMappingURL=layout-queries.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"layout-queries.js","sourceRoot":"","sources":["../../src/db/layout-queries.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,GAAG,EAAE,MAAM,aAAa,CAAA;AACrC,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAG/C,OAAO,EAAE,sBAAsB,EAAE,MAAM,iCAAiC,CAAA;AAExE,iFAAiF;AACjF,gFAAgF;AAChF,+EAA+E;AAC/E,gFAAgF;AAEhF;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,EAAU,EACV,SAAiB,EACjB,MAAe;IAEf,MAAM,CAAC,GAAG,CAAC,GAAG,MAAM,EAAE;SACnB,MAAM,CAAC,EAAE,MAAM,EAAE,WAAW,CAAC,MAAM,EAAE,CAAC;SACtC,IAAI,CAAC,WAAW,CAAC;SACjB,KAAK,CAAC,MAAM,KAAK,SAAS;QACzB,CAAC,CAAC,EAAE,CAAC,WAAW,CAAC,EAAE,EAAE,SAAS,CAAC;QAC/B,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,WAAW,CAAC,EAAE,EAAE,SAAS,CAAC,EAAE,EAAE,CAAC,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;SACtE,KAAK,CAAC,CAAC,CAAC,CAAA;IAEX,IAAI,CAAC,GAAG;QAAE,OAAO,IAAI,CAAA;IACrB,IAAI,CAAC,GAAG,CAAC,MAAM;QAAE,OAAO,IAAI,CAAA;IAE5B,OAAO,GAAG,CAAC,MAAwB,CAAA;AACrC,CAAC;AAED;;;;GAIG;AACH,KAAK,UAAU,gBAAgB,CAAI,EAAU,EAAE,EAA8B;IAC3E,IAAI,aAAa,IAAI,EAAE,IAAI,OAAQ,EAAgC,CAAC,WAAW,KAAK,UAAU,EAAE,CAAC;QAC/F,OAAQ,EAA4E,CAAC,WAAW,CAAC,EAAE,CAAC,CAAA;IACtG,CAAC;IACD,OAAO,EAAE,CAAC,EAAE,CAAC,CAAA;AACf,CAAC;
|
|
1
|
+
{"version":3,"file":"layout-queries.js","sourceRoot":"","sources":["../../src/db/layout-queries.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"search-queries.d.ts","sourceRoot":"","sources":["../../src/db/search-queries.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"search-queries.d.ts","sourceRoot":"","sources":["../../src/db/search-queries.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAEzC,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;IACZ,eAAe,EAAE,MAAM,CAAA;IACvB,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB,WAAW,EAAE,IAAI,GAAG,IAAI,CAAA;CACzB;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAA;IACd,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAChC,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC3B,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC3B,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC1B,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC3B;;;;;OAKG;IACH,eAAe,CAAC,EAAE,OAAO,GAAG,SAAS,CAAA;CACtC;AAED;;;GAGG;AACH,wBAAsB,aAAa,CACjC,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,aAAa,GAClB,OAAO,CAAC;IAAE,OAAO,EAAE,YAAY,EAAE,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CA+ErD"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { sql, eq, and } from 'drizzle-orm';
|
|
2
2
|
import { kywiContent } from '../schema/base.js';
|
|
3
|
+
import { summaryFor } from '../ax/summary.js';
|
|
3
4
|
/**
|
|
4
5
|
* Full-text search across title, body, and summary using PostgreSQL tsvector/tsquery.
|
|
5
6
|
* Returns ranked results ordered by relevance descending.
|
|
@@ -47,6 +48,13 @@ export async function searchContent(db, query, opts) {
|
|
|
47
48
|
contentTypeName: kywiContent.contentTypeName,
|
|
48
49
|
status: kywiContent.status,
|
|
49
50
|
summary: kywiContent.summary,
|
|
51
|
+
// Read only so an empty `summary` can fall back to real copy — see
|
|
52
|
+
// `resultSummary` below (kywi-cms#195). The body is TRUNCATED in the
|
|
53
|
+
// database: a snippet needs the first couple of hundred characters, and
|
|
54
|
+
// shipping whole article bodies for a page of results was pure transfer.
|
|
55
|
+
metaDescription: kywiContent.metaDescription,
|
|
56
|
+
body: sql `substring(coalesce(${kywiContent.body}, '') from 1 for 2000)`,
|
|
57
|
+
layout: kywiContent.layout,
|
|
50
58
|
publishedAt: kywiContent.publishedAt,
|
|
51
59
|
rank: sql `ts_rank(${tsvector}, ${tsquery})`,
|
|
52
60
|
})
|
|
@@ -61,9 +69,24 @@ export async function searchContent(db, query, opts) {
|
|
|
61
69
|
slug: row.slug,
|
|
62
70
|
contentTypeName: row.contentTypeName,
|
|
63
71
|
status: row.status,
|
|
64
|
-
summary: row
|
|
72
|
+
summary: resultSummary(row),
|
|
65
73
|
publishedAt: row.publishedAt,
|
|
66
74
|
}));
|
|
67
75
|
return { results, total };
|
|
68
76
|
}
|
|
77
|
+
/**
|
|
78
|
+
* The snippet a search result shows.
|
|
79
|
+
*
|
|
80
|
+
* A stored `summary` is returned VERBATIM — that is the editor's own words, and
|
|
81
|
+
* every existing caller already renders it. Only when it is empty does this fall
|
|
82
|
+
* back to the shared AX chain (`aiSummary` → `metaDescription` → the effective
|
|
83
|
+
* body), which reaches the page's LAYOUT copy (kywi-cms#195). Before that, a
|
|
84
|
+
* page composed in the layout editor — i.e. every page on a real Kywi site —
|
|
85
|
+
* came back with a null snippet.
|
|
86
|
+
*/
|
|
87
|
+
function resultSummary(row) {
|
|
88
|
+
if (row.summary && row.summary.trim())
|
|
89
|
+
return row.summary;
|
|
90
|
+
return summaryFor(row, 200) || null;
|
|
91
|
+
}
|
|
69
92
|
//# sourceMappingURL=search-queries.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"search-queries.js","sourceRoot":"","sources":["../../src/db/search-queries.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,EAAE,MAAM,aAAa,CAAA;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;
|
|
1
|
+
{"version":3,"file":"search-queries.js","sourceRoot":"","sources":["../../src/db/search-queries.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ax-invalidation.d.ts","sourceRoot":"","sources":["../../src/hooks/ax-invalidation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AACjD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;
|
|
1
|
+
{"version":3,"file":"ax-invalidation.d.ts","sourceRoot":"","sources":["../../src/hooks/ax-invalidation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AACjD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AAe1D;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,aAAa,EAAE,iBAAiB,EAAE,QAAQ,EAAE,YAAY,GAAG,IAAI,CAQjG"}
|
|
@@ -5,6 +5,10 @@ const AX_INVALIDATION_EVENTS = [
|
|
|
5
5
|
'content:afterUpdate',
|
|
6
6
|
'content:afterDelete',
|
|
7
7
|
'content:afterCreate',
|
|
8
|
+
// A layout save changes the page's copy just as a body edit does — and on a
|
|
9
|
+
// real Kywi site it is the ONLY thing that changes it (kywi-cms#195). Emitted
|
|
10
|
+
// by the dedicated layout routes, which are outside the content lifecycle.
|
|
11
|
+
'content:afterLayoutUpdate',
|
|
8
12
|
];
|
|
9
13
|
/**
|
|
10
14
|
* Subscribe AX cache invalidation to the content lifecycle — the single write
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ax-invalidation.js","sourceRoot":"","sources":["../../src/hooks/ax-invalidation.ts"],"names":[],"mappings":"AAGA,mEAAmE;AACnE,MAAM,sBAAsB,GAAG;IAC7B,sBAAsB;IACtB,wBAAwB;IACxB,qBAAqB;IACrB,qBAAqB;IACrB,qBAAqB;
|
|
1
|
+
{"version":3,"file":"ax-invalidation.js","sourceRoot":"","sources":["../../src/hooks/ax-invalidation.ts"],"names":[],"mappings":"AAGA,mEAAmE;AACnE,MAAM,sBAAsB,GAAG;IAC7B,sBAAsB;IACtB,wBAAwB;IACxB,qBAAqB;IACrB,qBAAqB;IACrB,qBAAqB;IACrB,4EAA4E;IAC5E,8EAA8E;IAC9E,2EAA2E;IAC3E,2BAA2B;CAC5B,CAAA;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,kBAAkB,CAAC,aAAgC,EAAE,QAAsB;IACzF,KAAK,MAAM,KAAK,IAAI,sBAAsB,EAAE,CAAC;QAC3C,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,OAAgB,EAAE,EAAE;YAC5C,MAAM,CAAC,GAAG,OAA6C,CAAA;YACvD,MAAM,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC,OAAO,EAAE,MAAM,IAAI,EAAE,CAAC,CAAA;YAC9C,IAAI,MAAM;gBAAE,MAAM,aAAa,CAAC,iBAAiB,CAAC,MAAM,MAAM,IAAI,CAAC,CAAA;QACrE,CAAC,CAAC,CAAA;IACJ,CAAC;AACH,CAAC"}
|
package/dist/layout/index.d.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
export * from './types.js';
|
|
2
2
|
export { collectComponentRefs, diffComponentRefs, rekeyResolvedSection, rekeyResolvedVariantContainer, rekeyResolvedModuleVariantContainer, unrekeyResolvedModuleVariantContainer, isCleanComponentInstance, resolveModulePlacement, applySectionPlacement, applyVariantContainerPlacement, applyModuleVariantContainerPlacement, unapplyModuleVariantContainerPlacement, componentDetachSource, validateComponentDefinition, materializeModuleNode, materializeSectionNode, materializeVariantContainerNode, materializeModuleVariantContainerNode, detachModuleNode, detachSectionNode, detachVariantContainerNode, detachModuleVariantContainerNode, detachComponentFromLayout, resolveComponentPlacements, type ComponentPlacementLookup, type ComponentRef, type ComponentRefKind, type ComponentRefDiff, type ComponentDetachSource, type ComponentDefinitionValidation, type ResolvedModuleDefinition, type DetachResult, } from './component-refs.js';
|
|
3
3
|
export { findLegacyVariantContainers, convertLegacyVariantContainer, migrateLegacyVariantContainers, hasLegacyVariantContainer, LEGACY_VARIANT_CONTAINER_TYPE, LEGACY_ARM_MODULE_TYPE, type LegacyVariantContainerPlacement, type LegacyPlacementScope, type LegacyMigrationOptions, type LegacyMigrationResult, } from './legacy-variant-container.js';
|
|
4
|
-
export { createModuleRegistry, BUILT_IN_MODULES, type ModuleRegistry, type ModuleRegistryEntry } from './registry.js';
|
|
4
|
+
export { createModuleRegistry, BUILT_IN_MODULES, seedModuleDefaults, type ModuleRegistry, type ModuleRegistryEntry } from './registry.js';
|
|
5
|
+
export { applyModuleDefaults, seedLayoutModuleDefaults } from './seed-defaults.js';
|
|
6
|
+
export { iterModuleNodes } from './walk.js';
|
|
5
7
|
export type { ModuleConfig, ModulePropDefinition, ModulePropOption } from '../config/types.js';
|
|
6
8
|
export { mergeLayoutCascade, type CascadeRule } from './cascade.js';
|
|
7
9
|
export { KywiLayout, KywiRegion, AudienceMetaTags, type ComponentResolver, type SectionComponentResolver, type VariantContainerComponentResolver, type ModuleVariantContainerComponentResolver, type PersonalizationState, type ModuleComponentMap, } from './renderer.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/layout/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAA;AAC1B,OAAO,EACL,oBAAoB,EACpB,iBAAiB,EACjB,oBAAoB,EACpB,6BAA6B,EAC7B,mCAAmC,EACnC,qCAAqC,EACrC,wBAAwB,EACxB,sBAAsB,EACtB,qBAAqB,EACrB,8BAA8B,EAC9B,oCAAoC,EACpC,sCAAsC,EACtC,qBAAqB,EACrB,2BAA2B,EAC3B,qBAAqB,EACrB,sBAAsB,EACtB,+BAA+B,EAC/B,qCAAqC,EACrC,gBAAgB,EAChB,iBAAiB,EACjB,0BAA0B,EAC1B,gCAAgC,EAChC,yBAAyB,EACzB,0BAA0B,EAC1B,KAAK,wBAAwB,EAC7B,KAAK,YAAY,EACjB,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,EACrB,KAAK,qBAAqB,EAC1B,KAAK,6BAA6B,EAClC,KAAK,wBAAwB,EAC7B,KAAK,YAAY,GAClB,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EACL,2BAA2B,EAC3B,6BAA6B,EAC7B,8BAA8B,EAC9B,yBAAyB,EACzB,6BAA6B,EAC7B,sBAAsB,EACtB,KAAK,+BAA+B,EACpC,KAAK,oBAAoB,EACzB,KAAK,sBAAsB,EAC3B,KAAK,qBAAqB,GAC3B,MAAM,+BAA+B,CAAA;AACtC,OAAO,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,KAAK,cAAc,EAAE,KAAK,mBAAmB,EAAE,MAAM,eAAe,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/layout/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAA;AAC1B,OAAO,EACL,oBAAoB,EACpB,iBAAiB,EACjB,oBAAoB,EACpB,6BAA6B,EAC7B,mCAAmC,EACnC,qCAAqC,EACrC,wBAAwB,EACxB,sBAAsB,EACtB,qBAAqB,EACrB,8BAA8B,EAC9B,oCAAoC,EACpC,sCAAsC,EACtC,qBAAqB,EACrB,2BAA2B,EAC3B,qBAAqB,EACrB,sBAAsB,EACtB,+BAA+B,EAC/B,qCAAqC,EACrC,gBAAgB,EAChB,iBAAiB,EACjB,0BAA0B,EAC1B,gCAAgC,EAChC,yBAAyB,EACzB,0BAA0B,EAC1B,KAAK,wBAAwB,EAC7B,KAAK,YAAY,EACjB,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,EACrB,KAAK,qBAAqB,EAC1B,KAAK,6BAA6B,EAClC,KAAK,wBAAwB,EAC7B,KAAK,YAAY,GAClB,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EACL,2BAA2B,EAC3B,6BAA6B,EAC7B,8BAA8B,EAC9B,yBAAyB,EACzB,6BAA6B,EAC7B,sBAAsB,EACtB,KAAK,+BAA+B,EACpC,KAAK,oBAAoB,EACzB,KAAK,sBAAsB,EAC3B,KAAK,qBAAqB,GAC3B,MAAM,+BAA+B,CAAA;AACtC,OAAO,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,KAAK,cAAc,EAAE,KAAK,mBAAmB,EAAE,MAAM,eAAe,CAAA;AACzI,OAAO,EAAE,mBAAmB,EAAE,wBAAwB,EAAE,MAAM,oBAAoB,CAAA;AAClF,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAA;AAC3C,YAAY,EAAE,YAAY,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAA;AAC9F,OAAO,EAAE,kBAAkB,EAAE,KAAK,WAAW,EAAE,MAAM,cAAc,CAAA;AACnE,OAAO,EACL,UAAU,EACV,UAAU,EACV,gBAAgB,EAChB,KAAK,iBAAiB,EACtB,KAAK,wBAAwB,EAC7B,KAAK,iCAAiC,EACtC,KAAK,uCAAuC,EAC5C,KAAK,oBAAoB,EACzB,KAAK,kBAAkB,GACxB,MAAM,eAAe,CAAA;AAGtB,OAAO,EACL,gBAAgB,EAChB,KAAK,uBAAuB,GAC7B,MAAM,wBAAwB,CAAA;AAC/B,OAAO,EACL,gBAAgB,EAChB,KAAK,oBAAoB,GAC1B,MAAM,oBAAoB,CAAA;AAC3B,OAAO,EACL,kBAAkB,EAClB,sBAAsB,EACtB,KAAK,eAAe,EACpB,KAAK,iBAAiB,GACvB,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EACL,yBAAyB,EACzB,gBAAgB,EAChB,0BAA0B,EAC1B,uBAAuB,GACxB,MAAM,sBAAsB,CAAA;AAC7B,OAAO,EAAE,0BAA0B,EAAE,MAAM,cAAc,CAAA;AACzD,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAA;AAC9D,OAAO,EAAE,mBAAmB,EAAE,KAAK,aAAa,EAAE,MAAM,qBAAqB,CAAA;AAC7E,OAAO,EACL,mBAAmB,EACnB,gBAAgB,EAChB,YAAY,EACZ,gBAAgB,EAChB,oBAAoB,EACpB,iBAAiB,EACjB,mBAAmB,EACnB,kBAAkB,EAClB,KAAK,oBAAoB,GAC1B,MAAM,gBAAgB,CAAA"}
|
package/dist/layout/index.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
export * from './types.js';
|
|
2
2
|
export { collectComponentRefs, diffComponentRefs, rekeyResolvedSection, rekeyResolvedVariantContainer, rekeyResolvedModuleVariantContainer, unrekeyResolvedModuleVariantContainer, isCleanComponentInstance, resolveModulePlacement, applySectionPlacement, applyVariantContainerPlacement, applyModuleVariantContainerPlacement, unapplyModuleVariantContainerPlacement, componentDetachSource, validateComponentDefinition, materializeModuleNode, materializeSectionNode, materializeVariantContainerNode, materializeModuleVariantContainerNode, detachModuleNode, detachSectionNode, detachVariantContainerNode, detachModuleVariantContainerNode, detachComponentFromLayout, resolveComponentPlacements, } from './component-refs.js';
|
|
3
3
|
export { findLegacyVariantContainers, convertLegacyVariantContainer, migrateLegacyVariantContainers, hasLegacyVariantContainer, LEGACY_VARIANT_CONTAINER_TYPE, LEGACY_ARM_MODULE_TYPE, } from './legacy-variant-container.js';
|
|
4
|
-
export { createModuleRegistry, BUILT_IN_MODULES } from './registry.js';
|
|
4
|
+
export { createModuleRegistry, BUILT_IN_MODULES, seedModuleDefaults } from './registry.js';
|
|
5
|
+
export { applyModuleDefaults, seedLayoutModuleDefaults } from './seed-defaults.js';
|
|
6
|
+
export { iterModuleNodes } from './walk.js';
|
|
5
7
|
export { mergeLayoutCascade } from './cascade.js';
|
|
6
8
|
export { KywiLayout, KywiRegion, AudienceMetaTags, } from './renderer.js';
|
|
7
9
|
// `PersonalizationState` stays exported from './renderer.js' above — exporting
|
package/dist/layout/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/layout/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAA;AAC1B,OAAO,EACL,oBAAoB,EACpB,iBAAiB,EACjB,oBAAoB,EACpB,6BAA6B,EAC7B,mCAAmC,EACnC,qCAAqC,EACrC,wBAAwB,EACxB,sBAAsB,EACtB,qBAAqB,EACrB,8BAA8B,EAC9B,oCAAoC,EACpC,sCAAsC,EACtC,qBAAqB,EACrB,2BAA2B,EAC3B,qBAAqB,EACrB,sBAAsB,EACtB,+BAA+B,EAC/B,qCAAqC,EACrC,gBAAgB,EAChB,iBAAiB,EACjB,0BAA0B,EAC1B,gCAAgC,EAChC,yBAAyB,EACzB,0BAA0B,GAS3B,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EACL,2BAA2B,EAC3B,6BAA6B,EAC7B,8BAA8B,EAC9B,yBAAyB,EACzB,6BAA6B,EAC7B,sBAAsB,GAKvB,MAAM,+BAA+B,CAAA;AACtC,OAAO,EAAE,oBAAoB,EAAE,gBAAgB,EAAiD,MAAM,eAAe,CAAA;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/layout/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAA;AAC1B,OAAO,EACL,oBAAoB,EACpB,iBAAiB,EACjB,oBAAoB,EACpB,6BAA6B,EAC7B,mCAAmC,EACnC,qCAAqC,EACrC,wBAAwB,EACxB,sBAAsB,EACtB,qBAAqB,EACrB,8BAA8B,EAC9B,oCAAoC,EACpC,sCAAsC,EACtC,qBAAqB,EACrB,2BAA2B,EAC3B,qBAAqB,EACrB,sBAAsB,EACtB,+BAA+B,EAC/B,qCAAqC,EACrC,gBAAgB,EAChB,iBAAiB,EACjB,0BAA0B,EAC1B,gCAAgC,EAChC,yBAAyB,EACzB,0BAA0B,GAS3B,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EACL,2BAA2B,EAC3B,6BAA6B,EAC7B,8BAA8B,EAC9B,yBAAyB,EACzB,6BAA6B,EAC7B,sBAAsB,GAKvB,MAAM,+BAA+B,CAAA;AACtC,OAAO,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,kBAAkB,EAAiD,MAAM,eAAe,CAAA;AACzI,OAAO,EAAE,mBAAmB,EAAE,wBAAwB,EAAE,MAAM,oBAAoB,CAAA;AAClF,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAA;AAE3C,OAAO,EAAE,kBAAkB,EAAoB,MAAM,cAAc,CAAA;AACnE,OAAO,EACL,UAAU,EACV,UAAU,EACV,gBAAgB,GAOjB,MAAM,eAAe,CAAA;AACtB,+EAA+E;AAC/E,6BAA6B;AAC7B,OAAO,EACL,gBAAgB,GAEjB,MAAM,wBAAwB,CAAA;AAC/B,OAAO,EACL,gBAAgB,GAEjB,MAAM,oBAAoB,CAAA;AAC3B,OAAO,EACL,kBAAkB,EAClB,sBAAsB,GAGvB,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EACL,yBAAyB,EACzB,gBAAgB,EAChB,0BAA0B,EAC1B,uBAAuB,GACxB,MAAM,sBAAsB,CAAA;AAC7B,OAAO,EAAE,0BAA0B,EAAE,MAAM,cAAc,CAAA;AACzD,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAA;AAC9D,OAAO,EAAE,mBAAmB,EAAsB,MAAM,qBAAqB,CAAA;AAC7E,OAAO,EACL,mBAAmB,EACnB,gBAAgB,EAChB,YAAY,EACZ,gBAAgB,EAChB,oBAAoB,EACpB,iBAAiB,EACjB,mBAAmB,EACnB,kBAAkB,GAEnB,MAAM,gBAAgB,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"module-permissions.d.ts","sourceRoot":"","sources":["../../src/layout/module-permissions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAyC,MAAM,YAAY,CAAA;
|
|
1
|
+
{"version":3,"file":"module-permissions.d.ts","sourceRoot":"","sources":["../../src/layout/module-permissions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAyC,MAAM,YAAY,CAAA;AAKvF;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,uBAAuB,EAAE,WAAW,CAAC,MAAM,CAAqB,CAAA;AA8C7E,6DAA6D;AAC7D,MAAM,WAAW,2BAA2B;IAC1C,IAAI,EAAE,MAAM,CAAA;IACZ,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAA;IACtC,UAAU,CAAC,EAAE,OAAO,CAAA;CACrB;AAED,yEAAyE;AACzE,MAAM,MAAM,yBAAyB,GAAG,CACtC,WAAW,EAAE,MAAM,KAChB,2BAA2B,GAAG,IAAI,GAAG,SAAS,CAAA;AAKnD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,6BAA6B,CAC3C,SAAS,EAAE,2BAA2B,GAAG,IAAI,GAAG,SAAS,GACxD,cAAc,GAAG,IAAI,CAoEvB;AASD;;;;;;;;;;GAUG;AACH,wBAAgB,yCAAyC,CACvD,QAAQ,EAAE,2BAA2B,EACrC,MAAM,EAAE,2BAA2B,GAAG,IAAI,GAAG,SAAS,GACrD,MAAM,EAAE,CAIV;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,wBAAgB,6BAA6B,CAC3C,QAAQ,EAAE,cAAc,EACxB,MAAM,EAAE,cAAc,GAAG,IAAI,GAAG,SAAS,EACzC,gBAAgB,CAAC,EAAE,yBAAyB,GAC3C,MAAM,EAAE,CAkBV"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { validateLayoutSection, validateModuleVariantContainer, validateVariantContainer } from './types.js';
|
|
2
|
+
import { iterModuleNodes } from './walk.js';
|
|
2
3
|
import { diffComponentRefs } from './component-refs.js';
|
|
3
4
|
/**
|
|
4
5
|
* Module types that expose privileged capabilities (raw HTML injection) and must
|
|
@@ -14,43 +15,6 @@ import { diffComponentRefs } from './component-refs.js';
|
|
|
14
15
|
* depth (privilege separation), not the XSS boundary.
|
|
15
16
|
*/
|
|
16
17
|
export const ADMIN_ONLY_MODULE_TYPES = new Set(['html']);
|
|
17
|
-
/** Yield every ModuleNode contained anywhere in a LayoutDocument. */
|
|
18
|
-
function* iterModuleNodes(doc) {
|
|
19
|
-
function* fromSections(sections) {
|
|
20
|
-
for (const section of sections ?? []) {
|
|
21
|
-
for (const column of section.columns ?? []) {
|
|
22
|
-
yield* columnModules(column);
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
function* fromRegionNodes(nodes) {
|
|
27
|
-
for (const node of nodes ?? []) {
|
|
28
|
-
if (node.type === 'section') {
|
|
29
|
-
yield* fromSections([node]);
|
|
30
|
-
}
|
|
31
|
-
else if (node.type === 'variantContainer') {
|
|
32
|
-
yield* fromSections(node.defaultSections);
|
|
33
|
-
for (const variant of node.variants ?? []) {
|
|
34
|
-
yield* fromSections(variant.sections);
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
function* fromRegions(regions) {
|
|
40
|
-
for (const nodes of Object.values(regions)) {
|
|
41
|
-
yield* fromRegionNodes(nodes);
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
yield* fromRegions(doc.regions ?? {});
|
|
45
|
-
for (const pageVariant of doc.pageVariants ?? []) {
|
|
46
|
-
yield* fromRegions(pageVariant.regions);
|
|
47
|
-
}
|
|
48
|
-
for (const experiment of doc.abExperiments ?? []) {
|
|
49
|
-
for (const variant of experiment.variants) {
|
|
50
|
-
yield* fromRegions(variant.regions);
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
18
|
/** Every admin-only module node present in a document, keyed by node id. */
|
|
55
19
|
function adminOnlyModulesById(doc) {
|
|
56
20
|
const byId = new Map();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"module-permissions.js","sourceRoot":"","sources":["../../src/layout/module-permissions.ts"],"names":[],"mappings":"AACA,OAAO,
|
|
1
|
+
{"version":3,"file":"module-permissions.js","sourceRoot":"","sources":["../../src/layout/module-permissions.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { LayoutDocument } from './types.js';
|
|
2
|
+
import type { ModuleRegistry } from './registry.js';
|
|
3
|
+
/**
|
|
4
|
+
* Module prop defaults, applied on the write path (kywi-cms#197).
|
|
5
|
+
*
|
|
6
|
+
* A module declares `defaultValue` per prop so it renders as something the
|
|
7
|
+
* moment it is placed. Until now only the editor's drag-insert honoured that
|
|
8
|
+
* (`seedModuleDefaults`, via `admin/layout-editor/drag-utils.ts`), so a module
|
|
9
|
+
* placed over the API — MCP `add_module`, a layout PUT, a content write
|
|
10
|
+
* carrying `layout` — landed with `props: {}` and rendered as a blank band.
|
|
11
|
+
* Every custom module then grew a second copy of its own defaults in component
|
|
12
|
+
* code just to survive being placed by an agent.
|
|
13
|
+
*
|
|
14
|
+
* The rule, in one sentence: **an omitted prop takes the module's default; an
|
|
15
|
+
* explicit `''` stays `''`.** Presence of the key is the whole signal — a prop
|
|
16
|
+
* written as `''`, `null`, `0` or `false` was written on purpose and is left
|
|
17
|
+
* exactly as it came in.
|
|
18
|
+
*/
|
|
19
|
+
/**
|
|
20
|
+
* One module's props with its registry defaults filled in for keys the caller
|
|
21
|
+
* did not supply. Returns a new object; the input is never mutated.
|
|
22
|
+
*/
|
|
23
|
+
export declare function applyModuleDefaults(props: Record<string, unknown> | undefined, registry: ModuleRegistry, moduleType: string): Record<string, unknown>;
|
|
24
|
+
/**
|
|
25
|
+
* Seed defaults into the modules a layout write ADDS, in place, and return it.
|
|
26
|
+
*
|
|
27
|
+
* Scoped by diffing against `stored`, the document already saved, because a
|
|
28
|
+
* layout arrives as a WHOLE document from every door — so a pass that seeded
|
|
29
|
+
* unconditionally would keep rewriting modules nobody touched. An editor
|
|
30
|
+
* retyping one heading would inject `buttonLabel: "Get Started"` into a cta
|
|
31
|
+
* that was deliberately placed without one, and the same for
|
|
32
|
+
* `relatedContent.heading`, `heading.text`, the richText placeholder and the
|
|
33
|
+
* comments/siteMap titles. A module already in the stored document is a
|
|
34
|
+
* decision that was already made; only a module that was not there is new
|
|
35
|
+
* enough to have defaults to take.
|
|
36
|
+
*
|
|
37
|
+
* `stored` null/undefined means there is nothing to diff against — a first save
|
|
38
|
+
* — so every module counts as added.
|
|
39
|
+
*
|
|
40
|
+
* Modules linked to a component (`componentId`) are skipped either way: they
|
|
41
|
+
* render the component's stored definition, so props written here would be
|
|
42
|
+
* inert at best.
|
|
43
|
+
*/
|
|
44
|
+
export declare function seedLayoutModuleDefaults(layout: LayoutDocument, registry: ModuleRegistry, stored?: LayoutDocument | null): LayoutDocument;
|
|
45
|
+
//# sourceMappingURL=seed-defaults.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"seed-defaults.d.ts","sourceRoot":"","sources":["../../src/layout/seed-defaults.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAChD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AAGnD;;;;;;;;;;;;;;;GAeG;AAEH;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,EAC1C,QAAQ,EAAE,cAAc,EACxB,UAAU,EAAE,MAAM,GACjB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAczB;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,cAAc,EACtB,QAAQ,EAAE,cAAc,EACxB,MAAM,CAAC,EAAE,cAAc,GAAG,IAAI,GAC7B,cAAc,CAehB"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { iterModuleNodes } from './walk.js';
|
|
2
|
+
/**
|
|
3
|
+
* Module prop defaults, applied on the write path (kywi-cms#197).
|
|
4
|
+
*
|
|
5
|
+
* A module declares `defaultValue` per prop so it renders as something the
|
|
6
|
+
* moment it is placed. Until now only the editor's drag-insert honoured that
|
|
7
|
+
* (`seedModuleDefaults`, via `admin/layout-editor/drag-utils.ts`), so a module
|
|
8
|
+
* placed over the API — MCP `add_module`, a layout PUT, a content write
|
|
9
|
+
* carrying `layout` — landed with `props: {}` and rendered as a blank band.
|
|
10
|
+
* Every custom module then grew a second copy of its own defaults in component
|
|
11
|
+
* code just to survive being placed by an agent.
|
|
12
|
+
*
|
|
13
|
+
* The rule, in one sentence: **an omitted prop takes the module's default; an
|
|
14
|
+
* explicit `''` stays `''`.** Presence of the key is the whole signal — a prop
|
|
15
|
+
* written as `''`, `null`, `0` or `false` was written on purpose and is left
|
|
16
|
+
* exactly as it came in.
|
|
17
|
+
*/
|
|
18
|
+
/**
|
|
19
|
+
* One module's props with its registry defaults filled in for keys the caller
|
|
20
|
+
* did not supply. Returns a new object; the input is never mutated.
|
|
21
|
+
*/
|
|
22
|
+
export function applyModuleDefaults(props, registry, moduleType) {
|
|
23
|
+
const entry = registry.get(moduleType);
|
|
24
|
+
const supplied = props ?? {};
|
|
25
|
+
if (!entry?.props)
|
|
26
|
+
return { ...supplied };
|
|
27
|
+
const out = { ...supplied };
|
|
28
|
+
for (const [key, def] of Object.entries(entry.props)) {
|
|
29
|
+
// `key in out` — NOT a truthiness or `undefined` check. That distinction is
|
|
30
|
+
// the contract: `{ title: '' }` keeps its empty string, `{}` gets the default.
|
|
31
|
+
if (def.defaultValue !== undefined && !(key in out)) {
|
|
32
|
+
out[key] = def.defaultValue;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return out;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Seed defaults into the modules a layout write ADDS, in place, and return it.
|
|
39
|
+
*
|
|
40
|
+
* Scoped by diffing against `stored`, the document already saved, because a
|
|
41
|
+
* layout arrives as a WHOLE document from every door — so a pass that seeded
|
|
42
|
+
* unconditionally would keep rewriting modules nobody touched. An editor
|
|
43
|
+
* retyping one heading would inject `buttonLabel: "Get Started"` into a cta
|
|
44
|
+
* that was deliberately placed without one, and the same for
|
|
45
|
+
* `relatedContent.heading`, `heading.text`, the richText placeholder and the
|
|
46
|
+
* comments/siteMap titles. A module already in the stored document is a
|
|
47
|
+
* decision that was already made; only a module that was not there is new
|
|
48
|
+
* enough to have defaults to take.
|
|
49
|
+
*
|
|
50
|
+
* `stored` null/undefined means there is nothing to diff against — a first save
|
|
51
|
+
* — so every module counts as added.
|
|
52
|
+
*
|
|
53
|
+
* Modules linked to a component (`componentId`) are skipped either way: they
|
|
54
|
+
* render the component's stored definition, so props written here would be
|
|
55
|
+
* inert at best.
|
|
56
|
+
*/
|
|
57
|
+
export function seedLayoutModuleDefaults(layout, registry, stored) {
|
|
58
|
+
// Identity is the node `id` — the same key the admin-only module gate diffs
|
|
59
|
+
// on. A node that moved to another column keeps its id and so counts as
|
|
60
|
+
// existing; a duplicate, which the editor mints a fresh id for, does not.
|
|
61
|
+
const existing = new Set();
|
|
62
|
+
if (stored) {
|
|
63
|
+
for (const node of iterModuleNodes(stored))
|
|
64
|
+
existing.add(node.id);
|
|
65
|
+
}
|
|
66
|
+
for (const node of iterModuleNodes(layout)) {
|
|
67
|
+
if (node.componentId)
|
|
68
|
+
continue;
|
|
69
|
+
if (existing.has(node.id))
|
|
70
|
+
continue;
|
|
71
|
+
node.props = applyModuleDefaults(node.props, registry, node.type);
|
|
72
|
+
}
|
|
73
|
+
return layout;
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=seed-defaults.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"seed-defaults.js","sourceRoot":"","sources":["../../src/layout/seed-defaults.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAA;AAE3C;;;;;;;;;;;;;;;GAeG;AAEH;;;GAGG;AACH,MAAM,UAAU,mBAAmB,CACjC,KAA0C,EAC1C,QAAwB,EACxB,UAAkB;IAElB,MAAM,KAAK,GAAG,QAAQ,CAAC,GAAG,CAAC,UAAU,CAAC,CAAA;IACtC,MAAM,QAAQ,GAAG,KAAK,IAAI,EAAE,CAAA;IAC5B,IAAI,CAAC,KAAK,EAAE,KAAK;QAAE,OAAO,EAAE,GAAG,QAAQ,EAAE,CAAA;IAEzC,MAAM,GAAG,GAA4B,EAAE,GAAG,QAAQ,EAAE,CAAA;IACpD,KAAK,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;QACrD,4EAA4E;QAC5E,+EAA+E;QAC/E,IAAI,GAAG,CAAC,YAAY,KAAK,SAAS,IAAI,CAAC,CAAC,GAAG,IAAI,GAAG,CAAC,EAAE,CAAC;YACpD,GAAG,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,YAAY,CAAA;QAC7B,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAA;AACZ,CAAC;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,UAAU,wBAAwB,CACtC,MAAsB,EACtB,QAAwB,EACxB,MAA8B;IAE9B,4EAA4E;IAC5E,wEAAwE;IACxE,0EAA0E;IAC1E,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAU,CAAA;IAClC,IAAI,MAAM,EAAE,CAAC;QACX,KAAK,MAAM,IAAI,IAAI,eAAe,CAAC,MAAM,CAAC;YAAE,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IACnE,CAAC;IAED,KAAK,MAAM,IAAI,IAAI,eAAe,CAAC,MAAM,CAAC,EAAE,CAAC;QAC3C,IAAI,IAAI,CAAC,WAAW;YAAE,SAAQ;QAC9B,IAAI,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YAAE,SAAQ;QACnC,IAAI,CAAC,KAAK,GAAG,mBAAmB,CAAC,IAAI,CAAC,KAAK,EAAE,QAAQ,EAAE,IAAI,CAAC,IAAI,CAAC,CAAA;IACnE,CAAC;IACD,OAAO,MAAM,CAAA;AACf,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { LayoutDocument, ModuleNode } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Yield every ModuleNode contained anywhere in a LayoutDocument — plain modules,
|
|
4
|
+
* the arms of a module-level variant container, sections inside a section-level
|
|
5
|
+
* variant container, page variants and A/B experiment regions alike.
|
|
6
|
+
*
|
|
7
|
+
* Nodes are yielded BY REFERENCE, so a pass that needs to rewrite modules in
|
|
8
|
+
* place (default seeding) and a pass that only reads them (the admin-only module
|
|
9
|
+
* gate) can share one definition of "every module in this document". Every rule
|
|
10
|
+
* that walks a layout should walk it through here: a rule with its own traversal
|
|
11
|
+
* is a rule with a blind spot the moment a new container shape lands.
|
|
12
|
+
*/
|
|
13
|
+
export declare function iterModuleNodes(doc: LayoutDocument): Iterable<ModuleNode>;
|
|
14
|
+
//# sourceMappingURL=walk.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"walk.d.ts","sourceRoot":"","sources":["../../src/layout/walk.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAiB,UAAU,EAAc,MAAM,YAAY,CAAA;AAGvF;;;;;;;;;;GAUG;AACH,wBAAiB,eAAe,CAAC,GAAG,EAAE,cAAc,GAAG,QAAQ,CAAC,UAAU,CAAC,CAmC1E"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { columnModules } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Yield every ModuleNode contained anywhere in a LayoutDocument — plain modules,
|
|
4
|
+
* the arms of a module-level variant container, sections inside a section-level
|
|
5
|
+
* variant container, page variants and A/B experiment regions alike.
|
|
6
|
+
*
|
|
7
|
+
* Nodes are yielded BY REFERENCE, so a pass that needs to rewrite modules in
|
|
8
|
+
* place (default seeding) and a pass that only reads them (the admin-only module
|
|
9
|
+
* gate) can share one definition of "every module in this document". Every rule
|
|
10
|
+
* that walks a layout should walk it through here: a rule with its own traversal
|
|
11
|
+
* is a rule with a blind spot the moment a new container shape lands.
|
|
12
|
+
*/
|
|
13
|
+
export function* iterModuleNodes(doc) {
|
|
14
|
+
function* fromSections(sections) {
|
|
15
|
+
for (const section of sections ?? []) {
|
|
16
|
+
for (const column of section.columns ?? []) {
|
|
17
|
+
yield* columnModules(column);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
function* fromRegionNodes(nodes) {
|
|
22
|
+
for (const node of nodes ?? []) {
|
|
23
|
+
if (node.type === 'section') {
|
|
24
|
+
yield* fromSections([node]);
|
|
25
|
+
}
|
|
26
|
+
else if (node.type === 'variantContainer') {
|
|
27
|
+
yield* fromSections(node.defaultSections);
|
|
28
|
+
for (const variant of node.variants ?? []) {
|
|
29
|
+
yield* fromSections(variant.sections);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
function* fromRegions(regions) {
|
|
35
|
+
for (const nodes of Object.values(regions)) {
|
|
36
|
+
yield* fromRegionNodes(nodes);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
yield* fromRegions(doc.regions ?? {});
|
|
40
|
+
for (const pageVariant of doc.pageVariants ?? []) {
|
|
41
|
+
yield* fromRegions(pageVariant.regions);
|
|
42
|
+
}
|
|
43
|
+
for (const experiment of doc.abExperiments ?? []) {
|
|
44
|
+
for (const variant of experiment.variants) {
|
|
45
|
+
yield* fromRegions(variant.regions);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=walk.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"walk.js","sourceRoot":"","sources":["../../src/layout/walk.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAE1C;;;;;;;;;;GAUG;AACH,MAAM,SAAS,CAAC,CAAC,eAAe,CAAC,GAAmB;IAClD,QAAQ,CAAC,CAAC,YAAY,CAAC,QAAyB;QAC9C,KAAK,MAAM,OAAO,IAAI,QAAQ,IAAI,EAAE,EAAE,CAAC;YACrC,KAAK,MAAM,MAAM,IAAI,OAAO,CAAC,OAAO,IAAI,EAAE,EAAE,CAAC;gBAC3C,KAAK,CAAC,CAAC,aAAa,CAAC,MAAM,CAAC,CAAA;YAC9B,CAAC;QACH,CAAC;IACH,CAAC;IACD,QAAQ,CAAC,CAAC,eAAe,CAAC,KAAmB;QAC3C,KAAK,MAAM,IAAI,IAAI,KAAK,IAAI,EAAE,EAAE,CAAC;YAC/B,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;gBAC5B,KAAK,CAAC,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,CAAC,CAAA;YAC7B,CAAC;iBAAM,IAAI,IAAI,CAAC,IAAI,KAAK,kBAAkB,EAAE,CAAC;gBAC5C,KAAK,CAAC,CAAC,YAAY,CAAC,IAAI,CAAC,eAAe,CAAC,CAAA;gBACzC,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,QAAQ,IAAI,EAAE,EAAE,CAAC;oBAC1C,KAAK,CAAC,CAAC,YAAY,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAA;gBACvC,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IACD,QAAQ,CAAC,CAAC,WAAW,CAAC,OAAqC;QACzD,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC;YAC3C,KAAK,CAAC,CAAC,eAAe,CAAC,KAAK,CAAC,CAAA;QAC/B,CAAC;IACH,CAAC;IAED,KAAK,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,OAAO,IAAI,EAAE,CAAC,CAAA;IACrC,KAAK,MAAM,WAAW,IAAI,GAAG,CAAC,YAAY,IAAI,EAAE,EAAE,CAAC;QACjD,KAAK,CAAC,CAAC,WAAW,CAAC,WAAW,CAAC,OAAO,CAAC,CAAA;IACzC,CAAC;IACD,KAAK,MAAM,UAAU,IAAI,GAAG,CAAC,aAAa,IAAI,EAAE,EAAE,CAAC;QACjD,KAAK,MAAM,OAAO,IAAI,UAAU,CAAC,QAAQ,EAAE,CAAC;YAC1C,KAAK,CAAC,CAAC,WAAW,CAAC,OAAO,CAAC,OAAO,CAAC,CAAA;QACrC,CAAC;IACH,CAAC;AACH,CAAC"}
|
package/dist/media/index.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ export * from './types.js';
|
|
|
2
2
|
export * from './image-manipulation.js';
|
|
3
3
|
export { createLocalStorage } from './local-storage.js';
|
|
4
4
|
export { createS3Storage } from './s3-storage.js';
|
|
5
|
-
export { checkUploadAllowed, fileExtension, normalizeMimeType, DEFAULT_ALLOWED_EXTENSIONS, DEFAULT_ALLOWED_MIME_TYPES, type UploadAllowResult, } from './upload-allowlist.js';
|
|
5
|
+
export { checkUploadAllowed, sanitizeUploadFilename, fileExtension, normalizeMimeType, DEFAULT_ALLOWED_EXTENSIONS, DEFAULT_ALLOWED_MIME_TYPES, type UploadAllowResult, } from './upload-allowlist.js';
|
|
6
6
|
import type { MediaConfig, StorageProvider } from './types.js';
|
|
7
7
|
export declare function createStorageProvider(config: MediaConfig): StorageProvider;
|
|
8
8
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/media/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAA;AAC1B,cAAc,yBAAyB,CAAA;AACvC,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAA;AACvD,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AACjD,OAAO,EACL,kBAAkB,EAClB,aAAa,EACb,iBAAiB,EACjB,0BAA0B,EAC1B,0BAA0B,EAC1B,KAAK,iBAAiB,GACvB,MAAM,uBAAuB,CAAA;AAE9B,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAI9D,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,WAAW,GAAG,eAAe,CAK1E"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/media/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAA;AAC1B,cAAc,yBAAyB,CAAA;AACvC,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAA;AACvD,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AACjD,OAAO,EACL,kBAAkB,EAClB,sBAAsB,EACtB,aAAa,EACb,iBAAiB,EACjB,0BAA0B,EAC1B,0BAA0B,EAC1B,KAAK,iBAAiB,GACvB,MAAM,uBAAuB,CAAA;AAE9B,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAI9D,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,WAAW,GAAG,eAAe,CAK1E"}
|
package/dist/media/index.js
CHANGED
|
@@ -2,7 +2,7 @@ export * from './types.js';
|
|
|
2
2
|
export * from './image-manipulation.js';
|
|
3
3
|
export { createLocalStorage } from './local-storage.js';
|
|
4
4
|
export { createS3Storage } from './s3-storage.js';
|
|
5
|
-
export { checkUploadAllowed, fileExtension, normalizeMimeType, DEFAULT_ALLOWED_EXTENSIONS, DEFAULT_ALLOWED_MIME_TYPES, } from './upload-allowlist.js';
|
|
5
|
+
export { checkUploadAllowed, sanitizeUploadFilename, fileExtension, normalizeMimeType, DEFAULT_ALLOWED_EXTENSIONS, DEFAULT_ALLOWED_MIME_TYPES, } from './upload-allowlist.js';
|
|
6
6
|
import { createLocalStorage } from './local-storage.js';
|
|
7
7
|
import { createS3Storage } from './s3-storage.js';
|
|
8
8
|
export function createStorageProvider(config) {
|
package/dist/media/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/media/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAA;AAC1B,cAAc,yBAAyB,CAAA;AACvC,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAA;AACvD,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AACjD,OAAO,EACL,kBAAkB,EAClB,aAAa,EACb,iBAAiB,EACjB,0BAA0B,EAC1B,0BAA0B,GAE3B,MAAM,uBAAuB,CAAA;AAG9B,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAA;AACvD,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAEjD,MAAM,UAAU,qBAAqB,CAAC,MAAmB;IACvD,IAAI,MAAM,CAAC,QAAQ,KAAK,IAAI,IAAI,MAAM,CAAC,EAAE,EAAE,CAAC;QAC1C,OAAO,eAAe,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;IACnC,CAAC;IACD,OAAO,kBAAkB,CAAC,MAAM,CAAC,SAAS,IAAI,WAAW,CAAC,CAAA;AAC5D,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/media/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAA;AAC1B,cAAc,yBAAyB,CAAA;AACvC,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAA;AACvD,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AACjD,OAAO,EACL,kBAAkB,EAClB,sBAAsB,EACtB,aAAa,EACb,iBAAiB,EACjB,0BAA0B,EAC1B,0BAA0B,GAE3B,MAAM,uBAAuB,CAAA;AAG9B,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAA;AACvD,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAEjD,MAAM,UAAU,qBAAqB,CAAC,MAAmB;IACvD,IAAI,MAAM,CAAC,QAAQ,KAAK,IAAI,IAAI,MAAM,CAAC,EAAE,EAAE,CAAC;QAC1C,OAAO,eAAe,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;IACnC,CAAC;IACD,OAAO,kBAAkB,CAAC,MAAM,CAAC,SAAS,IAAI,WAAW,CAAC,CAAA;AAC5D,CAAC"}
|
|
@@ -14,6 +14,29 @@ import type { MediaConfig } from './types.js';
|
|
|
14
14
|
export declare const DEFAULT_ALLOWED_EXTENSIONS: readonly string[];
|
|
15
15
|
/** Default allowed MIME types. Executable/script types are excluded. */
|
|
16
16
|
export declare const DEFAULT_ALLOWED_MIME_TYPES: readonly string[];
|
|
17
|
+
/**
|
|
18
|
+
* Reduce an attacker-supplied upload name to a safe basename, or null when
|
|
19
|
+
* nothing usable is left.
|
|
20
|
+
*
|
|
21
|
+
* `x-filename` is a header, so it is attacker-controlled, and it lands in
|
|
22
|
+
* `storageKey = ${siteId}/${id}/${filename}` — which the local storage provider
|
|
23
|
+
* feeds to `join(basePath, key)`. `join` normalises, so `../` segments walk out
|
|
24
|
+
* of the media root entirely, and `../../<otherSiteId>/<mediaId>/logo.png`
|
|
25
|
+
* overwrites another site's asset with nothing more than a writer token. The
|
|
26
|
+
* allowlist is no defence here on its own: {@link fileExtension} deliberately
|
|
27
|
+
* looks only at the basename, so a traversing path with a clean `.svg` on the
|
|
28
|
+
* end sails through the extension gate.
|
|
29
|
+
*
|
|
30
|
+
* So the name is reduced to its last segment (both separators, since a Windows
|
|
31
|
+
* client may send `\`) and everything outside `[A-Za-z0-9._-]` — spaces,
|
|
32
|
+
* quotes, NUL, non-ASCII — becomes `_`. `.` and `..` are refused outright:
|
|
33
|
+
* a name that means "a directory" is not a file name.
|
|
34
|
+
*
|
|
35
|
+
* Call this BEFORE `checkUploadAllowed`, and use the result for the storage key,
|
|
36
|
+
* the variant keys and the stored record alike — a record that keeps the raw
|
|
37
|
+
* name would hand the traversal straight back to whatever reads it later.
|
|
38
|
+
*/
|
|
39
|
+
export declare function sanitizeUploadFilename(raw: string): string | null;
|
|
17
40
|
/** Lowercased extension of a filename, without the leading dot. '' when none. */
|
|
18
41
|
export declare function fileExtension(filename: string): string;
|
|
19
42
|
/** Normalize a Content-Type header value to a bare lowercase MIME (strip params). */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"upload-allowlist.d.ts","sourceRoot":"","sources":["../../src/media/upload-allowlist.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAE7C;;;;;;;;;;GAUG;AAEH,gGAAgG;AAChG,eAAO,MAAM,0BAA0B,EAAE,SAAS,MAAM,EAWvD,CAAA;AAED,wEAAwE;AACxE,eAAO,MAAM,0BAA0B,EAAE,SAAS,MAAM,EAoBvD,CAAA;AAOD,iFAAiF;AACjF,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAKtD;AAED,qFAAqF;AACrF,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAE1D;AAED,MAAM,MAAM,iBAAiB,GAAG;IAAE,EAAE,EAAE,IAAI,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAA;AAE5E;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,WAAW,GAAG,SAAS,GAC9B,iBAAiB,CAkBnB"}
|
|
1
|
+
{"version":3,"file":"upload-allowlist.d.ts","sourceRoot":"","sources":["../../src/media/upload-allowlist.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAE7C;;;;;;;;;;GAUG;AAEH,gGAAgG;AAChG,eAAO,MAAM,0BAA0B,EAAE,SAAS,MAAM,EAWvD,CAAA;AAED,wEAAwE;AACxE,eAAO,MAAM,0BAA0B,EAAE,SAAS,MAAM,EAoBvD,CAAA;AAOD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAKjE;AAED,iFAAiF;AACjF,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAKtD;AAED,qFAAqF;AACrF,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAE1D;AAED,MAAM,MAAM,iBAAiB,GAAG;IAAE,EAAE,EAAE,IAAI,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAA;AAE5E;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,WAAW,GAAG,SAAS,GAC9B,iBAAiB,CAkBnB"}
|
|
@@ -48,6 +48,35 @@ export const DEFAULT_ALLOWED_MIME_TYPES = [
|
|
|
48
48
|
function isGenericMime(mime) {
|
|
49
49
|
return mime === '' || mime === 'application/octet-stream';
|
|
50
50
|
}
|
|
51
|
+
/**
|
|
52
|
+
* Reduce an attacker-supplied upload name to a safe basename, or null when
|
|
53
|
+
* nothing usable is left.
|
|
54
|
+
*
|
|
55
|
+
* `x-filename` is a header, so it is attacker-controlled, and it lands in
|
|
56
|
+
* `storageKey = ${siteId}/${id}/${filename}` — which the local storage provider
|
|
57
|
+
* feeds to `join(basePath, key)`. `join` normalises, so `../` segments walk out
|
|
58
|
+
* of the media root entirely, and `../../<otherSiteId>/<mediaId>/logo.png`
|
|
59
|
+
* overwrites another site's asset with nothing more than a writer token. The
|
|
60
|
+
* allowlist is no defence here on its own: {@link fileExtension} deliberately
|
|
61
|
+
* looks only at the basename, so a traversing path with a clean `.svg` on the
|
|
62
|
+
* end sails through the extension gate.
|
|
63
|
+
*
|
|
64
|
+
* So the name is reduced to its last segment (both separators, since a Windows
|
|
65
|
+
* client may send `\`) and everything outside `[A-Za-z0-9._-]` — spaces,
|
|
66
|
+
* quotes, NUL, non-ASCII — becomes `_`. `.` and `..` are refused outright:
|
|
67
|
+
* a name that means "a directory" is not a file name.
|
|
68
|
+
*
|
|
69
|
+
* Call this BEFORE `checkUploadAllowed`, and use the result for the storage key,
|
|
70
|
+
* the variant keys and the stored record alike — a record that keeps the raw
|
|
71
|
+
* name would hand the traversal straight back to whatever reads it later.
|
|
72
|
+
*/
|
|
73
|
+
export function sanitizeUploadFilename(raw) {
|
|
74
|
+
const lastSegment = raw.replace(/\\/g, '/').split('/').pop() ?? '';
|
|
75
|
+
const cleaned = lastSegment.trim().replace(/[^A-Za-z0-9._-]/g, '_');
|
|
76
|
+
if (cleaned === '' || cleaned === '.' || cleaned === '..')
|
|
77
|
+
return null;
|
|
78
|
+
return cleaned;
|
|
79
|
+
}
|
|
51
80
|
/** Lowercased extension of a filename, without the leading dot. '' when none. */
|
|
52
81
|
export function fileExtension(filename) {
|
|
53
82
|
const base = filename.split('/').pop() ?? filename;
|