@bestagentkits/render 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (140) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/LICENSE +21 -0
  3. package/README.md +166 -0
  4. package/dist/cli.d.ts +18 -0
  5. package/dist/cli.d.ts.map +1 -0
  6. package/dist/cli.js +336 -0
  7. package/dist/cli.js.map +1 -0
  8. package/dist/diagnostics.d.ts +45 -0
  9. package/dist/diagnostics.d.ts.map +1 -0
  10. package/dist/diagnostics.js +57 -0
  11. package/dist/diagnostics.js.map +1 -0
  12. package/dist/diagram/adapter.d.ts +71 -0
  13. package/dist/diagram/adapter.d.ts.map +1 -0
  14. package/dist/diagram/adapter.js +87 -0
  15. package/dist/diagram/adapter.js.map +1 -0
  16. package/dist/errors.d.ts +37 -0
  17. package/dist/errors.d.ts.map +1 -0
  18. package/dist/errors.js +42 -0
  19. package/dist/errors.js.map +1 -0
  20. package/dist/hash.d.ts +14 -0
  21. package/dist/hash.d.ts.map +1 -0
  22. package/dist/hash.js +27 -0
  23. package/dist/hash.js.map +1 -0
  24. package/dist/index.d.ts +43 -0
  25. package/dist/index.d.ts.map +1 -0
  26. package/dist/index.js +25 -0
  27. package/dist/index.js.map +1 -0
  28. package/dist/internal/yaml-error.d.ts +14 -0
  29. package/dist/internal/yaml-error.d.ts.map +1 -0
  30. package/dist/internal/yaml-error.js +12 -0
  31. package/dist/internal/yaml-error.js.map +1 -0
  32. package/dist/ir.d.ts +77 -0
  33. package/dist/ir.d.ts.map +1 -0
  34. package/dist/ir.js +20 -0
  35. package/dist/ir.js.map +1 -0
  36. package/dist/json.d.ts +23 -0
  37. package/dist/json.d.ts.map +1 -0
  38. package/dist/json.js +47 -0
  39. package/dist/json.js.map +1 -0
  40. package/dist/registry/actions.d.ts +48 -0
  41. package/dist/registry/actions.d.ts.map +1 -0
  42. package/dist/registry/actions.js +274 -0
  43. package/dist/registry/actions.js.map +1 -0
  44. package/dist/registry/prop-schema.d.ts +108 -0
  45. package/dist/registry/prop-schema.d.ts.map +1 -0
  46. package/dist/registry/prop-schema.js +400 -0
  47. package/dist/registry/prop-schema.js.map +1 -0
  48. package/dist/registry/registry.d.ts +47 -0
  49. package/dist/registry/registry.d.ts.map +1 -0
  50. package/dist/registry/registry.js +201 -0
  51. package/dist/registry/registry.js.map +1 -0
  52. package/dist/registry/roster.d.ts +53 -0
  53. package/dist/registry/roster.d.ts.map +1 -0
  54. package/dist/registry/roster.js +692 -0
  55. package/dist/registry/roster.js.map +1 -0
  56. package/dist/render/blocks.d.ts +41 -0
  57. package/dist/render/blocks.d.ts.map +1 -0
  58. package/dist/render/blocks.js +749 -0
  59. package/dist/render/blocks.js.map +1 -0
  60. package/dist/render/charts.d.ts +29 -0
  61. package/dist/render/charts.d.ts.map +1 -0
  62. package/dist/render/charts.js +235 -0
  63. package/dist/render/charts.js.map +1 -0
  64. package/dist/render/document.d.ts +40 -0
  65. package/dist/render/document.d.ts.map +1 -0
  66. package/dist/render/document.js +90 -0
  67. package/dist/render/document.js.map +1 -0
  68. package/dist/render/escape.d.ts +46 -0
  69. package/dist/render/escape.d.ts.map +1 -0
  70. package/dist/render/escape.js +108 -0
  71. package/dist/render/escape.js.map +1 -0
  72. package/dist/render/render.d.ts +52 -0
  73. package/dist/render/render.d.ts.map +1 -0
  74. package/dist/render/render.js +216 -0
  75. package/dist/render/render.js.map +1 -0
  76. package/dist/render/runtime.d.ts +25 -0
  77. package/dist/render/runtime.d.ts.map +1 -0
  78. package/dist/render/runtime.js +451 -0
  79. package/dist/render/runtime.js.map +1 -0
  80. package/dist/render/styles.d.ts +15 -0
  81. package/dist/render/styles.d.ts.map +1 -0
  82. package/dist/render/styles.js +163 -0
  83. package/dist/render/styles.js.map +1 -0
  84. package/dist/render/verify.d.ts +25 -0
  85. package/dist/render/verify.d.ts.map +1 -0
  86. package/dist/render/verify.js +168 -0
  87. package/dist/render/verify.js.map +1 -0
  88. package/dist/spec/bindings.d.ts +19 -0
  89. package/dist/spec/bindings.d.ts.map +1 -0
  90. package/dist/spec/bindings.js +51 -0
  91. package/dist/spec/bindings.js.map +1 -0
  92. package/dist/spec/bounds.d.ts +43 -0
  93. package/dist/spec/bounds.d.ts.map +1 -0
  94. package/dist/spec/bounds.js +144 -0
  95. package/dist/spec/bounds.js.map +1 -0
  96. package/dist/spec/forbidden.d.ts +27 -0
  97. package/dist/spec/forbidden.d.ts.map +1 -0
  98. package/dist/spec/forbidden.js +91 -0
  99. package/dist/spec/forbidden.js.map +1 -0
  100. package/dist/spec/migrate.d.ts +33 -0
  101. package/dist/spec/migrate.d.ts.map +1 -0
  102. package/dist/spec/migrate.js +113 -0
  103. package/dist/spec/migrate.js.map +1 -0
  104. package/dist/spec/normalize.d.ts +29 -0
  105. package/dist/spec/normalize.d.ts.map +1 -0
  106. package/dist/spec/normalize.js +649 -0
  107. package/dist/spec/normalize.js.map +1 -0
  108. package/dist/spec/parse.d.ts +22 -0
  109. package/dist/spec/parse.d.ts.map +1 -0
  110. package/dist/spec/parse.js +62 -0
  111. package/dist/spec/parse.js.map +1 -0
  112. package/dist/spec/providers.d.ts +30 -0
  113. package/dist/spec/providers.d.ts.map +1 -0
  114. package/dist/spec/providers.js +64 -0
  115. package/dist/spec/providers.js.map +1 -0
  116. package/dist/spec/validate.d.ts +28 -0
  117. package/dist/spec/validate.d.ts.map +1 -0
  118. package/dist/spec/validate.js +68 -0
  119. package/dist/spec/validate.js.map +1 -0
  120. package/dist/theme/load-theme.d.ts +55 -0
  121. package/dist/theme/load-theme.d.ts.map +1 -0
  122. package/dist/theme/load-theme.js +219 -0
  123. package/dist/theme/load-theme.js.map +1 -0
  124. package/dist/theme/presets.d.ts +50 -0
  125. package/dist/theme/presets.d.ts.map +1 -0
  126. package/dist/theme/presets.js +304 -0
  127. package/dist/theme/presets.js.map +1 -0
  128. package/dist/theme/theme-catalog.d.ts +68 -0
  129. package/dist/theme/theme-catalog.d.ts.map +1 -0
  130. package/dist/theme/theme-catalog.js +198 -0
  131. package/dist/theme/theme-catalog.js.map +1 -0
  132. package/dist/theme/tokens.d.ts +38 -0
  133. package/dist/theme/tokens.d.ts.map +1 -0
  134. package/dist/theme/tokens.js +190 -0
  135. package/dist/theme/tokens.js.map +1 -0
  136. package/dist/version.d.ts +12 -0
  137. package/dist/version.d.ts.map +1 -0
  138. package/dist/version.js +12 -0
  139. package/dist/version.js.map +1 -0
  140. package/package.json +80 -0
