@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/LICENSE +21 -0
- package/README.md +59 -0
- package/dist/index.d.ts +33 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +75 -0
- package/dist/index.js.map +1 -0
- package/dist/manifest.d.ts +67 -0
- package/dist/manifest.d.ts.map +1 -0
- package/dist/manifest.js +174 -0
- package/dist/manifest.js.map +1 -0
- package/dist/settings.d.ts +84 -0
- package/dist/settings.d.ts.map +1 -0
- package/dist/settings.js +23 -0
- package/dist/settings.js.map +1 -0
- package/dist/slots.d.ts +9 -0
- package/dist/slots.d.ts.map +1 -0
- package/dist/slots.js +40 -0
- package/dist/slots.js.map +1 -0
- package/dist/store-contract.d.ts +35 -0
- package/dist/store-contract.d.ts.map +1 -0
- package/dist/store-contract.js +3 -0
- package/dist/store-contract.js.map +1 -0
- package/dist/template.d.ts +119 -0
- package/dist/template.d.ts.map +1 -0
- package/dist/template.js +169 -0
- package/dist/template.js.map +1 -0
- package/dist/theme.d.ts +35 -0
- package/dist/theme.d.ts.map +1 -0
- package/dist/theme.js +31 -0
- package/dist/theme.js.map +1 -0
- package/dist/widget.d.ts +200 -0
- package/dist/widget.d.ts.map +1 -0
- package/dist/widget.js +232 -0
- package/dist/widget.js.map +1 -0
- package/package.json +51 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 SovEcom
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# @sovecom/theme-sdk
|
|
2
|
+
|
|
3
|
+
The public, author-facing SDK for building [SovEcom](../../README.md) themes.
|
|
4
|
+
|
|
5
|
+
> **Status:** stub. This package is `private` and consumed in-repo via the pnpm workspace; it is
|
|
6
|
+
> not yet published to npm. This README is a placeholder — the full author guide is forthcoming.
|
|
7
|
+
|
|
8
|
+
## What it is
|
|
9
|
+
|
|
10
|
+
This package is the **single source of truth** for the SovEcom theme **manifest** contract: the
|
|
11
|
+
`sovecom.theme.json` schema, its validator, the byte cap + semver gate, and the author ergonomics.
|
|
12
|
+
The core runtime (`apps/api`) imports these same definitions, so the published contract can never
|
|
13
|
+
drift from what the core enforces at install time.
|
|
14
|
+
|
|
15
|
+
A theme is a **declarative asset**: there is **no `activate`, no worker, no runtime entrypoint, no
|
|
16
|
+
capabilities, no namespaced tables**. So this package exports the manifest contract, author-time
|
|
17
|
+
validation/typing helpers, and the two store-contract types a storefront reads — nothing executable.
|
|
18
|
+
The shared core-API primitives (`CORE_API_VERSION`, `assertCoreCompatible`, `MANIFEST_MAX_BYTES`)
|
|
19
|
+
are reused from `@sovecom/module-sdk` so both SDKs gate against one core version.
|
|
20
|
+
|
|
21
|
+
## Authoring a theme
|
|
22
|
+
|
|
23
|
+
```ts
|
|
24
|
+
import { defineTheme, defineThemeSlots, defineThemeSettings } from '@sovecom/theme-sdk';
|
|
25
|
+
|
|
26
|
+
// defineTheme validates the config and returns the typed, validated manifest OBJECT
|
|
27
|
+
// (NOT an `{ activate }` entry — a theme has no runtime body):
|
|
28
|
+
export default defineTheme({
|
|
29
|
+
name: 'aurora',
|
|
30
|
+
displayName: 'Aurora',
|
|
31
|
+
version: '1.0.0',
|
|
32
|
+
compatibleCore: '^1.0.0',
|
|
33
|
+
slots: defineThemeSlots(['product-page', 'cart-drawer']),
|
|
34
|
+
settingsSchema: './settings.schema.json', // path stays opaque; never read here
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
// Optional: type your theme's default settings shape (pure compile-time helper):
|
|
38
|
+
export const defaults = defineThemeSettings({ accentColor: '#6c5ce7', showBadges: true });
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Exports
|
|
42
|
+
|
|
43
|
+
- `defineTheme(config)` — validates the config and returns the typed, validated `ThemeManifest`
|
|
44
|
+
object. A theme has no runtime entrypoint, so it returns a manifest, not an `{ activate }`.
|
|
45
|
+
- `defineThemeSlots(slots)` — typed, validated builder for the manifest's declarative slot-slug
|
|
46
|
+
array (lowercase slugs, no duplicates).
|
|
47
|
+
- `defineThemeSettings(defaults)` — pure compile-time helper to type the author's settings object.
|
|
48
|
+
- Manifest types + validators: `ThemeManifest`, `themeManifestSchema`, `parseAndVerifyThemeManifest`,
|
|
49
|
+
`THEME_NAME_RE`, `SLOT_SLUG_RE`.
|
|
50
|
+
- Shared core-API primitives (re-exported from `@sovecom/module-sdk`): `CORE_API_VERSION`,
|
|
51
|
+
`assertCoreCompatible`, `MANIFEST_MAX_BYTES`.
|
|
52
|
+
- Store-contract types (consumed by the storefront): `ActiveTheme` (`{ name, version, settings }`),
|
|
53
|
+
`SlotMap` (`Record<slot, { module, component }>`), `SlotBinding`.
|
|
54
|
+
|
|
55
|
+
## License
|
|
56
|
+
|
|
57
|
+
MIT. A theme is derivative of the MIT reference storefront across the HTTP API boundary, so this
|
|
58
|
+
SDK — distinct from the AGPL-3.0 core and the AGPL `@sovecom/module-sdk` — is MIT. See the
|
|
59
|
+
`LICENSE` file in this package.
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@sovecom/theme-sdk` — the public, semver-pinned author-facing contract for the SovEcom theme
|
|
3
|
+
* ecosystem. This package is the SINGLE SOURCE OF TRUTH for the theme manifest: the validator, the
|
|
4
|
+
* types, and the author ergonomics. The core runtime imports these definitions FROM here, so the
|
|
5
|
+
* published SDK can never drift from what the core actually enforces at install time.
|
|
6
|
+
*
|
|
7
|
+
* A theme is a declarative ASSET: there is NO `activate`, NO worker, NO runtime entrypoint, NO
|
|
8
|
+
* capabilities, NO namespaced tables. So this package exports the manifest contract, author-time
|
|
9
|
+
* validation/typing helpers, and the two store-contract types a storefront reads — nothing
|
|
10
|
+
* executable. It is MIT-licensed, distinct from the AGPL core, so it can be vendored by commercial
|
|
11
|
+
* theme authors across the HTTP API boundary.
|
|
12
|
+
*
|
|
13
|
+
* The shared core-API primitives (`CORE_API_VERSION`, `assertCoreCompatible`, `MANIFEST_MAX_BYTES`)
|
|
14
|
+
* are REUSED from `@sovecom/module-sdk` — they have ONE home so both SDKs gate against the same
|
|
15
|
+
* core version.
|
|
16
|
+
*/
|
|
17
|
+
/** SDK package version (independent of the core API contract version below). */
|
|
18
|
+
export declare const THEME_SDK_VERSION = "1.0.0-rc.1";
|
|
19
|
+
export { defineTheme } from './theme.js';
|
|
20
|
+
export type { DefineThemeConfig } from './theme.js';
|
|
21
|
+
export { defineThemeSlots } from './slots.js';
|
|
22
|
+
export { defineThemeSettings } from './settings.js';
|
|
23
|
+
export type { ThemeSettings, DocumentedThemeSettings, KnownThemeSettings } from './settings.js';
|
|
24
|
+
export { THEME_NAME_RE, SLOT_SLUG_RE, TEMPLATE_PATH_RE, themeManifestSchema, themeTemplateDeclSchema, parseAndVerifyThemeManifest, } from './manifest.js';
|
|
25
|
+
export type { ThemeManifest, ThemeTemplateDecl } from './manifest.js';
|
|
26
|
+
export { PAGE_TYPES, SECTION_TYPE_RE, REGION_NAME_RE, MAX_REGION_DEPTH, pageTypeSchema, regionNameSchema, templateSectionSchema, templateSchema, parseTemplate, defineTemplate, defineSection, } from './template.js';
|
|
27
|
+
export type { PageType, TemplateSection, ThemeTemplate, SectionDef } from './template.js';
|
|
28
|
+
export { WIDGET_TYPES, WIDGET_MAX_BYTES, actionPathSchema, actionSchema, starRatingSummaryPropsSchema, reviewListPropsSchema, productCarouselPropsSchema, toggleButtonPropsSchema, submitFormPropsSchema, widgetDescriptorSchema, parseWidget, } from './widget.js';
|
|
29
|
+
export type { WidgetType, WidgetDescriptor, StarRatingSummaryProps, ReviewListProps, ProductCarouselProps, ToggleButtonProps, SubmitFormProps, } from './widget.js';
|
|
30
|
+
export { MANIFEST_MAX_BYTES, assertCoreCompatible } from './manifest.js';
|
|
31
|
+
export { CORE_API_VERSION } from '@sovecom/module-sdk';
|
|
32
|
+
export type { ActiveTheme, SlotBinding, SlotMap } from './store-contract.js';
|
|
33
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,gFAAgF;AAChF,eAAO,MAAM,iBAAiB,eAAe,CAAC;AAG9C,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,YAAY,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AACpD,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AACpD,YAAY,EAAE,aAAa,EAAE,uBAAuB,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAGhG,OAAO,EACL,aAAa,EACb,YAAY,EACZ,gBAAgB,EAChB,mBAAmB,EACnB,uBAAuB,EACvB,2BAA2B,GAC5B,MAAM,eAAe,CAAC;AACvB,YAAY,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAMtE,OAAO,EACL,UAAU,EACV,eAAe,EACf,cAAc,EACd,gBAAgB,EAChB,cAAc,EACd,gBAAgB,EAChB,qBAAqB,EACrB,cAAc,EACd,aAAa,EACb,cAAc,EACd,aAAa,GACd,MAAM,eAAe,CAAC;AACvB,YAAY,EAAE,QAAQ,EAAE,eAAe,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAM1F,OAAO,EACL,YAAY,EACZ,gBAAgB,EAChB,gBAAgB,EAChB,YAAY,EACZ,4BAA4B,EAC5B,qBAAqB,EACrB,0BAA0B,EAC1B,uBAAuB,EACvB,qBAAqB,EACrB,sBAAsB,EACtB,WAAW,GACZ,MAAM,aAAa,CAAC;AACrB,YAAY,EACV,UAAU,EACV,gBAAgB,EAChB,sBAAsB,EACtB,eAAe,EACf,oBAAoB,EACpB,iBAAiB,EACjB,eAAe,GAChB,MAAM,aAAa,CAAC;AAGrB,OAAO,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AACzE,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAGvD,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* `@sovecom/theme-sdk` — the public, semver-pinned author-facing contract for the SovEcom theme
|
|
4
|
+
* ecosystem. This package is the SINGLE SOURCE OF TRUTH for the theme manifest: the validator, the
|
|
5
|
+
* types, and the author ergonomics. The core runtime imports these definitions FROM here, so the
|
|
6
|
+
* published SDK can never drift from what the core actually enforces at install time.
|
|
7
|
+
*
|
|
8
|
+
* A theme is a declarative ASSET: there is NO `activate`, NO worker, NO runtime entrypoint, NO
|
|
9
|
+
* capabilities, NO namespaced tables. So this package exports the manifest contract, author-time
|
|
10
|
+
* validation/typing helpers, and the two store-contract types a storefront reads — nothing
|
|
11
|
+
* executable. It is MIT-licensed, distinct from the AGPL core, so it can be vendored by commercial
|
|
12
|
+
* theme authors across the HTTP API boundary.
|
|
13
|
+
*
|
|
14
|
+
* The shared core-API primitives (`CORE_API_VERSION`, `assertCoreCompatible`, `MANIFEST_MAX_BYTES`)
|
|
15
|
+
* are REUSED from `@sovecom/module-sdk` — they have ONE home so both SDKs gate against the same
|
|
16
|
+
* core version.
|
|
17
|
+
*/
|
|
18
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
19
|
+
exports.CORE_API_VERSION = exports.assertCoreCompatible = exports.MANIFEST_MAX_BYTES = exports.parseWidget = exports.widgetDescriptorSchema = exports.submitFormPropsSchema = exports.toggleButtonPropsSchema = exports.productCarouselPropsSchema = exports.reviewListPropsSchema = exports.starRatingSummaryPropsSchema = exports.actionSchema = exports.actionPathSchema = exports.WIDGET_MAX_BYTES = exports.WIDGET_TYPES = exports.defineSection = exports.defineTemplate = exports.parseTemplate = exports.templateSchema = exports.templateSectionSchema = exports.regionNameSchema = exports.pageTypeSchema = exports.MAX_REGION_DEPTH = exports.REGION_NAME_RE = exports.SECTION_TYPE_RE = exports.PAGE_TYPES = exports.parseAndVerifyThemeManifest = exports.themeTemplateDeclSchema = exports.themeManifestSchema = exports.TEMPLATE_PATH_RE = exports.SLOT_SLUG_RE = exports.THEME_NAME_RE = exports.defineThemeSettings = exports.defineThemeSlots = exports.defineTheme = exports.THEME_SDK_VERSION = void 0;
|
|
20
|
+
/** SDK package version (independent of the core API contract version below). */
|
|
21
|
+
exports.THEME_SDK_VERSION = '1.0.0-rc.1';
|
|
22
|
+
// ── author ergonomics ───────────────────────────────────────────────────────────
|
|
23
|
+
var theme_js_1 = require("./theme.js");
|
|
24
|
+
Object.defineProperty(exports, "defineTheme", { enumerable: true, get: function () { return theme_js_1.defineTheme; } });
|
|
25
|
+
var slots_js_1 = require("./slots.js");
|
|
26
|
+
Object.defineProperty(exports, "defineThemeSlots", { enumerable: true, get: function () { return slots_js_1.defineThemeSlots; } });
|
|
27
|
+
var settings_js_1 = require("./settings.js");
|
|
28
|
+
Object.defineProperty(exports, "defineThemeSettings", { enumerable: true, get: function () { return settings_js_1.defineThemeSettings; } });
|
|
29
|
+
// ── manifest types + validators (single source of truth) ─────────────────────────
|
|
30
|
+
var manifest_js_1 = require("./manifest.js");
|
|
31
|
+
Object.defineProperty(exports, "THEME_NAME_RE", { enumerable: true, get: function () { return manifest_js_1.THEME_NAME_RE; } });
|
|
32
|
+
Object.defineProperty(exports, "SLOT_SLUG_RE", { enumerable: true, get: function () { return manifest_js_1.SLOT_SLUG_RE; } });
|
|
33
|
+
Object.defineProperty(exports, "TEMPLATE_PATH_RE", { enumerable: true, get: function () { return manifest_js_1.TEMPLATE_PATH_RE; } });
|
|
34
|
+
Object.defineProperty(exports, "themeManifestSchema", { enumerable: true, get: function () { return manifest_js_1.themeManifestSchema; } });
|
|
35
|
+
Object.defineProperty(exports, "themeTemplateDeclSchema", { enumerable: true, get: function () { return manifest_js_1.themeTemplateDeclSchema; } });
|
|
36
|
+
Object.defineProperty(exports, "parseAndVerifyThemeManifest", { enumerable: true, get: function () { return manifest_js_1.parseAndVerifyThemeManifest; } });
|
|
37
|
+
// ── template contract — section/JSON-template composition ──
|
|
38
|
+
// Declarative page templates (`{ page, sections[] }`) + author helpers. PURE validators, no code
|
|
39
|
+
// execution; the manifest is UNTOUCHED (the manifest `templates[]` declaration is deferred). Only
|
|
40
|
+
// `home` is consumed at this stage; the rest of `PAGE_TYPES` is declared for later stages.
|
|
41
|
+
var template_js_1 = require("./template.js");
|
|
42
|
+
Object.defineProperty(exports, "PAGE_TYPES", { enumerable: true, get: function () { return template_js_1.PAGE_TYPES; } });
|
|
43
|
+
Object.defineProperty(exports, "SECTION_TYPE_RE", { enumerable: true, get: function () { return template_js_1.SECTION_TYPE_RE; } });
|
|
44
|
+
Object.defineProperty(exports, "REGION_NAME_RE", { enumerable: true, get: function () { return template_js_1.REGION_NAME_RE; } });
|
|
45
|
+
Object.defineProperty(exports, "MAX_REGION_DEPTH", { enumerable: true, get: function () { return template_js_1.MAX_REGION_DEPTH; } });
|
|
46
|
+
Object.defineProperty(exports, "pageTypeSchema", { enumerable: true, get: function () { return template_js_1.pageTypeSchema; } });
|
|
47
|
+
Object.defineProperty(exports, "regionNameSchema", { enumerable: true, get: function () { return template_js_1.regionNameSchema; } });
|
|
48
|
+
Object.defineProperty(exports, "templateSectionSchema", { enumerable: true, get: function () { return template_js_1.templateSectionSchema; } });
|
|
49
|
+
Object.defineProperty(exports, "templateSchema", { enumerable: true, get: function () { return template_js_1.templateSchema; } });
|
|
50
|
+
Object.defineProperty(exports, "parseTemplate", { enumerable: true, get: function () { return template_js_1.parseTemplate; } });
|
|
51
|
+
Object.defineProperty(exports, "defineTemplate", { enumerable: true, get: function () { return template_js_1.defineTemplate; } });
|
|
52
|
+
Object.defineProperty(exports, "defineSection", { enumerable: true, get: function () { return template_js_1.defineSection; } });
|
|
53
|
+
// ── module slot-widget contract (data-descriptor widgets) ────────────────────
|
|
54
|
+
// A module contributes storefront UI by returning a typed `{ type, props }` widget descriptor from a
|
|
55
|
+
// CLOSED, core-owned MIT vocabulary. PURE validators only — no code/HTML/SVG crosses; the storefront
|
|
56
|
+
// renders its own known MIT components. `parseWidget` returns `null` on ANY failure (never throws).
|
|
57
|
+
var widget_js_1 = require("./widget.js");
|
|
58
|
+
Object.defineProperty(exports, "WIDGET_TYPES", { enumerable: true, get: function () { return widget_js_1.WIDGET_TYPES; } });
|
|
59
|
+
Object.defineProperty(exports, "WIDGET_MAX_BYTES", { enumerable: true, get: function () { return widget_js_1.WIDGET_MAX_BYTES; } });
|
|
60
|
+
Object.defineProperty(exports, "actionPathSchema", { enumerable: true, get: function () { return widget_js_1.actionPathSchema; } });
|
|
61
|
+
Object.defineProperty(exports, "actionSchema", { enumerable: true, get: function () { return widget_js_1.actionSchema; } });
|
|
62
|
+
Object.defineProperty(exports, "starRatingSummaryPropsSchema", { enumerable: true, get: function () { return widget_js_1.starRatingSummaryPropsSchema; } });
|
|
63
|
+
Object.defineProperty(exports, "reviewListPropsSchema", { enumerable: true, get: function () { return widget_js_1.reviewListPropsSchema; } });
|
|
64
|
+
Object.defineProperty(exports, "productCarouselPropsSchema", { enumerable: true, get: function () { return widget_js_1.productCarouselPropsSchema; } });
|
|
65
|
+
Object.defineProperty(exports, "toggleButtonPropsSchema", { enumerable: true, get: function () { return widget_js_1.toggleButtonPropsSchema; } });
|
|
66
|
+
Object.defineProperty(exports, "submitFormPropsSchema", { enumerable: true, get: function () { return widget_js_1.submitFormPropsSchema; } });
|
|
67
|
+
Object.defineProperty(exports, "widgetDescriptorSchema", { enumerable: true, get: function () { return widget_js_1.widgetDescriptorSchema; } });
|
|
68
|
+
Object.defineProperty(exports, "parseWidget", { enumerable: true, get: function () { return widget_js_1.parseWidget; } });
|
|
69
|
+
// ── shared core-API primitives (re-exported from @sovecom/module-sdk; ONE home) ───
|
|
70
|
+
var manifest_js_2 = require("./manifest.js");
|
|
71
|
+
Object.defineProperty(exports, "MANIFEST_MAX_BYTES", { enumerable: true, get: function () { return manifest_js_2.MANIFEST_MAX_BYTES; } });
|
|
72
|
+
Object.defineProperty(exports, "assertCoreCompatible", { enumerable: true, get: function () { return manifest_js_2.assertCoreCompatible; } });
|
|
73
|
+
var module_sdk_1 = require("@sovecom/module-sdk");
|
|
74
|
+
Object.defineProperty(exports, "CORE_API_VERSION", { enumerable: true, get: function () { return module_sdk_1.CORE_API_VERSION; } });
|
|
75
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;GAeG;;;AAEH,gFAAgF;AACnE,QAAA,iBAAiB,GAAG,YAAY,CAAC;AAE9C,mFAAmF;AACnF,uCAAyC;AAAhC,uGAAA,WAAW,OAAA;AAEpB,uCAA8C;AAArC,4GAAA,gBAAgB,OAAA;AACzB,6CAAoD;AAA3C,kHAAA,mBAAmB,OAAA;AAG5B,oFAAoF;AACpF,6CAOuB;AANrB,4GAAA,aAAa,OAAA;AACb,2GAAA,YAAY,OAAA;AACZ,+GAAA,gBAAgB,OAAA;AAChB,kHAAA,mBAAmB,OAAA;AACnB,sHAAA,uBAAuB,OAAA;AACvB,0HAAA,2BAA2B,OAAA;AAI7B,8DAA8D;AAC9D,iGAAiG;AACjG,kGAAkG;AAClG,2FAA2F;AAC3F,6CAYuB;AAXrB,yGAAA,UAAU,OAAA;AACV,8GAAA,eAAe,OAAA;AACf,6GAAA,cAAc,OAAA;AACd,+GAAA,gBAAgB,OAAA;AAChB,6GAAA,cAAc,OAAA;AACd,+GAAA,gBAAgB,OAAA;AAChB,oHAAA,qBAAqB,OAAA;AACrB,6GAAA,cAAc,OAAA;AACd,4GAAA,aAAa,OAAA;AACb,6GAAA,cAAc,OAAA;AACd,4GAAA,aAAa,OAAA;AAIf,gFAAgF;AAChF,qGAAqG;AACrG,qGAAqG;AACrG,oGAAoG;AACpG,yCAYqB;AAXnB,yGAAA,YAAY,OAAA;AACZ,6GAAA,gBAAgB,OAAA;AAChB,6GAAA,gBAAgB,OAAA;AAChB,yGAAA,YAAY,OAAA;AACZ,yHAAA,4BAA4B,OAAA;AAC5B,kHAAA,qBAAqB,OAAA;AACrB,uHAAA,0BAA0B,OAAA;AAC1B,oHAAA,uBAAuB,OAAA;AACvB,kHAAA,qBAAqB,OAAA;AACrB,mHAAA,sBAAsB,OAAA;AACtB,wGAAA,WAAW,OAAA;AAYb,qFAAqF;AACrF,6CAAyE;AAAhE,iHAAA,kBAAkB,OAAA;AAAE,mHAAA,oBAAoB,OAAA;AACjD,kDAAuD;AAA9C,8GAAA,gBAAgB,OAAA"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { MANIFEST_MAX_BYTES, assertCoreCompatible } from '@sovecom/module-sdk';
|
|
3
|
+
/** Theme name: a slug that forms the install identity and a URL segment. */
|
|
4
|
+
export declare const THEME_NAME_RE: RegExp;
|
|
5
|
+
/** A slot slug the theme exposes/renders (same lowercase-slug shape as the module side). */
|
|
6
|
+
export declare const SLOT_SLUG_RE: RegExp;
|
|
7
|
+
/**
|
|
8
|
+
* A template file path: a SAFE RELATIVE slug path ending in `.json`. Each segment is a lowercase
|
|
9
|
+
* slug (a-z0-9, `_`, `-`), segments are `/`-joined, and the whole thing ends in `.json`. By
|
|
10
|
+
* construction this admits NO leading `/` (absolute), NO `..` segment (traversal), NO `\` (Windows
|
|
11
|
+
* separator), and NO `.`-only / hidden segments — the manifest is the ALLOWLIST of files the ingest
|
|
12
|
+
* is permitted to read out of the extracted tree. The ingest re-asserts containment
|
|
13
|
+
* against the extraction root as defence in depth; this regex is the first gate.
|
|
14
|
+
*/
|
|
15
|
+
export declare const TEMPLATE_PATH_RE: RegExp;
|
|
16
|
+
/**
|
|
17
|
+
* A single template declaration: which `page` the theme ships a template for and the RELATIVE `path`
|
|
18
|
+
* to its JSON file inside the theme package. `.strict()` rejects unknown keys. The `path` is gated
|
|
19
|
+
* by {@link TEMPLATE_PATH_RE} (no `..`, no leading `/`, slug segments, `.json` suffix) so the
|
|
20
|
+
* declaration itself can never name a file outside the theme tree.
|
|
21
|
+
*/
|
|
22
|
+
export declare const themeTemplateDeclSchema: z.ZodObject<{
|
|
23
|
+
page: z.ZodEnum<{
|
|
24
|
+
home: "home";
|
|
25
|
+
product: "product";
|
|
26
|
+
category: "category";
|
|
27
|
+
products: "products";
|
|
28
|
+
search: "search";
|
|
29
|
+
cart: "cart";
|
|
30
|
+
}>;
|
|
31
|
+
path: z.ZodString;
|
|
32
|
+
}, z.core.$strict>;
|
|
33
|
+
/** A validated single template declaration (`{ page, path }`). */
|
|
34
|
+
export type ThemeTemplateDecl = z.infer<typeof themeTemplateDeclSchema>;
|
|
35
|
+
/**
|
|
36
|
+
* The manifest Zod schema. `.strict()` rejects unknown top-level keys. Mirrors the shape of
|
|
37
|
+
* the module manifest where it overlaps (name/displayName/version/compatibleCore) so the two
|
|
38
|
+
* verifiers stay recognisably similar.
|
|
39
|
+
*/
|
|
40
|
+
export declare const themeManifestSchema: z.ZodObject<{
|
|
41
|
+
name: z.ZodString;
|
|
42
|
+
displayName: z.ZodString;
|
|
43
|
+
version: z.ZodString;
|
|
44
|
+
compatibleCore: z.ZodString;
|
|
45
|
+
slots: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
46
|
+
settingsSchema: z.ZodOptional<z.ZodString>;
|
|
47
|
+
templates: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
48
|
+
page: z.ZodEnum<{
|
|
49
|
+
home: "home";
|
|
50
|
+
product: "product";
|
|
51
|
+
category: "category";
|
|
52
|
+
products: "products";
|
|
53
|
+
search: "search";
|
|
54
|
+
cart: "cart";
|
|
55
|
+
}>;
|
|
56
|
+
path: z.ZodString;
|
|
57
|
+
}, z.core.$strict>>>;
|
|
58
|
+
}, z.core.$strict>;
|
|
59
|
+
export type ThemeManifest = z.infer<typeof themeManifestSchema>;
|
|
60
|
+
/**
|
|
61
|
+
* Parse + verify a raw `sovecom.theme.json` string. Enforces the byte cap, parses JSON
|
|
62
|
+
* (mapping a parse failure to a clear error), then runs the Zod schema. Returns the typed
|
|
63
|
+
* manifest or throws a descriptive `Error`. PURE — no I/O, no code execution.
|
|
64
|
+
*/
|
|
65
|
+
export declare function parseAndVerifyThemeManifest(raw: string): ThemeManifest;
|
|
66
|
+
export { MANIFEST_MAX_BYTES, assertCoreCompatible };
|
|
67
|
+
//# sourceMappingURL=manifest.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../src/manifest.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAuC/E,4EAA4E;AAC5E,eAAO,MAAM,aAAa,QAAsB,CAAC;AACjD,4FAA4F;AAC5F,eAAO,MAAM,YAAY,QAAsB,CAAC;AAChD;;;;;;;GAOG;AACH,eAAO,MAAM,gBAAgB,QAAwD,CAAC;AAEtF;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB;;;;;;;;;;kBASzB,CAAC;AAEZ,kEAAkE;AAClE,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAExE;;;;GAIG;AACH,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;kBAuCrB,CAAC;AAEZ,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAEhE;;;;GAIG;AACH,wBAAgB,2BAA2B,CAAC,GAAG,EAAE,MAAM,GAAG,aAAa,CAuBtE;AAKD,OAAO,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,CAAC"}
|
package/dist/manifest.js
ADDED
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.assertCoreCompatible = exports.MANIFEST_MAX_BYTES = exports.themeManifestSchema = exports.themeTemplateDeclSchema = exports.TEMPLATE_PATH_RE = exports.SLOT_SLUG_RE = exports.THEME_NAME_RE = void 0;
|
|
37
|
+
exports.parseAndVerifyThemeManifest = parseAndVerifyThemeManifest;
|
|
38
|
+
const semver = __importStar(require("semver"));
|
|
39
|
+
const zod_1 = require("zod");
|
|
40
|
+
// Reuse the SHARED core-API primitives from @sovecom/module-sdk so BOTH SDKs gate against ONE
|
|
41
|
+
// `CORE_API_VERSION` and ONE byte cap (single source of truth; no duplication).
|
|
42
|
+
const module_sdk_1 = require("@sovecom/module-sdk");
|
|
43
|
+
Object.defineProperty(exports, "MANIFEST_MAX_BYTES", { enumerable: true, get: function () { return module_sdk_1.MANIFEST_MAX_BYTES; } });
|
|
44
|
+
Object.defineProperty(exports, "assertCoreCompatible", { enumerable: true, get: function () { return module_sdk_1.assertCoreCompatible; } });
|
|
45
|
+
// The `templates[]` declaration on the manifest references the page-type enum that the template
|
|
46
|
+
// contract owns. Reuse it so the manifest and the template validator agree on
|
|
47
|
+
// exactly which page types exist — no second enum to drift.
|
|
48
|
+
const template_js_1 = require("./template.js");
|
|
49
|
+
/**
|
|
50
|
+
* Theme manifest verification — the single source of truth. Exported from `@sovecom/theme-sdk`, so
|
|
51
|
+
* the published author SDK, the core runtime, and the contract-test suite all share ONE validator —
|
|
52
|
+
* it is structurally impossible for them to drift.
|
|
53
|
+
*
|
|
54
|
+
* PURE functions — no Nest, no DB, no filesystem, NO code execution. These parse and validate a
|
|
55
|
+
* `sovecom.theme.json` already read off disk. Themes are declarative ASSETS: there is no permission
|
|
56
|
+
* allowlist and no namespaced-tables rule (a theme owns NO DB tables). The security properties
|
|
57
|
+
* enforced here are data validation:
|
|
58
|
+
* - `.strict()` so unknown top-level keys are rejected (supply-chain hygiene);
|
|
59
|
+
* - the SAME byte cap as the module manifest on the raw bytes (reused from @sovecom/module-sdk);
|
|
60
|
+
* - a slug `name`, a valid-semver `version`, a valid-range `compatibleCore`;
|
|
61
|
+
* - a semver MAJOR gate against `CORE_API_VERSION` (reuses {@link assertCoreCompatible}).
|
|
62
|
+
* The `settingsSchema` path is stored OPAQUE — the referenced JSON-schema file is never read here
|
|
63
|
+
* (validation of theme settings against it is deferred).
|
|
64
|
+
*/
|
|
65
|
+
/** Bounds — generous but finite, to reject pathological manifests up front. */
|
|
66
|
+
const MAX_NAME_LEN = 64;
|
|
67
|
+
const MAX_DISPLAY_NAME_LEN = 128;
|
|
68
|
+
const MAX_SLOTS = 64;
|
|
69
|
+
const MAX_SLOT_LEN = 128;
|
|
70
|
+
const MAX_SETTINGS_SCHEMA_LEN = 256;
|
|
71
|
+
/**
|
|
72
|
+
* Bounds on the OPTIONAL `templates[]` declaration. A theme may ship at most one template per page
|
|
73
|
+
* type, so the array is capped at the number of page types (there is no point declaring more — the
|
|
74
|
+
* per-page-uniqueness refine would reject the duplicate anyway). The path is a bounded relative slug
|
|
75
|
+
* path ending in `.json`.
|
|
76
|
+
*/
|
|
77
|
+
const MAX_TEMPLATE_DECLS = template_js_1.PAGE_TYPES.length;
|
|
78
|
+
const MAX_TEMPLATE_PATH_LEN = 256;
|
|
79
|
+
/** Theme name: a slug that forms the install identity and a URL segment. */
|
|
80
|
+
exports.THEME_NAME_RE = /^[a-z][a-z0-9-]*$/;
|
|
81
|
+
/** A slot slug the theme exposes/renders (same lowercase-slug shape as the module side). */
|
|
82
|
+
exports.SLOT_SLUG_RE = /^[a-z][a-z0-9-]*$/;
|
|
83
|
+
/**
|
|
84
|
+
* A template file path: a SAFE RELATIVE slug path ending in `.json`. Each segment is a lowercase
|
|
85
|
+
* slug (a-z0-9, `_`, `-`), segments are `/`-joined, and the whole thing ends in `.json`. By
|
|
86
|
+
* construction this admits NO leading `/` (absolute), NO `..` segment (traversal), NO `\` (Windows
|
|
87
|
+
* separator), and NO `.`-only / hidden segments — the manifest is the ALLOWLIST of files the ingest
|
|
88
|
+
* is permitted to read out of the extracted tree. The ingest re-asserts containment
|
|
89
|
+
* against the extraction root as defence in depth; this regex is the first gate.
|
|
90
|
+
*/
|
|
91
|
+
exports.TEMPLATE_PATH_RE = /^[a-z0-9][a-z0-9_-]*(\/[a-z0-9][a-z0-9_-]*)*\.json$/;
|
|
92
|
+
/**
|
|
93
|
+
* A single template declaration: which `page` the theme ships a template for and the RELATIVE `path`
|
|
94
|
+
* to its JSON file inside the theme package. `.strict()` rejects unknown keys. The `path` is gated
|
|
95
|
+
* by {@link TEMPLATE_PATH_RE} (no `..`, no leading `/`, slug segments, `.json` suffix) so the
|
|
96
|
+
* declaration itself can never name a file outside the theme tree.
|
|
97
|
+
*/
|
|
98
|
+
exports.themeTemplateDeclSchema = zod_1.z
|
|
99
|
+
.object({
|
|
100
|
+
page: template_js_1.pageTypeSchema,
|
|
101
|
+
path: zod_1.z
|
|
102
|
+
.string()
|
|
103
|
+
.min(1)
|
|
104
|
+
.max(MAX_TEMPLATE_PATH_LEN)
|
|
105
|
+
.regex(exports.TEMPLATE_PATH_RE, 'path must be a relative .json slug path (no "..", no leading "/")'),
|
|
106
|
+
})
|
|
107
|
+
.strict();
|
|
108
|
+
/**
|
|
109
|
+
* The manifest Zod schema. `.strict()` rejects unknown top-level keys. Mirrors the shape of
|
|
110
|
+
* the module manifest where it overlaps (name/displayName/version/compatibleCore) so the two
|
|
111
|
+
* verifiers stay recognisably similar.
|
|
112
|
+
*/
|
|
113
|
+
exports.themeManifestSchema = zod_1.z
|
|
114
|
+
.object({
|
|
115
|
+
name: zod_1.z
|
|
116
|
+
.string()
|
|
117
|
+
.min(1)
|
|
118
|
+
.max(MAX_NAME_LEN)
|
|
119
|
+
.regex(exports.THEME_NAME_RE, 'name must be a lowercase slug like "aurora"'),
|
|
120
|
+
displayName: zod_1.z.string().min(1).max(MAX_DISPLAY_NAME_LEN),
|
|
121
|
+
version: zod_1.z
|
|
122
|
+
.string()
|
|
123
|
+
.max(64)
|
|
124
|
+
.refine((v) => semver.valid(v) !== null, 'version must be a valid semver'),
|
|
125
|
+
compatibleCore: zod_1.z
|
|
126
|
+
.string()
|
|
127
|
+
.max(256)
|
|
128
|
+
.refine((v) => semver.validRange(v) !== null, 'compatibleCore must be a valid semver range'),
|
|
129
|
+
slots: zod_1.z
|
|
130
|
+
.array(zod_1.z.string().min(1).max(MAX_SLOT_LEN).regex(exports.SLOT_SLUG_RE, 'slot must be a lowercase slug'))
|
|
131
|
+
.max(MAX_SLOTS)
|
|
132
|
+
// A theme declares any given slot at most once — mirrors the module side's duplicate-slot
|
|
133
|
+
// check so the two SDKs and `defineThemeSlots` agree.
|
|
134
|
+
.refine((arr) => new Set(arr).size === arr.length, 'each slot must be declared at most once')
|
|
135
|
+
.optional(),
|
|
136
|
+
settingsSchema: zod_1.z.string().min(1).max(MAX_SETTINGS_SCHEMA_LEN).optional(),
|
|
137
|
+
// OPTIONAL wire-delivered page templates. A bounded array of `{ page, path }` declarations:
|
|
138
|
+
// which page types the theme ships a template for, and the relative file to read at install.
|
|
139
|
+
// AT MOST ONE entry per page type (the `.refine`), array capped at the page-type count.
|
|
140
|
+
// Absent ⇒ a tokens/settings-only theme.
|
|
141
|
+
templates: zod_1.z
|
|
142
|
+
.array(exports.themeTemplateDeclSchema)
|
|
143
|
+
.max(MAX_TEMPLATE_DECLS)
|
|
144
|
+
.refine((arr) => new Set(arr.map((t) => t.page)).size === arr.length, 'each page type may be declared at most once in templates')
|
|
145
|
+
.optional(),
|
|
146
|
+
})
|
|
147
|
+
.strict();
|
|
148
|
+
/**
|
|
149
|
+
* Parse + verify a raw `sovecom.theme.json` string. Enforces the byte cap, parses JSON
|
|
150
|
+
* (mapping a parse failure to a clear error), then runs the Zod schema. Returns the typed
|
|
151
|
+
* manifest or throws a descriptive `Error`. PURE — no I/O, no code execution.
|
|
152
|
+
*/
|
|
153
|
+
function parseAndVerifyThemeManifest(raw) {
|
|
154
|
+
const byteLen = Buffer.byteLength(raw, 'utf8');
|
|
155
|
+
if (byteLen > module_sdk_1.MANIFEST_MAX_BYTES) {
|
|
156
|
+
throw new Error(`theme manifest too large: ${byteLen} bytes exceeds the ${module_sdk_1.MANIFEST_MAX_BYTES}-byte cap`);
|
|
157
|
+
}
|
|
158
|
+
let parsed;
|
|
159
|
+
try {
|
|
160
|
+
parsed = JSON.parse(raw);
|
|
161
|
+
}
|
|
162
|
+
catch {
|
|
163
|
+
throw new Error('theme manifest is not valid JSON');
|
|
164
|
+
}
|
|
165
|
+
const result = exports.themeManifestSchema.safeParse(parsed);
|
|
166
|
+
if (!result.success) {
|
|
167
|
+
const detail = result.error.issues
|
|
168
|
+
.map((issue) => `${issue.path.join('.') || '(root)'}: ${issue.message}`)
|
|
169
|
+
.join('; ');
|
|
170
|
+
throw new Error(`invalid theme manifest: ${detail}`);
|
|
171
|
+
}
|
|
172
|
+
return result.data;
|
|
173
|
+
}
|
|
174
|
+
//# sourceMappingURL=manifest.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manifest.js","sourceRoot":"","sources":["../src/manifest.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OPTIONAL settings-schema typing helper(s).
|
|
3
|
+
*
|
|
4
|
+
* A theme MAY ship a `settingsSchema` path pointing at a JSON-schema file describing the shape of
|
|
5
|
+
* its tunable settings. That path stays OPAQUE: the core never reads or executes
|
|
6
|
+
* the referenced file at validation time. These helpers are therefore purely COMPILE-TIME
|
|
7
|
+
* ergonomics — they let an author type the settings object their theme expects, with NO runtime
|
|
8
|
+
* behaviour, NO file read, NO code execution. The author's settings shape is their own; the SDK
|
|
9
|
+
* only gives it a name.
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* The settings shape a theme's `settingsSchema` describes — an arbitrary author-defined record.
|
|
13
|
+
* This is the same loose shape the store contract surfaces as {@link ActiveTheme.settings}.
|
|
14
|
+
* Authors may narrow it with their own interface (see {@link defineThemeSettings}).
|
|
15
|
+
*/
|
|
16
|
+
export type ThemeSettings = Record<string, unknown>;
|
|
17
|
+
/**
|
|
18
|
+
* The design-token settings keys the MIT storefront RECOGNISES and maps onto CSS custom properties.
|
|
19
|
+
* Documenting them here gives theme authors editor autocomplete for the supported knobs
|
|
20
|
+
* WITHOUT closing the contract — {@link KnownThemeSettings} intersects this with the open-ended
|
|
21
|
+
* record so arbitrary author keys still type-check. No runtime behaviour: these are pure
|
|
22
|
+
* compile-time ergonomics (the SDK keeps `settings` opaque to the core).
|
|
23
|
+
*
|
|
24
|
+
* Typography values are CSS `font-family` STACKS (e.g. `Georgia, 'Times New Roman', serif`).
|
|
25
|
+
* Per the project's RGPD rule the storefront ships SYSTEM stacks only — no webfont files / Google
|
|
26
|
+
* Fonts / CDN — so these need no asset and are safe by construction.
|
|
27
|
+
*/
|
|
28
|
+
export interface DocumentedThemeSettings {
|
|
29
|
+
/** CSS color string for the page background (→ `--background`). */
|
|
30
|
+
readonly background?: string;
|
|
31
|
+
/** CSS color string for the body text (→ `--foreground`). */
|
|
32
|
+
readonly foreground?: string;
|
|
33
|
+
/** Brand/primary color (→ `--primary`). */
|
|
34
|
+
readonly primary?: string;
|
|
35
|
+
/** Primary hover color (→ `--primary-hover`). */
|
|
36
|
+
readonly primaryHover?: string;
|
|
37
|
+
/** Primary active/pressed color (→ `--primary-active`). */
|
|
38
|
+
readonly primaryActive?: string;
|
|
39
|
+
/** Text/icon color on a primary surface (→ `--primary-foreground`). */
|
|
40
|
+
readonly primaryForeground?: string;
|
|
41
|
+
/** Accent color (→ `--accent`). */
|
|
42
|
+
readonly accent?: string;
|
|
43
|
+
/** Text/icon color on an accent surface (→ `--accent-foreground`). */
|
|
44
|
+
readonly accentForeground?: string;
|
|
45
|
+
/** Focus ring color (→ `--ring`). */
|
|
46
|
+
readonly ring?: string;
|
|
47
|
+
/** CSS length for the corner radius scale (→ `--radius`). */
|
|
48
|
+
readonly radius?: string;
|
|
49
|
+
/** Base sans font-family stack (→ `--font-sans`). System stack — no webfont (RGPD). */
|
|
50
|
+
readonly fontSans?: string;
|
|
51
|
+
/**
|
|
52
|
+
* Heading font-family stack (→ `--font-heading`); override to a serif stack.
|
|
53
|
+
* System stack — no webfont (RGPD).
|
|
54
|
+
*/
|
|
55
|
+
readonly fontHeading?: string;
|
|
56
|
+
/** Absolute http(s) or root-relative logo URL (consumed by the layout, not a CSS var). */
|
|
57
|
+
readonly logoUrl?: string;
|
|
58
|
+
/**
|
|
59
|
+
* Bounded HEADER LAYOUT chrome variant. NOT a CSS var — the storefront reads it to choose
|
|
60
|
+
* between the simple flat nav (`simple`, default) and a multi-column mega-menu (`mega`). An unknown
|
|
61
|
+
* value falls back to `simple`, so the default theme is unchanged.
|
|
62
|
+
*/
|
|
63
|
+
readonly 'header.layout'?: 'simple' | 'mega';
|
|
64
|
+
/**
|
|
65
|
+
* Bounded CART AFFORDANCE chrome variant. NOT a CSS var — the storefront reads it to choose
|
|
66
|
+
* between opening the in-page drawer (`drawer`, default) and a plain link to `/cart` (`page-link`). An
|
|
67
|
+
* unknown value falls back to `drawer`, so the default theme is unchanged.
|
|
68
|
+
*/
|
|
69
|
+
readonly 'cart.affordance'?: 'drawer' | 'page-link';
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* The settings shape with the {@link DocumentedThemeSettings} keys typed for autocomplete while
|
|
73
|
+
* staying open-ended for arbitrary author knobs. Use as the type argument to
|
|
74
|
+
* {@link defineThemeSettings} (e.g. `defineThemeSettings<KnownThemeSettings>({ … })`).
|
|
75
|
+
*/
|
|
76
|
+
export type KnownThemeSettings = DocumentedThemeSettings & ThemeSettings;
|
|
77
|
+
/**
|
|
78
|
+
* Identity helper that simply types-and-returns an author's default settings object. Gives the
|
|
79
|
+
* author editor autocomplete + a single inferred `T` to reuse, while remaining a pure no-op at
|
|
80
|
+
* runtime (it returns its argument unchanged). It does NOT read or validate against the
|
|
81
|
+
* `settingsSchema` file — that path stays opaque.
|
|
82
|
+
*/
|
|
83
|
+
export declare function defineThemeSettings<T extends ThemeSettings>(defaults: T): T;
|
|
84
|
+
//# sourceMappingURL=settings.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"settings.d.ts","sourceRoot":"","sources":["../src/settings.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH;;;;GAIG;AACH,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAEpD;;;;;;;;;;GAUG;AACH,MAAM,WAAW,uBAAuB;IACtC,mEAAmE;IACnE,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,6DAA6D;IAC7D,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,2CAA2C;IAC3C,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,iDAAiD;IACjD,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,2DAA2D;IAC3D,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,uEAAuE;IACvE,QAAQ,CAAC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IACpC,mCAAmC;IACnC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,sEAAsE;IACtE,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IACnC,qCAAqC;IACrC,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,6DAA6D;IAC7D,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,uFAAuF;IACvF,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B;;;OAGG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,0FAA0F;IAC1F,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B;;;;OAIG;IACH,QAAQ,CAAC,eAAe,CAAC,EAAE,QAAQ,GAAG,MAAM,CAAC;IAC7C;;;;OAIG;IACH,QAAQ,CAAC,iBAAiB,CAAC,EAAE,QAAQ,GAAG,WAAW,CAAC;CACrD;AAED;;;;GAIG;AACH,MAAM,MAAM,kBAAkB,GAAG,uBAAuB,GAAG,aAAa,CAAC;AAEzE;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,CAAC,SAAS,aAAa,EAAE,QAAQ,EAAE,CAAC,GAAG,CAAC,CAE3E"}
|
package/dist/settings.js
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* OPTIONAL settings-schema typing helper(s).
|
|
4
|
+
*
|
|
5
|
+
* A theme MAY ship a `settingsSchema` path pointing at a JSON-schema file describing the shape of
|
|
6
|
+
* its tunable settings. That path stays OPAQUE: the core never reads or executes
|
|
7
|
+
* the referenced file at validation time. These helpers are therefore purely COMPILE-TIME
|
|
8
|
+
* ergonomics — they let an author type the settings object their theme expects, with NO runtime
|
|
9
|
+
* behaviour, NO file read, NO code execution. The author's settings shape is their own; the SDK
|
|
10
|
+
* only gives it a name.
|
|
11
|
+
*/
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
exports.defineThemeSettings = defineThemeSettings;
|
|
14
|
+
/**
|
|
15
|
+
* Identity helper that simply types-and-returns an author's default settings object. Gives the
|
|
16
|
+
* author editor autocomplete + a single inferred `T` to reuse, while remaining a pure no-op at
|
|
17
|
+
* runtime (it returns its argument unchanged). It does NOT read or validate against the
|
|
18
|
+
* `settingsSchema` file — that path stays opaque.
|
|
19
|
+
*/
|
|
20
|
+
function defineThemeSettings(defaults) {
|
|
21
|
+
return defaults;
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=settings.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"settings.js","sourceRoot":"","sources":["../src/settings.ts"],"names":[],"mappings":";AAAA;;;;;;;;;GASG;;AA6EH,kDAEC;AARD;;;;;GAKG;AACH,SAAgB,mBAAmB,CAA0B,QAAW;IACtE,OAAO,QAAQ,CAAC;AAClB,CAAC"}
|
package/dist/slots.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validate + return a theme slot-slug array for the manifest. Enforces the SAME rules as
|
|
3
|
+
* `themeManifestSchema`:
|
|
4
|
+
* - each slot is a non-empty lowercase slug (`^[a-z][a-z0-9-]*$`);
|
|
5
|
+
* - no slot slug appears more than once.
|
|
6
|
+
* Throws a clear `Error` on the first violation. Returns a fresh, frozen array.
|
|
7
|
+
*/
|
|
8
|
+
export declare function defineThemeSlots(slots: ReadonlyArray<string>): readonly string[];
|
|
9
|
+
//# sourceMappingURL=slots.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"slots.d.ts","sourceRoot":"","sources":["../src/slots.ts"],"names":[],"mappings":"AAYA;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,aAAa,CAAC,MAAM,CAAC,GAAG,SAAS,MAAM,EAAE,CAmBhF"}
|
package/dist/slots.js
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.defineThemeSlots = defineThemeSlots;
|
|
4
|
+
/**
|
|
5
|
+
* a typed AUTHORING helper for the theme
|
|
6
|
+
* manifest's declarative `slots: string[]` array (the slot slugs a theme exposes/renders).
|
|
7
|
+
*
|
|
8
|
+
* Slots are DECLARATIVE metadata; the slot registry is DERIVED at runtime from enabled MODULES'
|
|
9
|
+
* manifests. This helper is NOT an RPC and there is NO runtime `registerSlot`. It
|
|
10
|
+
* exists purely so a theme author can build a typed, validated list of the slot slugs the theme
|
|
11
|
+
* declares, mirroring the same rules the manifest schema enforces (lowercase slug shape; no
|
|
12
|
+
* duplicate slug). Its output is dropped verbatim into the manifest's `slots`.
|
|
13
|
+
*/
|
|
14
|
+
const manifest_js_1 = require("./manifest.js");
|
|
15
|
+
/**
|
|
16
|
+
* Validate + return a theme slot-slug array for the manifest. Enforces the SAME rules as
|
|
17
|
+
* `themeManifestSchema`:
|
|
18
|
+
* - each slot is a non-empty lowercase slug (`^[a-z][a-z0-9-]*$`);
|
|
19
|
+
* - no slot slug appears more than once.
|
|
20
|
+
* Throws a clear `Error` on the first violation. Returns a fresh, frozen array.
|
|
21
|
+
*/
|
|
22
|
+
function defineThemeSlots(slots) {
|
|
23
|
+
if (!Array.isArray(slots)) {
|
|
24
|
+
throw new TypeError('defineThemeSlots(slots): slots must be an array');
|
|
25
|
+
}
|
|
26
|
+
const seen = new Set();
|
|
27
|
+
const out = [];
|
|
28
|
+
for (const slot of slots) {
|
|
29
|
+
if (typeof slot !== 'string' || !manifest_js_1.SLOT_SLUG_RE.test(slot)) {
|
|
30
|
+
throw new Error(`defineThemeSlots: slot "${String(slot)}" must be a lowercase slug`);
|
|
31
|
+
}
|
|
32
|
+
if (seen.has(slot)) {
|
|
33
|
+
throw new Error(`defineThemeSlots: slot "${slot}" is declared more than once; declare each slot at most once`);
|
|
34
|
+
}
|
|
35
|
+
seen.add(slot);
|
|
36
|
+
out.push(slot);
|
|
37
|
+
}
|
|
38
|
+
return Object.freeze(out);
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=slots.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"slots.js","sourceRoot":"","sources":["../src/slots.ts"],"names":[],"mappings":";;AAmBA,4CAmBC;AAtCD;;;;;;;;;GASG;AACH,+CAA6C;AAE7C;;;;;;GAMG;AACH,SAAgB,gBAAgB,CAAC,KAA4B;IAC3D,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QAC1B,MAAM,IAAI,SAAS,CAAC,iDAAiD,CAAC,CAAC;IACzE,CAAC;IACD,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,CAAC,0BAAY,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YACzD,MAAM,IAAI,KAAK,CAAC,2BAA2B,MAAM,CAAC,IAAI,CAAC,4BAA4B,CAAC,CAAC;QACvF,CAAC;QACD,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YACnB,MAAM,IAAI,KAAK,CACb,2BAA2B,IAAI,8DAA8D,CAC9F,CAAC;QACJ,CAAC;QACD,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACf,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACjB,CAAC;IACD,OAAO,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;AAC5B,CAAC"}
|