@es-joy/jsoe 0.16.0 → 0.17.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/.ncurc.cjs +4 -5
- package/CHANGES.md +4 -0
- package/README.md +27 -3
- package/badges/licenses-badge.svg +1 -0
- package/dist/formatAndTypeChoices.d.ts +39 -19
- package/dist/formatAndTypeChoices.d.ts.map +1 -1
- package/dist/formats/indexedDBKey.d.ts +1 -1
- package/dist/formats/indexedDBKey.d.ts.map +1 -1
- package/dist/formats/json.d.ts +1 -1
- package/dist/formats/json.d.ts.map +1 -1
- package/dist/formats/schema.d.ts +11 -0
- package/dist/formats/schema.d.ts.map +1 -0
- package/dist/formats/structuredCloning.d.ts +11 -13
- package/dist/formats/structuredCloning.d.ts.map +1 -1
- package/dist/formats.d.ts +86 -25
- package/dist/formats.d.ts.map +1 -1
- package/dist/fundamentalTypes/BooleanObjectType.d.ts +1 -1
- package/dist/fundamentalTypes/BooleanObjectType.d.ts.map +1 -1
- package/dist/fundamentalTypes/NumberObjectType.d.ts +1 -1
- package/dist/fundamentalTypes/NumberObjectType.d.ts.map +1 -1
- package/dist/fundamentalTypes/StringObjectType.d.ts +1 -1
- package/dist/fundamentalTypes/StringObjectType.d.ts.map +1 -1
- package/dist/fundamentalTypes/arrayReferenceType.d.ts +1 -1
- package/dist/fundamentalTypes/arrayType.d.ts +3 -3
- package/dist/fundamentalTypes/arrayType.d.ts.map +1 -1
- package/dist/fundamentalTypes/bigintObjectType.d.ts +6 -0
- package/dist/fundamentalTypes/bigintObjectType.d.ts.map +1 -0
- package/dist/fundamentalTypes/bigintType.d.ts +1 -1
- package/dist/fundamentalTypes/bigintType.d.ts.map +1 -1
- package/dist/fundamentalTypes/blobType.d.ts +1 -1
- package/dist/fundamentalTypes/blobType.d.ts.map +1 -1
- package/dist/fundamentalTypes/booleanType.d.ts +8 -0
- package/dist/fundamentalTypes/booleanType.d.ts.map +1 -0
- package/dist/fundamentalTypes/catchType.d.ts +6 -0
- package/dist/fundamentalTypes/catchType.d.ts.map +1 -0
- package/dist/fundamentalTypes/dateType.d.ts +4 -4
- package/dist/fundamentalTypes/dateType.d.ts.map +1 -1
- package/dist/fundamentalTypes/domexceptionType.d.ts +1 -1
- package/dist/fundamentalTypes/domexceptionType.d.ts.map +1 -1
- package/dist/fundamentalTypes/enumType.d.ts +6 -0
- package/dist/fundamentalTypes/enumType.d.ts.map +1 -0
- package/dist/fundamentalTypes/errorType.d.ts +1 -1
- package/dist/fundamentalTypes/errorType.d.ts.map +1 -1
- package/dist/fundamentalTypes/fileType.d.ts +1 -1
- package/dist/fundamentalTypes/fileType.d.ts.map +1 -1
- package/dist/fundamentalTypes/filelistType.d.ts +1 -1
- package/dist/fundamentalTypes/filelistType.d.ts.map +1 -1
- package/dist/fundamentalTypes/functionType.d.ts +6 -0
- package/dist/fundamentalTypes/functionType.d.ts.map +1 -0
- package/dist/fundamentalTypes/literalType.d.ts +6 -0
- package/dist/fundamentalTypes/literalType.d.ts.map +1 -0
- package/dist/fundamentalTypes/mapType.d.ts +1 -1
- package/dist/fundamentalTypes/mapType.d.ts.map +1 -1
- package/dist/fundamentalTypes/nanType.d.ts +6 -0
- package/dist/fundamentalTypes/nanType.d.ts.map +1 -0
- package/dist/fundamentalTypes/nativeEnumType.d.ts +6 -0
- package/dist/fundamentalTypes/nativeEnumType.d.ts.map +1 -0
- package/dist/fundamentalTypes/neverType.d.ts +6 -0
- package/dist/fundamentalTypes/neverType.d.ts.map +1 -0
- package/dist/fundamentalTypes/noneditableType.d.ts +1 -1
- package/dist/fundamentalTypes/noneditableType.d.ts.map +1 -1
- package/dist/fundamentalTypes/nullType.d.ts +1 -1
- package/dist/fundamentalTypes/nullType.d.ts.map +1 -1
- package/dist/fundamentalTypes/numberType.d.ts +1 -1
- package/dist/fundamentalTypes/numberType.d.ts.map +1 -1
- package/dist/fundamentalTypes/objectReferenceType.d.ts +1 -1
- package/dist/fundamentalTypes/objectType.d.ts +1 -1
- package/dist/fundamentalTypes/objectType.d.ts.map +1 -1
- package/dist/fundamentalTypes/promiseType.d.ts +6 -0
- package/dist/fundamentalTypes/promiseType.d.ts.map +1 -0
- package/dist/fundamentalTypes/recordType.d.ts +6 -0
- package/dist/fundamentalTypes/recordType.d.ts.map +1 -0
- package/dist/fundamentalTypes/regexpType.d.ts +1 -1
- package/dist/fundamentalTypes/regexpType.d.ts.map +1 -1
- package/dist/fundamentalTypes/setType.d.ts +1 -1
- package/dist/fundamentalTypes/setType.d.ts.map +1 -1
- package/dist/fundamentalTypes/sparseUndefinedType.d.ts +1 -1
- package/dist/fundamentalTypes/sparseUndefinedType.d.ts.map +1 -1
- package/dist/fundamentalTypes/stringType.d.ts +1 -1
- package/dist/fundamentalTypes/stringType.d.ts.map +1 -1
- package/dist/fundamentalTypes/symbolType.d.ts +8 -0
- package/dist/fundamentalTypes/symbolType.d.ts.map +1 -0
- package/dist/fundamentalTypes/tupleType.d.ts +6 -0
- package/dist/fundamentalTypes/tupleType.d.ts.map +1 -0
- package/dist/fundamentalTypes/undefinedType.d.ts +1 -1
- package/dist/fundamentalTypes/undefinedType.d.ts.map +1 -1
- package/dist/fundamentalTypes/voidType.d.ts +6 -0
- package/dist/fundamentalTypes/voidType.d.ts.map +1 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9660 -1586
- package/dist/subTypes/blobHTMLType.d.ts.map +1 -1
- package/dist/subTypes/falseType.d.ts +1 -1
- package/dist/subTypes/trueType.d.ts +1 -1
- package/dist/superTypes/SpecialNumberType.d.ts +1 -1
- package/dist/superTypes/SpecialRealNumberType.d.ts +1 -1
- package/dist/superTypes/SpecialRealNumberType.d.ts.map +1 -1
- package/dist/superTypes/buffersourceType.d.ts +1 -1
- package/dist/superTypes/buffersourceType.d.ts.map +1 -1
- package/dist/superTypes/dommatrixType.d.ts +1 -1
- package/dist/superTypes/dommatrixType.d.ts.map +1 -1
- package/dist/superTypes/dompointType.d.ts +1 -1
- package/dist/superTypes/dompointType.d.ts.map +1 -1
- package/dist/superTypes/domrectType.d.ts +1 -1
- package/dist/superTypes/domrectType.d.ts.map +1 -1
- package/dist/superTypes/errorsSpecialType.d.ts +1 -1
- package/dist/superTypes/errorsSpecialType.d.ts.map +1 -1
- package/dist/typeChoices.d.ts +33 -16
- package/dist/typeChoices.d.ts.map +1 -1
- package/dist/types.d.ts +161 -157
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/dialogs.d.ts +3 -3
- package/dist/utils/dialogs.d.ts.map +1 -1
- package/dist/utils/jsonPointer.d.ts.map +1 -1
- package/dist/utils/media.d.ts.map +1 -1
- package/dist/utils/objects.d.ts +16 -0
- package/dist/utils/objects.d.ts.map +1 -0
- package/dist/utils/types.d.ts +1 -1
- package/dist/utils/types.d.ts.map +1 -1
- package/dist/vendor-imports.d.ts +1 -1
- package/eslint.config.js +74 -0
- package/licenseInfo.json +4 -0
- package/package.json +33 -42
- package/rollup.config.js +15 -0
- package/src/formatAndTypeChoices.js +68 -54
- package/src/formats/indexedDBKey.js +9 -4
- package/src/formats/json.js +7 -4
- package/src/formats/schema.js +772 -0
- package/src/formats/structuredCloning.js +187 -86
- package/src/formats.js +61 -26
- package/src/fundamentalTypes/BooleanObjectType.js +18 -6
- package/src/fundamentalTypes/NumberObjectType.js +18 -5
- package/src/fundamentalTypes/StringObjectType.js +20 -8
- package/src/fundamentalTypes/arrayType.js +1241 -533
- package/src/fundamentalTypes/bigintObjectType.js +64 -0
- package/src/fundamentalTypes/bigintType.js +31 -5
- package/src/fundamentalTypes/blobType.js +201 -190
- package/src/fundamentalTypes/booleanType.js +63 -0
- package/src/fundamentalTypes/catchType.js +140 -0
- package/src/fundamentalTypes/dateType.js +57 -19
- package/src/fundamentalTypes/domexceptionType.js +61 -63
- package/src/fundamentalTypes/enumType.js +52 -0
- package/src/fundamentalTypes/errorType.js +20 -7
- package/src/fundamentalTypes/fileType.js +195 -189
- package/src/fundamentalTypes/filelistType.js +4 -0
- package/src/fundamentalTypes/functionType.js +150 -0
- package/src/fundamentalTypes/literalType.js +81 -0
- package/src/fundamentalTypes/mapType.js +4 -0
- package/src/fundamentalTypes/nanType.js +41 -0
- package/src/fundamentalTypes/nativeEnumType.js +155 -0
- package/src/fundamentalTypes/neverType.js +44 -0
- package/src/fundamentalTypes/noneditableType.js +19 -5
- package/src/fundamentalTypes/nullType.js +16 -6
- package/src/fundamentalTypes/numberType.js +49 -6
- package/src/fundamentalTypes/objectType.js +10 -2
- package/src/fundamentalTypes/promiseType.js +60 -0
- package/src/fundamentalTypes/recordType.js +42 -0
- package/src/fundamentalTypes/regexpType.js +51 -33
- package/src/fundamentalTypes/setType.js +4 -0
- package/src/fundamentalTypes/sparseUndefinedType.js +3 -0
- package/src/fundamentalTypes/stringType.js +254 -6
- package/src/fundamentalTypes/symbolType.js +81 -0
- package/src/fundamentalTypes/tupleType.js +39 -0
- package/src/fundamentalTypes/undefinedType.js +14 -4
- package/src/fundamentalTypes/voidType.js +48 -0
- package/src/jsoe.css +37 -3
- package/src/subTypes/blobHTMLType.js +33 -24
- package/src/superTypes/SpecialRealNumberType.js +22 -6
- package/src/superTypes/buffersourceType.js +86 -30
- package/src/superTypes/dommatrixType.js +24 -7
- package/src/superTypes/dompointType.js +27 -7
- package/src/superTypes/domrectType.js +33 -7
- package/src/superTypes/errorsSpecialType.js +30 -14
- package/src/typeChoices.js +115 -44
- package/src/types.js +129 -45
- package/src/utils/FileList.js +3 -3
- package/src/utils/dialogs.js +6 -8
- package/src/utils/objects.js +22 -0
- package/src/vendor-imports.js +1 -1
- package/tsconfig.json +2 -2
- package/vendor/jamilih/dist/jml-es.js +23 -6
- package/vendor/typeson-registry/dist/index.js +77 -47
- package/vendor/zod/lib/index.mjs +4236 -0
- package/vendor/zodex/dist/esm/dezerialize.d.ts +26 -0
- package/vendor/zodex/dist/esm/dezerialize.js +393 -0
- package/vendor/zodex/dist/esm/index.d.ts +9 -0
- package/vendor/zodex/dist/esm/index.js +4 -0
- package/vendor/zodex/dist/esm/infer.d.ts +29 -0
- package/vendor/zodex/dist/esm/infer.js +1 -0
- package/vendor/zodex/dist/esm/package.json +1 -0
- package/vendor/zodex/dist/esm/types.d.ts +201 -0
- package/vendor/zodex/dist/esm/types.js +13 -0
- package/vendor/zodex/dist/esm/ui.d.ts +23 -0
- package/vendor/zodex/dist/esm/ui.js +10 -0
- package/vendor/zodex/dist/esm/zerialize.d.ts +50 -0
- package/vendor/zodex/dist/esm/zerialize.js +417 -0
- package/vendor/zodex/dist/esm/zod-types.d.ts +11 -0
- package/vendor/zodex/dist/esm/zod-types.js +1 -0
- package/.eslintignore +0 -13
- package/.eslintrc.cjs +0 -145
- package/.nyc_output/out.json +0 -117370
- package/cypress.config.ts +0 -15
- package/demo/index-instrumented.html +0 -29
- package/demo/index-instrumented.js +0 -644
- package/demo/index.html +0 -29
- package/demo/index.js +0 -215
- package/src/formats/schemaAndArbitrary.js +0 -20
- package/src/formats/schemaOnly.js +0 -539
|
@@ -20,14 +20,17 @@ import json from './json.js';
|
|
|
20
20
|
};
|
|
21
21
|
|
|
22
22
|
/**
|
|
23
|
+
* Delegates data-based UI building to method for adding child elements (a
|
|
24
|
+
* method which is housed in the array type object).
|
|
23
25
|
* @typedef {(info: {
|
|
24
26
|
* propName: string,
|
|
25
27
|
* type: import('../types.js').AvailableType,
|
|
26
28
|
* value: import('../formats.js').StructuredCloneValue,
|
|
27
29
|
* bringIntoFocus?: boolean,
|
|
28
30
|
* setAValue?: boolean,
|
|
29
|
-
* schemaContent?:
|
|
30
|
-
*
|
|
31
|
+
* schemaContent?: import('../formats/schema.js').ZodexSchema,
|
|
32
|
+
* mustBeOptional?: boolean,
|
|
33
|
+
* schemaIdx?: number
|
|
31
34
|
* }) => HTMLElement|null} AddAndSetArrayElement
|
|
32
35
|
*/
|
|
33
36
|
|
|
@@ -36,6 +39,8 @@ import json from './json.js';
|
|
|
36
39
|
*/
|
|
37
40
|
|
|
38
41
|
/**
|
|
42
|
+
* Obtains state-specific data and returns an observer that can build a UI based
|
|
43
|
+
* on data it receives.
|
|
39
44
|
* @param {import('../types.js').StateObject} stateObj
|
|
40
45
|
* @returns {EncapsulateObserver}
|
|
41
46
|
*/
|
|
@@ -43,19 +48,26 @@ const encapsulateObserver = (stateObj) => {
|
|
|
43
48
|
const {
|
|
44
49
|
typeNamespace, readonly, format: frmt, schemaContent,
|
|
45
50
|
formats,
|
|
46
|
-
types
|
|
47
|
-
getPossibleSchemasForPathAndType
|
|
51
|
+
types
|
|
48
52
|
} = stateObj;
|
|
49
53
|
|
|
50
54
|
const format = /** @type {import('../formats.js').AvailableFormat} */ (frmt);
|
|
51
55
|
|
|
52
56
|
/**
|
|
57
|
+
* Matches keypaths to the HTML UI Element.
|
|
53
58
|
* @type {{[key: string]: HTMLElement & {
|
|
54
59
|
* $addAndSetArrayElement: AddAndSetArrayElement
|
|
55
60
|
* }}}
|
|
56
61
|
*/
|
|
57
62
|
const parents = {};
|
|
58
63
|
|
|
64
|
+
/**
|
|
65
|
+
* @type {{
|
|
66
|
+
* [key: string]: [import('zodex').SzType, number|undefined]|undefined
|
|
67
|
+
* }}
|
|
68
|
+
*/
|
|
69
|
+
const schemaParents = {};
|
|
70
|
+
|
|
59
71
|
/** @type {string[]} */
|
|
60
72
|
const mapPaths = [];
|
|
61
73
|
|
|
@@ -110,17 +122,39 @@ const encapsulateObserver = (stateObj) => {
|
|
|
110
122
|
? 'arrayNonindexKeys'
|
|
111
123
|
// ? 'sparseArrays'
|
|
112
124
|
: 'array';
|
|
125
|
+
|
|
126
|
+
const li = keypath.lastIndexOf('.');
|
|
127
|
+
const arrayOrObjectPropertyName =
|
|
128
|
+
unescapeKeyPathComponent(keypath.slice(li + 1));
|
|
129
|
+
const parentPath = li === -1 ? '' : keypath.slice(0, li);
|
|
130
|
+
|
|
131
|
+
let schema, schemaIdx, mustBeOptional;
|
|
113
132
|
if (typeof cyclicKeypath === 'string') {
|
|
114
133
|
newValue = typesonPathToJSONPointer(cyclicKeypath);
|
|
115
134
|
newType = type === 'array' ? 'arrayReference' : 'objectReference';
|
|
116
|
-
|
|
135
|
+
({
|
|
136
|
+
newType, schema, schemaIdx, mustBeOptional
|
|
137
|
+
} = canonicalTypeToAvailableTypeAndSchema(
|
|
117
138
|
/** @type {import('../types.js').default} */ (types),
|
|
118
139
|
/** @type {import('../formats.js').default} */ (formats),
|
|
119
|
-
format, state, newType, value
|
|
120
|
-
|
|
140
|
+
format, state, newType, value,
|
|
141
|
+
arrayOrObjectPropertyName,
|
|
142
|
+
schemaParents[parentPath],
|
|
143
|
+
stateObj
|
|
144
|
+
)); // Todo (low): Add accurate state for second argument
|
|
121
145
|
} else {
|
|
146
|
+
// console.log(
|
|
147
|
+
// // keypath
|
|
148
|
+
// 'schemaParents', keypath, parentPath, value,
|
|
149
|
+
// arrayOrObjectPropertyName, schemaParents[parentPath]
|
|
150
|
+
// );
|
|
122
151
|
try {
|
|
123
|
-
|
|
152
|
+
// console.log(
|
|
153
|
+
// 'VVVV0', JSON.stringify(parentPath), schemaParents // , stateObj
|
|
154
|
+
// );
|
|
155
|
+
({
|
|
156
|
+
newType, schema, schemaIdx, mustBeOptional
|
|
157
|
+
} = canonicalTypeToAvailableTypeAndSchema(
|
|
124
158
|
/** @type {import('../types.js').default} */ (types),
|
|
125
159
|
/** @type {import('../formats.js').default} */ (formats),
|
|
126
160
|
format,
|
|
@@ -129,8 +163,14 @@ const encapsulateObserver = (stateObj) => {
|
|
|
129
163
|
* @type {import('../types.js').AvailableType}
|
|
130
164
|
*/
|
|
131
165
|
(type),
|
|
132
|
-
value
|
|
133
|
-
|
|
166
|
+
value,
|
|
167
|
+
arrayOrObjectPropertyName,
|
|
168
|
+
schemaParents[parentPath],
|
|
169
|
+
stateObj
|
|
170
|
+
)); // Todo (low): Add state for second argument
|
|
171
|
+
// console.log('VVVV1', value, schema);
|
|
172
|
+
// console.log('VVVV2',
|
|
173
|
+
// JSON.stringify(stateObj.schemaContent, null, 2));
|
|
134
174
|
} catch (err) {
|
|
135
175
|
console.log('err', type, err);
|
|
136
176
|
stateObj.error = /** @type {Error} */ (err);
|
|
@@ -138,13 +178,8 @@ const encapsulateObserver = (stateObj) => {
|
|
|
138
178
|
}
|
|
139
179
|
}
|
|
140
180
|
|
|
141
|
-
const li = keypath.lastIndexOf('.');
|
|
142
|
-
const arrayOrObjectPropertyName =
|
|
143
|
-
unescapeKeyPathComponent(keypath.slice(li + 1));
|
|
144
|
-
const parentPath = li === -1 ? '' : keypath.slice(0, li);
|
|
145
|
-
|
|
146
181
|
const hasChildren = [
|
|
147
|
-
'array', 'object', 'set', 'map',
|
|
182
|
+
'array', 'object', 'set', 'map', 'tuple', 'record', 'filelist',
|
|
148
183
|
// 'sparseArrays',
|
|
149
184
|
'arrayNonindexKeys'
|
|
150
185
|
].includes(newType);
|
|
@@ -157,6 +192,18 @@ const encapsulateObserver = (stateObj) => {
|
|
|
157
192
|
mapPaths.push(keypath);
|
|
158
193
|
}
|
|
159
194
|
|
|
195
|
+
if (schema) {
|
|
196
|
+
stateObj.specificSchema = schema;
|
|
197
|
+
if (!stateObj.specificSchemas) {
|
|
198
|
+
stateObj.specificSchemas = [];
|
|
199
|
+
}
|
|
200
|
+
stateObj.specificSchemas.push(schema);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// console.log('is', stateObj.schemaContent);
|
|
204
|
+
// console.log('but could set to', schema);
|
|
205
|
+
// console.log('arrayOrObjectPropertyName', arrayOrObjectPropertyName);
|
|
206
|
+
|
|
160
207
|
if (!stateObj.rootUI) {
|
|
161
208
|
// console.log('vvvv0', newType, newValue);
|
|
162
209
|
stateObj.rootUI = types?.getUIForModeAndType({
|
|
@@ -166,16 +213,8 @@ const encapsulateObserver = (stateObj) => {
|
|
|
166
213
|
bringIntoFocus: false,
|
|
167
214
|
buildTypeChoices,
|
|
168
215
|
format,
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
/* schema:
|
|
172
|
-
&&
|
|
173
|
-
getPossibleSchemasForPathAndType({
|
|
174
|
-
keypath,
|
|
175
|
-
parentPath: '',
|
|
176
|
-
valueType: newType
|
|
177
|
-
}),
|
|
178
|
-
*/
|
|
216
|
+
specificSchemaObject: schema,
|
|
217
|
+
schemaContent: schema ?? schemaContent,
|
|
179
218
|
value: newValue,
|
|
180
219
|
hasValue: true,
|
|
181
220
|
// Not currently in use but may be convenient for a
|
|
@@ -187,6 +226,10 @@ const encapsulateObserver = (stateObj) => {
|
|
|
187
226
|
* {$addAndSetArrayElement: AddAndSetArrayElement}}
|
|
188
227
|
*/ (stateObj.rootUI);
|
|
189
228
|
|
|
229
|
+
if (schema) {
|
|
230
|
+
schemaParents[''] = [schema, schemaIdx];
|
|
231
|
+
}
|
|
232
|
+
|
|
190
233
|
// Since we're skipping the array elements, we need to add the
|
|
191
234
|
// map element to the array index where the array children
|
|
192
235
|
// will be found (which we do want)
|
|
@@ -201,6 +244,14 @@ const encapsulateObserver = (stateObj) => {
|
|
|
201
244
|
return;
|
|
202
245
|
}
|
|
203
246
|
|
|
247
|
+
if (schema) {
|
|
248
|
+
schemaParents[keypath] = [schema, schemaIdx];
|
|
249
|
+
}
|
|
250
|
+
// console.log(
|
|
251
|
+
// 'schemaParents', newValue, JSON.stringify(parentPath),
|
|
252
|
+
// schema, schemaParents
|
|
253
|
+
// );
|
|
254
|
+
|
|
204
255
|
// Todo (low): If could be async, use async encapsulate method
|
|
205
256
|
// Todo (low): Handle `awaitingTypesonPromise` with place-holder
|
|
206
257
|
// Todo (low): Handle `resolvingTypesonPromise` to replace place-holder
|
|
@@ -235,20 +286,13 @@ const encapsulateObserver = (stateObj) => {
|
|
|
235
286
|
// console.log('vvvv', newType, '::', newValue, '::', newValue?.cause);
|
|
236
287
|
|
|
237
288
|
const root = ui.$addAndSetArrayElement({
|
|
289
|
+
mustBeOptional,
|
|
238
290
|
propName: arrayOrObjectPropertyName,
|
|
239
291
|
type: newType,
|
|
240
292
|
value: newValue,
|
|
241
293
|
bringIntoFocus: false,
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
/* schema:
|
|
245
|
-
&& getPossibleSchemasForPathAndType({
|
|
246
|
-
keypath,
|
|
247
|
-
parentPath,
|
|
248
|
-
arrayOrObjectPropertyName,
|
|
249
|
-
valueType: newType
|
|
250
|
-
})
|
|
251
|
-
*/
|
|
294
|
+
schemaIdx,
|
|
295
|
+
schemaContent: schema ?? schemaContent
|
|
252
296
|
});
|
|
253
297
|
|
|
254
298
|
/* istanbul ignore if -- Guard for `null` return */
|
|
@@ -267,7 +311,9 @@ const encapsulateObserver = (stateObj) => {
|
|
|
267
311
|
type: newType,
|
|
268
312
|
// eslint-disable-next-line object-shorthand -- TS
|
|
269
313
|
root: /** @type {HTMLDivElement} */ (root),
|
|
270
|
-
topRoot: /** @type {HTMLDivElement} */ (stateObj.rootUI)
|
|
314
|
+
topRoot: /** @type {HTMLDivElement} */ (stateObj.rootUI),
|
|
315
|
+
// We don't want focus when values auto-added
|
|
316
|
+
avoidReport: true
|
|
271
317
|
});
|
|
272
318
|
}
|
|
273
319
|
|
|
@@ -296,6 +342,7 @@ const encapsulateObserver = (stateObj) => {
|
|
|
296
342
|
};
|
|
297
343
|
|
|
298
344
|
/**
|
|
345
|
+
* Performs replacements on a list of types.
|
|
299
346
|
* @param {string[]} originTypes
|
|
300
347
|
* @param {[originType: string, replacementType: string][]} replacements
|
|
301
348
|
* @returns {void}
|
|
@@ -307,21 +354,40 @@ const replaceTypes = (originTypes, replacements) => {
|
|
|
307
354
|
};
|
|
308
355
|
|
|
309
356
|
/**
|
|
310
|
-
*
|
|
311
|
-
*
|
|
312
|
-
*
|
|
313
|
-
* @param {
|
|
314
|
-
*
|
|
315
|
-
* @param {import('../formats.js').
|
|
316
|
-
*
|
|
317
|
-
* @
|
|
357
|
+
* Converts a (typeson structured cloning) type to a type name relevant for the
|
|
358
|
+
* format, state, value, and schema content, and may supply a child type if
|
|
359
|
+
* there is a match. Also returns relevant schema for the type.
|
|
360
|
+
* @param {import('../types.js').default} types The Types object containing
|
|
361
|
+
* type-specific data.
|
|
362
|
+
* @param {import('../formats.js').default} formats The Formats object
|
|
363
|
+
* containing format-specific data.
|
|
364
|
+
* @param {import('../formats.js').AvailableFormat} format The current format.
|
|
365
|
+
* @param {string} state The current state.
|
|
366
|
+
* @param {import('../types.js').AvailableType} valType The value type being
|
|
367
|
+
* checked.
|
|
368
|
+
* @param {import('../formats.js').StructuredCloneValue} v The value being
|
|
369
|
+
* checked.
|
|
370
|
+
* @param {string} arrayOrObjectPropertyName
|
|
371
|
+
* @param {[import('zodex').SzType, number|undefined]|undefined} parentSchema
|
|
372
|
+
* @param {import('../types.js').StateObject} stateObj The schema content
|
|
373
|
+
* being checked.
|
|
374
|
+
* @throws {Error} May throw if data found to be invalid.
|
|
375
|
+
* @returns {{
|
|
376
|
+
* newType: import('../types.js').AvailableType,
|
|
377
|
+
* schema?: import('zodex').SzType|undefined,
|
|
378
|
+
* mustBeOptional?: boolean,
|
|
379
|
+
* schemaIdx?: number
|
|
380
|
+
* }} Schema and type info.
|
|
318
381
|
*/
|
|
319
|
-
const
|
|
320
|
-
types, formats, format, state, valType, v
|
|
382
|
+
const canonicalTypeToAvailableTypeAndSchema = (
|
|
383
|
+
types, formats, format, state, valType, v, arrayOrObjectPropertyName,
|
|
384
|
+
parentSchema, stateObj
|
|
321
385
|
) => {
|
|
322
386
|
const frmt = formats.getAvailableFormat(format);
|
|
323
|
-
const {
|
|
324
|
-
const allowableTypes =
|
|
387
|
+
const {getTypesAndSchemasForState, convertFromTypeson, testInvalid} = frmt;
|
|
388
|
+
const allowableTypes = getTypesAndSchemasForState.call(
|
|
389
|
+
frmt, types, state, stateObj.schemaContent
|
|
390
|
+
)?.types;
|
|
325
391
|
/* istanbul ignore if -- Guard */
|
|
326
392
|
if (!allowableTypes) {
|
|
327
393
|
throw new Error('Unexpected undefined type for state');
|
|
@@ -331,41 +397,60 @@ const canonicalToAvailableType = (
|
|
|
331
397
|
* @type {import('../types.js').AvailableType|undefined}
|
|
332
398
|
*/
|
|
333
399
|
let ret;
|
|
334
|
-
// console.log('format, state, valType, v', format, state, valType, v);
|
|
335
400
|
|
|
336
401
|
/**
|
|
337
|
-
*
|
|
338
|
-
* @
|
|
339
|
-
* @
|
|
402
|
+
* Throws an error with information about the new value type.
|
|
403
|
+
* @param {string} newValType The new value type being recorded.
|
|
404
|
+
* @throws {Error} The invalid Error being thrown.
|
|
405
|
+
* @returns {never} Always throws instead of returning.
|
|
340
406
|
*/
|
|
341
407
|
const isInvalid = (newValType) => {
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
408
|
+
const err = /** @type {Error & {newValType: string}} */ (
|
|
409
|
+
new Error('Invalid')
|
|
410
|
+
);
|
|
411
|
+
err.newValType = newValType;
|
|
345
412
|
throw err;
|
|
346
413
|
};
|
|
414
|
+
let schema;
|
|
347
415
|
if (convertFromTypeson) {
|
|
348
|
-
|
|
416
|
+
let newValType;
|
|
417
|
+
let mustBeOptional;
|
|
418
|
+
let schemaIdx;
|
|
419
|
+
({
|
|
420
|
+
type: newValType,
|
|
421
|
+
schema,
|
|
422
|
+
schemaIdx,
|
|
423
|
+
mustBeOptional
|
|
424
|
+
} = convertFromTypeson(
|
|
425
|
+
valType, types, v, arrayOrObjectPropertyName, parentSchema, stateObj
|
|
426
|
+
));
|
|
349
427
|
if (typeof newValType === 'string') {
|
|
350
428
|
if (testInvalid && testInvalid(newValType, v)) {
|
|
351
429
|
return isInvalid(newValType);
|
|
352
430
|
}
|
|
353
431
|
valType = newValType;
|
|
432
|
+
if (schema) {
|
|
433
|
+
return {
|
|
434
|
+
newType: valType,
|
|
435
|
+
schema,
|
|
436
|
+
schemaIdx,
|
|
437
|
+
mustBeOptional
|
|
438
|
+
};
|
|
439
|
+
}
|
|
354
440
|
}
|
|
355
441
|
}
|
|
356
442
|
|
|
357
|
-
// console.log('ret', ret);
|
|
358
443
|
allowableTypes.some((allowableType) => {
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
444
|
+
const typeObj =
|
|
445
|
+
/** @type {import('../types.js').TypeObject & {childTypes: string[]}} */ (
|
|
446
|
+
types.getTypeObject(allowableType)
|
|
447
|
+
);
|
|
363
448
|
const {
|
|
364
449
|
valueMatch, superType, childTypes
|
|
365
450
|
} = typeObj;
|
|
366
451
|
if (
|
|
367
452
|
(superType && valueMatch &&
|
|
368
|
-
//
|
|
453
|
+
// Using, e.g., for `true` and `false` subtypes
|
|
369
454
|
superType === valType && valueMatch(v)) ||
|
|
370
455
|
(childTypes && childTypes.includes(valType))
|
|
371
456
|
) {
|
|
@@ -375,7 +460,7 @@ const canonicalToAvailableType = (
|
|
|
375
460
|
|
|
376
461
|
return false;
|
|
377
462
|
});
|
|
378
|
-
|
|
463
|
+
|
|
379
464
|
if (ret === undefined) {
|
|
380
465
|
// We run this separately from the `childTypes` check above
|
|
381
466
|
// to ensure `childTypes` have priority regardless of position
|
|
@@ -387,29 +472,25 @@ const canonicalToAvailableType = (
|
|
|
387
472
|
return false;
|
|
388
473
|
});
|
|
389
474
|
if (ret === undefined) {
|
|
475
|
+
console.log('AALLLowableTypes', state, allowableTypes, '::', valType);
|
|
390
476
|
return isInvalid(valType);
|
|
391
477
|
}
|
|
392
478
|
}
|
|
393
|
-
return
|
|
479
|
+
return {
|
|
480
|
+
newType: ret,
|
|
481
|
+
schema
|
|
482
|
+
};
|
|
394
483
|
};
|
|
395
484
|
|
|
396
|
-
/**
|
|
397
|
-
* @callback FormatIterator
|
|
398
|
-
* @param {import('../formats.js').StructuredCloneValue} records
|
|
399
|
-
* @param {import('../types.js').StateObject} stateObj
|
|
400
|
-
* @returns {Promise<Element>}
|
|
401
|
-
*/
|
|
402
|
-
|
|
403
485
|
/** @type {import('../formats.js').Format} */
|
|
404
486
|
const structuredCloning = {
|
|
405
487
|
iterate (records, stateObj) {
|
|
406
|
-
// console.log('records', records);
|
|
407
488
|
/* istanbul ignore if -- Just a guard */
|
|
408
489
|
if (!stateObj.format) {
|
|
409
490
|
stateObj.format = 'structuredCloning';
|
|
410
491
|
}
|
|
411
492
|
// Todo: Replace this with async typeson?
|
|
412
|
-
// eslint-disable-next-line promise/avoid-new
|
|
493
|
+
// eslint-disable-next-line promise/avoid-new -- Our own API for now
|
|
413
494
|
return new Promise((resolve, reject) => {
|
|
414
495
|
const structuredCloningFixed = structuredCloningThrowing.filter(
|
|
415
496
|
(typeSpecSet) => {
|
|
@@ -441,13 +522,13 @@ const structuredCloning = {
|
|
|
441
522
|
} else {
|
|
442
523
|
resolve(/** @type {Required<import('../types.js').StateObject>} */ (
|
|
443
524
|
stateObj
|
|
444
|
-
)
|
|
525
|
+
));
|
|
445
526
|
}
|
|
446
527
|
});
|
|
447
528
|
},
|
|
448
|
-
|
|
529
|
+
getTypesAndSchemasForState (types, state) {
|
|
449
530
|
if (state && types.getContextInfo('structuredCloning', state)) {
|
|
450
|
-
const typesForFormat = this.
|
|
531
|
+
const typesForFormat = this.getTypesAndSchemasForState(types)?.types ||
|
|
451
532
|
/* istanbul ignore next -- types should be an array */
|
|
452
533
|
[];
|
|
453
534
|
const contextInfo = types.getContextInfo('structuredCloning', state);
|
|
@@ -455,22 +536,39 @@ const structuredCloning = {
|
|
|
455
536
|
const precedingIdx = typesForFormat.indexOf(after);
|
|
456
537
|
typesForFormat.splice(precedingIdx + 1, 0, type);
|
|
457
538
|
});
|
|
458
|
-
return
|
|
539
|
+
return {
|
|
540
|
+
types: typesForFormat,
|
|
541
|
+
schemaObjects: []
|
|
542
|
+
};
|
|
459
543
|
}
|
|
460
|
-
// Todo:
|
|
461
|
-
//
|
|
462
|
-
//
|
|
544
|
+
// Todo: Introduce new keys (to `Types.contexts`?) which could be used to
|
|
545
|
+
// determine a delimited group of children (rather
|
|
546
|
+
// than manual exception handling as we do here)
|
|
463
547
|
if (state === 'errorsArray') {
|
|
464
|
-
return
|
|
548
|
+
return {
|
|
549
|
+
types: ['error', 'errors'],
|
|
550
|
+
schemaObjects: []
|
|
551
|
+
};
|
|
465
552
|
}
|
|
466
553
|
if (state === 'filelistArray') {
|
|
467
|
-
return
|
|
554
|
+
return {
|
|
555
|
+
types: ['file'],
|
|
556
|
+
schemaObjects: []
|
|
557
|
+
};
|
|
468
558
|
}
|
|
469
|
-
return
|
|
559
|
+
return {
|
|
560
|
+
types: this.types(),
|
|
561
|
+
schemaObjects: []
|
|
562
|
+
};
|
|
470
563
|
/*
|
|
471
|
-
//
|
|
564
|
+
// These have their children determined internally to array
|
|
472
565
|
if (['map', 'set'].includes(state)) {return;}
|
|
473
|
-
|
|
566
|
+
*/
|
|
567
|
+
|
|
568
|
+
// These have their own internal numeric children instead
|
|
569
|
+
/*
|
|
570
|
+
if (
|
|
571
|
+
'int8array', 'uint8array', 'uint8clampedarray',
|
|
474
572
|
'int16array', 'uint16array', 'int32array',
|
|
475
573
|
'uint32array', 'float32array', 'float64array'
|
|
476
574
|
).includes(state)) {return;}
|
|
@@ -481,6 +579,8 @@ const structuredCloning = {
|
|
|
481
579
|
replaceTypes(jsonTypes, [
|
|
482
580
|
[
|
|
483
581
|
'array',
|
|
582
|
+
// We can rename to this instead of `arrayNonindexKeys` if we change
|
|
583
|
+
// typeson-registry name
|
|
484
584
|
// 'sparseArrays',
|
|
485
585
|
'arrayNonindexKeys'
|
|
486
586
|
]
|
|
@@ -493,6 +593,7 @@ const structuredCloning = {
|
|
|
493
593
|
...jsonTypes,
|
|
494
594
|
'undef', // Explicit undefined only
|
|
495
595
|
'bigint',
|
|
596
|
+
'bigintObject',
|
|
496
597
|
'SpecialNumber', // '`NaN`, `Infinity`, `-Infinity`, `-0`
|
|
497
598
|
'date',
|
|
498
599
|
'regexp',
|
package/src/formats.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import indexedDBKey from './formats/indexedDBKey.js';
|
|
2
2
|
import json from './formats/json.js';
|
|
3
3
|
import structuredCloning from './formats/structuredCloning.js';
|
|
4
|
+
import schema from './formats/schema.js';
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* An arbitrary Structured Clone, JSON, etc. value.
|
|
@@ -8,11 +9,15 @@ import structuredCloning from './formats/structuredCloning.js';
|
|
|
8
9
|
*/
|
|
9
10
|
|
|
10
11
|
/**
|
|
11
|
-
* @callback
|
|
12
|
+
* @callback GetTypesAndSchemasForFormatAndState
|
|
12
13
|
* @param {import('./types.js').default} types
|
|
13
14
|
* @param {AvailableFormat} format
|
|
14
15
|
* @param {string} [state]
|
|
15
|
-
* @
|
|
16
|
+
* @param {import('./formatAndTypeChoices.js').ZodexSchema|
|
|
17
|
+
* undefined} [schemaObject]
|
|
18
|
+
* @param {import('./formatAndTypeChoices.js').ZodexSchema|
|
|
19
|
+
* undefined} [schemaOriginal]
|
|
20
|
+
* @returns {TypesAndSchemaObjects|undefined}
|
|
16
21
|
*/
|
|
17
22
|
|
|
18
23
|
/* schema:
|
|
@@ -25,25 +30,57 @@ export const getTypeForFormatStateAndValue = ({format, state, value}) => {
|
|
|
25
30
|
*/
|
|
26
31
|
|
|
27
32
|
/**
|
|
28
|
-
* @typedef {"indexedDBKey"|"json"|"structuredCloning"} AvailableFormat
|
|
33
|
+
* @typedef {"indexedDBKey"|"json"|"structuredCloning"|"schema"} AvailableFormat
|
|
29
34
|
*/
|
|
30
35
|
|
|
31
36
|
/**
|
|
32
37
|
* @typedef {{
|
|
33
|
-
* types: (
|
|
34
|
-
*
|
|
38
|
+
* types: (import('./types.js').AvailableType)[],
|
|
39
|
+
* schemaObjects: import('./formats/schema.js').ZodexSchema[]
|
|
40
|
+
* }} TypesAndSchemaObjects
|
|
41
|
+
*/
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Responsible for traversing over data (along with state information) to build
|
|
45
|
+
* and return a relevant UI element.
|
|
46
|
+
* @callback FormatIterator
|
|
47
|
+
* @param {StructuredCloneValue} records
|
|
48
|
+
* @param {import('./types.js').StateObject} stateObj
|
|
49
|
+
* @returns {Promise<Required<import('./types.js').StateObject>>}
|
|
50
|
+
*/
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* @typedef {object} Format
|
|
54
|
+
* @property {() => (import('./types.js').AvailableType)[]} types Returns list
|
|
55
|
+
* of types generally available to structured cloning. See
|
|
56
|
+
* {@link getTypesAndSchemasForState} for context-dependent method.
|
|
57
|
+
* @property {FormatIterator} iterate Traverses over data to build and return
|
|
58
|
+
* a relevant UI element.
|
|
59
|
+
* @property {(
|
|
60
|
+
* types: import('./types.js').default,
|
|
61
|
+
* state?: string,
|
|
62
|
+
* schemaObject?: import('./formatAndTypeChoices.js').ZodexSchema|
|
|
63
|
+
* undefined,
|
|
64
|
+
* schemaOriginal?: import('./formatAndTypeChoices.js').ZodexSchema|
|
|
65
|
+
* undefined
|
|
66
|
+
* ) => TypesAndSchemaObjects|undefined} getTypesAndSchemasForState Gets the
|
|
67
|
+
* specific types (and schemas) relevant to a given state.
|
|
68
|
+
* @property {(
|
|
35
69
|
* newType: string, value: Date|Array<StructuredCloneValue>
|
|
36
|
-
* ) => boolean|undefined
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
70
|
+
* ) => boolean|undefined} [testInvalid]
|
|
71
|
+
* @property {(
|
|
72
|
+
* typesonType: import('./types.js').AvailableType,
|
|
73
|
+
* types: import('./types.js').default,
|
|
74
|
+
* v?: import('./formats.js').StructuredCloneValue,
|
|
75
|
+
* arrayOrObjectPropertyName?: string,
|
|
76
|
+
* parentSchema?: [import('zodex').SzType, number|undefined]|undefined,
|
|
77
|
+
* stateObj?: import('./types.js').StateObject,
|
|
78
|
+
* ) => {
|
|
79
|
+
* type: import('./types.js').AvailableType|undefined
|
|
80
|
+
* schema?: import('zodex').SzType|undefined,
|
|
81
|
+
* mustBeOptional?: boolean,
|
|
82
|
+
* schemaIdx?: number
|
|
83
|
+
* }} [convertFromTypeson]
|
|
47
84
|
*/
|
|
48
85
|
|
|
49
86
|
/**
|
|
@@ -80,11 +117,7 @@ class Formats {
|
|
|
80
117
|
this.availableFormats = /** @type {{[key: string]: Format}} */ ({
|
|
81
118
|
indexedDBKey,
|
|
82
119
|
json,
|
|
83
|
-
|
|
84
|
-
/* schema:
|
|
85
|
-
schemaAndArbitrary,
|
|
86
|
-
schemaOnly,
|
|
87
|
-
*/
|
|
120
|
+
schema,
|
|
88
121
|
structuredCloning
|
|
89
122
|
});
|
|
90
123
|
}
|
|
@@ -94,7 +127,7 @@ class Formats {
|
|
|
94
127
|
* @param {AvailableFormat} format
|
|
95
128
|
* @param {StructuredCloneValue} record
|
|
96
129
|
* @param {import('./types.js').StateObject} stateObj
|
|
97
|
-
* @returns {Promise<
|
|
130
|
+
* @returns {Promise<Required<import('./types.js').StateObject>>}
|
|
98
131
|
*/
|
|
99
132
|
async getControlsForFormatAndValue (types, format, record, stateObj) {
|
|
100
133
|
return await this.availableFormats[format].
|
|
@@ -109,12 +142,14 @@ class Formats {
|
|
|
109
142
|
}
|
|
110
143
|
|
|
111
144
|
/**
|
|
112
|
-
* @type {
|
|
145
|
+
* @type {GetTypesAndSchemasForFormatAndState}
|
|
113
146
|
*/
|
|
114
|
-
|
|
115
|
-
types, format, state
|
|
147
|
+
getTypesAndSchemasForFormatAndState (
|
|
148
|
+
types, format, state, schemaObject, schemaOriginal
|
|
116
149
|
) {
|
|
117
|
-
return this.availableFormats[format].
|
|
150
|
+
return this.availableFormats[format].getTypesAndSchemasForState(
|
|
151
|
+
types, state, schemaObject, schemaOriginal
|
|
152
|
+
);
|
|
118
153
|
}
|
|
119
154
|
|
|
120
155
|
/**
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import {toStringTag} from '../vendor-imports.js';
|
|
1
2
|
import {$e, $$e} from '../utils/templateUtils.js';
|
|
2
3
|
|
|
3
4
|
/**
|
|
@@ -6,9 +7,13 @@ import {$e, $$e} from '../utils/templateUtils.js';
|
|
|
6
7
|
const BooleanObjectType = {
|
|
7
8
|
option: ['BooleanObject'],
|
|
8
9
|
stringRegex: /^Boolean\((.*)\)$/u,
|
|
10
|
+
valueMatch (x) {
|
|
11
|
+
return toStringTag(x) === 'Boolean' && typeof x === 'object';
|
|
12
|
+
},
|
|
9
13
|
toValue (s) {
|
|
10
14
|
return {
|
|
11
|
-
// eslint-disable-next-line
|
|
15
|
+
// eslint-disable-next-line @stylistic/max-len -- Long
|
|
16
|
+
// eslint-disable-next-line no-new-wrappers, unicorn/new-for-builtins -- Deliberate creation here
|
|
12
17
|
value: new Boolean(s === 'true')
|
|
13
18
|
};
|
|
14
19
|
},
|
|
@@ -27,16 +32,23 @@ const BooleanObjectType = {
|
|
|
27
32
|
const input = inputs[value.valueOf() ? 0 : 1];
|
|
28
33
|
input.checked = true;
|
|
29
34
|
},
|
|
30
|
-
viewUI ({value}) {
|
|
31
|
-
return ['i', {
|
|
35
|
+
viewUI ({value, specificSchemaObject}) {
|
|
36
|
+
return ['i', {
|
|
37
|
+
dataset: {type: 'BooleanObject'},
|
|
38
|
+
title: specificSchemaObject?.description ?? '(a Boolean Object)'
|
|
39
|
+
}, [specificSchemaObject ? `${value}` : `Boolean(${value})`]];
|
|
32
40
|
},
|
|
33
41
|
ct: 0,
|
|
34
42
|
editUI ({
|
|
35
|
-
// eslint-disable-next-line
|
|
36
|
-
|
|
43
|
+
// eslint-disable-next-line @stylistic/max-len -- Long
|
|
44
|
+
// eslint-disable-next-line no-new-wrappers, unicorn/new-for-builtins -- Deliberate creation here
|
|
45
|
+
typeNamespace, specificSchemaObject, value = new Boolean(true)
|
|
37
46
|
}) {
|
|
38
47
|
this.ct++;
|
|
39
|
-
return ['div', {
|
|
48
|
+
return ['div', {
|
|
49
|
+
dataset: {type: 'BooleanObject'},
|
|
50
|
+
title: specificSchemaObject?.description ?? 'Boolean object'
|
|
51
|
+
}, [
|
|
40
52
|
['label', [
|
|
41
53
|
'True',
|
|
42
54
|
['input', {
|