@shoppexio/builder-contracts 0.1.10 → 0.1.12

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.
@@ -64,5 +64,7 @@ export declare const PreviewBootPayloadSchema: z.ZodObject<{
64
64
  artifactStale: z.ZodOptional<z.ZodBoolean>;
65
65
  }, z.core.$strict>;
66
66
  export type PreviewBootPayload = z.infer<typeof PreviewBootPayloadSchema>;
67
+ /** Merge preview session identity + draft builder settings into an existing initial-data blob. */
68
+ export declare function mergePreviewBootFieldsIntoInitialData(initialData: Record<string, unknown>, payload: PreviewBootPayload): Record<string, unknown>;
67
69
  export declare function mergePreviewBootIntoInitialData(payload: PreviewBootPayload): Record<string, unknown>;
68
70
  //# sourceMappingURL=preview-boot.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"preview-boot.d.ts","sourceRoot":"","sources":["../src/preview-boot.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,QAAQ,CAAC;AAG5B,eAAO,MAAM,yBAAyB,gCAAgC,CAAC;AAIvE,eAAO,MAAM,oBAAoB;;;;;iBAOjB,CAAC;AAEjB,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAElE,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAS1B,CAAC;AAEZ,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC;AAE1E,wBAAgB,+BAA+B,CAC7C,OAAO,EAAE,kBAAkB,GAC1B,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAWzB"}
1
+ {"version":3,"file":"preview-boot.d.ts","sourceRoot":"","sources":["../src/preview-boot.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,QAAQ,CAAC;AAG5B,eAAO,MAAM,yBAAyB,gCAAgC,CAAC;AAIvE,eAAO,MAAM,oBAAoB;;;;;iBAOjB,CAAC;AAEjB,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAElE,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAS1B,CAAC;AAEZ,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC;AAE1E,kGAAkG;AAClG,wBAAgB,qCAAqC,CACnD,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACpC,OAAO,EAAE,kBAAkB,GAC1B,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAWzB;AAED,wBAAgB,+BAA+B,CAC7C,OAAO,EAAE,kBAAkB,GAC1B,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAKzB"}
@@ -21,10 +21,11 @@ export const PreviewBootPayloadSchema = z
21
21
  artifactStale: z.boolean().optional(),
22
22
  })
23
23
  .strict();
