@shoppexio/builder-contracts 0.1.0 → 0.1.2

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 (92) hide show
  1. package/dist/builder-settings.d.ts +11 -666
  2. package/dist/builder-settings.d.ts.map +1 -1
  3. package/dist/builder-settings.js +2 -1
  4. package/dist/canonical-settings.d.ts +18 -0
  5. package/dist/canonical-settings.d.ts.map +1 -0
  6. package/dist/canonical-settings.js +106 -0
  7. package/dist/custom-pages.d.ts +15 -0
  8. package/dist/custom-pages.d.ts.map +1 -0
  9. package/dist/custom-pages.js +40 -0
  10. package/dist/dedicated-pages.d.ts +15 -0
  11. package/dist/dedicated-pages.d.ts.map +1 -0
  12. package/dist/dedicated-pages.js +142 -0
  13. package/dist/events.d.ts +35 -240
  14. package/dist/events.d.ts.map +1 -1
  15. package/dist/events.js +7 -0
  16. package/dist/fields.d.ts +229 -10
  17. package/dist/fields.d.ts.map +1 -1
  18. package/dist/fields.js +27 -0
  19. package/dist/index.d.ts +10 -0
  20. package/dist/index.d.ts.map +1 -1
  21. package/dist/index.js +10 -0
  22. package/dist/legacy-manifest.d.ts +18 -0
  23. package/dist/legacy-manifest.d.ts.map +1 -1
  24. package/dist/legacy-manifest.js +137 -22
  25. package/dist/migrations.d.ts.map +1 -1
  26. package/dist/migrations.js +55 -6
  27. package/dist/persistence.d.ts +7 -0
  28. package/dist/persistence.d.ts.map +1 -0
  29. package/dist/persistence.js +58 -0
  30. package/dist/preview-boot.d.ts +68 -0
  31. package/dist/preview-boot.d.ts.map +1 -0
  32. package/dist/preview-boot.js +38 -0
  33. package/dist/preview-protocol.d.ts +227 -459
  34. package/dist/preview-protocol.d.ts.map +1 -1
  35. package/dist/preview-protocol.js +112 -0
  36. package/dist/preview-session-resolve.d.ts +115 -0
  37. package/dist/preview-session-resolve.d.ts.map +1 -0
  38. package/dist/preview-session-resolve.js +25 -0
  39. package/dist/preview-trusted-origins.d.ts +4 -0
  40. package/dist/preview-trusted-origins.d.ts.map +1 -0
  41. package/dist/preview-trusted-origins.js +28 -0
  42. package/dist/storefront-initial-data-html.d.ts +17 -0
  43. package/dist/storefront-initial-data-html.d.ts.map +1 -0
  44. package/dist/storefront-initial-data-html.js +83 -0
  45. package/dist/storefront-typography-fonts.d.ts +18 -0
  46. package/dist/storefront-typography-fonts.d.ts.map +1 -0
  47. package/dist/storefront-typography-fonts.js +89 -0
  48. package/dist/style-slots.d.ts +50 -152
  49. package/dist/style-slots.d.ts.map +1 -1
  50. package/dist/style-slots.js +80 -32
  51. package/dist/theme-manifest.d.ts +287 -456
  52. package/dist/theme-manifest.d.ts.map +1 -1
  53. package/dist/theme-manifest.js +92 -0
  54. package/dist/theme-schemes.d.ts +10 -0
  55. package/dist/theme-schemes.d.ts.map +1 -0
  56. package/dist/theme-schemes.js +25 -0
  57. package/dist/validation.d.ts +1 -1
  58. package/dist/validation.d.ts.map +1 -1
  59. package/dist/validation.js +23 -12
  60. package/package.json +43 -1
  61. package/src/builder-contracts.test.ts +416 -3
  62. package/src/builder-settings.ts +4 -1
  63. package/src/canonical-settings.ts +156 -0
  64. package/src/custom-pages.test.ts +74 -0
  65. package/src/custom-pages.ts +70 -0
  66. package/src/dedicated-pages.test.ts +88 -0
  67. package/src/dedicated-pages.ts +173 -0
  68. package/src/events.ts +8 -0
  69. package/src/fields.ts +30 -0
  70. package/src/index.ts +10 -0
  71. package/src/legacy-manifest.ts +147 -23
  72. package/src/migrations.ts +70 -6
  73. package/src/persistence.ts +77 -0
  74. package/src/preview-boot.test.ts +72 -0
  75. package/src/preview-boot.ts +49 -0
  76. package/src/preview-protocol.test.ts +132 -0
  77. package/src/preview-protocol.ts +122 -0
  78. package/src/preview-session-resolve.test.ts +37 -0
  79. package/src/preview-session-resolve.ts +34 -0
  80. package/src/preview-trusted-origins.test.ts +24 -0
  81. package/src/preview-trusted-origins.ts +35 -0
  82. package/src/storefront-initial-data-html.test.ts +73 -0
  83. package/src/storefront-initial-data-html.ts +112 -0
  84. package/src/storefront-typography-fonts.test.ts +48 -0
  85. package/src/storefront-typography-fonts.ts +108 -0
  86. package/src/style-slots.ts +102 -34
  87. package/src/theme-manifest.ts +118 -1
  88. package/src/theme-schemes.ts +34 -0
  89. package/src/validation.ts +32 -13
  90. package/dist/builder-contracts.test.d.ts +0 -2
  91. package/dist/builder-contracts.test.d.ts.map +0 -1
  92. package/dist/builder-contracts.test.js +0 -361
