@makehq/forman-schema 1.8.4 → 1.9.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/dist/index.cjs +83 -7
- package/dist/index.d.cts +7 -1
- package/dist/index.d.ts +7 -1
- package/dist/index.js +83 -7
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -98,6 +98,60 @@ function findValueInSelectOptions(field, value, optionsAndGroups) {
|
|
|
98
98
|
const found = optionsAndGroups.find((option) => "value" in option && option.value === value);
|
|
99
99
|
return found;
|
|
100
100
|
}
|
|
101
|
+
function pathToString(path) {
|
|
102
|
+
let result = "";
|
|
103
|
+
for (const key of path) {
|
|
104
|
+
if (typeof key === "number") {
|
|
105
|
+
result += `[${key}]`;
|
|
106
|
+
} else {
|
|
107
|
+
if (result.length > 0) {
|
|
108
|
+
result += ".";
|
|
109
|
+
}
|
|
110
|
+
if (key.includes("`")) {
|
|
111
|
+
throw new Error(`Invalid path key: backticks are not allowed in key "${key}"`);
|
|
112
|
+
}
|
|
113
|
+
result += key.includes(".") ? `\`${key}\`` : key;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
return result;
|
|
117
|
+
}
|
|
118
|
+
function stringToPath(str) {
|
|
119
|
+
const path = [];
|
|
120
|
+
let i = 0;
|
|
121
|
+
while (i < str.length) {
|
|
122
|
+
if (str[i] === ".") {
|
|
123
|
+
i++;
|
|
124
|
+
if (i >= str.length) break;
|
|
125
|
+
}
|
|
126
|
+
if (str[i] === "[") {
|
|
127
|
+
const end = str.indexOf("]", i);
|
|
128
|
+
if (end === -1) {
|
|
129
|
+
throw new Error(`Invalid path: missing closing bracket in "${str}"`);
|
|
130
|
+
}
|
|
131
|
+
const num = Number(str.slice(i + 1, end));
|
|
132
|
+
if (!Number.isInteger(num) || num < 0) {
|
|
133
|
+
throw new Error(`Invalid path: non-numeric or negative index in "${str}"`);
|
|
134
|
+
}
|
|
135
|
+
path.push(num);
|
|
136
|
+
i = end + 1;
|
|
137
|
+
} else if (str[i] === "`") {
|
|
138
|
+
const end = str.indexOf("`", i + 1);
|
|
139
|
+
if (end === -1) {
|
|
140
|
+
throw new Error(`Invalid path: missing closing backtick in "${str}"`);
|
|
141
|
+
}
|
|
142
|
+
path.push(str.slice(i + 1, end));
|
|
143
|
+
i = end + 1;
|
|
144
|
+
} else {
|
|
145
|
+
let end = i;
|
|
146
|
+
while (end < str.length && str[end] !== "." && str[end] !== "[") {
|
|
147
|
+
end++;
|
|
148
|
+
}
|
|
149
|
+
path.push(str.slice(i, end));
|
|
150
|
+
i = end;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
return path;
|
|
154
|
+
}
|
|
101
155
|
function buildRestoreStructure(items) {
|
|
102
156
|
const result = {};
|
|
103
157
|
for (const item of items) {
|
|
@@ -1079,6 +1133,25 @@ async function validateFormanWithDomainsInternal(domains, options) {
|
|
|
1079
1133
|
}
|
|
1080
1134
|
);
|
|
1081
1135
|
errors.push(...result.errors);
|
|
1136
|
+
const restoreExtras = options?.states && domains[domain]?.restoreExtras;
|
|
1137
|
+
if (restoreExtras) {
|
|
1138
|
+
const fieldStateMap = new Map(
|
|
1139
|
+
roots[domain].fieldStates.map(({ path, state }) => {
|
|
1140
|
+
return [pathToString(path), state];
|
|
1141
|
+
})
|
|
1142
|
+
);
|
|
1143
|
+
for (const [fieldPath, extra] of Object.entries(restoreExtras)) {
|
|
1144
|
+
const state = fieldStateMap.get(fieldPath);
|
|
1145
|
+
if (state) {
|
|
1146
|
+
state.extra = extra;
|
|
1147
|
+
} else {
|
|
1148
|
+
roots[domain].fieldStates.push({
|
|
1149
|
+
path: stringToPath(fieldPath),
|
|
1150
|
+
state: { extra }
|
|
1151
|
+
});
|
|
1152
|
+
}
|
|
1153
|
+
}
|
|
1154
|
+
}
|
|
1082
1155
|
}
|
|
1083
1156
|
return {
|
|
1084
1157
|
valid: errors.length === 0,
|
|
@@ -1506,11 +1579,14 @@ async function handleSelectType(value, field, context) {
|
|
|
1506
1579
|
if (resolved == null || typeof resolved !== "object") {
|
|
1507
1580
|
return {
|
|
1508
1581
|
valid: false,
|
|
1509
|
-
errors: [
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1582
|
+
errors: [
|
|
1583
|
+
...errors,
|
|
1584
|
+
{
|
|
1585
|
+
domain: context.domain,
|
|
1586
|
+
path: context.path.join("."),
|
|
1587
|
+
message: `Remote resource ${optionsOrGroups} returned no data.`
|
|
1588
|
+
}
|
|
1589
|
+
]
|
|
1514
1590
|
};
|
|
1515
1591
|
}
|
|
1516
1592
|
optionsOrGroups = Array.isArray(resolved) ? resolved : [resolved];
|
|
@@ -1876,8 +1952,8 @@ function toJSONSchema(field) {
|
|
|
1876
1952
|
function validateFormanWithDomains(domains, options) {
|
|
1877
1953
|
return validateFormanWithDomainsInternal(domains, options);
|
|
1878
1954
|
}
|
|
1879
|
-
function validateForman(values, schema, options) {
|
|
1880
|
-
return validateFormanWithDomains({ default: { values, schema } }, options);
|
|
1955
|
+
function validateForman(values, schema, options, restoreExtras) {
|
|
1956
|
+
return validateFormanWithDomains({ default: { values, schema, restoreExtras } }, options);
|
|
1881
1957
|
}
|
|
1882
1958
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1883
1959
|
0 && (module.exports = {
|
package/dist/index.d.cts
CHANGED
|
@@ -205,6 +205,7 @@ type FormanSchemaFieldState = {
|
|
|
205
205
|
label?: string;
|
|
206
206
|
path?: Array<string>;
|
|
207
207
|
data?: Record<string, unknown>;
|
|
208
|
+
extra?: Record<string, unknown>;
|
|
208
209
|
nested?: Record<string, FormanSchemaFieldState>;
|
|
209
210
|
items?: Record<string, FormanSchemaFieldState>[];
|
|
210
211
|
};
|
|
@@ -239,14 +240,19 @@ declare function toJSONSchema(field: FormanSchemaField): JSONSchema7;
|
|
|
239
240
|
declare function validateFormanWithDomains(domains: Record<string, {
|
|
240
241
|
values: Record<string, unknown>;
|
|
241
242
|
schema: FormanSchemaField[];
|
|
243
|
+
/** Extra values injected into restore states, keyed by string path (dot notation, `[index]`, backtick-escaping). */
|
|
244
|
+
restoreExtras?: Record<string, Record<string, unknown>>;
|
|
242
245
|
}>, options?: FormanValidationOptions): Promise<FormanValidationResult>;
|
|
243
246
|
/**
|
|
244
247
|
* Validates a simple Forman values against a schema
|
|
245
248
|
* @param values The values to validate
|
|
246
249
|
* @param schema The schema to validate against
|
|
247
250
|
* @param options The validation options
|
|
251
|
+
* @param restoreExtras Values to be injected into restore objects of particular fields.
|
|
252
|
+
* Keyed by string path using dot notation for nested keys, `[index]` for array indices,
|
|
253
|
+
* and backtick-escaping for keys containing dots (e.g. `"a.b[0].c"`, `` "`dotted.key`.child" ``).
|
|
248
254
|
* @returns The validation result
|
|
249
255
|
*/
|
|
250
|
-
declare function validateForman(values: Record<string, unknown>, schema: FormanSchemaField[], options?: FormanValidationOptions): Promise<FormanValidationResult>;
|
|
256
|
+
declare function validateForman(values: Record<string, unknown>, schema: FormanSchemaField[], options?: FormanValidationOptions, restoreExtras?: Record<string, Record<string, unknown>>): Promise<FormanValidationResult>;
|
|
251
257
|
|
|
252
258
|
export { type FormanSchemaDirectoryOption, type FormanSchemaExtendedNested, type FormanSchemaExtendedOptions, type FormanSchemaField, type FormanSchemaFieldType, type FormanSchemaNested, type FormanSchemaOption, type FormanSchemaOptionGroup, type FormanSchemaPathExtendedOptions, type FormanSchemaRPCButton, type FormanSchemaValue, toFormanSchema, toJSONSchema, validateForman, validateFormanWithDomains };
|
package/dist/index.d.ts
CHANGED
|
@@ -205,6 +205,7 @@ type FormanSchemaFieldState = {
|
|
|
205
205
|
label?: string;
|
|
206
206
|
path?: Array<string>;
|
|
207
207
|
data?: Record<string, unknown>;
|
|
208
|
+
extra?: Record<string, unknown>;
|
|
208
209
|
nested?: Record<string, FormanSchemaFieldState>;
|
|
209
210
|
items?: Record<string, FormanSchemaFieldState>[];
|
|
210
211
|
};
|
|
@@ -239,14 +240,19 @@ declare function toJSONSchema(field: FormanSchemaField): JSONSchema7;
|
|
|
239
240
|
declare function validateFormanWithDomains(domains: Record<string, {
|
|
240
241
|
values: Record<string, unknown>;
|
|
241
242
|
schema: FormanSchemaField[];
|
|
243
|
+
/** Extra values injected into restore states, keyed by string path (dot notation, `[index]`, backtick-escaping). */
|
|
244
|
+
restoreExtras?: Record<string, Record<string, unknown>>;
|
|
242
245
|
}>, options?: FormanValidationOptions): Promise<FormanValidationResult>;
|
|
243
246
|
/**
|
|
244
247
|
* Validates a simple Forman values against a schema
|
|
245
248
|
* @param values The values to validate
|
|
246
249
|
* @param schema The schema to validate against
|
|
247
250
|
* @param options The validation options
|
|
251
|
+
* @param restoreExtras Values to be injected into restore objects of particular fields.
|
|
252
|
+
* Keyed by string path using dot notation for nested keys, `[index]` for array indices,
|
|
253
|
+
* and backtick-escaping for keys containing dots (e.g. `"a.b[0].c"`, `` "`dotted.key`.child" ``).
|
|
248
254
|
* @returns The validation result
|
|
249
255
|
*/
|
|
250
|
-
declare function validateForman(values: Record<string, unknown>, schema: FormanSchemaField[], options?: FormanValidationOptions): Promise<FormanValidationResult>;
|
|
256
|
+
declare function validateForman(values: Record<string, unknown>, schema: FormanSchemaField[], options?: FormanValidationOptions, restoreExtras?: Record<string, Record<string, unknown>>): Promise<FormanValidationResult>;
|
|
251
257
|
|
|
252
258
|
export { type FormanSchemaDirectoryOption, type FormanSchemaExtendedNested, type FormanSchemaExtendedOptions, type FormanSchemaField, type FormanSchemaFieldType, type FormanSchemaNested, type FormanSchemaOption, type FormanSchemaOptionGroup, type FormanSchemaPathExtendedOptions, type FormanSchemaRPCButton, type FormanSchemaValue, toFormanSchema, toJSONSchema, validateForman, validateFormanWithDomains };
|
package/dist/index.js
CHANGED
|
@@ -69,6 +69,60 @@ function findValueInSelectOptions(field, value, optionsAndGroups) {
|
|
|
69
69
|
const found = optionsAndGroups.find((option) => "value" in option && option.value === value);
|
|
70
70
|
return found;
|
|
71
71
|
}
|
|
72
|
+
function pathToString(path) {
|
|
73
|
+
let result = "";
|
|
74
|
+
for (const key of path) {
|
|
75
|
+
if (typeof key === "number") {
|
|
76
|
+
result += `[${key}]`;
|
|
77
|
+
} else {
|
|
78
|
+
if (result.length > 0) {
|
|
79
|
+
result += ".";
|
|
80
|
+
}
|
|
81
|
+
if (key.includes("`")) {
|
|
82
|
+
throw new Error(`Invalid path key: backticks are not allowed in key "${key}"`);
|
|
83
|
+
}
|
|
84
|
+
result += key.includes(".") ? `\`${key}\`` : key;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return result;
|
|
88
|
+
}
|
|
89
|
+
function stringToPath(str) {
|
|
90
|
+
const path = [];
|
|
91
|
+
let i = 0;
|
|
92
|
+
while (i < str.length) {
|
|
93
|
+
if (str[i] === ".") {
|
|
94
|
+
i++;
|
|
95
|
+
if (i >= str.length) break;
|
|
96
|
+
}
|
|
97
|
+
if (str[i] === "[") {
|
|
98
|
+
const end = str.indexOf("]", i);
|
|
99
|
+
if (end === -1) {
|
|
100
|
+
throw new Error(`Invalid path: missing closing bracket in "${str}"`);
|
|
101
|
+
}
|
|
102
|
+
const num = Number(str.slice(i + 1, end));
|
|
103
|
+
if (!Number.isInteger(num) || num < 0) {
|
|
104
|
+
throw new Error(`Invalid path: non-numeric or negative index in "${str}"`);
|
|
105
|
+
}
|
|
106
|
+
path.push(num);
|
|
107
|
+
i = end + 1;
|
|
108
|
+
} else if (str[i] === "`") {
|
|
109
|
+
const end = str.indexOf("`", i + 1);
|
|
110
|
+
if (end === -1) {
|
|
111
|
+
throw new Error(`Invalid path: missing closing backtick in "${str}"`);
|
|
112
|
+
}
|
|
113
|
+
path.push(str.slice(i + 1, end));
|
|
114
|
+
i = end + 1;
|
|
115
|
+
} else {
|
|
116
|
+
let end = i;
|
|
117
|
+
while (end < str.length && str[end] !== "." && str[end] !== "[") {
|
|
118
|
+
end++;
|
|
119
|
+
}
|
|
120
|
+
path.push(str.slice(i, end));
|
|
121
|
+
i = end;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
return path;
|
|
125
|
+
}
|
|
72
126
|
function buildRestoreStructure(items) {
|
|
73
127
|
const result = {};
|
|
74
128
|
for (const item of items) {
|
|
@@ -1050,6 +1104,25 @@ async function validateFormanWithDomainsInternal(domains, options) {
|
|
|
1050
1104
|
}
|
|
1051
1105
|
);
|
|
1052
1106
|
errors.push(...result.errors);
|
|
1107
|
+
const restoreExtras = options?.states && domains[domain]?.restoreExtras;
|
|
1108
|
+
if (restoreExtras) {
|
|
1109
|
+
const fieldStateMap = new Map(
|
|
1110
|
+
roots[domain].fieldStates.map(({ path, state }) => {
|
|
1111
|
+
return [pathToString(path), state];
|
|
1112
|
+
})
|
|
1113
|
+
);
|
|
1114
|
+
for (const [fieldPath, extra] of Object.entries(restoreExtras)) {
|
|
1115
|
+
const state = fieldStateMap.get(fieldPath);
|
|
1116
|
+
if (state) {
|
|
1117
|
+
state.extra = extra;
|
|
1118
|
+
} else {
|
|
1119
|
+
roots[domain].fieldStates.push({
|
|
1120
|
+
path: stringToPath(fieldPath),
|
|
1121
|
+
state: { extra }
|
|
1122
|
+
});
|
|
1123
|
+
}
|
|
1124
|
+
}
|
|
1125
|
+
}
|
|
1053
1126
|
}
|
|
1054
1127
|
return {
|
|
1055
1128
|
valid: errors.length === 0,
|
|
@@ -1477,11 +1550,14 @@ async function handleSelectType(value, field, context) {
|
|
|
1477
1550
|
if (resolved == null || typeof resolved !== "object") {
|
|
1478
1551
|
return {
|
|
1479
1552
|
valid: false,
|
|
1480
|
-
errors: [
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1553
|
+
errors: [
|
|
1554
|
+
...errors,
|
|
1555
|
+
{
|
|
1556
|
+
domain: context.domain,
|
|
1557
|
+
path: context.path.join("."),
|
|
1558
|
+
message: `Remote resource ${optionsOrGroups} returned no data.`
|
|
1559
|
+
}
|
|
1560
|
+
]
|
|
1485
1561
|
};
|
|
1486
1562
|
}
|
|
1487
1563
|
optionsOrGroups = Array.isArray(resolved) ? resolved : [resolved];
|
|
@@ -1847,8 +1923,8 @@ function toJSONSchema(field) {
|
|
|
1847
1923
|
function validateFormanWithDomains(domains, options) {
|
|
1848
1924
|
return validateFormanWithDomainsInternal(domains, options);
|
|
1849
1925
|
}
|
|
1850
|
-
function validateForman(values, schema, options) {
|
|
1851
|
-
return validateFormanWithDomains({ default: { values, schema } }, options);
|
|
1926
|
+
function validateForman(values, schema, options, restoreExtras) {
|
|
1927
|
+
return validateFormanWithDomains({ default: { values, schema, restoreExtras } }, options);
|
|
1852
1928
|
}
|
|
1853
1929
|
export {
|
|
1854
1930
|
toFormanSchema,
|