@opra/common 0.31.12 → 0.31.13

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.js CHANGED
@@ -350,6 +350,12 @@ var ResponsiveMap = class extends Map {
350
350
  };
351
351
  return new Proxy({}, finalHandler);
352
352
  }
353
+ toObject() {
354
+ return Object.keys(this.keys()).reduce((trg, k) => {
355
+ trg[k] = this.get(k);
356
+ return trg;
357
+ }, {});
358
+ }
353
359
  [(_a = kKeyMap, _b = kKeyOrder, _c = kWellKnownKeys, _d = kOptions, Symbol.iterator)]() {
354
360
  return this.entries();
355
361
  }
@@ -2148,9 +2154,10 @@ var FieldClass = class {
2148
2154
  this.deprecated = init.deprecated;
2149
2155
  this.examples = init.examples;
2150
2156
  this.format = init.format;
2157
+ this.partialUpdate = init.partialUpdate;
2151
2158
  }
2152
2159
  exportSchema(options) {
2153
- const isAnonymous = !this.type.name || this.type.kind === "ComplexType" && this.type.isAnonymous;
2160
+ const isAnonymous = !this.type?.name || this.type?.kind === "ComplexType" && this.type.isAnonymous;
2154
2161
  return omitUndefined({
2155
2162
  type: this.type ? isAnonymous ? this.type.exportSchema(options) : this.type.name : void 0,
2156
2163
  description: this.description,
@@ -2164,7 +2171,8 @@ var FieldClass = class {
2164
2171
  translatable: this.translatable,
2165
2172
  deprecated: this.deprecated,
2166
2173
  examples: this.examples,
2167
- format: this.format
2174
+ format: this.format,
2175
+ partialUpdate: this.partialUpdate
2168
2176
  });
2169
2177
  }
2170
2178
  generateCodec(codec, options) {
@@ -2175,7 +2183,8 @@ var FieldClass = class {
2175
2183
  let fn = this.type.generateCodec(codec, { ...options, designType: this.designType });
2176
2184
  if (this.isArray)
2177
2185
  fn = vg3.isArray(fn);
2178
- return !options?.partial && this.required ? vg3.required(fn) : vg3.optional(fn);
2186
+ const partial = options?.partial && (this.partialUpdate || !this.isArray);
2187
+ return !partial && this.required ? vg3.required(fn) : vg3.optional(fn);
2179
2188
  }
2180
2189
  };
2181
2190
 
@@ -2362,8 +2371,12 @@ var ComplexTypeClass = class extends DataType {
2362
2371
  return false;
2363
2372
  }
2364
2373
  generateCodec(codec, options) {
2365
- const schema = this._generateCodecSchema(codec, options);
2366
- const additionalFields = this.additionalFields instanceof DataType ? this.additionalFields.generateCodec(codec, options) : this.additionalFields;
2374
+ const schema = this.generateCodecSchema(codec, options);
2375
+ const additionalFields = this.additionalFields instanceof DataType ? this.additionalFields.generateCodec(codec, {
2376
+ operation: options?.operation,
2377
+ caseSensitive: options?.caseSensitive,
2378
+ partial: options?.partial
2379
+ }) : this.additionalFields;
2367
2380
  return vg4.isObject(schema, {
2368
2381
  ctor: this.ctor,
2369
2382
  additionalFields,
@@ -2371,34 +2384,78 @@ var ComplexTypeClass = class extends DataType {
2371
2384
  caseInSensitive: !options?.caseSensitive
2372
2385
  });
2373
2386
  }
2387
+ generateCodecSchema(codec, options) {
2388
+ const opts = {
2389
+ ...options,
2390
+ pick: (options?.pick || []).map((x) => x.toLowerCase()),
2391
+ omit: (options?.omit || []).map((x) => x.toLowerCase()),
2392
+ overwriteFields: options?.overwriteFields ? this._buildOverwriteFieldsTree(options.overwriteFields) : void 0
2393
+ };
2394
+ return this._generateCodecSchema(codec, opts);
2395
+ }
2374
2396
  _generateCodecSchema(codec, options) {
2375
2397
  const schema = {};
2376
- const pickOption = (options?.pick || []).map((x) => x.toLowerCase());
2377
- const omitOption = (options?.omit || []).map((x) => x.toLowerCase());
2378
- const dedupedFieldNames = (options?.overwriteFields ? Array.from(/* @__PURE__ */ new Set([...this.fields.keys(), ...options?.overwriteFields.keys()])) : Array.from(this.fields.keys())).map((x) => x.toLowerCase());
2379
- for (const nameLower of dedupedFieldNames) {
2380
- const overwriteField = options?.overwriteFields?.get(nameLower);
2381
- const field = this.fields.get(nameLower);
2382
- if (!(field || overwriteField))
2383
- continue;
2384
- if (!overwriteField && (omitOption.find((x) => x === nameLower) || pickOption.length && !pickOption.find((x) => x === nameLower || x.startsWith(nameLower + "."))))
2398
+ const overwriteFields = options?.overwriteFields;
2399
+ const optionsPick = options?.pick || [];
2400
+ const optionsOmit = options?.omit || [];
2401
+ const fieldNames = [...this.fields.keys()];
2402
+ if (overwriteFields) {
2403
+ for (const k of Object.keys(overwriteFields)) {
2404
+ if (!this.fields.has(k))
2405
+ fieldNames.push(k);
2406
+ }
2407
+ }
2408
+ for (const fieldName of fieldNames) {
2409
+ const lowerName = fieldName.toLowerCase();
2410
+ const overwriteFieldInit = overwriteFields?.[fieldName];
2411
+ if (!overwriteFieldInit && (optionsOmit.find((x) => x === lowerName) || optionsPick.length && !optionsPick.find((x) => x === lowerName || x.startsWith(lowerName + "."))))
2385
2412
  continue;
2413
+ const subOptions = {
2414
+ ...options,
2415
+ pick: optionsPick.filter((x) => x.startsWith(lowerName + ".")).map((x) => x.substring(x.indexOf(".") + 1)),
2416
+ omit: optionsOmit.filter((x) => x.startsWith(lowerName + ".")).map((x) => x.substring(x.indexOf(".") + 1)),
2417
+ overwriteFields: overwriteFieldInit?.overrideFields
2418
+ };
2386
2419
  let f;
2387
- if (overwriteField) {
2388
- f = { ...overwriteField };
2389
- if (!field)
2390
- f.type = this.document.getDataType("any");
2391
- Object.setPrototypeOf(f, field || ApiField.prototype);
2420
+ if (overwriteFieldInit) {
2421
+ const field = this.fields.get(fieldName);
2422
+ const init = { ...field, ...overwriteFieldInit, name: fieldName };
2423
+ if (!(init.type instanceof DataType))
2424
+ init.type = this.document.getDataType(init.type || "any");
2425
+ f = new ApiField(this, init);
2392
2426
  } else
2393
- f = field;
2394
- schema[f.name] = f.generateCodec(codec, {
2395
- ...options,
2396
- pick: overwriteField ? [] : pickOption.filter((x) => x.startsWith(nameLower + ".")).map((x) => x.substring(x.indexOf(".") + 1)),
2397
- omit: overwriteField ? [] : omitOption.filter((x) => x.startsWith(nameLower + ".")).map((x) => x.substring(x.indexOf(".") + 1))
2398
- });
2427
+ f = this.getField(fieldName);
2428
+ schema[f.name] = f.generateCodec(codec, subOptions);
2399
2429
  }
2400
2430
  return schema;
2401
2431
  }
2432
+ _buildOverwriteFieldsTree(obj) {
2433
+ const tree = {};
2434
+ for (let k of Object.keys(obj)) {
2435
+ const v = obj[k];
2436
+ if (!k.includes(".")) {
2437
+ const field = this.fields.get(k);
2438
+ if (field)
2439
+ k = field.name;
2440
+ tree[k] = { ...tree[k], ...v };
2441
+ continue;
2442
+ }
2443
+ const keyPath = k.split(".");
2444
+ let subTree = tree;
2445
+ while (keyPath.length) {
2446
+ let j = keyPath.shift();
2447
+ const field = this.fields.get(j);
2448
+ if (field)
2449
+ j = field.name;
2450
+ const treeItem = subTree[j] = subTree[j] || {};
2451
+ if (keyPath.length) {
2452
+ subTree = treeItem.overrideFields = treeItem.overrideFields || {};
2453
+ } else
2454
+ Object.assign(treeItem, v);
2455
+ }
2456
+ }
2457
+ return tree;
2458
+ }
2402
2459
  };
2403
2460
 
2404
2461
  // ../../build/common/esm/document/data-type/complex-type.js
@@ -11121,22 +11178,20 @@ var CrudOperation = class extends Endpoint {
11121
11178
  this.encodeReturning = vg7.isAny();
11122
11179
  this.returnType = init.returnType instanceof DataType ? init.returnType : this.resource.document.getDataType(init.returnType || "any");
11123
11180
  this.encodeReturning = this.returnType.generateCodec("encode", { operation: "read" });
11124
- if (init.options?.inputOverwriteFields)
11125
- this.inputOverwriteFields = new ResponsiveMap(init.options.inputOverwriteFields);
11126
- if (init.options?.outputOverwriteFields)
11127
- this.outputOverwriteFields = new ResponsiveMap(init.options.outputOverwriteFields);
11181
+ this.inputOverwriteFields = init.options.inputOverwriteFields;
11182
+ this.outputOverwriteFields = init.options.outputOverwriteFields;
11128
11183
  }
11129
11184
  exportSchema(options) {
11130
11185
  const schema = super.exportSchema(options);
11131
11186
  if (this.inputOverwriteFields) {
11132
11187
  const trg = schema.options.inputOverwriteFields = {};
11133
- Array.from(this.inputOverwriteFields.entries()).forEach(([k, o]) => {
11188
+ Object.keys(this.inputOverwriteFields).forEach(([k, o]) => {
11134
11189
  trg[k] = ApiField.prototype.exportSchema.call(o, options);
11135
11190
  });
11136
11191
  }
11137
11192
  if (this.outputOverwriteFields) {
11138
11193
  const trg = schema.options.outputOverwriteFields = {};
11139
- Array.from(this.outputOverwriteFields.entries()).forEach(([k, o]) => {
11194
+ Object.keys(this.outputOverwriteFields).forEach(([k, o]) => {
11140
11195
  trg[k] = ApiField.prototype.exportSchema.call(o, options);
11141
11196
  });
11142
11197
  }
@@ -163,9 +163,13 @@ class ComplexTypeClass extends data_type_js_1.DataType {
163
163
  return false;
164
164
  }
165
165
  generateCodec(codec, options) {
166
- const schema = this._generateCodecSchema(codec, options);
166
+ const schema = this.generateCodecSchema(codec, options);
167
167
  const additionalFields = this.additionalFields instanceof data_type_js_1.DataType
168
- ? this.additionalFields.generateCodec(codec, options)
168
+ ? this.additionalFields.generateCodec(codec, {
169
+ operation: options?.operation,
170
+ caseSensitive: options?.caseSensitive,
171
+ partial: options?.partial
172
+ })
169
173
  : this.additionalFields;
170
174
  return vg.isObject(schema, {
171
175
  ctor: this.ctor,
@@ -174,45 +178,90 @@ class ComplexTypeClass extends data_type_js_1.DataType {
174
178
  caseInSensitive: !options?.caseSensitive
175
179
  });
176
180
  }
181
+ generateCodecSchema(codec, options) {
182
+ const opts = {
183
+ ...options,
184
+ pick: (options?.pick || []).map(x => x.toLowerCase()),
185
+ omit: (options?.omit || []).map(x => x.toLowerCase()),
186
+ overwriteFields: options?.overwriteFields ? this._buildOverwriteFieldsTree(options.overwriteFields) : undefined,
187
+ };
188
+ return this._generateCodecSchema(codec, opts);
189
+ }
177
190
  _generateCodecSchema(codec, options) {
178
191
  const schema = {};
179
- const pickOption = (options?.pick || []).map(x => x.toLowerCase());
180
- const omitOption = (options?.omit || []).map(x => x.toLowerCase());
181
- const dedupedFieldNames = (options?.overwriteFields
182
- ? Array.from(new Set([...this.fields.keys(), ...options?.overwriteFields.keys()]))
183
- : Array.from(this.fields.keys())).map(x => x.toLowerCase());
184
- for (const nameLower of dedupedFieldNames) {
185
- const overwriteField = options?.overwriteFields?.get(nameLower);
186
- const field = this.fields.get(nameLower);
187
- /* istanbul ignore next */
188
- if (!(field || overwriteField))
189
- continue;
190
- if (!overwriteField &&
191
- (omitOption.find(x => x === nameLower) ||
192
- (pickOption.length && !pickOption.find(x => x === nameLower || x.startsWith(nameLower + '.')))))
192
+ const overwriteFields = options?.overwriteFields;
193
+ const optionsPick = options?.pick || [];
194
+ const optionsOmit = options?.omit || [];
195
+ const fieldNames = [...this.fields.keys()];
196
+ // Add field name from overwriteFields which doesn't exist in this.fields
197
+ if (overwriteFields) {
198
+ for (const k of Object.keys(overwriteFields)) {
199
+ if (!this.fields.has(k))
200
+ fieldNames.push(k);
201
+ }
202
+ }
203
+ // Process fields
204
+ for (const fieldName of fieldNames) {
205
+ const lowerName = fieldName.toLowerCase();
206
+ const overwriteFieldInit = overwriteFields?.[fieldName];
207
+ // If field omitted or not in pick list we ignore it unless overwriteField defined
208
+ if (!overwriteFieldInit &&
209
+ (optionsOmit.find(x => x === lowerName) ||
210
+ (optionsPick.length && !optionsPick.find(x => x === lowerName || x.startsWith(lowerName + '.')))))
193
211
  continue;
212
+ const subOptions = {
213
+ ...options,
214
+ pick: optionsPick
215
+ .filter(x => x.startsWith(lowerName + '.'))
216
+ .map(x => x.substring(x.indexOf('.') + 1)),
217
+ omit: optionsOmit
218
+ .filter(x => x.startsWith(lowerName + '.'))
219
+ .map(x => x.substring(x.indexOf('.') + 1)),
220
+ overwriteFields: overwriteFieldInit?.overrideFields
221
+ };
194
222
  let f;
195
- if (overwriteField) {
196
- f = { ...overwriteField };
197
- if (!field)
198
- f.type = this.document.getDataType('any');
199
- Object.setPrototypeOf(f, field || field_js_1.ApiField.prototype);
223
+ if (overwriteFieldInit) {
224
+ const field = this.fields.get(fieldName);
225
+ const init = { ...field, ...overwriteFieldInit, name: fieldName };
226
+ if (!(init.type instanceof data_type_js_1.DataType))
227
+ init.type = this.document.getDataType(init.type || 'any');
228
+ f = new field_js_1.ApiField(this, init);
200
229
  }
201
230
  else
202
- f = field;
203
- schema[f.name] = f.generateCodec(codec, {
204
- ...options,
205
- pick: overwriteField ? [] :
206
- pickOption
207
- .filter(x => x.startsWith(nameLower + '.'))
208
- .map(x => x.substring(x.indexOf('.') + 1)),
209
- omit: overwriteField ? [] :
210
- omitOption
211
- .filter(x => x.startsWith(nameLower + '.'))
212
- .map(x => x.substring(x.indexOf('.') + 1)),
213
- });
231
+ f = this.getField(fieldName);
232
+ schema[f.name] = f.generateCodec(codec, subOptions);
214
233
  }
215
234
  return schema;
216
235
  }
236
+ _buildOverwriteFieldsTree(obj) {
237
+ const tree = {};
238
+ for (let k of Object.keys(obj)) {
239
+ const v = obj[k];
240
+ if (!k.includes('.')) {
241
+ // Fix field name
242
+ const field = this.fields.get(k);
243
+ if (field)
244
+ k = field.name;
245
+ tree[k] = { ...tree[k], ...v };
246
+ continue;
247
+ }
248
+ const keyPath = k.split('.');
249
+ let subTree = tree;
250
+ while (keyPath.length) {
251
+ let j = keyPath.shift();
252
+ // Fix field name
253
+ const field = this.fields.get(j);
254
+ if (field)
255
+ j = field.name;
256
+ const treeItem = subTree[j] = subTree[j] || {};
257
+ if (keyPath.length) {
258
+ subTree = treeItem.overrideFields = treeItem.overrideFields || {};
259
+ }
260
+ else
261
+ Object.assign(treeItem, v);
262
+ }
263
+ }
264
+ return tree;
265
+ }
217
266
  }
218
267
  exports.ComplexTypeClass = ComplexTypeClass;
@@ -23,10 +23,11 @@ class FieldClass {
23
23
  this.deprecated = init.deprecated;
24
24
  this.examples = init.examples;
25
25
  this.format = init.format;
26
+ this.partialUpdate = init.partialUpdate;
26
27
  }
27
28
  exportSchema(options) {
28
- const isAnonymous = !this.type.name ||
29
- (this.type.kind === 'ComplexType' && this.type.isAnonymous);
29
+ const isAnonymous = !this.type?.name ||
30
+ (this.type?.kind === 'ComplexType' && this.type.isAnonymous);
30
31
  return (0, index_js_1.omitUndefined)({
31
32
  type: this.type
32
33
  ? (isAnonymous ? this.type.exportSchema(options) : this.type.name)
@@ -43,6 +44,7 @@ class FieldClass {
43
44
  deprecated: this.deprecated,
44
45
  examples: this.examples,
45
46
  format: this.format,
47
+ partialUpdate: this.partialUpdate,
46
48
  });
47
49
  }
48
50
  generateCodec(codec, options) {
@@ -53,7 +55,8 @@ class FieldClass {
53
55
  let fn = this.type.generateCodec(codec, { ...options, designType: this.designType });
54
56
  if (this.isArray)
55
57
  fn = vg.isArray(fn);
56
- return !options?.partial && this.required ? vg.required(fn) : vg.optional(fn);
58
+ const partial = options?.partial && (this.partialUpdate || !this.isArray);
59
+ return !partial && this.required ? vg.required(fn) : vg.optional(fn);
57
60
  }
58
61
  }
59
62
  exports.FieldClass = FieldClass;
@@ -3,7 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.CrudOperation = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  const vg = tslib_1.__importStar(require("valgen"));
6
- const index_js_1 = require("../../helpers/index.js");
7
6
  const data_type_js_1 = require("../data-type/data-type.js");
8
7
  const field_js_1 = require("../data-type/field.js");
9
8
  const endpoint_js_1 = require("./endpoint.js");
@@ -22,23 +21,21 @@ class CrudOperation extends endpoint_js_1.Endpoint {
22
21
  this.returnType = init.returnType instanceof data_type_js_1.DataType
23
22
  ? init.returnType : this.resource.document.getDataType(init.returnType || 'any');
24
23
  this.encodeReturning = this.returnType.generateCodec('encode', { operation: 'read' });
25
- if (init.options?.inputOverwriteFields)
26
- this.inputOverwriteFields = new index_js_1.ResponsiveMap(init.options.inputOverwriteFields);
27
- if (init.options?.outputOverwriteFields)
28
- this.outputOverwriteFields = new index_js_1.ResponsiveMap(init.options.outputOverwriteFields);
24
+ this.inputOverwriteFields = init.options.inputOverwriteFields;
25
+ this.outputOverwriteFields = init.options.outputOverwriteFields;
29
26
  }
30
27
  exportSchema(options) {
31
28
  const schema = super.exportSchema(options);
32
29
  if (this.inputOverwriteFields) {
33
30
  const trg = schema.options.inputOverwriteFields = {};
34
- Array.from(this.inputOverwriteFields.entries())
31
+ Object.keys(this.inputOverwriteFields)
35
32
  .forEach(([k, o]) => {
36
33
  trg[k] = field_js_1.ApiField.prototype.exportSchema.call(o, options);
37
34
  });
38
35
  }
39
36
  if (this.outputOverwriteFields) {
40
37
  const trg = schema.options.outputOverwriteFields = {};
41
- Array.from(this.outputOverwriteFields.entries())
38
+ Object.keys(this.outputOverwriteFields)
42
39
  .forEach(([k, o]) => {
43
40
  trg[k] = field_js_1.ApiField.prototype.exportSchema.call(o, options);
44
41
  });
@@ -154,6 +154,12 @@ class ResponsiveMap extends Map {
154
154
  };
155
155
  return new Proxy({}, finalHandler);
156
156
  }
157
+ toObject() {
158
+ return Object.keys(this.keys()).reduce((trg, k) => {
159
+ trg[k] = this.get(k);
160
+ return trg;
161
+ }, {});
162
+ }
157
163
  [(_a = kKeyMap, _b = kKeyOrder, _c = kWellKnownKeys, _d = kOptions, Symbol.iterator)]() {
158
164
  return this.entries();
159
165
  }
@@ -159,9 +159,13 @@ export class ComplexTypeClass extends DataType {
159
159
  return false;
160
160
  }
161
161
  generateCodec(codec, options) {
162
- const schema = this._generateCodecSchema(codec, options);
162
+ const schema = this.generateCodecSchema(codec, options);
163
163
  const additionalFields = this.additionalFields instanceof DataType
164
- ? this.additionalFields.generateCodec(codec, options)
164
+ ? this.additionalFields.generateCodec(codec, {
165
+ operation: options?.operation,
166
+ caseSensitive: options?.caseSensitive,
167
+ partial: options?.partial
168
+ })
165
169
  : this.additionalFields;
166
170
  return vg.isObject(schema, {
167
171
  ctor: this.ctor,
@@ -170,44 +174,89 @@ export class ComplexTypeClass extends DataType {
170
174
  caseInSensitive: !options?.caseSensitive
171
175
  });
172
176
  }
177
+ generateCodecSchema(codec, options) {
178
+ const opts = {
179
+ ...options,
180
+ pick: (options?.pick || []).map(x => x.toLowerCase()),
181
+ omit: (options?.omit || []).map(x => x.toLowerCase()),
182
+ overwriteFields: options?.overwriteFields ? this._buildOverwriteFieldsTree(options.overwriteFields) : undefined,
183
+ };
184
+ return this._generateCodecSchema(codec, opts);
185
+ }
173
186
  _generateCodecSchema(codec, options) {
174
187
  const schema = {};
175
- const pickOption = (options?.pick || []).map(x => x.toLowerCase());
176
- const omitOption = (options?.omit || []).map(x => x.toLowerCase());
177
- const dedupedFieldNames = (options?.overwriteFields
178
- ? Array.from(new Set([...this.fields.keys(), ...options?.overwriteFields.keys()]))
179
- : Array.from(this.fields.keys())).map(x => x.toLowerCase());
180
- for (const nameLower of dedupedFieldNames) {
181
- const overwriteField = options?.overwriteFields?.get(nameLower);
182
- const field = this.fields.get(nameLower);
183
- /* istanbul ignore next */
184
- if (!(field || overwriteField))
185
- continue;
186
- if (!overwriteField &&
187
- (omitOption.find(x => x === nameLower) ||
188
- (pickOption.length && !pickOption.find(x => x === nameLower || x.startsWith(nameLower + '.')))))
188
+ const overwriteFields = options?.overwriteFields;
189
+ const optionsPick = options?.pick || [];
190
+ const optionsOmit = options?.omit || [];
191
+ const fieldNames = [...this.fields.keys()];
192
+ // Add field name from overwriteFields which doesn't exist in this.fields
193
+ if (overwriteFields) {
194
+ for (const k of Object.keys(overwriteFields)) {
195
+ if (!this.fields.has(k))
196
+ fieldNames.push(k);
197
+ }
198
+ }
199
+ // Process fields
200
+ for (const fieldName of fieldNames) {
201
+ const lowerName = fieldName.toLowerCase();
202
+ const overwriteFieldInit = overwriteFields?.[fieldName];
203
+ // If field omitted or not in pick list we ignore it unless overwriteField defined
204
+ if (!overwriteFieldInit &&
205
+ (optionsOmit.find(x => x === lowerName) ||
206
+ (optionsPick.length && !optionsPick.find(x => x === lowerName || x.startsWith(lowerName + '.')))))
189
207
  continue;
208
+ const subOptions = {
209
+ ...options,
210
+ pick: optionsPick
211
+ .filter(x => x.startsWith(lowerName + '.'))
212
+ .map(x => x.substring(x.indexOf('.') + 1)),
213
+ omit: optionsOmit
214
+ .filter(x => x.startsWith(lowerName + '.'))
215
+ .map(x => x.substring(x.indexOf('.') + 1)),
216
+ overwriteFields: overwriteFieldInit?.overrideFields
217
+ };
190
218
  let f;
191
- if (overwriteField) {
192
- f = { ...overwriteField };
193
- if (!field)
194
- f.type = this.document.getDataType('any');
195
- Object.setPrototypeOf(f, field || ApiField.prototype);
219
+ if (overwriteFieldInit) {
220
+ const field = this.fields.get(fieldName);
221
+ const init = { ...field, ...overwriteFieldInit, name: fieldName };
222
+ if (!(init.type instanceof DataType))
223
+ init.type = this.document.getDataType(init.type || 'any');
224
+ f = new ApiField(this, init);
196
225
  }
197
226
  else
198
- f = field;
199
- schema[f.name] = f.generateCodec(codec, {
200
- ...options,
201
- pick: overwriteField ? [] :
202
- pickOption
203
- .filter(x => x.startsWith(nameLower + '.'))
204
- .map(x => x.substring(x.indexOf('.') + 1)),
205
- omit: overwriteField ? [] :
206
- omitOption
207
- .filter(x => x.startsWith(nameLower + '.'))
208
- .map(x => x.substring(x.indexOf('.') + 1)),
209
- });
227
+ f = this.getField(fieldName);
228
+ schema[f.name] = f.generateCodec(codec, subOptions);
210
229
  }
211
230
  return schema;
212
231
  }
232
+ _buildOverwriteFieldsTree(obj) {
233
+ const tree = {};
234
+ for (let k of Object.keys(obj)) {
235
+ const v = obj[k];
236
+ if (!k.includes('.')) {
237
+ // Fix field name
238
+ const field = this.fields.get(k);
239
+ if (field)
240
+ k = field.name;
241
+ tree[k] = { ...tree[k], ...v };
242
+ continue;
243
+ }
244
+ const keyPath = k.split('.');
245
+ let subTree = tree;
246
+ while (keyPath.length) {
247
+ let j = keyPath.shift();
248
+ // Fix field name
249
+ const field = this.fields.get(j);
250
+ if (field)
251
+ j = field.name;
252
+ const treeItem = subTree[j] = subTree[j] || {};
253
+ if (keyPath.length) {
254
+ subTree = treeItem.overrideFields = treeItem.overrideFields || {};
255
+ }
256
+ else
257
+ Object.assign(treeItem, v);
258
+ }
259
+ }
260
+ return tree;
261
+ }
213
262
  }
@@ -19,10 +19,11 @@ export class FieldClass {
19
19
  this.deprecated = init.deprecated;
20
20
  this.examples = init.examples;
21
21
  this.format = init.format;
22
+ this.partialUpdate = init.partialUpdate;
22
23
  }
23
24
  exportSchema(options) {
24
- const isAnonymous = !this.type.name ||
25
- (this.type.kind === 'ComplexType' && this.type.isAnonymous);
25
+ const isAnonymous = !this.type?.name ||
26
+ (this.type?.kind === 'ComplexType' && this.type.isAnonymous);
26
27
  return omitUndefined({
27
28
  type: this.type
28
29
  ? (isAnonymous ? this.type.exportSchema(options) : this.type.name)
@@ -39,6 +40,7 @@ export class FieldClass {
39
40
  deprecated: this.deprecated,
40
41
  examples: this.examples,
41
42
  format: this.format,
43
+ partialUpdate: this.partialUpdate,
42
44
  });
43
45
  }
44
46
  generateCodec(codec, options) {
@@ -49,6 +51,7 @@ export class FieldClass {
49
51
  let fn = this.type.generateCodec(codec, { ...options, designType: this.designType });
50
52
  if (this.isArray)
51
53
  fn = vg.isArray(fn);
52
- return !options?.partial && this.required ? vg.required(fn) : vg.optional(fn);
54
+ const partial = options?.partial && (this.partialUpdate || !this.isArray);
55
+ return !partial && this.required ? vg.required(fn) : vg.optional(fn);
53
56
  }
54
57
  }
@@ -1,5 +1,4 @@
1
1
  import * as vg from 'valgen';
2
- import { ResponsiveMap } from '../../helpers/index.js';
3
2
  import { DataType } from '../data-type/data-type.js';
4
3
  import { ApiField } from '../data-type/field.js';
5
4
  import { Endpoint } from './endpoint.js';
@@ -18,23 +17,21 @@ export class CrudOperation extends Endpoint {
18
17
  this.returnType = init.returnType instanceof DataType
19
18
  ? init.returnType : this.resource.document.getDataType(init.returnType || 'any');
20
19
  this.encodeReturning = this.returnType.generateCodec('encode', { operation: 'read' });
21
- if (init.options?.inputOverwriteFields)
22
- this.inputOverwriteFields = new ResponsiveMap(init.options.inputOverwriteFields);
23
- if (init.options?.outputOverwriteFields)
24
- this.outputOverwriteFields = new ResponsiveMap(init.options.outputOverwriteFields);
20
+ this.inputOverwriteFields = init.options.inputOverwriteFields;
21
+ this.outputOverwriteFields = init.options.outputOverwriteFields;
25
22
  }
26
23
  exportSchema(options) {
27
24
  const schema = super.exportSchema(options);
28
25
  if (this.inputOverwriteFields) {
29
26
  const trg = schema.options.inputOverwriteFields = {};
30
- Array.from(this.inputOverwriteFields.entries())
27
+ Object.keys(this.inputOverwriteFields)
31
28
  .forEach(([k, o]) => {
32
29
  trg[k] = ApiField.prototype.exportSchema.call(o, options);
33
30
  });
34
31
  }
35
32
  if (this.outputOverwriteFields) {
36
33
  const trg = schema.options.outputOverwriteFields = {};
37
- Array.from(this.outputOverwriteFields.entries())
34
+ Object.keys(this.outputOverwriteFields)
38
35
  .forEach(([k, o]) => {
39
36
  trg[k] = ApiField.prototype.exportSchema.call(o, options);
40
37
  });
@@ -151,6 +151,12 @@ export class ResponsiveMap extends Map {
151
151
  };
152
152
  return new Proxy({}, finalHandler);
153
153
  }
154
+ toObject() {
155
+ return Object.keys(this.keys()).reduce((trg, k) => {
156
+ trg[k] = this.get(k);
157
+ return trg;
158
+ }, {});
159
+ }
154
160
  [(_a = kKeyMap, _b = kKeyOrder, _c = kWellKnownKeys, _d = kOptions, Symbol.iterator)]() {
155
161
  return this.entries();
156
162
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opra/common",
3
- "version": "0.31.12",
3
+ "version": "0.31.13",
4
4
  "description": "Opra common package",
5
5
  "author": "Panates",
6
6
  "license": "MIT",
@@ -1,4 +1,4 @@
1
- import { Type } from 'ts-gems';
1
+ import { RequiredSome, Type } from 'ts-gems';
2
2
  import * as vg from 'valgen';
3
3
  import { ResponsiveMap } from '../../helpers/index.js';
4
4
  import { OpraSchema } from '../../schema/index.js';
@@ -30,5 +30,7 @@ export declare class ComplexTypeClass extends DataType {
30
30
  isTypeOf(t: Type | Function): boolean;
31
31
  extendsFrom(t: string | Type | DataType): boolean;
32
32
  generateCodec(codec: 'decode' | 'encode', options?: DataType.GenerateCodecOptions): vg.Validator;
33
- protected _generateCodecSchema(codec: 'decode' | 'encode', options?: DataType.GenerateCodecOptions): vg.ObjectSchema;
33
+ generateCodecSchema(codec: 'decode' | 'encode', options?: DataType.GenerateCodecOptions): vg.ObjectSchema;
34
+ protected _generateCodecSchema(codec: 'decode' | 'encode', options?: RequiredSome<DataType.GenerateCodecOptions, 'pick' | 'omit'>): vg.ObjectSchema;
35
+ protected _buildOverwriteFieldsTree(obj: Record<string, DataType.OverrideFieldsConfig>): Record<string, DataType.OverrideFieldsConfig>;
34
36
  }
@@ -1,6 +1,5 @@
1
- import { RequiredSome, Type } from 'ts-gems';
1
+ import { RequiredSome, StrictOmit, Type } from 'ts-gems';
2
2
  import * as vg from 'valgen';
3
- import { ResponsiveMap } from '../../helpers/index.js';
4
3
  import { OpraSchema } from '../../schema/index.js';
5
4
  import type { ApiDocument } from '../api-document.js';
6
5
  import { nodeInspectCustom } from '../utils/inspect.util.js';
@@ -39,13 +38,19 @@ export declare namespace DataType {
39
38
  }
40
39
  interface OwnProperties {
41
40
  }
41
+ type GenerateCodecField = StrictOmit<ApiField.InitArguments, 'type' | 'name'> & {
42
+ type?: DataType | string;
43
+ };
44
+ type OverrideFieldsConfig = GenerateCodecField & {
45
+ overrideFields?: Record<string, OverrideFieldsConfig>;
46
+ };
42
47
  interface GenerateCodecOptions {
43
48
  caseSensitive?: boolean;
44
49
  pick?: string[];
45
50
  omit?: string[];
46
51
  partial?: boolean;
47
52
  operation?: 'read' | 'write';
48
- overwriteFields?: ResponsiveMap<ApiField.InitArguments>;
53
+ overwriteFields?: Record<string, OverrideFieldsConfig>;
49
54
  designType?: Type;
50
55
  }
51
56
  }
@@ -22,6 +22,7 @@ export declare class FieldClass {
22
22
  deprecated?: boolean | string;
23
23
  examples?: any[] | Record<string, any>;
24
24
  format?: string;
25
+ partialUpdate?: boolean;
25
26
  constructor(owner: ComplexType, init: ApiField.InitArguments);
26
27
  exportSchema(options?: {
27
28
  webSafe?: boolean;
@@ -1,6 +1,5 @@
1
1
  import { StrictOmit } from 'ts-gems';
2
2
  import * as vg from 'valgen';
3
- import { ResponsiveMap } from '../../helpers/index.js';
4
3
  import { OpraSchema } from '../../schema/index.js';
5
4
  import { DataType } from '../data-type/data-type.js';
6
5
  import { ApiField } from '../data-type/field.js';
@@ -18,8 +17,8 @@ export declare class CrudOperation extends Endpoint {
18
17
  decodeInput: vg.Validator;
19
18
  returnType: DataType;
20
19
  encodeReturning: vg.Validator;
21
- inputOverwriteFields?: ResponsiveMap<ApiField.InitArguments>;
22
- outputOverwriteFields?: ResponsiveMap<ApiField.InitArguments>;
20
+ inputOverwriteFields?: Record<string, ApiField.InitArguments>;
21
+ outputOverwriteFields?: Record<string, ApiField.InitArguments>;
23
22
  constructor(resource: Resource, name: string, init: CrudOperation.InitArguments);
24
23
  exportSchema(options?: {
25
24
  webSafe?: boolean;
@@ -27,6 +27,7 @@ export declare class ResponsiveMap<V> extends Map<string, V> {
27
27
  delete(key: string): boolean;
28
28
  sort(compareFn?: (a: string, b: string) => number): this;
29
29
  getProxy(handler?: ProxyHandler<Record<string, V>>): Record<string, V>;
30
+ toObject(): Record<string, V>;
30
31
  [Symbol.iterator](): IterableIterator<[string, V]>;
31
32
  protected _getOriginalKey(key: string): string;
32
33
  protected _getStoringKey(key: string): string;
@@ -10,7 +10,7 @@ export type Field = {
10
10
  */
11
11
  description?: string;
12
12
  /**
13
- * Defines if the field value is an array
13
+ * Indicates if the field value is an array
14
14
  */
15
15
  isArray?: boolean;
16
16
  /**
@@ -18,19 +18,19 @@ export type Field = {
18
18
  */
19
19
  default?: any;
20
20
  /**
21
- * Defines the fixed value of the field. The value of the field can not be any other value.
21
+ * Indicates the fixed value of the field. The value of the field can not be any other value.
22
22
  */
23
23
  fixed?: string | number | boolean;
24
24
  /**
25
- * Defines if field value required in create operation
25
+ * Indicates if field value required in create operation
26
26
  */
27
27
  required?: boolean;
28
28
  /**
29
- * Defines if the field is readonly
29
+ * Indicates if the field is readonly
30
30
  */
31
31
  readonly?: boolean;
32
32
  /**
33
- * Defines if the field is writeonly
33
+ * Indicates if the field is writeonly
34
34
  */
35
35
  writeonly?: boolean;
36
36
  /**
@@ -47,8 +47,12 @@ export type Field = {
47
47
  */
48
48
  examples?: any[] | Record<string, any>;
49
49
  /**
50
- * Defines if the field is deprecated and can be removed in the next
50
+ * Indicates if the field is deprecated and can be removed in the next
51
51
  */
52
52
  deprecated?: boolean | string;
53
53
  format?: string;
54
+ /**
55
+ * Indicates if partial update enabled for this field
56
+ */
57
+ partialUpdate?: boolean;
54
58
  };