@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.
Files changed (249) hide show
  1. package/AGENT-PATTERNS.md +47 -0
  2. package/dist/admin/audience-editor.d.ts +2 -0
  3. package/dist/admin/audience-editor.d.ts.map +1 -1
  4. package/dist/admin/audience-editor.js +4 -2
  5. package/dist/admin/audience-editor.js.map +1 -1
  6. package/dist/admin/condition-builder.d.ts.map +1 -1
  7. package/dist/admin/condition-builder.js +16 -3
  8. package/dist/admin/condition-builder.js.map +1 -1
  9. package/dist/admin/rule-tester.d.ts +1 -0
  10. package/dist/admin/rule-tester.d.ts.map +1 -1
  11. package/dist/admin/rule-tester.js +7 -4
  12. package/dist/admin/rule-tester.js.map +1 -1
  13. package/dist/admin/signal-options.d.ts +17 -0
  14. package/dist/admin/signal-options.d.ts.map +1 -1
  15. package/dist/admin/signal-options.js +28 -0
  16. package/dist/admin/signal-options.js.map +1 -1
  17. package/dist/admin/surfaces/audiences/audiences-data.d.ts +5 -0
  18. package/dist/admin/surfaces/audiences/audiences-data.d.ts.map +1 -1
  19. package/dist/admin/surfaces/audiences/audiences-data.js +3 -0
  20. package/dist/admin/surfaces/audiences/audiences-data.js.map +1 -1
  21. package/dist/api/api-key-routes.js +2 -2
  22. package/dist/api/api-key-routes.js.map +1 -1
  23. package/dist/api/audience-routes.d.ts.map +1 -1
  24. package/dist/api/audience-routes.js +10 -4
  25. package/dist/api/audience-routes.js.map +1 -1
  26. package/dist/api/audience-runtime-routes.d.ts +17 -0
  27. package/dist/api/audience-runtime-routes.d.ts.map +1 -1
  28. package/dist/api/audience-runtime-routes.js +474 -23
  29. package/dist/api/audience-runtime-routes.js.map +1 -1
  30. package/dist/api/ax-routes.d.ts.map +1 -1
  31. package/dist/api/ax-routes.js +7 -3
  32. package/dist/api/ax-routes.js.map +1 -1
  33. package/dist/api/category-routes.js +3 -3
  34. package/dist/api/category-routes.js.map +1 -1
  35. package/dist/api/changeset-routes.js +2 -2
  36. package/dist/api/changeset-routes.js.map +1 -1
  37. package/dist/api/comment-routes.js +4 -4
  38. package/dist/api/comment-routes.js.map +1 -1
  39. package/dist/api/component-routes.js +3 -3
  40. package/dist/api/component-routes.js.map +1 -1
  41. package/dist/api/config-routes.js +4 -4
  42. package/dist/api/config-routes.js.map +1 -1
  43. package/dist/api/content-permission-routes.js +2 -2
  44. package/dist/api/content-permission-routes.js.map +1 -1
  45. package/dist/api/content-routes.d.ts.map +1 -1
  46. package/dist/api/content-routes.js +8 -3
  47. package/dist/api/content-routes.js.map +1 -1
  48. package/dist/api/content-type-routes.js +3 -3
  49. package/dist/api/content-type-routes.js.map +1 -1
  50. package/dist/api/experiment-routes.js +2 -2
  51. package/dist/api/experiment-routes.js.map +1 -1
  52. package/dist/api/extension-routes.js +4 -4
  53. package/dist/api/extension-routes.js.map +1 -1
  54. package/dist/api/feed-routes.js +2 -2
  55. package/dist/api/feed-routes.js.map +1 -1
  56. package/dist/api/form-routes.js +2 -2
  57. package/dist/api/form-routes.js.map +1 -1
  58. package/dist/api/group-routes.js +3 -3
  59. package/dist/api/group-routes.js.map +1 -1
  60. package/dist/api/index.d.ts.map +1 -1
  61. package/dist/api/index.js +4 -1
  62. package/dist/api/index.js.map +1 -1
  63. package/dist/api/layout-routes.d.ts +19 -1
  64. package/dist/api/layout-routes.d.ts.map +1 -1
  65. package/dist/api/layout-routes.js +65 -5
  66. package/dist/api/layout-routes.js.map +1 -1
  67. package/dist/api/layout-write-guard.d.ts +3 -2
  68. package/dist/api/layout-write-guard.d.ts.map +1 -1
  69. package/dist/api/layout-write-guard.js +12 -4
  70. package/dist/api/layout-write-guard.js.map +1 -1
  71. package/dist/api/media-routes.d.ts.map +1 -1
  72. package/dist/api/media-routes.js +50 -9
  73. package/dist/api/media-routes.js.map +1 -1
  74. package/dist/api/menu-routes.js +2 -2
  75. package/dist/api/menu-routes.js.map +1 -1
  76. package/dist/api/nav-routes.js +3 -3
  77. package/dist/api/nav-routes.js.map +1 -1
  78. package/dist/api/oauth-routes.js +2 -2
  79. package/dist/api/oauth-routes.js.map +1 -1
  80. package/dist/api/openapi.d.ts.map +1 -1
  81. package/dist/api/openapi.js +14 -1
  82. package/dist/api/openapi.js.map +1 -1
  83. package/dist/api/pagination.d.ts +10 -0
  84. package/dist/api/pagination.d.ts.map +1 -1
  85. package/dist/api/pagination.js +7 -1
  86. package/dist/api/pagination.js.map +1 -1
  87. package/dist/api/response.d.ts +29 -0
  88. package/dist/api/response.d.ts.map +1 -1
  89. package/dist/api/response.js +23 -3
  90. package/dist/api/response.js.map +1 -1
  91. package/dist/api/search-routes.d.ts.map +1 -1
  92. package/dist/api/search-routes.js +17 -3
  93. package/dist/api/search-routes.js.map +1 -1
  94. package/dist/api/section-template-routes.js +2 -2
  95. package/dist/api/section-template-routes.js.map +1 -1
  96. package/dist/api/site-routes.js +2 -2
  97. package/dist/api/site-routes.js.map +1 -1
  98. package/dist/api/tag-routes.d.ts.map +1 -1
  99. package/dist/api/tag-routes.js +2 -2
  100. package/dist/api/tag-routes.js.map +1 -1
  101. package/dist/api/user-routes.js +2 -2
  102. package/dist/api/user-routes.js.map +1 -1
  103. package/dist/api/version-routes.js +2 -2
  104. package/dist/api/version-routes.js.map +1 -1
  105. package/dist/api/webhook-routes.js +3 -3
  106. package/dist/api/webhook-routes.js.map +1 -1
  107. package/dist/api/workflow-routes.d.ts.map +1 -1
  108. package/dist/api/workflow-routes.js +15 -6
  109. package/dist/api/workflow-routes.js.map +1 -1
  110. package/dist/audiences/collectors/index.d.ts +8 -4
  111. package/dist/audiences/collectors/index.d.ts.map +1 -1
  112. package/dist/audiences/collectors/index.js +17 -4
  113. package/dist/audiences/collectors/index.js.map +1 -1
  114. package/dist/audiences/collectors/selfid.d.ts +25 -0
  115. package/dist/audiences/collectors/selfid.d.ts.map +1 -0
  116. package/dist/audiences/collectors/selfid.js +46 -0
  117. package/dist/audiences/collectors/selfid.js.map +1 -0
  118. package/dist/audiences/collectors/session.d.ts +41 -0
  119. package/dist/audiences/collectors/session.d.ts.map +1 -0
  120. package/dist/audiences/collectors/session.js +50 -0
  121. package/dist/audiences/collectors/session.js.map +1 -0
  122. package/dist/audiences/consent.d.ts +13 -0
  123. package/dist/audiences/consent.d.ts.map +1 -1
  124. package/dist/audiences/consent.js +13 -0
  125. package/dist/audiences/consent.js.map +1 -1
  126. package/dist/audiences/cookies.d.ts +21 -0
  127. package/dist/audiences/cookies.d.ts.map +1 -1
  128. package/dist/audiences/cookies.js +26 -0
  129. package/dist/audiences/cookies.js.map +1 -1
  130. package/dist/audiences/engine.d.ts.map +1 -1
  131. package/dist/audiences/engine.js +1 -0
  132. package/dist/audiences/engine.js.map +1 -1
  133. package/dist/audiences/entry-page.d.ts +89 -0
  134. package/dist/audiences/entry-page.d.ts.map +1 -0
  135. package/dist/audiences/entry-page.js +116 -0
  136. package/dist/audiences/entry-page.js.map +1 -0
  137. package/dist/audiences/evaluator/instant-match.d.ts.map +1 -1
  138. package/dist/audiences/evaluator/instant-match.js +7 -0
  139. package/dist/audiences/evaluator/instant-match.js.map +1 -1
  140. package/dist/audiences/index.d.ts +3 -2
  141. package/dist/audiences/index.d.ts.map +1 -1
  142. package/dist/audiences/index.js +6 -2
  143. package/dist/audiences/index.js.map +1 -1
  144. package/dist/audiences/queries.d.ts +16 -0
  145. package/dist/audiences/queries.d.ts.map +1 -1
  146. package/dist/audiences/queries.js +28 -1
  147. package/dist/audiences/queries.js.map +1 -1
  148. package/dist/audiences/schema.d.ts +17 -0
  149. package/dist/audiences/schema.d.ts.map +1 -1
  150. package/dist/audiences/schema.js +7 -0
  151. package/dist/audiences/schema.js.map +1 -1
  152. package/dist/audiences/server-eval.d.ts +19 -0
  153. package/dist/audiences/server-eval.d.ts.map +1 -1
  154. package/dist/audiences/server-eval.js +17 -1
  155. package/dist/audiences/server-eval.js.map +1 -1
  156. package/dist/audiences/types.d.ts +22 -1
  157. package/dist/audiences/types.d.ts.map +1 -1
  158. package/dist/audiences/types.js +1 -0
  159. package/dist/audiences/types.js.map +1 -1
  160. package/dist/ax/content-source.d.ts +10 -2
  161. package/dist/ax/content-source.d.ts.map +1 -1
  162. package/dist/ax/content-source.js +81 -5
  163. package/dist/ax/content-source.js.map +1 -1
  164. package/dist/ax/effective-body.d.ts +28 -0
  165. package/dist/ax/effective-body.d.ts.map +1 -0
  166. package/dist/ax/effective-body.js +47 -0
  167. package/dist/ax/effective-body.js.map +1 -0
  168. package/dist/ax/index.d.ts +3 -1
  169. package/dist/ax/index.d.ts.map +1 -1
  170. package/dist/ax/index.js +2 -0
  171. package/dist/ax/index.js.map +1 -1
  172. package/dist/ax/jsonld.d.ts +31 -1
  173. package/dist/ax/jsonld.d.ts.map +1 -1
  174. package/dist/ax/jsonld.js +35 -22
  175. package/dist/ax/jsonld.js.map +1 -1
  176. package/dist/ax/layout-to-html.d.ts +127 -0
  177. package/dist/ax/layout-to-html.d.ts.map +1 -0
  178. package/dist/ax/layout-to-html.js +545 -0
  179. package/dist/ax/layout-to-html.js.map +1 -0
  180. package/dist/ax/llms-full-txt.d.ts +3 -1
  181. package/dist/ax/llms-full-txt.d.ts.map +1 -1
  182. package/dist/ax/llms-full-txt.js +5 -2
  183. package/dist/ax/llms-full-txt.js.map +1 -1
  184. package/dist/ax/page-markdown.d.ts +10 -2
  185. package/dist/ax/page-markdown.d.ts.map +1 -1
  186. package/dist/ax/page-markdown.js +16 -3
  187. package/dist/ax/page-markdown.js.map +1 -1
  188. package/dist/ax/summary.d.ts +4 -0
  189. package/dist/ax/summary.d.ts.map +1 -1
  190. package/dist/ax/summary.js +6 -1
  191. package/dist/ax/summary.js.map +1 -1
  192. package/dist/ax/types.d.ts +24 -0
  193. package/dist/ax/types.d.ts.map +1 -1
  194. package/dist/cache/content-invalidation.d.ts.map +1 -1
  195. package/dist/cache/content-invalidation.js +11 -0
  196. package/dist/cache/content-invalidation.js.map +1 -1
  197. package/dist/db/apply-snapshot.d.ts +7 -0
  198. package/dist/db/apply-snapshot.d.ts.map +1 -1
  199. package/dist/db/apply-snapshot.js +7 -0
  200. package/dist/db/apply-snapshot.js.map +1 -1
  201. package/dist/db/ax-queries.d.ts +6 -0
  202. package/dist/db/ax-queries.d.ts.map +1 -1
  203. package/dist/db/ax-queries.js +6 -0
  204. package/dist/db/ax-queries.js.map +1 -1
  205. package/dist/db/content-queries.d.ts.map +1 -1
  206. package/dist/db/content-queries.js +8 -0
  207. package/dist/db/content-queries.js.map +1 -1
  208. package/dist/db/layout-queries.d.ts +19 -2
  209. package/dist/db/layout-queries.d.ts.map +1 -1
  210. package/dist/db/layout-queries.js +11 -3
  211. package/dist/db/layout-queries.js.map +1 -1
  212. package/dist/db/search-queries.d.ts.map +1 -1
  213. package/dist/db/search-queries.js +24 -1
  214. package/dist/db/search-queries.js.map +1 -1
  215. package/dist/hooks/ax-invalidation.d.ts.map +1 -1
  216. package/dist/hooks/ax-invalidation.js +4 -0
  217. package/dist/hooks/ax-invalidation.js.map +1 -1
  218. package/dist/layout/index.d.ts +3 -1
  219. package/dist/layout/index.d.ts.map +1 -1
  220. package/dist/layout/index.js +3 -1
  221. package/dist/layout/index.js.map +1 -1
  222. package/dist/layout/module-permissions.d.ts.map +1 -1
  223. package/dist/layout/module-permissions.js +2 -38
  224. package/dist/layout/module-permissions.js.map +1 -1
  225. package/dist/layout/seed-defaults.d.ts +45 -0
  226. package/dist/layout/seed-defaults.d.ts.map +1 -0
  227. package/dist/layout/seed-defaults.js +75 -0
  228. package/dist/layout/seed-defaults.js.map +1 -0
  229. package/dist/layout/walk.d.ts +14 -0
  230. package/dist/layout/walk.d.ts.map +1 -0
  231. package/dist/layout/walk.js +49 -0
  232. package/dist/layout/walk.js.map +1 -0
  233. package/dist/media/index.d.ts +1 -1
  234. package/dist/media/index.d.ts.map +1 -1
  235. package/dist/media/index.js +1 -1
  236. package/dist/media/index.js.map +1 -1
  237. package/dist/media/upload-allowlist.d.ts +23 -0
  238. package/dist/media/upload-allowlist.d.ts.map +1 -1
  239. package/dist/media/upload-allowlist.js +29 -0
  240. package/dist/media/upload-allowlist.js.map +1 -1
  241. package/dist/schema/mysql-tables.d.ts +17 -0
  242. package/dist/schema/mysql-tables.d.ts.map +1 -1
  243. package/dist/schema/mysql-tables.js +2 -0
  244. package/dist/schema/mysql-tables.js.map +1 -1
  245. package/dist/scope/jsonld.d.ts +18 -3
  246. package/dist/scope/jsonld.d.ts.map +1 -1
  247. package/dist/scope/jsonld.js +6 -4
  248. package/dist/scope/jsonld.js.map +1 -1
  249. 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;;;;;;;;;;;;;;;;GAgBG;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,OAAO,CAAC,CAgClB"}
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 false when no row matched the (id, siteId) scope.
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 false;
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 true;
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;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,EAAU,EACV,SAAiB,EACjB,MAA6B,EAC7B,MAAe;IAEf,MAAM,KAAK,GAAG,MAAM,KAAK,SAAS;QAChC,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,CAAA;IAEtE,OAAO,gBAAgB,CAAC,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE;QACvC,MAAM,CAAC,QAAQ,CAAC,GAAG,MAAM,EAAE;aACxB,MAAM,CAAC;YACN,MAAM,EAAE,WAAW,CAAC,MAAM;YAC1B,eAAe,EAAE,WAAW,CAAC,eAAe;YAC5C,MAAM,EAAE,WAAW,CAAC,MAAM;SAC3B,CAAC;aACD,IAAI,CAAC,WAAW,CAAC;aACjB,KAAK,CAAC,KAAK,CAAC;aACZ,GAAG,CAAC,QAAQ,CAAC;aACb,KAAK,CAAC,CAAC,CAAC,CAAA;QACX,IAAI,CAAC,QAAQ;YAAE,OAAO,KAAK,CAAA;QAE3B,MAAM,EAAE;aACL,MAAM,CAAC,WAAW,CAAC;aACnB,GAAG,CAAC,EAAE,MAAM,EAAE,CAAC,MAAM,IAAI,IAAI,CAAU,EAAE,SAAS,EAAE,IAAI,IAAI,EAAE,EAAE,CAAC;aACjE,KAAK,CAAC,KAAK,CAAC,CAAA;QAEf,MAAM,sBAAsB,CAAC,EAAE,EAAE;YAC/B,MAAM,EAAE,QAAQ,CAAC,MAAM;YACvB,MAAM,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS,EAAE,WAAW,EAAE,QAAQ,CAAC,eAAe,EAAE;YAC7E,MAAM,EAAE,CAAC,QAAQ,CAAC,MAAM,IAAI,IAAI,CAA0B;YAC1D,KAAK,EAAE,MAAM;SACd,CAAC,CAAA;QAEF,OAAO,IAAI,CAAA;IACb,CAAC,CAAC,CAAA;AACJ,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":"AAEA,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,CAwErD"}
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.summary,
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":"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"}
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;AAW1D;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,aAAa,EAAE,iBAAiB,EAAE,QAAQ,EAAE,YAAY,GAAG,IAAI,CAQjG"}
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;CACtB,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"}
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"}
@@ -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;AACrH,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"}
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"}
@@ -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
@@ -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;AAErH,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
+ {"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;AAIvF;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,uBAAuB,EAAE,WAAW,CAAC,MAAM,CAAqB,CAAA;AAoF7E,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
+ {"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 { columnModules, validateLayoutSection, validateModuleVariantContainer, validateVariantContainer } from './types.js';
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":"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"}
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"}
@@ -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"}
@@ -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) {
@@ -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;