@makehq/forman-schema 1.17.0 → 1.18.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 CHANGED
@@ -58,6 +58,9 @@ function noEmpty(text) {
58
58
  function isObject(value) {
59
59
  return typeof value === "object" && value !== null && !Array.isArray(value);
60
60
  }
61
+ function isBooleanBranchNested(nested) {
62
+ return isObject(nested) && !("store" in nested) && ("true" in nested || "false" in nested);
63
+ }
61
64
  function isOptionGroup(value) {
62
65
  return "options" in value && Array.isArray(value.options);
63
66
  }
@@ -1124,7 +1127,7 @@ function processRpcDirective(field, result, context) {
1124
1127
  return result;
1125
1128
  }
1126
1129
  function extractNestedAndDomain(field) {
1127
- const nested = isObject(field.options) ? isObject(field.options.nested) ? field.options.nested.store : field.options.nested : isObject(field.nested) ? field.nested.store : field.nested;
1130
+ const nested = isObject(field.options) ? isObject(field.options.nested) ? field.options.nested.store : field.options.nested : isBooleanBranchNested(field.nested) ? void 0 : isObject(field.nested) ? field.nested.store : field.nested;
1128
1131
  const domain = isObject(field.options) ? isObject(field.options.nested) && field.options.nested.domain ? field.options.nested.domain : void 0 : isObject(field.nested) && field.nested.domain ? field.nested.domain : void 0;
1129
1132
  return { nested, domain };
1130
1133
  }
@@ -1393,6 +1396,13 @@ async function validateFormanWithDomainsInternal(domains, options) {
1393
1396
  };
1394
1397
  }