24
- export function mergePreviewBootIntoInitialData(payload) {
25
- const existingStore = isRecord(payload.storefrontSeed.store) ? payload.storefrontSeed.store : {};
24
+ /** Merge preview session identity + draft builder settings into an existing initial-data blob. */
25
+ export function mergePreviewBootFieldsIntoInitialData(initialData, payload) {
26
+ const existingStore = isRecord(initialData.store) ? initialData.store : {};
26
27
  return {
27
- ...payload.storefrontSeed,
28
+ ...initialData,
28
29
  store: {
29
30
  ...existingStore,
30
31
  id: payload.shopId,
@@ -33,6 +34,9 @@ export function mergePreviewBootIntoInitialData(payload) {
33
34
  },
34
35
  };
35
36
  }
37
+ export function mergePreviewBootIntoInitialData(payload) {
38
+ return mergePreviewBootFieldsIntoInitialData(payload.storefrontSeed, payload);
39
+ }
36
40
  function isRecord(value) {
37
41
  return typeof value === 'object' && value !== null && !Array.isArray(value);
38
42
  }
@@ -432,6 +432,11 @@ export declare const PreviewInlineEditCommitResponseSchema: z.ZodObject<{
432
432
  contentPath: z.ZodString;
433
433
  value: z.ZodString;
434
434
  }, z.core.$strict>;
435
+ /** Iframe reports in-preview navigation (pathname + search) for server-liquid block renders. */
436
+ export declare const PreviewRouteChangedResponseSchema: z.ZodObject<{
437
+ type: z.ZodLiteral<"PREVIEW_ROUTE_CHANGED">;
438
+ path: z.ZodString;
439
+ }, z.core.$strict>;
435
440
  export declare const PreviewResponseSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
436
441
  type: z.ZodLiteral<"BOOTSTRAP_OK">;
437
442
  revision: z.ZodNumber;
@@ -566,6 +571,9 @@ export declare const PreviewResponseSchema: z.ZodDiscriminatedUnion<[z.ZodObject
566
571
  blockId: z.ZodString;
567
572
  contentPath: z.ZodString;
568
573
  value: z.ZodString;
574
+ }, z.core.$strict>, z.ZodObject<{
575
+ type: z.ZodLiteral<"PREVIEW_ROUTE_CHANGED">;
576
+ path: z.ZodString;
569
577
  }, z.core.$strict>], "type">;
570
578
  export type PreviewResponse = z.infer<typeof PreviewResponseSchema>;
571
579
  //# sourceMappingURL=preview-protocol.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"preview-protocol.d.ts","sourceRoot":"","sources":["../src/preview-protocol.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,QAAQ,CAAC;AAG5B,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;kBAYxB,CAAC;AACZ,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAEtE,eAAO,MAAM,8BAA8B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAMhC,CAAC;AAEZ,eAAO,MAAM,4BAA4B,+BAA6B,CAAC;AACvE,MAAM,MAAM,sBAAsB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,4BAA4B,CAAC,CAAC;AAElF,eAAO,MAAM,2BAA2B;;;kBAK7B,CAAC;AACZ,MAAM,MAAM,qBAAqB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,2BAA2B,CAAC,CAAC;AAEhF,eAAO,MAAM,kCAAkC;;;;;;;;;;kBASpC,CAAC;AACZ,MAAM,MAAM,4BAA4B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kCAAkC,CAAC,CAAC;AAE9F,eAAO,MAAM,iCAAiC;;;;;;;kBASnC,CAAC;AACZ,MAAM,MAAM,2BAA2B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iCAAiC,CAAC,CAAC;AAE5F,eAAO,MAAM,0BAA0B;;;;;;;kBAM5B,CAAC;AAEZ,eAAO,MAAM,iCAAiC;;;;;;;;;;;;;;;;;;;;;kBAMnC,CAAC;AAEZ,eAAO,MAAM,gCAAgC;;kBAIlC,CAAC;AAEZ,eAAO,MAAM,qBAAqB;;;EAA8B,CAAC;AACjE,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAEpE;;;;;GAKG;AACH,eAAO,MAAM,sCAAsC;;;;;;kBAKxC,CAAC;AAEZ,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4BAQ/B,CAAC;AACH,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAElE,eAAO,MAAM,gCAAgC;;;;;;kBAQlC,CAAC;AAEZ;;;;;GAKG;AACH,eAAO,MAAM,+BAA+B;;;;kBAMjC,CAAC;AAEZ,eAAO,MAAM,wBAAwB;;;;;;;;uCAenC,CAAC;AACH,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC;AAE1E,eAAO,MAAM,0BAA0B;;;;;;;;;;;;kBAM5B,CAAC;AAEZ,eAAO,MAAM,4BAA4B;;;kBAK9B,CAAC;AAEZ,eAAO,MAAM,gCAAgC;;;;kBAMlC,CAAC;AAEZ,eAAO,MAAM,qCAAqC;;;;;;;;;;kBASvC,CAAC;AAEZ,eAAO,MAAM,oCAAoC;;;;;;;;kBAUtC,CAAC;AAEZ,eAAO,MAAM,mCAAmC;;;;;;;;;;;;;;;;;;;;;kBAMrC,CAAC;AAEZ,eAAO,MAAM,0BAA0B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBA0B5B,CAAC;AAEZ;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB;;;;;kBAOnB,CAAC;AACZ,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAE5D,eAAO,MAAM,8BAA8B;;;;;;;;;;kBAOhC,CAAC;AAEZ;;;;GAIG;AACH,eAAO,MAAM,kCAAkC;;;;;;;;;;kBAOpC,CAAC;AAEZ;;;;GAIG;AACH,eAAO,MAAM,qCAAqC;;;;;;kBAQvC,CAAC;AAEZ,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4BAahC,CAAC;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC"}
1
+ {"version":3,"file":"preview-protocol.d.ts","sourceRoot":"","sources":["../src/preview-protocol.ts"],"names":[],"mappings":"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"}
@@ -250,6 +250,13 @@ export const PreviewInlineEditCommitResponseSchema = z
250
250
  value: z.string(),
251
251
  })
252
252
  .strict();