@@ -1 +1 @@
1
- {"version":3,"file":"builder-settings.d.ts","sourceRoot":"","sources":["../src/builder-settings.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,QAAQ,CAAC;AAG5B,eAAO,MAAM,wBAAwB,IAAI,CAAC;AAE1C,eAAO,MAAM,YAAY,aAAoD,CAAC;AAC9E,MAAM,MAAM,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAAC;AAElD,eAAO,MAAM,qBAAqB,aAAoB,CAAC;AACvD,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAEpE,eAAO,MAAM,eAAe,aAAoD,CAAC;AACjF,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC;AAExD,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBASrB,CAAC;AACZ,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAEhE,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAIlB,CAAC;AACZ,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAE1D,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAelB,CAAC;AACZ,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAE1D,eAAO,MAAM,WAAW;;;;;mBAQV,CAAC;AACf,MAAM,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,CAAC;AAEhD,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAQzB,CAAC;AACZ,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAExE,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAMvB,CAAC;AACZ,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAEpE,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,OAAO,GAAG,eAAe,CAEpE"}
1
+ {"version":3,"file":"builder-settings.d.ts","sourceRoot":"","sources":["../src/builder-settings.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,QAAQ,CAAC;AAG5B,eAAO,MAAM,wBAAwB,IAAI,CAAC;AAE1C,eAAO,MAAM,YAAY,aAAoD,CAAC;AAC9E,MAAM,MAAM,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAAC;AAElD,eAAO,MAAM,qBAAqB,aAAoB,CAAC;AACvD,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAEpE,eAAO,MAAM,eAAe,aAAoD,CAAC;AACjF,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC;AAExD,eAAO,MAAM,mBAAmB;;;;;;;kBASrB,CAAC;AACZ,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAEhE,eAAO,MAAM,gBAAgB;;;;;;;;;kBAIlB,CAAC;AACZ,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAE1D,eAAO,MAAM,oBAAoB,aAAmD,CAAC;AACrF,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAElE,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;kBAelB,CAAC;AACZ,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAE1D,eAAO,MAAM,WAAW;;;;;mBAQV,CAAC;AACf,MAAM,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,CAAC;AAEhD,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAQzB,CAAC;AACZ,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAExE,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAMvB,CAAC;AACZ,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAEpE,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,OAAO,GAAG,eAAe,CAEpE"}
@@ -19,11 +19,12 @@ export const PageLayoutSchema = z
19
19
  blocks: z.array(BlockInstanceSchema).default([]),
20
20
  })
21
21
  .strict();
22
+ export const CustomPageSlugSchema = z.string().min(1).regex(/^[a-z0-9][a-z0-9-_]*$/);
22
23
  export const CustomPageSchema = z
