@endora-commerce/mod-cms 0.0.0-stage → 0.100.0

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 (264) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +65 -2
  3. package/dist/admin/api/cms-client.d.ts +77 -0
  4. package/dist/admin/api/cms-client.d.ts.map +1 -0
  5. package/dist/admin/api/cms-client.js +162 -0
  6. package/dist/admin/api/cms-client.js.map +1 -0
  7. package/dist/admin/components/AdminCatalogPreviewProvider.d.ts +6 -0
  8. package/dist/admin/components/AdminCatalogPreviewProvider.d.ts.map +1 -0
  9. package/dist/admin/components/AdminCatalogPreviewProvider.js +74 -0
  10. package/dist/admin/components/AdminCatalogPreviewProvider.js.map +1 -0
  11. package/dist/admin/components/AdminCmsAssetProvider.d.ts +9 -0
  12. package/dist/admin/components/AdminCmsAssetProvider.d.ts.map +1 -0
  13. package/dist/admin/components/AdminCmsAssetProvider.js +50 -0
  14. package/dist/admin/components/AdminCmsAssetProvider.js.map +1 -0
  15. package/dist/admin/components/BackgroundFields.d.ts +4 -0
  16. package/dist/admin/components/BackgroundFields.d.ts.map +1 -0
  17. package/dist/admin/components/BackgroundFields.js +40 -0
  18. package/dist/admin/components/BackgroundFields.js.map +1 -0
  19. package/dist/admin/components/ButtonLinkFields.d.ts +6 -0
  20. package/dist/admin/components/ButtonLinkFields.d.ts.map +1 -0
  21. package/dist/admin/components/ButtonLinkFields.js +127 -0
  22. package/dist/admin/components/ButtonLinkFields.js.map +1 -0
  23. package/dist/admin/components/CarouselPreviewNav.d.ts +12 -0
  24. package/dist/admin/components/CarouselPreviewNav.d.ts.map +1 -0
  25. package/dist/admin/components/CarouselPreviewNav.js +31 -0
  26. package/dist/admin/components/CarouselPreviewNav.js.map +1 -0
  27. package/dist/admin/components/CmsContentEditorLayout.d.ts +12 -0
  28. package/dist/admin/components/CmsContentEditorLayout.d.ts.map +1 -0
  29. package/dist/admin/components/CmsContentEditorLayout.js +9 -0
  30. package/dist/admin/components/CmsContentEditorLayout.js.map +1 -0
  31. package/dist/admin/components/ComponentDragHandle.d.ts +6 -0
  32. package/dist/admin/components/ComponentDragHandle.d.ts.map +1 -0
  33. package/dist/admin/components/ComponentDragHandle.js +119 -0
  34. package/dist/admin/components/ComponentDragHandle.js.map +1 -0
  35. package/dist/admin/components/ContentSliderActionBarExtras.d.ts +6 -0
  36. package/dist/admin/components/ContentSliderActionBarExtras.d.ts.map +1 -0
  37. package/dist/admin/components/ContentSliderActionBarExtras.js +109 -0
  38. package/dist/admin/components/ContentSliderActionBarExtras.js.map +1 -0
  39. package/dist/admin/components/HookBlockAttachmentsPanel.d.ts +9 -0
  40. package/dist/admin/components/HookBlockAttachmentsPanel.d.ts.map +1 -0
  41. package/dist/admin/components/HookBlockAttachmentsPanel.js +137 -0
  42. package/dist/admin/components/HookBlockAttachmentsPanel.js.map +1 -0
  43. package/dist/admin/components/PageBuilderActionBar.d.ts +10 -0
  44. package/dist/admin/components/PageBuilderActionBar.d.ts.map +1 -0
  45. package/dist/admin/components/PageBuilderActionBar.js +118 -0
  46. package/dist/admin/components/PageBuilderActionBar.js.map +1 -0
  47. package/dist/admin/components/PageBuilderDrawer.d.ts +16 -0
  48. package/dist/admin/components/PageBuilderDrawer.d.ts.map +1 -0
  49. package/dist/admin/components/PageBuilderDrawer.js +53 -0
  50. package/dist/admin/components/PageBuilderDrawer.js.map +1 -0
  51. package/dist/admin/components/PageBuilderEditor.d.ts +45 -0
  52. package/dist/admin/components/PageBuilderEditor.d.ts.map +1 -0
  53. package/dist/admin/components/PageBuilderEditor.js +632 -0
  54. package/dist/admin/components/PageBuilderEditor.js.map +1 -0
  55. package/dist/admin/components/PuckActionGuard.d.ts +12 -0
  56. package/dist/admin/components/PuckActionGuard.d.ts.map +1 -0
  57. package/dist/admin/components/PuckActionGuard.js +30 -0
  58. package/dist/admin/components/PuckActionGuard.js.map +1 -0
  59. package/dist/admin/components/RowLayoutPicker.d.ts +8 -0
  60. package/dist/admin/components/RowLayoutPicker.d.ts.map +1 -0
  61. package/dist/admin/components/RowLayoutPicker.js +17 -0
  62. package/dist/admin/components/RowLayoutPicker.js.map +1 -0
  63. package/dist/admin/components/SliderPreviewActionBarExtras.d.ts +6 -0
  64. package/dist/admin/components/SliderPreviewActionBarExtras.d.ts.map +1 -0
  65. package/dist/admin/components/SliderPreviewActionBarExtras.js +32 -0
  66. package/dist/admin/components/SliderPreviewActionBarExtras.js.map +1 -0
  67. package/dist/admin/components/admin-catalog-preview-map.d.ts +17 -0
  68. package/dist/admin/components/admin-catalog-preview-map.d.ts.map +1 -0
  69. package/dist/admin/components/admin-catalog-preview-map.js +18 -0
  70. package/dist/admin/components/admin-catalog-preview-map.js.map +1 -0
  71. package/dist/admin/components/build-viewports.d.ts +23 -0
  72. package/dist/admin/components/build-viewports.d.ts.map +1 -0
  73. package/dist/admin/components/build-viewports.js +23 -0
  74. package/dist/admin/components/build-viewports.js.map +1 -0
  75. package/dist/admin/components/cms-template-layout.d.ts +16 -0
  76. package/dist/admin/components/cms-template-layout.d.ts.map +1 -0
  77. package/dist/admin/components/cms-template-layout.js +53 -0
  78. package/dist/admin/components/cms-template-layout.js.map +1 -0
  79. package/dist/admin/components/page-builder-i18n.d.ts +27 -0
  80. package/dist/admin/components/page-builder-i18n.d.ts.map +1 -0
  81. package/dist/admin/components/page-builder-i18n.js +34 -0
  82. package/dist/admin/components/page-builder-i18n.js.map +1 -0
  83. package/dist/admin/components/puck-safe.d.ts +10 -0
  84. package/dist/admin/components/puck-safe.d.ts.map +1 -0
  85. package/dist/admin/components/puck-safe.js +22 -0
  86. package/dist/admin/components/puck-safe.js.map +1 -0
  87. package/dist/admin/components/scope-utils.d.ts +4 -0
  88. package/dist/admin/components/scope-utils.d.ts.map +1 -0
  89. package/dist/admin/components/scope-utils.js +7 -0
  90. package/dist/admin/components/scope-utils.js.map +1 -0
  91. package/dist/admin/editors/BlockEditor.d.ts +9 -0
  92. package/dist/admin/editors/BlockEditor.d.ts.map +1 -0
  93. package/dist/admin/editors/BlockEditor.js +217 -0
  94. package/dist/admin/editors/BlockEditor.js.map +1 -0
  95. package/dist/admin/editors/PageEditor.d.ts +9 -0
  96. package/dist/admin/editors/PageEditor.d.ts.map +1 -0
  97. package/dist/admin/editors/PageEditor.js +316 -0
  98. package/dist/admin/editors/PageEditor.js.map +1 -0
  99. package/dist/admin/editors/TemplateEditor.d.ts +9 -0
  100. package/dist/admin/editors/TemplateEditor.d.ts.map +1 -0
  101. package/dist/admin/editors/TemplateEditor.js +180 -0
  102. package/dist/admin/editors/TemplateEditor.js.map +1 -0
  103. package/dist/admin/index.d.ts +38 -0
  104. package/dist/admin/index.d.ts.map +1 -0
  105. package/dist/admin/index.js +144 -0
  106. package/dist/admin/index.js.map +1 -0
  107. package/dist/admin/pages/BlocksListPage.d.ts +9 -0
  108. package/dist/admin/pages/BlocksListPage.d.ts.map +1 -0
  109. package/dist/admin/pages/BlocksListPage.js +47 -0
  110. package/dist/admin/pages/BlocksListPage.js.map +1 -0
  111. package/dist/admin/pages/HooksPage.d.ts +9 -0
  112. package/dist/admin/pages/HooksPage.d.ts.map +1 -0
  113. package/dist/admin/pages/HooksPage.js +41 -0
  114. package/dist/admin/pages/HooksPage.js.map +1 -0
  115. package/dist/admin/pages/PagesListPage.d.ts +9 -0
  116. package/dist/admin/pages/PagesListPage.d.ts.map +1 -0
  117. package/dist/admin/pages/PagesListPage.js +51 -0
  118. package/dist/admin/pages/PagesListPage.js.map +1 -0
  119. package/dist/admin/pages/TemplatesListPage.d.ts +9 -0
  120. package/dist/admin/pages/TemplatesListPage.d.ts.map +1 -0
  121. package/dist/admin/pages/TemplatesListPage.js +47 -0
  122. package/dist/admin/pages/TemplatesListPage.js.map +1 -0
  123. package/dist/admin-ui/index.d.ts +90 -0
  124. package/dist/admin-ui/index.d.ts.map +1 -0
  125. package/dist/admin-ui/index.js +89 -0
  126. package/dist/admin-ui/index.js.map +1 -0
  127. package/dist/backend/cli/block-names.d.ts +92 -0
  128. package/dist/backend/cli/block-names.d.ts.map +1 -0
  129. package/dist/backend/cli/block-names.js +132 -0
  130. package/dist/backend/cli/block-names.js.map +1 -0
  131. package/dist/backend/entities/cms-block.entity.d.ts +20 -0
  132. package/dist/backend/entities/cms-block.entity.d.ts.map +1 -0
  133. package/dist/backend/entities/cms-block.entity.js +77 -0
  134. package/dist/backend/entities/cms-block.entity.js.map +1 -0
  135. package/dist/backend/entities/cms-hook-block-attachment.entity.d.ts +15 -0
  136. package/dist/backend/entities/cms-hook-block-attachment.entity.d.ts.map +1 -0
  137. package/dist/backend/entities/cms-hook-block-attachment.entity.js +46 -0
  138. package/dist/backend/entities/cms-hook-block-attachment.entity.js.map +1 -0
  139. package/dist/backend/entities/cms-hook.entity.d.ts +20 -0
  140. package/dist/backend/entities/cms-hook.entity.d.ts.map +1 -0
  141. package/dist/backend/entities/cms-hook.entity.js +73 -0
  142. package/dist/backend/entities/cms-hook.entity.js.map +1 -0
  143. package/dist/backend/entities/cms-page.entity.d.ts +43 -0
  144. package/dist/backend/entities/cms-page.entity.d.ts.map +1 -0
  145. package/dist/backend/entities/cms-page.entity.js +140 -0
  146. package/dist/backend/entities/cms-page.entity.js.map +1 -0
  147. package/dist/backend/entities/cms-template.entity.d.ts +20 -0
  148. package/dist/backend/entities/cms-template.entity.d.ts.map +1 -0
  149. package/dist/backend/entities/cms-template.entity.js +73 -0
  150. package/dist/backend/entities/cms-template.entity.js.map +1 -0
  151. package/dist/backend/index.d.ts +157 -0
  152. package/dist/backend/index.d.ts.map +1 -0
  153. package/dist/backend/index.js +317 -0
  154. package/dist/backend/index.js.map +1 -0
  155. package/dist/backend/plugin.d.ts +81 -0
  156. package/dist/backend/plugin.d.ts.map +1 -0
  157. package/dist/backend/plugin.js +81 -0
  158. package/dist/backend/plugin.js.map +1 -0
  159. package/dist/backend/routes.admin.d.ts +19 -0
  160. package/dist/backend/routes.admin.d.ts.map +1 -0
  161. package/dist/backend/routes.admin.js +164 -0
  162. package/dist/backend/routes.admin.js.map +1 -0
  163. package/dist/backend/routes.storefront.d.ts +6 -0
  164. package/dist/backend/routes.storefront.d.ts.map +1 -0
  165. package/dist/backend/routes.storefront.js +89 -0
  166. package/dist/backend/routes.storefront.js.map +1 -0
  167. package/dist/backend/services/asset-embed-resolver.d.ts +17 -0
  168. package/dist/backend/services/asset-embed-resolver.d.ts.map +1 -0
  169. package/dist/backend/services/asset-embed-resolver.js +40 -0
  170. package/dist/backend/services/asset-embed-resolver.js.map +1 -0
  171. package/dist/backend/services/asset-references.d.ts +4 -0
  172. package/dist/backend/services/asset-references.d.ts.map +1 -0
  173. package/dist/backend/services/asset-references.js +55 -0
  174. package/dist/backend/services/asset-references.js.map +1 -0
  175. package/dist/backend/services/cms-block-read-port.d.ts +27 -0
  176. package/dist/backend/services/cms-block-read-port.d.ts.map +1 -0
  177. package/dist/backend/services/cms-block-read-port.js +50 -0
  178. package/dist/backend/services/cms-block-read-port.js.map +1 -0
  179. package/dist/backend/services/cms-block-seed-port.d.ts +31 -0
  180. package/dist/backend/services/cms-block-seed-port.d.ts.map +1 -0
  181. package/dist/backend/services/cms-block-seed-port.js +68 -0
  182. package/dist/backend/services/cms-block-seed-port.js.map +1 -0
  183. package/dist/backend/services/cms-block-service.d.ts +38 -0
  184. package/dist/backend/services/cms-block-service.d.ts.map +1 -0
  185. package/dist/backend/services/cms-block-service.js +218 -0
  186. package/dist/backend/services/cms-block-service.js.map +1 -0
  187. package/dist/backend/services/cms-cache.d.ts +54 -0
  188. package/dist/backend/services/cms-cache.d.ts.map +1 -0
  189. package/dist/backend/services/cms-cache.js +113 -0
  190. package/dist/backend/services/cms-cache.js.map +1 -0
  191. package/dist/backend/services/cms-hook-service.d.ts +35 -0
  192. package/dist/backend/services/cms-hook-service.d.ts.map +1 -0
  193. package/dist/backend/services/cms-hook-service.js +216 -0
  194. package/dist/backend/services/cms-hook-service.js.map +1 -0
  195. package/dist/backend/services/cms-language-reference.d.ts +11 -0
  196. package/dist/backend/services/cms-language-reference.d.ts.map +1 -0
  197. package/dist/backend/services/cms-language-reference.js +26 -0
  198. package/dist/backend/services/cms-language-reference.js.map +1 -0
  199. package/dist/backend/services/cms-page-read-port.d.ts +23 -0
  200. package/dist/backend/services/cms-page-read-port.d.ts.map +1 -0
  201. package/dist/backend/services/cms-page-read-port.js +54 -0
  202. package/dist/backend/services/cms-page-read-port.js.map +1 -0
  203. package/dist/backend/services/cms-page-service.d.ts +104 -0
  204. package/dist/backend/services/cms-page-service.d.ts.map +1 -0
  205. package/dist/backend/services/cms-page-service.js +468 -0
  206. package/dist/backend/services/cms-page-service.js.map +1 -0
  207. package/dist/backend/services/cms-reference-registry.d.ts +30 -0
  208. package/dist/backend/services/cms-reference-registry.d.ts.map +1 -0
  209. package/dist/backend/services/cms-reference-registry.js +98 -0
  210. package/dist/backend/services/cms-reference-registry.js.map +1 -0
  211. package/dist/backend/services/cms-template-service.d.ts +37 -0
  212. package/dist/backend/services/cms-template-service.d.ts.map +1 -0
  213. package/dist/backend/services/cms-template-service.js +205 -0
  214. package/dist/backend/services/cms-template-service.js.map +1 -0
  215. package/dist/backend/services/content-tree-walker.d.ts +7 -0
  216. package/dist/backend/services/content-tree-walker.d.ts.map +1 -0
  217. package/dist/backend/services/content-tree-walker.js +89 -0
  218. package/dist/backend/services/content-tree-walker.js.map +1 -0
  219. package/dist/backend/services/page-builder-registry.d.ts +120 -0
  220. package/dist/backend/services/page-builder-registry.d.ts.map +1 -0
  221. package/dist/backend/services/page-builder-registry.js +220 -0
  222. package/dist/backend/services/page-builder-registry.js.map +1 -0
  223. package/dist/backend/services/seed-hooks.d.ts +22 -0
  224. package/dist/backend/services/seed-hooks.d.ts.map +1 -0
  225. package/dist/backend/services/seed-hooks.js +94 -0
  226. package/dist/backend/services/seed-hooks.js.map +1 -0
  227. package/dist/backend/services/storefront-resolver.d.ts +71 -0
  228. package/dist/backend/services/storefront-resolver.d.ts.map +1 -0
  229. package/dist/backend/services/storefront-resolver.js +329 -0
  230. package/dist/backend/services/storefront-resolver.js.map +1 -0
  231. package/dist/manifest.d.ts +225 -0
  232. package/dist/manifest.d.ts.map +1 -0
  233. package/dist/manifest.js +695 -0
  234. package/dist/manifest.js.map +1 -0
  235. package/dist/migrations/20260425T162418_cms_pages_init.d.ts +10 -0
  236. package/dist/migrations/20260425T162418_cms_pages_init.d.ts.map +1 -0
  237. package/dist/migrations/20260425T162418_cms_pages_init.js +30 -0
  238. package/dist/migrations/20260425T162418_cms_pages_init.js.map +1 -0
  239. package/dist/migrations/20260505T130214_cms_init.d.ts +28 -0
  240. package/dist/migrations/20260505T130214_cms_init.d.ts.map +1 -0
  241. package/dist/migrations/20260505T130214_cms_init.js +332 -0
  242. package/dist/migrations/20260505T130214_cms_init.js.map +1 -0
  243. package/dist/migrations/20260903T101741_cms_namespace_block_names.d.ts +6 -0
  244. package/dist/migrations/20260903T101741_cms_namespace_block_names.d.ts.map +1 -0
  245. package/dist/migrations/20260903T101741_cms_namespace_block_names.js +60 -0
  246. package/dist/migrations/20260903T101741_cms_namespace_block_names.js.map +1 -0
  247. package/dist/migrations/20260912T094733_cms_sales_channel_cms_pages.d.ts +27 -0
  248. package/dist/migrations/20260912T094733_cms_sales_channel_cms_pages.d.ts.map +1 -0
  249. package/dist/migrations/20260912T094733_cms_sales_channel_cms_pages.js +44 -0
  250. package/dist/migrations/20260912T094733_cms_sales_channel_cms_pages.js.map +1 -0
  251. package/dist/migrations/20260912T125709_cms_page_body_asset_ref_index.d.ts +32 -0
  252. package/dist/migrations/20260912T125709_cms_page_body_asset_ref_index.d.ts.map +1 -0
  253. package/dist/migrations/20260912T125709_cms_page_body_asset_ref_index.js +36 -0
  254. package/dist/migrations/20260912T125709_cms_page_body_asset_ref_index.js.map +1 -0
  255. package/dist/migrations/index.d.ts +31 -0
  256. package/dist/migrations/index.d.ts.map +1 -0
  257. package/dist/migrations/index.js +37 -0
  258. package/dist/migrations/index.js.map +1 -0
  259. package/docs/cms/extending-page-builder.md +256 -0
  260. package/docs/cms/index.md +233 -0
  261. package/i18n/en.json +231 -0
  262. package/i18n/pl.json +231 -0
  263. package/package.json +125 -3
  264. package/tailwind.css +16 -0
