@shoppexio/builder-contracts 0.1.3 → 0.1.6
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/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/preview-protocol.d.ts +28 -11
- package/dist/preview-protocol.d.ts.map +1 -1
- package/dist/preview-protocol.js +19 -8
- package/dist/storefront-render-frame-origins.d.ts +11 -0
- package/dist/storefront-render-frame-origins.d.ts.map +1 -0
- package/dist/storefront-render-frame-origins.js +23 -0
- package/dist/storefront-render-integrations.d.ts +10 -0
- package/dist/storefront-render-integrations.d.ts.map +1 -0
- package/dist/storefront-render-integrations.js +55 -0
- package/dist/storefront-render-seo.d.ts +11 -0
- package/dist/storefront-render-seo.d.ts.map +1 -0
- package/dist/storefront-render-seo.js +30 -0
- package/dist/theme-schemes.d.ts +8 -3
- package/dist/theme-schemes.d.ts.map +1 -1
- package/dist/theme-schemes.js +20 -1
- package/package.json +19 -1
- package/src/builder-contracts.test.ts +1 -1
- package/src/index.ts +2 -0
- package/src/preview-protocol.test.ts +55 -7
- package/src/preview-protocol.ts +23 -9
- package/src/storefront-render-frame-origins.ts +26 -0
- package/src/storefront-render-integrations.test.ts +62 -0
- package/src/storefront-render-integrations.ts +81 -0
- package/src/storefront-render-seo.test.ts +33 -0
- package/src/storefront-render-seo.ts +47 -0
- package/src/theme-schemes.ts +30 -2
package/dist/index.d.ts
CHANGED
|
@@ -12,6 +12,8 @@ export * from './preview-protocol.ts';
|
|
|
12
12
|
export * from './preview-session-resolve.ts';
|
|
13
13
|
export * from './preview-trusted-origins.ts';
|
|
14
14
|
export * from './storefront-initial-data-html.ts';
|
|
15
|
+
export * from './storefront-render-integrations.ts';
|
|
16
|
+
export * from './storefront-render-seo.ts';
|
|
15
17
|
export * from './storefront-typography-fonts.ts';
|
|
16
18
|
export * from './style-slots.ts';
|
|
17
19
|
export * from './theme-manifest.ts';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAClC,cAAc,sBAAsB,CAAC;AACrC,cAAc,uBAAuB,CAAC;AACtC,cAAc,yBAAyB,CAAC;AACxC,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,sBAAsB,CAAC;AACrC,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC;AAClC,cAAc,uBAAuB,CAAC;AACtC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,mCAAmC,CAAC;AAClD,cAAc,kCAAkC,CAAC;AACjD,cAAc,kBAAkB,CAAC;AACjC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,iBAAiB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAClC,cAAc,sBAAsB,CAAC;AACrC,cAAc,uBAAuB,CAAC;AACtC,cAAc,yBAAyB,CAAC;AACxC,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,sBAAsB,CAAC;AACrC,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC;AAClC,cAAc,uBAAuB,CAAC;AACtC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,mCAAmC,CAAC;AAClD,cAAc,qCAAqC,CAAC;AACpD,cAAc,4BAA4B,CAAC;AAC3C,cAAc,kCAAkC,CAAC;AACjD,cAAc,kBAAkB,CAAC;AACjC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,iBAAiB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -12,6 +12,8 @@ export * from "./preview-protocol.js";
|
|
|
12
12
|
export * from "./preview-session-resolve.js";
|
|
13
13
|
export * from "./preview-trusted-origins.js";
|
|
14
14
|
export * from "./storefront-initial-data-html.js";
|
|
15
|
+
export * from "./storefront-render-integrations.js";
|
|
16
|
+
export * from "./storefront-render-seo.js";
|
|
15
17
|
export * from "./storefront-typography-fonts.js";
|
|
16
18
|
export * from "./style-slots.js";
|
|
17
19
|
export * from "./theme-manifest.js";
|
|
@@ -66,8 +66,8 @@ export declare const PreviewApplyStateMessageSchema: z.ZodObject<{
|
|
|
66
66
|
}, z.core.$strict>;
|
|
67
67
|
}, z.core.$strict>;
|
|
68
68
|
}, z.core.$strict>;
|
|
69
|
-
export declare const
|
|
70
|
-
export type
|
|
69
|
+
export declare const ServerLiquidRenderModeSchema: z.ZodLiteral<"server-liquid">;
|
|
70
|
+
export type ServerLiquidRenderMode = z.infer<typeof ServerLiquidRenderModeSchema>;
|
|
71
71
|
export declare const PreviewBlockHtmlPatchSchema: z.ZodObject<{
|
|
72
72
|
blockId: z.ZodString;
|
|
73
73
|
html: z.ZodString;
|
|
@@ -78,12 +78,22 @@ export declare const PreviewApplyBlockHtmlMessageSchema: z.ZodObject<{
|
|
|
78
78
|
revision: z.ZodNumber;
|
|
79
79
|
pageId: z.ZodString;
|
|
80
80
|
sourceRevision: z.ZodString;
|
|
81
|
-
renderMode: z.ZodLiteral<"
|
|
81
|
+
renderMode: z.ZodLiteral<"server-liquid">;
|
|
82
82
|
blocks: z.ZodArray<z.ZodObject<{
|
|
83
83
|
blockId: z.ZodString;
|
|
84
84
|
html: z.ZodString;
|
|
85
85
|
}, z.core.$strict>>;
|
|
86
86
|
}, z.core.$strict>;
|
|
87
|
+
export type PreviewApplyBlockHtmlMessage = z.infer<typeof PreviewApplyBlockHtmlMessageSchema>;
|
|
88
|
+
export declare const PreviewApplyPageHtmlMessageSchema: z.ZodObject<{
|
|
89
|
+
type: z.ZodLiteral<"APPLY_PAGE_HTML">;
|
|
90
|
+
revision: z.ZodNumber;
|
|
91
|
+
pageId: z.ZodString;
|
|
92
|
+
sourceRevision: z.ZodString;
|
|
93
|
+
renderMode: z.ZodLiteral<"server-liquid">;
|
|
94
|
+
html: z.ZodString;
|
|
95
|
+
}, z.core.$strict>;
|
|
96
|
+
export type PreviewApplyPageHtmlMessage = z.infer<typeof PreviewApplyPageHtmlMessageSchema>;
|
|
87
97
|
export declare const PreviewReloadMessageSchema: z.ZodObject<{
|
|
88
98
|
type: z.ZodLiteral<"RELOAD">;
|
|
89
99
|
revision: z.ZodNumber;
|
|
@@ -187,11 +197,18 @@ export declare const PreviewMessageSchema: z.ZodDiscriminatedUnion<[z.ZodObject<
|
|
|
187
197
|
revision: z.ZodNumber;
|
|
188
198
|
pageId: z.ZodString;
|
|
189
199
|
sourceRevision: z.ZodString;
|
|
190
|
-
renderMode: z.ZodLiteral<"
|
|
200
|
+
renderMode: z.ZodLiteral<"server-liquid">;
|
|
191
201
|
blocks: z.ZodArray<z.ZodObject<{
|
|
192
202
|
blockId: z.ZodString;
|
|
193
203
|
html: z.ZodString;
|
|
194
204
|
}, z.core.$strict>>;
|
|
205
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
206
|
+
type: z.ZodLiteral<"APPLY_PAGE_HTML">;
|
|
207
|
+
revision: z.ZodNumber;
|
|
208
|
+
pageId: z.ZodString;
|
|
209
|
+
sourceRevision: z.ZodString;
|
|
210
|
+
renderMode: z.ZodLiteral<"server-liquid">;
|
|
211
|
+
html: z.ZodString;
|
|
195
212
|
}, z.core.$strict>, z.ZodObject<{
|
|
196
213
|
type: z.ZodLiteral<"RELOAD">;
|
|
197
214
|
revision: z.ZodNumber;
|
|
@@ -242,7 +259,7 @@ export declare const PreviewReadyHealthSchema: z.ZodDiscriminatedUnion<[z.ZodObj
|
|
|
242
259
|
builderRuntimeProvider: z.ZodLiteral<true>;
|
|
243
260
|
protocolVersion: z.ZodLiteral<2>;
|
|
244
261
|
}, z.core.$strict>, z.ZodObject<{
|
|
245
|
-
|
|
262
|
+
serverLiquidEngine: z.ZodLiteral<true>;
|
|
246
263
|
blockHtmlReconcile: z.ZodLiteral<true>;
|
|
247
264
|
protocolVersion: z.ZodLiteral<3>;
|
|
248
265
|
}, z.core.$strict>], "protocolVersion">;
|
|
@@ -255,7 +272,7 @@ export declare const PreviewReadyResponseSchema: z.ZodObject<{
|
|
|
255
272
|
builderRuntimeProvider: z.ZodLiteral<true>;
|
|
256
273
|
protocolVersion: z.ZodLiteral<2>;
|
|
257
274
|
}, z.core.$strict>, z.ZodObject<{
|
|
258
|
-
|
|
275
|
+
serverLiquidEngine: z.ZodLiteral<true>;
|
|
259
276
|
blockHtmlReconcile: z.ZodLiteral<true>;
|
|
260
277
|
protocolVersion: z.ZodLiteral<3>;
|
|
261
278
|
}, z.core.$strict>], "protocolVersion">>;
|
|
@@ -274,7 +291,7 @@ export declare const PreviewBlockHtmlAppliedResponseSchema: z.ZodObject<{
|
|
|
274
291
|
revision: z.ZodNumber;
|
|
275
292
|
pageId: z.ZodString;
|
|
276
293
|
sourceRevision: z.ZodString;
|
|
277
|
-
renderMode: z.ZodLiteral<"
|
|
294
|
+
renderMode: z.ZodLiteral<"server-liquid">;
|
|
278
295
|
blocks: z.ZodArray<z.ZodObject<{
|
|
279
296
|
blockId: z.ZodString;
|
|
280
297
|
html: z.ZodString;
|
|
@@ -285,7 +302,7 @@ export declare const PreviewBlockHtmlFailedResponseSchema: z.ZodObject<{
|
|
|
285
302
|
revision: z.ZodNumber;
|
|
286
303
|
pageId: z.ZodString;
|
|
287
304
|
sourceRevision: z.ZodOptional<z.ZodString>;
|
|
288
|
-
renderMode: z.ZodLiteral<"
|
|
305
|
+
renderMode: z.ZodLiteral<"server-liquid">;
|
|
289
306
|
blockIds: z.ZodArray<z.ZodString>;
|
|
290
307
|
error: z.ZodString;
|
|
291
308
|
}, z.core.$strict>;
|
|
@@ -418,7 +435,7 @@ export declare const PreviewResponseSchema: z.ZodDiscriminatedUnion<[z.ZodObject
|
|
|
418
435
|
builderRuntimeProvider: z.ZodLiteral<true>;
|
|
419
436
|
protocolVersion: z.ZodLiteral<2>;
|
|
420
437
|
}, z.core.$strict>, z.ZodObject<{
|
|
421
|
-
|
|
438
|
+
serverLiquidEngine: z.ZodLiteral<true>;
|
|
422
439
|
blockHtmlReconcile: z.ZodLiteral<true>;
|
|
423
440
|
protocolVersion: z.ZodLiteral<3>;
|
|
424
441
|
}, z.core.$strict>], "protocolVersion">>;
|
|
@@ -434,7 +451,7 @@ export declare const PreviewResponseSchema: z.ZodDiscriminatedUnion<[z.ZodObject
|
|
|
434
451
|
revision: z.ZodNumber;
|
|
435
452
|
pageId: z.ZodString;
|
|
436
453
|
sourceRevision: z.ZodString;
|
|
437
|
-
renderMode: z.ZodLiteral<"
|
|
454
|
+
renderMode: z.ZodLiteral<"server-liquid">;
|
|
438
455
|
blocks: z.ZodArray<z.ZodObject<{
|
|
439
456
|
blockId: z.ZodString;
|
|
440
457
|
html: z.ZodString;
|
|
@@ -444,7 +461,7 @@ export declare const PreviewResponseSchema: z.ZodDiscriminatedUnion<[z.ZodObject
|
|
|
444
461
|
revision: z.ZodNumber;
|
|
445
462
|
pageId: z.ZodString;
|
|
446
463
|
sourceRevision: z.ZodOptional<z.ZodString>;
|
|
447
|
-
renderMode: z.ZodLiteral<"
|
|
464
|
+
renderMode: z.ZodLiteral<"server-liquid">;
|
|
448
465
|
blockIds: z.ZodArray<z.ZodString>;
|
|
449
466
|
error: z.ZodString;
|
|
450
467
|
}, z.core.$strict>, z.ZodObject<{
|
|
@@ -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,
|
|
1
|
+
{"version":3,"file":"preview-protocol.d.ts","sourceRoot":"","sources":["../src/preview-protocol.ts"],"names":[],"mappings":"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"}
|
package/dist/preview-protocol.js
CHANGED
|
@@ -20,7 +20,7 @@ export const PreviewApplyStateMessageSchema = z
|
|
|
20
20
|
state: BuilderSettingsSchema,
|
|
21
21
|
})
|
|
22
22
|
.strict();
|
|
23
|
-
export const
|
|
23
|
+
export const ServerLiquidRenderModeSchema = z.literal('server-liquid');
|
|
24
24
|
export const PreviewBlockHtmlPatchSchema = z
|
|
25
25
|
.object({
|
|
26
26
|
blockId: z.string().min(1),
|
|
@@ -33,8 +33,18 @@ export const PreviewApplyBlockHtmlMessageSchema = z
|
|
|
33
33
|
revision: z.number().int().nonnegative(),
|
|
34
34
|
pageId: z.string().min(1),
|
|
35
35
|
sourceRevision: z.string().min(1),
|
|
36
|
-
renderMode:
|
|
37
|
-
blocks: z.array(PreviewBlockHtmlPatchSchema)
|
|
36
|
+
renderMode: ServerLiquidRenderModeSchema,
|
|
37
|
+
blocks: z.array(PreviewBlockHtmlPatchSchema),
|
|
38
|
+
})
|
|
39
|
+
.strict();
|
|
40
|
+
export const PreviewApplyPageHtmlMessageSchema = z
|
|
41
|
+
.object({
|
|
42
|
+
type: z.literal('APPLY_PAGE_HTML'),
|
|
43
|
+
revision: z.number().int().nonnegative(),
|
|
44
|
+
pageId: z.string().min(1),
|
|
45
|
+
sourceRevision: z.string().min(1),
|
|
46
|
+
renderMode: ServerLiquidRenderModeSchema,
|
|
47
|
+
html: z.string().min(1),
|
|
38
48
|
})
|
|
39
49
|
.strict();
|
|
40
50
|
export const PreviewReloadMessageSchema = z
|
|
@@ -72,6 +82,7 @@ export const PreviewSetInteractionModeMessageSchema = z
|
|
|
72
82
|
export const PreviewMessageSchema = z.discriminatedUnion('type', [
|
|
73
83
|
PreviewApplyStateMessageSchema,
|
|
74
84
|
PreviewApplyBlockHtmlMessageSchema,
|
|
85
|
+
PreviewApplyPageHtmlMessageSchema,
|
|
75
86
|
PreviewReloadMessageSchema,
|
|
76
87
|
PreviewSelectElementMessageSchema,
|
|
77
88
|
PreviewRequestReadyMessageSchema,
|
|
@@ -96,7 +107,7 @@ export const PreviewReadyHealthSchema = z.discriminatedUnion('protocolVersion',
|
|
|
96
107
|
.strict(),
|
|
97
108
|
z
|
|
98
109
|
.object({
|
|
99
|
-
|
|
110
|
+
serverLiquidEngine: z.literal(true),
|
|
100
111
|
blockHtmlReconcile: z.literal(true),
|
|
101
112
|
protocolVersion: z.literal(3),
|
|
102
113
|
})
|
|
@@ -128,8 +139,8 @@ export const PreviewBlockHtmlAppliedResponseSchema = z
|
|
|
128
139
|
revision: z.number().int().nonnegative(),
|
|
129
140
|
pageId: z.string().min(1),
|
|
130
141
|
sourceRevision: z.string().min(1),
|
|
131
|
-
renderMode:
|
|
132
|
-
blocks: z.array(PreviewBlockHtmlPatchSchema)
|
|
142
|
+
renderMode: ServerLiquidRenderModeSchema,
|
|
143
|
+
blocks: z.array(PreviewBlockHtmlPatchSchema),
|
|
133
144
|
})
|
|
134
145
|
.strict();
|
|
135
146
|
export const PreviewBlockHtmlFailedResponseSchema = z
|
|
@@ -138,8 +149,8 @@ export const PreviewBlockHtmlFailedResponseSchema = z
|
|
|
138
149
|
revision: z.number().int().nonnegative(),
|
|
139
150
|
pageId: z.string().min(1),
|
|
140
151
|
sourceRevision: z.string().min(1).optional(),
|
|
141
|
-
renderMode:
|
|
142
|
-
blockIds: z.array(z.string().min(1))
|
|
152
|
+
renderMode: ServerLiquidRenderModeSchema,
|
|
153
|
+
blockIds: z.array(z.string().min(1)),
|
|
143
154
|
error: z.string().min(1),
|
|
144
155
|
})
|
|
145
156
|
.strict();
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SSOT for iframe embed origins allowed in the Storefront Render Service CSP (frame-src)
|
|
3
|
+
* and for custom-embed postMessage trust in storefront-commerce (when registered).
|
|
4
|
+
*/
|
|
5
|
+
export declare const STOREFRONT_RENDER_YOUTUBE_FRAME_ORIGINS: readonly ["https://www.youtube.com", "https://www.youtube-nocookie.com"];
|
|
6
|
+
/** Trusted origins for custom-embed resize postMessage (storefront-commerce). */
|
|
7
|
+
export declare const STOREFRONT_RENDER_CUSTOM_EMBED_TRUSTED_ORIGINS: readonly ["https://calendly.com", "https://substack.com", "https://shoppex.io"];
|
|
8
|
+
/** frame-src entries for custom embed blocks (includes Substack wildcard). */
|
|
9
|
+
export declare const STOREFRONT_RENDER_CUSTOM_EMBED_FRAME_SRC_ORIGINS: readonly ["https://calendly.com", "https://substack.com", "https://shoppex.io", "https://*.substack.com"];
|
|
10
|
+
export declare const STOREFRONT_RENDER_ALLOWED_FRAME_ORIGINS: readonly ["https://www.youtube.com", "https://www.youtube-nocookie.com", "https://calendly.com", "https://substack.com", "https://shoppex.io", "https://*.substack.com"];
|
|
11
|
+
//# sourceMappingURL=storefront-render-frame-origins.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storefront-render-frame-origins.d.ts","sourceRoot":"","sources":["../src/storefront-render-frame-origins.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,eAAO,MAAM,uCAAuC,0EAG1C,CAAC;AAEX,iFAAiF;AACjF,eAAO,MAAM,8CAA8C,iFAIjD,CAAC;AAEX,8EAA8E;AAC9E,eAAO,MAAM,gDAAgD,2GAGnD,CAAC;AAEX,eAAO,MAAM,uCAAuC,0KAG1C,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SSOT for iframe embed origins allowed in the Storefront Render Service CSP (frame-src)
|
|
3
|
+
* and for custom-embed postMessage trust in storefront-commerce (when registered).
|
|
4
|
+
*/
|
|
5
|
+
export const STOREFRONT_RENDER_YOUTUBE_FRAME_ORIGINS = [
|
|
6
|
+
'https://www.youtube.com',
|
|
7
|
+
'https://www.youtube-nocookie.com',
|
|
8
|
+
];
|
|
9
|
+
/** Trusted origins for custom-embed resize postMessage (storefront-commerce). */
|
|
10
|
+
export const STOREFRONT_RENDER_CUSTOM_EMBED_TRUSTED_ORIGINS = [
|
|
11
|
+
'https://calendly.com',
|
|
12
|
+
'https://substack.com',
|
|
13
|
+
'https://shoppex.io',
|
|
14
|
+
];
|
|
15
|
+
/** frame-src entries for custom embed blocks (includes Substack wildcard). */
|
|
16
|
+
export const STOREFRONT_RENDER_CUSTOM_EMBED_FRAME_SRC_ORIGINS = [
|
|
17
|
+
...STOREFRONT_RENDER_CUSTOM_EMBED_TRUSTED_ORIGINS,
|
|
18
|
+
'https://*.substack.com',
|
|
19
|
+
];
|
|
20
|
+
export const STOREFRONT_RENDER_ALLOWED_FRAME_ORIGINS = [
|
|
21
|
+
...STOREFRONT_RENDER_YOUTUBE_FRAME_ORIGINS,
|
|
22
|
+
...STOREFRONT_RENDER_CUSTOM_EMBED_FRAME_SRC_ORIGINS,
|
|
23
|
+
];
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export declare const STOREFRONT_RENDER_INTEGRATIONS_HEADER = "X-Shoppex-Storefront-Integrations";
|
|
2
|
+
export interface StorefrontRenderIntegrationEntry {
|
|
3
|
+
provider: string;
|
|
4
|
+
enabled: boolean;
|
|
5
|
+
config: Record<string, string>;
|
|
6
|
+
}
|
|
7
|
+
export declare function normalizeStorefrontRenderIntegrations(value: unknown): StorefrontRenderIntegrationEntry[];
|
|
8
|
+
export declare function encodeStorefrontRenderIntegrationsHeader(integrations: readonly StorefrontRenderIntegrationEntry[]): string;
|
|
9
|
+
export declare function decodeStorefrontRenderIntegrationsHeader(value: string | null): StorefrontRenderIntegrationEntry[];
|
|
10
|
+
//# sourceMappingURL=storefront-render-integrations.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storefront-render-integrations.d.ts","sourceRoot":"","sources":["../src/storefront-render-integrations.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,qCAAqC,sCAAsC,CAAC;AAIzF,MAAM,WAAW,gCAAgC;IAC/C,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAChC;AAsBD,wBAAgB,qCAAqC,CACnD,KAAK,EAAE,OAAO,GACb,gCAAgC,EAAE,CA+BpC;AAED,wBAAgB,wCAAwC,CACtD,YAAY,EAAE,SAAS,gCAAgC,EAAE,GACxD,MAAM,CAER;AAED,wBAAgB,wCAAwC,CACtD,KAAK,EAAE,MAAM,GAAG,IAAI,GACnB,gCAAgC,EAAE,CAOpC"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
export const STOREFRONT_RENDER_INTEGRATIONS_HEADER = 'X-Shoppex-Storefront-Integrations';
|
|
2
|
+
const MAX_STOREFRONT_RENDER_INTEGRATIONS = 20;
|
|
3
|
+
function isRecord(value) {
|
|
4
|
+
return value !== null && typeof value === 'object' && !Array.isArray(value);
|
|
5
|
+
}
|
|
6
|
+
function readStringConfig(value) {
|
|
7
|
+
if (!isRecord(value)) {
|
|
8
|
+
return null;
|
|
9
|
+
}
|
|
10
|
+
const config = {};
|
|
11
|
+
for (const [key, rawValue] of Object.entries(value)) {
|
|
12
|
+
if (typeof key !== 'string' || typeof rawValue !== 'string') {
|
|
13
|
+
return null;
|
|
14
|
+
}
|
|
15
|
+
config[key] = rawValue;
|
|
16
|
+
}
|
|
17
|
+
return config;
|
|
18
|
+
}
|
|
19
|
+
export function normalizeStorefrontRenderIntegrations(value) {
|
|
20
|
+
if (!Array.isArray(value)) {
|
|
21
|
+
return [];
|
|
22
|
+
}
|
|
23
|
+
const integrations = [];
|
|
24
|
+
const seenProviders = new Set();
|
|
25
|
+
for (const rawEntry of value) {
|
|
26
|
+
if (integrations.length >= MAX_STOREFRONT_RENDER_INTEGRATIONS) {
|
|
27
|
+
break;
|
|
28
|
+
}
|
|
29
|
+
if (!isRecord(rawEntry)) {
|
|
30
|
+
continue;
|
|
31
|
+
}
|
|
32
|
+
const provider = rawEntry.provider;
|
|
33
|
+
const enabled = rawEntry.enabled;
|
|
34
|
+
const config = readStringConfig(rawEntry.config);
|
|
35
|
+
if (typeof provider !== 'string' || provider.length === 0 || typeof enabled !== 'boolean' || !config) {
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
if (seenProviders.has(provider)) {
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
seenProviders.add(provider);
|
|
42
|
+
integrations.push({ provider, enabled, config });
|
|
43
|
+
}
|
|
44
|
+
return integrations;
|
|
45
|
+
}
|
|
46
|
+
export function encodeStorefrontRenderIntegrationsHeader(integrations) {
|
|
47
|
+
return encodeURIComponent(JSON.stringify(normalizeStorefrontRenderIntegrations(integrations)));
|
|
48
|
+
}
|
|
49
|
+
export function decodeStorefrontRenderIntegrationsHeader(value) {
|
|
50
|
+
if (value === null) {
|
|
51
|
+
throw new Error(`${STOREFRONT_RENDER_INTEGRATIONS_HEADER} is required.`);
|
|
52
|
+
}
|
|
53
|
+
const parsed = JSON.parse(decodeURIComponent(value));
|
|
54
|
+
return normalizeStorefrontRenderIntegrations(parsed);
|
|
55
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export declare const STOREFRONT_RENDER_SEO_HEADER = "X-Shoppex-Storefront-Seo";
|
|
2
|
+
export interface StorefrontRenderSeoMetadata {
|
|
3
|
+
title: string;
|
|
4
|
+
description: string;
|
|
5
|
+
ogImage: string;
|
|
6
|
+
favicon: string;
|
|
7
|
+
}
|
|
8
|
+
export declare function normalizeStorefrontRenderSeoMetadata(value: unknown): StorefrontRenderSeoMetadata | null;
|
|
9
|
+
export declare function encodeStorefrontRenderSeoHeader(metadata: StorefrontRenderSeoMetadata): string;
|
|
10
|
+
export declare function decodeStorefrontRenderSeoHeader(value: string | null): StorefrontRenderSeoMetadata;
|
|
11
|
+
//# sourceMappingURL=storefront-render-seo.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storefront-render-seo.d.ts","sourceRoot":"","sources":["../src/storefront-render-seo.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,4BAA4B,6BAA6B,CAAC;AAEvE,MAAM,WAAW,2BAA2B;IAC1C,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;CACjB;AAMD,wBAAgB,oCAAoC,CAAC,KAAK,EAAE,OAAO,GAAG,2BAA2B,GAAG,IAAI,CAgBvG;AAED,wBAAgB,+BAA+B,CAAC,QAAQ,EAAE,2BAA2B,GAAG,MAAM,CAE7F;AAED,wBAAgB,+BAA+B,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,2BAA2B,CAWjG"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export const STOREFRONT_RENDER_SEO_HEADER = 'X-Shoppex-Storefront-Seo';
|
|
2
|
+
function isRecord(value) {
|
|
3
|
+
return value !== null && typeof value === 'object' && !Array.isArray(value);
|
|
4
|
+
}
|
|
5
|
+
export function normalizeStorefrontRenderSeoMetadata(value) {
|
|
6
|
+
if (!isRecord(value)) {
|
|
7
|
+
return null;
|
|
8
|
+
}
|
|
9
|
+
const { title, description, ogImage, favicon } = value;
|
|
10
|
+
if (typeof title !== 'string'
|
|
11
|
+
|| typeof description !== 'string'
|
|
12
|
+
|| typeof ogImage !== 'string'
|
|
13
|
+
|| typeof favicon !== 'string') {
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
16
|
+
return { title, description, ogImage, favicon };
|
|
17
|
+
}
|
|
18
|
+
export function encodeStorefrontRenderSeoHeader(metadata) {
|
|
19
|
+
return encodeURIComponent(JSON.stringify(metadata));
|
|
20
|
+
}
|
|
21
|
+
export function decodeStorefrontRenderSeoHeader(value) {
|
|
22
|
+
if (value === null) {
|
|
23
|
+
throw new Error(`${STOREFRONT_RENDER_SEO_HEADER} is required.`);
|
|
24
|
+
}
|
|
25
|
+
const metadata = normalizeStorefrontRenderSeoMetadata(JSON.parse(decodeURIComponent(value)));
|
|
26
|
+
if (!metadata) {
|
|
27
|
+
throw new Error(`${STOREFRONT_RENDER_SEO_HEADER} is invalid.`);
|
|
28
|
+
}
|
|
29
|
+
return metadata;
|
|
30
|
+
}
|
package/dist/theme-schemes.d.ts
CHANGED
|
@@ -1,10 +1,15 @@
|
|
|
1
|
-
export declare const PUBLIC_BUILDER_THEME_SCHEMES: readonly ["default", "classic", "nebula", "pulse", "phantom", "starlight", "apex", "vault", "
|
|
2
|
-
export declare const STARTER_BUILDER_THEME_SCHEMES: readonly ["blank"];
|
|
3
|
-
export declare const BUILDER_READY_THEME_SCHEMES: readonly ["blank", "default", "classic", "nebula", "pulse", "phantom", "starlight", "apex", "vault", "vortex", "clean-minimal"];
|
|
1
|
+
export declare const PUBLIC_BUILDER_THEME_SCHEMES: readonly ["default", "classic", "nebula", "pulse", "phantom", "starlight", "apex", "vault", "clean-minimal"];
|
|
4
2
|
export type PublicBuilderThemeScheme = (typeof PUBLIC_BUILDER_THEME_SCHEMES)[number];
|
|
3
|
+
export declare const STARTER_BUILDER_THEME_SCHEMES: readonly ["blank"];
|
|
4
|
+
export declare const THEME_STORE_DISABLED_SCHEMES: readonly ["classic", "vault", "nebula", "pulse", "phantom", "apex", "clean-minimal"];
|
|
5
|
+
export declare const THEME_STORE_INSTALLABLE_SCHEMES: readonly ["default", "starlight"];
|
|
6
|
+
export declare const BUILDER_READY_THEME_SCHEMES: readonly ["blank", "default", "classic", "nebula", "pulse", "phantom", "starlight", "apex", "vault", "clean-minimal"];
|
|
7
|
+
export type ThemeStoreInstallableScheme = (typeof THEME_STORE_INSTALLABLE_SCHEMES)[number];
|
|
5
8
|
export type StarterBuilderThemeScheme = (typeof STARTER_BUILDER_THEME_SCHEMES)[number];
|
|
6
9
|
export type BuilderReadyThemeScheme = (typeof BUILDER_READY_THEME_SCHEMES)[number];
|
|
7
10
|
export declare function isPublicBuilderThemeScheme(value: string): value is PublicBuilderThemeScheme;
|
|
11
|
+
export declare function isThemeStoreDisabledScheme(value: string): boolean;
|
|
12
|
+
export declare function isThemeStoreInstallableScheme(value: string): value is ThemeStoreInstallableScheme;
|
|
8
13
|
export declare function isStarterBuilderThemeScheme(value: string): value is StarterBuilderThemeScheme;
|
|
9
14
|
export declare function isBuilderReadyThemeScheme(value: string): value is BuilderReadyThemeScheme;
|
|
10
15
|
//# sourceMappingURL=theme-schemes.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"theme-schemes.d.ts","sourceRoot":"","sources":["../src/theme-schemes.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,4BAA4B,
|
|
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,sFAQe,CAAC;AAIzD,eAAO,MAAM,+BAA+B,mCAGY,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"}
|
package/dist/theme-schemes.js
CHANGED
|
@@ -7,10 +7,23 @@ export const PUBLIC_BUILDER_THEME_SCHEMES = [
|
|
|
7
7
|
'starlight',
|
|
8
8
|
'apex',
|
|
9
9
|
'vault',
|
|
10
|
-
'vortex',
|
|
11
10
|
'clean-minimal',
|
|
12
11
|
];
|
|
13
12
|
export const STARTER_BUILDER_THEME_SCHEMES = ['blank'];
|
|
13
|
+
export const THEME_STORE_DISABLED_SCHEMES = [
|
|
14
|
+
'classic',
|
|
15
|
+
'vault',
|
|
16
|
+
'nebula',
|
|
17
|
+
'pulse',
|
|
18
|
+
'phantom',
|
|
19
|
+
'apex',
|
|
20
|
+
'clean-minimal',
|
|
21
|
+
];
|
|
22
|
+
const THEME_STORE_DISABLED_SCHEME_SET = new Set(THEME_STORE_DISABLED_SCHEMES);
|
|
23
|
+
export const THEME_STORE_INSTALLABLE_SCHEMES = [
|
|
24
|
+
'default',
|
|
25
|
+
'starlight',
|
|
26
|
+
];
|
|
14
27
|
export const BUILDER_READY_THEME_SCHEMES = [
|
|
15
28
|
...STARTER_BUILDER_THEME_SCHEMES,
|
|
16
29
|
...PUBLIC_BUILDER_THEME_SCHEMES,
|
|
@@ -18,6 +31,12 @@ export const BUILDER_READY_THEME_SCHEMES = [
|
|
|
18
31
|
export function isPublicBuilderThemeScheme(value) {
|
|
19
32
|
return PUBLIC_BUILDER_THEME_SCHEMES.includes(value);
|
|
20
33
|
}
|
|
34
|
+
export function isThemeStoreDisabledScheme(value) {
|
|
35
|
+
return THEME_STORE_DISABLED_SCHEME_SET.has(value);
|
|
36
|
+
}
|
|
37
|
+
export function isThemeStoreInstallableScheme(value) {
|
|
38
|
+
return THEME_STORE_INSTALLABLE_SCHEMES.includes(value);
|
|
39
|
+
}
|
|
21
40
|
export function isStarterBuilderThemeScheme(value) {
|
|
22
41
|
return STARTER_BUILDER_THEME_SCHEMES.includes(value);
|
|
23
42
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@shoppexio/builder-contracts",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.6",
|
|
4
4
|
"description": "Shared Builder v2 contracts for Shoppex dashboard, backend, preview runtime, and themes",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|
|
@@ -37,6 +37,24 @@
|
|
|
37
37
|
"import": "./dist/builder-settings.js",
|
|
38
38
|
"default": "./dist/builder-settings.js"
|
|
39
39
|
},
|
|
40
|
+
"./storefront-render-frame-origins": {
|
|
41
|
+
"bun": "./src/storefront-render-frame-origins.ts",
|
|
42
|
+
"types": "./dist/storefront-render-frame-origins.d.ts",
|
|
43
|
+
"import": "./dist/storefront-render-frame-origins.js",
|
|
44
|
+
"default": "./dist/storefront-render-frame-origins.js"
|
|
45
|
+
},
|
|
46
|
+
"./storefront-render-integrations": {
|
|
47
|
+
"bun": "./src/storefront-render-integrations.ts",
|
|
48
|
+
"types": "./dist/storefront-render-integrations.d.ts",
|
|
49
|
+
"import": "./dist/storefront-render-integrations.js",
|
|
50
|
+
"default": "./dist/storefront-render-integrations.js"
|
|
51
|
+
},
|
|
52
|
+
"./storefront-render-seo": {
|
|
53
|
+
"bun": "./src/storefront-render-seo.ts",
|
|
54
|
+
"types": "./dist/storefront-render-seo.d.ts",
|
|
55
|
+
"import": "./dist/storefront-render-seo.js",
|
|
56
|
+
"default": "./dist/storefront-render-seo.js"
|
|
57
|
+
},
|
|
40
58
|
"./events": {
|
|
41
59
|
"bun": "./src/events.ts",
|
|
42
60
|
"types": "./dist/events.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']) {
|
|
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);
|
package/src/index.ts
CHANGED
|
@@ -12,6 +12,8 @@ export * from './preview-protocol.ts';
|
|
|
12
12
|
export * from './preview-session-resolve.ts';
|
|
13
13
|
export * from './preview-trusted-origins.ts';
|
|
14
14
|
export * from './storefront-initial-data-html.ts';
|
|
15
|
+
export * from './storefront-render-integrations.ts';
|
|
16
|
+
export * from './storefront-render-seo.ts';
|
|
15
17
|
export * from './storefront-typography-fonts.ts';
|
|
16
18
|
export * from './style-slots.ts';
|
|
17
19
|
export * from './theme-manifest.ts';
|
|
@@ -11,7 +11,7 @@ describe('PreviewMessageSchema', () => {
|
|
|
11
11
|
revision: 12,
|
|
12
12
|
pageId: 'product',
|
|
13
13
|
sourceRevision: 'theme-source-12',
|
|
14
|
-
renderMode: '
|
|
14
|
+
renderMode: 'server-liquid',
|
|
15
15
|
blocks: [
|
|
16
16
|
{
|
|
17
17
|
blockId: 'product-form-1',
|
|
@@ -26,12 +26,28 @@ describe('PreviewMessageSchema', () => {
|
|
|
26
26
|
}
|
|
27
27
|
});
|
|
28
28
|
|
|
29
|
+
it('accepts v3 block HTML apply messages with no blocks', () => {
|
|
30
|
+
const parsed = PreviewMessageSchema.parse({
|
|
31
|
+
type: 'APPLY_BLOCK_HTML',
|
|
32
|
+
revision: 12,
|
|
33
|
+
pageId: 'empty',
|
|
34
|
+
sourceRevision: 'theme-source-12',
|
|
35
|
+
renderMode: 'server-liquid',
|
|
36
|
+
blocks: [],
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
expect(parsed.type).toBe('APPLY_BLOCK_HTML');
|
|
40
|
+
if (parsed.type === 'APPLY_BLOCK_HTML') {
|
|
41
|
+
expect(parsed.blocks).toEqual([]);
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
|
|
29
45
|
it('rejects v3 block HTML apply messages without sourceRevision', () => {
|
|
30
46
|
const result = PreviewMessageSchema.safeParse({
|
|
31
47
|
type: 'APPLY_BLOCK_HTML',
|
|
32
48
|
revision: 12,
|
|
33
49
|
pageId: 'product',
|
|
34
|
-
renderMode: '
|
|
50
|
+
renderMode: 'server-liquid',
|
|
35
51
|
blocks: [
|
|
36
52
|
{
|
|
37
53
|
blockId: 'product-form-1',
|
|
@@ -43,6 +59,22 @@ describe('PreviewMessageSchema', () => {
|
|
|
43
59
|
expect(result.success).toBe(false);
|
|
44
60
|
});
|
|
45
61
|
|
|
62
|
+
it('accepts v3 full page HTML apply messages', () => {
|
|
63
|
+
const parsed = PreviewMessageSchema.parse({
|
|
64
|
+
type: 'APPLY_PAGE_HTML',
|
|
65
|
+
revision: 13,
|
|
66
|
+
pageId: 'product',
|
|
67
|
+
sourceRevision: 'theme-source-13',
|
|
68
|
+
renderMode: 'server-liquid',
|
|
69
|
+
html: '<!doctype html><html><body><main data-page-id="product"></main></body></html>',
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
expect(parsed.type).toBe('APPLY_PAGE_HTML');
|
|
73
|
+
if (parsed.type === 'APPLY_PAGE_HTML') {
|
|
74
|
+
expect(parsed.html).toContain('data-page-id="product"');
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
|
|
46
78
|
it('accepts SET_INTERACTION_MODE with edit/preview', () => {
|
|
47
79
|
for (const mode of ['edit', 'preview'] as const) {
|
|
48
80
|
const parsed = PreviewMessageSchema.parse({
|
|
@@ -63,12 +95,12 @@ describe('PreviewMessageSchema', () => {
|
|
|
63
95
|
});
|
|
64
96
|
|
|
65
97
|
describe('PreviewResponseSchema', () => {
|
|
66
|
-
it('accepts READY health for
|
|
98
|
+
it('accepts READY health for server-liquid protocol v3', () => {
|
|
67
99
|
const parsed = PreviewResponseSchema.parse({
|
|
68
100
|
type: 'READY',
|
|
69
101
|
revision: 12,
|
|
70
102
|
health: {
|
|
71
|
-
|
|
103
|
+
serverLiquidEngine: true,
|
|
72
104
|
blockHtmlReconcile: true,
|
|
73
105
|
protocolVersion: 3,
|
|
74
106
|
},
|
|
@@ -86,7 +118,7 @@ describe('PreviewResponseSchema', () => {
|
|
|
86
118
|
revision: 12,
|
|
87
119
|
pageId: 'product',
|
|
88
120
|
sourceRevision: 'theme-source-12',
|
|
89
|
-
renderMode: '
|
|
121
|
+
renderMode: 'server-liquid',
|
|
90
122
|
blocks: [
|
|
91
123
|
{
|
|
92
124
|
blockId: 'footer-1',
|
|
@@ -97,7 +129,23 @@ describe('PreviewResponseSchema', () => {
|
|
|
97
129
|
|
|
98
130
|
expect(parsed.type).toBe('BLOCK_HTML_APPLIED');
|
|
99
131
|
if (parsed.type === 'BLOCK_HTML_APPLIED') {
|
|
100
|
-
expect(parsed.renderMode).toBe('
|
|
132
|
+
expect(parsed.renderMode).toBe('server-liquid');
|
|
133
|
+
}
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
it('accepts v3 block HTML applied responses with no blocks', () => {
|
|
137
|
+
const parsed = PreviewResponseSchema.parse({
|
|
138
|
+
type: 'BLOCK_HTML_APPLIED',
|
|
139
|
+
revision: 12,
|
|
140
|
+
pageId: 'empty',
|
|
141
|
+
sourceRevision: 'theme-source-12',
|
|
142
|
+
renderMode: 'server-liquid',
|
|
143
|
+
blocks: [],
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
expect(parsed.type).toBe('BLOCK_HTML_APPLIED');
|
|
147
|
+
if (parsed.type === 'BLOCK_HTML_APPLIED') {
|
|
148
|
+
expect(parsed.blocks).toEqual([]);
|
|
101
149
|
}
|
|
102
150
|
});
|
|
103
151
|
|
|
@@ -107,7 +155,7 @@ describe('PreviewResponseSchema', () => {
|
|
|
107
155
|
revision: 12,
|
|
108
156
|
pageId: 'product',
|
|
109
157
|
sourceRevision: 'theme-source-12',
|
|
110
|
-
renderMode: '
|
|
158
|
+
renderMode: 'server-liquid',
|
|
111
159
|
blockIds: ['footer-1'],
|
|
112
160
|
error: 'Rendered block root does not match block id.',
|
|
113
161
|
});
|
package/src/preview-protocol.ts
CHANGED
|
@@ -24,8 +24,8 @@ export const PreviewApplyStateMessageSchema = z
|
|
|
24
24
|
})
|
|
25
25
|
.strict();
|
|
26
26
|
|
|
27
|
-
export const
|
|
28
|
-
export type
|
|
27
|
+
export const ServerLiquidRenderModeSchema = z.literal('server-liquid');
|
|
28
|
+
export type ServerLiquidRenderMode = z.infer<typeof ServerLiquidRenderModeSchema>;
|
|
29
29
|
|
|
30
30
|
export const PreviewBlockHtmlPatchSchema = z
|
|
31
31
|
.object({
|
|
@@ -41,10 +41,23 @@ export const PreviewApplyBlockHtmlMessageSchema = z
|
|
|
41
41
|
revision: z.number().int().nonnegative(),
|
|
42
42
|
pageId: z.string().min(1),
|
|
43
43
|
sourceRevision: z.string().min(1),
|
|
44
|
-
renderMode:
|
|
45
|
-
blocks: z.array(PreviewBlockHtmlPatchSchema)
|
|
44
|
+
renderMode: ServerLiquidRenderModeSchema,
|
|
45
|
+
blocks: z.array(PreviewBlockHtmlPatchSchema),
|
|
46
46
|
})
|
|
47
47
|
.strict();
|
|
48
|
+
export type PreviewApplyBlockHtmlMessage = z.infer<typeof PreviewApplyBlockHtmlMessageSchema>;
|
|
49
|
+
|
|
50
|
+
export const PreviewApplyPageHtmlMessageSchema = z
|
|
51
|
+
.object({
|
|
52
|
+
type: z.literal('APPLY_PAGE_HTML'),
|
|
53
|
+
revision: z.number().int().nonnegative(),
|
|
54
|
+
pageId: z.string().min(1),
|
|
55
|
+
sourceRevision: z.string().min(1),
|
|
56
|
+
renderMode: ServerLiquidRenderModeSchema,
|
|
57
|
+
html: z.string().min(1),
|
|
58
|
+
})
|
|
59
|
+
.strict();
|
|
60
|
+
export type PreviewApplyPageHtmlMessage = z.infer<typeof PreviewApplyPageHtmlMessageSchema>;
|
|
48
61
|
|
|
49
62
|
export const PreviewReloadMessageSchema = z
|
|
50
63
|
.object({
|
|
@@ -87,6 +100,7 @@ export const PreviewSetInteractionModeMessageSchema = z
|
|
|
87
100
|
export const PreviewMessageSchema = z.discriminatedUnion('type', [
|
|
88
101
|
PreviewApplyStateMessageSchema,
|
|
89
102
|
PreviewApplyBlockHtmlMessageSchema,
|
|
103
|
+
PreviewApplyPageHtmlMessageSchema,
|
|
90
104
|
PreviewReloadMessageSchema,
|
|
91
105
|
PreviewSelectElementMessageSchema,
|
|
92
106
|
PreviewRequestReadyMessageSchema,
|
|
@@ -114,7 +128,7 @@ export const PreviewReadyHealthSchema = z.discriminatedUnion('protocolVersion',
|
|
|
114
128
|
.strict(),
|
|
115
129
|
z
|
|
116
130
|
.object({
|
|
117
|
-
|
|
131
|
+
serverLiquidEngine: z.literal(true),
|
|
118
132
|
blockHtmlReconcile: z.literal(true),
|
|
119
133
|
protocolVersion: z.literal(3),
|
|
120
134
|
})
|
|
@@ -151,8 +165,8 @@ export const PreviewBlockHtmlAppliedResponseSchema = z
|
|
|
151
165
|
revision: z.number().int().nonnegative(),
|
|
152
166
|
pageId: z.string().min(1),
|
|
153
167
|
sourceRevision: z.string().min(1),
|
|
154
|
-
renderMode:
|
|
155
|
-
blocks: z.array(PreviewBlockHtmlPatchSchema)
|
|
168
|
+
renderMode: ServerLiquidRenderModeSchema,
|
|
169
|
+
blocks: z.array(PreviewBlockHtmlPatchSchema),
|
|
156
170
|
})
|
|
157
171
|
.strict();
|
|
158
172
|
|
|
@@ -162,8 +176,8 @@ export const PreviewBlockHtmlFailedResponseSchema = z
|
|
|
162
176
|
revision: z.number().int().nonnegative(),
|
|
163
177
|
pageId: z.string().min(1),
|
|
164
178
|
sourceRevision: z.string().min(1).optional(),
|
|
165
|
-
renderMode:
|
|
166
|
-
blockIds: z.array(z.string().min(1))
|
|
179
|
+
renderMode: ServerLiquidRenderModeSchema,
|
|
180
|
+
blockIds: z.array(z.string().min(1)),
|
|
167
181
|
error: z.string().min(1),
|
|
168
182
|
})
|
|
169
183
|
.strict();
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SSOT for iframe embed origins allowed in the Storefront Render Service CSP (frame-src)
|
|
3
|
+
* and for custom-embed postMessage trust in storefront-commerce (when registered).
|
|
4
|
+
*/
|
|
5
|
+
export const STOREFRONT_RENDER_YOUTUBE_FRAME_ORIGINS = [
|
|
6
|
+
'https://www.youtube.com',
|
|
7
|
+
'https://www.youtube-nocookie.com',
|
|
8
|
+
] as const;
|
|
9
|
+
|
|
10
|
+
/** Trusted origins for custom-embed resize postMessage (storefront-commerce). */
|
|
11
|
+
export const STOREFRONT_RENDER_CUSTOM_EMBED_TRUSTED_ORIGINS = [
|
|
12
|
+
'https://calendly.com',
|
|
13
|
+
'https://substack.com',
|
|
14
|
+
'https://shoppex.io',
|
|
15
|
+
] as const;
|
|
16
|
+
|
|
17
|
+
/** frame-src entries for custom embed blocks (includes Substack wildcard). */
|
|
18
|
+
export const STOREFRONT_RENDER_CUSTOM_EMBED_FRAME_SRC_ORIGINS = [
|
|
19
|
+
...STOREFRONT_RENDER_CUSTOM_EMBED_TRUSTED_ORIGINS,
|
|
20
|
+
'https://*.substack.com',
|
|
21
|
+
] as const;
|
|
22
|
+
|
|
23
|
+
export const STOREFRONT_RENDER_ALLOWED_FRAME_ORIGINS = [
|
|
24
|
+
...STOREFRONT_RENDER_YOUTUBE_FRAME_ORIGINS,
|
|
25
|
+
...STOREFRONT_RENDER_CUSTOM_EMBED_FRAME_SRC_ORIGINS,
|
|
26
|
+
] as const;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { describe, expect, test } from 'bun:test';
|
|
2
|
+
import {
|
|
3
|
+
decodeStorefrontRenderIntegrationsHeader,
|
|
4
|
+
encodeStorefrontRenderIntegrationsHeader,
|
|
5
|
+
normalizeStorefrontRenderIntegrations,
|
|
6
|
+
STOREFRONT_RENDER_INTEGRATIONS_HEADER,
|
|
7
|
+
} from './storefront-render-integrations.ts';
|
|
8
|
+
|
|
9
|
+
describe('storefront render integrations contract', () => {
|
|
10
|
+
test('round-trips integration metadata through an ASCII header value', () => {
|
|
11
|
+
const encoded = encodeStorefrontRenderIntegrationsHeader([
|
|
12
|
+
{
|
|
13
|
+
provider: 'google_tag_manager',
|
|
14
|
+
enabled: true,
|
|
15
|
+
config: { container_id: 'GTM-ABC123' },
|
|
16
|
+
},
|
|
17
|
+
]);
|
|
18
|
+
|
|
19
|
+
expect(encoded).toBe(
|
|
20
|
+
'%5B%7B%22provider%22%3A%22google_tag_manager%22%2C%22enabled%22%3Atrue%2C%22config%22%3A%7B%22container_id%22%3A%22GTM-ABC123%22%7D%7D%5D',
|
|
21
|
+
);
|
|
22
|
+
expect(decodeStorefrontRenderIntegrationsHeader(encoded)).toEqual([
|
|
23
|
+
{
|
|
24
|
+
provider: 'google_tag_manager',
|
|
25
|
+
enabled: true,
|
|
26
|
+
config: { container_id: 'GTM-ABC123' },
|
|
27
|
+
},
|
|
28
|
+
]);
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
test('normalizes malformed entries without throwing', () => {
|
|
32
|
+
expect(normalizeStorefrontRenderIntegrations([
|
|
33
|
+
{
|
|
34
|
+
provider: 'crisp',
|
|
35
|
+
enabled: true,
|
|
36
|
+
config: { website_id: 'crisp_123' },
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
provider: 'crisp',
|
|
40
|
+
enabled: true,
|
|
41
|
+
config: { website_id: 'duplicate' },
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
provider: 'broken',
|
|
45
|
+
enabled: true,
|
|
46
|
+
config: { id: 123 },
|
|
47
|
+
},
|
|
48
|
+
])).toEqual([
|
|
49
|
+
{
|
|
50
|
+
provider: 'crisp',
|
|
51
|
+
enabled: true,
|
|
52
|
+
config: { website_id: 'crisp_123' },
|
|
53
|
+
},
|
|
54
|
+
]);
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
test('fails when the required render header is missing', () => {
|
|
58
|
+
expect(() => decodeStorefrontRenderIntegrationsHeader(null)).toThrow(
|
|
59
|
+
`${STOREFRONT_RENDER_INTEGRATIONS_HEADER} is required.`,
|
|
60
|
+
);
|
|
61
|
+
});
|
|
62
|
+
});
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
export const STOREFRONT_RENDER_INTEGRATIONS_HEADER = 'X-Shoppex-Storefront-Integrations';
|
|
2
|
+
|
|
3
|
+
const MAX_STOREFRONT_RENDER_INTEGRATIONS = 20;
|
|
4
|
+
|
|
5
|
+
export interface StorefrontRenderIntegrationEntry {
|
|
6
|
+
provider: string;
|
|
7
|
+
enabled: boolean;
|
|
8
|
+
config: Record<string, string>;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
12
|
+
return value !== null && typeof value === 'object' && !Array.isArray(value);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function readStringConfig(value: unknown): Record<string, string> | null {
|
|
16
|
+
if (!isRecord(value)) {
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const config: Record<string, string> = {};
|
|
21
|
+
for (const [key, rawValue] of Object.entries(value)) {
|
|
22
|
+
if (typeof key !== 'string' || typeof rawValue !== 'string') {
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
config[key] = rawValue;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return config;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function normalizeStorefrontRenderIntegrations(
|
|
32
|
+
value: unknown,
|
|
33
|
+
): StorefrontRenderIntegrationEntry[] {
|
|
34
|
+
if (!Array.isArray(value)) {
|
|
35
|
+
return [];
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const integrations: StorefrontRenderIntegrationEntry[] = [];
|
|
39
|
+
const seenProviders = new Set<string>();
|
|
40
|
+
|
|
41
|
+
for (const rawEntry of value) {
|
|
42
|
+
if (integrations.length >= MAX_STOREFRONT_RENDER_INTEGRATIONS) {
|
|
43
|
+
break;
|
|
44
|
+
}
|
|
45
|
+
if (!isRecord(rawEntry)) {
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const provider = rawEntry.provider;
|
|
50
|
+
const enabled = rawEntry.enabled;
|
|
51
|
+
const config = readStringConfig(rawEntry.config);
|
|
52
|
+
if (typeof provider !== 'string' || provider.length === 0 || typeof enabled !== 'boolean' || !config) {
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
if (seenProviders.has(provider)) {
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
seenProviders.add(provider);
|
|
60
|
+
integrations.push({ provider, enabled, config });
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return integrations;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export function encodeStorefrontRenderIntegrationsHeader(
|
|
67
|
+
integrations: readonly StorefrontRenderIntegrationEntry[],
|
|
68
|
+
): string {
|
|
69
|
+
return encodeURIComponent(JSON.stringify(normalizeStorefrontRenderIntegrations(integrations)));
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export function decodeStorefrontRenderIntegrationsHeader(
|
|
73
|
+
value: string | null,
|
|
74
|
+
): StorefrontRenderIntegrationEntry[] {
|
|
75
|
+
if (value === null) {
|
|
76
|
+
throw new Error(`${STOREFRONT_RENDER_INTEGRATIONS_HEADER} is required.`);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const parsed = JSON.parse(decodeURIComponent(value)) as unknown;
|
|
80
|
+
return normalizeStorefrontRenderIntegrations(parsed);
|
|
81
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { describe, expect, test } from 'bun:test';
|
|
2
|
+
import {
|
|
3
|
+
decodeStorefrontRenderSeoHeader,
|
|
4
|
+
encodeStorefrontRenderSeoHeader,
|
|
5
|
+
STOREFRONT_RENDER_SEO_HEADER,
|
|
6
|
+
} from './storefront-render-seo.ts';
|
|
7
|
+
|
|
8
|
+
describe('storefront render SEO contract', () => {
|
|
9
|
+
test('round-trips SEO metadata through an ASCII header value', () => {
|
|
10
|
+
const encoded = encodeStorefrontRenderSeoHeader({
|
|
11
|
+
title: 'Demo Shop',
|
|
12
|
+
description: 'Premium digital products',
|
|
13
|
+
ogImage: 'https://cdn.example.com/og.png',
|
|
14
|
+
favicon: 'https://cdn.example.com/favicon.png',
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
expect(decodeStorefrontRenderSeoHeader(encoded)).toEqual({
|
|
18
|
+
title: 'Demo Shop',
|
|
19
|
+
description: 'Premium digital products',
|
|
20
|
+
ogImage: 'https://cdn.example.com/og.png',
|
|
21
|
+
favicon: 'https://cdn.example.com/favicon.png',
|
|
22
|
+
});
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
test('fails when the required SEO header is missing or malformed', () => {
|
|
26
|
+
expect(() => decodeStorefrontRenderSeoHeader(null)).toThrow(
|
|
27
|
+
`${STOREFRONT_RENDER_SEO_HEADER} is required.`,
|
|
28
|
+
);
|
|
29
|
+
expect(() => decodeStorefrontRenderSeoHeader(encodeURIComponent('{"title":"Missing fields"}'))).toThrow(
|
|
30
|
+
`${STOREFRONT_RENDER_SEO_HEADER} is invalid.`,
|
|
31
|
+
);
|
|
32
|
+
});
|
|
33
|
+
});
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
export const STOREFRONT_RENDER_SEO_HEADER = 'X-Shoppex-Storefront-Seo';
|
|
2
|
+
|
|
3
|
+
export interface StorefrontRenderSeoMetadata {
|
|
4
|
+
title: string;
|
|
5
|
+
description: string;
|
|
6
|
+
ogImage: string;
|
|
7
|
+
favicon: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
11
|
+
return value !== null && typeof value === 'object' && !Array.isArray(value);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function normalizeStorefrontRenderSeoMetadata(value: unknown): StorefrontRenderSeoMetadata | null {
|
|
15
|
+
if (!isRecord(value)) {
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const { title, description, ogImage, favicon } = value;
|
|
20
|
+
if (
|
|
21
|
+
typeof title !== 'string'
|
|
22
|
+
|| typeof description !== 'string'
|
|
23
|
+
|| typeof ogImage !== 'string'
|
|
24
|
+
|| typeof favicon !== 'string'
|
|
25
|
+
) {
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return { title, description, ogImage, favicon };
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function encodeStorefrontRenderSeoHeader(metadata: StorefrontRenderSeoMetadata): string {
|
|
33
|
+
return encodeURIComponent(JSON.stringify(metadata));
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function decodeStorefrontRenderSeoHeader(value: string | null): StorefrontRenderSeoMetadata {
|
|
37
|
+
if (value === null) {
|
|
38
|
+
throw new Error(`${STOREFRONT_RENDER_SEO_HEADER} is required.`);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const metadata = normalizeStorefrontRenderSeoMetadata(JSON.parse(decodeURIComponent(value)) as unknown);
|
|
42
|
+
if (!metadata) {
|
|
43
|
+
throw new Error(`${STOREFRONT_RENDER_SEO_HEADER} is invalid.`);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return metadata;
|
|
47
|
+
}
|
package/src/theme-schemes.ts
CHANGED
|
@@ -7,18 +7,36 @@ export const PUBLIC_BUILDER_THEME_SCHEMES = [
|
|
|
7
7
|
'starlight',
|
|
8
8
|
'apex',
|
|
9
9
|
'vault',
|
|
10
|
-
'vortex',
|
|
11
10
|
'clean-minimal',
|
|
12
11
|
] as const;
|
|
13
12
|
|
|
13
|
+
export type PublicBuilderThemeScheme = (typeof PUBLIC_BUILDER_THEME_SCHEMES)[number];
|
|
14
|
+
|
|
14
15
|
export const STARTER_BUILDER_THEME_SCHEMES = ['blank'] as const;
|
|
15
16
|
|
|
17
|
+
export const THEME_STORE_DISABLED_SCHEMES = [
|
|
18
|
+
'classic',
|
|
19
|
+
'vault',
|
|
20
|
+
'nebula',
|
|
21
|
+
'pulse',
|
|
22
|
+
'phantom',
|
|
23
|
+
'apex',
|
|
24
|
+
'clean-minimal',
|
|
25
|
+
] as const satisfies readonly PublicBuilderThemeScheme[];
|
|
26
|
+
|
|
27
|
+
const THEME_STORE_DISABLED_SCHEME_SET = new Set<string>(THEME_STORE_DISABLED_SCHEMES);
|
|
28
|
+
|
|
29
|
+
export const THEME_STORE_INSTALLABLE_SCHEMES = [
|
|
30
|
+
'default',
|
|
31
|
+
'starlight',
|
|
32
|
+
] as const satisfies readonly PublicBuilderThemeScheme[];
|
|
33
|
+
|
|
16
34
|
export const BUILDER_READY_THEME_SCHEMES = [
|
|
17
35
|
...STARTER_BUILDER_THEME_SCHEMES,
|
|
18
36
|
...PUBLIC_BUILDER_THEME_SCHEMES,
|
|
19
37
|
] as const;
|
|
20
38
|
|
|
21
|
-
export type
|
|
39
|
+
export type ThemeStoreInstallableScheme = (typeof THEME_STORE_INSTALLABLE_SCHEMES)[number];
|
|
22
40
|
export type StarterBuilderThemeScheme = (typeof STARTER_BUILDER_THEME_SCHEMES)[number];
|
|
23
41
|
export type BuilderReadyThemeScheme = (typeof BUILDER_READY_THEME_SCHEMES)[number];
|
|
24
42
|
|
|
@@ -26,6 +44,16 @@ export function isPublicBuilderThemeScheme(value: string): value is PublicBuilde
|
|
|
26
44
|
return (PUBLIC_BUILDER_THEME_SCHEMES as readonly string[]).includes(value);
|
|
27
45
|
}
|
|
28
46
|
|
|
47
|
+
export function isThemeStoreDisabledScheme(value: string): boolean {
|
|
48
|
+
return THEME_STORE_DISABLED_SCHEME_SET.has(value);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function isThemeStoreInstallableScheme(
|
|
52
|
+
value: string,
|
|
53
|
+
): value is ThemeStoreInstallableScheme {
|
|
54
|
+
return (THEME_STORE_INSTALLABLE_SCHEMES as readonly string[]).includes(value);
|
|
55
|
+
}
|
|
56
|
+
|
|
29
57
|
export function isStarterBuilderThemeScheme(value: string): value is StarterBuilderThemeScheme {
|
|
30
58
|
return (STARTER_BUILDER_THEME_SCHEMES as readonly string[]).includes(value);
|
|
31
59
|
}
|