@opra/common 1.17.4 → 1.17.6
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/browser/index.cjs +5 -5
- package/browser/index.mjs +5 -5
- package/cjs/document/data-type/complex-type-base.js +63 -19
- package/esm/document/data-type/complex-type-base.js +62 -19
- package/package.json +2 -1
- package/types/document/data-type/complex-type-base.d.ts +9 -8
- package/types/document/data-type/data-type.d.ts +3 -1
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.ComplexTypeBase = exports.FIELD_PATH_PATTERN = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const object_hash_1 = tslib_1.__importDefault(require("object-hash"));
|
|
4
6
|
const ts_gems_1 = require("ts-gems");
|
|
5
7
|
const valgen_1 = require("valgen");
|
|
6
8
|
const index_js_1 = require("../../helpers/index.js");
|
|
@@ -199,14 +201,18 @@ class ComplexTypeBaseClass extends data_type_js_1.DataType {
|
|
|
199
201
|
*
|
|
200
202
|
*/
|
|
201
203
|
generateCodec(codec, options) {
|
|
202
|
-
const
|
|
203
|
-
?
|
|
204
|
-
:
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
204
|
+
const context = options?.cache
|
|
205
|
+
? options
|
|
206
|
+
: {
|
|
207
|
+
...options,
|
|
208
|
+
projection: Array.isArray(options?.projection)
|
|
209
|
+
? (0, index_js_1.parseFieldsProjection)(options.projection)
|
|
210
|
+
: options?.projection,
|
|
211
|
+
currentPath: '',
|
|
212
|
+
};
|
|
213
|
+
let schema = this._generateSchema(codec, context);
|
|
214
|
+
if (context.generateSchemaHook)
|
|
215
|
+
schema = context.generateSchemaHook(schema, this, context.currentPath);
|
|
210
216
|
let additionalFields;
|
|
211
217
|
if (this.additionalFields instanceof data_type_js_1.DataType) {
|
|
212
218
|
additionalFields = this.additionalFields.generateCodec(codec, options);
|
|
@@ -218,10 +224,10 @@ class ComplexTypeBaseClass extends data_type_js_1.DataType {
|
|
|
218
224
|
additionalFields = 'error';
|
|
219
225
|
else {
|
|
220
226
|
const message = additionalFields[1];
|
|
221
|
-
additionalFields = (0, valgen_1.validator)((input,
|
|
227
|
+
additionalFields = (0, valgen_1.validator)((input, ctx, _this) => ctx.fail(_this, message, input));
|
|
222
228
|
}
|
|
223
229
|
}
|
|
224
|
-
|
|
230
|
+
const fn = valgen_1.vg.isObject(schema, {
|
|
225
231
|
ctor: this.name === 'object' ? Object : this.ctor,
|
|
226
232
|
additionalFields,
|
|
227
233
|
name: this.name,
|
|
@@ -229,8 +235,17 @@ class ComplexTypeBaseClass extends data_type_js_1.DataType {
|
|
|
229
235
|
caseInSensitive: options?.caseInSensitive,
|
|
230
236
|
onFail: options?.onFail,
|
|
231
237
|
});
|
|
238
|
+
if (context.level === 0 && context.forwardCallbacks?.size) {
|
|
239
|
+
for (const cb of context.forwardCallbacks) {
|
|
240
|
+
cb();
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
return fn;
|
|
232
244
|
}
|
|
233
245
|
_generateSchema(codec, context) {
|
|
246
|
+
context.fieldCache = context.fieldCache || new Map();
|
|
247
|
+
context.level = context.level || 0;
|
|
248
|
+
context.forwardCallbacks = context.forwardCallbacks || new Set();
|
|
234
249
|
const schema = {};
|
|
235
250
|
const { currentPath, projection } = context;
|
|
236
251
|
const pickList = !!(projection && Object.values(projection).find(p => !p.sign));
|
|
@@ -263,14 +278,40 @@ class ComplexTypeBaseClass extends data_type_js_1.DataType {
|
|
|
263
278
|
continue;
|
|
264
279
|
}
|
|
265
280
|
}
|
|
266
|
-
const
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
281
|
+
const subProjection = typeof projection === 'object'
|
|
282
|
+
? projection[fieldName]?.projection || '*'
|
|
283
|
+
: projection;
|
|
284
|
+
let cacheItem = context.fieldCache.get(field);
|
|
285
|
+
const cacheKey = typeof subProjection === 'string'
|
|
286
|
+
? subProjection
|
|
287
|
+
: (0, object_hash_1.default)(subProjection || {});
|
|
288
|
+
if (!cacheItem) {
|
|
289
|
+
cacheItem = {};
|
|
290
|
+
context.fieldCache.set(field, cacheItem);
|
|
291
|
+
}
|
|
292
|
+
let fn = cacheItem[cacheKey];
|
|
293
|
+
/** If in progress (circular) */
|
|
294
|
+
if (fn === null) {
|
|
295
|
+
// Temporary set any
|
|
296
|
+
fn = valgen_1.vg.isAny();
|
|
297
|
+
context.forwardCallbacks.add(() => {
|
|
298
|
+
fn = cacheItem[cacheKey];
|
|
299
|
+
schema[fieldName] =
|
|
300
|
+
context.partial || !field.required
|
|
301
|
+
? valgen_1.vg.optional(fn)
|
|
302
|
+
: valgen_1.vg.required(fn);
|
|
303
|
+
});
|
|
304
|
+
}
|
|
305
|
+
else if (!fn) {
|
|
306
|
+
cacheItem[cacheKey] = null;
|
|
307
|
+
fn = this._generateFieldCodec(codec, field, {
|
|
308
|
+
...context,
|
|
309
|
+
partial: context.partial === 'deep' ? context.partial : undefined,
|
|
310
|
+
projection: subProjection,
|
|
311
|
+
currentPath: currentPath + (currentPath ? '.' : '') + fieldName,
|
|
312
|
+
});
|
|
313
|
+
cacheItem[cacheKey] = fn;
|
|
314
|
+
}
|
|
274
315
|
schema[fieldName] =
|
|
275
316
|
context.partial || !field.required ? valgen_1.vg.optional(fn) : valgen_1.vg.required(fn);
|
|
276
317
|
}
|
|
@@ -281,7 +322,10 @@ class ComplexTypeBaseClass extends data_type_js_1.DataType {
|
|
|
281
322
|
return schema;
|
|
282
323
|
}
|
|
283
324
|
_generateFieldCodec(codec, field, context) {
|
|
284
|
-
let fn = field.type.generateCodec(codec,
|
|
325
|
+
let fn = field.type.generateCodec(codec, {
|
|
326
|
+
...context,
|
|
327
|
+
level: context.level + 1,
|
|
328
|
+
});
|
|
285
329
|
if (field.fixed)
|
|
286
330
|
fn = valgen_1.vg.isEqual(field.fixed);
|
|
287
331
|
if (field.isArray)
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import hashObject from 'object-hash';
|
|
1
2
|
import { asMutable } from 'ts-gems';
|
|
2
3
|
import { validator, vg } from 'valgen';
|
|
3
4
|
import { parseFieldsProjection, ResponsiveMap, } from '../../helpers/index.js';
|
|
@@ -196,14 +197,18 @@ class ComplexTypeBaseClass extends DataType {
|
|
|
196
197
|
*
|
|
197
198
|
*/
|
|
198
199
|
generateCodec(codec, options) {
|
|
199
|
-
const
|
|
200
|
-
?
|
|
201
|
-
:
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
200
|
+
const context = options?.cache
|
|
201
|
+
? options
|
|
202
|
+
: {
|
|
203
|
+
...options,
|
|
204
|
+
projection: Array.isArray(options?.projection)
|
|
205
|
+
? parseFieldsProjection(options.projection)
|
|
206
|
+
: options?.projection,
|
|
207
|
+
currentPath: '',
|
|
208
|
+
};
|
|
209
|
+
let schema = this._generateSchema(codec, context);
|
|
210
|
+
if (context.generateSchemaHook)
|
|
211
|
+
schema = context.generateSchemaHook(schema, this, context.currentPath);
|
|
207
212
|
let additionalFields;
|
|
208
213
|
if (this.additionalFields instanceof DataType) {
|
|
209
214
|
additionalFields = this.additionalFields.generateCodec(codec, options);
|
|
@@ -215,10 +220,10 @@ class ComplexTypeBaseClass extends DataType {
|
|
|
215
220
|
additionalFields = 'error';
|
|
216
221
|
else {
|
|
217
222
|
const message = additionalFields[1];
|
|
218
|
-
additionalFields = validator((input,
|
|
223
|
+
additionalFields = validator((input, ctx, _this) => ctx.fail(_this, message, input));
|
|
219
224
|
}
|
|
220
225
|
}
|
|
221
|
-
|
|
226
|
+
const fn = vg.isObject(schema, {
|
|
222
227
|
ctor: this.name === 'object' ? Object : this.ctor,
|
|
223
228
|
additionalFields,
|
|
224
229
|
name: this.name,
|
|
@@ -226,8 +231,17 @@ class ComplexTypeBaseClass extends DataType {
|
|
|
226
231
|
caseInSensitive: options?.caseInSensitive,
|
|
227
232
|
onFail: options?.onFail,
|
|
228
233
|
});
|
|
234
|
+
if (context.level === 0 && context.forwardCallbacks?.size) {
|
|
235
|
+
for (const cb of context.forwardCallbacks) {
|
|
236
|
+
cb();
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
return fn;
|
|
229
240
|
}
|
|
230
241
|
_generateSchema(codec, context) {
|
|
242
|
+
context.fieldCache = context.fieldCache || new Map();
|
|
243
|
+
context.level = context.level || 0;
|
|
244
|
+
context.forwardCallbacks = context.forwardCallbacks || new Set();
|
|
231
245
|
const schema = {};
|
|
232
246
|
const { currentPath, projection } = context;
|
|
233
247
|
const pickList = !!(projection && Object.values(projection).find(p => !p.sign));
|
|
@@ -260,14 +274,40 @@ class ComplexTypeBaseClass extends DataType {
|
|
|
260
274
|
continue;
|
|
261
275
|
}
|
|
262
276
|
}
|
|
263
|
-
const
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
277
|
+
const subProjection = typeof projection === 'object'
|
|
278
|
+
? projection[fieldName]?.projection || '*'
|
|
279
|
+
: projection;
|
|
280
|
+
let cacheItem = context.fieldCache.get(field);
|
|
281
|
+
const cacheKey = typeof subProjection === 'string'
|
|
282
|
+
? subProjection
|
|
283
|
+
: hashObject(subProjection || {});
|
|
284
|
+
if (!cacheItem) {
|
|
285
|
+
cacheItem = {};
|
|
286
|
+
context.fieldCache.set(field, cacheItem);
|
|
287
|
+
}
|
|
288
|
+
let fn = cacheItem[cacheKey];
|
|
289
|
+
/** If in progress (circular) */
|
|
290
|
+
if (fn === null) {
|
|
291
|
+
// Temporary set any
|
|
292
|
+
fn = vg.isAny();
|
|
293
|
+
context.forwardCallbacks.add(() => {
|
|
294
|
+
fn = cacheItem[cacheKey];
|
|
295
|
+
schema[fieldName] =
|
|
296
|
+
context.partial || !field.required
|
|
297
|
+
? vg.optional(fn)
|
|
298
|
+
: vg.required(fn);
|
|
299
|
+
});
|
|
300
|
+
}
|
|
301
|
+
else if (!fn) {
|
|
302
|
+
cacheItem[cacheKey] = null;
|
|
303
|
+
fn = this._generateFieldCodec(codec, field, {
|
|
304
|
+
...context,
|
|
305
|
+
partial: context.partial === 'deep' ? context.partial : undefined,
|
|
306
|
+
projection: subProjection,
|
|
307
|
+
currentPath: currentPath + (currentPath ? '.' : '') + fieldName,
|
|
308
|
+
});
|
|
309
|
+
cacheItem[cacheKey] = fn;
|
|
310
|
+
}
|
|
271
311
|
schema[fieldName] =
|
|
272
312
|
context.partial || !field.required ? vg.optional(fn) : vg.required(fn);
|
|
273
313
|
}
|
|
@@ -278,7 +318,10 @@ class ComplexTypeBaseClass extends DataType {
|
|
|
278
318
|
return schema;
|
|
279
319
|
}
|
|
280
320
|
_generateFieldCodec(codec, field, context) {
|
|
281
|
-
let fn = field.type.generateCodec(codec,
|
|
321
|
+
let fn = field.type.generateCodec(codec, {
|
|
322
|
+
...context,
|
|
323
|
+
level: context.level + 1,
|
|
324
|
+
});
|
|
282
325
|
if (field.fixed)
|
|
283
326
|
fn = vg.isEqual(field.fixed);
|
|
284
327
|
if (field.isArray)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opra/common",
|
|
3
|
-
"version": "1.17.
|
|
3
|
+
"version": "1.17.6",
|
|
4
4
|
"description": "Opra common package",
|
|
5
5
|
"author": "Panates",
|
|
6
6
|
"license": "MIT",
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
"@browsery/type-is": "^1.6.18-r8",
|
|
13
13
|
"@jsopen/objects": "^1.6.2",
|
|
14
14
|
"fast-tokenizer": "^1.7.0",
|
|
15
|
+
"object-hash": "^3.0.0",
|
|
15
16
|
"putil-promisify": "^1.10.1",
|
|
16
17
|
"putil-varhelpers": "^1.6.5",
|
|
17
18
|
"reflect-metadata": "^0.2.2",
|
|
@@ -73,13 +73,14 @@ declare abstract class ComplexTypeBaseClass extends DataType {
|
|
|
73
73
|
*
|
|
74
74
|
*/
|
|
75
75
|
generateCodec(codec: 'encode' | 'decode', options?: DataType.GenerateCodecOptions): Validator;
|
|
76
|
-
protected _generateSchema(codec: 'encode' | 'decode', context:
|
|
77
|
-
|
|
78
|
-
projection?: FieldsProjection | '*';
|
|
79
|
-
}): IsObject.Schema;
|
|
80
|
-
protected _generateFieldCodec(codec: 'encode' | 'decode', field: ApiField, context: StrictOmit<DataType.GenerateCodecOptions, 'projection'> & {
|
|
81
|
-
currentPath: string;
|
|
82
|
-
projection?: FieldsProjection | '*';
|
|
83
|
-
}): Validator;
|
|
76
|
+
protected _generateSchema(codec: 'encode' | 'decode', context: GenerateCodecContext): IsObject.Schema;
|
|
77
|
+
protected _generateFieldCodec(codec: 'encode' | 'decode', field: ApiField, context: GenerateCodecContext): Validator;
|
|
84
78
|
}
|
|
79
|
+
type GenerateCodecContext = StrictOmit<DataType.GenerateCodecOptions, 'projection'> & {
|
|
80
|
+
currentPath: string;
|
|
81
|
+
projection?: FieldsProjection | '*';
|
|
82
|
+
level?: number;
|
|
83
|
+
fieldCache?: Map<ApiField, Record<string, Validator | null>>;
|
|
84
|
+
forwardCallbacks?: Set<Function>;
|
|
85
|
+
};
|
|
85
86
|
export {};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type StrictOmit, type Type } from 'ts-gems';
|
|
2
|
-
import type { ValidationOptions, Validator } from 'valgen';
|
|
2
|
+
import type { IsObject, ValidationOptions, Validator } from 'valgen';
|
|
3
3
|
import { FieldsProjection } from '../../helpers/index.js';
|
|
4
4
|
import type { DataTypeBase } from '../../schema/data-type/data-type.interface.js';
|
|
5
5
|
import { OpraSchema } from '../../schema/index.js';
|
|
@@ -7,6 +7,7 @@ import type { ApiDocument } from '../api-document.js';
|
|
|
7
7
|
import { DocumentElement } from '../common/document-element.js';
|
|
8
8
|
import { DocumentInitContext } from '../common/document-init-context.js';
|
|
9
9
|
import { nodeInspectCustom } from '../utils/inspect.util.js';
|
|
10
|
+
import type { ComplexType } from './complex-type.js';
|
|
10
11
|
/**
|
|
11
12
|
* @namespace DataType
|
|
12
13
|
*/
|
|
@@ -30,6 +31,7 @@ export declare namespace DataType {
|
|
|
30
31
|
ignoreReadonlyFields?: boolean;
|
|
31
32
|
ignoreWriteonlyFields?: boolean;
|
|
32
33
|
allowPatchOperators?: boolean;
|
|
34
|
+
generateSchemaHook?: (schema: IsObject.Schema, dataType: ComplexType, path: string) => IsObject.Schema;
|
|
33
35
|
}
|
|
34
36
|
}
|
|
35
37
|
interface DataTypeStatic {
|