tinybase 9.4.0 → 9.5.0-beta.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.
Files changed (126) hide show
  1. package/@types/_internal/store/with-schemas/index.d.ts +43 -8
  2. package/@types/mergeable-store/with-schemas/index.d.ts +30 -11
  3. package/@types/queries/index.d.ts +11 -11
  4. package/@types/queries/with-schemas/index.d.ts +17 -3
  5. package/@types/schematizers/index.d.ts +6 -4
  6. package/@types/schematizers/schematizer-arktype/index.d.ts +6 -6
  7. package/@types/schematizers/schematizer-arktype/with-schemas/index.d.ts +112 -1
  8. package/@types/schematizers/schematizer-effect/index.d.ts +9 -11
  9. package/@types/schematizers/schematizer-effect/with-schemas/index.d.ts +114 -1
  10. package/@types/schematizers/schematizer-typebox/index.d.ts +7 -7
  11. package/@types/schematizers/schematizer-typebox/with-schemas/index.d.ts +114 -1
  12. package/@types/schematizers/schematizer-valibot/index.d.ts +6 -6
  13. package/@types/schematizers/schematizer-valibot/with-schemas/index.d.ts +112 -1
  14. package/@types/schematizers/schematizer-yup/index.d.ts +5 -4
  15. package/@types/schematizers/schematizer-yup/with-schemas/index.d.ts +112 -1
  16. package/@types/schematizers/schematizer-zod/index.d.ts +6 -6
  17. package/@types/schematizers/schematizer-zod/with-schemas/index.d.ts +112 -1
  18. package/@types/schematizers/with-schemas/index.d.ts +113 -4
  19. package/@types/store/index.d.ts +175 -16
  20. package/@types/store/with-schemas/index.d.ts +238 -55
  21. package/@types/synchronizers/with-schemas/index.d.ts +12 -2
  22. package/@types/ui-react/with-schemas/index.d.ts +576 -7
  23. package/@types/ui-react-dom/index.d.ts +10 -10
  24. package/@types/ui-react-dom/with-schemas/index.d.ts +94 -10
  25. package/@types/ui-react-dom-charts/index.d.ts +7 -7
  26. package/@types/ui-react-dom-charts/with-schemas/index.d.ts +7 -7
  27. package/@types/ui-react-inspector/index.d.ts +1 -1
  28. package/@types/ui-react-inspector/with-schemas/index.d.ts +1 -1
  29. package/@types/ui-solid/with-schemas/index.d.ts +340 -7
  30. package/@types/ui-solid-dom/index.d.ts +10 -10
  31. package/@types/ui-solid-dom/with-schemas/index.d.ts +94 -10
  32. package/@types/ui-solid-inspector/index.d.ts +1 -1
  33. package/@types/ui-solid-inspector/with-schemas/index.d.ts +1 -1
  34. package/@types/ui-svelte/with-schemas/index.d.ts +30 -0
  35. package/@types/ui-svelte-dom/index.d.ts +10 -10
  36. package/@types/ui-svelte-dom/with-schemas/index.d.ts +94 -10
  37. package/@types/ui-svelte-inspector/index.d.ts +1 -1
  38. package/@types/ui-svelte-inspector/with-schemas/index.d.ts +1 -1
  39. package/agents.md +4 -0
  40. package/index.js +76 -22
  41. package/mergeable-store/index.js +76 -22
  42. package/mergeable-store/with-schemas/index.js +76 -22
  43. package/min/index.js +1 -1
  44. package/min/index.js.gz +0 -0
  45. package/min/mergeable-store/index.js +1 -1
  46. package/min/mergeable-store/index.js.gz +0 -0
  47. package/min/mergeable-store/with-schemas/index.js +1 -1
  48. package/min/mergeable-store/with-schemas/index.js.gz +0 -0
  49. package/min/omni/index.js +1 -1
  50. package/min/omni/index.js.gz +0 -0
  51. package/min/omni/with-schemas/index.js +1 -1
  52. package/min/omni/with-schemas/index.js.gz +0 -0
  53. package/min/schematizers/index.js +1 -1
  54. package/min/schematizers/index.js.gz +0 -0
  55. package/min/schematizers/schematizer-arktype/index.js +1 -1
  56. package/min/schematizers/schematizer-arktype/index.js.gz +0 -0
  57. package/min/schematizers/schematizer-arktype/with-schemas/index.js +1 -1
  58. package/min/schematizers/schematizer-arktype/with-schemas/index.js.gz +0 -0
  59. package/min/schematizers/schematizer-effect/index.js +1 -1
  60. package/min/schematizers/schematizer-effect/index.js.gz +0 -0
  61. package/min/schematizers/schematizer-effect/with-schemas/index.js +1 -1
  62. package/min/schematizers/schematizer-effect/with-schemas/index.js.gz +0 -0
  63. package/min/schematizers/schematizer-typebox/index.js +1 -1
  64. package/min/schematizers/schematizer-typebox/index.js.gz +0 -0
  65. package/min/schematizers/schematizer-typebox/with-schemas/index.js +1 -1
  66. package/min/schematizers/schematizer-typebox/with-schemas/index.js.gz +0 -0
  67. package/min/schematizers/schematizer-valibot/index.js +1 -1
  68. package/min/schematizers/schematizer-valibot/index.js.gz +0 -0
  69. package/min/schematizers/schematizer-valibot/with-schemas/index.js +1 -1
  70. package/min/schematizers/schematizer-valibot/with-schemas/index.js.gz +0 -0
  71. package/min/schematizers/schematizer-yup/index.js +1 -1
  72. package/min/schematizers/schematizer-yup/index.js.gz +0 -0
  73. package/min/schematizers/schematizer-yup/with-schemas/index.js +1 -1
  74. package/min/schematizers/schematizer-yup/with-schemas/index.js.gz +0 -0
  75. package/min/schematizers/schematizer-zod/index.js +1 -1
  76. package/min/schematizers/schematizer-zod/index.js.gz +0 -0
  77. package/min/schematizers/schematizer-zod/with-schemas/index.js +1 -1
  78. package/min/schematizers/schematizer-zod/with-schemas/index.js.gz +0 -0
  79. package/min/schematizers/with-schemas/index.js +1 -1
  80. package/min/schematizers/with-schemas/index.js.gz +0 -0
  81. package/min/store/index.js +1 -1
  82. package/min/store/index.js.gz +0 -0
  83. package/min/store/with-schemas/index.js +1 -1
  84. package/min/store/with-schemas/index.js.gz +0 -0
  85. package/min/ui-react-inspector/index.js +1 -1
  86. package/min/ui-react-inspector/index.js.gz +0 -0
  87. package/min/ui-react-inspector/with-schemas/index.js +1 -1
  88. package/min/ui-react-inspector/with-schemas/index.js.gz +0 -0
  89. package/min/ui-solid-inspector/index.js +1 -1
  90. package/min/ui-solid-inspector/index.js.gz +0 -0
  91. package/min/ui-solid-inspector/with-schemas/index.js +1 -1
  92. package/min/ui-solid-inspector/with-schemas/index.js.gz +0 -0
  93. package/min/ui-svelte-inspector/index.js +1 -1
  94. package/min/ui-svelte-inspector/index.js.gz +0 -0
  95. package/min/ui-svelte-inspector/with-schemas/index.js +1 -1
  96. package/min/ui-svelte-inspector/with-schemas/index.js.gz +0 -0
  97. package/min/with-schemas/index.js +1 -1
  98. package/min/with-schemas/index.js.gz +0 -0
  99. package/omni/index.js +76 -22
  100. package/omni/with-schemas/index.js +76 -22
  101. package/package.json +2 -2
  102. package/readme.md +14 -14
  103. package/releases.md +95 -65
  104. package/schematizers/index.js +54 -6
  105. package/schematizers/schematizer-arktype/index.js +99 -19
  106. package/schematizers/schematizer-arktype/with-schemas/index.js +99 -19
  107. package/schematizers/schematizer-effect/index.js +101 -11
  108. package/schematizers/schematizer-effect/with-schemas/index.js +101 -11
  109. package/schematizers/schematizer-typebox/index.js +87 -11
  110. package/schematizers/schematizer-typebox/with-schemas/index.js +87 -11
  111. package/schematizers/schematizer-valibot/index.js +125 -21
  112. package/schematizers/schematizer-valibot/with-schemas/index.js +125 -21
  113. package/schematizers/schematizer-yup/index.js +58 -14
  114. package/schematizers/schematizer-yup/with-schemas/index.js +58 -14
  115. package/schematizers/schematizer-zod/index.js +131 -12
  116. package/schematizers/schematizer-zod/with-schemas/index.js +131 -12
  117. package/schematizers/with-schemas/index.js +54 -6
  118. package/store/index.js +76 -22
  119. package/store/with-schemas/index.js +76 -22
  120. package/ui-react-inspector/index.js +76 -22
  121. package/ui-react-inspector/with-schemas/index.js +76 -22
  122. package/ui-solid-inspector/index.js +76 -22
  123. package/ui-solid-inspector/with-schemas/index.js +76 -22
  124. package/ui-svelte-inspector/index.js +76 -22
  125. package/ui-svelte-inspector/with-schemas/index.js +76 -22
  126. package/with-schemas/index.js +76 -22
