@verdant-web/common 2.3.4 → 2.4.0-next.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/dist/esm/authz.d.ts +25 -0
- package/dist/esm/authz.js +54 -0
- package/dist/esm/authz.js.map +1 -0
- package/dist/esm/baseline.d.ts +1 -0
- package/dist/esm/baseline.js +3 -0
- package/dist/esm/baseline.js.map +1 -1
- package/dist/esm/files.d.ts +4 -0
- package/dist/esm/files.js +18 -0
- package/dist/esm/files.js.map +1 -1
- package/dist/esm/index.d.ts +2 -0
- package/dist/esm/index.js +2 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/indexes.js +1 -1
- package/dist/esm/indexes.js.map +1 -1
- package/dist/esm/indexes.test.js +1 -1
- package/dist/esm/indexes.test.js.map +1 -1
- package/dist/esm/migration.d.ts +4 -2
- package/dist/esm/migration.js.map +1 -1
- package/dist/esm/oids.d.ts +6 -24
- package/dist/esm/oids.js +18 -107
- package/dist/esm/oids.js.map +1 -1
- package/dist/esm/oids.test.js +1 -188
- package/dist/esm/oids.test.js.map +1 -1
- package/dist/esm/oidsLegacy.d.ts +18 -0
- package/dist/esm/oidsLegacy.js +72 -0
- package/dist/esm/oidsLegacy.js.map +1 -0
- package/dist/esm/oidsLegacy.test.d.ts +1 -0
- package/dist/esm/oidsLegacy.test.js +115 -0
- package/dist/esm/oidsLegacy.test.js.map +1 -0
- package/dist/esm/operation.d.ts +28 -4
- package/dist/esm/operation.js +70 -35
- package/dist/esm/operation.js.map +1 -1
- package/dist/esm/operation.test.js.map +1 -1
- package/dist/esm/presence.d.ts +0 -2
- package/dist/esm/schema/fields.js +1 -1
- package/dist/esm/schema/fields.js.map +1 -1
- package/dist/esm/schema/validation.js +14 -7
- package/dist/esm/schema/validation.js.map +1 -1
- package/package.json +1 -1
- package/src/authz.ts +67 -0
- package/src/baseline.ts +5 -4
- package/src/files.ts +25 -0
- package/src/index.ts +2 -0
- package/src/indexes.test.ts +1 -1
- package/src/indexes.ts +1 -1
- package/src/migration.ts +5 -1
- package/src/oids.test.ts +0 -241
- package/src/oids.ts +24 -122
- package/src/oidsLegacy.test.ts +147 -0
- package/src/oidsLegacy.ts +87 -0
- package/src/operation.test.ts +0 -1
- package/src/operation.ts +202 -103
- package/src/presence.ts +0 -2
- package/src/schema/fields.ts +1 -1
- package/src/schema/validation.ts +23 -14
package/src/operation.ts
CHANGED
|
@@ -9,12 +9,12 @@ import {
|
|
|
9
9
|
ensureOid,
|
|
10
10
|
getOid,
|
|
11
11
|
getOidRoot,
|
|
12
|
-
isOidKey,
|
|
13
12
|
maybeGetOid,
|
|
14
13
|
normalize,
|
|
15
14
|
ObjectIdentifier,
|
|
16
15
|
removeOid,
|
|
17
16
|
} from './oids.js';
|
|
17
|
+
import { isOidKey } from './oidsLegacy.js';
|
|
18
18
|
import { compareRefs, isRef } from './refs.js';
|
|
19
19
|
import { assert, cloneDeep, findLastIndex, isObject } from './utils.js';
|
|
20
20
|
|
|
@@ -156,6 +156,7 @@ export type Operation = {
|
|
|
156
156
|
oid: ObjectIdentifier;
|
|
157
157
|
timestamp: string;
|
|
158
158
|
data: OperationPatch;
|
|
159
|
+
authz?: string;
|
|
159
160
|
};
|
|
160
161
|
|
|
161
162
|
function isDiffableObject(val: any) {
|
|
@@ -174,7 +175,7 @@ export function diffToPatches<T extends { [key: string]: any } | any[]>(
|
|
|
174
175
|
getNow: () => string,
|
|
175
176
|
createSubId?: () => string,
|
|
176
177
|
patches: Operation[] = [],
|
|
177
|
-
options
|
|
178
|
+
options?: {
|
|
178
179
|
/**
|
|
179
180
|
* If an object is merged with another and the new one does not
|
|
180
181
|
* have an OID assigned, assume it is the same identity as previous
|
|
@@ -185,10 +186,16 @@ export function diffToPatches<T extends { [key: string]: any } | any[]>(
|
|
|
185
186
|
* If false, undefined properties will erase the previous value.
|
|
186
187
|
*/
|
|
187
188
|
defaultUndefined?: boolean;
|
|
188
|
-
|
|
189
|
+
/**
|
|
190
|
+
* Authorization to apply to all created operations
|
|
191
|
+
*/
|
|
192
|
+
authz?: string;
|
|
193
|
+
},
|
|
189
194
|
): Operation[] {
|
|
195
|
+
const authz = options?.authz;
|
|
190
196
|
const oid = getOid(from);
|
|
191
197
|
|
|
198
|
+
// FIXME: allocating this function inline seems wasteful.
|
|
192
199
|
function diffItems(
|
|
193
200
|
key: string | number,
|
|
194
201
|
value: any,
|
|
@@ -200,25 +207,35 @@ export function diffToPatches<T extends { [key: string]: any } | any[]>(
|
|
|
200
207
|
// do not need to recurse, of course
|
|
201
208
|
if (!compareNonDiffable(value, oldValue)) {
|
|
202
209
|
if (isList) {
|
|
203
|
-
patches.push(
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
210
|
+
patches.push(
|
|
211
|
+
addAuthzToOp(
|
|
212
|
+
{
|
|
213
|
+
oid,
|
|
214
|
+
timestamp: getNow(),
|
|
215
|
+
data: {
|
|
216
|
+
op: 'list-set',
|
|
217
|
+
index: key as number,
|
|
218
|
+
value,
|
|
219
|
+
},
|
|
220
|
+
},
|
|
221
|
+
authz,
|
|
222
|
+
),
|
|
223
|
+
);
|
|
212
224
|
} else {
|
|
213
|
-
patches.push(
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
225
|
+
patches.push(
|
|
226
|
+
addAuthzToOp(
|
|
227
|
+
{
|
|
228
|
+
oid,
|
|
229
|
+
timestamp: getNow(),
|
|
230
|
+
data: {
|
|
231
|
+
op: 'set',
|
|
232
|
+
name: key,
|
|
233
|
+
value,
|
|
234
|
+
},
|
|
235
|
+
},
|
|
236
|
+
authz,
|
|
237
|
+
),
|
|
238
|
+
);
|
|
222
239
|
}
|
|
223
240
|
}
|
|
224
241
|
} else {
|
|
@@ -231,7 +248,7 @@ export function diffToPatches<T extends { [key: string]: any } | any[]>(
|
|
|
231
248
|
value = cloneDeep(value, false);
|
|
232
249
|
valueOid = createSubOid(oid, createSubId);
|
|
233
250
|
assignOid(value, valueOid);
|
|
234
|
-
} else if (!options
|
|
251
|
+
} else if (!options?.mergeUnknownObjects) {
|
|
235
252
|
valueOid = ensureOid(value, oid, createSubId);
|
|
236
253
|
} else {
|
|
237
254
|
// if merge unknown objects is requested, we copy the previous value's oid
|
|
@@ -258,24 +275,34 @@ export function diffToPatches<T extends { [key: string]: any } | any[]>(
|
|
|
258
275
|
// we add the whole new object and also update the reference on this
|
|
259
276
|
// key of the parent to point to the new object
|
|
260
277
|
initialToPatches(value, valueOid, getNow, createSubId, patches);
|
|
261
|
-
patches.push(
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
278
|
+
patches.push(
|
|
279
|
+
addAuthzToOp(
|
|
280
|
+
{
|
|
281
|
+
oid,
|
|
282
|
+
timestamp: getNow(),
|
|
283
|
+
data: {
|
|
284
|
+
op: 'set',
|
|
285
|
+
name: key,
|
|
286
|
+
value: createRef(valueOid),
|
|
287
|
+
},
|
|
288
|
+
},
|
|
289
|
+
authz,
|
|
290
|
+
),
|
|
291
|
+
);
|
|
270
292
|
// if there was an old value, we need to delete it altogether.
|
|
271
293
|
if (oldValueOid !== undefined) {
|
|
272
|
-
patches.push(
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
294
|
+
patches.push(
|
|
295
|
+
addAuthzToOp(
|
|
296
|
+
{
|
|
297
|
+
oid: oldValueOid,
|
|
298
|
+
timestamp: getNow(),
|
|
299
|
+
data: {
|
|
300
|
+
op: 'delete',
|
|
301
|
+
},
|
|
302
|
+
},
|
|
303
|
+
authz,
|
|
304
|
+
),
|
|
305
|
+
);
|
|
279
306
|
}
|
|
280
307
|
} else {
|
|
281
308
|
// third case: OIDs are the same, meaning the identity is the same,
|
|
@@ -302,32 +329,42 @@ export function diffToPatches<T extends { [key: string]: any } | any[]>(
|
|
|
302
329
|
const value = from[i];
|
|
303
330
|
const valueOid = maybeGetOid(value);
|
|
304
331
|
if (valueOid) {
|
|
305
|
-
patches.push(
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
332
|
+
patches.push(
|
|
333
|
+
addAuthzToOp(
|
|
334
|
+
{
|
|
335
|
+
oid: valueOid,
|
|
336
|
+
timestamp: getNow(),
|
|
337
|
+
data: {
|
|
338
|
+
op: 'delete',
|
|
339
|
+
},
|
|
340
|
+
},
|
|
341
|
+
authz,
|
|
342
|
+
),
|
|
343
|
+
);
|
|
312
344
|
}
|
|
313
345
|
}
|
|
314
346
|
// push the list-delete for the deleted items
|
|
315
|
-
patches.push(
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
347
|
+
patches.push(
|
|
348
|
+
addAuthzToOp(
|
|
349
|
+
{
|
|
350
|
+
oid,
|
|
351
|
+
timestamp: getNow(),
|
|
352
|
+
data: {
|
|
353
|
+
op: 'list-delete',
|
|
354
|
+
index: to.length,
|
|
355
|
+
count: deletedItemsAtEnd,
|
|
356
|
+
},
|
|
357
|
+
},
|
|
358
|
+
authz,
|
|
359
|
+
),
|
|
360
|
+
);
|
|
324
361
|
}
|
|
325
362
|
} else if (Array.isArray(from) || Array.isArray(to)) {
|
|
326
363
|
throw new Error('Cannot diff an array with an object');
|
|
327
364
|
} else if (isDiffableObject(from) && isDiffableObject(to)) {
|
|
328
365
|
const oldKeys = new Set(Object.keys(from));
|
|
329
366
|
for (const [key, value] of Object.entries(to)) {
|
|
330
|
-
if (value === undefined && options
|
|
367
|
+
if (value === undefined && options?.defaultUndefined) continue;
|
|
331
368
|
|
|
332
369
|
oldKeys.delete(key);
|
|
333
370
|
|
|
@@ -339,18 +376,23 @@ export function diffToPatches<T extends { [key: string]: any } | any[]>(
|
|
|
339
376
|
}
|
|
340
377
|
|
|
341
378
|
// this set now only contains keys which were not in the new object
|
|
342
|
-
if (!options
|
|
379
|
+
if (!options?.defaultUndefined) {
|
|
343
380
|
for (const key of oldKeys) {
|
|
344
381
|
if (isOidKey(key)) continue;
|
|
345
382
|
// push the delete for the property
|
|
346
|
-
patches.push(
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
383
|
+
patches.push(
|
|
384
|
+
addAuthzToOp(
|
|
385
|
+
{
|
|
386
|
+
oid,
|
|
387
|
+
timestamp: getNow(),
|
|
388
|
+
data: {
|
|
389
|
+
op: 'remove',
|
|
390
|
+
name: key,
|
|
391
|
+
},
|
|
392
|
+
},
|
|
393
|
+
authz,
|
|
394
|
+
),
|
|
395
|
+
);
|
|
354
396
|
}
|
|
355
397
|
}
|
|
356
398
|
}
|
|
@@ -363,8 +405,10 @@ export function shallowDiffToPatches(
|
|
|
363
405
|
to: any,
|
|
364
406
|
getNow: () => string,
|
|
365
407
|
patches: Operation[] = [],
|
|
408
|
+
options?: { authz?: string },
|
|
366
409
|
) {
|
|
367
410
|
const oid = getOid(from);
|
|
411
|
+
const authz = options?.authz;
|
|
368
412
|
|
|
369
413
|
function diffItems(
|
|
370
414
|
key: string | number,
|
|
@@ -377,25 +421,35 @@ export function shallowDiffToPatches(
|
|
|
377
421
|
// do not need to recurse, of course
|
|
378
422
|
if (!compareNonDiffable(value, oldValue)) {
|
|
379
423
|
if (isList) {
|
|
380
|
-
patches.push(
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
424
|
+
patches.push(
|
|
425
|
+
addAuthzToOp(
|
|
426
|
+
{
|
|
427
|
+
oid,
|
|
428
|
+
timestamp: getNow(),
|
|
429
|
+
data: {
|
|
430
|
+
op: 'list-set',
|
|
431
|
+
index: key as number,
|
|
432
|
+
value,
|
|
433
|
+
},
|
|
434
|
+
},
|
|
435
|
+
authz,
|
|
436
|
+
),
|
|
437
|
+
);
|
|
389
438
|
} else {
|
|
390
|
-
patches.push(
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
439
|
+
patches.push(
|
|
440
|
+
addAuthzToOp(
|
|
441
|
+
{
|
|
442
|
+
oid,
|
|
443
|
+
timestamp: getNow(),
|
|
444
|
+
data: {
|
|
445
|
+
op: 'set',
|
|
446
|
+
name: key,
|
|
447
|
+
value,
|
|
448
|
+
},
|
|
449
|
+
},
|
|
450
|
+
authz,
|
|
451
|
+
),
|
|
452
|
+
);
|
|
399
453
|
}
|
|
400
454
|
}
|
|
401
455
|
} else {
|
|
@@ -418,15 +472,20 @@ export function shallowDiffToPatches(
|
|
|
418
472
|
const deletedItemsAtEnd = from.length - to.length;
|
|
419
473
|
if (deletedItemsAtEnd > 0) {
|
|
420
474
|
// push the list-delete for the deleted items
|
|
421
|
-
patches.push(
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
475
|
+
patches.push(
|
|
476
|
+
addAuthzToOp(
|
|
477
|
+
{
|
|
478
|
+
oid,
|
|
479
|
+
timestamp: getNow(),
|
|
480
|
+
data: {
|
|
481
|
+
op: 'list-delete',
|
|
482
|
+
index: to.length,
|
|
483
|
+
count: deletedItemsAtEnd,
|
|
484
|
+
},
|
|
485
|
+
},
|
|
486
|
+
authz,
|
|
487
|
+
),
|
|
488
|
+
);
|
|
430
489
|
}
|
|
431
490
|
} else if (Array.isArray(from) || Array.isArray(to)) {
|
|
432
491
|
throw new Error('Cannot diff an array with an object');
|
|
@@ -446,14 +505,19 @@ export function shallowDiffToPatches(
|
|
|
446
505
|
for (const key of oldKeys) {
|
|
447
506
|
if (isOidKey(key)) continue;
|
|
448
507
|
// push the delete for the property
|
|
449
|
-
patches.push(
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
508
|
+
patches.push(
|
|
509
|
+
addAuthzToOp(
|
|
510
|
+
{
|
|
511
|
+
oid,
|
|
512
|
+
timestamp: getNow(),
|
|
513
|
+
data: {
|
|
514
|
+
op: 'remove',
|
|
515
|
+
name: key,
|
|
516
|
+
},
|
|
517
|
+
},
|
|
518
|
+
authz,
|
|
519
|
+
),
|
|
520
|
+
);
|
|
457
521
|
}
|
|
458
522
|
}
|
|
459
523
|
|
|
@@ -470,20 +534,22 @@ export function initialToPatches(
|
|
|
470
534
|
getNow: () => string,
|
|
471
535
|
createSubId?: () => string,
|
|
472
536
|
patches: Operation[] = [],
|
|
537
|
+
options?: { authz?: string },
|
|
473
538
|
) {
|
|
474
539
|
assignOid(initial, rootOid);
|
|
475
540
|
assignOidsToAllSubObjects(initial, createSubId);
|
|
476
541
|
const normalized = normalize(initial);
|
|
477
542
|
for (const key of normalized.keys()) {
|
|
478
543
|
const value = normalized.get(key);
|
|
479
|
-
|
|
544
|
+
const op: Operation = {
|
|
480
545
|
oid: key,
|
|
481
546
|
timestamp: getNow(),
|
|
482
547
|
data: {
|
|
483
548
|
op: 'initialize',
|
|
484
549
|
value: removeOid(value),
|
|
485
550
|
},
|
|
486
|
-
}
|
|
551
|
+
};
|
|
552
|
+
patches.push(addAuthzToOp(op, options?.authz));
|
|
487
553
|
}
|
|
488
554
|
return patches;
|
|
489
555
|
}
|
|
@@ -493,18 +559,29 @@ export function shallowInitialToPatches(
|
|
|
493
559
|
rootOid: ObjectIdentifier,
|
|
494
560
|
getNow: () => string,
|
|
495
561
|
patches: Operation[] = [],
|
|
562
|
+
options?: { authz?: string },
|
|
496
563
|
) {
|
|
497
|
-
|
|
564
|
+
const op: Operation = {
|
|
498
565
|
oid: rootOid,
|
|
499
566
|
timestamp: getNow(),
|
|
500
567
|
data: {
|
|
501
568
|
op: 'initialize',
|
|
502
569
|
value: initial,
|
|
503
570
|
},
|
|
504
|
-
}
|
|
571
|
+
};
|
|
572
|
+
patches.push(addAuthzToOp(op, options?.authz));
|
|
505
573
|
return patches;
|
|
506
574
|
}
|
|
507
575
|
|
|
576
|
+
// saves a bit of network traffic by not attaching authz
|
|
577
|
+
// key at all if not present
|
|
578
|
+
function addAuthzToOp(op: Operation, authz?: string) {
|
|
579
|
+
if (authz) {
|
|
580
|
+
op.authz = authz;
|
|
581
|
+
}
|
|
582
|
+
return op;
|
|
583
|
+
}
|
|
584
|
+
|
|
508
585
|
export function groupPatchesByOid(patches: Operation[]) {
|
|
509
586
|
const grouped: Record<ObjectIdentifier, Operation[]> = {};
|
|
510
587
|
for (const patch of patches) {
|
|
@@ -719,10 +796,18 @@ export function applyOperations<T extends NormalizedObject>(
|
|
|
719
796
|
base: T | undefined,
|
|
720
797
|
operations: Operation[],
|
|
721
798
|
deletedRefs?: (ObjectRef | FileRef)[],
|
|
799
|
+
/**
|
|
800
|
+
* Provide and it will be assigned any authz info assigned
|
|
801
|
+
* in applied operations
|
|
802
|
+
*/
|
|
803
|
+
authzRef?: { authz?: string },
|
|
722
804
|
): T | undefined {
|
|
723
805
|
let cur = base as T | undefined;
|
|
724
806
|
for (const op of operations) {
|
|
725
807
|
cur = applyPatch(cur, op.data, deletedRefs);
|
|
808
|
+
if (authzRef && op.data.op === 'initialize' && op.authz) {
|
|
809
|
+
authzRef.authz = op.authz;
|
|
810
|
+
}
|
|
726
811
|
}
|
|
727
812
|
return cur;
|
|
728
813
|
}
|
|
@@ -841,3 +926,17 @@ export function isSuperseded(
|
|
|
841
926
|
|
|
842
927
|
return false;
|
|
843
928
|
}
|
|
929
|
+
|
|
930
|
+
/**
|
|
931
|
+
* Allocates a copy with only valid keys for transmitting over
|
|
932
|
+
* the protocol. TODO: make this unnecessary or evaluate if it's
|
|
933
|
+
* worth it to do.
|
|
934
|
+
*/
|
|
935
|
+
export function pickValidOperationKeys(operation: Operation): Operation {
|
|
936
|
+
return {
|
|
937
|
+
oid: operation.oid,
|
|
938
|
+
timestamp: operation.timestamp,
|
|
939
|
+
data: operation.data,
|
|
940
|
+
authz: operation.authz,
|
|
941
|
+
};
|
|
942
|
+
}
|
package/src/presence.ts
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
export interface UserInfo<Profile, Presence> {
|
|
2
2
|
/**
|
|
3
|
-
* @deprecated - include the ID in your Profile data instead.
|
|
4
|
-
*
|
|
5
3
|
* This is the ID representing the user who is utilizing a
|
|
6
4
|
* replica client to connect to the storage network.
|
|
7
5
|
* One user may have multiple replica clients active at once,
|
package/src/schema/fields.ts
CHANGED
package/src/schema/validation.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { isFile, isFileData } from '../files.js';
|
|
2
|
+
import { OID_KEY } from '../oidsLegacy.js';
|
|
2
3
|
import { isObject } from '../utils.js';
|
|
3
4
|
import { getFieldDefault, hasDefault, isNullable } from './fields.js';
|
|
4
5
|
import { StorageFieldSchema, StorageFieldsSchema } from './types.js';
|
|
@@ -71,9 +72,9 @@ export function validateEntityField({
|
|
|
71
72
|
return {
|
|
72
73
|
type: 'invalid-type',
|
|
73
74
|
fieldPath,
|
|
74
|
-
message: `Expected object${
|
|
75
|
-
field.nullable ? '
|
|
76
|
-
}
|
|
75
|
+
message: `Expected object ${
|
|
76
|
+
field.nullable ? 'or null ' : ''
|
|
77
|
+
}for field ${formatField(fieldPath)}, got ${value}`,
|
|
77
78
|
};
|
|
78
79
|
}
|
|
79
80
|
for (const [key, subField] of Object.entries(
|
|
@@ -108,9 +109,9 @@ export function validateEntityField({
|
|
|
108
109
|
return {
|
|
109
110
|
type: 'invalid-value',
|
|
110
111
|
fieldPath,
|
|
111
|
-
message: `Expected array${
|
|
112
|
-
field.nullable ? '
|
|
113
|
-
}
|
|
112
|
+
message: `Expected array ${
|
|
113
|
+
field.nullable ? 'or null ' : ''
|
|
114
|
+
}for field ${formatField(fieldPath)}, got ${value}`,
|
|
114
115
|
};
|
|
115
116
|
}
|
|
116
117
|
for (const item of value) {
|
|
@@ -145,8 +146,8 @@ export function validateEntityField({
|
|
|
145
146
|
type: 'invalid-type',
|
|
146
147
|
fieldPath,
|
|
147
148
|
message: `Expected string ${
|
|
148
|
-
field.nullable ? '
|
|
149
|
-
}
|
|
149
|
+
field.nullable ? 'or null ' : ''
|
|
150
|
+
}for field ${formatField(fieldPath)}, got ${value}`,
|
|
150
151
|
};
|
|
151
152
|
}
|
|
152
153
|
if (field.options && !field.options.includes(value)) {
|
|
@@ -164,8 +165,8 @@ export function validateEntityField({
|
|
|
164
165
|
type: 'invalid-type',
|
|
165
166
|
fieldPath,
|
|
166
167
|
message: `Expected boolean ${
|
|
167
|
-
field.nullable ? '
|
|
168
|
-
}
|
|
168
|
+
field.nullable ? 'or null ' : ''
|
|
169
|
+
}for field ${formatField(fieldPath)}, got ${value}`,
|
|
169
170
|
};
|
|
170
171
|
}
|
|
171
172
|
} else if (field.type === 'number') {
|
|
@@ -174,12 +175,20 @@ export function validateEntityField({
|
|
|
174
175
|
type: 'invalid-type',
|
|
175
176
|
fieldPath,
|
|
176
177
|
message: `Expected number ${
|
|
177
|
-
field.nullable ? '
|
|
178
|
-
}
|
|
178
|
+
field.nullable ? 'or null ' : ''
|
|
179
|
+
}for field ${formatField(fieldPath)}, got ${value}`,
|
|
179
180
|
};
|
|
180
181
|
}
|
|
181
182
|
} else if (field.type === 'file') {
|
|
182
|
-
|
|
183
|
+
if (!isFile(value) && !isFileData(value)) {
|
|
184
|
+
return {
|
|
185
|
+
type: 'invalid-type',
|
|
186
|
+
fieldPath,
|
|
187
|
+
message: `Expected file ${
|
|
188
|
+
field.nullable ? 'or null ' : ''
|
|
189
|
+
}for field ${formatField(fieldPath)}, got ${value}`,
|
|
190
|
+
};
|
|
191
|
+
}
|
|
183
192
|
}
|
|
184
193
|
}
|
|
185
194
|
|