@metamesh/generator-sdk 0.5.2 → 0.6.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.
- package/CHANGELOG.md +6 -0
- package/README.md +146 -149
- package/dist/authoring.d.ts +57 -0
- package/dist/authoring.d.ts.map +1 -0
- package/dist/authoring.js +33 -0
- package/dist/authoring.js.map +1 -0
- package/dist/contracts.d.ts +31 -99
- package/dist/contracts.d.ts.map +1 -1
- package/dist/execute-generator.d.ts +22 -28
- package/dist/execute-generator.d.ts.map +1 -1
- package/dist/execute-generator.js +27 -32
- package/dist/execute-generator.js.map +1 -1
- package/dist/generated-parts.d.ts +1 -2
- package/dist/generated-parts.d.ts.map +1 -1
- package/dist/generated-parts.js +7 -31
- package/dist/generated-parts.js.map +1 -1
- package/dist/generator-module.d.ts +18 -40
- package/dist/generator-module.d.ts.map +1 -1
- package/dist/generator-module.js +4 -111
- package/dist/generator-module.js.map +1 -1
- package/dist/generator-package/constants.d.ts +2 -2
- package/dist/generator-package/constants.js +2 -2
- package/dist/generator-package/schemas/definition.schema.d.ts +3 -0
- package/dist/generator-package/schemas/definition.schema.d.ts.map +1 -1
- package/dist/generator-package/schemas/manifest.schema.d.ts +5 -8422
- package/dist/generator-package/schemas/manifest.schema.d.ts.map +1 -1
- package/dist/generator-package/schemas/parameter.schema.d.ts +7 -0
- package/dist/generator-package/schemas/parameter.schema.d.ts.map +1 -1
- package/dist/generator-package/schemas/parameter.schema.js +2 -0
- package/dist/generator-package/schemas/parameter.schema.js.map +1 -1
- package/dist/generator-package/schemas/preset.schema.d.ts +2 -13
- package/dist/generator-package/schemas/preset.schema.d.ts.map +1 -1
- package/dist/generator-package/schemas/preset.schema.js.map +1 -1
- package/dist/generator-package/validate-definition.d.ts.map +1 -1
- package/dist/generator-package/validate-definition.js +18 -0
- package/dist/generator-package/validate-definition.js.map +1 -1
- package/dist/generator-package/validate-manifest.d.ts.map +1 -1
- package/dist/generator-package/validate-manifest.js +2 -13
- package/dist/generator-package/validate-manifest.js.map +1 -1
- package/dist/generator-services.d.ts +1 -1
- package/dist/generator-services.d.ts.map +1 -1
- package/dist/index.d.ts +8 -15
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -6
- package/dist/index.js.map +1 -1
- package/dist/parameter-contracts.d.ts +121 -0
- package/dist/parameter-contracts.d.ts.map +1 -0
- package/dist/parameter-contracts.js +2 -0
- package/dist/parameter-contracts.js.map +1 -0
- package/dist/parameters/issues.d.ts +14 -0
- package/dist/parameters/issues.d.ts.map +1 -0
- package/dist/parameters/issues.js +262 -0
- package/dist/parameters/issues.js.map +1 -0
- package/dist/parameters/preparation.d.ts +13 -0
- package/dist/parameters/preparation.d.ts.map +1 -0
- package/dist/parameters/preparation.js +35 -0
- package/dist/parameters/preparation.js.map +1 -0
- package/dist/parameters/recovery.d.ts +10 -0
- package/dist/parameters/recovery.d.ts.map +1 -0
- package/dist/parameters/recovery.js +124 -0
- package/dist/parameters/recovery.js.map +1 -0
- package/dist/parameters/strict.d.ts +30 -0
- package/dist/parameters/strict.d.ts.map +1 -0
- package/dist/parameters/strict.js +116 -0
- package/dist/parameters/strict.js.map +1 -0
- package/dist/parameters/values.d.ts +13 -0
- package/dist/parameters/values.d.ts.map +1 -0
- package/dist/parameters/values.js +73 -0
- package/dist/parameters/values.js.map +1 -0
- package/dist/parameters.d.ts +7 -69
- package/dist/parameters.d.ts.map +1 -1
- package/dist/parameters.js +5 -592
- package/dist/parameters.js.map +1 -1
- package/dist/parse-generator-module.d.ts +29 -0
- package/dist/parse-generator-module.d.ts.map +1 -0
- package/dist/parse-generator-module.js +137 -0
- package/dist/parse-generator-module.js.map +1 -0
- package/dist/runtime.d.ts +10 -0
- package/dist/runtime.d.ts.map +1 -0
- package/dist/runtime.js +5 -0
- package/dist/runtime.js.map +1 -0
- package/dist/worker-contracts.d.ts +80 -0
- package/dist/worker-contracts.d.ts.map +1 -0
- package/dist/worker-contracts.js +12 -0
- package/dist/worker-contracts.js.map +1 -0
- package/package.json +14 -1
- package/dist/prepared-generator-module.d.ts +0 -24
- package/dist/prepared-generator-module.d.ts.map +0 -1
- package/dist/prepared-generator-module.js +0 -124
- package/dist/prepared-generator-module.js.map +0 -1
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
import { isFontSelection } from "../fonts.js";
|
|
2
|
+
import { MAX_ARRAY_ITEMS, MAX_METADATA_TEXT_LENGTH, MAX_PARAMETER_OPTIONS, MAX_TEXT_PARAMETER_LENGTH, } from "../generator-package/constants.js";
|
|
3
|
+
import { isProfileValue } from "../profiles.js";
|
|
4
|
+
import { HEX_COLOR_PATTERN, isRecord, readDenseArray, svgValueFits } from "./values.js";
|
|
5
|
+
export const MAX_PARAMETER_ISSUES = 100;
|
|
6
|
+
export const MAX_PARAMETER_ISSUE_MESSAGE_LENGTH = 1_000;
|
|
7
|
+
function issue(parameterId, message) {
|
|
8
|
+
return { severity: "error", parameterId, message };
|
|
9
|
+
}
|
|
10
|
+
export function validateDefinitionValue(parameter, value) {
|
|
11
|
+
switch (parameter.type) {
|
|
12
|
+
case "profile":
|
|
13
|
+
return isProfileValue(value)
|
|
14
|
+
? []
|
|
15
|
+
: [issue(parameter.id, `${parameter.label} must be a bounded, normalized side outline.`)];
|
|
16
|
+
case "font":
|
|
17
|
+
return isFontSelection(value)
|
|
18
|
+
? []
|
|
19
|
+
: [issue(parameter.id, `${parameter.label} must be an immutable font selection.`)];
|
|
20
|
+
case "number":
|
|
21
|
+
case "slider": {
|
|
22
|
+
if (typeof value !== "number" || !Number.isFinite(value)) {
|
|
23
|
+
return [issue(parameter.id, `${parameter.label} must be a finite number.`)];
|
|
24
|
+
}
|
|
25
|
+
const issues = [];
|
|
26
|
+
if (parameter.integer && !Number.isInteger(value)) {
|
|
27
|
+
issues.push(issue(parameter.id, `${parameter.label} must be an integer.`));
|
|
28
|
+
}
|
|
29
|
+
if (parameter.min !== undefined && value < parameter.min) {
|
|
30
|
+
issues.push(issue(parameter.id, `${parameter.label} must be at least ${parameter.min}.`));
|
|
31
|
+
}
|
|
32
|
+
if (parameter.max !== undefined && value > parameter.max) {
|
|
33
|
+
issues.push(issue(parameter.id, `${parameter.label} must be at most ${parameter.max}.`));
|
|
34
|
+
}
|
|
35
|
+
return issues;
|
|
36
|
+
}
|
|
37
|
+
case "boolean":
|
|
38
|
+
return typeof value === "boolean"
|
|
39
|
+
? []
|
|
40
|
+
: [issue(parameter.id, `${parameter.label} must be true or false.`)];
|
|
41
|
+
case "select":
|
|
42
|
+
return typeof value === "string" && parameter.options.some((option) => option.value === value)
|
|
43
|
+
? []
|
|
44
|
+
: [issue(parameter.id, `${parameter.label} must be one of its available options.`)];
|
|
45
|
+
case "choice-set": {
|
|
46
|
+
if (!Array.isArray(value)) {
|
|
47
|
+
return [issue(parameter.id, `${parameter.label} must be a list of available choices.`)];
|
|
48
|
+
}
|
|
49
|
+
const issues = [];
|
|
50
|
+
if (value.length > MAX_PARAMETER_OPTIONS) {
|
|
51
|
+
issues.push(issue(parameter.id, `${parameter.label} must include at most ${MAX_PARAMETER_OPTIONS} choices.`));
|
|
52
|
+
return issues;
|
|
53
|
+
}
|
|
54
|
+
const entries = readDenseArray(value, MAX_PARAMETER_OPTIONS);
|
|
55
|
+
if (entries === undefined) {
|
|
56
|
+
issues.push(issue(parameter.id, `${parameter.label} must be a dense list of data values.`));
|
|
57
|
+
return issues;
|
|
58
|
+
}
|
|
59
|
+
const knownValues = new Set(parameter.options.map((option) => option.value));
|
|
60
|
+
const seen = new Set();
|
|
61
|
+
const inspectedLength = Math.min(entries.length, MAX_PARAMETER_OPTIONS);
|
|
62
|
+
for (let index = 0; index < inspectedLength; index += 1) {
|
|
63
|
+
if (issues.length === MAX_PARAMETER_ISSUES)
|
|
64
|
+
break;
|
|
65
|
+
const entry = entries[index];
|
|
66
|
+
if (typeof entry !== "string" || !knownValues.has(entry)) {
|
|
67
|
+
issues.push(issue(parameter.id, `${parameter.label} choice ${index + 1} must be available.`));
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
if (seen.has(entry)) {
|
|
71
|
+
issues.push(issue(parameter.id, `${parameter.label} choices must be unique.`));
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
seen.add(entry);
|
|
75
|
+
}
|
|
76
|
+
if (parameter.minSelections !== undefined && entries.length < parameter.minSelections) {
|
|
77
|
+
issues.push(issue(parameter.id, `${parameter.label} must include at least ${parameter.minSelections} choices.`));
|
|
78
|
+
}
|
|
79
|
+
if (parameter.maxSelections !== undefined && entries.length > parameter.maxSelections) {
|
|
80
|
+
issues.push(issue(parameter.id, `${parameter.label} must include at most ${parameter.maxSelections} choices.`));
|
|
81
|
+
}
|
|
82
|
+
return issues;
|
|
83
|
+
}
|
|
84
|
+
case "color":
|
|
85
|
+
return typeof value === "string" && HEX_COLOR_PATTERN.test(value)
|
|
86
|
+
? []
|
|
87
|
+
: [issue(parameter.id, `${parameter.label} must be a six-digit hex color.`)];
|
|
88
|
+
case "text":
|
|
89
|
+
if (typeof value !== "string") {
|
|
90
|
+
return [issue(parameter.id, `${parameter.label} must be text.`)];
|
|
91
|
+
}
|
|
92
|
+
return value.length <= MAX_TEXT_PARAMETER_LENGTH
|
|
93
|
+
? []
|
|
94
|
+
: [
|
|
95
|
+
issue(parameter.id, `${parameter.label} must contain at most ${MAX_TEXT_PARAMETER_LENGTH} characters.`),
|
|
96
|
+
];
|
|
97
|
+
case "svg":
|
|
98
|
+
if (typeof value !== "string")
|
|
99
|
+
return [issue(parameter.id, `${parameter.label} must be SVG text.`)];
|
|
100
|
+
return svgValueFits(value)
|
|
101
|
+
? []
|
|
102
|
+
: [issue(parameter.id, `${parameter.label} must be 256 KiB or smaller.`)];
|
|
103
|
+
case "array": {
|
|
104
|
+
if (!Array.isArray(value)) {
|
|
105
|
+
return [issue(parameter.id, `${parameter.label} must be a list.`)];
|
|
106
|
+
}
|
|
107
|
+
const issues = [];
|
|
108
|
+
if (value.length > MAX_ARRAY_ITEMS) {
|
|
109
|
+
issues.push(issue(parameter.id, `${parameter.label} must contain at most ${MAX_ARRAY_ITEMS} items.`));
|
|
110
|
+
return issues;
|
|
111
|
+
}
|
|
112
|
+
if (parameter.minItems !== undefined && value.length < parameter.minItems) {
|
|
113
|
+
issues.push(issue(parameter.id, `${parameter.label} must contain at least ${parameter.minItems} items.`));
|
|
114
|
+
}
|
|
115
|
+
if (parameter.maxItems !== undefined && value.length > parameter.maxItems) {
|
|
116
|
+
issues.push(issue(parameter.id, `${parameter.label} must contain at most ${parameter.maxItems} items.`));
|
|
117
|
+
}
|
|
118
|
+
const entries = readDenseArray(value, MAX_ARRAY_ITEMS);
|
|
119
|
+
if (entries === undefined) {
|
|
120
|
+
issues.push(issue(parameter.id, `${parameter.label} must be a dense list of data values.`));
|
|
121
|
+
return issues;
|
|
122
|
+
}
|
|
123
|
+
const inspectedLength = Math.min(value.length, MAX_ARRAY_ITEMS);
|
|
124
|
+
for (let index = 0; index < inspectedLength; index += 1) {
|
|
125
|
+
if (issues.length === MAX_PARAMETER_ISSUES)
|
|
126
|
+
break;
|
|
127
|
+
const item = entries[index];
|
|
128
|
+
if (parameter.items.type === "string") {
|
|
129
|
+
if (typeof item !== "string") {
|
|
130
|
+
issues.push(issue(parameter.id, `${parameter.label} item ${index + 1} must be text.`));
|
|
131
|
+
}
|
|
132
|
+
else if (item.length > MAX_METADATA_TEXT_LENGTH) {
|
|
133
|
+
issues.push(issue(parameter.id, `${parameter.label} item ${index + 1} must contain at most ${MAX_METADATA_TEXT_LENGTH} characters.`));
|
|
134
|
+
}
|
|
135
|
+
continue;
|
|
136
|
+
}
|
|
137
|
+
if (typeof item !== "number" || !Number.isFinite(item)) {
|
|
138
|
+
issues.push(issue(parameter.id, `${parameter.label} item ${index + 1} must be a finite number.`));
|
|
139
|
+
continue;
|
|
140
|
+
}
|
|
141
|
+
if (parameter.items.integer && !Number.isInteger(item)) {
|
|
142
|
+
issues.push(issue(parameter.id, `${parameter.label} item ${index + 1} must be an integer.`));
|
|
143
|
+
}
|
|
144
|
+
if (parameter.items.min !== undefined && item < parameter.items.min) {
|
|
145
|
+
issues.push(issue(parameter.id, `${parameter.label} item ${index + 1} must be at least ${parameter.items.min}.`));
|
|
146
|
+
}
|
|
147
|
+
if (parameter.items.max !== undefined && item > parameter.items.max) {
|
|
148
|
+
issues.push(issue(parameter.id, `${parameter.label} item ${index + 1} must be at most ${parameter.items.max}.`));
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
return issues;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
/** Caps reported issues, prioritizing errors while preserving the retained issues' input order. */
|
|
156
|
+
export function aggregateParameterIssues(...issueSets) {
|
|
157
|
+
let remainingErrors = 0;
|
|
158
|
+
for (const set of issueSets) {
|
|
159
|
+
for (const entry of set) {
|
|
160
|
+
if (entry.severity === "error" && remainingErrors < MAX_PARAMETER_ISSUES) {
|
|
161
|
+
remainingErrors += 1;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
let remainingWarnings = MAX_PARAMETER_ISSUES - remainingErrors;
|
|
166
|
+
const issues = [];
|
|
167
|
+
for (const set of issueSets) {
|
|
168
|
+
for (const entry of set) {
|
|
169
|
+
if (entry.severity === "error" && remainingErrors > 0) {
|
|
170
|
+
issues.push(entry);
|
|
171
|
+
remainingErrors -= 1;
|
|
172
|
+
}
|
|
173
|
+
else if (entry.severity === "warning" && remainingWarnings > 0) {
|
|
174
|
+
issues.push(entry);
|
|
175
|
+
remainingWarnings -= 1;
|
|
176
|
+
}
|
|
177
|
+
if (issues.length === MAX_PARAMETER_ISSUES)
|
|
178
|
+
break;
|
|
179
|
+
}
|
|
180
|
+
if (issues.length === MAX_PARAMETER_ISSUES)
|
|
181
|
+
break;
|
|
182
|
+
}
|
|
183
|
+
const errors = issues.filter((entry) => entry.severity === "error");
|
|
184
|
+
const warnings = issues.filter((entry) => entry.severity === "warning");
|
|
185
|
+
return {
|
|
186
|
+
isValid: errors.length === 0,
|
|
187
|
+
issues,
|
|
188
|
+
errors,
|
|
189
|
+
warnings,
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Parses validator output at the executable-code boundary.
|
|
194
|
+
*
|
|
195
|
+
* Validation issues are intentionally strict and bounded because authored and
|
|
196
|
+
* installed generator code can return values that did not pass TypeScript.
|
|
197
|
+
*/
|
|
198
|
+
export function parseParameterIssues(definition, value) {
|
|
199
|
+
if (!Array.isArray(value)) {
|
|
200
|
+
throw new TypeError("Generator validation must return an array of parameter issues.");
|
|
201
|
+
}
|
|
202
|
+
if (value.length > MAX_PARAMETER_ISSUES) {
|
|
203
|
+
throw new TypeError(`Generator validation may return at most ${MAX_PARAMETER_ISSUES} issues.`);
|
|
204
|
+
}
|
|
205
|
+
const entries = readDenseArray(value, MAX_PARAMETER_ISSUES);
|
|
206
|
+
if (entries === undefined) {
|
|
207
|
+
throw new TypeError("Generator validation must return a dense array of issue data values.");
|
|
208
|
+
}
|
|
209
|
+
const parameterIds = new Set(definition.parameters.map((parameter) => parameter.id));
|
|
210
|
+
const parsed = entries.map((entry, index) => {
|
|
211
|
+
const path = `Generator validation issue ${index + 1}`;
|
|
212
|
+
if (!isRecord(entry)) {
|
|
213
|
+
throw new TypeError(`${path} must be an object.`);
|
|
214
|
+
}
|
|
215
|
+
const allowedKeys = new Set(["severity", "parameterId", "message"]);
|
|
216
|
+
let keys;
|
|
217
|
+
try {
|
|
218
|
+
keys = Reflect.ownKeys(entry);
|
|
219
|
+
}
|
|
220
|
+
catch (cause) {
|
|
221
|
+
throw new TypeError(`${path} fields could not be inspected.`, { cause });
|
|
222
|
+
}
|
|
223
|
+
const unknownKey = keys.find((key) => typeof key !== "string" || !allowedKeys.has(key));
|
|
224
|
+
if (unknownKey !== undefined) {
|
|
225
|
+
throw new TypeError(`${path} contains unknown field "${String(unknownKey)}".`);
|
|
226
|
+
}
|
|
227
|
+
const dataField = (key) => {
|
|
228
|
+
let descriptor;
|
|
229
|
+
try {
|
|
230
|
+
descriptor = Object.getOwnPropertyDescriptor(entry, key);
|
|
231
|
+
}
|
|
232
|
+
catch (cause) {
|
|
233
|
+
throw new TypeError(`${path}.${key} could not be inspected.`, { cause });
|
|
234
|
+
}
|
|
235
|
+
if (descriptor === undefined)
|
|
236
|
+
return undefined;
|
|
237
|
+
if (!("value" in descriptor)) {
|
|
238
|
+
throw new TypeError(`${path}.${key} must be an own data field.`);
|
|
239
|
+
}
|
|
240
|
+
return descriptor.value;
|
|
241
|
+
};
|
|
242
|
+
const severity = dataField("severity");
|
|
243
|
+
const message = dataField("message");
|
|
244
|
+
const parameterId = dataField("parameterId");
|
|
245
|
+
if (severity !== "error" && severity !== "warning") {
|
|
246
|
+
throw new TypeError(`${path}.severity must be "error" or "warning".`);
|
|
247
|
+
}
|
|
248
|
+
if (typeof message !== "string" || message.trim().length === 0) {
|
|
249
|
+
throw new TypeError(`${path}.message must be a non-empty string.`);
|
|
250
|
+
}
|
|
251
|
+
if (message.length > MAX_PARAMETER_ISSUE_MESSAGE_LENGTH) {
|
|
252
|
+
throw new TypeError(`${path}.message may contain at most ${MAX_PARAMETER_ISSUE_MESSAGE_LENGTH} characters.`);
|
|
253
|
+
}
|
|
254
|
+
if (parameterId !== undefined &&
|
|
255
|
+
(typeof parameterId !== "string" || !parameterIds.has(parameterId))) {
|
|
256
|
+
throw new TypeError(`${path}.parameterId must identify a declared parameter.`);
|
|
257
|
+
}
|
|
258
|
+
return Object.freeze(parameterId === undefined ? { severity, message } : { severity, parameterId, message });
|
|
259
|
+
});
|
|
260
|
+
return Object.freeze(parsed);
|
|
261
|
+
}
|
|
262
|
+
//# sourceMappingURL=issues.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"issues.js","sourceRoot":"","sources":["../../src/parameters/issues.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { GeneratorDefinition, GeneratorIssue, GeneratorParams, ParameterValidationResult } from "../contracts.js";
|
|
2
|
+
export interface PreparedParameters<D extends GeneratorDefinition> {
|
|
3
|
+
readonly parameters: GeneratorParams<D>;
|
|
4
|
+
readonly validation: ParameterValidationResult;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Normalizes known values once, then aggregates schema and Generator-owned issues.
|
|
8
|
+
* Obsolete keys never leak into Generator validation.
|
|
9
|
+
*/
|
|
10
|
+
export declare function prepareParameters<const D extends GeneratorDefinition>(definition: D, parameters: Readonly<Record<string, unknown>>, validate?: (parameters: GeneratorParams<D>) => readonly GeneratorIssue<D>[]): PreparedParameters<D>;
|
|
11
|
+
/** Aggregates definition and Generator-owned validation issues. */
|
|
12
|
+
export declare function validateParameters<const D extends GeneratorDefinition>(definition: D, parameters: Readonly<Record<string, unknown>>, validate?: (parameters: GeneratorParams<D>) => readonly GeneratorIssue<D>[]): ParameterValidationResult;
|
|
13
|
+
//# sourceMappingURL=preparation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"preparation.d.ts","sourceRoot":"","sources":["../../src/parameters/preparation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,mBAAmB,EACnB,cAAc,EACd,eAAe,EAEf,yBAAyB,EAC1B,MAAM,iBAAiB,CAAC;AASzB,MAAM,WAAW,kBAAkB,CAAC,CAAC,SAAS,mBAAmB;IAC/D,QAAQ,CAAC,UAAU,EAAE,eAAe,CAAC,CAAC,CAAC,CAAC;IACxC,QAAQ,CAAC,UAAU,EAAE,yBAAyB,CAAC;CAChD;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,CAAC,CAAC,SAAS,mBAAmB,EACnE,UAAU,EAAE,CAAC,EACb,UAAU,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,EAC7C,QAAQ,CAAC,EAAE,CAAC,UAAU,EAAE,eAAe,CAAC,CAAC,CAAC,KAAK,SAAS,cAAc,CAAC,CAAC,CAAC,EAAE,GAC1E,kBAAkB,CAAC,CAAC,CAAC,CA2BvB;AAED,mEAAmE;AACnE,wBAAgB,kBAAkB,CAAC,KAAK,CAAC,CAAC,SAAS,mBAAmB,EACpE,UAAU,EAAE,CAAC,EACb,UAAU,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,EAC7C,QAAQ,CAAC,EAAE,CAAC,UAAU,EAAE,eAAe,CAAC,CAAC,CAAC,KAAK,SAAS,cAAc,CAAC,CAAC,CAAC,EAAE,GAC1E,yBAAyB,CAE3B"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { aggregateParameterIssues, parseParameterIssues, validateDefinitionValue, } from "./issues.js";
|
|
2
|
+
import { normalizeParameters } from "./recovery.js";
|
|
3
|
+
import { MAX_PROJECT_SVG_PARAMETER_BYTES, ownValue, svgParameterBytes } from "./values.js";
|
|
4
|
+
/**
|
|
5
|
+
* Normalizes known values once, then aggregates schema and Generator-owned issues.
|
|
6
|
+
* Obsolete keys never leak into Generator validation.
|
|
7
|
+
*/
|
|
8
|
+
export function prepareParameters(definition, parameters, validate) {
|
|
9
|
+
const schemaIssues = definition.parameters.flatMap((parameter) => validateDefinitionValue(parameter, ownValue(parameters, parameter.id)));
|
|
10
|
+
const svgBytes = definition.parameters.reduce((total, parameter) => {
|
|
11
|
+
const value = ownValue(parameters, parameter.id);
|
|
12
|
+
return parameter.type === "svg" && typeof value === "string"
|
|
13
|
+
? total + svgParameterBytes(value)
|
|
14
|
+
: total;
|
|
15
|
+
}, 0);
|
|
16
|
+
const projectSvgIssues = svgBytes > MAX_PROJECT_SVG_PARAMETER_BYTES
|
|
17
|
+
? [
|
|
18
|
+
{
|
|
19
|
+
severity: "error",
|
|
20
|
+
message: "All SVG parameters together must be 512 KiB or smaller.",
|
|
21
|
+
},
|
|
22
|
+
]
|
|
23
|
+
: [];
|
|
24
|
+
const normalized = normalizeParameters(definition, parameters);
|
|
25
|
+
const customIssues = validate === undefined ? [] : parseParameterIssues(definition, validate(normalized));
|
|
26
|
+
return {
|
|
27
|
+
parameters: normalized,
|
|
28
|
+
validation: aggregateParameterIssues(schemaIssues, projectSvgIssues, customIssues),
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
/** Aggregates definition and Generator-owned validation issues. */
|
|
32
|
+
export function validateParameters(definition, parameters, validate) {
|
|
33
|
+
return prepareParameters(definition, parameters, validate).validation;
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=preparation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"preparation.js","sourceRoot":"","sources":["../../src/parameters/preparation.ts"],"names":[],"mappings":"AAOA,OAAO,EACL,wBAAwB,EACxB,oBAAoB,EACpB,uBAAuB,GACxB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,EAAE,+BAA+B,EAAE,QAAQ,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAO3F;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAC/B,UAAa,EACb,UAA6C,EAC7C,QAA2E;IAE3E,MAAM,YAAY,GAAG,UAAU,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,SAAS,EAAE,EAAE,CAC/D,uBAAuB,CAAC,SAAS,EAAE,QAAQ,CAAC,UAAU,EAAE,SAAS,CAAC,EAAE,CAAC,CAAC,CACvE,CAAC;IACF,MAAM,QAAQ,GAAG,UAAU,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,SAAS,EAAE,EAAE;QACjE,MAAM,KAAK,GAAG,QAAQ,CAAC,UAAU,EAAE,SAAS,CAAC,EAAE,CAAC,CAAC;QACjD,OAAO,SAAS,CAAC,IAAI,KAAK,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ;YAC1D,CAAC,CAAC,KAAK,GAAG,iBAAiB,CAAC,KAAK,CAAC;YAClC,CAAC,CAAC,KAAK,CAAC;IACZ,CAAC,EAAE,CAAC,CAAC,CAAC;IACN,MAAM,gBAAgB,GACpB,QAAQ,GAAG,+BAA+B;QACxC,CAAC,CAAC;YACE;gBACE,QAAQ,EAAE,OAAO;gBACjB,OAAO,EAAE,yDAAyD;aAC1C;SAC3B;QACH,CAAC,CAAC,EAAE,CAAC;IACT,MAAM,UAAU,GAAG,mBAAmB,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;IAC/D,MAAM,YAAY,GAChB,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,oBAAoB,CAAC,UAAU,EAAE,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC;IAEvF,OAAO;QACL,UAAU,EAAE,UAAU;QACtB,UAAU,EAAE,wBAAwB,CAAC,YAAY,EAAE,gBAAgB,EAAE,YAAY,CAAC;KACnF,CAAC;AACJ,CAAC;AAED,mEAAmE;AACnE,MAAM,UAAU,kBAAkB,CAChC,UAAa,EACb,UAA6C,EAC7C,QAA2E;IAE3E,OAAO,iBAAiB,CAAC,UAAU,EAAE,UAAU,EAAE,QAAQ,CAAC,CAAC,UAAU,CAAC;AACxE,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { GeneratorDefinition, GeneratorParams, ParameterDefinition, ParameterValue } from "../contracts.js";
|
|
2
|
+
export declare function normalizeValue(parameter: ParameterDefinition, value: unknown, fallback: ParameterValue): ParameterValue;
|
|
3
|
+
export declare function normalizedDefinitionDefault(parameter: ParameterDefinition): ParameterValue;
|
|
4
|
+
/**
|
|
5
|
+
* Returns one value per declared parameter. Unknown input keys are discarded,
|
|
6
|
+
* missing/invalid values fall back to defaults, and numbers are clamped.
|
|
7
|
+
*/
|
|
8
|
+
export declare function normalizeParameters<const D extends GeneratorDefinition>(definition: D, input?: Readonly<Record<string, unknown>> | null): GeneratorParams<D>;
|
|
9
|
+
export declare function getDefaultParameters<const D extends GeneratorDefinition>(definition: D): GeneratorParams<D>;
|
|
10
|
+
//# sourceMappingURL=recovery.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recovery.d.ts","sourceRoot":"","sources":["../../src/parameters/recovery.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,mBAAmB,EACnB,eAAe,EACf,mBAAmB,EACnB,cAAc,EACf,MAAM,iBAAiB,CAAC;AAkCzB,wBAAgB,cAAc,CAC5B,SAAS,EAAE,mBAAmB,EAC9B,KAAK,EAAE,OAAO,EACd,QAAQ,EAAE,cAAc,GACvB,cAAc,CAwFhB;AAED,wBAAgB,2BAA2B,CAAC,SAAS,EAAE,mBAAmB,GAAG,cAAc,CAE1F;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,CAAC,CAAC,SAAS,mBAAmB,EACrE,UAAU,EAAE,CAAC,EACb,KAAK,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,IAAI,GAC/C,eAAe,CAAC,CAAC,CAAC,CASpB;AAED,wBAAgB,oBAAoB,CAAC,KAAK,CAAC,CAAC,SAAS,mBAAmB,EACtE,UAAU,EAAE,CAAC,GACZ,eAAe,CAAC,CAAC,CAAC,CAEpB"}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { isFontSelection } from "../fonts.js";
|
|
2
|
+
import { MAX_ARRAY_ITEMS, MAX_METADATA_TEXT_LENGTH, MAX_PARAMETER_OPTIONS, MAX_TEXT_PARAMETER_LENGTH, } from "../generator-package/constants.js";
|
|
3
|
+
import { cloneProfileValue, isProfileValue } from "../profiles.js";
|
|
4
|
+
import { freezeParameters, HEX_COLOR_PATTERN, ownValue, readDenseArray, svgValueFits, } from "./values.js";
|
|
5
|
+
function isBoundedStringArray(value) {
|
|
6
|
+
return value.every((item) => typeof item === "string" && item.length <= MAX_METADATA_TEXT_LENGTH);
|
|
7
|
+
}
|
|
8
|
+
function isFiniteNumberArray(value) {
|
|
9
|
+
return value.every((item) => typeof item === "number" && Number.isFinite(item));
|
|
10
|
+
}
|
|
11
|
+
function isParameterArray(value) {
|
|
12
|
+
return Array.isArray(value);
|
|
13
|
+
}
|
|
14
|
+
function clamp(value, minimum, maximum) {
|
|
15
|
+
const withMinimum = minimum === undefined ? value : Math.max(minimum, value);
|
|
16
|
+
return maximum === undefined ? withMinimum : Math.min(maximum, withMinimum);
|
|
17
|
+
}
|
|
18
|
+
export function normalizeValue(parameter, value, fallback) {
|
|
19
|
+
const fallbackValue = isParameterArray(fallback)
|
|
20
|
+
? fallback.slice()
|
|
21
|
+
: isFontSelection(fallback)
|
|
22
|
+
? { ...fallback }
|
|
23
|
+
: isProfileValue(fallback)
|
|
24
|
+
? cloneProfileValue(fallback)
|
|
25
|
+
: fallback;
|
|
26
|
+
switch (parameter.type) {
|
|
27
|
+
case "profile":
|
|
28
|
+
return isProfileValue(value) ? cloneProfileValue(value) : fallbackValue;
|
|
29
|
+
case "font":
|
|
30
|
+
return isFontSelection(value)
|
|
31
|
+
? { faceId: value.faceId, revision: value.revision, weight: value.weight }
|
|
32
|
+
: fallbackValue;
|
|
33
|
+
case "number":
|
|
34
|
+
case "slider":
|
|
35
|
+
return typeof value === "number" &&
|
|
36
|
+
Number.isFinite(value) &&
|
|
37
|
+
(!parameter.integer || Number.isInteger(value))
|
|
38
|
+
? clamp(value, parameter.min, parameter.max)
|
|
39
|
+
: fallbackValue;
|
|
40
|
+
case "boolean":
|
|
41
|
+
return typeof value === "boolean" ? value : fallbackValue;
|
|
42
|
+
case "select":
|
|
43
|
+
return typeof value === "string" && parameter.options.some((option) => option.value === value)
|
|
44
|
+
? value
|
|
45
|
+
: fallbackValue;
|
|
46
|
+
case "choice-set": {
|
|
47
|
+
if (!Array.isArray(value) || value.length > MAX_PARAMETER_OPTIONS) {
|
|
48
|
+
return fallbackValue;
|
|
49
|
+
}
|
|
50
|
+
const entries = readDenseArray(value, MAX_PARAMETER_OPTIONS);
|
|
51
|
+
if (entries === undefined)
|
|
52
|
+
return fallbackValue;
|
|
53
|
+
const knownValues = new Set(parameter.options.map((option) => option.value));
|
|
54
|
+
const selected = new Set();
|
|
55
|
+
for (let index = 0; index < entries.length; index += 1) {
|
|
56
|
+
const entry = entries[index];
|
|
57
|
+
if (typeof entry !== "string" || !knownValues.has(entry) || selected.has(entry)) {
|
|
58
|
+
return fallbackValue;
|
|
59
|
+
}
|
|
60
|
+
selected.add(entry);
|
|
61
|
+
}
|
|
62
|
+
if ((parameter.minSelections !== undefined && entries.length < parameter.minSelections) ||
|
|
63
|
+
(parameter.maxSelections !== undefined && entries.length > parameter.maxSelections)) {
|
|
64
|
+
return fallbackValue;
|
|
65
|
+
}
|
|
66
|
+
// Selection order has no meaning; option-definition order is the
|
|
67
|
+
// canonical representation used by persistence, presets, and equality.
|
|
68
|
+
return parameter.options
|
|
69
|
+
.map((option) => option.value)
|
|
70
|
+
.filter((option) => selected.has(option));
|
|
71
|
+
}
|
|
72
|
+
case "color":
|
|
73
|
+
return typeof value === "string" && HEX_COLOR_PATTERN.test(value)
|
|
74
|
+
? value.toLowerCase()
|
|
75
|
+
: fallbackValue;
|
|
76
|
+
case "text":
|
|
77
|
+
return typeof value === "string" && value.length <= MAX_TEXT_PARAMETER_LENGTH
|
|
78
|
+
? value
|
|
79
|
+
: fallbackValue;
|
|
80
|
+
case "svg":
|
|
81
|
+
return typeof value === "string" && svgValueFits(value) ? value : fallbackValue;
|
|
82
|
+
case "array": {
|
|
83
|
+
if (!Array.isArray(value))
|
|
84
|
+
return fallbackValue;
|
|
85
|
+
if (value.length > MAX_ARRAY_ITEMS ||
|
|
86
|
+
(parameter.minItems !== undefined && value.length < parameter.minItems) ||
|
|
87
|
+
(parameter.maxItems !== undefined && value.length > parameter.maxItems)) {
|
|
88
|
+
return fallbackValue;
|
|
89
|
+
}
|
|
90
|
+
const entries = readDenseArray(value, MAX_ARRAY_ITEMS);
|
|
91
|
+
if (entries === undefined)
|
|
92
|
+
return fallbackValue;
|
|
93
|
+
if (parameter.items.type === "string") {
|
|
94
|
+
return isBoundedStringArray(entries) ? entries : fallbackValue;
|
|
95
|
+
}
|
|
96
|
+
const numericItems = parameter.items;
|
|
97
|
+
if (!isFiniteNumberArray(entries) ||
|
|
98
|
+
(numericItems.integer && !entries.every(Number.isInteger)))
|
|
99
|
+
return fallbackValue;
|
|
100
|
+
return entries.map((item) => clamp(item, numericItems.min, numericItems.max));
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
export function normalizedDefinitionDefault(parameter) {
|
|
105
|
+
return normalizeValue(parameter, parameter.default, parameter.default);
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Returns one value per declared parameter. Unknown input keys are discarded,
|
|
109
|
+
* missing/invalid values fall back to defaults, and numbers are clamped.
|
|
110
|
+
*/
|
|
111
|
+
export function normalizeParameters(definition, input) {
|
|
112
|
+
const entries = definition.parameters.map((parameter) => {
|
|
113
|
+
const fallback = normalizedDefinitionDefault(parameter);
|
|
114
|
+
return [
|
|
115
|
+
parameter.id,
|
|
116
|
+
normalizeValue(parameter, ownValue(input, parameter.id), fallback),
|
|
117
|
+
];
|
|
118
|
+
});
|
|
119
|
+
return freezeParameters(Object.fromEntries(entries));
|
|
120
|
+
}
|
|
121
|
+
export function getDefaultParameters(definition) {
|
|
122
|
+
return normalizeParameters(definition);
|
|
123
|
+
}
|
|
124
|
+
//# sourceMappingURL=recovery.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recovery.js","sourceRoot":"","sources":["../../src/parameters/recovery.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EACL,eAAe,EACf,wBAAwB,EACxB,qBAAqB,EACrB,yBAAyB,GAC1B,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AACnE,OAAO,EACL,gBAAgB,EAChB,iBAAiB,EACjB,QAAQ,EACR,cAAc,EACd,YAAY,GACb,MAAM,aAAa,CAAC;AAErB,SAAS,oBAAoB,CAAC,KAAyB;IACrD,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,MAAM,IAAI,wBAAwB,CAAC,CAAC;AACpG,CAAC;AAED,SAAS,mBAAmB,CAAC,KAAyB;IACpD,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,IAAI,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC;AAClF,CAAC;AAED,SAAS,gBAAgB,CAAC,KAAqB;IAC7C,OAAO,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AAC9B,CAAC;AAED,SAAS,KAAK,CAAC,KAAa,EAAE,OAAgB,EAAE,OAAgB;IAC9D,MAAM,WAAW,GAAG,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;IAC7E,OAAO,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;AAC9E,CAAC;AAED,MAAM,UAAU,cAAc,CAC5B,SAA8B,EAC9B,KAAc,EACd,QAAwB;IAExB,MAAM,aAAa,GAAG,gBAAgB,CAAC,QAAQ,CAAC;QAC9C,CAAC,CAAC,QAAQ,CAAC,KAAK,EAAE;QAClB,CAAC,CAAC,eAAe,CAAC,QAAQ,CAAC;YACzB,CAAC,CAAC,EAAE,GAAG,QAAQ,EAAE;YACjB,CAAC,CAAC,cAAc,CAAC,QAAQ,CAAC;gBACxB,CAAC,CAAC,iBAAiB,CAAC,QAAQ,CAAC;gBAC7B,CAAC,CAAC,QAAQ,CAAC;IACjB,QAAQ,SAAS,CAAC,IAAI,EAAE,CAAC;QACvB,KAAK,SAAS;YACZ,OAAO,cAAc,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,iBAAiB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC;QAC1E,KAAK,MAAM;YACT,OAAO,eAAe,CAAC,KAAK,CAAC;gBAC3B,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE;gBAC1E,CAAC,CAAC,aAAa,CAAC;QACpB,KAAK,QAAQ,CAAC;QACd,KAAK,QAAQ;YACX,OAAO,OAAO,KAAK,KAAK,QAAQ;gBAC9B,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC;gBACtB,CAAC,CAAC,SAAS,CAAC,OAAO,IAAI,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;gBAC/C,CAAC,CAAC,KAAK,CAAC,KAAK,EAAE,SAAS,CAAC,GAAG,EAAE,SAAS,CAAC,GAAG,CAAC;gBAC5C,CAAC,CAAC,aAAa,CAAC;QACpB,KAAK,SAAS;YACZ,OAAO,OAAO,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,aAAa,CAAC;QAC5D,KAAK,QAAQ;YACX,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,KAAK,KAAK,CAAC;gBAC5F,CAAC,CAAC,KAAK;gBACP,CAAC,CAAC,aAAa,CAAC;QACpB,KAAK,YAAY,CAAC,CAAC,CAAC;YAClB,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,MAAM,GAAG,qBAAqB,EAAE,CAAC;gBAClE,OAAO,aAAa,CAAC;YACvB,CAAC;YACD,MAAM,OAAO,GAAG,cAAc,CAAC,KAAK,EAAE,qBAAqB,CAAC,CAAC;YAC7D,IAAI,OAAO,KAAK,SAAS;gBAAE,OAAO,aAAa,CAAC;YAChD,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC,SAAS,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;YAC7E,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAU,CAAC;YACnC,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,OAAO,CAAC,MAAM,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;gBACvD,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC;gBAC7B,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;oBAChF,OAAO,aAAa,CAAC;gBACvB,CAAC;gBACD,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;YACtB,CAAC;YACD,IACE,CAAC,SAAS,CAAC,aAAa,KAAK,SAAS,IAAI,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,aAAa,CAAC;gBACnF,CAAC,SAAS,CAAC,aAAa,KAAK,SAAS,IAAI,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,aAAa,CAAC,EACnF,CAAC;gBACD,OAAO,aAAa,CAAC;YACvB,CAAC;YACD,iEAAiE;YACjE,uEAAuE;YACvE,OAAO,SAAS,CAAC,OAAO;iBACrB,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC;iBAC7B,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;QAC9C,CAAC;QACD,KAAK,OAAO;YACV,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,iBAAiB,CAAC,IAAI,CAAC,KAAK,CAAC;gBAC/D,CAAC,CAAC,KAAK,CAAC,WAAW,EAAE;gBACrB,CAAC,CAAC,aAAa,CAAC;QACpB,KAAK,MAAM;YACT,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,MAAM,IAAI,yBAAyB;gBAC3E,CAAC,CAAC,KAAK;gBACP,CAAC,CAAC,aAAa,CAAC;QACpB,KAAK,KAAK;YACR,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,aAAa,CAAC;QAClF,KAAK,OAAO,CAAC,CAAC,CAAC;YACb,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;gBAAE,OAAO,aAAa,CAAC;YAChD,IACE,KAAK,CAAC,MAAM,GAAG,eAAe;gBAC9B,CAAC,SAAS,CAAC,QAAQ,KAAK,SAAS,IAAI,KAAK,CAAC,MAAM,GAAG,SAAS,CAAC,QAAQ,CAAC;gBACvE,CAAC,SAAS,CAAC,QAAQ,KAAK,SAAS,IAAI,KAAK,CAAC,MAAM,GAAG,SAAS,CAAC,QAAQ,CAAC,EACvE,CAAC;gBACD,OAAO,aAAa,CAAC;YACvB,CAAC;YACD,MAAM,OAAO,GAAG,cAAc,CAAC,KAAK,EAAE,eAAe,CAAC,CAAC;YACvD,IAAI,OAAO,KAAK,SAAS;gBAAE,OAAO,aAAa,CAAC;YAChD,IAAI,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBACtC,OAAO,oBAAoB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,aAAa,CAAC;YACjE,CAAC;YACD,MAAM,YAAY,GAAG,SAAS,CAAC,KAAK,CAAC;YACrC,IACE,CAAC,mBAAmB,CAAC,OAAO,CAAC;gBAC7B,CAAC,YAAY,CAAC,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;gBAE1D,OAAO,aAAa,CAAC;YACvB,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,YAAY,CAAC,GAAG,EAAE,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC;QAChF,CAAC;IACH,CAAC;AACH,CAAC;AAED,MAAM,UAAU,2BAA2B,CAAC,SAA8B;IACxE,OAAO,cAAc,CAAC,SAAS,EAAE,SAAS,CAAC,OAAO,EAAE,SAAS,CAAC,OAAO,CAAC,CAAC;AACzE,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,mBAAmB,CACjC,UAAa,EACb,KAAgD;IAEhD,MAAM,OAAO,GAAG,UAAU,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE;QACtD,MAAM,QAAQ,GAAG,2BAA2B,CAAC,SAAS,CAAC,CAAC;QACxD,OAAO;YACL,SAAS,CAAC,EAAE;YACZ,cAAc,CAAC,SAAS,EAAE,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC,EAAE,CAAC,EAAE,QAAQ,CAAC;SAC1D,CAAC;IACb,CAAC,CAAC,CAAC;IACH,OAAO,gBAAgB,CAAC,MAAM,CAAC,WAAW,CAAC,OAAO,CAAuB,CAAC,CAAC;AAC7E,CAAC;AAED,MAAM,UAAU,oBAAoB,CAClC,UAAa;IAEb,OAAO,mBAAmB,CAAC,UAAU,CAAC,CAAC;AACzC,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { GeneratorDefinition, GeneratorParams } from "../contracts.js";
|
|
2
|
+
export type ParamDecodeCode = "invalid" | "missing" | "type" | "unknown";
|
|
3
|
+
export interface ParamDecodeIssue {
|
|
4
|
+
readonly code: ParamDecodeCode;
|
|
5
|
+
readonly parameterId?: string;
|
|
6
|
+
readonly path: readonly (number | string)[];
|
|
7
|
+
readonly message: string;
|
|
8
|
+
}
|
|
9
|
+
export type ParamParseResult<P> = {
|
|
10
|
+
readonly success: true;
|
|
11
|
+
readonly data: P;
|
|
12
|
+
} | {
|
|
13
|
+
readonly success: false;
|
|
14
|
+
readonly issues: readonly ParamDecodeIssue[];
|
|
15
|
+
};
|
|
16
|
+
export interface ParamCodec<D extends GeneratorDefinition> {
|
|
17
|
+
readonly parse: (input: unknown) => GeneratorParams<D>;
|
|
18
|
+
readonly safeParse: (input: unknown) => ParamParseResult<GeneratorParams<D>>;
|
|
19
|
+
}
|
|
20
|
+
export declare class ParamDecodeError extends TypeError {
|
|
21
|
+
readonly issues: readonly ParamDecodeIssue[];
|
|
22
|
+
constructor(issues: readonly ParamDecodeIssue[]);
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Creates a strict decoder for the exact normalized parameter map described by
|
|
26
|
+
* a definition. Unlike normalization, decoding never fills, drops, clamps, or
|
|
27
|
+
* canonicalizes values.
|
|
28
|
+
*/
|
|
29
|
+
export declare function createParamCodec<const D extends GeneratorDefinition>(definition: D): ParamCodec<D>;
|
|
30
|
+
//# sourceMappingURL=strict.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"strict.d.ts","sourceRoot":"","sources":["../../src/parameters/strict.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,eAAe,EAAkB,MAAM,iBAAiB,CAAC;AAe5F,MAAM,MAAM,eAAe,GAAG,SAAS,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAAC;AAEzE,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAC;IAC/B,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,CAAC;IAC5C,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,MAAM,gBAAgB,CAAC,CAAC,IAC1B;IAAE,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAA;CAAE,GAC5C;IAAE,QAAQ,CAAC,OAAO,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,SAAS,gBAAgB,EAAE,CAAA;CAAE,CAAC;AAE9E,MAAM,WAAW,UAAU,CAAC,CAAC,SAAS,mBAAmB;IACvD,QAAQ,CAAC,KAAK,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,eAAe,CAAC,CAAC,CAAC,CAAC;IACvD,QAAQ,CAAC,SAAS,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,gBAAgB,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC;CAC9E;AAED,qBAAa,gBAAiB,SAAQ,SAAS;IAC7C,QAAQ,CAAC,MAAM,EAAE,SAAS,gBAAgB,EAAE,CAAC;gBAEjC,MAAM,EAAE,SAAS,gBAAgB,EAAE;CAKhD;AA2BD;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,CAAC,CAAC,SAAS,mBAAmB,EAClE,UAAU,EAAE,CAAC,GACZ,UAAU,CAAC,CAAC,CAAC,CA6Gf"}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { isFontSelection } from "../fonts.js";
|
|
2
|
+
import { MAX_ARRAY_ITEMS } from "../generator-package/constants.js";
|
|
3
|
+
import { isProfileValue, profileValuesEqual } from "../profiles.js";
|
|
4
|
+
import { MAX_PARAMETER_ISSUES, validateDefinitionValue } from "./issues.js";
|
|
5
|
+
import { normalizedDefinitionDefault, normalizeValue } from "./recovery.js";
|
|
6
|
+
import { freezeParameters, isRecord, MAX_PROJECT_SVG_PARAMETER_BYTES, parameterValueEquals, readDenseArray, svgParameterBytes, } from "./values.js";
|
|
7
|
+
export class ParamDecodeError extends TypeError {
|
|
8
|
+
issues;
|
|
9
|
+
constructor(issues) {
|
|
10
|
+
super(issues[0]?.message ?? "Generator parameters are invalid.");
|
|
11
|
+
this.name = "ParamDecodeError";
|
|
12
|
+
this.issues = issues;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
function valueMatchesCanonical(value, canonical) {
|
|
16
|
+
if (isProfileValue(canonical)) {
|
|
17
|
+
return isProfileValue(value) && profileValuesEqual(value, canonical);
|
|
18
|
+
}
|
|
19
|
+
if (isFontSelection(canonical))
|
|
20
|
+
return isFontSelection(value) && parameterValueEquals(value, canonical);
|
|
21
|
+
if (!Array.isArray(canonical))
|
|
22
|
+
return Object.is(value, canonical);
|
|
23
|
+
const entries = readDenseArray(value, MAX_ARRAY_ITEMS);
|
|
24
|
+
if (entries === undefined || entries.length !== canonical.length)
|
|
25
|
+
return false;
|
|
26
|
+
return canonical.every((entry, index) => Object.is(entry, entries[index]));
|
|
27
|
+
}
|
|
28
|
+
function decodeIssue(code, path, message, parameterId) {
|
|
29
|
+
return parameterId === undefined ? { code, path, message } : { code, path, parameterId, message };
|
|
30
|
+
}
|
|
31
|
+
function appendDecodeIssue(issues, next) {
|
|
32
|
+
if (issues.length < MAX_PARAMETER_ISSUES)
|
|
33
|
+
issues.push(next);
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Creates a strict decoder for the exact normalized parameter map described by
|
|
37
|
+
* a definition. Unlike normalization, decoding never fills, drops, clamps, or
|
|
38
|
+
* canonicalizes values.
|
|
39
|
+
*/
|
|
40
|
+
export function createParamCodec(definition) {
|
|
41
|
+
const parameterIds = new Set(definition.parameters.map((parameter) => parameter.id));
|
|
42
|
+
if (parameterIds.size !== definition.parameters.length) {
|
|
43
|
+
throw new TypeError("Generator parameter IDs must be unique.");
|
|
44
|
+
}
|
|
45
|
+
const safeParse = (input) => {
|
|
46
|
+
if (!isRecord(input)) {
|
|
47
|
+
return {
|
|
48
|
+
success: false,
|
|
49
|
+
issues: [decodeIssue("type", [], "Generator parameters must be an object.")],
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
const issues = [];
|
|
53
|
+
for (const key of Reflect.ownKeys(input)) {
|
|
54
|
+
if (typeof key !== "string" || !parameterIds.has(key)) {
|
|
55
|
+
const printableKey = typeof key === "string" ? key : String(key);
|
|
56
|
+
appendDecodeIssue(issues, decodeIssue("unknown", [printableKey], `Unknown Generator parameter "${printableKey}".`));
|
|
57
|
+
if (issues.length === MAX_PARAMETER_ISSUES)
|
|
58
|
+
break;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
const entries = [];
|
|
62
|
+
let svgBytes = 0;
|
|
63
|
+
for (const parameter of definition.parameters) {
|
|
64
|
+
if (issues.length === MAX_PARAMETER_ISSUES)
|
|
65
|
+
break;
|
|
66
|
+
const descriptor = Object.getOwnPropertyDescriptor(input, parameter.id);
|
|
67
|
+
if (descriptor === undefined) {
|
|
68
|
+
appendDecodeIssue(issues, decodeIssue("missing", [parameter.id], `${parameter.label} is required.`, parameter.id));
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
if (!("value" in descriptor)) {
|
|
72
|
+
appendDecodeIssue(issues, decodeIssue("invalid", [parameter.id], `${parameter.label} must be a data value.`, parameter.id));
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
const value = descriptor.value;
|
|
76
|
+
const fieldIssues = validateDefinitionValue(parameter, value);
|
|
77
|
+
for (const fieldIssue of fieldIssues) {
|
|
78
|
+
appendDecodeIssue(issues, decodeIssue("invalid", [parameter.id], fieldIssue.message, parameter.id));
|
|
79
|
+
}
|
|
80
|
+
if (fieldIssues.length > 0)
|
|
81
|
+
continue;
|
|
82
|
+
const canonical = normalizeValue(parameter, value, normalizedDefinitionDefault(parameter));
|
|
83
|
+
if (!valueMatchesCanonical(value, canonical)) {
|
|
84
|
+
appendDecodeIssue(issues, decodeIssue("invalid", [parameter.id], `${parameter.label} must use its canonical representation.`, parameter.id));
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
87
|
+
if (parameter.type === "svg" && typeof value === "string") {
|
|
88
|
+
svgBytes += svgParameterBytes(value);
|
|
89
|
+
}
|
|
90
|
+
entries.push([
|
|
91
|
+
parameter.id,
|
|
92
|
+
Array.isArray(canonical) ? canonical.slice() : canonical,
|
|
93
|
+
]);
|
|
94
|
+
}
|
|
95
|
+
if (svgBytes > MAX_PROJECT_SVG_PARAMETER_BYTES && issues.length < MAX_PARAMETER_ISSUES) {
|
|
96
|
+
appendDecodeIssue(issues, decodeIssue("invalid", [], "All SVG parameters together must be 512 KiB or smaller."));
|
|
97
|
+
}
|
|
98
|
+
if (issues.length > 0) {
|
|
99
|
+
return { success: false, issues: Object.freeze(issues) };
|
|
100
|
+
}
|
|
101
|
+
return {
|
|
102
|
+
success: true,
|
|
103
|
+
data: freezeParameters(Object.fromEntries(entries)),
|
|
104
|
+
};
|
|
105
|
+
};
|
|
106
|
+
return {
|
|
107
|
+
safeParse,
|
|
108
|
+
parse(input) {
|
|
109
|
+
const result = safeParse(input);
|
|
110
|
+
if (!result.success)
|
|
111
|
+
throw new ParamDecodeError(result.issues);
|
|
112
|
+
return result.data;
|
|
113
|
+
},
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
//# sourceMappingURL=strict.js.map
|