@@ -6,29 +6,40 @@ const NUMBER = getTypeOf(0);
6
6
  const OBJECT = 'object';
7
7
  const ARRAY = 'array';
8
8
  const TYPE = 'type';
9
+ const ENUM = 'enum';
9
10
  const DEFAULT = 'default';
10
11
  const ALLOW_NULL = 'allowNull';
12
+ const NULL = 'null';
11
13
  const FALLBACK = 'fallback';
12
14
  const NULLABLE = 'nullable';
13
15
  const OPTIONAL = 'optional';
14
16
  const REQUIRED = 'required';
15
17
  const WRAPPED = 'wrapped';
16
18
  const RECORD = 'record';
19
+ const UNDEFINED = '\uFFFC';
20
+ const JSON_PREFIX = '\uFFFD';
17
21
 
18
22
  const getIfNotFunction = (predicate) => (value, then, otherwise) =>
19
23
  predicate(value)
20
24
  ? /* istanbul ignore next */
21
25
  otherwise?.()
22
26
  : then(value);
27
+ const isFiniteNumber = isFinite;
23
28
  const isNullish = (thing) => thing == null;
24
29
  const isUndefined = (thing) => thing === void 0;
30
+ const isNull = (thing) => thing === null;
25
31
  const ifNotNullish = getIfNotFunction(isNullish);
