@makehq/forman-schema 1.12.1 → 1.13.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -185,6 +185,7 @@ const result = await validateFormanWithDomains(
185
185
  - email → string
186
186
  - file → string
187
187
  - filename → string
188
+ - filestorage → array (of UUID strings)
188
189
  - filter → array
189
190
  - folder → string
190
191
  - hidden → string
@@ -196,6 +197,7 @@ const result = await validateFormanWithDomains(
196
197
  - path → string
197
198
  - pkey → string
198
199
  - port → number
200
+ - scenario → string
199
201
  - select → string with enum
200
202
  - text → string
201
203
  - time → string
package/dist/index.cjs CHANGED
@@ -93,13 +93,20 @@ function normalizeFormanFieldType(field) {
93
93
  }
94
94
  };
95
95
  }
96
+ function valuesMatch(a, b) {
97
+ if (a === b) return true;
98
+ if (isObject(a) && isObject(b)) return JSON.stringify(a) === JSON.stringify(b);
99
+ return false;
100
+ }
96
101
  function findValueInSelectOptions(field, value, optionsAndGroups) {
97
102
  if (!optionsAndGroups) return void 0;
103
+ const valueKey = isObject(field.options) && field.options.value ? field.options.value : "value";
104
+ const matches = (option) => valuesMatch(option[valueKey], value);
98
105
  if (field.grouped) {
99
- const found2 = optionsAndGroups.flatMap((group) => "options" in group ? group.options : []).find((option) => option.value === value);
106
+ const found2 = optionsAndGroups.flatMap((group) => "options" in group ? group.options : []).find(matches);
100
107
  if (found2) return found2;
101
108
  }
102
- const found = optionsAndGroups.find((option) => "value" in option && option.value === value);
109
+ const found = optionsAndGroups.find((option) => valueKey in option && matches(option));
103
110
  return found;
104
111
  }