1395
1398
  async function validateFormanValue(value, field, context) {
1399
+ if (context.registerOnly) {
1400
+ return {
1401
+ valid: true,
1402
+ errors: [],
1403
+ warnings: []
1404
+ };
1405
+ }
1396
1406
  if (isVisualType(field.type)) {
1397
1407
  return {
1398
1408
  valid: true,
@@ -1414,7 +1424,7 @@ async function validateFormanValue(value, field, context) {
1414
1424
  };
1415
1425
  }
1416
1426
  const normalizedField = normalizeFormanFieldType(field);
1417
- if (normalizedField.required && (value == null || value === "")) {
1427
+ if (normalizedField.required && !context.suppressRequired && (value == null || value === "")) {
1418
1428
  return {
1419
1429
  valid: false,
1420
1430
  errors: [
@@ -1584,7 +1594,7 @@ async function handleCollectionType2(value, field, context) {
1584
1594
  continue;
1585
1595
  }
1586
1596
  if (context2.strict && !seen.has(subField2.name)) seen.add(subField2.name);
1587
- if (path.length === 0) {
1597
+ if (path.length === 0 && !context2.registerOnly) {
1588
1598
  context2.roots[context2.domain].schemaFields.push(clampFieldForSchema(subField2));
1589
1599
  }
1590
1600
  const result2 = await validateFormanValue(value[subField2.name], subField2, {
@@ -2177,7 +2187,7 @@ async function handlePrimitiveType2(value, field, context) {
2177
2187
  }
2178
2188
  const nested = extractNestedFromField(field);
2179
2189
  if (nested) {
2180
- const result = await handleNestedFields(nested, value, field, context);
2190
+ const result = FORMAN_TYPE_MAP2[field.type] === "boolean" ? await handleBooleanNestedFields(nested, value, field, context) : await handleNestedFields(nested, value, field, context);
2181
2191
  errors.push(...result.errors);
2182
2192
  warnings.push(...result.warnings);
2183
2193
  }
@@ -2187,6 +2197,19 @@ async function handlePrimitiveType2(value, field, context) {
2187
2197
  warnings
2188
2198
  };
2189
2199
  }
2200
+ async function handleBooleanNestedFields(nested, value, field, context) {
2201
+ if (isBooleanBranchNested(nested)) {
2202
+ const active2 = value === false ? nested.false : nested.true;
2203
+ const inactive = value === false ? nested.true : nested.false;
2204
+ const result = active2 ? await handleNestedFields(active2, value, field, context) : { valid: true, errors: [], warnings: [] };
2205
+ if (context.strict && inactive) {
2206
+ await handleNestedFields(inactive, value, field, { ...context, registerOnly: true });
2207
+ }
2208
+ return result;
2209
+ }
2210
+ const active = field.reversedNested === true ? value === false : value === true;
2211
+ return handleNestedFields(nested, value, field, active ? context : { ...context, suppressRequired: true });
2212
+ }
2190
2213
 
2191
2214
  // src/json.ts
2192
2215
  var JSON_PRIMITIVE_TYPE_MAP = {
package/dist/index.d.cts CHANGED
@@ -47,8 +47,8 @@ type FormanSchemaField = {
47
47
  advanced?: boolean;
48
48
  /** Human readable label for the field */
49
49
  label?: string;
50
- /** Nested fields */
51
- nested?: FormanSchemaNested;
50
+ nested?: FormanSchemaNested | FormanSchemaBooleanNested;
51
+ reversedNested?: boolean;
52
52
  /** Validation rules */
53
53
  validate?: FormanSchemaValidation;
54
54
  /** Whether the field is disabled (`false` by default) */
@@ -186,6 +186,10 @@ type FormanSchemaExtendedNested = {
186
186
  /** Domain for the nested fields */
187
187
  domain?: string;
188
188
  };
189
+ type FormanSchemaBooleanNested = {
190
+ true?: (FormanSchemaField | string)[] | string;
191
+ false?: (FormanSchemaField | string)[] | string;
192
+ };
189
193
  /**
190
194
  * Validation result
191
195
  */
@@ -402,4 +406,4 @@ declare function validateFormanWithDomains(domains: Record<string, {
402
406
  */
403
407
  declare function validateForman(values: Record<string, unknown>, schema: FormanSchemaField[], options?: FormanValidationOptions, restoreExtras?: Record<string, Record<string, unknown>>): Promise<FormanValidationResult>;
404
408
 
405
- export { type FormanExternalValidationResult, type FormanJsonSchemaOptions, type FormanJsonSchemaResult, type FormanSchemaDirectoryOption, type FormanSchemaExtendedNested, type FormanSchemaExtendedOptions, type FormanSchemaField, type FormanSchemaFieldType, type FormanSchemaNested, type FormanSchemaOption, type FormanSchemaOptionGroup, type FormanSchemaPathExtendedOptions, type FormanSchemaRPCButton, type FormanSchemaValue, type FormanValidationOptions, type FormanValidationResult, SchemaConversionError, resolveFormanFieldType, toFormanSchema, toJSONSchema, toJSONSchemaAdvanced, validateForman, validateFormanWithDomains };
409
+ export { type FormanExternalValidationResult, type FormanJsonSchemaOptions, type FormanJsonSchemaResult, type FormanSchemaBooleanNested, type FormanSchemaDirectoryOption, type FormanSchemaExtendedNested, type FormanSchemaExtendedOptions, type FormanSchemaField, type FormanSchemaFieldType, type FormanSchemaNested, type FormanSchemaOption, type FormanSchemaOptionGroup, type FormanSchemaPathExtendedOptions, type FormanSchemaRPCButton, type FormanSchemaValue, type FormanValidationOptions, type FormanValidationResult, SchemaConversionError, resolveFormanFieldType, toFormanSchema, toJSONSchema, toJSONSchemaAdvanced, validateForman, validateFormanWithDomains };
package/dist/index.d.ts CHANGED
@@ -47,8 +47,8 @@ type FormanSchemaField = {
47
47
  advanced?: boolean;
48
48
  /** Human readable label for the field */
49
49
  label?: string;
50
- /** Nested fields */
51
- nested?: FormanSchemaNested;
50
+ nested?: FormanSchemaNested | FormanSchemaBooleanNested;
51
+ reversedNested?: boolean;
52
52
  /** Validation rules */
53
53
  validate?: FormanSchemaValidation;
54
54
  /** Whether the field is disabled (`false` by default) */
@@ -186,6 +186,10 @@ type FormanSchemaExtendedNested = {
186
186
  /** Domain for the nested fields */
187
187
  domain?: string;
188
188
  };
189
+ type FormanSchemaBooleanNested = {
190
+ true?: (FormanSchemaField | string)[] | string;
191
+ false?: (FormanSchemaField | string)[] | string;
192
+ };
189
193
  /**
190
194
  * Validation result
191
195
  */
@@ -402,4 +406,4 @@ declare function validateFormanWithDomains(domains: Record<string, {
402
406
  */
403
407
  declare function validateForman(values: Record<string, unknown>, schema: FormanSchemaField[], options?: FormanValidationOptions, restoreExtras?: Record<string, Record<string, unknown>>): Promise<FormanValidationResult>;
404
408
 
405
- export { type FormanExternalValidationResult, type FormanJsonSchemaOptions, type FormanJsonSchemaResult, type FormanSchemaDirectoryOption, type FormanSchemaExtendedNested, type FormanSchemaExtendedOptions, type FormanSchemaField, type FormanSchemaFieldType, type FormanSchemaNested, type FormanSchemaOption, type FormanSchemaOptionGroup, type FormanSchemaPathExtendedOptions, type FormanSchemaRPCButton, type FormanSchemaValue, type FormanValidationOptions, type FormanValidationResult, SchemaConversionError, resolveFormanFieldType, toFormanSchema, toJSONSchema, toJSONSchemaAdvanced, validateForman, validateFormanWithDomains };
409
+ export { type FormanExternalValidationResult, type FormanJsonSchemaOptions, type FormanJsonSchemaResult, type FormanSchemaBooleanNested, type FormanSchemaDirectoryOption, type FormanSchemaExtendedNested, type FormanSchemaExtendedOptions, type FormanSchemaField, type FormanSchemaFieldType, type FormanSchemaNested, type FormanSchemaOption, type FormanSchemaOptionGroup, type FormanSchemaPathExtendedOptions, type FormanSchemaRPCButton, type FormanSchemaValue, type FormanValidationOptions, type FormanValidationResult, SchemaConversionError, resolveFormanFieldType, toFormanSchema, toJSONSchema, toJSONSchemaAdvanced, validateForman, validateFormanWithDomains };
package/dist/index.js CHANGED
@@ -26,6 +26,9 @@ function noEmpty(text) {
26
26
  function isObject(value) {
27
27
  return typeof value === "object" && value !== null && !Array.isArray(value);
28
28
  }
29
+ function isBooleanBranchNested(nested) {
30
+ return isObject(nested) && !("store" in nested) && ("true" in nested || "false" in nested);
31
+ }
29
32
  function isOptionGroup(value) {
30
33
  return "options" in value && Array.isArray(value.options);
31
34
  }
@@ -1092,7 +1095,7 @@ function processRpcDirective(field, result, context) {
1092
1095
  return result;
1093
1096
  }
1094
1097
  function extractNestedAndDomain(field) {
1095
- const nested = isObject(field.options) ? isObject(field.options.nested) ? field.options.nested.store : field.options.nested : isObject(field.nested) ? field.nested.store : field.nested;
1098
+ const nested = isObject(field.options) ? isObject(field.options.nested) ? field.options.nested.store : field.options.nested : isBooleanBranchNested(field.nested) ? void 0 : isObject(field.nested) ? field.nested.store : field.nested;
1096
1099
  const domain = isObject(field.options) ? isObject(field.options.nested) && field.options.nested.domain ? field.options.nested.domain : void 0 : isObject(field.nested) && field.nested.domain ? field.nested.domain : void 0;
1097
1100
  return { nested, domain };
1098
1101
  }
@@ -1361,6 +1364,13 @@ async function validateFormanWithDomainsInternal(domains, options) {
1361
1364
  };
1362
1365
  }
1363
1366
  async function validateFormanValue(value, field, context) {
1367
+ if (context.registerOnly) {
1368
+ return {
1369
+ valid: true,
1370
+ errors: [],
1371
+ warnings: []
1372
+ };
1373
+ }
1364
1374
  if (isVisualType(field.type)) {
1365
1375
  return {
1366
1376
  valid: true,
@@ -1382,7 +1392,7 @@ async function validateFormanValue(value, field, context) {
1382
1392
  };
1383
1393
  }
1384
1394
  const normalizedField = normalizeFormanFieldType(field);
1385
- if (normalizedField.required && (value == null || value === "")) {
1395
+ if (normalizedField.required && !context.suppressRequired && (value == null || value === "")) {
1386
1396
  return {
1387
1397
  valid: false,
1388
1398
  errors: [
@@ -1552,7 +1562,7 @@ async function handleCollectionType2(value, field, context) {
1552
1562
  continue;
1553
1563
  }
1554
1564
  if (context2.strict && !seen.has(subField2.name)) seen.add(subField2.name);
1555
- if (path.length === 0) {
1565
+ if (path.length === 0 && !context2.registerOnly) {
1556
1566
  context2.roots[context2.domain].schemaFields.push(clampFieldForSchema(subField2));
1557
1567
  }
1558
1568
  const result2 = await validateFormanValue(value[subField2.name], subField2, {
@@ -2145,7 +2155,7 @@ async function handlePrimitiveType2(value, field, context) {
2145
2155
  }
2146
2156
  const nested = extractNestedFromField(field);
2147
2157
  if (nested) {
2148
- const result = await handleNestedFields(nested, value, field, context);
2158
+ const result = FORMAN_TYPE_MAP2[field.type] === "boolean" ? await handleBooleanNestedFields(nested, value, field, context) : await handleNestedFields(nested, value, field, context);
2149
2159
  errors.push(...result.errors);
2150
2160
  warnings.push(...result.warnings);
2151
2161
  }
@@ -2155,6 +2165,19 @@ async function handlePrimitiveType2(value, field, context) {
2155
2165
  warnings
2156
2166
  };
2157
2167
  }
2168
+ async function handleBooleanNestedFields(nested, value, field, context) {
2169
+ if (isBooleanBranchNested(nested)) {
2170
+ const active2 = value === false ? nested.false : nested.true;
2171
+ const inactive = value === false ? nested.true : nested.false;
2172
+ const result = active2 ? await handleNestedFields(active2, value, field, context) : { valid: true, errors: [], warnings: [] };
2173
+ if (context.strict && inactive) {
2174
+ await handleNestedFields(inactive, value, field, { ...context, registerOnly: true });
2175
+ }
2176
+ return result;
2177
+ }
2178
+ const active = field.reversedNested === true ? value === false : value === true;
2179
+ return handleNestedFields(nested, value, field, active ? context : { ...context, suppressRequired: true });
2180
+ }
2158
2181
 
2159
2182
  // src/json.ts
2160
2183
  var JSON_PRIMITIVE_TYPE_MAP = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@makehq/forman-schema",
3
- "version": "1.17.0",
3
+ "version": "1.18.0",
4
4
  "description": "Forman Schema Tools",
5
5
  "license": "MIT",
6
6
  "author": "Make",