26
32
  const ifNotUndefined = getIfNotFunction(isUndefined);
33
+ const isTypeStringOrBoolean = (type) => type == STRING || type == BOOLEAN;
27
34
  const isString = (thing) => getTypeOf(thing) == STRING;
35
+ const isArray = (thing) => Array.isArray(thing);
28
36
  const size = (thing) => thing.length;
29
37
 
38
+ const arrayIndexOf = (array, value) => array.indexOf(value);
30
39
  const arrayEvery = (array, cb) => array.every(cb);
31
40
  const arrayForEach = (array, cb) => array.forEach(cb);
41
+ const arrayFilter = (array, cb) => array.filter(cb);
42
+ const arrayPush = (array, ...values) => array.push(...values);
32
43
 
33
44
  const object = Object;
34
45
  const getPrototypeOf = (obj) => object.getPrototypeOf(obj);
@@ -64,6 +75,44 @@ const objForEach = (obj, cb) =>
64
75
  const objSize = (obj) => size(objIds(obj));
65
76
  const objIsEmpty = (obj) => isObject(obj) && objSize(obj) == 0;
66
77
 
78
+ const getCellOrValueType = (cellOrValue) => {
79
+ if (isNull(cellOrValue)) {
80
+ return NULL;
81
+ }
82
+ if (isArray(cellOrValue)) {
83
+ return ARRAY;
84
+ }
85
+ if (isObject(cellOrValue)) {
86
+ return OBJECT;
87
+ }
88
+ const type = getTypeOf(cellOrValue);
89
+ return isTypeStringOrBoolean(type) ||
90
+ (type == NUMBER && isFiniteNumber(cellOrValue))
91
+ ? type
92
+ : void 0;
93
+ };
94
+ const isJsonType = (type) => type == OBJECT || type == ARRAY;
95
+ const isCellOrValueSchemaType = (type) =>
96
+ isTypeStringOrBoolean(type) || type == NUMBER || isJsonType(type);
97
+ const isCellOrValueSchemaTypes = (types) =>
98
+ isArray(types)
99
+ ? !isUndefined(types[0]) && arrayEvery(types, isCellOrValueSchemaType)
100
+ : isCellOrValueSchemaType(types);
101
+ const isEncodedJson = (value) => isString(value) && value[0] == JSON_PREFIX;
102
+ const isReservedString = (value, encoded = 0) =>
103
+ value === UNDEFINED || (!encoded && isEncodedJson(value));
104
+
105
+ const getTypeOrTypeUnion = (types) => {
106
+ if (!arrayEvery(types, isCellOrValueSchemaType)) {
107
+ return;
108
+ }
109
+ const uniqueTypes = arrayFilter(
110
+ types,
111
+ (type, index) => arrayIndexOf(types, type) == index,
112
+ );
113
+ return uniqueTypes[1] ? uniqueTypes : uniqueTypes[0];
114
+ };
115
+
67
116
  const createCustomSchematizer = (
68
117
  unwrapSchema,
69
118
  getProperties,
@@ -73,16 +122,27 @@ const createCustomSchematizer = (
73
122
  const [unwrapped, defaultValue, allowNull, unwrappedRequired = required] =
74
123
  unwrapSchema(schema, void 0, void 0, required);
75
124
  const type = unwrapped?.type;
125
+ const enumValues = unwrapped?.[ENUM];
126
+ const isEnum =
127
+ isUndefined(type) &&
128
+ isArray(enumValues) &&
129
+ !isUndefined(enumValues[0]) &&
130
+ arrayEvery(enumValues, (enumValue) => {
131
+ const enumType = getCellOrValueType(enumValue);
132
+ return (
133
+ !isNull(enumValue) &&
134
+ !isUndefined(enumType) &&
135
+ !isJsonType(enumType) &&
136
+ !isReservedString(enumValue)
137
+ );
138
+ });
76
139
  if (
77
- type !== STRING &&
78
- type !== NUMBER &&
79
- type !== BOOLEAN &&
80
- type !== OBJECT &&
81
- type !== ARRAY
140
+ !isEnum &&
141
+ (!isUndefined(enumValues) || !isCellOrValueSchemaTypes(type))
82
142
  ) {
83
143
  return void 0;
84
144
  }
85
- const cellOrValueSchema = {[TYPE]: type};
145
+ const cellOrValueSchema = isEnum ? {[ENUM]: enumValues} : {[TYPE]: type};
86
146
  ifNotUndefined(defaultValue, (defaultValue2) => {
87
147
  cellOrValueSchema[DEFAULT] = defaultValue2;
88
148
  });
@@ -134,6 +194,7 @@ const createCustomSchematizer = (
134
194
 
135
195
  const LITERAL = 'literal';
136
196
  const PICKLIST = 'picklist';
197
+ const VALIBOT_UNION = 'union';
137
198
  const unwrapSchema = (schema, defaultValue, allowNull, required = true) => {
138
199
  const type = schema?.type;
139
200
  return type === OPTIONAL
@@ -152,26 +213,69 @@ const unwrapSchema = (schema, defaultValue, allowNull, required = true) => {
152
213
  allowNull ?? false,
153
214
  required,
154
215
  ]
155
- : type === PICKLIST && arrayEvery(schema.options, isString)
216
+ : type === PICKLIST
156
217
  ? [
157
- {[TYPE]: STRING},
218
+ {[ENUM]: schema.options},
158
219
  defaultValue ?? schema?.[FALLBACK],
159
220
  allowNull ?? false,
160
221
  required,
161
222
  ]
162
- : type === LITERAL && isString(schema.literal)
163
- ? [
164
- {[TYPE]: STRING},
165
- defaultValue ?? schema?.[FALLBACK],
166
- allowNull ?? false,
167
- required,
168
- ]
169
- : [
170
- schema,
171
- defaultValue ?? schema?.[FALLBACK],
172
- allowNull ?? false,
173
- required,
174
- ];
223
+ : type === VALIBOT_UNION
224
+ ? unwrapUnion(schema, defaultValue, allowNull, required)
225
+ : type === LITERAL
226
+ ? [
227
+ {[ENUM]: [schema.literal]},
228
+ defaultValue ?? schema?.[FALLBACK],
229
+ allowNull ?? false,
230
+ required,
231
+ ]
232
+ : [
233
+ schema,
234
+ defaultValue ?? schema?.[FALLBACK],
235
+ allowNull ?? false,
236
+ required,
237
+ ];
238
+ };
239
+ const unwrapUnion = (schema, defaultValue, allowNull, required = true) => {
240
+ const nonNullOptions = arrayFilter(
241
+ schema.options,
242
+ (option) => option.type !== NULL,
243
+ );
244
+ const hasNull = nonNullOptions.length !== schema.options.length;
245
+ const enumValues = [];
246
+ const allEnums = arrayEvery(nonNullOptions, (option) => {
247
+ const values =
248
+ option.type === LITERAL
249
+ ? [option.literal]
250
+ : option.type === PICKLIST
251
+ ? option.options
252
+ : void 0;
253
+ if (isUndefined(values)) {
254
+ return false;
255
+ }
256
+ arrayForEach(values, (value) => arrayPush(enumValues, value));
257
+ return true;
258
+ });
259
+ const types = [];
260
+ if (!allEnums) {
261
+ arrayForEach(nonNullOptions, (option) => {
262
+ if (option.type === LITERAL) {
263
+ arrayPush(types, getCellOrValueType(option.literal));
264
+ } else if (option.type === PICKLIST) {
265
+ arrayForEach(option.options, (value) =>
266
+ arrayPush(types, getCellOrValueType(value)),
267
+ );
268
+ } else {
269
+ arrayPush(types, option.type === RECORD ? OBJECT : option.type);
270
+ }
271
+ });
272
+ }
273
+ return [
274
+ allEnums ? {[ENUM]: enumValues} : {type: getTypeOrTypeUnion(types)},
275
+ defaultValue ?? schema?.[FALLBACK],
276
+ allowNull || hasNull,
277
+ required,
278
+ ];
175
279
  };
176
280
  const getProperties = (schema) => schema?.entries;
177
281
  const createValibotSchematizer = () =>
@@ -6,29 +6,40 @@ const NUMBER = getTypeOf(0);
6
6
  const OBJECT = 'object';
7
7
  const ARRAY = 'array';
8
8
  const TYPE = 'type';
9
+ const ENUM = 'enum';
9
10
  const DEFAULT = 'default';
10
11
  const ALLOW_NULL = 'allowNull';
12
+ const NULL = 'null';
11
13
  const FALLBACK = 'fallback';
12
14
  const NULLABLE = 'nullable';
13
15
  const OPTIONAL = 'optional';
14
16
  const REQUIRED = 'required';
15
17
  const WRAPPED = 'wrapped';
16
18
  const RECORD = 'record';
19
+ const UNDEFINED = '\uFFFC';
20
+ const JSON_PREFIX = '\uFFFD';
17
21
 
18
22
  const getIfNotFunction = (predicate) => (value, then, otherwise) =>
19
23
  predicate(value)
20
24
  ? /* istanbul ignore next */
21
25
  otherwise?.()
22
26
  : then(value);
27
+ const isFiniteNumber = isFinite;
23
28
  const isNullish = (thing) => thing == null;
24
29
  const isUndefined = (thing) => thing === void 0;
30
+ const isNull = (thing) => thing === null;
25
31
  const ifNotNullish = getIfNotFunction(isNullish);
26
32
  const ifNotUndefined = getIfNotFunction(isUndefined);
33
+ const isTypeStringOrBoolean = (type) => type == STRING || type == BOOLEAN;
27
34
  const isString = (thing) => getTypeOf(thing) == STRING;
35
+ const isArray = (thing) => Array.isArray(thing);
28
36
  const size = (thing) => thing.length;
29
37
 
38
+ const arrayIndexOf = (array, value) => array.indexOf(value);
30
39
  const arrayEvery = (array, cb) => array.every(cb);
31
40
  const arrayForEach = (array, cb) => array.forEach(cb);
41
+ const arrayFilter = (array, cb) => array.filter(cb);
42
+ const arrayPush = (array, ...values) => array.push(...values);
32
43
 
33
44
  const object = Object;
34
45
  const getPrototypeOf = (obj) => object.getPrototypeOf(obj);
@@ -64,6 +75,44 @@ const objForEach = (obj, cb) =>
64
75
  const objSize = (obj) => size(objIds(obj));
65
76
  const objIsEmpty = (obj) => isObject(obj) && objSize(obj) == 0;
66
77
 
78
+ const getCellOrValueType = (cellOrValue) => {
79
+ if (isNull(cellOrValue)) {
80
+ return NULL;
81
+ }
82
+ if (isArray(cellOrValue)) {
83
+ return ARRAY;
84
+ }
85
+ if (isObject(cellOrValue)) {
86
+ return OBJECT;
87
+ }
88
+ const type = getTypeOf(cellOrValue);
89
+ return isTypeStringOrBoolean(type) ||
90
+ (type == NUMBER && isFiniteNumber(cellOrValue))
91
+ ? type
92
+ : void 0;
93
+ };
94
+ const isJsonType = (type) => type == OBJECT || type == ARRAY;
95
+ const isCellOrValueSchemaType = (type) =>
96
+ isTypeStringOrBoolean(type) || type == NUMBER || isJsonType(type);
97
+ const isCellOrValueSchemaTypes = (types) =>
98
+ isArray(types)
99
+ ? !isUndefined(types[0]) && arrayEvery(types, isCellOrValueSchemaType)
100
+ : isCellOrValueSchemaType(types);
101
+ const isEncodedJson = (value) => isString(value) && value[0] == JSON_PREFIX;
102
+ const isReservedString = (value, encoded = 0) =>
103
+ value === UNDEFINED || (!encoded && isEncodedJson(value));
104
+
105
+ const getTypeOrTypeUnion = (types) => {
106
+ if (!arrayEvery(types, isCellOrValueSchemaType)) {
107
+ return;
108
+ }
109
+ const uniqueTypes = arrayFilter(
110
+ types,
111
+ (type, index) => arrayIndexOf(types, type) == index,
112
+ );
113
+ return uniqueTypes[1] ? uniqueTypes : uniqueTypes[0];
114
+ };
115
+
67
116
  const createCustomSchematizer = (
68
117
  unwrapSchema,
69
118
  getProperties,
@@ -73,16 +122,27 @@ const createCustomSchematizer = (
73
122
  const [unwrapped, defaultValue, allowNull, unwrappedRequired = required] =
74
123
  unwrapSchema(schema, void 0, void 0, required);
75
124
  const type = unwrapped?.type;
125
+ const enumValues = unwrapped?.[ENUM];
126
+ const isEnum =
127
+ isUndefined(type) &&
128
+ isArray(enumValues) &&
129
+ !isUndefined(enumValues[0]) &&
130
+ arrayEvery(enumValues, (enumValue) => {
131
+ const enumType = getCellOrValueType(enumValue);
132
+ return (
133
+ !isNull(enumValue) &&
134
+ !isUndefined(enumType) &&
135
+ !isJsonType(enumType) &&
136
+ !isReservedString(enumValue)
137
+ );
138
+ });
76
139
  if (
77
- type !== STRING &&
78
- type !== NUMBER &&
79
- type !== BOOLEAN &&
80
- type !== OBJECT &&
81
- type !== ARRAY
140
+ !isEnum &&
141
+ (!isUndefined(enumValues) || !isCellOrValueSchemaTypes(type))
82
142
  ) {
83
143
  return void 0;
84
144
  }
85
- const cellOrValueSchema = {[TYPE]: type};
145
+ const cellOrValueSchema = isEnum ? {[ENUM]: enumValues} : {[TYPE]: type};
86
146
  ifNotUndefined(defaultValue, (defaultValue2) => {
87
147
  cellOrValueSchema[DEFAULT] = defaultValue2;
88
148
  });
@@ -134,6 +194,7 @@ const createCustomSchematizer = (
134
194
 
135
195
  const LITERAL = 'literal';
136
196
  const PICKLIST = 'picklist';
197
+ const VALIBOT_UNION = 'union';
137
198
  const unwrapSchema = (schema, defaultValue, allowNull, required = true) => {
138
199
  const type = schema?.type;
139
200
  return type === OPTIONAL
@@ -152,26 +213,69 @@ const unwrapSchema = (schema, defaultValue, allowNull, required = true) => {
152
213
  allowNull ?? false,
153
214
  required,
154
215
  ]
155
- : type === PICKLIST && arrayEvery(schema.options, isString)
216
+ : type === PICKLIST
156
217
  ? [
157
- {[TYPE]: STRING},
218
+ {[ENUM]: schema.options},
158
219
  defaultValue ?? schema?.[FALLBACK],
159
220
  allowNull ?? false,
160
221
  required,
161
222
  ]
162
- : type === LITERAL && isString(schema.literal)
163
- ? [
164
- {[TYPE]: STRING},
165
- defaultValue ?? schema?.[FALLBACK],
166
- allowNull ?? false,
167
- required,
168
- ]
169
- : [
170
- schema,
171
- defaultValue ?? schema?.[FALLBACK],
172
- allowNull ?? false,
173
- required,
174
- ];
223
+ : type === VALIBOT_UNION
224
+ ? unwrapUnion(schema, defaultValue, allowNull, required)
225
+ : type === LITERAL
226
+ ? [
227
+ {[ENUM]: [schema.literal]},
228
+ defaultValue ?? schema?.[FALLBACK],
229
+ allowNull ?? false,
230
+ required,
231
+ ]
232
+ : [
233
+ schema,
234
+ defaultValue ?? schema?.[FALLBACK],
235
+ allowNull ?? false,
236
+ required,
237
+ ];
238
+ };
239
+ const unwrapUnion = (schema, defaultValue, allowNull, required = true) => {
240
+ const nonNullOptions = arrayFilter(
241
+ schema.options,
242
+ (option) => option.type !== NULL,
243
+ );
244
+ const hasNull = nonNullOptions.length !== schema.options.length;
245
+ const enumValues = [];
246
+ const allEnums = arrayEvery(nonNullOptions, (option) => {
247
+ const values =
248
+ option.type === LITERAL
249
+ ? [option.literal]
250
+ : option.type === PICKLIST
251
+ ? option.options
252
+ : void 0;
253
+ if (isUndefined(values)) {
254
+ return false;
255
+ }
256
+ arrayForEach(values, (value) => arrayPush(enumValues, value));
257
+ return true;
258
+ });
259
+ const types = [];
260
+ if (!allEnums) {
261
+ arrayForEach(nonNullOptions, (option) => {
262
+ if (option.type === LITERAL) {
263
+ arrayPush(types, getCellOrValueType(option.literal));
264
+ } else if (option.type === PICKLIST) {
265
+ arrayForEach(option.options, (value) =>
266
+ arrayPush(types, getCellOrValueType(value)),
267
+ );
268
+ } else {
269
+ arrayPush(types, option.type === RECORD ? OBJECT : option.type);
270
+ }
271
+ });
272
+ }
273
+ return [
274
+ allEnums ? {[ENUM]: enumValues} : {type: getTypeOrTypeUnion(types)},
275
+ defaultValue ?? schema?.[FALLBACK],
276
+ allowNull || hasNull,
277
+ required,
278
+ ];
175
279
  };
176
280
  const getProperties = (schema) => schema?.entries;
177
281
  const createValibotSchematizer = () =>
@@ -6,27 +6,37 @@ const NUMBER = getTypeOf(0);
6
6
  const OBJECT = 'object';
7
7
  const ARRAY = 'array';
8
8
  const TYPE = 'type';
9
+ const ENUM = 'enum';
9
10
  const DEFAULT = 'default';
10
11
  const ALLOW_NULL = 'allowNull';
12
+ const NULL = 'null';
11
13
  const NULLABLE = 'nullable';
12
14
  const OPTIONAL = 'optional';
13
15
  const REQUIRED = 'required';
16
+ const UNDEFINED = '\uFFFC';
17
+ const JSON_PREFIX = '\uFFFD';
14
18
 
15
19
  const getIfNotFunction = (predicate) => (value, then, otherwise) =>
16
20
  predicate(value)
17
21
  ? /* istanbul ignore next */
18
22
  otherwise?.()
19
23
  : then(value);
24
+ const isFiniteNumber = isFinite;
20
25
  const isNullish = (thing) => thing == null;
21
26
  const isUndefined = (thing) => thing === void 0;
27
+ const isNull = (thing) => thing === null;
22
28
  const ifNotNullish = getIfNotFunction(isNullish);
23
29
  const ifNotUndefined = getIfNotFunction(isUndefined);
30
+ const isTypeStringOrBoolean = (type) => type == STRING || type == BOOLEAN;
24
31
  const isString = (thing) => getTypeOf(thing) == STRING;
32
+ const isArray = (thing) => Array.isArray(thing);
25
33
  const size = (thing) => thing.length;
26
34
  const isEmpty = (thing) => size(thing) == 0;
27
35
 
28
36
  const arrayEvery = (array, cb) => array.every(cb);
29
37
  const arrayForEach = (array, cb) => array.forEach(cb);
38
+ const arrayFilter = (array, cb) => array.filter(cb);
39
+ const arrayFind = (array, cb) => array.find(cb);
30
40
 
31
41
  const collValues = (coll) => [...(coll?.values() ?? [])];
32
42
 
@@ -64,6 +74,33 @@ const objForEach = (obj, cb) =>
64
74
  const objSize = (obj) => size(objIds(obj));
65
75
  const objIsEmpty = (obj) => isObject(obj) && objSize(obj) == 0;
66
76
 
77
+ const getCellOrValueType = (cellOrValue) => {
78
+ if (isNull(cellOrValue)) {
79
+ return NULL;
80
+ }
81
+ if (isArray(cellOrValue)) {
82
+ return ARRAY;
83
+ }
84
+ if (isObject(cellOrValue)) {
85
+ return OBJECT;
86
+ }
87
+ const type = getTypeOf(cellOrValue);
88
+ return isTypeStringOrBoolean(type) ||
89
+ (type == NUMBER && isFiniteNumber(cellOrValue))
90
+ ? type
91
+ : void 0;
92
+ };
93
+ const isJsonType = (type) => type == OBJECT || type == ARRAY;
94
+ const isCellOrValueSchemaType = (type) =>
95
+ isTypeStringOrBoolean(type) || type == NUMBER || isJsonType(type);
96
+ const isCellOrValueSchemaTypes = (types) =>
97
+ isArray(types)
98
+ ? !isUndefined(types[0]) && arrayEvery(types, isCellOrValueSchemaType)
99
+ : isCellOrValueSchemaType(types);
100
+ const isEncodedJson = (value) => isString(value) && value[0] == JSON_PREFIX;
101
+ const isReservedString = (value, encoded = 0) =>
102
+ value === UNDEFINED || (!encoded && isEncodedJson(value));
103
+
67
104
  const createCustomSchematizer = (
68
105
  unwrapSchema,
69
106
  getProperties,
@@ -73,16 +110,27 @@ const createCustomSchematizer = (
73
110
  const [unwrapped, defaultValue, allowNull, unwrappedRequired = required] =
74
111
  unwrapSchema(schema, void 0, void 0, required);
75
112
  const type = unwrapped?.type;
113
+ const enumValues = unwrapped?.[ENUM];
114
+ const isEnum =
115
+ isUndefined(type) &&
116
+ isArray(enumValues) &&
117
+ !isUndefined(enumValues[0]) &&
118
+ arrayEvery(enumValues, (enumValue) => {
119
+ const enumType = getCellOrValueType(enumValue);
120
+ return (
121
+ !isNull(enumValue) &&
122
+ !isUndefined(enumType) &&
123
+ !isJsonType(enumType) &&
124
+ !isReservedString(enumValue)
125
+ );
126
+ });
76
127
  if (
77
- type !== STRING &&
78
- type !== NUMBER &&
79
- type !== BOOLEAN &&
80
- type !== OBJECT &&
81
- type !== ARRAY
128
+ !isEnum &&
129
+ (!isUndefined(enumValues) || !isCellOrValueSchemaTypes(type))
82
130
  ) {
83
131
  return void 0;
84
132
  }
85
- const cellOrValueSchema = {[TYPE]: type};
133
+ const cellOrValueSchema = isEnum ? {[ENUM]: enumValues} : {[TYPE]: type};
86
134
  ifNotUndefined(defaultValue, (defaultValue2) => {
87
135
  cellOrValueSchema[DEFAULT] = defaultValue2;
88
136
  });
@@ -132,7 +180,6 @@ const createCustomSchematizer = (
132
180
  });
133
181
  };
134
182
 
135
- const MIXED = 'mixed';
136
183
  const unwrapSchema = (
137
184
  schema,
138
185
  defaultValue,
@@ -140,15 +187,12 @@ const unwrapSchema = (
140
187
  required = schema?.spec?.[OPTIONAL] === false,
141
188
  ) => {
142
189
  const oneOf = collValues(schema?._whitelist);
190
+ const enumValues = arrayFilter(oneOf, (value) => !isNull(value));
191
+ const hasNull = !isUndefined(arrayFind(oneOf, isNull));
143
192
  return [
144
- {
145
- [TYPE]:
146
- schema?.type === MIXED && !isEmpty(oneOf) && arrayEvery(oneOf, isString)
147
- ? STRING
148
- : schema?.type,
149
- },
193
+ !isEmpty(enumValues) ? {[ENUM]: enumValues} : {[TYPE]: schema?.type},
150
194
  defaultValue ?? schema?.spec?.[DEFAULT],
151
- allowNull || schema?.spec?.[NULLABLE] || false,
195
+ allowNull || schema?.spec?.[NULLABLE] || hasNull || false,
152
196
  required,
153
197
  ];
154
198
  };
@@ -6,27 +6,37 @@ const NUMBER = getTypeOf(0);
6
6
  const OBJECT = 'object';
7
7
  const ARRAY = 'array';
8
8
  const TYPE = 'type';
9
+ const ENUM = 'enum';
9
10
  const DEFAULT = 'default';
10
11
  const ALLOW_NULL = 'allowNull';
12
+ const NULL = 'null';
11
13
  const NULLABLE = 'nullable';
12
14
  const OPTIONAL = 'optional';
13
15
  const REQUIRED = 'required';
16
+ const UNDEFINED = '\uFFFC';
17
+ const JSON_PREFIX = '\uFFFD';
14
18
 
15
19
  const getIfNotFunction = (predicate) => (value, then, otherwise) =>
16
20
  predicate(value)
17
21
  ? /* istanbul ignore next */
18
22
  otherwise?.()
19
23
  : then(value);
24
+ const isFiniteNumber = isFinite;
20
25
  const isNullish = (thing) => thing == null;
21
26
  const isUndefined = (thing) => thing === void 0;
27
+ const isNull = (thing) => thing === null;
22
28
  const ifNotNullish = getIfNotFunction(isNullish);
23
29
  const ifNotUndefined = getIfNotFunction(isUndefined);
30
+ const isTypeStringOrBoolean = (type) => type == STRING || type == BOOLEAN;
24
31
  const isString = (thing) => getTypeOf(thing) == STRING;
32
+ const isArray = (thing) => Array.isArray(thing);
25
33
  const size = (thing) => thing.length;
26
34
  const isEmpty = (thing) => size(thing) == 0;
27
35
 
28
36
  const arrayEvery = (array, cb) => array.every(cb);
29
37
  const arrayForEach = (array, cb) => array.forEach(cb);
38
+ const arrayFilter = (array, cb) => array.filter(cb);
39
+ const arrayFind = (array, cb) => array.find(cb);
30
40
 
31
41
  const collValues = (coll) => [...(coll?.values() ?? [])];
32
42
 
@@ -64,6 +74,33 @@ const objForEach = (obj, cb) =>
64
74
  const objSize = (obj) => size(objIds(obj));
65
75
  const objIsEmpty = (obj) => isObject(obj) && objSize(obj) == 0;
66
76
 
77
+ const getCellOrValueType = (cellOrValue) => {
78
+ if (isNull(cellOrValue)) {
79
+ return NULL;
80
+ }
81
+ if (isArray(cellOrValue)) {
82
+ return ARRAY;
83
+ }
84
+ if (isObject(cellOrValue)) {
85
+ return OBJECT;
86
+ }
87
+ const type = getTypeOf(cellOrValue);
88
+ return isTypeStringOrBoolean(type) ||
89
+ (type == NUMBER && isFiniteNumber(cellOrValue))
90
+ ? type
91
+ : void 0;
92
+ };
93
+ const isJsonType = (type) => type == OBJECT || type == ARRAY;
94
+ const isCellOrValueSchemaType = (type) =>
95
+ isTypeStringOrBoolean(type) || type == NUMBER || isJsonType(type);
96
+ const isCellOrValueSchemaTypes = (types) =>
97
+ isArray(types)
98
+ ? !isUndefined(types[0]) && arrayEvery(types, isCellOrValueSchemaType)
99
+ : isCellOrValueSchemaType(types);
100
+ const isEncodedJson = (value) => isString(value) && value[0] == JSON_PREFIX;
101
+ const isReservedString = (value, encoded = 0) =>
102
+ value === UNDEFINED || (!encoded && isEncodedJson(value));
103
+
67
104
  const createCustomSchematizer = (
68
105
  unwrapSchema,
69
106
  getProperties,
@@ -73,16 +110,27 @@ const createCustomSchematizer = (
73
110
  const [unwrapped, defaultValue, allowNull, unwrappedRequired = required] =
74
111
  unwrapSchema(schema, void 0, void 0, required);
75
112
  const type = unwrapped?.type;
113
+ const enumValues = unwrapped?.[ENUM];
114
+ const isEnum =
115
+ isUndefined(type) &&
116
+ isArray(enumValues) &&
117
+ !isUndefined(enumValues[0]) &&
118
+ arrayEvery(enumValues, (enumValue) => {
119
+ const enumType = getCellOrValueType(enumValue);
120
+ return (
121
+ !isNull(enumValue) &&
122
+ !isUndefined(enumType) &&
123
+ !isJsonType(enumType) &&
124
+ !isReservedString(enumValue)
125
+ );
126
+ });
76
127
  if (
77
- type !== STRING &&
78
- type !== NUMBER &&
79
- type !== BOOLEAN &&
80
- type !== OBJECT &&
81
- type !== ARRAY
128
+ !isEnum &&
129
+ (!isUndefined(enumValues) || !isCellOrValueSchemaTypes(type))
82
130
  ) {
83
131
  return void 0;
84
132
  }
85
- const cellOrValueSchema = {[TYPE]: type};
133
+ const cellOrValueSchema = isEnum ? {[ENUM]: enumValues} : {[TYPE]: type};
86
134
  ifNotUndefined(defaultValue, (defaultValue2) => {
87
135
  cellOrValueSchema[DEFAULT] = defaultValue2;
88
136
  });
@@ -132,7 +180,6 @@ const createCustomSchematizer = (
132
180
  });
133
181
  };
134
182
 
135
- const MIXED = 'mixed';
136
183
  const unwrapSchema = (
137
184
  schema,
138
185
  defaultValue,
@@ -140,15 +187,12 @@ const unwrapSchema = (
140
187
  required = schema?.spec?.[OPTIONAL] === false,
141
188
  ) => {
142
189
  const oneOf = collValues(schema?._whitelist);
190
+ const enumValues = arrayFilter(oneOf, (value) => !isNull(value));
191
+ const hasNull = !isUndefined(arrayFind(oneOf, isNull));
143
192
  return [
144
- {
145
- [TYPE]:
146
- schema?.type === MIXED && !isEmpty(oneOf) && arrayEvery(oneOf, isString)
147
- ? STRING
148
- : schema?.type,
149
- },
193
+ !isEmpty(enumValues) ? {[ENUM]: enumValues} : {[TYPE]: schema?.type},
150
194
  defaultValue ?? schema?.spec?.[DEFAULT],
151
- allowNull || schema?.spec?.[NULLABLE] || false,
195
+ allowNull || schema?.spec?.[NULLABLE] || hasNull || false,
152
196
  required,
153
197
  ];
154
198
  };