105
112
  function pathToString(path) {
@@ -560,6 +567,7 @@ var FORMAN_TYPE_MAP = {
560
567
  email: "string",
561
568
  filename: "string",
562
569
  file: "string",
570
+ filestorage: "array",
563
571
  filter: "array",
564
572
  folder: "string",
565
573
  hidden: void 0,
@@ -569,6 +577,9 @@ var FORMAN_TYPE_MAP = {
569
577
  path: "string",
570
578
  pkey: "string",
571
579
  port: "number",
580
+ list: "string",
581
+ radio: "string",
582
+ scenario: "string",
572
583
  select: "string",
573
584
  udttype: "string",
574
585
  udtspec: "array",
@@ -658,7 +669,10 @@ function toJSONSchemaInternal(field, context) {
658
669
  case "dynamicCollection":
659
670
  return handleCollectionType(normalizedField, result, context);
660
671
  case "array":
672
+ case "filestorage":
661
673
  return handleArrayType(normalizedField, result, context);
674
+ case "list":
675
+ case "radio":
662
676
  case "select":
663
677
  case "account":
664
678
  case "hook":
@@ -666,6 +680,7 @@ function toJSONSchemaInternal(field, context) {
666
680
  case "keychain":
667
681
  case "datastore":
668
682
  case "aiagent":
683
+ case "scenario":
669
684
  case "file":
670
685
  case "folder":
671
686
  return handleSelectOrPathType(normalizedField, result, context);
@@ -734,7 +749,15 @@ function handleCollectionType(field, result, context) {
734
749
  return result;
735
750
  }
736
751
  function handleArrayType(field, result, context) {
737
- if (field.spec) {
752
+ if (field.type === "filestorage") {
753
+ result.items = { type: "string" };
754
+ Object.defineProperty(result, "x-filestorage", {
755
+ configurable: true,
756
+ enumerable: false,
757
+ writable: true,
758
+ value: true
759
+ });
760
+ } else if (field.spec) {
738
761
  result.items = toJSONSchemaInternal(
739
762
  Array.isArray(field.spec) ? { type: "collection", spec: field.spec } : field.spec,
740
763
  {
@@ -873,6 +896,32 @@ function handleSelectOrPathType(field, result, context) {
873
896
  writable: true,
874
897
  value: appendQueryString(optionsOrGroups, context.domain, context.tail)
875
898
  });
899
+ const xFetchOptions = {};
900
+ if (isObject(field.options)) {
901
+ for (const transferKey of ["label", "value"]) {
902
+ const transferValue = field.options[transferKey];
903
+ if (transferValue) xFetchOptions[transferKey] = transferValue;
904
+ }
905
+ }
906
+ if (![
907
+ // Reference Types are distinguished by the Loader Tool Name directly
908
+ ...FORMAN_REFERENCE_TYPES,
909
+ // Select is default
910
+ "select",
911
+ // File and Folder are distinguished by the x-path metadata, so we don't need to append it here
912
+ "file",
913
+ "folder"
914
+ ].includes(field.type)) {
915
+ xFetchOptions["type"] = field.type;
916
+ }
917
+ if (Object.keys(xFetchOptions).length) {
918
+ Object.defineProperty(result, "x-fetch-options", {
919
+ configurable: true,
920
+ enumerable: true,
921
+ writable: true,
922
+ value: xFetchOptions
923
+ });
924
+ }
876
925
  } else {
877
926
  let options = optionsOrGroups?.flatMap((optionOrGroup) => {
878
927
  if (isOptionGroup(optionOrGroup)) {
@@ -1141,6 +1190,8 @@ var FORMAN_TYPE_MAP2 = {
1141
1190
  path: "string",
1142
1191
  pkey: "string",
1143
1192
  port: "number",
1193
+ list: void 0,
1194
+ radio: void 0,
1144
1195
  select: void 0,
1145
1196
  udttype: "string",
1146
1197
  udtspec: "array",
@@ -1148,6 +1199,8 @@ var FORMAN_TYPE_MAP2 = {
1148
1199
  timestamp: "string",
1149
1200
  timezone: "string",
1150
1201
  upload: "array",
1202
+ filestorage: "array",
1203
+ scenario: "string",
1151
1204
  url: "string",
1152
1205
  uuid: "string",
1153
1206
  any: void 0
@@ -1351,7 +1404,10 @@ async function validateFormanValue(value, field, context) {
1351
1404
  case "collection":
1352
1405
  return handleCollectionType2(value, normalizedField, context);
1353
1406
  case "array":
1407
+ case "filestorage":
1354
1408
  return handleArrayType2(value, normalizedField, context);
1409
+ case "list":
1410
+ case "radio":
1355
1411
  case "select":
1356
1412
  case "account":
1357
1413
  case "hook":
@@ -2043,6 +2099,14 @@ function toFormanSchema(field) {
2043
2099
  spec
2044
2100
  };
2045
2101
  case "array":
2102
+ const filestorageMarker = Object.getOwnPropertyDescriptor(field, "x-filestorage");
2103
+ if (filestorageMarker) {
2104
+ return {
2105
+ type: "filestorage",
2106
+ label: noEmpty(field.title),
2107
+ help: noEmpty(field.description)
2108
+ };
2109
+ }
2046
2110
  const filterLogic = Object.getOwnPropertyDescriptor(field, "x-filter");
2047
2111
  if (filterLogic) {
2048
2112
  return {
package/dist/index.d.cts CHANGED
@@ -3,7 +3,7 @@ import { JSONSchema7 } from 'json-schema';
3
3
  /**
4
4
  * Valid Forman Schema field types
5
5
  */
6
- type FormanSchemaFieldType = 'aiagent' | 'account' | 'hook' | 'device' | 'keychain' | 'datastore' | 'udt' | 'scenario' | 'array' | 'collection' | 'text' | 'number' | 'boolean' | 'checkbox' | 'date' | 'json' | 'buffer' | 'cert' | 'color' | 'email' | 'filename' | 'file' | 'filter' | 'folder' | 'hidden' | 'integer' | 'uinteger' | 'path' | 'pkey' | 'port' | 'select' | 'time' | 'timestamp' | 'timezone' | 'url' | 'uuid' | `account:${string}` | `hook:${string}` | `keychain:${string}` | `device:${string}` | 'banner' | 'markdown' | 'html' | 'separator' | string;
6
+ type FormanSchemaFieldType = 'aiagent' | 'account' | 'hook' | 'device' | 'keychain' | 'datastore' | 'udt' | 'scenario' | 'array' | 'collection' | 'text' | 'number' | 'boolean' | 'checkbox' | 'date' | 'json' | 'buffer' | 'cert' | 'color' | 'email' | 'filename' | 'file' | 'filter' | 'filestorage' | 'folder' | 'hidden' | 'integer' | 'uinteger' | 'path' | 'pkey' | 'port' | 'list' | 'radio' | 'select' | 'time' | 'timestamp' | 'timezone' | 'url' | 'uuid' | `account:${string}` | `hook:${string}` | `keychain:${string}` | `device:${string}` | 'banner' | 'markdown' | 'html' | 'separator' | string;
7
7
  /**
8
8
  * Validation configuration for Forman Schema fields
9
9
  */
package/dist/index.d.ts CHANGED
@@ -3,7 +3,7 @@ import { JSONSchema7 } from 'json-schema';
3
3
  /**
4
4
  * Valid Forman Schema field types
5
5
  */
6
- type FormanSchemaFieldType = 'aiagent' | 'account' | 'hook' | 'device' | 'keychain' | 'datastore' | 'udt' | 'scenario' | 'array' | 'collection' | 'text' | 'number' | 'boolean' | 'checkbox' | 'date' | 'json' | 'buffer' | 'cert' | 'color' | 'email' | 'filename' | 'file' | 'filter' | 'folder' | 'hidden' | 'integer' | 'uinteger' | 'path' | 'pkey' | 'port' | 'select' | 'time' | 'timestamp' | 'timezone' | 'url' | 'uuid' | `account:${string}` | `hook:${string}` | `keychain:${string}` | `device:${string}` | 'banner' | 'markdown' | 'html' | 'separator' | string;
6
+ type FormanSchemaFieldType = 'aiagent' | 'account' | 'hook' | 'device' | 'keychain' | 'datastore' | 'udt' | 'scenario' | 'array' | 'collection' | 'text' | 'number' | 'boolean' | 'checkbox' | 'date' | 'json' | 'buffer' | 'cert' | 'color' | 'email' | 'filename' | 'file' | 'filter' | 'filestorage' | 'folder' | 'hidden' | 'integer' | 'uinteger' | 'path' | 'pkey' | 'port' | 'list' | 'radio' | 'select' | 'time' | 'timestamp' | 'timezone' | 'url' | 'uuid' | `account:${string}` | `hook:${string}` | `keychain:${string}` | `device:${string}` | 'banner' | 'markdown' | 'html' | 'separator' | string;
7
7
  /**
8
8
  * Validation configuration for Forman Schema fields
9
9
  */
package/dist/index.js CHANGED
@@ -64,13 +64,20 @@ function normalizeFormanFieldType(field) {
64
64
  }
65
65
  };
66
66
  }
67
+ function valuesMatch(a, b) {
68
+ if (a === b) return true;
69
+ if (isObject(a) && isObject(b)) return JSON.stringify(a) === JSON.stringify(b);
70
+ return false;
71
+ }
67
72
  function findValueInSelectOptions(field, value, optionsAndGroups) {
68
73
  if (!optionsAndGroups) return void 0;
74
+ const valueKey = isObject(field.options) && field.options.value ? field.options.value : "value";
75
+ const matches = (option) => valuesMatch(option[valueKey], value);
69
76
  if (field.grouped) {
70
- const found2 = optionsAndGroups.flatMap((group) => "options" in group ? group.options : []).find((option) => option.value === value);
77
+ const found2 = optionsAndGroups.flatMap((group) => "options" in group ? group.options : []).find(matches);
71
78
  if (found2) return found2;
72
79
  }
73
- const found = optionsAndGroups.find((option) => "value" in option && option.value === value);
80
+ const found = optionsAndGroups.find((option) => valueKey in option && matches(option));
74
81
  return found;
75
82
  }
76
83
  function pathToString(path) {
@@ -531,6 +538,7 @@ var FORMAN_TYPE_MAP = {
531
538
  email: "string",
532
539
  filename: "string",
533
540
  file: "string",
541
+ filestorage: "array",
534
542
  filter: "array",
535
543
  folder: "string",
536
544
  hidden: void 0,
@@ -540,6 +548,9 @@ var FORMAN_TYPE_MAP = {
540
548
  path: "string",
541
549
  pkey: "string",
542
550
  port: "number",
551
+ list: "string",
552
+ radio: "string",
553
+ scenario: "string",
543
554
  select: "string",
544
555
  udttype: "string",
545
556
  udtspec: "array",
@@ -629,7 +640,10 @@ function toJSONSchemaInternal(field, context) {
629
640
  case "dynamicCollection":
630
641
  return handleCollectionType(normalizedField, result, context);
631
642
  case "array":
643
+ case "filestorage":
632
644
  return handleArrayType(normalizedField, result, context);
645
+ case "list":
646
+ case "radio":
633
647
  case "select":
634
648
  case "account":
635
649
  case "hook":
@@ -637,6 +651,7 @@ function toJSONSchemaInternal(field, context) {
637
651
  case "keychain":
638
652
  case "datastore":
639
653
  case "aiagent":
654
+ case "scenario":
640
655
  case "file":
641
656
  case "folder":
642
657
  return handleSelectOrPathType(normalizedField, result, context);
@@ -705,7 +720,15 @@ function handleCollectionType(field, result, context) {
705
720
  return result;
706
721
  }
707
722
  function handleArrayType(field, result, context) {
708
- if (field.spec) {
723
+ if (field.type === "filestorage") {
724
+ result.items = { type: "string" };
725
+ Object.defineProperty(result, "x-filestorage", {
726
+ configurable: true,
727
+ enumerable: false,
728
+ writable: true,
729
+ value: true
730
+ });
731
+ } else if (field.spec) {
709
732
  result.items = toJSONSchemaInternal(
710
733
  Array.isArray(field.spec) ? { type: "collection", spec: field.spec } : field.spec,
711
734
  {
@@ -844,6 +867,32 @@ function handleSelectOrPathType(field, result, context) {
844
867
  writable: true,
845
868
  value: appendQueryString(optionsOrGroups, context.domain, context.tail)
846
869
  });
870
+ const xFetchOptions = {};
871
+ if (isObject(field.options)) {
872
+ for (const transferKey of ["label", "value"]) {
873
+ const transferValue = field.options[transferKey];
874
+ if (transferValue) xFetchOptions[transferKey] = transferValue;
875
+ }
876
+ }
877
+ if (![
878
+ // Reference Types are distinguished by the Loader Tool Name directly
879
+ ...FORMAN_REFERENCE_TYPES,
880
+ // Select is default
881
+ "select",
882
+ // File and Folder are distinguished by the x-path metadata, so we don't need to append it here
883
+ "file",
884
+ "folder"
885
+ ].includes(field.type)) {
886
+ xFetchOptions["type"] = field.type;
887
+ }
888
+ if (Object.keys(xFetchOptions).length) {
889
+ Object.defineProperty(result, "x-fetch-options", {
890
+ configurable: true,
891
+ enumerable: true,
892
+ writable: true,
893
+ value: xFetchOptions
894
+ });
895
+ }
847
896
  } else {
848
897
  let options = optionsOrGroups?.flatMap((optionOrGroup) => {
849
898
  if (isOptionGroup(optionOrGroup)) {
@@ -1112,6 +1161,8 @@ var FORMAN_TYPE_MAP2 = {
1112
1161
  path: "string",
1113
1162
  pkey: "string",
1114
1163
  port: "number",
1164
+ list: void 0,
1165
+ radio: void 0,
1115
1166
  select: void 0,
1116
1167
  udttype: "string",
1117
1168
  udtspec: "array",
@@ -1119,6 +1170,8 @@ var FORMAN_TYPE_MAP2 = {
1119
1170
  timestamp: "string",
1120
1171
  timezone: "string",
1121
1172
  upload: "array",
1173
+ filestorage: "array",
1174
+ scenario: "string",
1122
1175
  url: "string",
1123
1176
  uuid: "string",
1124
1177
  any: void 0
@@ -1322,7 +1375,10 @@ async function validateFormanValue(value, field, context) {
1322
1375
  case "collection":
1323
1376
  return handleCollectionType2(value, normalizedField, context);
1324
1377
  case "array":
1378
+ case "filestorage":
1325
1379
  return handleArrayType2(value, normalizedField, context);
1380
+ case "list":
1381
+ case "radio":
1326
1382
  case "select":
1327
1383
  case "account":
1328
1384
  case "hook":
@@ -2014,6 +2070,14 @@ function toFormanSchema(field) {
2014
2070
  spec
2015
2071
  };
2016
2072
  case "array":
2073
+ const filestorageMarker = Object.getOwnPropertyDescriptor(field, "x-filestorage");
2074
+ if (filestorageMarker) {
2075
+ return {
2076
+ type: "filestorage",
2077
+ label: noEmpty(field.title),
2078
+ help: noEmpty(field.description)
2079
+ };
2080
+ }
2017
2081
  const filterLogic = Object.getOwnPropertyDescriptor(field, "x-filter");
2018
2082
  if (filterLogic) {
2019
2083
  return {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@makehq/forman-schema",
3
- "version": "1.12.1",
3
+ "version": "1.13.1",
4
4
  "description": "Forman Schema Tools",
5
5
  "license": "MIT",
6
6
  "author": "Make",