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 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 (mustCleanNulls)
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 (mustCleanNulls)
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 (mustCleanNulls)
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 (mustCleanNulls)
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, ev.change));
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: "string",
101
- type: "enum",
102
- change: entityName,
103
- [aggregateRelationField]: entityName,
104
- date: "string"
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
- const field = eventEntity.fields?.[f];
108
- if (!field) throw new Error(`"${eventEntityName}" must have field "${f}"`);
109
- if (expectedFields[f] === "enum") {
110
- if (!schema[field.type]?.enumValues?.creation) throw new Error(`Field "${eventEntityName}.${f}" must be enum that accepts value 'creation'`);
111
- } else {
112
- if (field.type !== expectedFields[f]) throw new Error(`"${eventEntityName}.${f}" must have type "${expectedFields[f]}"`);
113
- if (f === "change" && !field.isChange) {
114
- throw new Error(`"${eventEntityName}.${f}" must have type "Change<${expectedFields[f]}>"`);
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 = { id: aggId };
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: "enum",
94
- change: entityName,
95
- [aggregateRelationField]: entityName,
96
- date: "string"
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
- const field = eventEntity.fields?.[f];
100
- if (!field)
101
- throw new Error(`"${eventEntityName}" must have field "${f}"`);
102
- if (expectedFields[f] === "enum") {
103
- if (!schema[field.type]?.enumValues?.creation)
104
- throw new Error(`Field "${eventEntityName}.${f}" must be enum that accepts value 'creation'`);
105
- } else {
106
- if (field.type !== expectedFields[f])
107
- throw new Error(`"${eventEntityName}.${f}" must have type "${expectedFields[f]}"`);
108
- if (f === "change" && !field.isChange) {
109
- throw new Error(`"${eventEntityName}.${f}" must have type "Change<${expectedFields[f]}>"`);
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.radsDbNuxt = void 0;
7
- var _kit = require("@nuxt/kit");
8
- const radsDbNuxt = (0, _kit.defineNuxtModule)({
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;
@@ -0,0 +1,2 @@
1
+ declare const _default: {};
2
+ export default _default;
@@ -1,16 +1 @@
1
- import { addServerHandler, createResolver, defineNuxtModule } from "@nuxt/kit";
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.24",
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 build && pnpm generate-test-schema && pnpm link-rads-db && vitest --ui --test-timeout 300000",
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"