@@ -0,0 +1,468 @@
1
+ import { randomUUID } from 'crypto';
2
+ import { ERROR_CODES, firstSlugSegment, } from '@endora-commerce/contracts';
3
+ import { HttpError } from '@endora-commerce/platform/http';
4
+ import { SalesChannel } from '@endora-commerce/platform/kernel';
5
+ import { walkBlockEmbeds, walkUnknownComponents } from './content-tree-walker.js';
6
+ const emptyContent = { languages: {} };
7
+ /**
8
+ * The reserved set as the refusal reads it, from the value an operator typed.
9
+ *
10
+ * The Setting is free-form JSON, so this is forgiving in the three ways an
11
+ * operator's list is likely to be wrong and in no other: `"/cart"` and
12
+ * `"Cart"` and `"checkout/pay"` all mean the segment `cart`, `cart` and
13
+ * `checkout`. A non-string entry is dropped rather than stringified — an
14
+ * operator who typed `["cart", 7]` reserved one segment, not two, and
15
+ * `"7"` reserving a path is a rule nobody wrote.
16
+ */
17
+ export function normalizeReservedSegments(value) {
18
+ if (!Array.isArray(value))
19
+ return [];
20
+ const out = new Set();
21
+ for (const entry of value) {
22
+ if (typeof entry !== 'string')
23
+ continue;
24
+ const segment = firstSlugSegment(entry.trim());
25
+ if (segment.length > 0)
26
+ out.add(segment);
27
+ }
28
+ return [...out];
29
+ }
30
+ export class CmsPageService {
31
+ emFactory;
32
+ knownComponentNames;
33
+ cache;
34
+ references;
35
+ /**
36
+ * Absent until `registerModule` installs it, and absent means "nothing is
37
+ * reserved". That is the manifest's own default (`defaultValue: []`), so an
38
+ * unwired service and a deployment that reserves nothing answer alike — and
39
+ * a *failing* read is not this state: it propagates, see `reservedSegments`.
40
+ */
41
+ reservedSegmentsResolver = null;
42
+ constructor(emFactory, knownComponentNames, cache, references) {
43
+ this.emFactory = emFactory;
44
+ this.knownComponentNames = knownComponentNames;
45
+ this.cache = cache;
46
+ this.references = references;
47
+ }
48
+ setReservedSegmentsResolver(resolver) {
49
+ this.reservedSegmentsResolver = resolver;
50
+ }
51
+ /**
52
+ * The deployment's reserved first path segments — the **one** value the
53
+ * save-time refusal below and the editor's inline warning both read
54
+ * (FR-033). Two lists would be two answers waiting to disagree, and a warning
55
+ * that disagrees with a refusal is worse than no warning.
56
+ */
57
+ async reservedSegments() {
58
+ if (!this.reservedSegmentsResolver)
59
+ return [];
60
+ return normalizeReservedSegments(await this.reservedSegmentsResolver());
61
+ }
62
+ /**
63
+ * FR-031 — refuse a slug whose first segment the deployment reserves.
64
+ *
65
+ * Nothing here creates precedence and nothing may (`contracts/cms-page-url.md`
66
+ * §5.0): the storefront's route already wins, measured, with no mechanism.
67
+ * What this removes is the **silence** — a page that saves, publishes and is
68
+ * never served while the operator is told nothing, which is a defect
69
+ * indistinguishable from a legitimate state because the URL answers 200 with
70
+ * somebody else's content.
71
+ *
72
+ * The offending segment travels in `details` so the envelope can fill the
73
+ * `{segment}` placeholder in the operator's own language (§5.4): the code for
74
+ * a consumer to branch on, the sentence for the operator to read.
75
+ */
76
+ async assertSlugNotReserved(slug) {
77
+ const segment = firstSlugSegment(slug);
78
+ if (segment.length === 0)
79
+ return;
80
+ const reserved = await this.reservedSegments();
81
+ if (!reserved.includes(segment))
82
+ return;
83
+ throw new HttpError(409, ERROR_CODES.CMS_SLUG_RESERVED, `The first path segment "${segment}" is reserved by this storefront.`, { segment });
84
+ }
85
+ async invalidateForPageId(pageId) {
86
+ if (!this.cache)
87
+ return;
88
+ const rows = (await this.emFactory().execute(`select slug from cms_page_sales_channels where page_id = ?
89
+ union
90
+ select slug from cms_pages where id = ?`, [pageId, pageId]));
91
+ const slugs = new Set(rows.map((r) => r.slug).filter((s) => s && s.length > 0));
92
+ if (slugs.size > 0)
93
+ await this.cache.invalidatePagesBySlug(slugs);
94
+ }
95
+ async invalidateForSlugs(slugs) {
96
+ if (!this.cache)
97
+ return;
98
+ const filtered = Array.from(slugs).filter((s) => s && s.length > 0);
99
+ if (filtered.length > 0)
100
+ await this.cache.invalidatePagesBySlug(filtered);
101
+ }
102
+ async list(filters = {}) {
103
+ const em = this.emFactory();
104
+ const params = [];
105
+ const where = [];
106
+ if (filters.salesChannelId) {
107
+ params.push(filters.salesChannelId);
108
+ where.push(`exists (
109
+ select 1 from cms_page_sales_channels cpsc
110
+ where cpsc.page_id = p.id and cpsc.sales_channel_id = ?
111
+ )`);
112
+ }
113
+ if (filters.status) {
114
+ params.push(filters.status);
115
+ where.push('p.status = ?');
116
+ }
117
+ if (filters.q) {
118
+ params.push(`%${filters.q.toLowerCase()}%`);
119
+ where.push('(lower(p.name) like ? or lower(p.slug) like ?)');
120
+ params.push(`%${filters.q.toLowerCase()}%`);
121
+ }
122
+ const rows = (await em.execute(`select p.* from cms_pages p
123
+ ${where.length > 0 ? `where ${where.join(' and ')}` : ''}
124
+ order by p.updated_at desc
125
+ limit 50`, params));
126
+ const data = await Promise.all(rows.map((row) => this.toSummary(row)));
127
+ return { data, nextCursor: null };
128
+ }
129
+ async create(input) {
130
+ // Before the transaction, deliberately: this is a judgement on the input
131
+ // against the deployment's configuration and touches no row, so opening a
132
+ // transaction to refuse it would hold a connection for the length of a
133
+ // settings read.
134
+ await this.assertSlugNotReserved(input.slug);
135
+ const em = this.emFactory();
136
+ const id = randomUUID();
137
+ const now = new Date();
138
+ const meta = this.splitMeta(input.meta ?? null);
139
+ const title = Object.fromEntries(input.languages.map((language) => [
140
+ language,
141
+ input.meta?.[language]?.title?.trim() || input.name,
142
+ ]));
143
+ const body = Object.fromEntries(input.languages.map((language) => [language, '']));
144
+ await em.transactional(async (tx) => {
145
+ await this.assertLanguagesInChannelScope(tx, input.languages, input.salesChannelIds);
146
+ await this.assertSlugAvailable(tx, input.slug, input.salesChannelIds);
147
+ await tx.execute(`insert into cms_pages
148
+ (id, path, status, title, body, published_at, archived_at, created_at, updated_at,
149
+ name, slug, active, description, meta_title, meta_description, meta_keywords,
150
+ content, languages, version)
151
+ values (?, ?, 'draft', ?::jsonb, ?::jsonb, null, null, ?, ?,
152
+ ?, ?, ?, ?, ?::jsonb, ?::jsonb, ?::jsonb, ?::jsonb, ?::jsonb, 1)`, [
153
+ id,
154
+ this.legacyPath(input.slug, id),
155
+ JSON.stringify(title),
156
+ JSON.stringify(body),
157
+ now,
158
+ now,
159
+ input.name,
160
+ input.slug,
161
+ input.active ?? true,
162
+ input.description ?? null,
163
+ JSON.stringify(meta.metaTitle),
164
+ JSON.stringify(meta.metaDescription),
165
+ JSON.stringify(meta.metaKeywords),
166
+ JSON.stringify(emptyContent),
167
+ JSON.stringify(input.languages),
168
+ ]);
169
+ await this.replaceChannelScope(tx, id, input.salesChannelIds, input.slug);
170
+ });
171
+ await this.invalidateForSlugs([input.slug]);
172
+ return this.get(id);
173
+ }
174
+ async get(id) {
175
+ const row = await this.findRow(id);
176
+ if (!row)
177
+ throw new HttpError(404, ERROR_CODES.CMS_PAGE_NOT_FOUND, 'CMS Page not found.');
178
+ return this.toDetail(row);
179
+ }
180
+ async patch(id, input) {
181
+ // Only when the request **writes** a slug. A patch that renames a page or
182
+ // edits its meta description is not choosing an address, and refusing it
183
+ // would make every page whose slug predates the deployment's reserved set
184
+ // uneditable — a rule that punishes the operator for a decision somebody
185
+ // else made later.
186
+ if (input.slug !== undefined)
187
+ await this.assertSlugNotReserved(input.slug);
188
+ const em = this.emFactory();
189
+ const slugsToInvalidate = new Set();
190
+ await em.transactional(async (tx) => {
191
+ const row = await this.findRow(id, tx);
192
+ if (!row)
193
+ throw new HttpError(404, ERROR_CODES.CMS_PAGE_NOT_FOUND, 'CMS Page not found.');
194
+ this.assertVersion(row, input.version);
195
+ slugsToInvalidate.add(row.slug);
196
+ const nextSlug = input.slug ?? row.slug;
197
+ const nextChannels = input.salesChannelIds ?? (await this.channelIdsFor(id, tx));
198
+ const nextLanguages = input.languages ?? row.languages;
199
+ await this.assertLanguagesInChannelScope(tx, nextLanguages, nextChannels);
200
+ if (input.slug || input.salesChannelIds) {
201
+ await this.assertSlugAvailable(tx, nextSlug, nextChannels, id);
202
+ }
203
+ const meta = input.meta !== undefined ? this.splitMeta(input.meta ?? null) : null;
204
+ const sets = [];
205
+ const params = [];
206
+ const set = (sql, value) => {
207
+ sets.push(sql);
208
+ params.push(value);
209
+ };
210
+ if (input.name !== undefined)
211
+ set('name = ?', input.name);
212
+ if (input.slug !== undefined)
213
+ set('slug = ?', input.slug);
214
+ if (input.active !== undefined)
215
+ set('active = ?', input.active);
216
+ if (input.description !== undefined)
217
+ set('description = ?', input.description);
218
+ if (input.languages !== undefined)
219
+ set('languages = ?::jsonb', JSON.stringify(input.languages));
220
+ if (meta) {
221
+ set('meta_title = ?::jsonb', JSON.stringify(meta.metaTitle));
222
+ set('meta_description = ?::jsonb', JSON.stringify(meta.metaDescription));
223
+ set('meta_keywords = ?::jsonb', JSON.stringify(meta.metaKeywords));
224
+ }
225
+ if (sets.length > 0) {
226
+ params.push(id);
227
+ await tx.execute(`update cms_pages
228
+ set ${sets.join(', ')}, version = version + 1, updated_at = now()
229
+ where id = ?`, params);
230
+ }
231
+ if (input.salesChannelIds || input.slug) {
232
+ await this.replaceChannelScope(tx, id, nextChannels, nextSlug);
233
+ }
234
+ slugsToInvalidate.add(nextSlug);
235
+ });
236
+ await this.invalidateForSlugs(slugsToInvalidate);
237
+ return this.get(id);
238
+ }
239
+ async setContent(id, language, data, version) {
240
+ const em = this.emFactory();
241
+ await em.transactional(async (tx) => {
242
+ const row = await this.findRow(id, tx);
243
+ if (!row)
244
+ throw new HttpError(404, ERROR_CODES.CMS_PAGE_NOT_FOUND, 'CMS Page not found.');
245
+ this.assertVersion(row, version);
246
+ const unknown = walkUnknownComponents(data, new Set(this.knownComponentNames()));
247
+ if (unknown.size > 0) {
248
+ console.warn(`CMS page ${id} saved with unknown components: ${Array.from(unknown).join(', ')}`);
249
+ }
250
+ await this.assertBlockEmbedsExist(tx, data, await this.channelIdsFor(id, tx));
251
+ const content = {
252
+ languages: {
253
+ ...(row.content.languages ?? {}),
254
+ [language]: data,
255
+ },
256
+ };
257
+ if (!row.languages.includes(language)) {
258
+ throw new HttpError(400, ERROR_CODES.CMS_LANGUAGE_NOT_IN_CHANNEL_SCOPE, `CMS Page language "${language}" is not assigned to this page.`);
259
+ }
260
+ await tx.execute(`update cms_pages
261
+ set content = ?::jsonb, version = version + 1, updated_at = now()
262
+ where id = ?`, [JSON.stringify(content), id]);
263
+ });
264
+ await this.invalidateForPageId(id);
265
+ return this.get(id);
266
+ }
267
+ async publish(id) {
268
+ return this.transition(id, 'published');
269
+ }
270
+ async archive(id) {
271
+ return this.transition(id, 'archived');
272
+ }
273
+ async unarchive(id) {
274
+ return this.transition(id, 'draft');
275
+ }
276
+ async delete(id) {
277
+ if (this.references) {
278
+ const refs = await this.references.findPageReferences(id);
279
+ if (refs.length > 0) {
280
+ throw new HttpError(409, ERROR_CODES.CMS_REFERENCED, 'CMS Page is referenced.');
281
+ }
282
+ }
283
+ await this.invalidateForPageId(id);
284
+ await this.emFactory().execute('delete from cms_pages where id = ?', [id]);
285
+ }
286
+ async transition(id, status) {
287
+ const em = this.emFactory();
288
+ const row = await this.findRow(id, em);
289
+ if (!row)
290
+ throw new HttpError(404, ERROR_CODES.CMS_PAGE_NOT_FOUND, 'CMS Page not found.');
291
+ await em.execute(`update cms_pages
292
+ set status = ?,
293
+ published_at = case when ? = 'published' then now() else published_at end,
294
+ archived_at = case when ? = 'archived' then now() else null end,
295
+ version = version + 1,
296
+ updated_at = now()
297
+ where id = ?`, [status, status, status, id]);
298
+ await this.invalidateForPageId(id);
299
+ return this.get(id);
300
+ }
301
+ async findRow(id, em = this.emFactory()) {
302
+ const rows = (await em.execute('select * from cms_pages where id = ?', [
303
+ id,
304
+ ]));
305
+ return rows[0] ?? null;
306
+ }
307
+ async assertSlugAvailable(em, slug, salesChannelIds, exceptPageId) {
308
+ if (salesChannelIds.length === 0)
309
+ return;
310
+ const placeholders = salesChannelIds.map(() => '?').join(', ');
311
+ const rows = (await em.execute(`select page_id from cms_page_sales_channels
312
+ where slug = ? and sales_channel_id in (${placeholders})
313
+ ${exceptPageId ? 'and page_id <> ?' : ''}
314
+ limit 1`, exceptPageId ? [slug, ...salesChannelIds, exceptPageId] : [slug, ...salesChannelIds]));
315
+ if (rows.length > 0) {
316
+ throw new HttpError(409, ERROR_CODES.CMS_SLUG_CONFLICT, 'CMS Page slug already exists.');
317
+ }
318
+ }
319
+ channelLanguageCodes(value) {
320
+ if (Array.isArray(value)) {
321
+ return value.filter((item) => typeof item === 'string');
322
+ }
323
+ if (typeof value === 'string') {
324
+ try {
325
+ const parsed = JSON.parse(value);
326
+ if (Array.isArray(parsed)) {
327
+ return parsed.filter((item) => typeof item === 'string');
328
+ }
329
+ }
330
+ catch {
331
+ return [];
332
+ }
333
+ }
334
+ return [];
335
+ }
336
+ resolvedChannelLanguageCodes(languages, defaultLanguage) {
337
+ const codes = this.channelLanguageCodes(languages);
338
+ if (codes.length > 0)
339
+ return codes;
340
+ if (typeof defaultLanguage === 'string' && defaultLanguage.length > 0) {
341
+ return [defaultLanguage];
342
+ }
343
+ return [];
344
+ }
345
+ async assertLanguagesInChannelScope(em, languages, salesChannelIds) {
346
+ if (languages.length === 0 || salesChannelIds.length === 0)
347
+ return;
348
+ /**
349
+ * The kernel's own entity, not `select languages, default_language from
350
+ * sales_channels` (feature 075, D-87). `sales_channels` is the kernel's
351
+ * table since feature 072 moved the resolution machinery there, and a
352
+ * module relating into the kernel by ORM is the sanctioned access. The read
353
+ * stays on the caller's `em` so it still sees the transaction the write is
354
+ * being validated inside.
355
+ */
356
+ const channels = await em.find(SalesChannel, { id: { $in: salesChannelIds } });
357
+ const allowed = new Set(channels.flatMap((channel) => this.resolvedChannelLanguageCodes(channel.languages, channel.defaultLanguage)));
358
+ const unsupported = languages.find((language) => !allowed.has(language));
359
+ if (unsupported) {
360
+ throw new HttpError(400, ERROR_CODES.CMS_LANGUAGE_NOT_IN_CHANNEL_SCOPE, `CMS Page language "${unsupported}" is not configured for the assigned sales channels.`);
361
+ }
362
+ }
363
+ async replaceChannelScope(em, pageId, salesChannelIds, slug) {
364
+ await em.execute('delete from cms_page_sales_channels where page_id = ?', [
365
+ pageId,
366
+ ]);
367
+ for (const salesChannelId of salesChannelIds) {
368
+ await em.execute(`insert into cms_page_sales_channels (page_id, sales_channel_id, slug)
369
+ values (?, ?, ?)`, [pageId, salesChannelId, slug]);
370
+ }
371
+ }
372
+ async assertBlockEmbedsExist(em, data, salesChannelIds) {
373
+ const codes = Array.from(walkBlockEmbeds(data));
374
+ if (codes.length === 0 || salesChannelIds.length === 0)
375
+ return;
376
+ const codePlaceholders = codes.map(() => '?').join(', ');
377
+ const channelPlaceholders = salesChannelIds.map(() => '?').join(', ');
378
+ const rows = (await em.execute(`select distinct code
379
+ from cms_block_sales_channels
380
+ where code in (${codePlaceholders})
381
+ and sales_channel_id in (${channelPlaceholders})`, [...codes, ...salesChannelIds]));
382
+ const found = new Set(rows.map((row) => row.code));
383
+ const missing = codes.find((code) => !found.has(code));
384
+ if (missing) {
385
+ throw new HttpError(404, ERROR_CODES.CMS_BLOCK_NOT_FOUND, `CMS Block "${missing}" not found.`);
386
+ }
387
+ }
388
+ async channelIdsFor(pageId, em = this.emFactory()) {
389
+ const rows = (await em.execute('select sales_channel_id::text as id from cms_page_sales_channels where page_id = ?', [pageId]));
390
+ return rows.map((row) => row.id);
391
+ }
392
+ assertVersion(row, version) {
393
+ if (version !== undefined && version !== row.version) {
394
+ throw new HttpError(409, ERROR_CODES.VERSION_CONFLICT, 'CMS Page was updated concurrently.');
395
+ }
396
+ }
397
+ splitMeta(meta) {
398
+ const metaTitle = {};
399
+ const metaDescription = {};
400
+ const metaKeywords = {};
401
+ const entries = Object.entries(meta ?? {});
402
+ for (const [language, value] of entries) {
403
+ if (value.title !== undefined)
404
+ metaTitle[language] = value.title;
405
+ if (value.description !== undefined)
406
+ metaDescription[language] = value.description;
407
+ if (value.keywords !== undefined)
408
+ metaKeywords[language] = value.keywords;
409
+ }
410
+ return { metaTitle, metaDescription, metaKeywords };
411
+ }
412
+ async toSummary(row) {
413
+ return {
414
+ id: row.id,
415
+ name: row.name,
416
+ slug: row.slug,
417
+ status: row.status,
418
+ active: row.active,
419
+ description: row.description,
420
+ salesChannelIds: await this.channelIdsFor(row.id),
421
+ languages: row.languages,
422
+ version: row.version,
423
+ createdAt: this.iso(row.created_at),
424
+ updatedAt: this.iso(row.updated_at),
425
+ };
426
+ }
427
+ async toDetail(row) {
428
+ return {
429
+ ...(await this.toSummary(row)),
430
+ meta: this.combineMeta(row),
431
+ content: {
432
+ languages: row.content.languages ?? {},
433
+ },
434
+ };
435
+ }
436
+ combineMeta(row) {
437
+ const languages = new Set([
438
+ ...Object.keys(row.meta_title ?? {}),
439
+ ...Object.keys(row.meta_description ?? {}),
440
+ ...Object.keys(row.meta_keywords ?? {}),
441
+ ]);
442
+ if (languages.size === 0)
443
+ return null;
444
+ const meta = {};
445
+ for (const language of languages) {
446
+ meta[language] = {
447
+ ...(row.meta_title?.[language] !== undefined
448
+ ? { title: row.meta_title[language] }
449
+ : {}),
450
+ ...(row.meta_description?.[language] !== undefined
451
+ ? { description: row.meta_description[language] }
452
+ : {}),
453
+ ...(row.meta_keywords?.[language] !== undefined
454
+ ? { keywords: row.meta_keywords[language] }
455
+ : {}),
456
+ };
457
+ }
458
+ return meta;
459
+ }
460
+ iso(value) {
461
+ return value instanceof Date ? value.toISOString() : new Date(value).toISOString();
462
+ }
463
+ legacyPath(slug, id) {
464
+ const suffix = id.slice(0, 8);
465
+ return `${slug}-${suffix}`.slice(0, 180);
466
+ }
467
+ }
468
+ //# sourceMappingURL=cms-page-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cms-page-service.js","sourceRoot":"","sources":["../../../src/backend/services/cms-page-service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ import type { CmsReference, CmsExternalReferenceScanner } from '@endora-commerce/contracts';
2
+ import type { EntityManager } from '@mikro-orm/postgresql';
3
+ /**
4
+ * Both shapes moved to `@endora-commerce/contracts` in feature 075's Phase P — `megamenu`
5
+ * contributes a scanner, which makes the descriptor a boundary shape rather
6
+ * than an internal. Re-exported here for the length of Phase P, which cuts no
7
+ * consumer.
8
+ */
9
+ export type { CmsReference, CmsExternalReferenceScanner };
10
+ export declare class CmsReferenceRegistry {
11
+ private readonly emFactory;
12
+ private readonly externalScanners;
13
+ constructor(emFactory: () => EntityManager);
14
+ /**
15
+ * Register an external scanner. Another module calls this from its own
16
+ * `ctx.onBoot`, so the contribution passes through the lifecycle seams rather
17
+ * than a composition root's back door. Idempotent across registrations of the
18
+ * same scanner instance.
19
+ */
20
+ register(scanner: CmsExternalReferenceScanner): void;
21
+ /** The contributing module of every registered scanner, in registration order. */
22
+ externalOwners(): readonly string[];
23
+ /** Pages and modules that point at the Page with this id. */
24
+ findPageReferences(pageId: string): Promise<CmsReference[]>;
25
+ /** Pages, Templates, Hooks, and external modules that reference the Block. */
26
+ findBlockReferences(blockIdOrCode: string, blockCode?: string): Promise<CmsReference[]>;
27
+ /** Pages and Blocks that point at the Template with this code. */
28
+ findTemplateReferences(templateIdOrCode: string, templateCode?: string): Promise<CmsReference[]>;
29
+ }
30
+ //# sourceMappingURL=cms-reference-registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cms-reference-registry.d.ts","sourceRoot":"","sources":["../../../src/backend/services/cms-reference-registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,2BAA2B,EAAE,MAAM,4BAA4B,CAAC;AAC5F,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAG3D;;;;;GAKG;AACH,YAAY,EAAE,YAAY,EAAE,2BAA2B,EAAE,CAAC;AAE1D,qBAAa,oBAAoB;IAGnB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAFtC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAqC;gBAEzC,SAAS,EAAE,MAAM,aAAa;IAE3D;;;;;OAKG;IACH,QAAQ,CAAC,OAAO,EAAE,2BAA2B,GAAG,IAAI;IAMpD,kFAAkF;IAClF,cAAc,IAAI,SAAS,MAAM,EAAE;IAInC,6DAA6D;IACvD,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;IAUjE,8EAA8E;IACxE,mBAAmB,CAAC,aAAa,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;IAiD7F,kEAAkE;IAC5D,sBAAsB,CAAC,gBAAgB,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;CAkCvG"}
@@ -0,0 +1,98 @@
1
+ import { walkBlockEmbeds, walkTemplateEmbeds } from './content-tree-walker.js';
2
+ export class CmsReferenceRegistry {
3
+ emFactory;
4
+ externalScanners = [];
5
+ constructor(emFactory) {
6
+ this.emFactory = emFactory;
7
+ }
8
+ /**
9
+ * Register an external scanner. Another module calls this from its own
10
+ * `ctx.onBoot`, so the contribution passes through the lifecycle seams rather
11
+ * than a composition root's back door. Idempotent across registrations of the
12
+ * same scanner instance.
13
+ */
14
+ register(scanner) {
15
+ if (!this.externalScanners.includes(scanner)) {
16
+ this.externalScanners.push(scanner);
17
+ }
18
+ }
19
+ /** The contributing module of every registered scanner, in registration order. */
20
+ externalOwners() {
21
+ return this.externalScanners.map((scanner) => scanner.ownerModuleId);
22
+ }
23
+ /** Pages and modules that point at the Page with this id. */
24
+ async findPageReferences(pageId) {
25
+ const out = [];
26
+ for (const scanner of this.externalScanners) {
27
+ if (scanner.findPageReferences) {
28
+ out.push(...(await scanner.findPageReferences(pageId)));
29
+ }
30
+ }
31
+ return out;
32
+ }
33
+ /** Pages, Templates, Hooks, and external modules that reference the Block. */
34
+ async findBlockReferences(blockIdOrCode, blockCode) {
35
+ // Backwards-compat: callers that supply only the code (the historical
36
+ // shape) skip the external scanners that need an id.
37
+ const code = blockCode ?? blockIdOrCode;
38
+ const blockId = blockCode === undefined ? null : blockIdOrCode;
39
+ const out = [];
40
+ const em = this.emFactory();
41
+ const pages = (await em.execute(`select id::text, name, content from cms_pages`));
42
+ for (const row of pages) {
43
+ if (walkBlockEmbeds(row.content).has(code)) {
44
+ out.push({ kind: 'cms_page', entityId: row.id, label: row.name });
45
+ }
46
+ }
47
+ const templates = (await em.execute(`select id::text, name, content from cms_templates`));
48
+ for (const row of templates) {
49
+ if (walkBlockEmbeds(row.content).has(code)) {
50
+ out.push({ kind: 'cms_template', entityId: row.id, label: row.name });
51
+ }
52
+ }
53
+ const hooks = (await em.execute(`select h.id::text, h.name
54
+ from cms_hook_block_attachments a
55
+ join cms_hooks h on h.id = a.hook_id
56
+ join cms_blocks b on b.id = a.block_id
57
+ where b.code = ?`, [code]));
58
+ for (const row of hooks) {
59
+ out.push({ kind: 'cms_hook', entityId: row.id, label: row.name });
60
+ }
61
+ if (blockId) {
62
+ for (const scanner of this.externalScanners) {
63
+ if (scanner.findBlockReferences) {
64
+ out.push(...(await scanner.findBlockReferences(blockId, code)));
65
+ }
66
+ }
67
+ }
68
+ return out;
69
+ }
70
+ /** Pages and Blocks that point at the Template with this code. */
71
+ async findTemplateReferences(templateIdOrCode, templateCode) {
72
+ const code = templateCode ?? templateIdOrCode;
73
+ const templateId = templateCode === undefined ? null : templateIdOrCode;
74
+ const out = [];
75
+ const em = this.emFactory();
76
+ const pages = (await em.execute(`select id::text, name, content from cms_pages`));
77
+ for (const row of pages) {
78
+ if (walkTemplateEmbeds(row.content).has(code)) {
79
+ out.push({ kind: 'cms_page', entityId: row.id, label: row.name });
80
+ }
81
+ }
82
+ const blocks = (await em.execute(`select id::text, name, content from cms_blocks`));
83
+ for (const row of blocks) {
84
+ if (walkTemplateEmbeds(row.content).has(code)) {
85
+ out.push({ kind: 'cms_block', entityId: row.id, label: row.name });
86
+ }
87
+ }
88
+ if (templateId) {
89
+ for (const scanner of this.externalScanners) {
90
+ if (scanner.findTemplateReferences) {
91
+ out.push(...(await scanner.findTemplateReferences(templateId, code)));
92
+ }
93
+ }
94
+ }
95
+ return out;
96
+ }
97
+ }
98
+ //# sourceMappingURL=cms-reference-registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cms-reference-registry.js","sourceRoot":"","sources":["../../../src/backend/services/cms-reference-registry.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAU/E,MAAM,OAAO,oBAAoB;IAGF;IAFZ,gBAAgB,GAAkC,EAAE,CAAC;IAEtE,YAA6B,SAA8B;QAA9B,cAAS,GAAT,SAAS,CAAqB;IAAG,CAAC;IAE/D;;;;;OAKG;IACH,QAAQ,CAAC,OAAoC;QAC3C,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;YAC7C,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACtC,CAAC;IACH,CAAC;IAED,kFAAkF;IAClF,cAAc;QACZ,OAAO,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC;IACvE,CAAC;IAED,6DAA6D;IAC7D,KAAK,CAAC,kBAAkB,CAAC,MAAc;QACrC,MAAM,GAAG,GAAmB,EAAE,CAAC;QAC/B,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,gBAAgB,EAAE,CAAC;YAC5C,IAAI,OAAO,CAAC,kBAAkB,EAAE,CAAC;gBAC/B,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,OAAO,CAAC,kBAAkB,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;YAC1D,CAAC;QACH,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC;IAED,8EAA8E;IAC9E,KAAK,CAAC,mBAAmB,CAAC,aAAqB,EAAE,SAAkB;QACjE,sEAAsE;QACtE,qDAAqD;QACrD,MAAM,IAAI,GAAG,SAAS,IAAI,aAAa,CAAC;QACxC,MAAM,OAAO,GAAG,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,aAAa,CAAC;QAC/D,MAAM,GAAG,GAAmB,EAAE,CAAC;QAC/B,MAAM,EAAE,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC;QAE5B,MAAM,KAAK,GAAG,CAAC,MAAM,EAAE,CAAC,OAAO,CAC7B,+CAA+C,CAChD,CAA0D,CAAC;QAC5D,KAAK,MAAM,GAAG,IAAI,KAAK,EAAE,CAAC;YACxB,IAAI,eAAe,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC3C,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,CAAC,EAAE,EAAE,KAAK,EAAE,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;YACpE,CAAC;QACH,CAAC;QAED,MAAM,SAAS,GAAG,CAAC,MAAM,EAAE,CAAC,OAAO,CACjC,mDAAmD,CACpD,CAA0D,CAAC;QAC5D,KAAK,MAAM,GAAG,IAAI,SAAS,EAAE,CAAC;YAC5B,IAAI,eAAe,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC3C,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,cAAc,EAAE,QAAQ,EAAE,GAAG,CAAC,EAAE,EAAE,KAAK,EAAE,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;YACxE,CAAC;QACH,CAAC;QAED,MAAM,KAAK,GAAG,CAAC,MAAM,EAAE,CAAC,OAAO,CAC7B;;;;wBAIkB,EAClB,CAAC,IAAI,CAAC,CACP,CAAwC,CAAC;QAC1C,KAAK,MAAM,GAAG,IAAI,KAAK,EAAE,CAAC;YACxB,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,CAAC,EAAE,EAAE,KAAK,EAAE,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;QACpE,CAAC;QAED,IAAI,OAAO,EAAE,CAAC;YACZ,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,gBAAgB,EAAE,CAAC;gBAC5C,IAAI,OAAO,CAAC,mBAAmB,EAAE,CAAC;oBAChC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,OAAO,CAAC,mBAAmB,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC;gBAClE,CAAC;YACH,CAAC;QACH,CAAC;QAED,OAAO,GAAG,CAAC;IACb,CAAC;IAED,kEAAkE;IAClE,KAAK,CAAC,sBAAsB,CAAC,gBAAwB,EAAE,YAAqB;QAC1E,MAAM,IAAI,GAAG,YAAY,IAAI,gBAAgB,CAAC;QAC9C,MAAM,UAAU,GAAG,YAAY,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,gBAAgB,CAAC;QACxE,MAAM,GAAG,GAAmB,EAAE,CAAC;QAC/B,MAAM,EAAE,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC;QAE5B,MAAM,KAAK,GAAG,CAAC,MAAM,EAAE,CAAC,OAAO,CAC7B,+CAA+C,CAChD,CAA0D,CAAC;QAC5D,KAAK,MAAM,GAAG,IAAI,KAAK,EAAE,CAAC;YACxB,IAAI,kBAAkB,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC9C,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,CAAC,EAAE,EAAE,KAAK,EAAE,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;YACpE,CAAC;QACH,CAAC;QAED,MAAM,MAAM,GAAG,CAAC,MAAM,EAAE,CAAC,OAAO,CAC9B,gDAAgD,CACjD,CAA0D,CAAC;QAC5D,KAAK,MAAM,GAAG,IAAI,MAAM,EAAE,CAAC;YACzB,IAAI,kBAAkB,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC9C,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,QAAQ,EAAE,GAAG,CAAC,EAAE,EAAE,KAAK,EAAE,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;YACrE,CAAC;QACH,CAAC;QAED,IAAI,UAAU,EAAE,CAAC;YACf,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,gBAAgB,EAAE,CAAC;gBAC5C,IAAI,OAAO,CAAC,sBAAsB,EAAE,CAAC;oBACnC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,OAAO,CAAC,sBAAsB,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC;gBACxE,CAAC;YACH,CAAC;QACH,CAAC;QAED,OAAO,GAAG,CAAC;IACb,CAAC;CACF"}