rads-db 3.0.24 → 3.0.26
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/index.cjs +72 -59
- package/dist/index.d.ts +4 -1
- package/dist/index.mjs +72 -60
- package/features/eventSourcing.cjs +54 -19
- package/features/eventSourcing.mjs +39 -21
- package/integrations/nuxtModule.cjs +3 -20
- package/integrations/nuxtModule.d.ts +2 -0
- package/integrations/nuxtModule.mjs +1 -16
- package/package.json +2 -3
package/dist/index.cjs
CHANGED
|
@@ -543,12 +543,12 @@ async function fillDenormFieldsBeforePut(computedContext, docUpdates, ctx) {
|
|
|
543
543
|
await Promise.all(promises);
|
|
544
544
|
}
|
|
545
545
|
|
|
546
|
-
function cleanUndefinedAndNull(obj) {
|
|
546
|
+
function cleanUndefinedAndNull(obj, isChange = false) {
|
|
547
547
|
for (const key in obj) {
|
|
548
|
-
if (obj[key] == null)
|
|
548
|
+
if (obj[key] == null && !isChange)
|
|
549
549
|
delete obj[key];
|
|
550
550
|
if (___default.isPlainObject(obj[key]))
|
|
551
|
-
cleanUndefinedAndNull(obj[key]);
|
|
551
|
+
cleanUndefinedAndNull(obj[key], key === "change");
|
|
552
552
|
}
|
|
553
553
|
}
|
|
554
554
|
|
|
@@ -607,7 +607,6 @@ function mustUseDeepDiff(value, oldValue) {
|
|
|
607
607
|
|
|
608
608
|
function getRadsDbMethods(key, computedContext, driverInstance) {
|
|
609
609
|
const { schema, options, validators } = computedContext;
|
|
610
|
-
const mustCleanNulls = driverInstance.driverName !== "restApi";
|
|
611
610
|
const { precomputedFields } = schema[key];
|
|
612
611
|
async function getMany(args, ctx) {
|
|
613
612
|
args = { ...args, where: { ...args?.where } };
|
|
@@ -639,7 +638,7 @@ function getRadsDbMethods(key, computedContext, driverInstance) {
|
|
|
639
638
|
const docArgsToSave = docs.map((doc) => {
|
|
640
639
|
const oldDoc = oldDocsById[doc.id];
|
|
641
640
|
doc = merge(oldDoc, doc);
|
|
642
|
-
if (
|
|
641
|
+
if (!options.keepNulls)
|
|
643
642
|
cleanUndefinedAndNull(doc);
|
|
644
643
|
return { oldDoc, doc };
|
|
645
644
|
});
|
|
@@ -660,6 +659,59 @@ function getRadsDbMethods(key, computedContext, driverInstance) {
|
|
|
660
659
|
await afterPut(docArgsToSave, ctx, computedContext);
|
|
661
660
|
return docsToSave;
|
|
662
661
|
}
|
|
662
|
+
async function verifyMany(args, ctx) {
|
|
663
|
+
if (driverInstance.verifyMany) {
|
|
664
|
+
return driverInstance.verifyMany(args, ctx);
|
|
665
|
+
}
|
|
666
|
+
ctx = { ...options.context, ...ctx };
|
|
667
|
+
if (args?.dryRun) {
|
|
668
|
+
ctx._logs = ctx._logs || [];
|
|
669
|
+
ctx.dryRun = true;
|
|
670
|
+
}
|
|
671
|
+
const { _logs } = ctx;
|
|
672
|
+
const { nodes, cursor } = await driverInstance.getMany(args, ctx);
|
|
673
|
+
let correctCount = 0;
|
|
674
|
+
let incorrectCount = 0;
|
|
675
|
+
const incorrectDocs = [];
|
|
676
|
+
const oldDocs = nodes;
|
|
677
|
+
const docArgsToSave = oldDocs.map((oldDoc) => {
|
|
678
|
+
const doc = merge(oldDoc, {});
|
|
679
|
+
if (args?.recompute) {
|
|
680
|
+
for (const p of args.recompute) {
|
|
681
|
+
delete doc[p];
|
|
682
|
+
}
|
|
683
|
+
}
|
|
684
|
+
if (!options.keepNulls)
|
|
685
|
+
cleanUndefinedAndNull(doc);
|
|
686
|
+
return { oldDoc, doc };
|
|
687
|
+
});
|
|
688
|
+
await handlePrecomputed(computedContext, docArgsToSave, ctx);
|
|
689
|
+
const beforePutResults = await handleEffectsBeforePut(computedContext, docArgsToSave, ctx);
|
|
690
|
+
await beforePut(docArgsToSave, ctx, computedContext);
|
|
691
|
+
for (const d of docArgsToSave) {
|
|
692
|
+
const validatedDoc = validators[key](d.doc);
|
|
693
|
+
for (const f of precomputedFields || []) {
|
|
694
|
+
___default.set(validatedDoc, f, ___default.get(d.doc, f));
|
|
695
|
+
}
|
|
696
|
+
d.doc = validatedDoc;
|
|
697
|
+
}
|
|
698
|
+
await fillDenormFieldsBeforePut(computedContext, docArgsToSave, ctx);
|
|
699
|
+
for (const { oldDoc, doc } of docArgsToSave) {
|
|
700
|
+
const d = diff(doc, oldDoc);
|
|
701
|
+
if (___default.isEmpty(d))
|
|
702
|
+
correctCount++;
|
|
703
|
+
else {
|
|
704
|
+
incorrectCount++;
|
|
705
|
+
const objToAdd = { id: doc.id, diff: d };
|
|
706
|
+
incorrectDocs.push(objToAdd);
|
|
707
|
+
}
|
|
708
|
+
}
|
|
709
|
+
const docsToSave = docArgsToSave.map((x) => x.doc);
|
|
710
|
+
await driverInstance.putMany(docsToSave, ctx);
|
|
711
|
+
await handleEffectsAfterPut(computedContext, docArgsToSave, beforePutResults, ctx);
|
|
712
|
+
await afterPut(docArgsToSave, ctx, computedContext);
|
|
713
|
+
return { _logs, cursor, correctCount, incorrectCount, incorrectDocs };
|
|
714
|
+
}
|
|
663
715
|
const result = {
|
|
664
716
|
// No deleteMany / deleteAll on purpose - it's a dangerous operation, let them use driver instead
|
|
665
717
|
createObject() {
|
|
@@ -667,6 +719,7 @@ function getRadsDbMethods(key, computedContext, driverInstance) {
|
|
|
667
719
|
},
|
|
668
720
|
getMany,
|
|
669
721
|
putMany,
|
|
722
|
+
verifyMany,
|
|
670
723
|
driver: driverInstance,
|
|
671
724
|
getAgg: async (args, ctx) => {
|
|
672
725
|
args = { ...args, where: { ...args?.where } };
|
|
@@ -704,6 +757,17 @@ function getRadsDbMethods(key, computedContext, driverInstance) {
|
|
|
704
757
|
await afterGet(result2, args, ctx, computedContext);
|
|
705
758
|
return result2;
|
|
706
759
|
},
|
|
760
|
+
verifyAll: async (args, ctx) => {
|
|
761
|
+
let cursor = args?.cursor;
|
|
762
|
+
const result2 = { correctCount: 0, incorrectCount: 0 };
|
|
763
|
+
do {
|
|
764
|
+
const response = await verifyMany({ ...args, cursor }, ctx);
|
|
765
|
+
cursor = response.cursor;
|
|
766
|
+
result2.correctCount += response.correctCount;
|
|
767
|
+
result2.incorrectCount += response.incorrectCount;
|
|
768
|
+
} while (cursor);
|
|
769
|
+
return result2;
|
|
770
|
+
},
|
|
707
771
|
put: async (doc, ctx) => {
|
|
708
772
|
const precomputed = schema[key].decorators.precomputed;
|
|
709
773
|
if (precomputed && ctx?.skipPrecomputedCheckFor !== key) {
|
|
@@ -717,7 +781,7 @@ function getRadsDbMethods(key, computedContext, driverInstance) {
|
|
|
717
781
|
const oldDoc = await driverInstance.get({ where: { id: doc.id } }, ctx);
|
|
718
782
|
if (oldDoc)
|
|
719
783
|
doc = merge(oldDoc, doc);
|
|
720
|
-
if (
|
|
784
|
+
if (!options.keepNulls)
|
|
721
785
|
cleanUndefinedAndNull(doc);
|
|
722
786
|
const docArgsToSave = [{ doc, oldDoc }];
|
|
723
787
|
await handlePrecomputed(computedContext, docArgsToSave, ctx);
|
|
@@ -736,59 +800,6 @@ function getRadsDbMethods(key, computedContext, driverInstance) {
|
|
|
736
800
|
await handleEffectsAfterPut(computedContext, docArgsToSave, beforePutResults, ctx);
|
|
737
801
|
await afterPut(docArgsToSave, ctx, computedContext);
|
|
738
802
|
return doc;
|
|
739
|
-
},
|
|
740
|
-
async verifyMany(args, ctx) {
|
|
741
|
-
if (driverInstance.verifyMany) {
|
|
742
|
-
return driverInstance.verifyMany(args, ctx);
|
|
743
|
-
}
|
|
744
|
-
ctx = { ...options.context, ...ctx };
|
|
745
|
-
if (args?.dryRun) {
|
|
746
|
-
ctx._logs = ctx._logs || [];
|
|
747
|
-
ctx.dryRun = true;
|
|
748
|
-
}
|
|
749
|
-
const { _logs } = ctx;
|
|
750
|
-
const { nodes, cursor } = await driverInstance.getMany(args, ctx);
|
|
751
|
-
let correctCount = 0;
|
|
752
|
-
let incorrectCount = 0;
|
|
753
|
-
const incorrectDocs = [];
|
|
754
|
-
const oldDocs = nodes;
|
|
755
|
-
const docArgsToSave = oldDocs.map((oldDoc) => {
|
|
756
|
-
const doc = merge(oldDoc, {});
|
|
757
|
-
if (args?.recompute) {
|
|
758
|
-
for (const p of args.recompute) {
|
|
759
|
-
delete doc[p];
|
|
760
|
-
}
|
|
761
|
-
}
|
|
762
|
-
if (mustCleanNulls)
|
|
763
|
-
cleanUndefinedAndNull(doc);
|
|
764
|
-
return { oldDoc, doc };
|
|
765
|
-
});
|
|
766
|
-
await handlePrecomputed(computedContext, docArgsToSave, ctx);
|
|
767
|
-
const beforePutResults = await handleEffectsBeforePut(computedContext, docArgsToSave, ctx);
|
|
768
|
-
await beforePut(docArgsToSave, ctx, computedContext);
|
|
769
|
-
for (const d of docArgsToSave) {
|
|
770
|
-
const validatedDoc = validators[key](d.doc);
|
|
771
|
-
for (const f of precomputedFields || []) {
|
|
772
|
-
___default.set(validatedDoc, f, ___default.get(d.doc, f));
|
|
773
|
-
}
|
|
774
|
-
d.doc = validatedDoc;
|
|
775
|
-
}
|
|
776
|
-
await fillDenormFieldsBeforePut(computedContext, docArgsToSave, ctx);
|
|
777
|
-
for (const { oldDoc, doc } of docArgsToSave) {
|
|
778
|
-
const d = diff(doc, oldDoc);
|
|
779
|
-
if (___default.isEmpty(d))
|
|
780
|
-
correctCount++;
|
|
781
|
-
else {
|
|
782
|
-
incorrectCount++;
|
|
783
|
-
const objToAdd = { id: doc.id, diff: d };
|
|
784
|
-
incorrectDocs.push(objToAdd);
|
|
785
|
-
}
|
|
786
|
-
}
|
|
787
|
-
const docsToSave = docArgsToSave.map((x) => x.doc);
|
|
788
|
-
await driverInstance.putMany(docsToSave, ctx);
|
|
789
|
-
await handleEffectsAfterPut(computedContext, docArgsToSave, beforePutResults, ctx);
|
|
790
|
-
await afterPut(docArgsToSave, ctx, computedContext);
|
|
791
|
-
return { _logs, cursor, correctCount, incorrectCount, incorrectDocs };
|
|
792
803
|
}
|
|
793
804
|
};
|
|
794
805
|
for (const f of options.features) {
|
|
@@ -1138,6 +1149,7 @@ function createRadsDbClient(args) {
|
|
|
1138
1149
|
...args,
|
|
1139
1150
|
noComputed: true,
|
|
1140
1151
|
noCustomDrivers: true,
|
|
1152
|
+
keepNulls: true,
|
|
1141
1153
|
driver: restApi(args?.driver)
|
|
1142
1154
|
};
|
|
1143
1155
|
const s = radsDbArgs.schema || _radsDb.schema;
|
|
@@ -1145,6 +1157,7 @@ function createRadsDbClient(args) {
|
|
|
1145
1157
|
return generateMethods(s, validators, radsDbArgs);
|
|
1146
1158
|
}
|
|
1147
1159
|
|
|
1160
|
+
exports.cleanUndefinedAndNull = cleanUndefinedAndNull;
|
|
1148
1161
|
exports.computed = computed;
|
|
1149
1162
|
exports.createRadsDb = createRadsDb;
|
|
1150
1163
|
exports.createRadsDbClient = createRadsDbClient;
|
package/dist/index.d.ts
CHANGED
|
@@ -186,6 +186,7 @@ interface CreateRadsDbArgs {
|
|
|
186
186
|
beforeGet?: (args: GetArgsAny, ctx: RadsRequestContext, context: ComputedContext) => MaybePromise<void>;
|
|
187
187
|
context?: Record<string, any> & Omit<RadsRequestContext, 'dryRun' | 'silent'>;
|
|
188
188
|
features?: RadsFeature[];
|
|
189
|
+
keepNulls?: boolean;
|
|
189
190
|
}
|
|
190
191
|
type CreateRadsDbArgsNormalized = RequiredFields<CreateRadsDbArgs, 'computed' | 'features'> & {
|
|
191
192
|
driver: CreateRadsArgsDrivers;
|
|
@@ -393,6 +394,8 @@ declare function merge<T extends Record<string, any>>(target: T, source: any): T
|
|
|
393
394
|
|
|
394
395
|
declare function diff(object: any, base: any, includeDenormFields?: boolean): any;
|
|
395
396
|
|
|
397
|
+
declare function cleanUndefinedAndNull(obj: Record<string, any>, isChange?: boolean): void;
|
|
398
|
+
|
|
396
399
|
/**
|
|
397
400
|
* Creates instance of rads db - object that provides access to all entities.
|
|
398
401
|
* Intended to be used on the backend. On the client you may want to opt for "createRadsDbClient" instead.
|
|
@@ -405,4 +408,4 @@ declare function createRadsDb(args?: CreateRadsDbArgs): RadsDb;
|
|
|
405
408
|
*/
|
|
406
409
|
declare function createRadsDbClient(args?: CreateRadsDbClientArgs): RadsDb;
|
|
407
410
|
|
|
408
|
-
export { Change, ComputedContext, ComputedContextGlobal, ComputedDecoratorArgs, CreateRadsArgsDrivers, CreateRadsDbArgs, CreateRadsDbArgsNormalized, CreateRadsDbClientArgs, DeepPartial, Driver, DriverConstructor, EntityDecoratorArgs, EntityMethods, EnumDefinition, FieldDecoratorArgs, FieldDefinition, FileSystemNode, FileUploadArgs, FileUploadDriver, FileUploadResult, GenerateClientNormalizedOptions, GenerateClientOptions, GetAggArgs, GetAggArgsAgg, GetAggArgsAny, GetAggResponse, GetArgs, GetArgsAny, GetArgsInclude, GetManyArgs, GetManyArgsAny, GetManyResponse, GetResponse, GetResponseInclude, GetResponseIncludeSelect, GetResponseNoInclude, GetRestRoutesArgs, GetRestRoutesOptions, GetRestRoutesResponse, MinimalDriver, PutArgs, PutEffect, RadsFeature, RadsRequestContext, RadsUiSlotDefinition, RadsUiSlotName, RadsVitePluginOptions, Relation, RequiredFields, RestDriverOptions, RestFileUploadDriverOptions, Schema, SchemaValidators, TypeDefinition, UiDecoratorArgs, UiFieldDecoratorArgs, ValidateEntityDecoratorArgs, ValidateFieldDecoratorArgs, ValidateStringDecoratorArgs, VerifyManyArgs, VerifyManyArgsAny, VerifyManyResponse, computed, createRadsDb, createRadsDbClient, diff, entity, field, getDriverInstance, handlePrecomputed, merge, precomputed, ui, validate };
|
|
411
|
+
export { Change, ComputedContext, ComputedContextGlobal, ComputedDecoratorArgs, CreateRadsArgsDrivers, CreateRadsDbArgs, CreateRadsDbArgsNormalized, CreateRadsDbClientArgs, DeepPartial, Driver, DriverConstructor, EntityDecoratorArgs, EntityMethods, EnumDefinition, FieldDecoratorArgs, FieldDefinition, FileSystemNode, FileUploadArgs, FileUploadDriver, FileUploadResult, GenerateClientNormalizedOptions, GenerateClientOptions, GetAggArgs, GetAggArgsAgg, GetAggArgsAny, GetAggResponse, GetArgs, GetArgsAny, GetArgsInclude, GetManyArgs, GetManyArgsAny, GetManyResponse, GetResponse, GetResponseInclude, GetResponseIncludeSelect, GetResponseNoInclude, GetRestRoutesArgs, GetRestRoutesOptions, GetRestRoutesResponse, MinimalDriver, PutArgs, PutEffect, RadsFeature, RadsRequestContext, RadsUiSlotDefinition, RadsUiSlotName, RadsVitePluginOptions, Relation, RequiredFields, RestDriverOptions, RestFileUploadDriverOptions, Schema, SchemaValidators, TypeDefinition, UiDecoratorArgs, UiFieldDecoratorArgs, ValidateEntityDecoratorArgs, ValidateFieldDecoratorArgs, ValidateStringDecoratorArgs, VerifyManyArgs, VerifyManyArgsAny, VerifyManyResponse, cleanUndefinedAndNull, computed, createRadsDb, createRadsDbClient, diff, entity, field, getDriverInstance, handlePrecomputed, merge, precomputed, ui, validate };
|
package/dist/index.mjs
CHANGED
|
@@ -535,12 +535,12 @@ async function fillDenormFieldsBeforePut(computedContext, docUpdates, ctx) {
|
|
|
535
535
|
await Promise.all(promises);
|
|
536
536
|
}
|
|
537
537
|
|
|
538
|
-
function cleanUndefinedAndNull(obj) {
|
|
538
|
+
function cleanUndefinedAndNull(obj, isChange = false) {
|
|
539
539
|
for (const key in obj) {
|
|
540
|
-
if (obj[key] == null)
|
|
540
|
+
if (obj[key] == null && !isChange)
|
|
541
541
|
delete obj[key];
|
|
542
542
|
if (_.isPlainObject(obj[key]))
|
|
543
|
-
cleanUndefinedAndNull(obj[key]);
|
|
543
|
+
cleanUndefinedAndNull(obj[key], key === "change");
|
|
544
544
|
}
|
|
545
545
|
}
|
|
546
546
|
|
|
@@ -599,7 +599,6 @@ function mustUseDeepDiff(value, oldValue) {
|
|
|
599
599
|
|
|
600
600
|
function getRadsDbMethods(key, computedContext, driverInstance) {
|
|
601
601
|
const { schema, options, validators } = computedContext;
|
|
602
|
-
const mustCleanNulls = driverInstance.driverName !== "restApi";
|
|
603
602
|
const { precomputedFields } = schema[key];
|
|
604
603
|
async function getMany(args, ctx) {
|
|
605
604
|
args = { ...args, where: { ...args?.where } };
|
|
@@ -631,7 +630,7 @@ function getRadsDbMethods(key, computedContext, driverInstance) {
|
|
|
631
630
|
const docArgsToSave = docs.map((doc) => {
|
|
632
631
|
const oldDoc = oldDocsById[doc.id];
|
|
633
632
|
doc = merge(oldDoc, doc);
|
|
634
|
-
if (
|
|
633
|
+
if (!options.keepNulls)
|
|
635
634
|
cleanUndefinedAndNull(doc);
|
|
636
635
|
return { oldDoc, doc };
|
|
637
636
|
});
|
|
@@ -652,6 +651,59 @@ function getRadsDbMethods(key, computedContext, driverInstance) {
|
|
|
652
651
|
await afterPut(docArgsToSave, ctx, computedContext);
|
|
653
652
|
return docsToSave;
|
|
654
653
|
}
|
|
654
|
+
async function verifyMany(args, ctx) {
|
|
655
|
+
if (driverInstance.verifyMany) {
|
|
656
|
+
return driverInstance.verifyMany(args, ctx);
|
|
657
|
+
}
|
|
658
|
+
ctx = { ...options.context, ...ctx };
|
|
659
|
+
if (args?.dryRun) {
|
|
660
|
+
ctx._logs = ctx._logs || [];
|
|
661
|
+
ctx.dryRun = true;
|
|
662
|
+
}
|
|
663
|
+
const { _logs } = ctx;
|
|
664
|
+
const { nodes, cursor } = await driverInstance.getMany(args, ctx);
|
|
665
|
+
let correctCount = 0;
|
|
666
|
+
let incorrectCount = 0;
|
|
667
|
+
const incorrectDocs = [];
|
|
668
|
+
const oldDocs = nodes;
|
|
669
|
+
const docArgsToSave = oldDocs.map((oldDoc) => {
|
|
670
|
+
const doc = merge(oldDoc, {});
|
|
671
|
+
if (args?.recompute) {
|
|
672
|
+
for (const p of args.recompute) {
|
|
673
|
+
delete doc[p];
|
|
674
|
+
}
|
|
675
|
+
}
|
|
676
|
+
if (!options.keepNulls)
|
|
677
|
+
cleanUndefinedAndNull(doc);
|
|
678
|
+
return { oldDoc, doc };
|
|
679
|
+
});
|
|
680
|
+
await handlePrecomputed(computedContext, docArgsToSave, ctx);
|
|
681
|
+
const beforePutResults = await handleEffectsBeforePut(computedContext, docArgsToSave, ctx);
|
|
682
|
+
await beforePut(docArgsToSave, ctx, computedContext);
|
|
683
|
+
for (const d of docArgsToSave) {
|
|
684
|
+
const validatedDoc = validators[key](d.doc);
|
|
685
|
+
for (const f of precomputedFields || []) {
|
|
686
|
+
_.set(validatedDoc, f, _.get(d.doc, f));
|
|
687
|
+
}
|
|
688
|
+
d.doc = validatedDoc;
|
|
689
|
+
}
|
|
690
|
+
await fillDenormFieldsBeforePut(computedContext, docArgsToSave, ctx);
|
|
691
|
+
for (const { oldDoc, doc } of docArgsToSave) {
|
|
692
|
+
const d = diff(doc, oldDoc);
|
|
693
|
+
if (_.isEmpty(d))
|
|
694
|
+
correctCount++;
|
|
695
|
+
else {
|
|
696
|
+
incorrectCount++;
|
|
697
|
+
const objToAdd = { id: doc.id, diff: d };
|
|
698
|
+
incorrectDocs.push(objToAdd);
|
|
699
|
+
}
|
|
700
|
+
}
|
|
701
|
+
const docsToSave = docArgsToSave.map((x) => x.doc);
|
|
702
|
+
await driverInstance.putMany(docsToSave, ctx);
|
|
703
|
+
await handleEffectsAfterPut(computedContext, docArgsToSave, beforePutResults, ctx);
|
|
704
|
+
await afterPut(docArgsToSave, ctx, computedContext);
|
|
705
|
+
return { _logs, cursor, correctCount, incorrectCount, incorrectDocs };
|
|
706
|
+
}
|
|
655
707
|
const result = {
|
|
656
708
|
// No deleteMany / deleteAll on purpose - it's a dangerous operation, let them use driver instead
|
|
657
709
|
createObject() {
|
|
@@ -659,6 +711,7 @@ function getRadsDbMethods(key, computedContext, driverInstance) {
|
|
|
659
711
|
},
|
|
660
712
|
getMany,
|
|
661
713
|
putMany,
|
|
714
|
+
verifyMany,
|
|
662
715
|
driver: driverInstance,
|
|
663
716
|
getAgg: async (args, ctx) => {
|
|
664
717
|
args = { ...args, where: { ...args?.where } };
|
|
@@ -696,6 +749,17 @@ function getRadsDbMethods(key, computedContext, driverInstance) {
|
|
|
696
749
|
await afterGet(result2, args, ctx, computedContext);
|
|
697
750
|
return result2;
|
|
698
751
|
},
|
|
752
|
+
verifyAll: async (args, ctx) => {
|
|
753
|
+
let cursor = args?.cursor;
|
|
754
|
+
const result2 = { correctCount: 0, incorrectCount: 0 };
|
|
755
|
+
do {
|
|
756
|
+
const response = await verifyMany({ ...args, cursor }, ctx);
|
|
757
|
+
cursor = response.cursor;
|
|
758
|
+
result2.correctCount += response.correctCount;
|
|
759
|
+
result2.incorrectCount += response.incorrectCount;
|
|
760
|
+
} while (cursor);
|
|
761
|
+
return result2;
|
|
762
|
+
},
|
|
699
763
|
put: async (doc, ctx) => {
|
|
700
764
|
const precomputed = schema[key].decorators.precomputed;
|
|
701
765
|
if (precomputed && ctx?.skipPrecomputedCheckFor !== key) {
|
|
@@ -709,7 +773,7 @@ function getRadsDbMethods(key, computedContext, driverInstance) {
|
|
|
709
773
|
const oldDoc = await driverInstance.get({ where: { id: doc.id } }, ctx);
|
|
710
774
|
if (oldDoc)
|
|
711
775
|
doc = merge(oldDoc, doc);
|
|
712
|
-
if (
|
|
776
|
+
if (!options.keepNulls)
|
|
713
777
|
cleanUndefinedAndNull(doc);
|
|
714
778
|
const docArgsToSave = [{ doc, oldDoc }];
|
|
715
779
|
await handlePrecomputed(computedContext, docArgsToSave, ctx);
|
|
@@ -728,59 +792,6 @@ function getRadsDbMethods(key, computedContext, driverInstance) {
|
|
|
728
792
|
await handleEffectsAfterPut(computedContext, docArgsToSave, beforePutResults, ctx);
|
|
729
793
|
await afterPut(docArgsToSave, ctx, computedContext);
|
|
730
794
|
return doc;
|
|
731
|
-
},
|
|
732
|
-
async verifyMany(args, ctx) {
|
|
733
|
-
if (driverInstance.verifyMany) {
|
|
734
|
-
return driverInstance.verifyMany(args, ctx);
|
|
735
|
-
}
|
|
736
|
-
ctx = { ...options.context, ...ctx };
|
|
737
|
-
if (args?.dryRun) {
|
|
738
|
-
ctx._logs = ctx._logs || [];
|
|
739
|
-
ctx.dryRun = true;
|
|
740
|
-
}
|
|
741
|
-
const { _logs } = ctx;
|
|
742
|
-
const { nodes, cursor } = await driverInstance.getMany(args, ctx);
|
|
743
|
-
let correctCount = 0;
|
|
744
|
-
let incorrectCount = 0;
|
|
745
|
-
const incorrectDocs = [];
|
|
746
|
-
const oldDocs = nodes;
|
|
747
|
-
const docArgsToSave = oldDocs.map((oldDoc) => {
|
|
748
|
-
const doc = merge(oldDoc, {});
|
|
749
|
-
if (args?.recompute) {
|
|
750
|
-
for (const p of args.recompute) {
|
|
751
|
-
delete doc[p];
|
|
752
|
-
}
|
|
753
|
-
}
|
|
754
|
-
if (mustCleanNulls)
|
|
755
|
-
cleanUndefinedAndNull(doc);
|
|
756
|
-
return { oldDoc, doc };
|
|
757
|
-
});
|
|
758
|
-
await handlePrecomputed(computedContext, docArgsToSave, ctx);
|
|
759
|
-
const beforePutResults = await handleEffectsBeforePut(computedContext, docArgsToSave, ctx);
|
|
760
|
-
await beforePut(docArgsToSave, ctx, computedContext);
|
|
761
|
-
for (const d of docArgsToSave) {
|
|
762
|
-
const validatedDoc = validators[key](d.doc);
|
|
763
|
-
for (const f of precomputedFields || []) {
|
|
764
|
-
_.set(validatedDoc, f, _.get(d.doc, f));
|
|
765
|
-
}
|
|
766
|
-
d.doc = validatedDoc;
|
|
767
|
-
}
|
|
768
|
-
await fillDenormFieldsBeforePut(computedContext, docArgsToSave, ctx);
|
|
769
|
-
for (const { oldDoc, doc } of docArgsToSave) {
|
|
770
|
-
const d = diff(doc, oldDoc);
|
|
771
|
-
if (_.isEmpty(d))
|
|
772
|
-
correctCount++;
|
|
773
|
-
else {
|
|
774
|
-
incorrectCount++;
|
|
775
|
-
const objToAdd = { id: doc.id, diff: d };
|
|
776
|
-
incorrectDocs.push(objToAdd);
|
|
777
|
-
}
|
|
778
|
-
}
|
|
779
|
-
const docsToSave = docArgsToSave.map((x) => x.doc);
|
|
780
|
-
await driverInstance.putMany(docsToSave, ctx);
|
|
781
|
-
await handleEffectsAfterPut(computedContext, docArgsToSave, beforePutResults, ctx);
|
|
782
|
-
await afterPut(docArgsToSave, ctx, computedContext);
|
|
783
|
-
return { _logs, cursor, correctCount, incorrectCount, incorrectDocs };
|
|
784
795
|
}
|
|
785
796
|
};
|
|
786
797
|
for (const f of options.features) {
|
|
@@ -1130,6 +1141,7 @@ function createRadsDbClient(args) {
|
|
|
1130
1141
|
...args,
|
|
1131
1142
|
noComputed: true,
|
|
1132
1143
|
noCustomDrivers: true,
|
|
1144
|
+
keepNulls: true,
|
|
1133
1145
|
driver: restApi(args?.driver)
|
|
1134
1146
|
};
|
|
1135
1147
|
const s = radsDbArgs.schema || schema;
|
|
@@ -1137,4 +1149,4 @@ function createRadsDbClient(args) {
|
|
|
1137
1149
|
return generateMethods(s, validators, radsDbArgs);
|
|
1138
1150
|
}
|
|
1139
1151
|
|
|
1140
|
-
export { computed, createRadsDb, createRadsDbClient, diff, entity, field, getDriverInstance, handlePrecomputed, merge, precomputed, ui, validate };
|
|
1152
|
+
export { cleanUndefinedAndNull, computed, createRadsDb, createRadsDbClient, diff, entity, field, getDriverInstance, handlePrecomputed, merge, precomputed, ui, validate };
|
|
@@ -62,13 +62,15 @@ function verifyEventSourcingSetup(schema, effects) {
|
|
|
62
62
|
if (events.slice(1).some(ev => ev.type === "creation")) {
|
|
63
63
|
throw new Error(`Only first event may have type = "creation"`);
|
|
64
64
|
}
|
|
65
|
-
let aggDoc
|
|
66
|
-
id: aggId
|
|
67
|
-
};
|
|
65
|
+
let aggDoc;
|
|
68
66
|
for (const ev of events) {
|
|
69
|
-
const newAggDoc = context.validators[entityName]((0, _radsDb.merge)(aggDoc
|
|
67
|
+
const newAggDoc = context.validators[entityName]((0, _radsDb.merge)(aggDoc || {
|
|
68
|
+
id: aggId
|
|
69
|
+
}, ev.change));
|
|
70
|
+
ev.beforeChange = aggDoc;
|
|
70
71
|
ev.change = (0, _radsDb.diff)(newAggDoc, aggDoc);
|
|
71
72
|
aggDoc = newAggDoc;
|
|
73
|
+
if (!context.options.keepNulls) (0, _radsDb.cleanUndefinedAndNull)(aggDoc);
|
|
72
74
|
}
|
|
73
75
|
result.push({
|
|
74
76
|
aggDoc,
|
|
@@ -97,22 +99,55 @@ function validateEventSourcingSetup(schema, entityName, eventEntityName, aggrega
|
|
|
97
99
|
if (!eventEntity) throw new Error(`You must create entity with name "${eventEntityName}" to use eventSourcing feature with "${entityName}"`);
|
|
98
100
|
if (!eventEntity.decorators.entity) throw new Error(`"${eventEntityName}" must have "@entity()" decorator.`);
|
|
99
101
|
const expectedFields = {
|
|
100
|
-
id:
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
102
|
+
id: {
|
|
103
|
+
type: "string"
|
|
104
|
+
},
|
|
105
|
+
change: {
|
|
106
|
+
type: entityName,
|
|
107
|
+
isChange: true
|
|
108
|
+
},
|
|
109
|
+
type: {
|
|
110
|
+
isEnum: true
|
|
111
|
+
},
|
|
112
|
+
beforeChange: {
|
|
113
|
+
type: entityName,
|
|
114
|
+
isChange: false,
|
|
115
|
+
isRelation: false,
|
|
116
|
+
isRequired: false
|
|
117
|
+
},
|
|
118
|
+
[aggregateRelationField]: {
|
|
119
|
+
type: entityName,
|
|
120
|
+
isRelation: true
|
|
121
|
+
},
|
|
122
|
+
date: {
|
|
123
|
+
type: "string"
|
|
124
|
+
}
|
|
105
125
|
};
|
|
106
126
|
for (const f in expectedFields) {
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
}
|
|
127
|
+
validateSchemaField(f, eventEntityName, expectedFields, schema);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
function validateSchemaField(fieldName, eventEntityName, expectedFields, schema) {
|
|
131
|
+
const eventEntity = schema[eventEntityName];
|
|
132
|
+
const field = eventEntity.fields?.[fieldName];
|
|
133
|
+
if (!field) throw new Error(`"${eventEntityName}" must have field "${fieldName}"`);
|
|
134
|
+
const expectedField = expectedFields[fieldName];
|
|
135
|
+
if (expectedField.type && expectedField.type !== field.type) {
|
|
136
|
+
throw new Error(`"${eventEntityName}.${fieldName}" must have type "${expectedField.type}"`);
|
|
137
|
+
}
|
|
138
|
+
if (expectedField.isEnum) {
|
|
139
|
+
if (!schema[field.type]?.enumValues?.creation) throw new Error(`Field "${eventEntityName}.${fieldName}" must be enum that accepts value 'creation'`);
|
|
140
|
+
}
|
|
141
|
+
if (expectedField.isChange != null && expectedField.isChange !== (field.isChange || false)) {
|
|
142
|
+
const expectedType = expectedField.isChange ? `Change<${expectedField.type}>` : expectedField.type;
|
|
143
|
+
throw new Error(`"${eventEntityName}.${fieldName}" must have type "${expectedType}"`);
|
|
144
|
+
}
|
|
145
|
+
if (expectedField.isRelation != null && expectedField.isRelation !== (field.isRelation || false)) {
|
|
146
|
+
const expectedType = expectedField.isRelation ? `Relation<${expectedField.type}>` : expectedField.type;
|
|
147
|
+
throw new Error(`"${eventEntityName}.${fieldName}" must have type "${expectedType}"`);
|
|
148
|
+
}
|
|
149
|
+
if (expectedField.isRequired != null && expectedField.isRequired !== (field.isRequired || false)) {
|
|
150
|
+
const expectedRequired = expectedField.isRequired ? `required` : "optional";
|
|
151
|
+
throw new Error(`"${eventEntityName}.${fieldName}" must be ${expectedRequired}`);
|
|
117
152
|
}
|
|
118
153
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import _ from "lodash";
|
|
2
|
-
import { diff, handlePrecomputed, merge } from "rads-db";
|
|
2
|
+
import { cleanUndefinedAndNull, diff, handlePrecomputed, merge } from "rads-db";
|
|
3
3
|
export default () => {
|
|
4
4
|
return {
|
|
5
5
|
name: "eventSourcing",
|
|
@@ -58,11 +58,14 @@ function verifyEventSourcingSetup(schema, effects) {
|
|
|
58
58
|
if (events.slice(1).some((ev) => ev.type === "creation")) {
|
|
59
59
|
throw new Error(`Only first event may have type = "creation"`);
|
|
60
60
|
}
|
|
61
|
-
let aggDoc
|
|
61
|
+
let aggDoc;
|
|
62
62
|
for (const ev of events) {
|
|
63
|
-
const newAggDoc = context.validators[entityName](merge(aggDoc, ev.change));
|
|
63
|
+
const newAggDoc = context.validators[entityName](merge(aggDoc || { id: aggId }, ev.change));
|
|
64
|
+
ev.beforeChange = aggDoc;
|
|
64
65
|
ev.change = diff(newAggDoc, aggDoc);
|
|
65
66
|
aggDoc = newAggDoc;
|
|
67
|
+
if (!context.options.keepNulls)
|
|
68
|
+
cleanUndefinedAndNull(aggDoc);
|
|
66
69
|
}
|
|
67
70
|
result.push({ aggDoc, events });
|
|
68
71
|
}
|
|
@@ -89,25 +92,40 @@ function validateEventSourcingSetup(schema, entityName, eventEntityName, aggrega
|
|
|
89
92
|
if (!eventEntity.decorators.entity)
|
|
90
93
|
throw new Error(`"${eventEntityName}" must have "@entity()" decorator.`);
|
|
91
94
|
const expectedFields = {
|
|
92
|
-
id: "string",
|
|
93
|
-
type:
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
95
|
+
id: { type: "string" },
|
|
96
|
+
change: { type: entityName, isChange: true },
|
|
97
|
+
type: { isEnum: true },
|
|
98
|
+
beforeChange: { type: entityName, isChange: false, isRelation: false, isRequired: false },
|
|
99
|
+
[aggregateRelationField]: { type: entityName, isRelation: true },
|
|
100
|
+
date: { type: "string" }
|
|
97
101
|
};
|
|
98
102
|
for (const f in expectedFields) {
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
103
|
+
validateSchemaField(f, eventEntityName, expectedFields, schema);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
function validateSchemaField(fieldName, eventEntityName, expectedFields, schema) {
|
|
107
|
+
const eventEntity = schema[eventEntityName];
|
|
108
|
+
const field = eventEntity.fields?.[fieldName];
|
|
109
|
+
if (!field)
|
|
110
|
+
throw new Error(`"${eventEntityName}" must have field "${fieldName}"`);
|
|
111
|
+
const expectedField = expectedFields[fieldName];
|
|
112
|
+
if (expectedField.type && expectedField.type !== field.type) {
|
|
113
|
+
throw new Error(`"${eventEntityName}.${fieldName}" must have type "${expectedField.type}"`);
|
|
114
|
+
}
|
|
115
|
+
if (expectedField.isEnum) {
|
|
116
|
+
if (!schema[field.type]?.enumValues?.creation)
|
|
117
|
+
throw new Error(`Field "${eventEntityName}.${fieldName}" must be enum that accepts value 'creation'`);
|
|
118
|
+
}
|
|
119
|
+
if (expectedField.isChange != null && expectedField.isChange !== (field.isChange || false)) {
|
|
120
|
+
const expectedType = expectedField.isChange ? `Change<${expectedField.type}>` : expectedField.type;
|
|
121
|
+
throw new Error(`"${eventEntityName}.${fieldName}" must have type "${expectedType}"`);
|
|
122
|
+
}
|
|
123
|
+
if (expectedField.isRelation != null && expectedField.isRelation !== (field.isRelation || false)) {
|
|
124
|
+
const expectedType = expectedField.isRelation ? `Relation<${expectedField.type}>` : expectedField.type;
|
|
125
|
+
throw new Error(`"${eventEntityName}.${fieldName}" must have type "${expectedType}"`);
|
|
126
|
+
}
|
|
127
|
+
if (expectedField.isRequired != null && expectedField.isRequired !== (field.isRequired || false)) {
|
|
128
|
+
const expectedRequired = expectedField.isRequired ? `required` : "optional";
|
|
129
|
+
throw new Error(`"${eventEntityName}.${fieldName}" must be ${expectedRequired}`);
|
|
112
130
|
}
|
|
113
131
|
}
|
|
@@ -3,23 +3,6 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports
|
|
7
|
-
var
|
|
8
|
-
|
|
9
|
-
meta: {
|
|
10
|
-
name: "rads-db",
|
|
11
|
-
compatibility: {
|
|
12
|
-
nuxt: "^3.0.0"
|
|
13
|
-
}
|
|
14
|
-
},
|
|
15
|
-
defaults: {},
|
|
16
|
-
setup(options, nuxt) {
|
|
17
|
-
const {
|
|
18
|
-
resolve
|
|
19
|
-
} = (0, _kit.createResolver)(require('url').pathToFileURL(__filename).toString());
|
|
20
|
-
(0, _kit.addServerHandler)({
|
|
21
|
-
handler: resolve("./nuxtModuleHandler")
|
|
22
|
-
});
|
|
23
|
-
}
|
|
24
|
-
});
|
|
25
|
-
exports.radsDbNuxt = radsDbNuxt;
|
|
6
|
+
module.exports = void 0;
|
|
7
|
+
var _default = {};
|
|
8
|
+
module.exports = _default;
|
|
@@ -1,16 +1 @@
|
|
|
1
|
-
|
|
2
|
-
export const radsDbNuxt = defineNuxtModule({
|
|
3
|
-
meta: {
|
|
4
|
-
name: "rads-db",
|
|
5
|
-
compatibility: {
|
|
6
|
-
nuxt: "^3.0.0"
|
|
7
|
-
}
|
|
8
|
-
},
|
|
9
|
-
defaults: {},
|
|
10
|
-
setup(options, nuxt) {
|
|
11
|
-
const { resolve } = createResolver(import.meta.url);
|
|
12
|
-
addServerHandler({
|
|
13
|
-
handler: resolve("./nuxtModuleHandler")
|
|
14
|
-
});
|
|
15
|
-
}
|
|
16
|
-
});
|
|
1
|
+
export default {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "rads-db",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.26",
|
|
4
4
|
"files": [
|
|
5
5
|
"dist",
|
|
6
6
|
"drivers",
|
|
@@ -94,7 +94,6 @@
|
|
|
94
94
|
},
|
|
95
95
|
"dependencies": {
|
|
96
96
|
"@fastify/deepmerge": "^1.3.0",
|
|
97
|
-
"@nuxt/kit": "^3.5.1",
|
|
98
97
|
"dataloader": "^2.2.2",
|
|
99
98
|
"ignore": "^5.2.4",
|
|
100
99
|
"klaw": "^4.1.0",
|
|
@@ -107,7 +106,7 @@
|
|
|
107
106
|
"test": "vitest --run && vitest typecheck --run",
|
|
108
107
|
"link-rads-db": "symlink-dir ./test/_rads-db ./node_modules/_rads-db",
|
|
109
108
|
"generate-test-schema": "rads-db",
|
|
110
|
-
"dev": "pnpm install && pnpm
|
|
109
|
+
"dev": "pnpm install && pnpm link-rads-db && pnpm build && pnpm generate-test-schema && vitest --ui --test-timeout 300000",
|
|
111
110
|
"lint": "cross-env NODE_ENV=production eslint src/**/*.* test/**/*.*",
|
|
112
111
|
"dev-typecheck": "pnpm install && pnpm build && pnpm generate-test-schema && pnpm link-rads-db && vitest typecheck --ui",
|
|
113
112
|
"build": "unbuild"
|