@@ -0,0 +1,144 @@
1
+ /**
2
+ * Input bounds.
3
+ *
4
+ * Bounds are checked before schema validation so an absurd document fails fast
5
+ * and cheaply. Every limit is application-level and deliberately far below any
6
+ * platform limit, because the same code runs in a CLI, in a library caller, and
7
+ * inside a worker with a bounded memory budget and a request-size ceiling.
8
+ */
9
+ import { pathIndex, pathKey } from '../diagnostics.js';
10
+ import { isPlainObject } from '../json.js';
11
+ export const LIMITS = {
12
+ /** Nesting depth of the raw document, root included. */
13
+ maxDepth: 24,
14
+ /** Entries in any `blocks` array, and total authored blocks. */
15
+ maxBlocks: 200,
16
+ /** Objects in the document, anywhere (props objects and list items included). */
17
+ maxNodes: 20_000,
18
+ /** Serialized size of the whole document. */
19
+ maxSerializedBytes: 1_000_000,
20
+ /** Items in any single list. */
21
+ maxListItems: 200,
22
+ /** Keys in an open-keyed map such as `state`. */
23
+ maxMapKeys: 200,
24
+ /** Length of a single-line string. */
25
+ maxStringLength: 2_000,
26
+ /** Length of multiline text. */
27
+ maxTextLength: 50_000,
28
+ };
29
+ function walk(value, path, depth, state) {
30
+ if (depth > state.depth)
31
+ state.depth = depth;
32
+ if (depth > LIMITS.maxDepth && !state.overflowed.depth) {
33
+ state.overflowed.depth = true;
34
+ state.bag.add({
35
+ code: 'SPEC_BOUNDS_ERROR',
36
+ path,
37
+ message: `document nests ${depth} levels deep, limit is ${LIMITS.maxDepth}`,
38
+ });
39
+ return;
40
+ }
41
+ if (typeof value === 'string') {
42
+ if (value.length > state.longestString)
43
+ state.longestString = value.length;
44
+ return;
45
+ }
46
+ if (value === null || typeof value !== 'object')
47
+ return;
48
+ if (Array.isArray(value)) {
49
+ if (value.length > state.largestList)
50
+ state.largestList = value.length;
51
+ if (value.length > LIMITS.maxListItems) {
52
+ state.bag.add({
53
+ code: 'SPEC_BOUNDS_ERROR',
54
+ path,
55
+ message: `list has ${value.length} items, limit is ${LIMITS.maxListItems}`,
56
+ });
57
+ }
58
+ for (let index = 0; index < value.length; index += 1) {
59
+ walk(value[index], pathIndex(path, index), depth + 1, state);
60
+ }
61
+ return;
62
+ }
63
+ if (!isPlainObject(value))
64
+ return;
65
+ state.nodes += 1;
66
+ if (state.nodes > LIMITS.maxNodes && !state.overflowed.nodes) {
67
+ state.overflowed.nodes = true;
68
+ state.bag.add({
69
+ code: 'SPEC_BOUNDS_ERROR',
70
+ path,
71
+ message: `document has more than ${LIMITS.maxNodes} objects`,
72
+ });
73
+ return;
74
+ }
75
+ for (const [key, child] of Object.entries(value)) {
76
+ const childPath = pathKey(path, key);
77
+ if (key === 'blocks' && Array.isArray(child)) {
78
+ state.blocks += child.length;
79
+ if (state.blocks > LIMITS.maxBlocks && !state.overflowed.blocks) {
80
+ state.overflowed.blocks = true;
81
+ state.bag.add({
82
+ code: 'SPEC_BOUNDS_ERROR',
83
+ path: childPath,
84
+ message: `document declares more than ${LIMITS.maxBlocks} blocks`,
85
+ });
86
+ }
87
+ if (child.length > LIMITS.maxBlocks) {
88
+ state.bag.add({
89
+ code: 'SPEC_BOUNDS_ERROR',
90
+ path: childPath,
91
+ message: `blocks array has ${child.length} entries, limit is ${LIMITS.maxBlocks}`,
92
+ });
93
+ }
94
+ }
95
+ walk(child, childPath, depth + 1, state);
96
+ }
97
+ }
98
+ /**
99
+ * Measure a raw document and report every exceeded bound.
100
+ *
101
+ * The walk is bounded even when the input is not: exceeding a limit stops
102
+ * descending at that branch instead of continuing to allocate diagnostics.
103
+ */
104
+ export function checkBounds(value, bag) {
105
+ const state = {
106
+ blocks: 0,
107
+ nodes: 0,
108
+ depth: 0,
109
+ bytes: 0,
110
+ longestString: 0,
111
+ largestList: 0,
112
+ bag,
113
+ overflowed: { depth: false, blocks: false, nodes: false },
114
+ };
115
+ let serialized = '';
116
+ try {
117
+ serialized = JSON.stringify(value) ?? '';
118
+ }
119
+ catch {
120
+ bag.add({
121
+ code: 'SPEC_BOUNDS_ERROR',
122
+ path: '$',
123
+ message: 'document is not JSON-serializable',
124
+ });
125
+ }
126
+ state.bytes = serialized.length;
127
+ if (state.bytes > LIMITS.maxSerializedBytes) {
128
+ bag.add({
129
+ code: 'SPEC_BOUNDS_ERROR',
130
+ path: '$',
131
+ message: `document is ${state.bytes} bytes serialized, limit is ${LIMITS.maxSerializedBytes}`,
132
+ });
133
+ }
134
+ walk(value, '$', 1, state);
135
+ return {
136
+ blocks: state.blocks,
137
+ nodes: state.nodes,
138
+ depth: state.depth,
139
+ bytes: state.bytes,
140
+ longestString: state.longestString,
141
+ largestList: state.largestList,
142
+ };
143
+ }
144
+ //# sourceMappingURL=bounds.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bounds.js","sourceRoot":"","sources":["../../src/spec/bounds.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Forbidden-key scan.
3
+ *
4
+ * Two independent things must be true for the trust boundary to hold: an
5
+ * author must not be able to smuggle executable or presentational-script
6
+ * content into a spec through a property name, and a typo must not silently
7
+ * become a no-op. This scan runs before schema validation so the failure is
8
+ * reported as a policy violation with the exact path, not as an
9
+ * unknown-property error that a reader might "fix" by adding the key to a
10
+ * schema.
11
+ */
12
+ import { type DiagnosticBag } from '../diagnostics.js';
13
+ /**
14
+ * Keys that must never appear anywhere in a Page Spec.
15
+ *
16
+ * `style` is included deliberately: a spec cannot carry CSS, and a theme is
17
+ * typed token data rather than a stylesheet escape hatch.
18
+ */
19
+ export declare const FORBIDDEN_KEYS: readonly string[];
20
+ /**
21
+ * Walk the raw document and report every forbidden key.
22
+ *
23
+ * `elements` is a permitted key name: HTML template content lives in compiler
24
+ * code, never in a spec.
25
+ */
26
+ export declare function scanForbiddenKeys(value: unknown, bag: DiagnosticBag): void;
27
+ //# sourceMappingURL=forbidden.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"forbidden.d.ts","sourceRoot":"","sources":["../../src/spec/forbidden.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,KAAK,aAAa,EAAsB,MAAM,mBAAmB,CAAC;AAG3E;;;;;GAKG;AACH,eAAO,MAAM,cAAc,EAAE,SAAS,MAAM,EAqB3C,CAAC;AAeF;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,aAAa,GAAG,IAAI,CAgC1E"}
@@ -0,0 +1,91 @@
1
+ /**
2
+ * Forbidden-key scan.
3
+ *
4
+ * Two independent things must be true for the trust boundary to hold: an
5
+ * author must not be able to smuggle executable or presentational-script
6
+ * content into a spec through a property name, and a typo must not silently
7
+ * become a no-op. This scan runs before schema validation so the failure is
8
+ * reported as a policy violation with the exact path, not as an
9
+ * unknown-property error that a reader might "fix" by adding the key to a
10
+ * schema.
11
+ */
12
+ import { pathIndex, pathKey } from '../diagnostics.js';
13
+ import { isPlainObject } from '../json.js';
14
+ /**
15
+ * Keys that must never appear anywhere in a Page Spec.
16
+ *
17
+ * `style` is included deliberately: a spec cannot carry CSS, and a theme is
18
+ * typed token data rather than a stylesheet escape hatch.
19
+ */
20
+ export const FORBIDDEN_KEYS = [
21
+ 'html',
22
+ 'rawhtml',
23
+ 'innerhtml',
24
+ 'outerhtml',
25
+ 'srcdoc',
26
+ 'css',
27
+ 'stylesheet',
28
+ 'style',
29
+ 'script',
30
+ 'javascript',
31
+ 'js',
32
+ 'eval',
33
+ 'expression',
34
+ 'handler',
35
+ 'iframe',
36
+ 'embed',
37
+ 'object',
38
+ 'formaction',
39
+ 'dangerouslysetinnerhtml',
40
+ 'template',
41
+ ];
42
+ /** Snake-case and kebab-case event-handler attributes. */
43
+ const HANDLER_KEY = /^(onclick|onchange|oninput|onsubmit|onload|onerror|onfocus|onblur|onkeydown|onkeyup|onkeypress|onmouseover|onmouseout|onmousedown|onmouseup|ondblclick|oncontextmenu|onscroll|onwheel|ontoggle|onanimationstart|ontransitionend|onpointerdown|onpointerup)$/i;
44
+ /** Camel-case handler properties (`onClick`, `onError`, ...). `on` itself is allowed. */
45
+ const CAMEL_HANDLER_KEY = /^on[A-Z]/;
46
+ function isForbiddenKey(key) {
47
+ if (FORBIDDEN_KEYS.includes(key.toLowerCase()))
48
+ return true;
49
+ if (key === 'on')
50
+ return false;
51
+ return HANDLER_KEY.test(key) || CAMEL_HANDLER_KEY.test(key);
52
+ }
53
+ /**
54
+ * Walk the raw document and report every forbidden key.
55
+ *
56
+ * `elements` is a permitted key name: HTML template content lives in compiler
57
+ * code, never in a spec.
58
+ */
59
+ export function scanForbiddenKeys(value, bag) {
60
+ const seen = new Set();
61
+ const visit = (node, path) => {
62
+ if (node === null || typeof node !== 'object')
63
+ return;
64
+ if (seen.has(node))
65
+ return;
66
+ seen.add(node);
67
+ if (Array.isArray(node)) {
68
+ for (let index = 0; index < node.length; index += 1) {
69
+ visit(node[index], pathIndex(path, index));
70
+ }
71
+ return;
72
+ }
73
+ if (!isPlainObject(node))
74
+ return;
75
+ for (const [key, child] of Object.entries(node)) {
76
+ const childPath = pathKey(path, key);
77
+ if (isForbiddenKey(key)) {
78
+ bag.add({
79
+ code: 'POLICY_VIOLATION',
80
+ path: childPath,
81
+ message: `"${key}" is not accepted in a Page Spec: presentation and behavior belong to the compiler`,
82
+ details: { key },
83
+ });
84
+ continue;
85
+ }
86
+ visit(child, childPath);
87
+ }
88
+ };
89
+ visit(value, '$');
90
+ }
91
+ //# sourceMappingURL=forbidden.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"forbidden.js","sourceRoot":"","sources":["../../src/spec/forbidden.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAsB,SAAS,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAC3E,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE3C;;;;;GAKG;AACH,MAAM,CAAC,MAAM,cAAc,GAAsB;IAC/C,MAAM;IACN,SAAS;IACT,WAAW;IACX,WAAW;IACX,QAAQ;IACR,KAAK;IACL,YAAY;IACZ,OAAO;IACP,QAAQ;IACR,YAAY;IACZ,IAAI;IACJ,MAAM;IACN,YAAY;IACZ,SAAS;IACT,QAAQ;IACR,OAAO;IACP,QAAQ;IACR,YAAY;IACZ,yBAAyB;IACzB,UAAU;CACX,CAAC;AAEF,0DAA0D;AAC1D,MAAM,WAAW,GACf,8PAA8P,CAAC;AAEjQ,yFAAyF;AACzF,MAAM,iBAAiB,GAAG,UAAU,CAAC;AAErC,SAAS,cAAc,CAAC,GAAW;IACjC,IAAI,cAAc,CAAC,QAAQ,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC;QAAE,OAAO,IAAI,CAAC;IAC5D,IAAI,GAAG,KAAK,IAAI;QAAE,OAAO,KAAK,CAAC;IAC/B,OAAO,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,iBAAiB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC9D,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAAC,KAAc,EAAE,GAAkB;IAClE,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAE/B,MAAM,KAAK,GAAG,CAAC,IAAa,EAAE,IAAY,EAAQ,EAAE;QAClD,IAAI,IAAI,KAAK,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ;YAAE,OAAO;QACtD,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC;YAAE,OAAO;QAC3B,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAEf,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;YACxB,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,IAAI,CAAC,MAAM,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;gBACpD,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,SAAS,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC;YAC7C,CAAC;YACD,OAAO;QACT,CAAC;QACD,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC;YAAE,OAAO;QAEjC,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;YAChD,MAAM,SAAS,GAAG,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;YACrC,IAAI,cAAc,CAAC,GAAG,CAAC,EAAE,CAAC;gBACxB,GAAG,CAAC,GAAG,CAAC;oBACN,IAAI,EAAE,kBAAkB;oBACxB,IAAI,EAAE,SAAS;oBACf,OAAO,EAAE,IAAI,GAAG,oFAAoF;oBACpG,OAAO,EAAE,EAAE,GAAG,EAAE;iBACjB,CAAC,CAAC;gBACH,SAAS;YACX,CAAC;YACD,KAAK,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;QAC1B,CAAC;IACH,CAAC,CAAC;IAEF,KAAK,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;AACpB,CAAC"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Schema versioning and migrations.
3
+ *
4
+ * A Page Spec declares its own `version`, independent of the package version.
5
+ * Older supported versions are upgraded in memory before validation, so a
6
+ * document that was valid when it was written keeps working. Removing a
7
+ * supported version is a major release; see `docs/release-policy.md`.
8
+ */
9
+ import type { DiagnosticBag } from '../diagnostics.js';
10
+ export declare const CURRENT_SPEC_VERSION = 1;
11
+ export interface Migration {
12
+ from: number;
13
+ to: number;
14
+ description: string;
15
+ apply(document: Record<string, unknown>): Record<string, unknown>;
16
+ }
17
+ export declare const MIGRATIONS: readonly Migration[];
18
+ export declare function supportedVersions(): number[];
19
+ /** The declared version, or 0 for the pre-versioning shape, or undefined. */
20
+ export declare function detectSpecVersion(document: unknown): number | undefined;
21
+ export interface MigrationResult {
22
+ document: Record<string, unknown>;
23
+ /** Version the document was written in, before any migration. */
24
+ originalVersion: number;
25
+ applied: string[];
26
+ }
27
+ /**
28
+ * Detect, validate, and apply migrations. Returns the document in the current
29
+ * schema version. Reports diagnostics instead of throwing so `validate()` can
30
+ * surface every problem at once.
31
+ */
32
+ export declare function migrateSpec(document: unknown, bag: DiagnosticBag): MigrationResult | undefined;
33
+ //# sourceMappingURL=migrate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migrate.d.ts","sourceRoot":"","sources":["../../src/spec/migrate.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAIvD,eAAO,MAAM,oBAAoB,IAAsB,CAAC;AAExD,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnE;AAwBD,eAAO,MAAM,UAAU,EAAE,SAAS,SAAS,EAAqB,CAAC;AAEjE,wBAAgB,iBAAiB,IAAI,MAAM,EAAE,CAE5C;AAED,6EAA6E;AAC7E,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAQvE;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,iEAAiE;IACjE,eAAe,EAAE,MAAM,CAAC;IACxB,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,EAAE,aAAa,GAAG,eAAe,GAAG,SAAS,CA8D9F"}
@@ -0,0 +1,113 @@
1
+ /**
2
+ * Schema versioning and migrations.
3
+ *
4
+ * A Page Spec declares its own `version`, independent of the package version.
5
+ * Older supported versions are upgraded in memory before validation, so a
6
+ * document that was valid when it was written keeps working. Removing a
7
+ * supported version is a major release; see `docs/release-policy.md`.
8
+ */
9
+ import { isPlainObject } from '../json.js';
10
+ import { SPEC_SCHEMA_VERSION } from '../registry/registry.js';
11
+ export const CURRENT_SPEC_VERSION = SPEC_SCHEMA_VERSION;
12
+ /**
13
+ * Version 0 is the pre-versioning authoring shape: a bare `blocks` array (or a
14
+ * document whose only meaningful key is `blocks`). The migration adds the
15
+ * envelope so v1 validation and normalization have one shape to handle.
16
+ */
17
+ const VERSION_0_TO_1 = {
18
+ from: 0,
19
+ to: 1,
20
+ description: 'Wrap a bare block document in the v1 envelope: adds version, meta, theme, and policy defaults.',
21
+ apply(document) {
22
+ const blocks = Array.isArray(document) ? document : (document.blocks ?? []);
23
+ return {
24
+ version: 1,
25
+ meta: { title: 'Untitled page', locale: 'en' },
26
+ theme: { preset: 'editorial' },
27
+ policy: { network: 'deny' },
28
+ blocks,
29
+ };
30
+ },
31
+ };
32
+ export const MIGRATIONS = [VERSION_0_TO_1];
33
+ export function supportedVersions() {
34
+ return [0, CURRENT_SPEC_VERSION];
35
+ }
36
+ /** The declared version, or 0 for the pre-versioning shape, or undefined. */
37
+ export function detectSpecVersion(document) {
38
+ if (Array.isArray(document))
39
+ return 0;
40
+ if (!isPlainObject(document))
41
+ return undefined;
42
+ const declared = document.version;
43
+ if (typeof declared === 'number')
44
+ return declared;
45
+ if (declared !== undefined)
46
+ return Number.NaN;
47
+ if (Array.isArray(document.blocks))
48
+ return 0;
49
+ return undefined;
50
+ }
51
+ /**
52
+ * Detect, validate, and apply migrations. Returns the document in the current
53
+ * schema version. Reports diagnostics instead of throwing so `validate()` can
54
+ * surface every problem at once.
55
+ */
56
+ export function migrateSpec(document, bag) {
57
+ if (!Array.isArray(document) && !isPlainObject(document)) {
58
+ bag.add({
59
+ code: 'SPEC_VALIDATION_ERROR',
60
+ path: '$',
61
+ message: 'expected a Page Spec object or a block array',
62
+ });
63
+ return undefined;
64
+ }
65
+ const detected = detectSpecVersion(document);
66
+ if (detected === undefined || Number.isNaN(detected)) {
67
+ bag.add({
68
+ code: 'SPEC_VALIDATION_ERROR',
69
+ path: '$.version',
70
+ message: `"version" must be a number; supported versions are ${supportedVersions().join(', ')}`,
71
+ details: { supported: supportedVersions() },
72
+ });
73
+ return undefined;
74
+ }
75
+ if (!Number.isInteger(detected) || detected < 0) {
76
+ bag.add({
77
+ code: 'SPEC_VALIDATION_ERROR',
78
+ path: '$.version',
79
+ message: `"${String(detected)}" is not a supported schema version`,
80
+ details: { supported: supportedVersions() },
81
+ });
82
+ return undefined;
83
+ }
84
+ if (detected > CURRENT_SPEC_VERSION) {
85
+ bag.add({
86
+ code: 'SPEC_VALIDATION_ERROR',
87
+ path: '$.version',
88
+ message: `schema version ${detected} is newer than this compiler supports (${CURRENT_SPEC_VERSION})`,
89
+ details: { supported: supportedVersions(), documentVersion: detected },
90
+ });
91
+ return undefined;
92
+ }
93
+ let current = Array.isArray(document) ? { blocks: [...document] } : { ...document };
94
+ const applied = [];
95
+ let version = detected;
96
+ while (version < CURRENT_SPEC_VERSION) {
97
+ const migration = MIGRATIONS.find((candidate) => candidate.from === version);
98
+ if (migration === undefined) {
99
+ bag.add({
100
+ code: 'SPEC_VALIDATION_ERROR',
101
+ path: '$.version',
102
+ message: `no migration path from schema version ${version}`,
103
+ details: { supported: supportedVersions() },
104
+ });
105
+ return undefined;
106
+ }
107
+ current = migration.apply(current);
108
+ applied.push(`v${migration.from}->v${migration.to}`);
109
+ version = migration.to;
110
+ }
111
+ return { document: current, originalVersion: detected, applied };
112
+ }
113
+ //# sourceMappingURL=migrate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migrate.js","sourceRoot":"","sources":["../../src/spec/migrate.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Normalizer: nested authoring Page Spec -> flat internal IR.
3
+ *
4
+ * The author-facing shape is optimized for authoring (nested, tolerant of
5
+ * omission, semantic). The IR is optimized for the compiler (flat, ordered,
6
+ * every node resolved). This module owns the crossing between them, including
7
+ * stable node IDs, slot wiring, and the cross-field checks that a per-prop
8
+ * schema cannot express.
9
+ */
10
+ import { type Diagnostic } from '../diagnostics.js';
11
+ import type { IrDocument } from '../ir.js';
12
+ import { type BoundsReport } from './bounds.js';
13
+ import { type ParseOptions } from './parse.js';
14
+ export interface NormalizeResult {
15
+ ir: IrDocument;
16
+ diagnostics: Diagnostic[];
17
+ bounds: BoundsReport;
18
+ }
19
+ export declare const NETWORK_CAPABILITIES: readonly ["media", "fonts", "images"];
20
+ /** Build the IR without throwing: diagnostics are returned, not raised. */
21
+ export declare function normalizeSpec(input: unknown, options?: ParseOptions): NormalizeResult;
22
+ /**
23
+ * Normalize or throw.
24
+ *
25
+ * The thrown error carries the first error's code and path, and lists every
26
+ * diagnostic in `details.diagnostics` so a caller can render a full report.
27
+ */
28
+ export declare function normalize(input: unknown, options?: ParseOptions): IrDocument;
29
+ //# sourceMappingURL=normalize.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"normalize.d.ts","sourceRoot":"","sources":["../../src/spec/normalize.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,KAAK,UAAU,EAAqC,MAAM,mBAAmB,CAAC;AAGvF,OAAO,KAAK,EAAE,UAAU,EAAmB,MAAM,UAAU,CAAC;AAO5D,OAAO,EAAE,KAAK,YAAY,EAAe,MAAM,aAAa,CAAC;AAG7D,OAAO,EAAE,KAAK,YAAY,EAAa,MAAM,YAAY,CAAC;AAG1D,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,UAAU,CAAC;IACf,WAAW,EAAE,UAAU,EAAE,CAAC;IAC1B,MAAM,EAAE,YAAY,CAAC;CACtB;AAKD,eAAO,MAAM,oBAAoB,uCAAwC,CAAC;AAikB1E,2EAA2E;AAC3E,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,GAAE,YAAiB,GAAG,eAAe,CA+EzF;AAqBD;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,GAAE,YAAiB,GAAG,UAAU,CAchF"}