253
+ /** Iframe reports in-preview navigation (pathname + search) for server-liquid block renders. */
254
+ export const PreviewRouteChangedResponseSchema = z
255
+ .object({
256
+ type: z.literal('PREVIEW_ROUTE_CHANGED'),
257
+ path: z.string().min(1),
258
+ })
259
+ .strict();
253
260
  export const PreviewResponseSchema = z.discriminatedUnion('type', [
254
261
  PreviewBootstrapOkResponseSchema,
255
262
  PreviewBootFailedResponseSchema,
@@ -263,4 +270,5 @@ export const PreviewResponseSchema = z.discriminatedUnion('type', [
263
270
  PreviewBlockRectResponseSchema,
264
271
  PreviewInserterHoverResponseSchema,
265
272
  PreviewInlineEditCommitResponseSchema,
273
+ PreviewRouteChangedResponseSchema,
266
274
  ]);
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Normalizes the storefront route visible inside a theme-preview iframe after the
3
+ * worker strips the `/s/:sessionId/:draftToken` prefix via history.replaceState.
4
+ */
5
+ export declare function readPreviewStorefrontRoutePath(pathname: string, search?: string, hash?: string): string | null;
6
+ //# sourceMappingURL=preview-route.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"preview-route.d.ts","sourceRoot":"","sources":["../src/preview-route.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,wBAAgB,8BAA8B,CAC5C,QAAQ,EAAE,MAAM,EAChB,MAAM,SAAK,EACX,IAAI,SAAK,GACR,MAAM,GAAG,IAAI,CAaf"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Normalizes the storefront route visible inside a theme-preview iframe after the
3
+ * worker strips the `/s/:sessionId/:draftToken` prefix via history.replaceState.
4
+ */
5
+ export function readPreviewStorefrontRoutePath(pathname, search = '', hash = '') {
6
+ const path = pathname.trim() || '/';
7
+ if (path.includes('/__shoppex/')) {
8
+ return null;
9
+ }
10
+ const lastSegment = path.split('/').pop() ?? '';
11
+ if (lastSegment.includes('.')) {
12
+ return null;
13
+ }
14
+ const normalizedPath = path.replace(/\/+$/, '') || '/';
15
+ return `${normalizedPath}${search}${hash}`;
16
+ }
@@ -12,6 +12,13 @@ export declare function buildPlainInitialDataScript(initialData: Record<string,
12
12
  export declare function buildWrappedStorefrontInitialDataScript(serialized: string, deployedThemeEntryPathPattern: RegExp): string;
13
13
  export declare function injectPlainInitialDataBeforeHeadClose(html: string, script: string): string;
14
14
  export declare function injectPreviewInitialData(html: string, payload: PreviewBootPayload): string;
15
+ /**
16
+ * Server-liquid preview pages are SSR'd with live storefront slices (storeStats, catalog, …).
17
+ * Replacing their initial-data scripts with the build-time artifact seed drops live sales counts
18
+ * and the bootstrap hydration pass overwrites hero stats back to 0. Keep the SSR snapshot and
19
+ * only merge preview-session fields (shop id/slug + draft builder settings).
20
+ */
21
+ export declare function injectServerLiquidPreviewBoot(html: string, payload: PreviewBootPayload): string;
15
22
  export declare function assertSingleInitialDataScript(html: string, expectedSlug: string): void;
16
23
  export declare function safeJson(value: unknown): string;
17
24
  //# sourceMappingURL=storefront-initial-data-html.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"storefront-initial-data-html.d.ts","sourceRoot":"","sources":["../src/storefront-initial-data-html.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAG5D,eAAO,MAAM,0BAA0B,QAC8K,CAAC;AAEtN,eAAO,MAAM,2BAA2B,QACuB,CAAC;AAOhE,MAAM,MAAM,sBAAsB,GAAG;IACnC,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAI/D;AAED,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,MAAM,GAAG,sBAAsB,GAAG,IAAI,CAYrF;AAED,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAWnF;AAED,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAK5D;AAED,wBAAgB,2BAA2B,CAAC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAExF;AAED,wBAAgB,uCAAuC,CACrD,UAAU,EAAE,MAAM,EAClB,6BAA6B,EAAE,MAAM,GACpC,MAAM,CAOR;AAED,wBAAgB,qCAAqC,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAK1F;AAED,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,kBAAkB,GAAG,MAAM,CAK1F;AAED,wBAAgB,6BAA6B,CAAC,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,IAAI,CAmBtF;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAE/C"}
1
+ {"version":3,"file":"storefront-initial-data-html.d.ts","sourceRoot":"","sources":["../src/storefront-initial-data-html.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAM5D,eAAO,MAAM,0BAA0B,QAC8K,CAAC;AAEtN,eAAO,MAAM,2BAA2B,QACuB,CAAC;AAOhE,MAAM,MAAM,sBAAsB,GAAG;IACnC,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAI/D;AAED,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,MAAM,GAAG,sBAAsB,GAAG,IAAI,CAYrF;AAED,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAWnF;AAED,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAK5D;AAED,wBAAgB,2BAA2B,CAAC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAExF;AAED,wBAAgB,uCAAuC,CACrD,UAAU,EAAE,MAAM,EAClB,6BAA6B,EAAE,MAAM,GACpC,MAAM,CAOR;AAED,wBAAgB,qCAAqC,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAK1F;AAED,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,kBAAkB,GAAG,MAAM,CAK1F;AAED;;;;;GAKG;AACH,wBAAgB,6BAA6B,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,kBAAkB,GAAG,MAAM,CAa/F;AAED,wBAAgB,6BAA6B,CAAC,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,IAAI,CAmBtF;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAE/C"}
@@ -1,4 +1,4 @@
1
- import { mergePreviewBootIntoInitialData } from "./preview-boot.js";
1
+ import { mergePreviewBootFieldsIntoInitialData, mergePreviewBootIntoInitialData, } from "./preview-boot.js";
2
2
  export const HTML_INITIAL_BLOCK_PATTERN = /<!--shoppex-initial-data:start--><script>\(function\(\)\{[\s\S]*?window\.__SHOPPEX_INITIAL__=([\s\S]*?)(?=;\}\)\(\);<\/script><!--shoppex-initial-data:end-->);\}\)\(\);<\/script><!--shoppex-initial-data:end-->/;
3
3
  export const LEGACY_HTML_INITIAL_PATTERN = /<script>\s*window\.__SHOPPEX_INITIAL__=([\s\S]*?)<\/script>/;
4
4
  const HTML_INITIAL_BLOCK_GLOBAL_PATTERN = new RegExp(HTML_INITIAL_BLOCK_PATTERN.source, 'g');
@@ -61,6 +61,25 @@ export function injectPreviewInitialData(html, payload) {
61
61
  const script = buildPlainInitialDataScript(initialData);
62
62
  return injectPlainInitialDataBeforeHeadClose(withoutScripts, script);
63
63
  }
64
+ /**
65
+ * Server-liquid preview pages are SSR'd with live storefront slices (storeStats, catalog, …).
66
+ * Replacing their initial-data scripts with the build-time artifact seed drops live sales counts
67
+ * and the bootstrap hydration pass overwrites hero stats back to 0. Keep the SSR snapshot and
68
+ * only merge preview-session fields (shop id/slug + draft builder settings).
69
+ */
70
+ export function injectServerLiquidPreviewBoot(html, payload) {
71
+ const existing = findInitialDataPayload(html);
72
+ if (!existing) {
73
+ const merged = mergePreviewBootFieldsIntoInitialData({ store: {} }, payload);
74
+ const withoutScripts = stripAllInitialDataScripts(html);
75
+ const script = buildPlainInitialDataScript(merged);
76
+ return injectPlainInitialDataBeforeHeadClose(withoutScripts, script);
77
+ }
78
+ const merged = mergePreviewBootFieldsIntoInitialData(existing, payload);
79
+ const withoutScripts = stripAllInitialDataScripts(html);
80
+ const script = buildPlainInitialDataScript(merged);
81
+ return injectPlainInitialDataBeforeHeadClose(withoutScripts, script);
82
+ }
64
83
  export function assertSingleInitialDataScript(html, expectedSlug) {
65
84
  const count = countInitialDataScripts(html);
66
85
  if (count !== 1) {
@@ -1,9 +1,9 @@
1
- export declare const PUBLIC_BUILDER_THEME_SCHEMES: readonly ["default", "classic", "nebula", "pulse", "phantom", "starlight", "apex", "vault", "clean-minimal"];
1
+ export declare const PUBLIC_BUILDER_THEME_SCHEMES: readonly ["default", "classic", "nebula", "pulse", "phantom", "starlight", "apex", "vault", "clean-minimal", "shadow"];
2
2
  export type PublicBuilderThemeScheme = (typeof PUBLIC_BUILDER_THEME_SCHEMES)[number];
3
3
  export declare const STARTER_BUILDER_THEME_SCHEMES: readonly ["blank"];
4
- export declare const THEME_STORE_DISABLED_SCHEMES: readonly ["apex"];
5
- export declare const THEME_STORE_INSTALLABLE_SCHEMES: readonly ["default", "starlight", "pulse", "vault", "clean-minimal", "classic", "phantom", "nebula"];
6
- export declare const BUILDER_READY_THEME_SCHEMES: readonly ["blank", "default", "classic", "nebula", "pulse", "phantom", "starlight", "apex", "vault", "clean-minimal"];
4
+ export declare const THEME_STORE_DISABLED_SCHEMES: readonly [];
5
+ export declare const THEME_STORE_INSTALLABLE_SCHEMES: readonly ["default", "starlight", "pulse", "vault", "clean-minimal", "classic", "phantom", "nebula", "apex", "shadow"];
6
+ export declare const BUILDER_READY_THEME_SCHEMES: readonly ["blank", "default", "classic", "nebula", "pulse", "phantom", "starlight", "apex", "vault", "clean-minimal", "shadow"];
7
7
  export type ThemeStoreInstallableScheme = (typeof THEME_STORE_INSTALLABLE_SCHEMES)[number];
8
8
  export type StarterBuilderThemeScheme = (typeof STARTER_BUILDER_THEME_SCHEMES)[number];
9
9
  export type BuilderReadyThemeScheme = (typeof BUILDER_READY_THEME_SCHEMES)[number];
@@ -1 +1 @@
1
- {"version":3,"file":"theme-schemes.d.ts","sourceRoot":"","sources":["../src/theme-schemes.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,4BAA4B,8GAU/B,CAAC;AAEX,MAAM,MAAM,wBAAwB,GAAG,CAAC,OAAO,4BAA4B,CAAC,CAAC,MAAM,CAAC,CAAC;AAErF,eAAO,MAAM,6BAA6B,oBAAqB,CAAC;AAEhE,eAAO,MAAM,4BAA4B,mBAEe,CAAC;AAIzD,eAAO,MAAM,+BAA+B,sGASY,CAAC;AAEzD,eAAO,MAAM,2BAA2B,uHAG9B,CAAC;AAEX,MAAM,MAAM,2BAA2B,GAAG,CAAC,OAAO,+BAA+B,CAAC,CAAC,MAAM,CAAC,CAAC;AAC3F,MAAM,MAAM,yBAAyB,GAAG,CAAC,OAAO,6BAA6B,CAAC,CAAC,MAAM,CAAC,CAAC;AACvF,MAAM,MAAM,uBAAuB,GAAG,CAAC,OAAO,2BAA2B,CAAC,CAAC,MAAM,CAAC,CAAC;AAEnF,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,IAAI,wBAAwB,CAE3F;AAED,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAEjE;AAED,wBAAgB,6BAA6B,CAC3C,KAAK,EAAE,MAAM,GACZ,KAAK,IAAI,2BAA2B,CAEtC;AAED,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,IAAI,yBAAyB,CAE7F;AAED,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,IAAI,uBAAuB,CAEzF"}
1
+ {"version":3,"file":"theme-schemes.d.ts","sourceRoot":"","sources":["../src/theme-schemes.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,4BAA4B,wHAW/B,CAAC;AAEX,MAAM,MAAM,wBAAwB,GAAG,CAAC,OAAO,4BAA4B,CAAC,CAAC,MAAM,CAAC,CAAC;AAErF,eAAO,MAAM,6BAA6B,oBAAqB,CAAC;AAEhE,eAAO,MAAM,4BAA4B,aAA4D,CAAC;AAItG,eAAO,MAAM,+BAA+B,wHAWY,CAAC;AAEzD,eAAO,MAAM,2BAA2B,iIAG9B,CAAC;AAEX,MAAM,MAAM,2BAA2B,GAAG,CAAC,OAAO,+BAA+B,CAAC,CAAC,MAAM,CAAC,CAAC;AAC3F,MAAM,MAAM,yBAAyB,GAAG,CAAC,OAAO,6BAA6B,CAAC,CAAC,MAAM,CAAC,CAAC;AACvF,MAAM,MAAM,uBAAuB,GAAG,CAAC,OAAO,2BAA2B,CAAC,CAAC,MAAM,CAAC,CAAC;AAEnF,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,IAAI,wBAAwB,CAE3F;AAED,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAEjE;AAED,wBAAgB,6BAA6B,CAC3C,KAAK,EAAE,MAAM,GACZ,KAAK,IAAI,2BAA2B,CAEtC;AAED,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,IAAI,yBAAyB,CAE7F;AAED,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,IAAI,uBAAuB,CAEzF"}
@@ -8,11 +8,10 @@ export const PUBLIC_BUILDER_THEME_SCHEMES = [
8
8
  'apex',
9
9
  'vault',
10
10
  'clean-minimal',
11
+ 'shadow',
11
12
  ];
12
13
  export const STARTER_BUILDER_THEME_SCHEMES = ['blank'];
13
- export const THEME_STORE_DISABLED_SCHEMES = [
14
- 'apex',
15
- ];
14
+ export const THEME_STORE_DISABLED_SCHEMES = [];
16
15
  const THEME_STORE_DISABLED_SCHEME_SET = new Set(THEME_STORE_DISABLED_SCHEMES);
17
16
  export const THEME_STORE_INSTALLABLE_SCHEMES = [
18
17
  'default',
@@ -23,6 +22,8 @@ export const THEME_STORE_INSTALLABLE_SCHEMES = [
23
22
  'classic',
24
23
  'phantom',
25
24
  'nebula',
25
+ 'apex',
26
+ 'shadow',
26
27
  ];
27
28
  export const BUILDER_READY_THEME_SCHEMES = [
28
29
  ...STARTER_BUILDER_THEME_SCHEMES,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shoppexio/builder-contracts",
3
- "version": "0.1.10",
3
+ "version": "0.1.12",
4
4
  "description": "Shared Builder v2 contracts for Shoppex dashboard, backend, preview runtime, and themes",
5
5
  "type": "module",
6
6
  "repository": {
@@ -91,6 +91,12 @@
91
91
  "import": "./dist/preview-protocol.js",
92
92
  "default": "./dist/preview-protocol.js"
93
93
  },
94
+ "./preview-route": {
95
+ "bun": "./src/preview-route.ts",
96
+ "types": "./dist/preview-route.d.ts",
97
+ "import": "./dist/preview-route.js",
98
+ "default": "./dist/preview-route.js"
99
+ },
94
100
  "./preview-boot": {
95
101
  "bun": "./src/preview-boot.ts",
96
102
  "types": "./dist/preview-boot.d.ts",
@@ -857,7 +857,7 @@ describe('@shoppex/builder-contracts', () => {
857
857
 
858
858
  test('parses official theme manifests with transparent contact-form backgrounds', () => {
859
859
  const repoRoot = join(import.meta.dir, '../../..');
860
- for (const theme of ['default', 'nebula', 'classic', 'pulse', 'starlight', 'vault', 'phantom', 'apex']) {
860
+ for (const theme of ['default', 'nebula', 'classic', 'pulse', 'starlight', 'vault', 'phantom', 'apex', 'shadow']) {
861
861
  const manifestPath = join(repoRoot, 'themes', theme, 'theme.manifest.json');
862
862
  const raw = JSON.parse(readFileSync(manifestPath, 'utf8'));
863
863
  expect(ThemeManifestSchema.safeParse(raw).success, `${theme} manifest should validate`).toBe(true);
@@ -1,5 +1,5 @@
1
1
  import { describe, expect, it } from 'bun:test';
2
- import { mergePreviewBootIntoInitialData, PreviewBootPayloadSchema } from './preview-boot.ts';
2
+ import { mergePreviewBootFieldsIntoInitialData, mergePreviewBootIntoInitialData, PreviewBootPayloadSchema } from './preview-boot.ts';
3
3
 
4
4
  describe('PreviewBootPayloadSchema', () => {
5
5
  it('accepts storefront seeds with catalog fields from built theme artifacts', () => {
@@ -69,4 +69,41 @@ describe('PreviewBootPayloadSchema', () => {
69
69
  expect(initialData.addons).toEqual([{ id: 'addon_1' }]);
70
70
  expect(initialData.menus).toEqual([{ id: 'menu_1' }]);
71
71
  });
72
+
73
+ it('mergePreviewBootFieldsIntoInitialData preserves live storeStats from SSR snapshots', () => {
74
+ const initialData = mergePreviewBootFieldsIntoInitialData(
75
+ {
76
+ store: { slug: 'florain', name: 'Florain' },
77
+ storeStats: { sales: '29', products: '13+', rating: '0.0' },
78
+ products: [{ uniqid: 'p1' }],
79
+ },
80
+ {
81
+ shopId: 'shop_1',
82
+ shopSlug: 'florain',
83
+ builderSettings: {
84
+ version: 2,
85
+ revision: 2,
86
+ theme: {
87
+ content: {},
88
+ layout: {},
89
+ style_slots: {},
90
+ pages: [],
91
+ terms: {},
92
+ },
93
+ },
94
+ storefrontSeed: {
95
+ store: { slug: 'stale-artifact', products_sold_count: 0 },
96
+ storeStats: { sales: '0' },
97
+ },
98
+ },
99
+ );
100
+
101
+ expect(initialData.storeStats).toEqual({ sales: '29', products: '13+', rating: '0.0' });
102
+ expect(initialData.products).toEqual([{ uniqid: 'p1' }]);
103
+ expect(initialData.store).toMatchObject({
104
+ id: 'shop_1',
105
+ slug: 'florain',
106
+ name: 'Florain',
107
+ });
108
+ });
72
109
  });
@@ -29,12 +29,14 @@ export const PreviewBootPayloadSchema = z
29
29
 
30
30
  export type PreviewBootPayload = z.infer<typeof PreviewBootPayloadSchema>;
31
31
 
32
- export function mergePreviewBootIntoInitialData(
32
+ /** Merge preview session identity + draft builder settings into an existing initial-data blob. */
33
+ export function mergePreviewBootFieldsIntoInitialData(
34
+ initialData: Record<string, unknown>,
33
35
  payload: PreviewBootPayload,
34
36
  ): Record<string, unknown> {
35
- const existingStore = isRecord(payload.storefrontSeed.store) ? payload.storefrontSeed.store : {};
37
+ const existingStore = isRecord(initialData.store) ? initialData.store : {};
36
38
  return {
37
- ...payload.storefrontSeed,
39
+ ...initialData,
38
40
  store: {
39
41
  ...existingStore,
40
42
  id: payload.shopId,
@@ -44,6 +46,15 @@ export function mergePreviewBootIntoInitialData(
44
46
  };
45
47
  }
46
48
 
49
+ export function mergePreviewBootIntoInitialData(
50
+ payload: PreviewBootPayload,
51
+ ): Record<string, unknown> {
52
+ return mergePreviewBootFieldsIntoInitialData(
53
+ payload.storefrontSeed as Record<string, unknown>,
54
+ payload,
55
+ );
56
+ }
57
+
47
58
  function isRecord(value: unknown): value is Record<string, unknown> {
48
59
  return typeof value === 'object' && value !== null && !Array.isArray(value);
49
60
  }
@@ -259,6 +259,17 @@ describe('PreviewResponseSchema', () => {
259
259
  }
260
260
  });
261
261
 
262
+ it('accepts PREVIEW_ROUTE_CHANGED with storefront path', () => {
263
+ const parsed = PreviewResponseSchema.parse({
264
+ type: 'PREVIEW_ROUTE_CHANGED',
265
+ path: '/products?category=fivem&sort=price-asc',
266
+ });
267
+ expect(parsed.type).toBe('PREVIEW_ROUTE_CHANGED');
268
+ if (parsed.type === 'PREVIEW_ROUTE_CHANGED') {
269
+ expect(parsed.path).toBe('/products?category=fivem&sort=price-asc');
270
+ }
271
+ });
272
+
262
273
  it('rejects INLINE_EDIT_COMMIT without contentPath', () => {
263
274
  const result = PreviewResponseSchema.safeParse({
264
275
  type: 'INLINE_EDIT_COMMIT',
@@ -286,6 +286,14 @@ export const PreviewInlineEditCommitResponseSchema = z
286
286
  })
287
287
  .strict();
288
288
 
289
+ /** Iframe reports in-preview navigation (pathname + search) for server-liquid block renders. */
290
+ export const PreviewRouteChangedResponseSchema = z
291
+ .object({
292
+ type: z.literal('PREVIEW_ROUTE_CHANGED'),
293
+ path: z.string().min(1),
294
+ })
295
+ .strict();
296
+
289
297
  export const PreviewResponseSchema = z.discriminatedUnion('type', [
290
298
  PreviewBootstrapOkResponseSchema,
291
299
  PreviewBootFailedResponseSchema,
@@ -299,5 +307,6 @@ export const PreviewResponseSchema = z.discriminatedUnion('type', [
299
307
  PreviewBlockRectResponseSchema,
300
308
  PreviewInserterHoverResponseSchema,
301
309
  PreviewInlineEditCommitResponseSchema,
310
+ PreviewRouteChangedResponseSchema,
302
311
  ]);
303
312
  export type PreviewResponse = z.infer<typeof PreviewResponseSchema>;
@@ -0,0 +1,22 @@
1
+ import { describe, expect, test } from 'vitest';
2
+ import { readPreviewStorefrontRoutePath } from './preview-route';
3
+
4
+ describe('readPreviewStorefrontRoutePath', () => {
5
+ test('returns pathname and search for storefront routes', () => {
6
+ expect(readPreviewStorefrontRoutePath('/products', '?category=fivem&sort=price-asc'))
7
+ .toBe('/products?category=fivem&sort=price-asc');
8
+ });
9
+
10
+ test('normalizes trailing slashes on non-root paths', () => {
11
+ expect(readPreviewStorefrontRoutePath('/products/', '?page=2')).toBe('/products?page=2');
12
+ });
13
+
14
+ test('preserves root path', () => {
15
+ expect(readPreviewStorefrontRoutePath('/', '?currency=EUR')).toBe('/?currency=EUR');
16
+ });
17
+
18
+ test('rejects asset and sidecar paths', () => {
19
+ expect(readPreviewStorefrontRoutePath('/assets/built.css')).toBeNull();
20
+ expect(readPreviewStorefrontRoutePath('/s/session/token/__shoppex/preview-boot.json')).toBeNull();
21
+ });
22
+ });
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Normalizes the storefront route visible inside a theme-preview iframe after the
3
+ * worker strips the `/s/:sessionId/:draftToken` prefix via history.replaceState.
4
+ */
5
+ export function readPreviewStorefrontRoutePath(
6
+ pathname: string,
7
+ search = '',
8
+ hash = '',
9
+ ): string | null {
10
+ const path = pathname.trim() || '/';
11
+ if (path.includes('/__shoppex/')) {
12
+ return null;
13
+ }
14
+
15
+ const lastSegment = path.split('/').pop() ?? '';
16
+ if (lastSegment.includes('.')) {
17
+ return null;
18
+ }
19
+
20
+ const normalizedPath = path.replace(/\/+$/, '') || '/';
21
+ return `${normalizedPath}${search}${hash}`;
22
+ }
@@ -6,6 +6,7 @@ import {
6
6
  countInitialDataScripts,
7
7
  findInitialDataPayload,
8
8
  injectPreviewInitialData,
9
+ injectServerLiquidPreviewBoot,
9
10
  stripAllInitialDataScripts,
10
11
  } from './storefront-initial-data-html.ts';
11
12
 
@@ -56,6 +57,31 @@ describe('storefront-initial-data-html', () => {
56
57
  slug: 'demo-shop',
57
58
  });
58
59
  });
60
+
61
+ it('preserves live storeStats when merging preview boot into server-liquid SSR initial data', () => {
62
+ const html = [
63
+ '<html><head>',
64
+ '<script>window.__SHOPPEX_INITIAL__={"store":{"slug":"florain","name":"Florain"},"storeStats":{"sales":"29","products":"13+","rating":"0.0"}};</script>',
65
+ '<script data-shoppex-bootstrap="v2">window.shopId="shop_1";</script>',
66
+ '</head><body><span data-shoppex-runtime-stat="sales">29</span></body></html>',
67
+ ].join('');
68
+
69
+ const next = injectServerLiquidPreviewBoot(html, samplePayload);
70
+ expect(countInitialDataScripts(next)).toBe(1);
71
+ assertSingleInitialDataScript(next, 'demo-shop');
72
+ expect(findInitialDataPayload(next)).toMatchObject({
73
+ storeStats: {
74
+ sales: '29',
75
+ products: '13+',
76
+ rating: '0.0',
77
+ },
78
+ store: {
79
+ id: 'shop_1',
80
+ slug: 'demo-shop',
81
+ name: 'Florain',
82
+ },
83
+ });
84
+ });
59
85
  it('throws when assert sees zero or multiple scripts', () => {
60
86
  expect(() => assertSingleInitialDataScript('<html></html>', 'demo-shop')).toThrow();
61
87
  const html = [
@@ -1,5 +1,8 @@
1
1
  import type { PreviewBootPayload } from './preview-boot.ts';
2
- import { mergePreviewBootIntoInitialData } from './preview-boot.ts';
2
+ import {
3
+ mergePreviewBootFieldsIntoInitialData,
4
+ mergePreviewBootIntoInitialData,
5
+ } from './preview-boot.ts';
3
6
 
4
7
  export const HTML_INITIAL_BLOCK_PATTERN =
5
8
  /<!--shoppex-initial-data:start--><script>\(function\(\)\{[\s\S]*?window\.__SHOPPEX_INITIAL__=([\s\S]*?)(?=;\}\)\(\);<\/script><!--shoppex-initial-data:end-->);\}\)\(\);<\/script><!--shoppex-initial-data:end-->/;
@@ -86,6 +89,27 @@ export function injectPreviewInitialData(html: string, payload: PreviewBootPaylo
86
89
  return injectPlainInitialDataBeforeHeadClose(withoutScripts, script);
87
90
  }
88
91
 
92
+ /**
93
+ * Server-liquid preview pages are SSR'd with live storefront slices (storeStats, catalog, …).
94
+ * Replacing their initial-data scripts with the build-time artifact seed drops live sales counts
95
+ * and the bootstrap hydration pass overwrites hero stats back to 0. Keep the SSR snapshot and
96
+ * only merge preview-session fields (shop id/slug + draft builder settings).
97
+ */
98
+ export function injectServerLiquidPreviewBoot(html: string, payload: PreviewBootPayload): string {
99
+ const existing = findInitialDataPayload(html);
100
+ if (!existing) {
101
+ const merged = mergePreviewBootFieldsIntoInitialData({ store: {} }, payload);
102
+ const withoutScripts = stripAllInitialDataScripts(html);
103
+ const script = buildPlainInitialDataScript(merged);
104
+ return injectPlainInitialDataBeforeHeadClose(withoutScripts, script);
105
+ }
106
+
107
+ const merged = mergePreviewBootFieldsIntoInitialData(existing, payload);
108
+ const withoutScripts = stripAllInitialDataScripts(html);
109
+ const script = buildPlainInitialDataScript(merged);
110
+ return injectPlainInitialDataBeforeHeadClose(withoutScripts, script);
111
+ }
112
+
89
113
  export function assertSingleInitialDataScript(html: string, expectedSlug: string): void {
90
114
  const count = countInitialDataScripts(html);
91
115
  if (count !== 1) {
@@ -8,15 +8,14 @@ export const PUBLIC_BUILDER_THEME_SCHEMES = [
8
8
  'apex',
9
9
  'vault',
10
10
  'clean-minimal',
11
+ 'shadow',
11
12
  ] as const;
12
13
 
13
14
  export type PublicBuilderThemeScheme = (typeof PUBLIC_BUILDER_THEME_SCHEMES)[number];
14
15
 
15
16
  export const STARTER_BUILDER_THEME_SCHEMES = ['blank'] as const;
16
17
 
17
- export const THEME_STORE_DISABLED_SCHEMES = [
18
- 'apex',
19
- ] as const satisfies readonly PublicBuilderThemeScheme[];
18
+ export const THEME_STORE_DISABLED_SCHEMES = [] as const satisfies readonly PublicBuilderThemeScheme[];
20
19
 
21
20
  const THEME_STORE_DISABLED_SCHEME_SET = new Set<string>(THEME_STORE_DISABLED_SCHEMES);
22
21
 
@@ -29,6 +28,8 @@ export const THEME_STORE_INSTALLABLE_SCHEMES = [
29
28
  'classic',
30
29
  'phantom',
31
30
  'nebula',
31
+ 'apex',
32
+ 'shadow',
32
33
  ] as const satisfies readonly PublicBuilderThemeScheme[];
33
34
 
34
35
  export const BUILDER_READY_THEME_SCHEMES = [