rads-db 3.2.6 → 3.2.8
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/config.d.ts +1 -1
- package/dist/index.cjs +60 -13
- package/dist/index.d.ts +2 -2
- package/dist/index.mjs +60 -13
- package/dist/{types-17bcd41b.d.ts → types-efed26f9.d.ts} +9 -3
- package/drivers/azureCosmos.cjs +0 -2
- package/drivers/azureCosmos.mjs +0 -2
- package/drivers/sql.cjs +0 -1
- package/drivers/sql.mjs +0 -1
- package/features/eventSourcing.cjs +2 -1
- package/features/eventSourcing.mjs +2 -1
- package/integrations/cli.cjs +0 -0
- package/package.json +10 -17
package/dist/config.d.ts
CHANGED
package/dist/index.cjs
CHANGED
|
@@ -383,6 +383,21 @@ function prepareArgs(args) {
|
|
|
383
383
|
return { where, orderByProperties, orderByDirections, maxItemCount, cursor: args.cursor, pick: args.include };
|
|
384
384
|
}
|
|
385
385
|
|
|
386
|
+
function getEnabledEffects(effects, ctx) {
|
|
387
|
+
const { excludeFeatures, includeFeatures } = ctx;
|
|
388
|
+
if (excludeFeatures && includeFeatures) {
|
|
389
|
+
throw new Error("Cannot use both excludeFeatures and includeFeatures together");
|
|
390
|
+
}
|
|
391
|
+
const systemEffects = effects.filter((ef) => ef.featureName.startsWith("_"));
|
|
392
|
+
const featureEffects = effects.filter((ef) => !ef.featureName.startsWith("_"));
|
|
393
|
+
if (includeFeatures) {
|
|
394
|
+
return [...systemEffects, ...featureEffects.filter((ef) => includeFeatures.includes(ef.featureName))];
|
|
395
|
+
}
|
|
396
|
+
if (excludeFeatures) {
|
|
397
|
+
return [...systemEffects, ...featureEffects.filter((ef) => !excludeFeatures.includes(ef.featureName))];
|
|
398
|
+
}
|
|
399
|
+
return effects;
|
|
400
|
+
}
|
|
386
401
|
const computedPresets = {
|
|
387
402
|
createdAt: ({ fieldName, doc, oldDoc }) => {
|
|
388
403
|
return oldDoc?.[fieldName] || (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -421,6 +436,9 @@ async function handlePrecomputed(context, docs, ctx) {
|
|
|
421
436
|
const { precomputedFields, nestedTypeFields, fields } = schema[typeName];
|
|
422
437
|
const computed = options.computed;
|
|
423
438
|
for (const fieldName of precomputedFields || []) {
|
|
439
|
+
if (ctx.skipPrecomputed?.includes(fieldName)) {
|
|
440
|
+
continue;
|
|
441
|
+
}
|
|
424
442
|
const typeComputed = computed[typeName];
|
|
425
443
|
let handler = typeComputed?.[fieldName];
|
|
426
444
|
if (!handler) {
|
|
@@ -503,6 +521,7 @@ function verifyComputedPresense(schema, computed, effects) {
|
|
|
503
521
|
}
|
|
504
522
|
for (const dependencyEntity in handler.recomputeWhen) {
|
|
505
523
|
effects[dependencyEntity].push({
|
|
524
|
+
featureName: "_computed",
|
|
506
525
|
async afterPut(computedContext, docs, ctx) {
|
|
507
526
|
const conditionResult = handler.recomputeWhen[dependencyEntity](docs);
|
|
508
527
|
if (!conditionResult)
|
|
@@ -546,13 +565,19 @@ function verifyComputedPresense(schema, computed, effects) {
|
|
|
546
565
|
async function handleEffectsBeforePut(context, docs, ctx) {
|
|
547
566
|
if (context.drivers[context.typeName]?.driverName === "restApi")
|
|
548
567
|
return [];
|
|
549
|
-
|
|
568
|
+
const effects = getEnabledEffects(context.effects[context.typeName], ctx);
|
|
569
|
+
return Promise.all(effects.map((ef) => ef.beforePut?.(context, docs, ctx)));
|
|
550
570
|
}
|
|
551
571
|
async function handleEffectsAfterPut(context, docs, beforePutResults, ctx) {
|
|
552
572
|
if (context.drivers[context.typeName]?.driverName === "restApi")
|
|
553
573
|
return [];
|
|
574
|
+
const allEffects = context.effects[context.typeName];
|
|
575
|
+
const enabledEffects = getEnabledEffects(allEffects, ctx);
|
|
554
576
|
return Promise.all(
|
|
555
|
-
|
|
577
|
+
enabledEffects.map((ef) => {
|
|
578
|
+
const originalIndex = allEffects.indexOf(ef);
|
|
579
|
+
return ef.afterPut(context, docs, beforePutResults[originalIndex], ctx);
|
|
580
|
+
})
|
|
556
581
|
);
|
|
557
582
|
}
|
|
558
583
|
|
|
@@ -630,11 +655,12 @@ function verifyRelationsSetup(schema, effects) {
|
|
|
630
655
|
for (const fName in entity.fields) {
|
|
631
656
|
const f = entity.fields[fName];
|
|
632
657
|
const denormFields = [];
|
|
633
|
-
if (!f.isRelation || !denormFields)
|
|
658
|
+
if (!f.isRelation || !denormFields?.length)
|
|
634
659
|
continue;
|
|
635
660
|
if (!newEffects[f.type])
|
|
636
661
|
newEffects[f.type] = [];
|
|
637
662
|
newEffects[f.type].push({
|
|
663
|
+
featureName: "_relations",
|
|
638
664
|
async afterPut(context, docs, beforePutResult, ctx) {
|
|
639
665
|
const { drivers } = context;
|
|
640
666
|
const changedDocs = docs.filter((d) => denormFields.some((f2) => !___default.isEqual(d.doc[f2], d.oldDoc?.[f2])));
|
|
@@ -671,6 +697,7 @@ function verifyRelationsSetup(schema, effects) {
|
|
|
671
697
|
}
|
|
672
698
|
for (const relatedEntityName in newEffects) {
|
|
673
699
|
effects[relatedEntityName].push({
|
|
700
|
+
featureName: "_relations",
|
|
674
701
|
async afterPut(computedContext, docs, beforePutResult, ctx) {
|
|
675
702
|
for (const effect of newEffects[relatedEntityName]) {
|
|
676
703
|
await effect.afterPut(computedContext, docs, beforePutResult, ctx);
|
|
@@ -860,10 +887,10 @@ function getRadsDbMethods(key, computedContext, driverInstance) {
|
|
|
860
887
|
}
|
|
861
888
|
await radsDbRelations.fillDenormFieldsBeforePut(computedContext, docArgsToSave, ctx);
|
|
862
889
|
const docsToSave = docArgsToSave.map((x) => x.doc);
|
|
863
|
-
await driverInstance.putMany(docsToSave, ctx);
|
|
890
|
+
const putManyResponse = await driverInstance.putMany(docsToSave, ctx);
|
|
864
891
|
await handleEffectsAfterPut(computedContext, docArgsToSave, beforePutResults, ctx);
|
|
865
892
|
await afterPut(docArgsToSave, ctx, computedContext);
|
|
866
|
-
return docsToSave;
|
|
893
|
+
return putManyResponse || docsToSave;
|
|
867
894
|
}
|
|
868
895
|
async function verifyMany(args, ctx) {
|
|
869
896
|
if (driverInstance.verifyMany) {
|
|
@@ -1047,25 +1074,44 @@ function getRadsDbMethods(key, computedContext, driverInstance) {
|
|
|
1047
1074
|
}
|
|
1048
1075
|
return result;
|
|
1049
1076
|
}
|
|
1077
|
+
function getEnabledFeatures(allFeatures, ctx) {
|
|
1078
|
+
if (!ctx)
|
|
1079
|
+
return allFeatures;
|
|
1080
|
+
const { excludeFeatures, includeFeatures } = ctx;
|
|
1081
|
+
if (excludeFeatures && includeFeatures) {
|
|
1082
|
+
throw new Error("Cannot use both excludeFeatures and includeFeatures together");
|
|
1083
|
+
}
|
|
1084
|
+
if (includeFeatures) {
|
|
1085
|
+
return allFeatures.filter((f) => includeFeatures.includes(f.name));
|
|
1086
|
+
}
|
|
1087
|
+
if (excludeFeatures) {
|
|
1088
|
+
return allFeatures.filter((f) => !excludeFeatures.includes(f.name));
|
|
1089
|
+
}
|
|
1090
|
+
return allFeatures;
|
|
1091
|
+
}
|
|
1050
1092
|
async function beforeGet(args, ctx, computedContext) {
|
|
1051
|
-
|
|
1093
|
+
const enabledFeatures = getEnabledFeatures(computedContext.options.features, ctx);
|
|
1094
|
+
for (const f of enabledFeatures) {
|
|
1052
1095
|
const result = await f.beforeGet?.(args, ctx, computedContext);
|
|
1053
1096
|
if (result)
|
|
1054
1097
|
return result;
|
|
1055
1098
|
}
|
|
1056
1099
|
}
|
|
1057
1100
|
async function afterGet(items, args, ctx, computedContext) {
|
|
1058
|
-
|
|
1101
|
+
const enabledFeatures = getEnabledFeatures(computedContext.options.features, ctx);
|
|
1102
|
+
for (const f of enabledFeatures) {
|
|
1059
1103
|
await f.afterGet?.(items, args, ctx, computedContext);
|
|
1060
1104
|
}
|
|
1061
1105
|
}
|
|
1062
1106
|
async function beforePut(items, ctx, computedContext) {
|
|
1063
|
-
|
|
1107
|
+
const enabledFeatures = getEnabledFeatures(computedContext.options.features, ctx);
|
|
1108
|
+
for (const f of enabledFeatures) {
|
|
1064
1109
|
await f.beforePut?.(items, ctx, computedContext);
|
|
1065
1110
|
}
|
|
1066
1111
|
}
|
|
1067
1112
|
async function afterPut(items, ctx, computedContext) {
|
|
1068
|
-
|
|
1113
|
+
const enabledFeatures = getEnabledFeatures(computedContext.options.features, ctx);
|
|
1114
|
+
for (const f of enabledFeatures) {
|
|
1069
1115
|
await f.afterPut?.(items, ctx, computedContext);
|
|
1070
1116
|
}
|
|
1071
1117
|
}
|
|
@@ -1088,16 +1134,17 @@ function generateMethods(schema, validators, options) {
|
|
|
1088
1134
|
const db = {
|
|
1089
1135
|
_schema: schema,
|
|
1090
1136
|
_radsUiSlots: getRadsUiSlots(opts.features),
|
|
1091
|
-
async uploadFile(args) {
|
|
1092
|
-
|
|
1137
|
+
async uploadFile(args, ctx) {
|
|
1138
|
+
const enabledFeatures = getEnabledFeatures(opts.features, ctx);
|
|
1139
|
+
for (const f of enabledFeatures) {
|
|
1093
1140
|
const result2 = await f.beforeUploadFile?.(args);
|
|
1094
1141
|
if (result2)
|
|
1095
1142
|
return result2;
|
|
1096
1143
|
}
|
|
1097
1144
|
if (!opts.fileUploadDriver)
|
|
1098
1145
|
throw new Error(`Missing configuration. Please specify "fileUploadDriver" argument in "createRads()".`);
|
|
1099
|
-
const result = await opts.fileUploadDriver.uploadFile(args);
|
|
1100
|
-
for (const f of
|
|
1146
|
+
const result = await opts.fileUploadDriver.uploadFile(args, ctx);
|
|
1147
|
+
for (const f of enabledFeatures) {
|
|
1101
1148
|
await f.afterUploadFile?.(result, args);
|
|
1102
1149
|
}
|
|
1103
1150
|
return result;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { E as EntityDecoratorArgs, U as UiDecoratorArgs, a as UiFieldDecoratorArgs, V as ValidateEntityDecoratorArgs, b as ValidateFieldDecoratorArgs, F as FieldDecoratorArgs, C as ComputedDecoratorArgs, S as Schema, D as DriverConstructor, c as Driver, d as ComputedContext, R as RadsRequestContext, e as CreateRadsDbArgs, f as CreateRadsDbClientArgs } from './types-
|
|
2
|
-
export { O as Change, x as ComputedContextGlobal, k as CreateRadsArgsDrivers, m as CreateRadsDbArgsNormalized, ak as DeepKeys, af as DeepPartial, ad as DeepPartialWithNulls, ae as DeepPartialWithNullsItem, al as EntityMethods, w as EnumDefinition, v as FieldDefinition, J as FileSystemNode, u as FileUploadArgs, q as FileUploadDriver, p as FileUploadResult, H as GenerateClientNormalizedOptions, B as GenerateClientOptions, a9 as Get, $ as GetAggArgs, a0 as GetAggArgsAgg, a3 as GetAggArgsAny, a6 as GetAggResponse, _ as GetArgs, a2 as GetArgsAny, a5 as GetArgsInclude, Q as GetManyArgs, a1 as GetManyArgsAny, a7 as GetManyResponse, a8 as GetResponse, aa as GetResponseInclude, ab as GetResponseIncludeSelect, ac as GetResponseNoInclude, s as GetRestRoutesArgs, G as GetRestRoutesOptions, t as GetRestRoutesResponse, ah as InverseRelation, M as MinimalDriver, aj as Put, ai as PutArgs, P as PutEffect, g as RadsConfig, h as RadsConfigDataSource, r as RadsDbInstance, N as RadsFeature, y as RadsHookDoc, L as RadsUiSlotDefinition, K as RadsUiSlotName, I as RadsVitePluginOptions, ag as Relation, i as RequiredFields, l as RestDriverOptions, A as RestFileUploadDriverOptions, n as SchemaLoadResult, o as SchemaValidators, z as SqlDriverOptions, T as TypeDefinition, j as ValidateStringDecoratorArgs, X as VerifyManyArgs, a4 as VerifyManyArgsAny, Y as VerifyManyResponse, Z as Where, W as WhereJsonContains } from './types-
|
|
1
|
+
import { E as EntityDecoratorArgs, U as UiDecoratorArgs, a as UiFieldDecoratorArgs, V as ValidateEntityDecoratorArgs, b as ValidateFieldDecoratorArgs, F as FieldDecoratorArgs, C as ComputedDecoratorArgs, S as Schema, D as DriverConstructor, c as Driver, d as ComputedContext, R as RadsRequestContext, e as CreateRadsDbArgs, f as CreateRadsDbClientArgs } from './types-efed26f9.js';
|
|
2
|
+
export { O as Change, x as ComputedContextGlobal, k as CreateRadsArgsDrivers, m as CreateRadsDbArgsNormalized, ak as DeepKeys, af as DeepPartial, ad as DeepPartialWithNulls, ae as DeepPartialWithNullsItem, al as EntityMethods, w as EnumDefinition, v as FieldDefinition, J as FileSystemNode, u as FileUploadArgs, q as FileUploadDriver, p as FileUploadResult, H as GenerateClientNormalizedOptions, B as GenerateClientOptions, a9 as Get, $ as GetAggArgs, a0 as GetAggArgsAgg, a3 as GetAggArgsAny, a6 as GetAggResponse, _ as GetArgs, a2 as GetArgsAny, a5 as GetArgsInclude, Q as GetManyArgs, a1 as GetManyArgsAny, a7 as GetManyResponse, a8 as GetResponse, aa as GetResponseInclude, ab as GetResponseIncludeSelect, ac as GetResponseNoInclude, s as GetRestRoutesArgs, G as GetRestRoutesOptions, t as GetRestRoutesResponse, ah as InverseRelation, M as MinimalDriver, aj as Put, ai as PutArgs, P as PutEffect, g as RadsConfig, h as RadsConfigDataSource, r as RadsDbInstance, N as RadsFeature, y as RadsHookDoc, L as RadsUiSlotDefinition, K as RadsUiSlotName, I as RadsVitePluginOptions, ag as Relation, i as RequiredFields, l as RestDriverOptions, A as RestFileUploadDriverOptions, n as SchemaLoadResult, o as SchemaValidators, z as SqlDriverOptions, T as TypeDefinition, j as ValidateStringDecoratorArgs, X as VerifyManyArgs, a4 as VerifyManyArgsAny, Y as VerifyManyResponse, Z as Where, W as WhereJsonContains } from './types-efed26f9.js';
|
|
3
3
|
import { RadsDb } from '_rads-db';
|
|
4
4
|
export { RadsDb } from '_rads-db';
|
|
5
5
|
import 'mssql';
|
package/dist/index.mjs
CHANGED
|
@@ -376,6 +376,21 @@ function prepareArgs(args) {
|
|
|
376
376
|
return { where, orderByProperties, orderByDirections, maxItemCount, cursor: args.cursor, pick: args.include };
|
|
377
377
|
}
|
|
378
378
|
|
|
379
|
+
function getEnabledEffects(effects, ctx) {
|
|
380
|
+
const { excludeFeatures, includeFeatures } = ctx;
|
|
381
|
+
if (excludeFeatures && includeFeatures) {
|
|
382
|
+
throw new Error("Cannot use both excludeFeatures and includeFeatures together");
|
|
383
|
+
}
|
|
384
|
+
const systemEffects = effects.filter((ef) => ef.featureName.startsWith("_"));
|
|
385
|
+
const featureEffects = effects.filter((ef) => !ef.featureName.startsWith("_"));
|
|
386
|
+
if (includeFeatures) {
|
|
387
|
+
return [...systemEffects, ...featureEffects.filter((ef) => includeFeatures.includes(ef.featureName))];
|
|
388
|
+
}
|
|
389
|
+
if (excludeFeatures) {
|
|
390
|
+
return [...systemEffects, ...featureEffects.filter((ef) => !excludeFeatures.includes(ef.featureName))];
|
|
391
|
+
}
|
|
392
|
+
return effects;
|
|
393
|
+
}
|
|
379
394
|
const computedPresets = {
|
|
380
395
|
createdAt: ({ fieldName, doc, oldDoc }) => {
|
|
381
396
|
return oldDoc?.[fieldName] || (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -414,6 +429,9 @@ async function handlePrecomputed(context, docs, ctx) {
|
|
|
414
429
|
const { precomputedFields, nestedTypeFields, fields } = schema[typeName];
|
|
415
430
|
const computed = options.computed;
|
|
416
431
|
for (const fieldName of precomputedFields || []) {
|
|
432
|
+
if (ctx.skipPrecomputed?.includes(fieldName)) {
|
|
433
|
+
continue;
|
|
434
|
+
}
|
|
417
435
|
const typeComputed = computed[typeName];
|
|
418
436
|
let handler = typeComputed?.[fieldName];
|
|
419
437
|
if (!handler) {
|
|
@@ -496,6 +514,7 @@ function verifyComputedPresense(schema, computed, effects) {
|
|
|
496
514
|
}
|
|
497
515
|
for (const dependencyEntity in handler.recomputeWhen) {
|
|
498
516
|
effects[dependencyEntity].push({
|
|
517
|
+
featureName: "_computed",
|
|
499
518
|
async afterPut(computedContext, docs, ctx) {
|
|
500
519
|
const conditionResult = handler.recomputeWhen[dependencyEntity](docs);
|
|
501
520
|
if (!conditionResult)
|
|
@@ -539,13 +558,19 @@ function verifyComputedPresense(schema, computed, effects) {
|
|
|
539
558
|
async function handleEffectsBeforePut(context, docs, ctx) {
|
|
540
559
|
if (context.drivers[context.typeName]?.driverName === "restApi")
|
|
541
560
|
return [];
|
|
542
|
-
|
|
561
|
+
const effects = getEnabledEffects(context.effects[context.typeName], ctx);
|
|
562
|
+
return Promise.all(effects.map((ef) => ef.beforePut?.(context, docs, ctx)));
|
|
543
563
|
}
|
|
544
564
|
async function handleEffectsAfterPut(context, docs, beforePutResults, ctx) {
|
|
545
565
|
if (context.drivers[context.typeName]?.driverName === "restApi")
|
|
546
566
|
return [];
|
|
567
|
+
const allEffects = context.effects[context.typeName];
|
|
568
|
+
const enabledEffects = getEnabledEffects(allEffects, ctx);
|
|
547
569
|
return Promise.all(
|
|
548
|
-
|
|
570
|
+
enabledEffects.map((ef) => {
|
|
571
|
+
const originalIndex = allEffects.indexOf(ef);
|
|
572
|
+
return ef.afterPut(context, docs, beforePutResults[originalIndex], ctx);
|
|
573
|
+
})
|
|
549
574
|
);
|
|
550
575
|
}
|
|
551
576
|
|
|
@@ -623,11 +648,12 @@ function verifyRelationsSetup(schema, effects) {
|
|
|
623
648
|
for (const fName in entity.fields) {
|
|
624
649
|
const f = entity.fields[fName];
|
|
625
650
|
const denormFields = [];
|
|
626
|
-
if (!f.isRelation || !denormFields)
|
|
651
|
+
if (!f.isRelation || !denormFields?.length)
|
|
627
652
|
continue;
|
|
628
653
|
if (!newEffects[f.type])
|
|
629
654
|
newEffects[f.type] = [];
|
|
630
655
|
newEffects[f.type].push({
|
|
656
|
+
featureName: "_relations",
|
|
631
657
|
async afterPut(context, docs, beforePutResult, ctx) {
|
|
632
658
|
const { drivers } = context;
|
|
633
659
|
const changedDocs = docs.filter((d) => denormFields.some((f2) => !_.isEqual(d.doc[f2], d.oldDoc?.[f2])));
|
|
@@ -664,6 +690,7 @@ function verifyRelationsSetup(schema, effects) {
|
|
|
664
690
|
}
|
|
665
691
|
for (const relatedEntityName in newEffects) {
|
|
666
692
|
effects[relatedEntityName].push({
|
|
693
|
+
featureName: "_relations",
|
|
667
694
|
async afterPut(computedContext, docs, beforePutResult, ctx) {
|
|
668
695
|
for (const effect of newEffects[relatedEntityName]) {
|
|
669
696
|
await effect.afterPut(computedContext, docs, beforePutResult, ctx);
|
|
@@ -853,10 +880,10 @@ function getRadsDbMethods(key, computedContext, driverInstance) {
|
|
|
853
880
|
}
|
|
854
881
|
await radsDbRelations.fillDenormFieldsBeforePut(computedContext, docArgsToSave, ctx);
|
|
855
882
|
const docsToSave = docArgsToSave.map((x) => x.doc);
|
|
856
|
-
await driverInstance.putMany(docsToSave, ctx);
|
|
883
|
+
const putManyResponse = await driverInstance.putMany(docsToSave, ctx);
|
|
857
884
|
await handleEffectsAfterPut(computedContext, docArgsToSave, beforePutResults, ctx);
|
|
858
885
|
await afterPut(docArgsToSave, ctx, computedContext);
|
|
859
|
-
return docsToSave;
|
|
886
|
+
return putManyResponse || docsToSave;
|
|
860
887
|
}
|
|
861
888
|
async function verifyMany(args, ctx) {
|
|
862
889
|
if (driverInstance.verifyMany) {
|
|
@@ -1040,25 +1067,44 @@ function getRadsDbMethods(key, computedContext, driverInstance) {
|
|
|
1040
1067
|
}
|
|
1041
1068
|
return result;
|
|
1042
1069
|
}
|
|
1070
|
+
function getEnabledFeatures(allFeatures, ctx) {
|
|
1071
|
+
if (!ctx)
|
|
1072
|
+
return allFeatures;
|
|
1073
|
+
const { excludeFeatures, includeFeatures } = ctx;
|
|
1074
|
+
if (excludeFeatures && includeFeatures) {
|
|
1075
|
+
throw new Error("Cannot use both excludeFeatures and includeFeatures together");
|
|
1076
|
+
}
|
|
1077
|
+
if (includeFeatures) {
|
|
1078
|
+
return allFeatures.filter((f) => includeFeatures.includes(f.name));
|
|
1079
|
+
}
|
|
1080
|
+
if (excludeFeatures) {
|
|
1081
|
+
return allFeatures.filter((f) => !excludeFeatures.includes(f.name));
|
|
1082
|
+
}
|
|
1083
|
+
return allFeatures;
|
|
1084
|
+
}
|
|
1043
1085
|
async function beforeGet(args, ctx, computedContext) {
|
|
1044
|
-
|
|
1086
|
+
const enabledFeatures = getEnabledFeatures(computedContext.options.features, ctx);
|
|
1087
|
+
for (const f of enabledFeatures) {
|
|
1045
1088
|
const result = await f.beforeGet?.(args, ctx, computedContext);
|
|
1046
1089
|
if (result)
|
|
1047
1090
|
return result;
|
|
1048
1091
|
}
|
|
1049
1092
|
}
|
|
1050
1093
|
async function afterGet(items, args, ctx, computedContext) {
|
|
1051
|
-
|
|
1094
|
+
const enabledFeatures = getEnabledFeatures(computedContext.options.features, ctx);
|
|
1095
|
+
for (const f of enabledFeatures) {
|
|
1052
1096
|
await f.afterGet?.(items, args, ctx, computedContext);
|
|
1053
1097
|
}
|
|
1054
1098
|
}
|
|
1055
1099
|
async function beforePut(items, ctx, computedContext) {
|
|
1056
|
-
|
|
1100
|
+
const enabledFeatures = getEnabledFeatures(computedContext.options.features, ctx);
|
|
1101
|
+
for (const f of enabledFeatures) {
|
|
1057
1102
|
await f.beforePut?.(items, ctx, computedContext);
|
|
1058
1103
|
}
|
|
1059
1104
|
}
|
|
1060
1105
|
async function afterPut(items, ctx, computedContext) {
|
|
1061
|
-
|
|
1106
|
+
const enabledFeatures = getEnabledFeatures(computedContext.options.features, ctx);
|
|
1107
|
+
for (const f of enabledFeatures) {
|
|
1062
1108
|
await f.afterPut?.(items, ctx, computedContext);
|
|
1063
1109
|
}
|
|
1064
1110
|
}
|
|
@@ -1081,16 +1127,17 @@ function generateMethods(schema, validators, options) {
|
|
|
1081
1127
|
const db = {
|
|
1082
1128
|
_schema: schema,
|
|
1083
1129
|
_radsUiSlots: getRadsUiSlots(opts.features),
|
|
1084
|
-
async uploadFile(args) {
|
|
1085
|
-
|
|
1130
|
+
async uploadFile(args, ctx) {
|
|
1131
|
+
const enabledFeatures = getEnabledFeatures(opts.features, ctx);
|
|
1132
|
+
for (const f of enabledFeatures) {
|
|
1086
1133
|
const result2 = await f.beforeUploadFile?.(args);
|
|
1087
1134
|
if (result2)
|
|
1088
1135
|
return result2;
|
|
1089
1136
|
}
|
|
1090
1137
|
if (!opts.fileUploadDriver)
|
|
1091
1138
|
throw new Error(`Missing configuration. Please specify "fileUploadDriver" argument in "createRads()".`);
|
|
1092
|
-
const result = await opts.fileUploadDriver.uploadFile(args);
|
|
1093
|
-
for (const f of
|
|
1139
|
+
const result = await opts.fileUploadDriver.uploadFile(args, ctx);
|
|
1140
|
+
for (const f of enabledFeatures) {
|
|
1094
1141
|
await f.afterUploadFile?.(result, args);
|
|
1095
1142
|
}
|
|
1096
1143
|
return result;
|
|
@@ -34,8 +34,7 @@ interface GetArgs<EN extends keyof EntityMeta> {
|
|
|
34
34
|
where?: Where<EN>;
|
|
35
35
|
include?: GetArgsInclude<EN>;
|
|
36
36
|
}
|
|
37
|
-
interface GetAggArgs<EN extends keyof EntityMeta> {
|
|
38
|
-
where?: Where<EN>;
|
|
37
|
+
interface GetAggArgs<EN extends keyof EntityMeta> extends Omit<GetManyArgs<EN>, 'include'> {
|
|
39
38
|
agg: GetAggArgsAgg<EN>;
|
|
40
39
|
}
|
|
41
40
|
type GetAggArgsAgg<EN extends keyof EntityMeta, F extends string = EntityMeta[EN]['aggregates']> = ('_count' | `${F}_min` | `${F}_max` | `${F}_sum`)[];
|
|
@@ -101,7 +100,7 @@ type Relation<T extends {
|
|
|
101
100
|
* Note: this field is not stored in the database at all. Returns up to 100 items and doesn't support pagination
|
|
102
101
|
* If you need more control, please, use separate request instead.
|
|
103
102
|
*/
|
|
104
|
-
type InverseRelation<EN extends keyof EntityMeta
|
|
103
|
+
type InverseRelation<EN extends keyof EntityMeta> = EntityMeta[EN]['type'];
|
|
105
104
|
type PutArgs<T> = {
|
|
106
105
|
id: string;
|
|
107
106
|
} & DeepPartialWithNulls<T>;
|
|
@@ -374,6 +373,7 @@ interface RadsHookDoc {
|
|
|
374
373
|
updatedEvents?: any[];
|
|
375
374
|
}
|
|
376
375
|
interface PutEffect {
|
|
376
|
+
featureName: string;
|
|
377
377
|
beforePut?: (computedContext: ComputedContext, docs: RadsHookDoc[], ctx: RadsRequestContext) => MaybePromise<any>;
|
|
378
378
|
afterPut: (computedContext: ComputedContext, docs: RadsHookDoc[], beforePutResult: any, ctx: RadsRequestContext) => MaybePromise<any>;
|
|
379
379
|
}
|
|
@@ -425,10 +425,16 @@ interface RadsRequestContext {
|
|
|
425
425
|
silent?: boolean;
|
|
426
426
|
/** Mostly for internal use. When entity name is specified, indicates that calling put* on this entity is allowed, even if it's marked as @precomputed or @readonly */
|
|
427
427
|
skipPrecomputedCheckFor?: string;
|
|
428
|
+
/** Skip precomputed calculation for these fields and use provided values instead */
|
|
429
|
+
skipPrecomputed?: string[];
|
|
428
430
|
/** Method that was called - get, getAll, getMany, getAgg, put, putMany, etc */
|
|
429
431
|
method?: 'get' | 'getAll' | 'getMany' | 'getAgg' | 'put' | 'putMany' | 'deleteMany' | 'deleteAll';
|
|
430
432
|
/** if true, all cache layers will be bypassed */
|
|
431
433
|
noCache?: boolean;
|
|
434
|
+
/** Skip these features for this request (blacklist) */
|
|
435
|
+
excludeFeatures?: string[];
|
|
436
|
+
/** Run only these features, skip all others (whitelist). Cannot be used together with excludeFeatures */
|
|
437
|
+
includeFeatures?: string[];
|
|
432
438
|
[key: string]: any;
|
|
433
439
|
}
|
|
434
440
|
interface FileSystemNode {
|
package/drivers/azureCosmos.cjs
CHANGED
|
@@ -99,12 +99,10 @@ var _default = options => (schema, entity) => {
|
|
|
99
99
|
getMany,
|
|
100
100
|
async getAgg(args, ctx) {
|
|
101
101
|
args = args || {};
|
|
102
|
-
const where = args.where || {};
|
|
103
102
|
const {
|
|
104
103
|
query,
|
|
105
104
|
parameters
|
|
106
105
|
} = getCosmosQuery(schema, entity, args);
|
|
107
|
-
let cursor;
|
|
108
106
|
const response = client.items.query({
|
|
109
107
|
query,
|
|
110
108
|
parameters: Object.keys(parameters).map(k => ({
|
package/drivers/azureCosmos.mjs
CHANGED
|
@@ -66,9 +66,7 @@ export default (options) => (schema, entity) => {
|
|
|
66
66
|
getMany,
|
|
67
67
|
async getAgg(args, ctx) {
|
|
68
68
|
args = args || {};
|
|
69
|
-
const where = args.where || {};
|
|
70
69
|
const { query, parameters } = getCosmosQuery(schema, entity, args);
|
|
71
|
-
let cursor;
|
|
72
70
|
const response = client.items.query(
|
|
73
71
|
{
|
|
74
72
|
query,
|
package/drivers/sql.cjs
CHANGED
|
@@ -13,7 +13,6 @@ const strType = "VARCHAR(MAX)";
|
|
|
13
13
|
const numberType = "DECIMAL(30,15)";
|
|
14
14
|
const booleanType = "BIT";
|
|
15
15
|
const simpleSubclauseRegex = /^[a-z0-9_@]+.[a-z0-9_@]+ = [a-z0-9_@.]+$/i;
|
|
16
|
-
const sanitizePathRegex = /^[a-z0-9_\[\]\.]+$/i;
|
|
17
16
|
const operatorHandlers = {
|
|
18
17
|
some: (ctx, parameters, whereArgs) => {
|
|
19
18
|
const {
|
package/drivers/sql.mjs
CHANGED
|
@@ -6,7 +6,6 @@ const strType = "VARCHAR(MAX)";
|
|
|
6
6
|
const numberType = "DECIMAL(30,15)";
|
|
7
7
|
const booleanType = "BIT";
|
|
8
8
|
const simpleSubclauseRegex = /^[a-z0-9_@]+.[a-z0-9_@]+ = [a-z0-9_@.]+$/i;
|
|
9
|
-
const sanitizePathRegex = /^[a-z0-9_\[\]\.]+$/i;
|
|
10
9
|
const operatorHandlers = {
|
|
11
10
|
some: (ctx, parameters, whereArgs) => {
|
|
12
11
|
const { name, namePrefix, paramNamePrefix, paramName, whereVal } = whereArgs;
|
|
@@ -29,6 +29,7 @@ function verifyEventSourcingSetup(schema, effects, options) {
|
|
|
29
29
|
}
|
|
30
30
|
function getEffectFor(entityName, aggregateRelationField, eventEntityName, schema, options) {
|
|
31
31
|
return {
|
|
32
|
+
featureName: "eventSourcing",
|
|
32
33
|
async beforePut(context, docs, ctx) {
|
|
33
34
|
const docsByAggId = {};
|
|
34
35
|
const docsById = {};
|
|
@@ -62,7 +63,7 @@ function getEffectFor(entityName, aggregateRelationField, eventEntityName, schem
|
|
|
62
63
|
const existingAggregatesById = _lodash.default.keyBy(existingAggregates, "id");
|
|
63
64
|
const result = [];
|
|
64
65
|
for (const aggId in docsByAggId) {
|
|
65
|
-
|
|
66
|
+
const events = _lodash.default.orderBy([...docsByAggId[aggId], ...(existingEventsByAggId[aggId] || [])], ["date"], "asc");
|
|
66
67
|
if (events[0].type !== "creation") throw new Error(`First event must have type = "creation". (type: ${events[0].type}, id: ${events[0].id})`);
|
|
67
68
|
if (events.slice(1).some(ev => ev.type === "creation")) {
|
|
68
69
|
throw new Error(`Only first event may have type = "creation"`);
|
|
@@ -21,6 +21,7 @@ function verifyEventSourcingSetup(schema, effects, options) {
|
|
|
21
21
|
}
|
|
22
22
|
function getEffectFor(entityName, aggregateRelationField, eventEntityName, schema, options) {
|
|
23
23
|
return {
|
|
24
|
+
featureName: "eventSourcing",
|
|
24
25
|
async beforePut(context, docs, ctx) {
|
|
25
26
|
const docsByAggId = {};
|
|
26
27
|
const docsById = {};
|
|
@@ -52,7 +53,7 @@ function getEffectFor(entityName, aggregateRelationField, eventEntityName, schem
|
|
|
52
53
|
const existingAggregatesById = _.keyBy(existingAggregates, "id");
|
|
53
54
|
const result = [];
|
|
54
55
|
for (const aggId in docsByAggId) {
|
|
55
|
-
|
|
56
|
+
const events = _.orderBy([...docsByAggId[aggId], ...existingEventsByAggId[aggId] || []], ["date"], "asc");
|
|
56
57
|
if (events[0].type !== "creation")
|
|
57
58
|
throw new Error(`First event must have type = "creation". (type: ${events[0].type}, id: ${events[0].id})`);
|
|
58
59
|
if (events.slice(1).some((ev) => ev.type === "creation")) {
|
package/integrations/cli.cjs
CHANGED
|
File without changes
|
package/package.json
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "rads-db",
|
|
3
|
-
"version": "3.2.
|
|
4
|
-
"packageManager": "pnpm@10.12.1+sha512.f0dda8580f0ee9481c5c79a1d927b9164f2c478e90992ad268bbb2465a736984391d6333d2c327913578b2804af33474ca554ba29c04a8b13060a717675ae3ac",
|
|
3
|
+
"version": "3.2.8",
|
|
5
4
|
"description": "Say goodbye to boilerplate code and hello to efficient and elegant syntax.",
|
|
6
5
|
"author": "",
|
|
7
6
|
"license": "ISC",
|
|
@@ -51,16 +50,6 @@
|
|
|
51
50
|
"integrations",
|
|
52
51
|
"features"
|
|
53
52
|
],
|
|
54
|
-
"scripts": {
|
|
55
|
-
"prepublishOnly": "pnpm build",
|
|
56
|
-
"test": "vitest --run && vitest typecheck --run",
|
|
57
|
-
"link-rads-db": "symlink-dir ./test/_rads-db ./node_modules/_rads-db",
|
|
58
|
-
"generate-test-schema": "jiti ./src/integrations/cli",
|
|
59
|
-
"dev": "pnpm install && pnpm link-rads-db && pnpm build && pnpm generate-test-schema && vitest --ui --test-timeout 300000 --typecheck",
|
|
60
|
-
"lint": "cross-env NODE_ENV=production eslint src/**/*.* test/**/*.*",
|
|
61
|
-
"typecheck": "tsc --noEmit",
|
|
62
|
-
"build": "unbuild"
|
|
63
|
-
},
|
|
64
53
|
"peerDependencies": {
|
|
65
54
|
"@azure/cosmos": ">=3",
|
|
66
55
|
"@azure/storage-blob": ">=12",
|
|
@@ -122,9 +111,13 @@
|
|
|
122
111
|
"vite": "^4.0.0",
|
|
123
112
|
"vitest": "^1.6.0"
|
|
124
113
|
},
|
|
125
|
-
"
|
|
126
|
-
"
|
|
127
|
-
|
|
128
|
-
|
|
114
|
+
"scripts": {
|
|
115
|
+
"test": "vitest --run --typecheck",
|
|
116
|
+
"link-rads-db": "symlink-dir ./test/_rads-db ./node_modules/_rads-db",
|
|
117
|
+
"generate-test-schema": "jiti ./src/integrations/cli",
|
|
118
|
+
"dev": "pnpm install && pnpm link-rads-db && pnpm build && pnpm generate-test-schema && vitest --ui --test-timeout 300000 --typecheck",
|
|
119
|
+
"lint": "cross-env NODE_ENV=production eslint src/**/*.* test/**/*.*",
|
|
120
|
+
"typecheck": "tsc --noEmit",
|
|
121
|
+
"build": "unbuild"
|
|
129
122
|
}
|
|
130
|
-
}
|
|
123
|
+
}
|