@sovecom/theme-sdk 1.0.0-rc.1

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/widget.js ADDED
@@ -0,0 +1,232 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.widgetDescriptorSchema = exports.submitFormPropsSchema = exports.toggleButtonPropsSchema = exports.productCarouselPropsSchema = exports.reviewListPropsSchema = exports.starRatingSummaryPropsSchema = exports.actionSchema = exports.actionPathSchema = exports.WIDGET_MAX_BYTES = exports.WIDGET_TYPES = void 0;
4
+ exports.parseWidget = parseWidget;
5
+ /**
6
+ * the module slot-widget CONTRACT + vocabulary.
7
+ *
8
+ * A sandboxed module contributes storefront UI by returning a typed **widget descriptor**
9
+ * `{ type, props }` — a widget `type` from a CLOSED, core-owned MIT vocabulary plus validated props.
10
+ * The storefront renders its OWN known MIT components with that data; NO code, NO HTML, NO SVG
11
+ * crosses the boundary — only DATA.
12
+ *
13
+ * Like `manifest.ts` / `template.ts`, this file is a declarative ASSET contract: PURE validators +
14
+ * types only. There is NO React, NO fetch, NO Node runtime API, NO render here. `parseWidget` mirrors
15
+ * `parseTemplate`'s byte-cap + JSON.parse + Zod pipeline, with ONE deliberate difference: it returns
16
+ * `null` on ANY failure (never throws) — the defensive fail-closed contract the storefront RSC relies
17
+ * on to "render nothing, never 500 the page".
18
+ *
19
+ * The byte cap is its own constant ({@link WIDGET_MAX_BYTES}) but reuses the manifest cap value so a
20
+ * widget descriptor is gated by the same finite bound — one numeric home, no divergence.
21
+ */
22
+ const zod_1 = require("zod");
23
+ const manifest_js_1 = require("./manifest.js");
24
+ /**
25
+ * The CLOSED, core-owned widget vocabulary. A module author CANNOT register a new type;
26
+ * adding one is an MIT storefront contribution reviewed like adding a section. The
27
+ * `component` slug in a module manifest's `slots[]` IS one of these `type`s. The literal-tuple
28
+ * `as const` lets the discriminated union below mirror it exactly.
29
+ */
30
+ exports.WIDGET_TYPES = [
31
+ 'star-rating-summary',
32
+ 'review-list',
33
+ 'product-carousel',
34
+ 'toggle-button',
35
+ 'submit-form',
36
+ ];
37
+ /**
38
+ * Byte cap for a raw widget descriptor. Reuses the manifest cap VALUE (one source of truth) — a
39
+ * descriptor is small data, so this generous bound only rejects pathological payloads up front, before
40
+ * any JSON.parse or schema work.
41
+ */
42
+ exports.WIDGET_MAX_BYTES = manifest_js_1.MANIFEST_MAX_BYTES;
43
+ // ── shared field bounds (every string capped, every array `.max`, every number ranged) ───
44
+ const MAX_ID_LEN = 64;
45
+ const MAX_REVIEW_BODY_LEN = 2000;
46
+ const MAX_AUTHOR_LEN = 120;
47
+ const MAX_REVIEW_ITEMS = 50;
48
+ const MAX_HEADING_LEN = 120;
49
+ const MAX_SLUG_LEN = 200;
50
+ const MAX_TITLE_LEN = 200;
51
+ const MAX_IMAGE_URL_LEN = 2048;
52
+ const MAX_CAROUSEL_ITEMS = 24;
53
+ const MAX_LABEL_LEN = 60;
54
+ const MAX_FIELD_NAME_LEN = 40;
55
+ const MAX_FIELD_LABEL_LEN = 120;
56
+ const MAX_FORM_FIELDS = 8;
57
+ const MAX_OPTION_LEN = 120;
58
+ const MAX_OPTIONS = 20;
59
+ const MAX_SUCCESS_MSG_LEN = 200;
60
+ /** Generous-but-finite bound on an action path — rejects a pathological path before refining it. */
61
+ const MAX_ACTION_PATH_LEN = 512;
62
+ /**
63
+ * The required prefix for an interactive widget's POST-back `action`/`onAction`/`offAction` path.
64
+ * This layer can only validate the SHAPE — it cannot know the originating module's name. The storefront
65
+ * enforces that the path targets the ORIGINATING module's own mount (the module name comes from the slot
66
+ * BINDING, never from the descriptor). See {@link actionPathSchema}.
67
+ */
68
+ const ACTION_PATH_PREFIX = '/store/v1/modules/';
69
+ /**
70
+ * A header-injection-safe RELATIVE action path. This layer validates the SHAPE only; the storefront binds
71
+ * it to the originating module's mount. Rejects: anything not starting with {@link ACTION_PATH_PREFIX}
72
+ * (so no absolute `https://`/`http:`/`//host` URL, no scheme, no other origin); any `..` path traversal; any
73
+ * CR/LF or other ASCII control character (header-injection / response-splitting); and over-length.
74
+ *
75
+ * The allowlist regex is the real gate: a clean path is a `/store/v1/modules/` prefix followed only by
76
+ * URL-safe path characters (`A–Z a–z 0–9 - _ . ~ / : @ ! $ & ' ( ) * + , ; =`). Because `/` is the
77
+ * only structural separator and `\r`/`\n`/space/control bytes are NOT in the class, CRLF and control
78
+ * chars cannot match; `..` is rejected by an explicit segment check (defence in depth — a `.` IS in the
79
+ * class, so the regex alone would admit `..`).
80
+ *
81
+ * `%` is DELIBERATELY EXCLUDED from the class. An action path is a simple relative endpoint (POST
82
+ * params ride the body, never the path), so it never needs percent-encoding — and admitting `%` would
83
+ * open an encoding channel where `%2e%2e` (→ `..`) or `%0d%0a` (→ CR/LF) passes the char-by-char regex
84
+ * AND the RAW `split('/')` segment refine (which never decodes), re-introducing traversal / response-
85
+ * splitting after the fact. With `%` banned there is NO encoding channel: a literal `..` is caught by
86
+ * the segment refine, and CRLF / space / control / backslash / unicode are all already outside the class.
87
+ */
88
+ const SAFE_PATH_BODY_RE = /^\/store\/v1\/modules\/[A-Za-z0-9\-._~/:@!$&'()*+,;=]*$/;
89
+ exports.actionPathSchema = zod_1.z
90
+ .string()
91
+ .min(ACTION_PATH_PREFIX.length)
92
+ .max(MAX_ACTION_PATH_LEN)
93
+ .regex(SAFE_PATH_BODY_RE, 'action path must be a clean relative /store/v1/modules/... path')
94
+ .refine((p) => !p.split('/').includes('..'), {
95
+ message: 'action path must not contain `..` traversal',
96
+ });
97
+ /** An interactive widget's action target: just a validated relative `path` (C1 shape-only). */
98
+ exports.actionSchema = zod_1.z.object({ path: exports.actionPathSchema }).strict();
99
+ // ── per-widget props schemas (each `.strict()`, fully bounded) ────────────────────
100
+ /** `star-rating-summary` props: an average in [0,5] and a non-negative integer count. */
101
+ exports.starRatingSummaryPropsSchema = zod_1.z
102
+ .object({
103
+ average: zod_1.z.number().min(0).max(5),
104
+ count: zod_1.z.number().int().min(0),
105
+ })
106
+ .strict();
107
+ /** `review-list` props: a bounded list of bounded review items (id/rating/body/author/createdAt). */
108
+ exports.reviewListPropsSchema = zod_1.z
109
+ .object({
110
+ items: zod_1.z
111
+ .array(zod_1.z
112
+ .object({
113
+ id: zod_1.z.string().min(1).max(MAX_ID_LEN),
114
+ rating: zod_1.z.number().int().min(1).max(5),
115
+ body: zod_1.z.string().max(MAX_REVIEW_BODY_LEN),
116
+ author: zod_1.z.string().max(MAX_AUTHOR_LEN).optional(),
117
+ // An ISO-8601 datetime string (e.g. `2026-06-22T10:00:00.000Z`). z.iso.datetime is a pure
118
+ // format check — no Date construction, no I/O.
119
+ createdAt: zod_1.z.iso.datetime(),
120
+ })
121
+ .strict())
122
+ .max(MAX_REVIEW_ITEMS),
123
+ })
124
+ .strict();
125
+ /**
126
+ * A product `slug` used to build a `/product/<slug>` link. Bounded length + a TRAVERSAL guard: it must
127
+ * not contain `/` or `\` (no extra path segments) and must not be a `..` segment — so a module can't
128
+ * return `slug:'../../admin'` and turn the carousel link into a within-origin redirect to another route.
129
+ * NOT constrained to a strict charset (real slugs vary by locale/tenant); only the traversal MECHANISM
130
+ * is barred. C2 ALSO `encodeURIComponent`s the slug at render (defense in depth) — this is the contract
131
+ * layer that rejects the descriptor outright. The `..` check is on the whole value (the slash ban already
132
+ * means a `..` can only appear as the entire slug, but checking explicitly keeps the intent legible).
133
+ */
134
+ const carouselSlugSchema = zod_1.z
135
+ .string()
136
+ .min(1)
137
+ .max(MAX_SLUG_LEN)
138
+ .refine((s) => !s.includes('/') && !s.includes('\\') && s !== '..', {
139
+ message: 'slug must not contain path separators or a `..` traversal segment',
140
+ });
141
+ /** `product-carousel` props: an optional heading + a bounded list of bounded product cards. */
142
+ exports.productCarouselPropsSchema = zod_1.z
143
+ .object({
144
+ heading: zod_1.z.string().max(MAX_HEADING_LEN).optional(),
145
+ items: zod_1.z
146
+ .array(zod_1.z
147
+ .object({
148
+ productId: zod_1.z.string().min(1).max(MAX_ID_LEN),
149
+ slug: carouselSlugSchema,
150
+ title: zod_1.z.string().min(1).max(MAX_TITLE_LEN),
151
+ imageUrl: zod_1.z.string().max(MAX_IMAGE_URL_LEN).optional(),
152
+ })
153
+ .strict())
154
+ .max(MAX_CAROUSEL_ITEMS),
155
+ })
156
+ .strict();
157
+ /** `toggle-button` props: on/off actions (relative paths), bounded labels, enum-only icon. */
158
+ exports.toggleButtonPropsSchema = zod_1.z
159
+ .object({
160
+ initialOn: zod_1.z.boolean(),
161
+ onAction: exports.actionSchema,
162
+ offAction: exports.actionSchema,
163
+ labels: zod_1.z
164
+ .object({
165
+ on: zod_1.z.string().min(1).max(MAX_LABEL_LEN),
166
+ off: zod_1.z.string().min(1).max(MAX_LABEL_LEN),
167
+ })
168
+ .strict(),
169
+ icon: zod_1.z.enum(['heart', 'bell', 'star']),
170
+ })
171
+ .strict();
172
+ /** `submit-form` props: a relative action path, a bounded field list with enum-only kinds. */
173
+ exports.submitFormPropsSchema = zod_1.z
174
+ .object({
175
+ action: exports.actionSchema,
176
+ submitLabel: zod_1.z.string().min(1).max(MAX_LABEL_LEN),
177
+ fields: zod_1.z
178
+ .array(zod_1.z
179
+ .object({
180
+ name: zod_1.z.string().min(1).max(MAX_FIELD_NAME_LEN),
181
+ label: zod_1.z.string().min(1).max(MAX_FIELD_LABEL_LEN),
182
+ kind: zod_1.z.enum(['text', 'textarea', 'rating', 'email', 'select']),
183
+ required: zod_1.z.boolean(),
184
+ options: zod_1.z.array(zod_1.z.string().max(MAX_OPTION_LEN)).max(MAX_OPTIONS).optional(),
185
+ })
186
+ .strict())
187
+ .max(MAX_FORM_FIELDS),
188
+ successMessage: zod_1.z.string().max(MAX_SUCCESS_MSG_LEN).optional(),
189
+ })
190
+ .strict();
191
+ /**
192
+ * The widget descriptor: `{ type, props }` discriminated on `type`, so each widget's props are
193
+ * validated against ITS OWN schema (wrong props for a type ⇒ fail). `.strict()` on each member rejects
194
+ * unknown keys at the descriptor level; the per-widget props schemas are `.strict()` too, so unknown
195
+ * keys are rejected at BOTH levels.
196
+ */
197
+ exports.widgetDescriptorSchema = zod_1.z.discriminatedUnion('type', [
198
+ zod_1.z
199
+ .object({ type: zod_1.z.literal('star-rating-summary'), props: exports.starRatingSummaryPropsSchema })
200
+ .strict(),
201
+ zod_1.z.object({ type: zod_1.z.literal('review-list'), props: exports.reviewListPropsSchema }).strict(),
202
+ zod_1.z.object({ type: zod_1.z.literal('product-carousel'), props: exports.productCarouselPropsSchema }).strict(),
203
+ zod_1.z.object({ type: zod_1.z.literal('toggle-button'), props: exports.toggleButtonPropsSchema }).strict(),
204
+ zod_1.z.object({ type: zod_1.z.literal('submit-form'), props: exports.submitFormPropsSchema }).strict(),
205
+ ]);
206
+ /**
207
+ * Parse + verify a raw widget descriptor. PURE — no I/O, no code execution, no render.
208
+ *
209
+ * Accepts either a JSON string (the wire form — byte-capped, then `JSON.parse`d, mirroring
210
+ * {@link parseTemplate}) or an already-parsed value (so the storefront can hand it the parsed JSON
211
+ * directly). Enforces the byte cap on the string form, validates against {@link widgetDescriptorSchema}
212
+ * (the discriminated union + per-widget `.strict()` props), and returns the typed descriptor — or
213
+ * `null` on ANY failure: oversized, non-JSON, non-object, unknown type, discriminator mismatch, an
214
+ * out-of-bounds / bad-enum / bad-path prop, or an unknown key at either level. It NEVER throws: the
215
+ * fail-closed contract the storefront RSC relies on to "render nothing, never block or 500 the page".
216
+ */
217
+ function parseWidget(raw) {
218
+ let candidate = raw;
219
+ if (typeof raw === 'string') {
220
+ if (Buffer.byteLength(raw, 'utf8') > exports.WIDGET_MAX_BYTES)
221
+ return null;
222
+ try {
223
+ candidate = JSON.parse(raw);
224
+ }
225
+ catch {
226
+ return null;
227
+ }
228
+ }
229
+ const result = exports.widgetDescriptorSchema.safeParse(candidate);
230
+ return result.success ? result.data : null;
231
+ }
232
+ //# sourceMappingURL=widget.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"widget.js","sourceRoot":"","sources":["../src/widget.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,51 @@
1
+ {
2
+ "name": "@sovecom/theme-sdk",
3
+ "version": "1.0.0-rc.1",
4
+ "license": "MIT",
5
+ "description": "Public author-facing contract SDK for the SovEcom theme ecosystem",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "https://github.com/asifwanders/SovEcom.git",
9
+ "directory": "packages/theme-sdk"
10
+ },
11
+ "homepage": "https://github.com/asifwanders/SovEcom#readme",
12
+ "bugs": {
13
+ "url": "https://github.com/asifwanders/SovEcom/issues"
14
+ },
15
+ "publishConfig": {
16
+ "access": "public"
17
+ },
18
+ "files": [
19
+ "dist",
20
+ "README.md"
21
+ ],
22
+ "main": "./dist/index.js",
23
+ "types": "./dist/index.d.ts",
24
+ "exports": {
25
+ ".": {
26
+ "types": "./dist/index.d.ts",
27
+ "import": "./dist/index.js",
28
+ "require": "./dist/index.js",
29
+ "default": "./dist/index.js"
30
+ }
31
+ },
32
+ "dependencies": {
33
+ "semver": "^7.8.4",
34
+ "zod": "^4.4.3",
35
+ "@sovecom/module-sdk": "1.0.0-rc.1"
36
+ },
37
+ "devDependencies": {
38
+ "@types/node": "^24.0.0",
39
+ "@types/semver": "^7.7.1",
40
+ "typescript": "^5.4.0",
41
+ "vitest": "^4.0.0"
42
+ },
43
+ "scripts": {
44
+ "build": "tsc -p tsconfig.json",
45
+ "typecheck": "tsc -p tsconfig.json --noEmit",
46
+ "lint": "eslint src --ext .ts",
47
+ "test": "vitest run",
48
+ "test:watch": "vitest",
49
+ "clean": "rm -rf dist"
50
+ }
51
+ }