@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.
- package/LICENSE +21 -0
- package/README.md +65 -2
- package/dist/admin/api/cms-client.d.ts +77 -0
- package/dist/admin/api/cms-client.d.ts.map +1 -0
- package/dist/admin/api/cms-client.js +162 -0
- package/dist/admin/api/cms-client.js.map +1 -0
- package/dist/admin/components/AdminCatalogPreviewProvider.d.ts +6 -0
- package/dist/admin/components/AdminCatalogPreviewProvider.d.ts.map +1 -0
- package/dist/admin/components/AdminCatalogPreviewProvider.js +74 -0
- package/dist/admin/components/AdminCatalogPreviewProvider.js.map +1 -0
- package/dist/admin/components/AdminCmsAssetProvider.d.ts +9 -0
- package/dist/admin/components/AdminCmsAssetProvider.d.ts.map +1 -0
- package/dist/admin/components/AdminCmsAssetProvider.js +50 -0
- package/dist/admin/components/AdminCmsAssetProvider.js.map +1 -0
- package/dist/admin/components/BackgroundFields.d.ts +4 -0
- package/dist/admin/components/BackgroundFields.d.ts.map +1 -0
- package/dist/admin/components/BackgroundFields.js +40 -0
- package/dist/admin/components/BackgroundFields.js.map +1 -0
- package/dist/admin/components/ButtonLinkFields.d.ts +6 -0
- package/dist/admin/components/ButtonLinkFields.d.ts.map +1 -0
- package/dist/admin/components/ButtonLinkFields.js +127 -0
- package/dist/admin/components/ButtonLinkFields.js.map +1 -0
- package/dist/admin/components/CarouselPreviewNav.d.ts +12 -0
- package/dist/admin/components/CarouselPreviewNav.d.ts.map +1 -0
- package/dist/admin/components/CarouselPreviewNav.js +31 -0
- package/dist/admin/components/CarouselPreviewNav.js.map +1 -0
- package/dist/admin/components/CmsContentEditorLayout.d.ts +12 -0
- package/dist/admin/components/CmsContentEditorLayout.d.ts.map +1 -0
- package/dist/admin/components/CmsContentEditorLayout.js +9 -0
- package/dist/admin/components/CmsContentEditorLayout.js.map +1 -0
- package/dist/admin/components/ComponentDragHandle.d.ts +6 -0
- package/dist/admin/components/ComponentDragHandle.d.ts.map +1 -0
- package/dist/admin/components/ComponentDragHandle.js +119 -0
- package/dist/admin/components/ComponentDragHandle.js.map +1 -0
- package/dist/admin/components/ContentSliderActionBarExtras.d.ts +6 -0
- package/dist/admin/components/ContentSliderActionBarExtras.d.ts.map +1 -0
- package/dist/admin/components/ContentSliderActionBarExtras.js +109 -0
- package/dist/admin/components/ContentSliderActionBarExtras.js.map +1 -0
- package/dist/admin/components/HookBlockAttachmentsPanel.d.ts +9 -0
- package/dist/admin/components/HookBlockAttachmentsPanel.d.ts.map +1 -0
- package/dist/admin/components/HookBlockAttachmentsPanel.js +137 -0
- package/dist/admin/components/HookBlockAttachmentsPanel.js.map +1 -0
- package/dist/admin/components/PageBuilderActionBar.d.ts +10 -0
- package/dist/admin/components/PageBuilderActionBar.d.ts.map +1 -0
- package/dist/admin/components/PageBuilderActionBar.js +118 -0
- package/dist/admin/components/PageBuilderActionBar.js.map +1 -0
- package/dist/admin/components/PageBuilderDrawer.d.ts +16 -0
- package/dist/admin/components/PageBuilderDrawer.d.ts.map +1 -0
- package/dist/admin/components/PageBuilderDrawer.js +53 -0
- package/dist/admin/components/PageBuilderDrawer.js.map +1 -0
- package/dist/admin/components/PageBuilderEditor.d.ts +45 -0
- package/dist/admin/components/PageBuilderEditor.d.ts.map +1 -0
- package/dist/admin/components/PageBuilderEditor.js +632 -0
- package/dist/admin/components/PageBuilderEditor.js.map +1 -0
- package/dist/admin/components/PuckActionGuard.d.ts +12 -0
- package/dist/admin/components/PuckActionGuard.d.ts.map +1 -0
- package/dist/admin/components/PuckActionGuard.js +30 -0
- package/dist/admin/components/PuckActionGuard.js.map +1 -0
- package/dist/admin/components/RowLayoutPicker.d.ts +8 -0
- package/dist/admin/components/RowLayoutPicker.d.ts.map +1 -0
- package/dist/admin/components/RowLayoutPicker.js +17 -0
- package/dist/admin/components/RowLayoutPicker.js.map +1 -0
- package/dist/admin/components/SliderPreviewActionBarExtras.d.ts +6 -0
- package/dist/admin/components/SliderPreviewActionBarExtras.d.ts.map +1 -0
- package/dist/admin/components/SliderPreviewActionBarExtras.js +32 -0
- package/dist/admin/components/SliderPreviewActionBarExtras.js.map +1 -0
- package/dist/admin/components/admin-catalog-preview-map.d.ts +17 -0
- package/dist/admin/components/admin-catalog-preview-map.d.ts.map +1 -0
- package/dist/admin/components/admin-catalog-preview-map.js +18 -0
- package/dist/admin/components/admin-catalog-preview-map.js.map +1 -0
- package/dist/admin/components/build-viewports.d.ts +23 -0
- package/dist/admin/components/build-viewports.d.ts.map +1 -0
- package/dist/admin/components/build-viewports.js +23 -0
- package/dist/admin/components/build-viewports.js.map +1 -0
- package/dist/admin/components/cms-template-layout.d.ts +16 -0
- package/dist/admin/components/cms-template-layout.d.ts.map +1 -0
- package/dist/admin/components/cms-template-layout.js +53 -0
- package/dist/admin/components/cms-template-layout.js.map +1 -0
- package/dist/admin/components/page-builder-i18n.d.ts +27 -0
- package/dist/admin/components/page-builder-i18n.d.ts.map +1 -0
- package/dist/admin/components/page-builder-i18n.js +34 -0
- package/dist/admin/components/page-builder-i18n.js.map +1 -0
- package/dist/admin/components/puck-safe.d.ts +10 -0
- package/dist/admin/components/puck-safe.d.ts.map +1 -0
- package/dist/admin/components/puck-safe.js +22 -0
- package/dist/admin/components/puck-safe.js.map +1 -0
- package/dist/admin/components/scope-utils.d.ts +4 -0
- package/dist/admin/components/scope-utils.d.ts.map +1 -0
- package/dist/admin/components/scope-utils.js +7 -0
- package/dist/admin/components/scope-utils.js.map +1 -0
- package/dist/admin/editors/BlockEditor.d.ts +9 -0
- package/dist/admin/editors/BlockEditor.d.ts.map +1 -0
- package/dist/admin/editors/BlockEditor.js +217 -0
- package/dist/admin/editors/BlockEditor.js.map +1 -0
- package/dist/admin/editors/PageEditor.d.ts +9 -0
- package/dist/admin/editors/PageEditor.d.ts.map +1 -0
- package/dist/admin/editors/PageEditor.js +316 -0
- package/dist/admin/editors/PageEditor.js.map +1 -0
- package/dist/admin/editors/TemplateEditor.d.ts +9 -0
- package/dist/admin/editors/TemplateEditor.d.ts.map +1 -0
- package/dist/admin/editors/TemplateEditor.js +180 -0
- package/dist/admin/editors/TemplateEditor.js.map +1 -0
- package/dist/admin/index.d.ts +38 -0
- package/dist/admin/index.d.ts.map +1 -0
- package/dist/admin/index.js +144 -0
- package/dist/admin/index.js.map +1 -0
- package/dist/admin/pages/BlocksListPage.d.ts +9 -0
- package/dist/admin/pages/BlocksListPage.d.ts.map +1 -0
- package/dist/admin/pages/BlocksListPage.js +47 -0
- package/dist/admin/pages/BlocksListPage.js.map +1 -0
- package/dist/admin/pages/HooksPage.d.ts +9 -0
- package/dist/admin/pages/HooksPage.d.ts.map +1 -0
- package/dist/admin/pages/HooksPage.js +41 -0
- package/dist/admin/pages/HooksPage.js.map +1 -0
- package/dist/admin/pages/PagesListPage.d.ts +9 -0
- package/dist/admin/pages/PagesListPage.d.ts.map +1 -0
- package/dist/admin/pages/PagesListPage.js +51 -0
- package/dist/admin/pages/PagesListPage.js.map +1 -0
- package/dist/admin/pages/TemplatesListPage.d.ts +9 -0
- package/dist/admin/pages/TemplatesListPage.d.ts.map +1 -0
- package/dist/admin/pages/TemplatesListPage.js +47 -0
- package/dist/admin/pages/TemplatesListPage.js.map +1 -0
- package/dist/admin-ui/index.d.ts +90 -0
- package/dist/admin-ui/index.d.ts.map +1 -0
- package/dist/admin-ui/index.js +89 -0
- package/dist/admin-ui/index.js.map +1 -0
- package/dist/backend/cli/block-names.d.ts +92 -0
- package/dist/backend/cli/block-names.d.ts.map +1 -0
- package/dist/backend/cli/block-names.js +132 -0
- package/dist/backend/cli/block-names.js.map +1 -0
- package/dist/backend/entities/cms-block.entity.d.ts +20 -0
- package/dist/backend/entities/cms-block.entity.d.ts.map +1 -0
- package/dist/backend/entities/cms-block.entity.js +77 -0
- package/dist/backend/entities/cms-block.entity.js.map +1 -0
- package/dist/backend/entities/cms-hook-block-attachment.entity.d.ts +15 -0
- package/dist/backend/entities/cms-hook-block-attachment.entity.d.ts.map +1 -0
- package/dist/backend/entities/cms-hook-block-attachment.entity.js +46 -0
- package/dist/backend/entities/cms-hook-block-attachment.entity.js.map +1 -0
- package/dist/backend/entities/cms-hook.entity.d.ts +20 -0
- package/dist/backend/entities/cms-hook.entity.d.ts.map +1 -0
- package/dist/backend/entities/cms-hook.entity.js +73 -0
- package/dist/backend/entities/cms-hook.entity.js.map +1 -0
- package/dist/backend/entities/cms-page.entity.d.ts +43 -0
- package/dist/backend/entities/cms-page.entity.d.ts.map +1 -0
- package/dist/backend/entities/cms-page.entity.js +140 -0
- package/dist/backend/entities/cms-page.entity.js.map +1 -0
- package/dist/backend/entities/cms-template.entity.d.ts +20 -0
- package/dist/backend/entities/cms-template.entity.d.ts.map +1 -0
- package/dist/backend/entities/cms-template.entity.js +73 -0
- package/dist/backend/entities/cms-template.entity.js.map +1 -0
- package/dist/backend/index.d.ts +157 -0
- package/dist/backend/index.d.ts.map +1 -0
- package/dist/backend/index.js +317 -0
- package/dist/backend/index.js.map +1 -0
- package/dist/backend/plugin.d.ts +81 -0
- package/dist/backend/plugin.d.ts.map +1 -0
- package/dist/backend/plugin.js +81 -0
- package/dist/backend/plugin.js.map +1 -0
- package/dist/backend/routes.admin.d.ts +19 -0
- package/dist/backend/routes.admin.d.ts.map +1 -0
- package/dist/backend/routes.admin.js +164 -0
- package/dist/backend/routes.admin.js.map +1 -0
- package/dist/backend/routes.storefront.d.ts +6 -0
- package/dist/backend/routes.storefront.d.ts.map +1 -0
- package/dist/backend/routes.storefront.js +89 -0
- package/dist/backend/routes.storefront.js.map +1 -0
- package/dist/backend/services/asset-embed-resolver.d.ts +17 -0
- package/dist/backend/services/asset-embed-resolver.d.ts.map +1 -0
- package/dist/backend/services/asset-embed-resolver.js +40 -0
- package/dist/backend/services/asset-embed-resolver.js.map +1 -0
- package/dist/backend/services/asset-references.d.ts +4 -0
- package/dist/backend/services/asset-references.d.ts.map +1 -0
- package/dist/backend/services/asset-references.js +55 -0
- package/dist/backend/services/asset-references.js.map +1 -0
- package/dist/backend/services/cms-block-read-port.d.ts +27 -0
- package/dist/backend/services/cms-block-read-port.d.ts.map +1 -0
- package/dist/backend/services/cms-block-read-port.js +50 -0
- package/dist/backend/services/cms-block-read-port.js.map +1 -0
- package/dist/backend/services/cms-block-seed-port.d.ts +31 -0
- package/dist/backend/services/cms-block-seed-port.d.ts.map +1 -0
- package/dist/backend/services/cms-block-seed-port.js +68 -0
- package/dist/backend/services/cms-block-seed-port.js.map +1 -0
- package/dist/backend/services/cms-block-service.d.ts +38 -0
- package/dist/backend/services/cms-block-service.d.ts.map +1 -0
- package/dist/backend/services/cms-block-service.js +218 -0
- package/dist/backend/services/cms-block-service.js.map +1 -0
- package/dist/backend/services/cms-cache.d.ts +54 -0
- package/dist/backend/services/cms-cache.d.ts.map +1 -0
- package/dist/backend/services/cms-cache.js +113 -0
- package/dist/backend/services/cms-cache.js.map +1 -0
- package/dist/backend/services/cms-hook-service.d.ts +35 -0
- package/dist/backend/services/cms-hook-service.d.ts.map +1 -0
- package/dist/backend/services/cms-hook-service.js +216 -0
- package/dist/backend/services/cms-hook-service.js.map +1 -0
- package/dist/backend/services/cms-language-reference.d.ts +11 -0
- package/dist/backend/services/cms-language-reference.d.ts.map +1 -0
- package/dist/backend/services/cms-language-reference.js +26 -0
- package/dist/backend/services/cms-language-reference.js.map +1 -0
- package/dist/backend/services/cms-page-read-port.d.ts +23 -0
- package/dist/backend/services/cms-page-read-port.d.ts.map +1 -0
- package/dist/backend/services/cms-page-read-port.js +54 -0
- package/dist/backend/services/cms-page-read-port.js.map +1 -0
- package/dist/backend/services/cms-page-service.d.ts +104 -0
- package/dist/backend/services/cms-page-service.d.ts.map +1 -0
- package/dist/backend/services/cms-page-service.js +468 -0
- package/dist/backend/services/cms-page-service.js.map +1 -0
- package/dist/backend/services/cms-reference-registry.d.ts +30 -0
- package/dist/backend/services/cms-reference-registry.d.ts.map +1 -0
- package/dist/backend/services/cms-reference-registry.js +98 -0
- package/dist/backend/services/cms-reference-registry.js.map +1 -0
- package/dist/backend/services/cms-template-service.d.ts +37 -0
- package/dist/backend/services/cms-template-service.d.ts.map +1 -0
- package/dist/backend/services/cms-template-service.js +205 -0
- package/dist/backend/services/cms-template-service.js.map +1 -0
- package/dist/backend/services/content-tree-walker.d.ts +7 -0
- package/dist/backend/services/content-tree-walker.d.ts.map +1 -0
- package/dist/backend/services/content-tree-walker.js +89 -0
- package/dist/backend/services/content-tree-walker.js.map +1 -0
- package/dist/backend/services/page-builder-registry.d.ts +120 -0
- package/dist/backend/services/page-builder-registry.d.ts.map +1 -0
- package/dist/backend/services/page-builder-registry.js +220 -0
- package/dist/backend/services/page-builder-registry.js.map +1 -0
- package/dist/backend/services/seed-hooks.d.ts +22 -0
- package/dist/backend/services/seed-hooks.d.ts.map +1 -0
- package/dist/backend/services/seed-hooks.js +94 -0
- package/dist/backend/services/seed-hooks.js.map +1 -0
- package/dist/backend/services/storefront-resolver.d.ts +71 -0
- package/dist/backend/services/storefront-resolver.d.ts.map +1 -0
- package/dist/backend/services/storefront-resolver.js +329 -0
- package/dist/backend/services/storefront-resolver.js.map +1 -0
- package/dist/manifest.d.ts +225 -0
- package/dist/manifest.d.ts.map +1 -0
- package/dist/manifest.js +695 -0
- package/dist/manifest.js.map +1 -0
- package/dist/migrations/20260425T162418_cms_pages_init.d.ts +10 -0
- package/dist/migrations/20260425T162418_cms_pages_init.d.ts.map +1 -0
- package/dist/migrations/20260425T162418_cms_pages_init.js +30 -0
- package/dist/migrations/20260425T162418_cms_pages_init.js.map +1 -0
- package/dist/migrations/20260505T130214_cms_init.d.ts +28 -0
- package/dist/migrations/20260505T130214_cms_init.d.ts.map +1 -0
- package/dist/migrations/20260505T130214_cms_init.js +332 -0
- package/dist/migrations/20260505T130214_cms_init.js.map +1 -0
- package/dist/migrations/20260903T101741_cms_namespace_block_names.d.ts +6 -0
- package/dist/migrations/20260903T101741_cms_namespace_block_names.d.ts.map +1 -0
- package/dist/migrations/20260903T101741_cms_namespace_block_names.js +60 -0
- package/dist/migrations/20260903T101741_cms_namespace_block_names.js.map +1 -0
- package/dist/migrations/20260912T094733_cms_sales_channel_cms_pages.d.ts +27 -0
- package/dist/migrations/20260912T094733_cms_sales_channel_cms_pages.d.ts.map +1 -0
- package/dist/migrations/20260912T094733_cms_sales_channel_cms_pages.js +44 -0
- package/dist/migrations/20260912T094733_cms_sales_channel_cms_pages.js.map +1 -0
- package/dist/migrations/20260912T125709_cms_page_body_asset_ref_index.d.ts +32 -0
- package/dist/migrations/20260912T125709_cms_page_body_asset_ref_index.d.ts.map +1 -0
- package/dist/migrations/20260912T125709_cms_page_body_asset_ref_index.js +36 -0
- package/dist/migrations/20260912T125709_cms_page_body_asset_ref_index.js.map +1 -0
- package/dist/migrations/index.d.ts +31 -0
- package/dist/migrations/index.d.ts.map +1 -0
- package/dist/migrations/index.js +37 -0
- package/dist/migrations/index.js.map +1 -0
- package/docs/cms/extending-page-builder.md +256 -0
- package/docs/cms/index.md +233 -0
- package/i18n/en.json +231 -0
- package/i18n/pl.json +231 -0
- package/package.json +125 -3
- package/tailwind.css +16 -0
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
// Page Builder component registry — feature 014 / T028, rebuilt on module
|
|
2
|
+
// declarations by feature 096 (T209/T210).
|
|
3
|
+
//
|
|
4
|
+
// **It is populated from the composed modules' manifests, not from a call.**
|
|
5
|
+
// Until 2026-09-03 it was populated by a single hand-written
|
|
6
|
+
// `register('cms', …)` at `plugin.ts:90` which declared all 35 CMS names with
|
|
7
|
+
// `ownerModule: 'cms'` — five of which are `catalog`'s, so the descriptor
|
|
8
|
+
// answered the ownership question wrongly for every one of them and FR-010's
|
|
9
|
+
// presence filter had nothing true to key on. Ownership is now stated once, in
|
|
10
|
+
// the block's own `name`, by the module that owns it
|
|
11
|
+
// (`contracts/block-definition.md` §1 and §4.1).
|
|
12
|
+
//
|
|
13
|
+
// The registry is React-free: it stores metadata only. The render functions
|
|
14
|
+
// live in `@endora-commerce/cms-components` and the per-module packages, and
|
|
15
|
+
// the storefront imports them directly.
|
|
16
|
+
//
|
|
17
|
+
// ## Two things it deliberately does not do
|
|
18
|
+
//
|
|
19
|
+
// **It does not merge categories at registration.** A merge performed there has
|
|
20
|
+
// consumed composition order and can no longer answer differently when a module
|
|
21
|
+
// is switched off — which is the whole of B12. Declarations are kept keyed by
|
|
22
|
+
// their declaring module and folded at `describe()`, after the presence filter.
|
|
23
|
+
//
|
|
24
|
+
// **It applies no context admission.** `email` admitting into `newsletter` is
|
|
25
|
+
// the *palette* derivation's rule, applied once through `contextAdmits`
|
|
26
|
+
// (`contracts/block-definition.md` §4.1.1), so the wire shape keeps saying what
|
|
27
|
+
// the manifests say and exactly one layer answers "which sections does the
|
|
28
|
+
// newsletter palette have".
|
|
29
|
+
import { DEFAULT_BREAKPOINTS } from '@endora-commerce/page-builder-core/types/responsive';
|
|
30
|
+
/**
|
|
31
|
+
* Raised when two modules declare one block name.
|
|
32
|
+
*
|
|
33
|
+
* **D-31's collision requirement, and the reversal of defect D-d**: the old
|
|
34
|
+
* `register` warned and overwrote, which is last-writer-wins over a *persisted*
|
|
35
|
+
* identifier — one contributor's stored documents silently rendering as
|
|
36
|
+
* another's block. It has never been exercised because there was one
|
|
37
|
+
* contributor; there are now six.
|
|
38
|
+
*
|
|
39
|
+
* **Two contributors, never one registering twice.** The owner is compared, so
|
|
40
|
+
* a module re-declaring its own manifest is idempotent; a name that arrives
|
|
41
|
+
* from a second module id is the collision, and it is the only thing this error
|
|
42
|
+
* is for.
|
|
43
|
+
*/
|
|
44
|
+
export class DuplicateBlockNameError extends Error {
|
|
45
|
+
constructor(name, first, second) {
|
|
46
|
+
super(`[cms/page-builder-registry] Block name "${name}" is declared by both "${first}" and ` +
|
|
47
|
+
`"${second}". A block name is persisted and must have one owner — rename one of the ` +
|
|
48
|
+
'two declarations (`contracts/block-definition.md` §4.1).');
|
|
49
|
+
this.name = 'DuplicateBlockNameError';
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
export class PageBuilderRegistry {
|
|
53
|
+
components = new Map();
|
|
54
|
+
categories = [];
|
|
55
|
+
schemaVersion = 1;
|
|
56
|
+
breakpoints;
|
|
57
|
+
isModulePresent;
|
|
58
|
+
breakpointsResolver;
|
|
59
|
+
colorPaletteResolver;
|
|
60
|
+
constructor(options = {}) {
|
|
61
|
+
this.breakpoints = options.breakpoints ?? { ...DEFAULT_BREAKPOINTS };
|
|
62
|
+
this.isModulePresent = options.isModulePresent ?? (() => true);
|
|
63
|
+
for (const entry of options.manifests ?? []) {
|
|
64
|
+
this.registerManifest(entry.manifest);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Take one module's `blocks` and `blockCategories` declarations.
|
|
69
|
+
*
|
|
70
|
+
* The owner is the block name's first segment, which `defineModuleManifest`
|
|
71
|
+
* has already refused to let differ from the declaring module's `id`. It is
|
|
72
|
+
* read from the name rather than from the manifest so that the registry and
|
|
73
|
+
* the persisted document agree by construction.
|
|
74
|
+
*/
|
|
75
|
+
registerManifest(manifest) {
|
|
76
|
+
for (const block of (manifest.blocks ?? [])) {
|
|
77
|
+
const existing = this.components.get(block.name);
|
|
78
|
+
// **The refusal's subject is two contributors**, which is what D-31 asks
|
|
79
|
+
// for and what defect D-d got wrong by warning and overwriting. One
|
|
80
|
+
// module registering twice — an idempotent re-composition, a harness
|
|
81
|
+
// calling a fixture once per test case — is not a collision, and refusing
|
|
82
|
+
// it produced the sentence `declared by both "x" and "x"`, which is
|
|
83
|
+
// self-evidently not one.
|
|
84
|
+
if (existing && existing.ownerModule !== manifest.id) {
|
|
85
|
+
throw new DuplicateBlockNameError(block.name, existing.ownerModule, manifest.id);
|
|
86
|
+
}
|
|
87
|
+
this.components.set(block.name, {
|
|
88
|
+
ownerModule: block.name.slice(0, block.name.indexOf('.')),
|
|
89
|
+
fields: block.fields,
|
|
90
|
+
contexts: [...block.contexts],
|
|
91
|
+
labelKey: block.labelKey,
|
|
92
|
+
...(block.descriptionKey !== undefined ? { descriptionKey: block.descriptionKey } : {}),
|
|
93
|
+
category: block.category,
|
|
94
|
+
...(block.defaultProps !== undefined ? { defaultProps: block.defaultProps } : {}),
|
|
95
|
+
...(block.responsiveFields !== undefined
|
|
96
|
+
? { responsiveFields: [...block.responsiveFields] }
|
|
97
|
+
: {}),
|
|
98
|
+
...(block.previewIcon !== undefined ? { previewIcon: block.previewIcon } : {}),
|
|
99
|
+
...(block.weight !== undefined ? { weight: block.weight } : {}),
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
for (const category of (manifest.blockCategories ?? [])) {
|
|
103
|
+
this.categories.push({ ...category, ownerModule: manifest.id });
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
setBreakpointsResolver(resolver) {
|
|
107
|
+
this.breakpointsResolver = resolver;
|
|
108
|
+
}
|
|
109
|
+
setColorPaletteResolver(resolver) {
|
|
110
|
+
this.colorPaletteResolver = resolver;
|
|
111
|
+
}
|
|
112
|
+
async resolveBreakpoints() {
|
|
113
|
+
if (this.breakpointsResolver) {
|
|
114
|
+
return this.breakpointsResolver();
|
|
115
|
+
}
|
|
116
|
+
return this.getBreakpoints();
|
|
117
|
+
}
|
|
118
|
+
isComponentRegistered(name) {
|
|
119
|
+
return this.components.has(name);
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Every declared block name, **unfiltered by presence**.
|
|
123
|
+
*
|
|
124
|
+
* This answers "is this string a block name this platform knows", which the
|
|
125
|
+
* reference registries ask when they decide whether a stored node is a known
|
|
126
|
+
* embed. A switched-off module's blocks are still real names in stored
|
|
127
|
+
* documents, so filtering here would make a present document's node look
|
|
128
|
+
* unknown — a different question with a different right answer from the
|
|
129
|
+
* palette's.
|
|
130
|
+
*/
|
|
131
|
+
knownNames() {
|
|
132
|
+
return new Set(this.components.keys());
|
|
133
|
+
}
|
|
134
|
+
getBreakpoints() {
|
|
135
|
+
return { ...this.breakpoints };
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* The metadata view used by `GET /api/v1/admin/cms/page-builder/config`.
|
|
139
|
+
*
|
|
140
|
+
* Filters to the effectively present modules and *then* folds the categories,
|
|
141
|
+
* in that order (`contracts/block-definition.md` §4.1). Both outputs are
|
|
142
|
+
* sorted by a function of the declarations alone, so the response is
|
|
143
|
+
* byte-identical under a re-composition or a reordering of `MODULES` — the
|
|
144
|
+
* D-45 property, which a fold at registration cannot have.
|
|
145
|
+
*/
|
|
146
|
+
async describe() {
|
|
147
|
+
const breakpoints = await this.resolveBreakpoints();
|
|
148
|
+
const colorPalette = this.colorPaletteResolver ? await this.colorPaletteResolver() : [];
|
|
149
|
+
return {
|
|
150
|
+
schemaVersion: this.schemaVersion,
|
|
151
|
+
breakpoints,
|
|
152
|
+
colorPalette,
|
|
153
|
+
components: Array.from(this.components.entries())
|
|
154
|
+
.filter(([, reg]) => this.isModulePresent(reg.ownerModule))
|
|
155
|
+
.sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0))
|
|
156
|
+
.map(([name, reg]) => ({
|
|
157
|
+
name,
|
|
158
|
+
ownerModule: reg.ownerModule,
|
|
159
|
+
fields: reg.fields,
|
|
160
|
+
...(reg.previewIcon !== undefined ? { previewIcon: reg.previewIcon } : {}),
|
|
161
|
+
contexts: reg.contexts ?? ['cms'],
|
|
162
|
+
...(reg.labelKey !== undefined ? { labelKey: reg.labelKey } : {}),
|
|
163
|
+
...(reg.descriptionKey !== undefined ? { descriptionKey: reg.descriptionKey } : {}),
|
|
164
|
+
...(reg.category !== undefined ? { category: reg.category } : {}),
|
|
165
|
+
...(reg.defaultProps !== undefined ? { defaultProps: reg.defaultProps } : {}),
|
|
166
|
+
...(reg.responsiveFields !== undefined ? { responsiveFields: reg.responsiveFields } : {}),
|
|
167
|
+
...(reg.weight !== undefined ? { weight: reg.weight } : {}),
|
|
168
|
+
})),
|
|
169
|
+
categories: this.foldCategories(),
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Reduce every `(key, context)` group to one served record.
|
|
174
|
+
*
|
|
175
|
+
* `titleKey`, `weight` and `visible` come from **one** winning declaration and
|
|
176
|
+
* never field by field: a title from one module beside a weight from another
|
|
177
|
+
* is a presentation nobody wrote. The order is lowest `weight` first with an
|
|
178
|
+
* absent `weight` sorting after every declared one, ties broken by the
|
|
179
|
+
* declaring module's `id` ascending — a function of the declarations and of
|
|
180
|
+
* nothing else, so it is stable under re-composition
|
|
181
|
+
* (`contracts/block-definition.md` §1.1).
|
|
182
|
+
*/
|
|
183
|
+
foldCategories() {
|
|
184
|
+
const groups = new Map();
|
|
185
|
+
for (const declaration of this.categories) {
|
|
186
|
+
if (!this.isModulePresent(declaration.ownerModule))
|
|
187
|
+
continue;
|
|
188
|
+
for (const context of declaration.contexts) {
|
|
189
|
+
const key = `${context} ${declaration.key}`;
|
|
190
|
+
const bucket = groups.get(key);
|
|
191
|
+
if (bucket)
|
|
192
|
+
bucket.push(declaration);
|
|
193
|
+
else
|
|
194
|
+
groups.set(key, [declaration]);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
return [...groups.entries()]
|
|
198
|
+
.sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0))
|
|
199
|
+
.map(([key, declarations]) => {
|
|
200
|
+
const context = key.slice(0, key.indexOf(' '));
|
|
201
|
+
const winner = [...declarations].sort(compareCategoryDeclarations)[0];
|
|
202
|
+
return {
|
|
203
|
+
key: winner.key,
|
|
204
|
+
titleKey: winner.titleKey,
|
|
205
|
+
contexts: [context],
|
|
206
|
+
...(winner.weight !== undefined ? { weight: winner.weight } : {}),
|
|
207
|
+
...(winner.visible !== undefined ? { visible: winner.visible } : {}),
|
|
208
|
+
ownerModule: winner.ownerModule,
|
|
209
|
+
};
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
function compareCategoryDeclarations(a, b) {
|
|
214
|
+
const aw = a.weight ?? Number.POSITIVE_INFINITY;
|
|
215
|
+
const bw = b.weight ?? Number.POSITIVE_INFINITY;
|
|
216
|
+
if (aw !== bw)
|
|
217
|
+
return aw - bw;
|
|
218
|
+
return a.ownerModule < b.ownerModule ? -1 : a.ownerModule > b.ownerModule ? 1 : 0;
|
|
219
|
+
}
|
|
220
|
+
//# sourceMappingURL=page-builder-registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"page-builder-registry.js","sourceRoot":"","sources":["../../../src/backend/services/page-builder-registry.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { EntityManager } from '@mikro-orm/postgresql';
|
|
2
|
+
export interface SeededHook {
|
|
3
|
+
code: string;
|
|
4
|
+
name: string;
|
|
5
|
+
description?: string;
|
|
6
|
+
}
|
|
7
|
+
export declare const SEEDED_HOOKS: ReadonlyArray<SeededHook>;
|
|
8
|
+
export interface SeedHooksReconcileResult {
|
|
9
|
+
inserted: number;
|
|
10
|
+
preservedExisting: number;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Idempotent reconciler. Existing rows (matched by code) are preserved
|
|
14
|
+
* untouched — admin-edited names + descriptions survive every run.
|
|
15
|
+
* Missing seeded codes are inserted with `is_system=true`. Every seeded
|
|
16
|
+
* hook is also (re-)bound to every existing sales channel via
|
|
17
|
+
* `cms_hook_sales_channels` so the storefront's per-channel resolution
|
|
18
|
+
* sees the hook even after `sales_channels` was truncated (e.g. between
|
|
19
|
+
* test runs — the bindings cascade-deleted with the channels).
|
|
20
|
+
*/
|
|
21
|
+
export declare function reconcileSeededHooks(emFactory: () => EntityManager): Promise<SeedHooksReconcileResult>;
|
|
22
|
+
//# sourceMappingURL=seed-hooks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"seed-hooks.d.ts","sourceRoot":"","sources":["../../../src/backend/services/seed-hooks.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAI3D,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,eAAO,MAAM,YAAY,EAAE,aAAa,CAAC,UAAU,CA4BlD,CAAC;AAEF,MAAM,WAAW,wBAAwB;IACvC,QAAQ,EAAE,MAAM,CAAC;IACjB,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAED;;;;;;;;GAQG;AACH,wBAAsB,oBAAoB,CACxC,SAAS,EAAE,MAAM,aAAa,GAC7B,OAAO,CAAC,wBAAwB,CAAC,CA+CnC"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
// Seeded base Hook codes — feature 014 / R8 / T030.
|
|
2
|
+
//
|
|
3
|
+
// The 23 codes here are recognised natively by the storefront's named
|
|
4
|
+
// insertion points. The reconciler is idempotent: re-running it preserves
|
|
5
|
+
// admin-edited names + descriptions and re-creates a system Hook only if
|
|
6
|
+
// it is somehow missing. Runs at composition time before HTTP routes
|
|
7
|
+
// start serving (called from composition.ts), and inside the migration
|
|
8
|
+
// (035_cms_init.ts) so first boot doesn't race.
|
|
9
|
+
import { CmsHook } from '../entities/cms-hook.entity.js';
|
|
10
|
+
import { SalesChannel } from '@endora-commerce/platform/kernel';
|
|
11
|
+
export const SEEDED_HOOKS = [
|
|
12
|
+
{
|
|
13
|
+
code: 'header.top',
|
|
14
|
+
name: 'Header Top',
|
|
15
|
+
description: 'Top-of-page strip — phone number, free-shipping notice, etc.',
|
|
16
|
+
},
|
|
17
|
+
{ code: 'homepage.top', name: 'Homepage Top', description: 'Above the homepage content.' },
|
|
18
|
+
{ code: 'homepage.bottom', name: 'Homepage Bottom', description: 'Below the homepage content.' },
|
|
19
|
+
{ code: 'footer.before', name: 'Footer Before' },
|
|
20
|
+
{ code: 'footer.top', name: 'Footer Top' },
|
|
21
|
+
{ code: 'footer.bottom', name: 'Footer Bottom' },
|
|
22
|
+
{ code: 'footer.after', name: 'Footer After' },
|
|
23
|
+
{ code: 'footer.copyright', name: 'Footer Copyright' },
|
|
24
|
+
{ code: 'category.top', name: 'Category Page Top' },
|
|
25
|
+
{ code: 'category.bottom', name: 'Category Page Bottom' },
|
|
26
|
+
{ code: 'product.top', name: 'Product Page Top' },
|
|
27
|
+
{ code: 'product.bottom', name: 'Product Page Bottom' },
|
|
28
|
+
{ code: 'product.buttons.after', name: 'Product Page After Buttons Set' },
|
|
29
|
+
{ code: 'search.top', name: 'Search Page Top' },
|
|
30
|
+
{ code: 'search.bottom', name: 'Search Page Bottom' },
|
|
31
|
+
{ code: 'page.top', name: 'Every Page Top' },
|
|
32
|
+
{ code: 'page.bottom', name: 'Every Page Bottom' },
|
|
33
|
+
{ code: 'cms.page.top', name: 'Every CMS Page Top' },
|
|
34
|
+
{ code: 'cms.page.bottom', name: 'Every CMS Page Bottom' },
|
|
35
|
+
{ code: 'login.top', name: 'Login Page Top' },
|
|
36
|
+
{ code: 'login.bottom', name: 'Login Page Bottom' },
|
|
37
|
+
{ code: 'register.top', name: 'Register Page Top' },
|
|
38
|
+
{ code: 'register.bottom', name: 'Register Page Bottom' },
|
|
39
|
+
];
|
|
40
|
+
/**
|
|
41
|
+
* Idempotent reconciler. Existing rows (matched by code) are preserved
|
|
42
|
+
* untouched — admin-edited names + descriptions survive every run.
|
|
43
|
+
* Missing seeded codes are inserted with `is_system=true`. Every seeded
|
|
44
|
+
* hook is also (re-)bound to every existing sales channel via
|
|
45
|
+
* `cms_hook_sales_channels` so the storefront's per-channel resolution
|
|
46
|
+
* sees the hook even after `sales_channels` was truncated (e.g. between
|
|
47
|
+
* test runs — the bindings cascade-deleted with the channels).
|
|
48
|
+
*/
|
|
49
|
+
export async function reconcileSeededHooks(emFactory) {
|
|
50
|
+
// command-coverage-ignore: idempotent boot seed/reconcile of module-declared CMS
|
|
51
|
+
// hooks — a system-invariant repair, not an operator-initiated audited write.
|
|
52
|
+
const em = emFactory();
|
|
53
|
+
const existing = await em.find(CmsHook, { isSystem: true });
|
|
54
|
+
const existingByCode = new Map(existing.map((h) => [h.code, h]));
|
|
55
|
+
let inserted = 0;
|
|
56
|
+
for (const seed of SEEDED_HOOKS) {
|
|
57
|
+
if (existingByCode.has(seed.code))
|
|
58
|
+
continue;
|
|
59
|
+
const hook = em.create(CmsHook, {
|
|
60
|
+
name: seed.name,
|
|
61
|
+
code: seed.code,
|
|
62
|
+
active: true,
|
|
63
|
+
description: seed.description ?? null,
|
|
64
|
+
isSystem: true,
|
|
65
|
+
});
|
|
66
|
+
em.persist(hook);
|
|
67
|
+
inserted += 1;
|
|
68
|
+
}
|
|
69
|
+
if (inserted > 0)
|
|
70
|
+
await em.flush();
|
|
71
|
+
/**
|
|
72
|
+
* The channel ids come from the kernel's own entity, not from a
|
|
73
|
+
* `cross join "sales_channels"` (feature 075, D-87). `sales_channels` is the
|
|
74
|
+
* kernel's table since feature 072 moved the resolution machinery there, and
|
|
75
|
+
* a module relating into the kernel by ORM is the sanctioned access. The
|
|
76
|
+
* binding insert stays one set-based statement over this module's own two
|
|
77
|
+
* tables, with one ordinary binding per channel id.
|
|
78
|
+
*/
|
|
79
|
+
const channelIds = (await em.find(SalesChannel, {}, { fields: ['id'] })).map((c) => c.id);
|
|
80
|
+
if (channelIds.length > 0) {
|
|
81
|
+
const channelValues = channelIds.map(() => '(?::uuid)').join(', ');
|
|
82
|
+
await em.execute(`insert into "cms_hook_sales_channels" ("hook_id", "sales_channel_id")
|
|
83
|
+
select h."id", c."id"
|
|
84
|
+
from "cms_hooks" h
|
|
85
|
+
cross join (values ${channelValues}) as c("id")
|
|
86
|
+
where h."is_system" = true
|
|
87
|
+
and not exists (
|
|
88
|
+
select 1 from "cms_hook_sales_channels" x
|
|
89
|
+
where x."hook_id" = h."id" and x."sales_channel_id" = c."id"
|
|
90
|
+
)`, channelIds);
|
|
91
|
+
}
|
|
92
|
+
return { inserted, preservedExisting: existing.length };
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=seed-hooks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"seed-hooks.js","sourceRoot":"","sources":["../../../src/backend/services/seed-hooks.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import type { EntityManager } from '@mikro-orm/postgresql';
|
|
2
|
+
import type { CmsAssetEmbedResolution, CmsPageIndexEntry, CmsResolvedBlock, CmsResolvedHook, CmsResolvedPage } from '@endora-commerce/contracts';
|
|
3
|
+
import type { CmsCache } from './cms-cache.js';
|
|
4
|
+
export type CmsAssetResolver = (assetId: string) => Promise<CmsAssetEmbedResolution | null>;
|
|
5
|
+
/**
|
|
6
|
+
* The request's resolved sales channel, handed in by the route from the
|
|
7
|
+
* canonical resolver, read via `getResolvedChannel()` — feature 053 / FR-002. The
|
|
8
|
+
* service no longer re-resolves the channel from the raw header.
|
|
9
|
+
*/
|
|
10
|
+
export type ResolvedChannel = {
|
|
11
|
+
id: string;
|
|
12
|
+
code: string;
|
|
13
|
+
defaultLanguage: string;
|
|
14
|
+
};
|
|
15
|
+
export declare class StorefrontResolver {
|
|
16
|
+
private readonly emFactory;
|
|
17
|
+
private readonly cache?;
|
|
18
|
+
private assetResolver;
|
|
19
|
+
constructor(emFactory: () => EntityManager, cache?: CmsCache | undefined);
|
|
20
|
+
setAssetResolver(resolver: CmsAssetResolver | null): void;
|
|
21
|
+
private resolveAssetsForTrees;
|
|
22
|
+
resolvePageBySlug(input: {
|
|
23
|
+
resolvedChannel: ResolvedChannel;
|
|
24
|
+
language?: string | undefined;
|
|
25
|
+
slug: string;
|
|
26
|
+
}): Promise<CmsResolvedPage | null>;
|
|
27
|
+
/**
|
|
28
|
+
* Every published page of one sales channel, at the slug that channel serves
|
|
29
|
+
* it under (feature 105, FR-021; `contracts/cms-page-url.md` §4.1).
|
|
30
|
+
*
|
|
31
|
+
* The join is `resolvePageBySlug`'s, minus the slug predicate: same table,
|
|
32
|
+
* same three conditions — the channel binding, `status = 'published'` and
|
|
33
|
+
* `active = true` — so a page this answer names is a page that endpoint
|
|
34
|
+
* serves, and a page it omits is one that would 404. A sitemap built from a
|
|
35
|
+
* looser query would advertise a URL the shop refuses, which is the state §4.1
|
|
36
|
+
* exists to make unreachable.
|
|
37
|
+
*
|
|
38
|
+
* The slug comes off `cms_page_sales_channels`, never off `cms_pages`: the
|
|
39
|
+
* address is per channel (Constitution XII), and the page row's own column is
|
|
40
|
+
* one value shared by all of them.
|
|
41
|
+
*
|
|
42
|
+
* Uncached, deliberately. `CmsCache` keys a page by `(slug, channel, language)`
|
|
43
|
+
* and is invalidated per slug on write, so an index cached beside it would
|
|
44
|
+
* survive every invalidation the module performs and go stale on the first
|
|
45
|
+
* publish. The read is one indexed join per sitemap build, which Next's own
|
|
46
|
+
* route cache already sits in front of.
|
|
47
|
+
*/
|
|
48
|
+
listPublishedPages(input: {
|
|
49
|
+
resolvedChannel: ResolvedChannel;
|
|
50
|
+
}): Promise<CmsPageIndexEntry[]>;
|
|
51
|
+
resolveBlockByCode(input: {
|
|
52
|
+
resolvedChannel: ResolvedChannel;
|
|
53
|
+
language?: string | undefined;
|
|
54
|
+
code: string;
|
|
55
|
+
}): Promise<CmsResolvedBlock | null>;
|
|
56
|
+
resolveHookByCode(input: {
|
|
57
|
+
resolvedChannel: ResolvedChannel;
|
|
58
|
+
language?: string | undefined;
|
|
59
|
+
code: string;
|
|
60
|
+
}): Promise<CmsResolvedHook | null>;
|
|
61
|
+
/**
|
|
62
|
+
* Recursively inlines InsertBlock / InsertTemplate references found in the
|
|
63
|
+
* supplied Page Builder data tree. Capped at EMBED_DEPTH_CAP levels —
|
|
64
|
+
* cycles or deeper graphs degrade to placeholders rendered admin-side.
|
|
65
|
+
*/
|
|
66
|
+
private inlineEmbeds;
|
|
67
|
+
private fetchBlocksByCodes;
|
|
68
|
+
private fetchTemplatesByCodes;
|
|
69
|
+
private resolveLanguage;
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=storefront-resolver.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storefront-resolver.d.ts","sourceRoot":"","sources":["../../../src/backend/services/storefront-resolver.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,KAAK,EACV,uBAAuB,EACvB,iBAAiB,EACjB,gBAAgB,EAChB,eAAe,EACf,eAAe,EAEhB,MAAM,4BAA4B,CAAC;AAEpC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE/C,MAAM,MAAM,gBAAgB,GAAG,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,uBAAuB,GAAG,IAAI,CAAC,CAAC;AAiC5F;;;;GAIG;AACH,MAAM,MAAM,eAAe,GAAG;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,eAAe,EAAE,MAAM,CAAC;CACzB,CAAC;AA0BF,qBAAa,kBAAkB;IAI3B,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC;IAJzB,OAAO,CAAC,aAAa,CAAiC;gBAGnC,SAAS,EAAE,MAAM,aAAa,EAC9B,KAAK,CAAC,EAAE,QAAQ,YAAA;IAGnC,gBAAgB,CAAC,QAAQ,EAAE,gBAAgB,GAAG,IAAI,GAAG,IAAI;YAI3C,qBAAqB;IAkB7B,iBAAiB,CAAC,KAAK,EAAE;QAC7B,eAAe,EAAE,eAAe,CAAC;QACjC,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;QAC9B,IAAI,EAAE,MAAM,CAAC;KACd,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC;IA0DnC;;;;;;;;;;;;;;;;;;;;OAoBG;IACG,kBAAkB,CAAC,KAAK,EAAE;QAC9B,eAAe,EAAE,eAAe,CAAC;KAClC,GAAG,OAAO,CAAC,iBAAiB,EAAE,CAAC;IAoB1B,kBAAkB,CAAC,KAAK,EAAE;QAC9B,eAAe,EAAE,eAAe,CAAC;QACjC,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;QAC9B,IAAI,EAAE,MAAM,CAAC;KACd,GAAG,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC;IAwC9B,iBAAiB,CAAC,KAAK,EAAE;QAC7B,eAAe,EAAE,eAAe,CAAC;QACjC,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;QAC9B,IAAI,EAAE,MAAM,CAAC;KACd,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC;IAuEnC;;;;OAIG;YACW,YAAY;YA0EZ,kBAAkB;YAkBlB,qBAAqB;IAiBnC,OAAO,CAAC,eAAe;CA6BxB"}
|