23
24
  .object({
24
25
  id: PageIdSchema,
25
26
  title: z.string().min(1),
26
- slug: z.string().min(1).regex(/^[a-z0-9][a-z0-9-_/]*$/),
27
+ slug: CustomPageSlugSchema,
27
28
  visible: z.boolean().default(true),
28
29
  layout: PageLayoutSchema.default({ blocks: [] }),
29
30
  seo: z
@@ -0,0 +1,18 @@
1
+ import type { BuilderSettings } from './builder-settings.ts';
2
+ import type { ThemeManifest } from './theme-manifest.ts';
3
+ export type BuilderSettingsCanonicalizationConflict = {
4
+ pageId: string;
5
+ blockId: string;
6
+ blockType: string;
7
+ alias: string;
8
+ canonicalPath: string;
9
+ };
10
+ export type BuilderSettingsCanonicalizationResult = {
11
+ settings: BuilderSettings;
12
+ migratedAliases: number;
13
+ removedAliases: number;
14
+ conflicts: BuilderSettingsCanonicalizationConflict[];
15
+ };
16
+ export declare function canonicalizeBuilderSettingsForManifest(settings: BuilderSettings, manifest: ThemeManifest): BuilderSettings;
17
+ export declare function canonicalizeBuilderSettingsForManifestWithReport(settings: BuilderSettings, manifest: ThemeManifest): BuilderSettingsCanonicalizationResult;
18
+ //# sourceMappingURL=canonical-settings.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"canonical-settings.d.ts","sourceRoot":"","sources":["../src/canonical-settings.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAiB,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAE5E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEzD,MAAM,MAAM,uCAAuC,GAAG;IACpD,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,qCAAqC,GAAG;IAClD,QAAQ,EAAE,eAAe,CAAC;IAC1B,eAAe,EAAE,MAAM,CAAC;IACxB,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,uCAAuC,EAAE,CAAC;CACtD,CAAC;AAEF,wBAAgB,sCAAsC,CACpD,QAAQ,EAAE,eAAe,EACzB,QAAQ,EAAE,aAAa,GACtB,eAAe,CAEjB;AAED,wBAAgB,gDAAgD,CAC9D,QAAQ,EAAE,eAAe,EACzB,QAAQ,EAAE,aAAa,GACtB,qCAAqC,CAwBvC"}
@@ -0,0 +1,106 @@
1
+ import { sanitizeBuilderSettingsState } from "./persistence.js";
2
+ export function canonicalizeBuilderSettingsForManifest(settings, manifest) {
3
+ return canonicalizeBuilderSettingsForManifestWithReport(settings, manifest).settings;
4
+ }
5
+ export function canonicalizeBuilderSettingsForManifestWithReport(settings, manifest) {
6
+ const next = sanitizeBuilderSettingsState(cloneBuilderSettings(settings));
7
+ const conflicts = [];
8
+ let migratedAliases = 0;
9
+ let removedAliases = 0;
10
+ for (const [pageId, layout] of Object.entries(next.theme.layout)) {
11
+ for (const block of layout.blocks) {
12
+ const blockDefinition = manifest.blocks[block.type];
13
+ if (!blockDefinition)
14
+ continue;
15
+ const result = canonicalizeBlockSettings(pageId, block, Object.keys(blockDefinition.settings));
16
+ migratedAliases += result.migratedAliases;
17
+ removedAliases += result.removedAliases;
18
+ conflicts.push(...result.conflicts);
19
+ }
20
+ }
21
+ return {
22
+ settings: next,
23
+ migratedAliases,
24
+ removedAliases,
25
+ conflicts,
26
+ };
27
+ }
28
+ function canonicalizeBlockSettings(pageId, block, settingPaths) {
29
+ const aliases = buildAliasMap(block.type, settingPaths);
30
+ const conflicts = [];
31
+ let migratedAliases = 0;
32
+ let removedAliases = 0;
33
+ for (const [alias, canonicalPaths] of aliases.entries()) {
34
+ if (!Object.prototype.hasOwnProperty.call(block.settings, alias)) {
35
+ continue;
36
+ }
37
+ const aliasValue = block.settings[alias];
38
+ if (canonicalPaths.length === 1) {
39
+ const canonicalPath = canonicalPaths[0];
40
+ if (!Object.prototype.hasOwnProperty.call(block.settings, canonicalPath)) {
41
+ block.settings[canonicalPath] = aliasValue;
42
+ migratedAliases += 1;
43
+ }
44
+ else if (!isJsonEqual(block.settings[canonicalPath], aliasValue)) {
45
+ conflicts.push({
46
+ pageId,
47
+ blockId: block.id,
48
+ blockType: block.type,
49
+ alias,
50
+ canonicalPath,
51
+ });
52
+ }
53
+ delete block.settings[alias];
54
+ removedAliases += 1;
55
+ continue;
56
+ }
57
+ const everyCanonicalExists = canonicalPaths.every((canonicalPath) => Object.prototype.hasOwnProperty.call(block.settings, canonicalPath));
58
+ if (everyCanonicalExists) {
59
+ delete block.settings[alias];
60
+ removedAliases += 1;
61
+ }
62
+ }
63
+ return {
64
+ migratedAliases,
65
+ removedAliases,
66
+ conflicts,
67
+ };
68
+ }
69
+ function buildAliasMap(blockType, settingPaths) {
70
+ const aliases = new Map();
71
+ const canonicalPaths = new Set(settingPaths);
72
+ for (const canonicalPath of settingPaths) {
73
+ for (const alias of getLegacyAliases(blockType, canonicalPath)) {
74
+ if (alias === canonicalPath || canonicalPaths.has(alias))
75
+ continue;
76
+ const canonicalAliases = aliases.get(alias) ?? new Set();
77
+ canonicalAliases.add(canonicalPath);
78
+ aliases.set(alias, canonicalAliases);
79
+ }
80
+ }
81
+ return new Map(Array.from(aliases.entries()).map(([alias, paths]) => [alias, Array.from(paths).sort()]));
82
+ }
83
+ function getLegacyAliases(blockType, canonicalPath) {
84
+ const aliases = new Set();
85
+ const shortKey = getShortSettingKey(canonicalPath);
86
+ if (shortKey && shortKey !== canonicalPath) {
87
+ aliases.add(shortKey);
88
+ }
89
+ if (!canonicalPath.includes('.')) {
90
+ aliases.add(`${blockType}.${canonicalPath}`);
91
+ }
92
+ return Array.from(aliases);
93
+ }
94
+ function getShortSettingKey(path) {
95
+ const parts = path.split('.').filter(Boolean);
96
+ return parts.at(-1) ?? path;
97
+ }
98
+ function cloneBuilderSettings(settings) {
99
+ if (typeof structuredClone === 'function') {
100
+ return structuredClone(settings);
101
+ }
102
+ return JSON.parse(JSON.stringify(settings));
103
+ }
104
+ function isJsonEqual(left, right) {
105
+ return JSON.stringify(left) === JSON.stringify(right);
106
+ }
@@ -0,0 +1,15 @@
1
+ import type { BuilderSettings } from './builder-settings.ts';
2
+ import type { ManifestPage, ThemeManifest } from './theme-manifest.ts';
3
+ /**
4
+ * Allowed embed/content blocks on merchant custom pages (`theme.pages[]`).
5
+ * Keep aligned with `customPageAllowedBlocks` in
6
+ * `config/builder-shared-manifest-blocks.json`.
7
+ */
8
+ export declare const MERCHANT_CUSTOM_PAGE_ALLOWED_BLOCKS: readonly ["custom-html", "youtube-embed", "text-block"];
9
+ export type MerchantCustomPageAllowedBlock = (typeof MERCHANT_CUSTOM_PAGE_ALLOWED_BLOCKS)[number];
10
+ export declare function resolveMerchantCustomPageAllowedBlocks(manifest: ThemeManifest): string[];
11
+ export declare function buildMerchantCustomPageManifestEntry(customPage: BuilderSettings['theme']['pages'][number], manifest: ThemeManifest): ManifestPage;
12
+ export declare function mergeCustomPagesIntoManifest(manifest: ThemeManifest, settings: BuilderSettings): ThemeManifest;
13
+ export declare function findCustomPageBySlug(settings: BuilderSettings, slug: string): BuilderSettings['theme']['pages'][number] | undefined;
14
+ export declare function findCustomPageById(settings: BuilderSettings, pageId: string): BuilderSettings['theme']['pages'][number] | undefined;
15
+ //# sourceMappingURL=custom-pages.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"custom-pages.d.ts","sourceRoot":"","sources":["../src/custom-pages.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEvE;;;;GAIG;AACH,eAAO,MAAM,mCAAmC,yDAItC,CAAC;AAEX,MAAM,MAAM,8BAA8B,GACxC,CAAC,OAAO,mCAAmC,CAAC,CAAC,MAAM,CAAC,CAAC;AAEvD,wBAAgB,sCAAsC,CACpD,QAAQ,EAAE,aAAa,GACtB,MAAM,EAAE,CAIV;AAED,wBAAgB,oCAAoC,CAClD,UAAU,EAAE,eAAe,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,EACrD,QAAQ,EAAE,aAAa,GACtB,YAAY,CAOd;AAED,wBAAgB,4BAA4B,CAC1C,QAAQ,EAAE,aAAa,EACvB,QAAQ,EAAE,eAAe,GACxB,aAAa,CAef;AAED,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,eAAe,EACzB,IAAI,EAAE,MAAM,GACX,eAAe,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,GAAG,SAAS,CAEvD;AAED,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,eAAe,EACzB,MAAM,EAAE,MAAM,GACb,eAAe,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,GAAG,SAAS,CAEvD"}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Allowed embed/content blocks on merchant custom pages (`theme.pages[]`).
3
+ * Keep aligned with `customPageAllowedBlocks` in
4
+ * `config/builder-shared-manifest-blocks.json`.
5
+ */
6
+ export const MERCHANT_CUSTOM_PAGE_ALLOWED_BLOCKS = [
7
+ 'custom-html',
8
+ 'youtube-embed',
9
+ 'text-block',
10
+ ];
11
+ export function resolveMerchantCustomPageAllowedBlocks(manifest) {
12
+ return MERCHANT_CUSTOM_PAGE_ALLOWED_BLOCKS.filter((blockType) => blockType in manifest.blocks);
13
+ }
14
+ export function buildMerchantCustomPageManifestEntry(customPage, manifest) {
15
+ return {
16
+ label: customPage.title,
17
+ previewPath: `/page/${customPage.slug}`,
18
+ allowedBlocks: resolveMerchantCustomPageAllowedBlocks(manifest),
19
+ defaultBlocks: [],
20
+ };
21
+ }
22
+ export function mergeCustomPagesIntoManifest(manifest, settings) {
23
+ if (settings.theme.pages.length === 0) {
24
+ return manifest;
25
+ }
26
+ const pages = { ...manifest.pages };
27
+ for (const customPage of settings.theme.pages) {
28
+ if (pages[customPage.id]) {
29
+ continue;
30
+ }
31
+ pages[customPage.id] = buildMerchantCustomPageManifestEntry(customPage, manifest);
32
+ }
33
+ return { ...manifest, pages };
34
+ }
35
+ export function findCustomPageBySlug(settings, slug) {
36
+ return settings.theme.pages.find((page) => page.slug === slug);
37
+ }
38
+ export function findCustomPageById(settings, pageId) {
39
+ return settings.theme.pages.find((page) => page.id === pageId);
40
+ }
@@ -0,0 +1,15 @@
1
+ export declare const BUILDER_LAYOUT_PAGE_IDS: readonly ["home", "navigation", "product", "footer", "terms"];
2
+ export type BuilderLayoutPageId = (typeof BUILDER_LAYOUT_PAGE_IDS)[number];
3
+ export declare const BUILDER_DEDICATED_PAGE_IDS: readonly ["contact-page", "faq-page", "reviews-page", "feedback-page", "guide-page", "status-page", "checkout-page", "tool-page"];
4
+ export type BuilderDedicatedPageId = (typeof BUILDER_DEDICATED_PAGE_IDS)[number];
5
+ /** @deprecated Legacy manifest page ids migrated on settings load. */
6
+ export declare const DEDICATED_PAGE_ID_ALIASES: Readonly<Record<string, BuilderDedicatedPageId>>;
7
+ export declare function normalizeDedicatedPageId(pageId: string): string;
8
+ export declare function isDedicatedPageId(pageId: string): pageId is BuilderDedicatedPageId;
9
+ export declare function dedicatedPagePreviewPath(pageId: string): string | null;
10
+ export declare function dedicatedPageContentKey(pageId: string, field: string): string;
11
+ export declare function normalizeDedicatedPageBlockType(pageId: string): string;
12
+ export declare function createDedicatedPageBlockType(pageId: string): string;
13
+ export declare function migrateDedicatedPageLayout(layout: Record<string, unknown>): Record<string, unknown>;
14
+ export declare function migrateDedicatedPageContent(content: Record<string, unknown>): Record<string, unknown>;
15
+ //# sourceMappingURL=dedicated-pages.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dedicated-pages.d.ts","sourceRoot":"","sources":["../src/dedicated-pages.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,uBAAuB,+DAM1B,CAAC;AAEX,MAAM,MAAM,mBAAmB,GAAG,CAAC,OAAO,uBAAuB,CAAC,CAAC,MAAM,CAAC,CAAC;AAE3E,eAAO,MAAM,0BAA0B,mIAS7B,CAAC;AAEX,MAAM,MAAM,sBAAsB,GAAG,CAAC,OAAO,0BAA0B,CAAC,CAAC,MAAM,CAAC,CAAC;AAEjF,sEAAsE;AACtE,eAAO,MAAM,yBAAyB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,sBAAsB,CAAC,CAGtF,CAAC;AAaF,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAE/D;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,IAAI,sBAAsB,CAElF;AAED,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAMtE;AAED,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAE7E;AAED,wBAAgB,+BAA+B,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAEtE;AAED,wBAAgB,4BAA4B,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAMnE;AAkBD,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAoDnG;AAED,wBAAgB,2BAA2B,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CA8BrG"}
@@ -0,0 +1,142 @@
1
+ export const BUILDER_LAYOUT_PAGE_IDS = [
2
+ 'home',
3
+ 'navigation',
4
+ 'product',
5
+ 'footer',
6
+ 'terms',
7
+ ];
8
+ export const BUILDER_DEDICATED_PAGE_IDS = [
9
+ 'contact-page',
10
+ 'faq-page',
11
+ 'reviews-page',
12
+ 'feedback-page',
13
+ 'guide-page',
14
+ 'status-page',
15
+ 'checkout-page',
16
+ 'tool-page',
17
+ ];
18
+ /** @deprecated Legacy manifest page ids migrated on settings load. */
19
+ export const DEDICATED_PAGE_ID_ALIASES = {
20
+ reviews: 'reviews-page',
21
+ tool: 'tool-page',
22
+ };
23
+ const DEDICATED_PAGE_PREVIEW_PATHS = {
24
+ 'contact-page': '/contact',
25
+ 'faq-page': '/faq',
26
+ 'reviews-page': '/reviews',
27
+ 'feedback-page': '/feedback',
28
+ 'guide-page': '/guide',
29
+ 'status-page': '/status',
30
+ 'checkout-page': '/checkout',
31
+ 'tool-page': '/tool',
32
+ };
33
+ export function normalizeDedicatedPageId(pageId) {
34
+ return DEDICATED_PAGE_ID_ALIASES[pageId] ?? pageId;
35
+ }
36
+ export function isDedicatedPageId(pageId) {
37
+ return BUILDER_DEDICATED_PAGE_IDS.includes(pageId);
38
+ }
39
+ export function dedicatedPagePreviewPath(pageId) {
40
+ const normalized = normalizeDedicatedPageId(pageId);
41
+ if (!isDedicatedPageId(normalized)) {
42
+ return null;
43
+ }
44
+ return DEDICATED_PAGE_PREVIEW_PATHS[normalized];
45
+ }
46
+ export function dedicatedPageContentKey(pageId, field) {
47
+ return `pages.${normalizeDedicatedPageId(pageId)}.${field}`;
48
+ }
49
+ export function normalizeDedicatedPageBlockType(pageId) {
50
+ return createDedicatedPageBlockType(normalizeDedicatedPageId(pageId));
51
+ }
52
+ export function createDedicatedPageBlockType(pageId) {
53
+ const normalizedPageId = pageId
54
+ .toLowerCase()
55
+ .replace(/[^a-z0-9\-_.]+/g, '-')
56
+ .replace(/^[-_.]+/, '');
57
+ return `page-${normalizedPageId || 'custom'}`;
58
+ }
59
+ function migrateDedicatedPageBlockSettings(settings) {
60
+ if (typeof settings !== 'object' || settings === null || Array.isArray(settings)) {
61
+ return {};
62
+ }
63
+ const next = {};
64
+ for (const [key, value] of Object.entries(settings)) {
65
+ if (key.startsWith('tool.')) {
66
+ next[`pages.tool-page.${key.slice('tool.'.length)}`] = value;
67
+ continue;
68
+ }
69
+ next[key] = value;
70
+ }
71
+ return next;
72
+ }
73
+ export function migrateDedicatedPageLayout(layout) {
74
+ const next = { ...layout };
75
+ for (const [legacyId, canonicalId] of Object.entries(DEDICATED_PAGE_ID_ALIASES)) {
76
+ if (!Object.prototype.hasOwnProperty.call(next, legacyId)) {
77
+ continue;
78
+ }
79
+ const legacyLayout = next[legacyId];
80
+ delete next[legacyId];
81
+ if (Object.prototype.hasOwnProperty.call(next, canonicalId)) {
82
+ continue;
83
+ }
84
+ if (typeof legacyLayout !== 'object' || legacyLayout === null || Array.isArray(legacyLayout)) {
85
+ continue;
86
+ }
87
+ const blocks = legacyLayout.blocks;
88
+ if (!Array.isArray(blocks)) {
89
+ next[canonicalId] = legacyLayout;
90
+ continue;
91
+ }
92
+ const legacyBlockType = createDedicatedPageBlockType(legacyId);
93
+ const canonicalBlockType = createDedicatedPageBlockType(canonicalId);
94
+ next[canonicalId] = {
95
+ ...legacyLayout,
96
+ blocks: blocks.map((block) => {
97
+ if (typeof block !== 'object' || block === null || Array.isArray(block)) {
98
+ return block;
99
+ }
100
+ const typed = block;
101
+ const isLegacyBlockType = typed.type === legacyBlockType
102
+ || (legacyId === 'tool' && typed.type === 'tool');
103
+ if (!isLegacyBlockType) {
104
+ return block;
105
+ }
106
+ return {
107
+ ...typed,
108
+ type: canonicalBlockType,
109
+ settings: migrateDedicatedPageBlockSettings(typed.settings),
110
+ };
111
+ }),
112
+ };
113
+ }
114
+ return next;
115
+ }
116
+ export function migrateDedicatedPageContent(content) {
117
+ const next = { ...content };
118
+ for (const [key, value] of Object.entries(next)) {
119
+ if (key.startsWith('tool.') && !key.startsWith('tool-page.')) {
120
+ const canonicalKey = `pages.tool-page.${key.slice('tool.'.length)}`;
121
+ if (!Object.prototype.hasOwnProperty.call(next, canonicalKey)) {
122
+ next[canonicalKey] = value;
123
+ }
124
+ delete next[key];
125
+ }
126
+ }
127
+ for (const [legacyId, canonicalId] of Object.entries(DEDICATED_PAGE_ID_ALIASES)) {
128
+ const legacyPrefix = `pages.${legacyId}.`;
129
+ const canonicalPrefix = `pages.${canonicalId}.`;
130
+ for (const [key, value] of Object.entries(next)) {
131
+ if (!key.startsWith(legacyPrefix)) {
132
+ continue;
133
+ }
134
+ const canonicalKey = `${canonicalPrefix}${key.slice(legacyPrefix.length)}`;
135
+ if (!Object.prototype.hasOwnProperty.call(next, canonicalKey)) {
136
+ next[canonicalKey] = value;
137
+ }
138
+ delete next[key];
139
+ }
140
+ }
141
+ return next;
142
+ }