rads-db 0.1.92 → 0.1.94
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 +68 -41
- package/dist/index.d.ts +16 -4
- package/dist/index.mjs +68 -42
- package/drivers/memory.cjs +10 -7
- package/drivers/memory.mjs +10 -7
- package/features/cache.cjs +146 -0
- package/features/cache.d.ts +30 -0
- package/features/cache.mjs +123 -0
- package/integrations/node.cjs +1 -1
- package/integrations/node.mjs +1 -1
- package/integrations/restEndpointsDev.cjs +4 -0
- package/integrations/restEndpointsDev.d.ts +1 -0
- package/integrations/restEndpointsDev.mjs +4 -0
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -131,23 +131,26 @@ const operatorFns = {
|
|
|
131
131
|
}
|
|
132
132
|
};
|
|
133
133
|
const memory = (options) => (schema, entity) => {
|
|
134
|
-
let
|
|
134
|
+
let itemsById = {};
|
|
135
135
|
function getItemById(id) {
|
|
136
|
-
return
|
|
136
|
+
return itemsById[id] ?? null;
|
|
137
137
|
}
|
|
138
138
|
function getItemByIds(ids) {
|
|
139
|
-
return ids.map((id) =>
|
|
139
|
+
return ids.map((id) => itemsById[id]);
|
|
140
140
|
}
|
|
141
141
|
const instance = {
|
|
142
142
|
driverName: "memory",
|
|
143
|
+
get itemsById() {
|
|
144
|
+
return itemsById;
|
|
145
|
+
},
|
|
143
146
|
clear() {
|
|
144
|
-
|
|
147
|
+
itemsById = {};
|
|
145
148
|
},
|
|
146
149
|
putMany(items) {
|
|
147
150
|
for (const item of items) {
|
|
148
151
|
if (!item?.id)
|
|
149
152
|
throw new Error(`You must provide an id`);
|
|
150
|
-
|
|
153
|
+
itemsById[item.id] = item;
|
|
151
154
|
}
|
|
152
155
|
},
|
|
153
156
|
getMany(args) {
|
|
@@ -160,7 +163,7 @@ const memory = (options) => (schema, entity) => {
|
|
|
160
163
|
if (whereKeys[0] === "id_in")
|
|
161
164
|
return { nodes: ___default.cloneDeep(getItemByIds(where.id_in).filter((x) => x)), cursor: null };
|
|
162
165
|
}
|
|
163
|
-
return queryArray(Object.values(
|
|
166
|
+
return queryArray(Object.values(itemsById), args);
|
|
164
167
|
}
|
|
165
168
|
};
|
|
166
169
|
return instance;
|
|
@@ -267,7 +270,7 @@ function getFilterInner(operator, whereVal, name, namePrefix) {
|
|
|
267
270
|
if (operatorFn) {
|
|
268
271
|
return (x) => operatorFn(___default.get(x, name), whereVal);
|
|
269
272
|
}
|
|
270
|
-
console.warn(`[rads-
|
|
273
|
+
console.warn(`[rads-db] Operator not supported: ${operator || "eq"}`);
|
|
271
274
|
return null;
|
|
272
275
|
}
|
|
273
276
|
function prepareArgs(args) {
|
|
@@ -705,14 +708,15 @@ function getRadsDbMethods(key, computedContext, driverInstance) {
|
|
|
705
708
|
const { precomputedFields } = schema[key];
|
|
706
709
|
async function getMany(args, ctx) {
|
|
707
710
|
args = { ...args, where: { ...args?.where } };
|
|
708
|
-
ctx = { ...options.context, ...ctx };
|
|
709
|
-
await beforeGet(args, ctx, computedContext);
|
|
710
|
-
|
|
711
|
+
ctx = { ...options.context, ...ctx, method: "getMany" };
|
|
712
|
+
let result2 = await beforeGet(args, ctx, computedContext);
|
|
713
|
+
if (!result2)
|
|
714
|
+
result2 = await driverInstance.getMany(args, ctx);
|
|
711
715
|
if (args.include)
|
|
712
|
-
await handleInclude(computedContext, args.include,
|
|
713
|
-
await handleComputed(computedContext,
|
|
714
|
-
await afterGet(
|
|
715
|
-
return
|
|
716
|
+
await handleInclude(computedContext, args.include, result2.nodes, ctx);
|
|
717
|
+
await handleComputed(computedContext, result2.nodes, ctx);
|
|
718
|
+
await afterGet(result2.nodes, args, ctx, computedContext);
|
|
719
|
+
return result2;
|
|
716
720
|
}
|
|
717
721
|
async function putMany(docs, ctx) {
|
|
718
722
|
const precomputed = schema[key].decorators.precomputed;
|
|
@@ -726,7 +730,7 @@ function getRadsDbMethods(key, computedContext, driverInstance) {
|
|
|
726
730
|
throw new Error("Id is required");
|
|
727
731
|
return i.id;
|
|
728
732
|
});
|
|
729
|
-
ctx = { ...options.context, ...ctx };
|
|
733
|
+
ctx = { ...options.context, ...ctx, method: "putMany" };
|
|
730
734
|
const oldDocs = await driverInstance.getAll({ where: { id_in: ids } }, ctx);
|
|
731
735
|
const oldDocsById = ___default.keyBy(oldDocs, "id");
|
|
732
736
|
const docArgsToSave = docs.map((doc) => {
|
|
@@ -753,7 +757,10 @@ function getRadsDbMethods(key, computedContext, driverInstance) {
|
|
|
753
757
|
await afterPut(docArgsToSave, ctx, computedContext);
|
|
754
758
|
return docsToSave;
|
|
755
759
|
}
|
|
756
|
-
|
|
760
|
+
const result = {
|
|
761
|
+
createObject() {
|
|
762
|
+
throw new Error("Not implemented");
|
|
763
|
+
},
|
|
757
764
|
getMany,
|
|
758
765
|
putMany,
|
|
759
766
|
driver: driverInstance,
|
|
@@ -761,34 +768,37 @@ function getRadsDbMethods(key, computedContext, driverInstance) {
|
|
|
761
768
|
args = { ...args, where: { ...args?.where } };
|
|
762
769
|
if (!args.agg)
|
|
763
770
|
throw new Error(`Please provide 'agg' argument`);
|
|
764
|
-
ctx = { ...options.context, ...ctx };
|
|
765
|
-
await beforeGet(args, ctx, computedContext);
|
|
766
|
-
|
|
767
|
-
|
|
771
|
+
ctx = { ...options.context, ...ctx, method: "getAgg" };
|
|
772
|
+
let result2 = await beforeGet(args, ctx, computedContext);
|
|
773
|
+
if (!result2)
|
|
774
|
+
result2 = await driverInstance.getAgg(args, ctx);
|
|
775
|
+
return result2;
|
|
768
776
|
},
|
|
769
777
|
get: async (args, ctx) => {
|
|
770
778
|
args = { ...args, where: { ...args?.where } };
|
|
771
|
-
ctx = { ...options.context, ...ctx };
|
|
772
|
-
await beforeGet(args, ctx, computedContext);
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
779
|
+
ctx = { ...options.context, ...ctx, method: "get" };
|
|
780
|
+
let result2 = await beforeGet(args, ctx, computedContext);
|
|
781
|
+
if (!result2)
|
|
782
|
+
result2 = await driverInstance.get(args, ctx);
|
|
783
|
+
const resultArray = result2 ? [result2] : [];
|
|
784
|
+
if (result2 && args.include)
|
|
776
785
|
await handleInclude(computedContext, args.include, resultArray, ctx);
|
|
777
|
-
if (
|
|
786
|
+
if (result2)
|
|
778
787
|
await handleComputed(computedContext, resultArray, ctx);
|
|
779
788
|
await afterGet(resultArray, args, ctx, computedContext);
|
|
780
|
-
return
|
|
789
|
+
return result2;
|
|
781
790
|
},
|
|
782
791
|
getAll: async (args, ctx) => {
|
|
783
792
|
args = { ...args, where: { ...args?.where } };
|
|
784
|
-
ctx = { ...options.context, ...ctx };
|
|
785
|
-
await beforeGet(args, ctx, computedContext);
|
|
786
|
-
|
|
793
|
+
ctx = { ...options.context, ...ctx, method: "getAll" };
|
|
794
|
+
let result2 = await beforeGet(args, ctx, computedContext);
|
|
795
|
+
if (!result2)
|
|
796
|
+
result2 = await driverInstance.getAll(args, ctx);
|
|
787
797
|
if (args.include)
|
|
788
|
-
await handleInclude(computedContext, args.include,
|
|
789
|
-
await handleComputed(computedContext,
|
|
790
|
-
await afterGet(
|
|
791
|
-
return
|
|
798
|
+
await handleInclude(computedContext, args.include, result2, ctx);
|
|
799
|
+
await handleComputed(computedContext, result2, ctx);
|
|
800
|
+
await afterGet(result2, args, ctx, computedContext);
|
|
801
|
+
return result2;
|
|
792
802
|
},
|
|
793
803
|
put: async (doc, ctx) => {
|
|
794
804
|
const precomputed = schema[key].decorators.precomputed;
|
|
@@ -881,10 +891,17 @@ function getRadsDbMethods(key, computedContext, driverInstance) {
|
|
|
881
891
|
return driverInstance.clear(ctx);
|
|
882
892
|
}
|
|
883
893
|
};
|
|
894
|
+
for (const f of options.features) {
|
|
895
|
+
if (f.enhanceEntityMethods)
|
|
896
|
+
f.enhanceEntityMethods(computedContext, result);
|
|
897
|
+
}
|
|
898
|
+
return result;
|
|
884
899
|
}
|
|
885
900
|
async function beforeGet(args, ctx, computedContext) {
|
|
886
901
|
for (const f of computedContext.options.features) {
|
|
887
|
-
await f.beforeGet?.(args, ctx, computedContext);
|
|
902
|
+
const result = await f.beforeGet?.(args, ctx, computedContext);
|
|
903
|
+
if (result)
|
|
904
|
+
return result;
|
|
888
905
|
}
|
|
889
906
|
}
|
|
890
907
|
async function afterGet(items, args, ctx, computedContext) {
|
|
@@ -980,6 +997,14 @@ function generateMethods(schema, validators, options) {
|
|
|
980
997
|
}
|
|
981
998
|
verifyEventSourcingSetup(schema, effects);
|
|
982
999
|
verifyRelationsSetup(schema, effects);
|
|
1000
|
+
const computedContextGlobal = {
|
|
1001
|
+
schema,
|
|
1002
|
+
validators,
|
|
1003
|
+
options: opts,
|
|
1004
|
+
drivers,
|
|
1005
|
+
effects,
|
|
1006
|
+
db
|
|
1007
|
+
};
|
|
983
1008
|
for (const key in schema) {
|
|
984
1009
|
if (!schema[key].decorators.entity)
|
|
985
1010
|
continue;
|
|
@@ -987,17 +1012,17 @@ function generateMethods(schema, validators, options) {
|
|
|
987
1012
|
if (!handle)
|
|
988
1013
|
throw new Error(`Missing handle for entity ${key}`);
|
|
989
1014
|
const computedContext = {
|
|
990
|
-
|
|
1015
|
+
...computedContextGlobal,
|
|
991
1016
|
typeName: key,
|
|
992
|
-
|
|
993
|
-
options: opts,
|
|
994
|
-
drivers,
|
|
995
|
-
effects,
|
|
996
|
-
db
|
|
1017
|
+
handle: schema[key].handle
|
|
997
1018
|
};
|
|
998
1019
|
const driverInstance = getDriverInstance(schema, key, opts.driver, drivers);
|
|
999
1020
|
db[handle] = getRadsDbMethods(key, computedContext, driverInstance);
|
|
1000
1021
|
}
|
|
1022
|
+
for (const f of opts.features) {
|
|
1023
|
+
if (f.init)
|
|
1024
|
+
f.init(db, computedContextGlobal);
|
|
1025
|
+
}
|
|
1001
1026
|
return db;
|
|
1002
1027
|
}
|
|
1003
1028
|
function getDriverInstance(schema, key, driver, drivers) {
|
|
@@ -1011,6 +1036,7 @@ function getDriverInstanceInner(schema, key, driverConstructor) {
|
|
|
1011
1036
|
addDryRunSupport(driverInstance, key);
|
|
1012
1037
|
async function getAll(args, ctx) {
|
|
1013
1038
|
const result = [];
|
|
1039
|
+
args = args || {};
|
|
1014
1040
|
let cursor = args.cursor;
|
|
1015
1041
|
let maxItemCount = args.maxItemCount || 1e3;
|
|
1016
1042
|
if (maxItemCount < 1e3)
|
|
@@ -1122,6 +1148,7 @@ exports.computed = computed;
|
|
|
1122
1148
|
exports.createRads = createRads;
|
|
1123
1149
|
exports.entity = entity;
|
|
1124
1150
|
exports.field = field;
|
|
1151
|
+
exports.getDriverInstance = getDriverInstance;
|
|
1125
1152
|
exports.precomputed = precomputed;
|
|
1126
1153
|
exports.ui = ui;
|
|
1127
1154
|
exports.validate = validate;
|
package/dist/index.d.ts
CHANGED
|
@@ -234,15 +234,18 @@ interface FieldDefinition {
|
|
|
234
234
|
comment?: string;
|
|
235
235
|
decorators?: Record<string, Record<string, any>>;
|
|
236
236
|
}
|
|
237
|
-
interface
|
|
237
|
+
interface ComputedContextGlobal {
|
|
238
238
|
db: RadsDb;
|
|
239
239
|
schema: Schema;
|
|
240
|
-
typeName: string;
|
|
241
240
|
validators: SchemaValidators;
|
|
242
241
|
options: CreateRadsArgs;
|
|
243
242
|
drivers: Record<string, Driver>;
|
|
244
243
|
effects: Record<string, PutEffect[]>;
|
|
245
244
|
}
|
|
245
|
+
interface ComputedContext extends ComputedContextGlobal {
|
|
246
|
+
typeName: string;
|
|
247
|
+
handle: string;
|
|
248
|
+
}
|
|
246
249
|
interface PutEffect {
|
|
247
250
|
beforePut?: (computedContext: ComputedContext, docs: {
|
|
248
251
|
oldDoc: any;
|
|
@@ -290,6 +293,11 @@ interface RadsRequestContext {
|
|
|
290
293
|
silent?: boolean;
|
|
291
294
|
/** 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 */
|
|
292
295
|
skipPrecomputedCheckFor?: string;
|
|
296
|
+
/** Mostly for internal use. Method that was called - get, getAll, getMany, getAgg, put, putMany, etc */
|
|
297
|
+
method?: string;
|
|
298
|
+
/** if true, all cache layers will be bypassed */
|
|
299
|
+
noCache?: boolean;
|
|
300
|
+
[key: string]: any;
|
|
293
301
|
}
|
|
294
302
|
interface FileSystemNode {
|
|
295
303
|
path: string;
|
|
@@ -298,7 +306,9 @@ interface FileSystemNode {
|
|
|
298
306
|
}
|
|
299
307
|
interface RadsFeature {
|
|
300
308
|
name: string;
|
|
301
|
-
|
|
309
|
+
init?: (db: Record<string, any>, context: ComputedContextGlobal) => void;
|
|
310
|
+
enhanceEntityMethods?: (context: ComputedContext, entityMethodsObj: EntityMethods<any, any, any>) => void;
|
|
311
|
+
beforeGet?: (args: GetArgsAny, ctx: RadsRequestContext, context: ComputedContext) => MaybePromise<any>;
|
|
302
312
|
afterGet?: (items: any[], args: GetArgsAny, ctx: RadsRequestContext, context: ComputedContext) => MaybePromise<void>;
|
|
303
313
|
beforePut?: (items: {
|
|
304
314
|
oldDoc: any;
|
|
@@ -317,6 +327,8 @@ declare function field(meta?: FieldDecoratorArgs): (a: any, b?: ClassFieldDecora
|
|
|
317
327
|
declare function precomputed(meta?: ComputedDecoratorArgs): (a: any, b?: ClassFieldDecoratorContext | ClassDecoratorContext) => void;
|
|
318
328
|
declare function computed(meta?: ComputedDecoratorArgs): (a: any, b?: ClassFieldDecoratorContext | ClassDecoratorContext) => void;
|
|
319
329
|
|
|
330
|
+
declare function getDriverInstance(schema: Schema, key: string, driver: DriverConstructor, drivers: Record<string, Driver>): Driver;
|
|
331
|
+
|
|
320
332
|
declare function createRads(args?: CreateRadsArgs): RadsDb;
|
|
321
333
|
|
|
322
|
-
export { Change, ComputedContext, ComputedDecoratorArgs, CreateRadsArgs, DeepPartial, Driver, DriverConstructor, EntityDecoratorArgs, EntityMethods, FieldDecoratorArgs, FieldDefinition, FileSystemNode, FileUploadArgs, FileUploadDriver, GenerateClientNormalizedOptions, GenerateClientOptions, GetAggArgs, GetAggArgsAgg, GetAggArgsAny, GetAggResponse, GetArgs, GetArgsAny, GetArgsInclude, GetManyArgs, GetManyArgsAny, GetManyResponse, GetResponse, GetResponseInclude, GetResponseIncludeSelect, GetResponseNoInclude, GetRestRoutesArgs, GetRestRoutesOptions, GetRestRoutesResponse, MinimalDriver, PutArgs, PutEffect, RadsFeature, RadsRequestContext, RadsVitePluginOptions, Relation, RestFileUploadDriverOptions, Schema, SchemaValidators, TypeDefinition, UiDecoratorArgs, UiFieldDecoratorArgs, ValidateEntityDecoratorArgs, ValidateFieldDecoratorArgs, ValidateStringDecoratorArgs, VerifyManyArgs, VerifyManyArgsAny, VerifyManyResponse, computed, createRads, entity, field, precomputed, ui, validate };
|
|
334
|
+
export { Change, ComputedContext, ComputedContextGlobal, ComputedDecoratorArgs, CreateRadsArgs, DeepPartial, Driver, DriverConstructor, EntityDecoratorArgs, EntityMethods, FieldDecoratorArgs, FieldDefinition, FileSystemNode, FileUploadArgs, FileUploadDriver, GenerateClientNormalizedOptions, GenerateClientOptions, GetAggArgs, GetAggArgsAgg, GetAggArgsAny, GetAggResponse, GetArgs, GetArgsAny, GetArgsInclude, GetManyArgs, GetManyArgsAny, GetManyResponse, GetResponse, GetResponseInclude, GetResponseIncludeSelect, GetResponseNoInclude, GetRestRoutesArgs, GetRestRoutesOptions, GetRestRoutesResponse, MinimalDriver, PutArgs, PutEffect, RadsFeature, RadsRequestContext, RadsVitePluginOptions, Relation, RestFileUploadDriverOptions, Schema, SchemaValidators, TypeDefinition, UiDecoratorArgs, UiFieldDecoratorArgs, ValidateEntityDecoratorArgs, ValidateFieldDecoratorArgs, ValidateStringDecoratorArgs, VerifyManyArgs, VerifyManyArgsAny, VerifyManyResponse, computed, createRads, entity, field, getDriverInstance, precomputed, ui, validate };
|
package/dist/index.mjs
CHANGED
|
@@ -124,23 +124,26 @@ const operatorFns = {
|
|
|
124
124
|
}
|
|
125
125
|
};
|
|
126
126
|
const memory = (options) => (schema, entity) => {
|
|
127
|
-
let
|
|
127
|
+
let itemsById = {};
|
|
128
128
|
function getItemById(id) {
|
|
129
|
-
return
|
|
129
|
+
return itemsById[id] ?? null;
|
|
130
130
|
}
|
|
131
131
|
function getItemByIds(ids) {
|
|
132
|
-
return ids.map((id) =>
|
|
132
|
+
return ids.map((id) => itemsById[id]);
|
|
133
133
|
}
|
|
134
134
|
const instance = {
|
|
135
135
|
driverName: "memory",
|
|
136
|
+
get itemsById() {
|
|
137
|
+
return itemsById;
|
|
138
|
+
},
|
|
136
139
|
clear() {
|
|
137
|
-
|
|
140
|
+
itemsById = {};
|
|
138
141
|
},
|
|
139
142
|
putMany(items) {
|
|
140
143
|
for (const item of items) {
|
|
141
144
|
if (!item?.id)
|
|
142
145
|
throw new Error(`You must provide an id`);
|
|
143
|
-
|
|
146
|
+
itemsById[item.id] = item;
|
|
144
147
|
}
|
|
145
148
|
},
|
|
146
149
|
getMany(args) {
|
|
@@ -153,7 +156,7 @@ const memory = (options) => (schema, entity) => {
|
|
|
153
156
|
if (whereKeys[0] === "id_in")
|
|
154
157
|
return { nodes: _.cloneDeep(getItemByIds(where.id_in).filter((x) => x)), cursor: null };
|
|
155
158
|
}
|
|
156
|
-
return queryArray(Object.values(
|
|
159
|
+
return queryArray(Object.values(itemsById), args);
|
|
157
160
|
}
|
|
158
161
|
};
|
|
159
162
|
return instance;
|
|
@@ -260,7 +263,7 @@ function getFilterInner(operator, whereVal, name, namePrefix) {
|
|
|
260
263
|
if (operatorFn) {
|
|
261
264
|
return (x) => operatorFn(_.get(x, name), whereVal);
|
|
262
265
|
}
|
|
263
|
-
console.warn(`[rads-
|
|
266
|
+
console.warn(`[rads-db] Operator not supported: ${operator || "eq"}`);
|
|
264
267
|
return null;
|
|
265
268
|
}
|
|
266
269
|
function prepareArgs(args) {
|
|
@@ -698,14 +701,15 @@ function getRadsDbMethods(key, computedContext, driverInstance) {
|
|
|
698
701
|
const { precomputedFields } = schema[key];
|
|
699
702
|
async function getMany(args, ctx) {
|
|
700
703
|
args = { ...args, where: { ...args?.where } };
|
|
701
|
-
ctx = { ...options.context, ...ctx };
|
|
702
|
-
await beforeGet(args, ctx, computedContext);
|
|
703
|
-
|
|
704
|
+
ctx = { ...options.context, ...ctx, method: "getMany" };
|
|
705
|
+
let result2 = await beforeGet(args, ctx, computedContext);
|
|
706
|
+
if (!result2)
|
|
707
|
+
result2 = await driverInstance.getMany(args, ctx);
|
|
704
708
|
if (args.include)
|
|
705
|
-
await handleInclude(computedContext, args.include,
|
|
706
|
-
await handleComputed(computedContext,
|
|
707
|
-
await afterGet(
|
|
708
|
-
return
|
|
709
|
+
await handleInclude(computedContext, args.include, result2.nodes, ctx);
|
|
710
|
+
await handleComputed(computedContext, result2.nodes, ctx);
|
|
711
|
+
await afterGet(result2.nodes, args, ctx, computedContext);
|
|
712
|
+
return result2;
|
|
709
713
|
}
|
|
710
714
|
async function putMany(docs, ctx) {
|
|
711
715
|
const precomputed = schema[key].decorators.precomputed;
|
|
@@ -719,7 +723,7 @@ function getRadsDbMethods(key, computedContext, driverInstance) {
|
|
|
719
723
|
throw new Error("Id is required");
|
|
720
724
|
return i.id;
|
|
721
725
|
});
|
|
722
|
-
ctx = { ...options.context, ...ctx };
|
|
726
|
+
ctx = { ...options.context, ...ctx, method: "putMany" };
|
|
723
727
|
const oldDocs = await driverInstance.getAll({ where: { id_in: ids } }, ctx);
|
|
724
728
|
const oldDocsById = _.keyBy(oldDocs, "id");
|
|
725
729
|
const docArgsToSave = docs.map((doc) => {
|
|
@@ -746,7 +750,10 @@ function getRadsDbMethods(key, computedContext, driverInstance) {
|
|
|
746
750
|
await afterPut(docArgsToSave, ctx, computedContext);
|
|
747
751
|
return docsToSave;
|
|
748
752
|
}
|
|
749
|
-
|
|
753
|
+
const result = {
|
|
754
|
+
createObject() {
|
|
755
|
+
throw new Error("Not implemented");
|
|
756
|
+
},
|
|
750
757
|
getMany,
|
|
751
758
|
putMany,
|
|
752
759
|
driver: driverInstance,
|
|
@@ -754,34 +761,37 @@ function getRadsDbMethods(key, computedContext, driverInstance) {
|
|
|
754
761
|
args = { ...args, where: { ...args?.where } };
|
|
755
762
|
if (!args.agg)
|
|
756
763
|
throw new Error(`Please provide 'agg' argument`);
|
|
757
|
-
ctx = { ...options.context, ...ctx };
|
|
758
|
-
await beforeGet(args, ctx, computedContext);
|
|
759
|
-
|
|
760
|
-
|
|
764
|
+
ctx = { ...options.context, ...ctx, method: "getAgg" };
|
|
765
|
+
let result2 = await beforeGet(args, ctx, computedContext);
|
|
766
|
+
if (!result2)
|
|
767
|
+
result2 = await driverInstance.getAgg(args, ctx);
|
|
768
|
+
return result2;
|
|
761
769
|
},
|
|
762
770
|
get: async (args, ctx) => {
|
|
763
771
|
args = { ...args, where: { ...args?.where } };
|
|
764
|
-
ctx = { ...options.context, ...ctx };
|
|
765
|
-
await beforeGet(args, ctx, computedContext);
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
772
|
+
ctx = { ...options.context, ...ctx, method: "get" };
|
|
773
|
+
let result2 = await beforeGet(args, ctx, computedContext);
|
|
774
|
+
if (!result2)
|
|
775
|
+
result2 = await driverInstance.get(args, ctx);
|
|
776
|
+
const resultArray = result2 ? [result2] : [];
|
|
777
|
+
if (result2 && args.include)
|
|
769
778
|
await handleInclude(computedContext, args.include, resultArray, ctx);
|
|
770
|
-
if (
|
|
779
|
+
if (result2)
|
|
771
780
|
await handleComputed(computedContext, resultArray, ctx);
|
|
772
781
|
await afterGet(resultArray, args, ctx, computedContext);
|
|
773
|
-
return
|
|
782
|
+
return result2;
|
|
774
783
|
},
|
|
775
784
|
getAll: async (args, ctx) => {
|
|
776
785
|
args = { ...args, where: { ...args?.where } };
|
|
777
|
-
ctx = { ...options.context, ...ctx };
|
|
778
|
-
await beforeGet(args, ctx, computedContext);
|
|
779
|
-
|
|
786
|
+
ctx = { ...options.context, ...ctx, method: "getAll" };
|
|
787
|
+
let result2 = await beforeGet(args, ctx, computedContext);
|
|
788
|
+
if (!result2)
|
|
789
|
+
result2 = await driverInstance.getAll(args, ctx);
|
|
780
790
|
if (args.include)
|
|
781
|
-
await handleInclude(computedContext, args.include,
|
|
782
|
-
await handleComputed(computedContext,
|
|
783
|
-
await afterGet(
|
|
784
|
-
return
|
|
791
|
+
await handleInclude(computedContext, args.include, result2, ctx);
|
|
792
|
+
await handleComputed(computedContext, result2, ctx);
|
|
793
|
+
await afterGet(result2, args, ctx, computedContext);
|
|
794
|
+
return result2;
|
|
785
795
|
},
|
|
786
796
|
put: async (doc, ctx) => {
|
|
787
797
|
const precomputed = schema[key].decorators.precomputed;
|
|
@@ -874,10 +884,17 @@ function getRadsDbMethods(key, computedContext, driverInstance) {
|
|
|
874
884
|
return driverInstance.clear(ctx);
|
|
875
885
|
}
|
|
876
886
|
};
|
|
887
|
+
for (const f of options.features) {
|
|
888
|
+
if (f.enhanceEntityMethods)
|
|
889
|
+
f.enhanceEntityMethods(computedContext, result);
|
|
890
|
+
}
|
|
891
|
+
return result;
|
|
877
892
|
}
|
|
878
893
|
async function beforeGet(args, ctx, computedContext) {
|
|
879
894
|
for (const f of computedContext.options.features) {
|
|
880
|
-
await f.beforeGet?.(args, ctx, computedContext);
|
|
895
|
+
const result = await f.beforeGet?.(args, ctx, computedContext);
|
|
896
|
+
if (result)
|
|
897
|
+
return result;
|
|
881
898
|
}
|
|
882
899
|
}
|
|
883
900
|
async function afterGet(items, args, ctx, computedContext) {
|
|
@@ -973,6 +990,14 @@ function generateMethods(schema, validators, options) {
|
|
|
973
990
|
}
|
|
974
991
|
verifyEventSourcingSetup(schema, effects);
|
|
975
992
|
verifyRelationsSetup(schema, effects);
|
|
993
|
+
const computedContextGlobal = {
|
|
994
|
+
schema,
|
|
995
|
+
validators,
|
|
996
|
+
options: opts,
|
|
997
|
+
drivers,
|
|
998
|
+
effects,
|
|
999
|
+
db
|
|
1000
|
+
};
|
|
976
1001
|
for (const key in schema) {
|
|
977
1002
|
if (!schema[key].decorators.entity)
|
|
978
1003
|
continue;
|
|
@@ -980,17 +1005,17 @@ function generateMethods(schema, validators, options) {
|
|
|
980
1005
|
if (!handle)
|
|
981
1006
|
throw new Error(`Missing handle for entity ${key}`);
|
|
982
1007
|
const computedContext = {
|
|
983
|
-
|
|
1008
|
+
...computedContextGlobal,
|
|
984
1009
|
typeName: key,
|
|
985
|
-
|
|
986
|
-
options: opts,
|
|
987
|
-
drivers,
|
|
988
|
-
effects,
|
|
989
|
-
db
|
|
1010
|
+
handle: schema[key].handle
|
|
990
1011
|
};
|
|
991
1012
|
const driverInstance = getDriverInstance(schema, key, opts.driver, drivers);
|
|
992
1013
|
db[handle] = getRadsDbMethods(key, computedContext, driverInstance);
|
|
993
1014
|
}
|
|
1015
|
+
for (const f of opts.features) {
|
|
1016
|
+
if (f.init)
|
|
1017
|
+
f.init(db, computedContextGlobal);
|
|
1018
|
+
}
|
|
994
1019
|
return db;
|
|
995
1020
|
}
|
|
996
1021
|
function getDriverInstance(schema, key, driver, drivers) {
|
|
@@ -1004,6 +1029,7 @@ function getDriverInstanceInner(schema, key, driverConstructor) {
|
|
|
1004
1029
|
addDryRunSupport(driverInstance, key);
|
|
1005
1030
|
async function getAll(args, ctx) {
|
|
1006
1031
|
const result = [];
|
|
1032
|
+
args = args || {};
|
|
1007
1033
|
let cursor = args.cursor;
|
|
1008
1034
|
let maxItemCount = args.maxItemCount || 1e3;
|
|
1009
1035
|
if (maxItemCount < 1e3)
|
|
@@ -1111,4 +1137,4 @@ function createRads(args) {
|
|
|
1111
1137
|
return generateMethods(s, validators, args);
|
|
1112
1138
|
}
|
|
1113
1139
|
|
|
1114
|
-
export { computed, createRads, entity, field, precomputed, ui, validate };
|
|
1140
|
+
export { computed, createRads, entity, field, getDriverInstance, precomputed, ui, validate };
|
package/drivers/memory.cjs
CHANGED
|
@@ -39,22 +39,25 @@ const operatorFns = {
|
|
|
39
39
|
}
|
|
40
40
|
};
|
|
41
41
|
var _default = options => (schema, entity) => {
|
|
42
|
-
let
|
|
42
|
+
let itemsById = {};
|
|
43
43
|
function getItemById(id) {
|
|
44
|
-
return
|
|
44
|
+
return itemsById[id] ?? null;
|
|
45
45
|
}
|
|
46
46
|
function getItemByIds(ids) {
|
|
47
|
-
return ids.map(id =>
|
|
47
|
+
return ids.map(id => itemsById[id]);
|
|
48
48
|
}
|
|
49
49
|
const instance = {
|
|
50
50
|
driverName: "memory",
|
|
51
|
+
get itemsById() {
|
|
52
|
+
return itemsById;
|
|
53
|
+
},
|
|
51
54
|
clear() {
|
|
52
|
-
|
|
55
|
+
itemsById = {};
|
|
53
56
|
},
|
|
54
57
|
putMany(items) {
|
|
55
58
|
for (const item of items) {
|
|
56
59
|
if (!item?.id) throw new Error(`You must provide an id`);
|
|
57
|
-
|
|
60
|
+
itemsById[item.id] = item;
|
|
58
61
|
}
|
|
59
62
|
},
|
|
60
63
|
getMany(args) {
|
|
@@ -71,7 +74,7 @@ var _default = options => (schema, entity) => {
|
|
|
71
74
|
cursor: null
|
|
72
75
|
};
|
|
73
76
|
}
|
|
74
|
-
return queryArray(Object.values(
|
|
77
|
+
return queryArray(Object.values(itemsById), args);
|
|
75
78
|
}
|
|
76
79
|
};
|
|
77
80
|
return instance;
|
|
@@ -169,7 +172,7 @@ function getFilterInner(operator, whereVal, name, namePrefix) {
|
|
|
169
172
|
if (operatorFn) {
|
|
170
173
|
return x => operatorFn(_lodash.default.get(x, name), whereVal);
|
|
171
174
|
}
|
|
172
|
-
console.warn(`[rads-
|
|
175
|
+
console.warn(`[rads-db] Operator not supported: ${operator || "eq"}`);
|
|
173
176
|
return null;
|
|
174
177
|
}
|
|
175
178
|
function prepareArgs(args) {
|
package/drivers/memory.mjs
CHANGED
|
@@ -31,23 +31,26 @@ const operatorFns = {
|
|
|
31
31
|
}
|
|
32
32
|
};
|
|
33
33
|
export default (options) => (schema, entity) => {
|
|
34
|
-
let
|
|
34
|
+
let itemsById = {};
|
|
35
35
|
function getItemById(id) {
|
|
36
|
-
return
|
|
36
|
+
return itemsById[id] ?? null;
|
|
37
37
|
}
|
|
38
38
|
function getItemByIds(ids) {
|
|
39
|
-
return ids.map((id) =>
|
|
39
|
+
return ids.map((id) => itemsById[id]);
|
|
40
40
|
}
|
|
41
41
|
const instance = {
|
|
42
42
|
driverName: "memory",
|
|
43
|
+
get itemsById() {
|
|
44
|
+
return itemsById;
|
|
45
|
+
},
|
|
43
46
|
clear() {
|
|
44
|
-
|
|
47
|
+
itemsById = {};
|
|
45
48
|
},
|
|
46
49
|
putMany(items) {
|
|
47
50
|
for (const item of items) {
|
|
48
51
|
if (!item?.id)
|
|
49
52
|
throw new Error(`You must provide an id`);
|
|
50
|
-
|
|
53
|
+
itemsById[item.id] = item;
|
|
51
54
|
}
|
|
52
55
|
},
|
|
53
56
|
getMany(args) {
|
|
@@ -60,7 +63,7 @@ export default (options) => (schema, entity) => {
|
|
|
60
63
|
if (whereKeys[0] === "id_in")
|
|
61
64
|
return { nodes: _.cloneDeep(getItemByIds(where.id_in).filter((x) => x)), cursor: null };
|
|
62
65
|
}
|
|
63
|
-
return queryArray(Object.values(
|
|
66
|
+
return queryArray(Object.values(itemsById), args);
|
|
64
67
|
}
|
|
65
68
|
};
|
|
66
69
|
return instance;
|
|
@@ -167,7 +170,7 @@ function getFilterInner(operator, whereVal, name, namePrefix) {
|
|
|
167
170
|
if (operatorFn) {
|
|
168
171
|
return (x) => operatorFn(_.get(x, name), whereVal);
|
|
169
172
|
}
|
|
170
|
-
console.warn(`[rads-
|
|
173
|
+
console.warn(`[rads-db] Operator not supported: ${operator || "eq"}`);
|
|
171
174
|
return null;
|
|
172
175
|
}
|
|
173
176
|
function prepareArgs(args) {
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
module.exports = void 0;
|
|
7
|
+
var _memory = _interopRequireDefault(require("@/drivers/memory"));
|
|
8
|
+
var _radsDb = require("rads-db");
|
|
9
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
10
|
+
var _default = options => {
|
|
11
|
+
const normalizedOptions = normalizeOptions(options);
|
|
12
|
+
const cacheDrivers = {};
|
|
13
|
+
const cacheStatus = {};
|
|
14
|
+
return {
|
|
15
|
+
name: "cache",
|
|
16
|
+
init(db, context) {
|
|
17
|
+
const entitiesToCache = Object.keys(normalizedOptions.entities);
|
|
18
|
+
const {
|
|
19
|
+
schema,
|
|
20
|
+
drivers
|
|
21
|
+
} = context;
|
|
22
|
+
for (const typeName of entitiesToCache) {
|
|
23
|
+
const handle = schema[typeName].handle;
|
|
24
|
+
const cacheEntityName = `Cache_${typeName}`;
|
|
25
|
+
schema[cacheEntityName] = {
|
|
26
|
+
...schema[typeName],
|
|
27
|
+
name: cacheEntityName,
|
|
28
|
+
handle: cacheEntityName,
|
|
29
|
+
handlePlural: `${cacheEntityName}s`
|
|
30
|
+
};
|
|
31
|
+
cacheDrivers[handle] = (0, _radsDb.getDriverInstance)(schema, cacheEntityName, normalizedOptions.driver, drivers);
|
|
32
|
+
cacheStatus[handle] = {
|
|
33
|
+
preloadStatus: normalizedOptions.preload ? "neverLoaded" : void 0
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
db.cache = {
|
|
37
|
+
drivers: cacheDrivers,
|
|
38
|
+
status: cacheStatus,
|
|
39
|
+
async preload() {
|
|
40
|
+
if (!entitiesToCache.length) {
|
|
41
|
+
console.warn('No entities found to preload. Please, add "preload: true" to your cache configuration.');
|
|
42
|
+
}
|
|
43
|
+
for (const typeName of entitiesToCache) {
|
|
44
|
+
const handle = schema[typeName].handle;
|
|
45
|
+
cacheStatus[handle].preloadStatus = "loading";
|
|
46
|
+
try {
|
|
47
|
+
const allData = await db[handle].getAll({}, {
|
|
48
|
+
noCache: true
|
|
49
|
+
});
|
|
50
|
+
const now = Date.now();
|
|
51
|
+
await cacheDrivers[handle].putMany(allData.map(item => ({
|
|
52
|
+
...item,
|
|
53
|
+
_cacheUpdatedAt: now
|
|
54
|
+
})));
|
|
55
|
+
cacheStatus[handle].preloadStatus = "upToDate";
|
|
56
|
+
} catch (e) {
|
|
57
|
+
cacheStatus[handle].preloadStatus = "error";
|
|
58
|
+
console.error(`Error preloading db.${handle}`, e);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
},
|
|
64
|
+
// enhanceEntityMethods(context, entityMethodsObj) {
|
|
65
|
+
// if (normalizedOptions.entities && !normalizedOptions.entities[context.typeName]) return
|
|
66
|
+
// const { typeName, schema, drivers } = context
|
|
67
|
+
// const cacheEntityName = `Cache_${typeName}`
|
|
68
|
+
// schema[cacheEntityName] = {
|
|
69
|
+
// ...schema[typeName],
|
|
70
|
+
// name: cacheEntityName,
|
|
71
|
+
// handle: cacheEntityName,
|
|
72
|
+
// handlePlural: `${cacheEntityName}s`,
|
|
73
|
+
// } // A bit of a hack. Maybe better approach is to adjust driver constructor to accept entityPrefix
|
|
74
|
+
// cacheDrivers[typeName] = getDriverInstance(schema, cacheEntityName, normalizedOptions.driver, drivers)
|
|
75
|
+
// const emo = entityMethodsObj as any
|
|
76
|
+
// emo.cache = {
|
|
77
|
+
// driver: cacheDrivers[typeName],
|
|
78
|
+
// }
|
|
79
|
+
// },
|
|
80
|
+
async beforeGet(args, ctx, context) {
|
|
81
|
+
if (ctx.noCache) return;
|
|
82
|
+
const {
|
|
83
|
+
handle
|
|
84
|
+
} = context;
|
|
85
|
+
const d = cacheDrivers[handle];
|
|
86
|
+
if (!d) return;
|
|
87
|
+
if (ctx.method === "get") {
|
|
88
|
+
const result2 = await d[ctx.method](args, ctx);
|
|
89
|
+
if (!result2) return;
|
|
90
|
+
const ageMs = Date.now() - result2._cacheUpdatedAt;
|
|
91
|
+
const maxAge = ctx.maxAge ?? normalizedOptions.maxAge;
|
|
92
|
+
const staleWhileRevalidate = ctx.staleWhileRevalidate ?? normalizedOptions.staleWhileRevalidate;
|
|
93
|
+
if (maxAge !== -1 && (maxAge === 0 || ageMs > maxAge * 1e3)) {
|
|
94
|
+
if (staleWhileRevalidate !== 0 && (staleWhileRevalidate === -1 || ageMs <= staleWhileRevalidate * 1e3)) {
|
|
95
|
+
const db = context.db;
|
|
96
|
+
await context.db[handle].get(args, {
|
|
97
|
+
maxAge: 0,
|
|
98
|
+
staleWhileRevalidate: 0
|
|
99
|
+
});
|
|
100
|
+
return result2;
|
|
101
|
+
}
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
return result2;
|
|
105
|
+
}
|
|
106
|
+
if (cacheStatus[handle].preloadStatus !== "upToDate") return;
|
|
107
|
+
const result = await d[ctx.method](args, ctx);
|
|
108
|
+
return result;
|
|
109
|
+
},
|
|
110
|
+
async afterGet(items, args, ctx, context) {
|
|
111
|
+
const {
|
|
112
|
+
handle
|
|
113
|
+
} = context;
|
|
114
|
+
const d = cacheDrivers[handle];
|
|
115
|
+
if (!d || !items?.length) return;
|
|
116
|
+
if (items[0]._cacheUpdatedAt) return;
|
|
117
|
+
const now = Date.now();
|
|
118
|
+
await d.putMany(items.map(item => ({
|
|
119
|
+
...item,
|
|
120
|
+
_cacheUpdatedAt: now
|
|
121
|
+
})));
|
|
122
|
+
},
|
|
123
|
+
async afterPut(items, ctx, computedContext) {
|
|
124
|
+
const {
|
|
125
|
+
handle
|
|
126
|
+
} = computedContext;
|
|
127
|
+
const d = cacheDrivers[handle];
|
|
128
|
+
if (!d) return;
|
|
129
|
+
const now = Date.now();
|
|
130
|
+
await d.putMany(items.map(item => item.doc).map(item => ({
|
|
131
|
+
...item,
|
|
132
|
+
_cacheUpdatedAt: now
|
|
133
|
+
})));
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
};
|
|
137
|
+
module.exports = _default;
|
|
138
|
+
function normalizeOptions(options) {
|
|
139
|
+
return {
|
|
140
|
+
driver: (0, _memory.default)(),
|
|
141
|
+
maxAge: 300,
|
|
142
|
+
staleWhileRevalidate: 0,
|
|
143
|
+
entities: {},
|
|
144
|
+
...options
|
|
145
|
+
};
|
|
146
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { DriverConstructor } from '@/types';
|
|
2
|
+
declare const _default: (options?: CacheOptions) => RadsFeature;
|
|
3
|
+
export default _default;
|
|
4
|
+
export interface CacheOptions {
|
|
5
|
+
entities: Record<string, boolean>;
|
|
6
|
+
driver?: DriverConstructor;
|
|
7
|
+
/**
|
|
8
|
+
* Number in seconds. If document was stored in cache more than maxAge seconds ago, cache is ignored.
|
|
9
|
+
* 0 = 0s = all documents immediately expire, so never get anything from cache.
|
|
10
|
+
* -1 = infinity = documents never expire (always returned from cache if exist)
|
|
11
|
+
* defaults to 300 (5 minutes)
|
|
12
|
+
* */
|
|
13
|
+
maxAge?: number;
|
|
14
|
+
/**
|
|
15
|
+
* Number in seconds.
|
|
16
|
+
* If document was stored in cache more than staleWhileRevalidate seconds ago, cache is ignored.
|
|
17
|
+
* If document was stored in cache less than staleWhileRevalidate seconds ago,
|
|
18
|
+
* but more than maxAge seconds ago, it is immediately returned form cache, but also is downloaded again in the background.
|
|
19
|
+
* 0 = 0s = documents are never revalidated in background
|
|
20
|
+
* -1 = infinity = documents always are returned from cache immediately and revalidated in background
|
|
21
|
+
* defaults to 0
|
|
22
|
+
* */
|
|
23
|
+
staleWhileRevalidate?: number;
|
|
24
|
+
/**
|
|
25
|
+
* Start preloading all data into cache immediately in the background.
|
|
26
|
+
* After data are preloaded, getAll/getMany queries will start working from cache as well.
|
|
27
|
+
* If your driver already contains data, "preload" will download only newly changed records (based on `updatedAt`)
|
|
28
|
+
*/
|
|
29
|
+
preload?: boolean;
|
|
30
|
+
}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import memory from "@/drivers/memory";
|
|
2
|
+
import { getDriverInstance } from "rads-db";
|
|
3
|
+
export default (options) => {
|
|
4
|
+
const normalizedOptions = normalizeOptions(options);
|
|
5
|
+
const cacheDrivers = {};
|
|
6
|
+
const cacheStatus = {};
|
|
7
|
+
return {
|
|
8
|
+
name: "cache",
|
|
9
|
+
init(db, context) {
|
|
10
|
+
const entitiesToCache = Object.keys(normalizedOptions.entities);
|
|
11
|
+
const { schema, drivers } = context;
|
|
12
|
+
for (const typeName of entitiesToCache) {
|
|
13
|
+
const handle = schema[typeName].handle;
|
|
14
|
+
const cacheEntityName = `Cache_${typeName}`;
|
|
15
|
+
schema[cacheEntityName] = {
|
|
16
|
+
...schema[typeName],
|
|
17
|
+
name: cacheEntityName,
|
|
18
|
+
handle: cacheEntityName,
|
|
19
|
+
handlePlural: `${cacheEntityName}s`
|
|
20
|
+
};
|
|
21
|
+
cacheDrivers[handle] = getDriverInstance(schema, cacheEntityName, normalizedOptions.driver, drivers);
|
|
22
|
+
cacheStatus[handle] = { preloadStatus: normalizedOptions.preload ? "neverLoaded" : void 0 };
|
|
23
|
+
}
|
|
24
|
+
db.cache = {
|
|
25
|
+
drivers: cacheDrivers,
|
|
26
|
+
status: cacheStatus,
|
|
27
|
+
async preload() {
|
|
28
|
+
if (!entitiesToCache.length) {
|
|
29
|
+
console.warn('No entities found to preload. Please, add "preload: true" to your cache configuration.');
|
|
30
|
+
}
|
|
31
|
+
for (const typeName of entitiesToCache) {
|
|
32
|
+
const handle = schema[typeName].handle;
|
|
33
|
+
cacheStatus[handle].preloadStatus = "loading";
|
|
34
|
+
try {
|
|
35
|
+
const allData = await db[handle].getAll({}, { noCache: true });
|
|
36
|
+
const now = Date.now();
|
|
37
|
+
await cacheDrivers[handle].putMany(allData.map((item) => ({ ...item, _cacheUpdatedAt: now })));
|
|
38
|
+
cacheStatus[handle].preloadStatus = "upToDate";
|
|
39
|
+
} catch (e) {
|
|
40
|
+
cacheStatus[handle].preloadStatus = "error";
|
|
41
|
+
console.error(`Error preloading db.${handle}`, e);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
},
|
|
47
|
+
// enhanceEntityMethods(context, entityMethodsObj) {
|
|
48
|
+
// if (normalizedOptions.entities && !normalizedOptions.entities[context.typeName]) return
|
|
49
|
+
// const { typeName, schema, drivers } = context
|
|
50
|
+
// const cacheEntityName = `Cache_${typeName}`
|
|
51
|
+
// schema[cacheEntityName] = {
|
|
52
|
+
// ...schema[typeName],
|
|
53
|
+
// name: cacheEntityName,
|
|
54
|
+
// handle: cacheEntityName,
|
|
55
|
+
// handlePlural: `${cacheEntityName}s`,
|
|
56
|
+
// } // A bit of a hack. Maybe better approach is to adjust driver constructor to accept entityPrefix
|
|
57
|
+
// cacheDrivers[typeName] = getDriverInstance(schema, cacheEntityName, normalizedOptions.driver, drivers)
|
|
58
|
+
// const emo = entityMethodsObj as any
|
|
59
|
+
// emo.cache = {
|
|
60
|
+
// driver: cacheDrivers[typeName],
|
|
61
|
+
// }
|
|
62
|
+
// },
|
|
63
|
+
async beforeGet(args, ctx, context) {
|
|
64
|
+
if (ctx.noCache)
|
|
65
|
+
return;
|
|
66
|
+
const { handle } = context;
|
|
67
|
+
const d = cacheDrivers[handle];
|
|
68
|
+
if (!d)
|
|
69
|
+
return;
|
|
70
|
+
if (ctx.method === "get") {
|
|
71
|
+
const result2 = await d[ctx.method](args, ctx);
|
|
72
|
+
if (!result2)
|
|
73
|
+
return;
|
|
74
|
+
const ageMs = Date.now() - result2._cacheUpdatedAt;
|
|
75
|
+
const maxAge = ctx.maxAge ?? normalizedOptions.maxAge;
|
|
76
|
+
const staleWhileRevalidate = ctx.staleWhileRevalidate ?? normalizedOptions.staleWhileRevalidate;
|
|
77
|
+
if (maxAge !== -1 && (maxAge === 0 || ageMs > maxAge * 1e3)) {
|
|
78
|
+
if (staleWhileRevalidate !== 0 && (staleWhileRevalidate === -1 || ageMs <= staleWhileRevalidate * 1e3)) {
|
|
79
|
+
const db = context.db;
|
|
80
|
+
await context.db[handle].get(args, {
|
|
81
|
+
maxAge: 0,
|
|
82
|
+
staleWhileRevalidate: 0
|
|
83
|
+
});
|
|
84
|
+
return result2;
|
|
85
|
+
}
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
return result2;
|
|
89
|
+
}
|
|
90
|
+
if (cacheStatus[handle].preloadStatus !== "upToDate")
|
|
91
|
+
return;
|
|
92
|
+
const result = await d[ctx.method](args, ctx);
|
|
93
|
+
return result;
|
|
94
|
+
},
|
|
95
|
+
async afterGet(items, args, ctx, context) {
|
|
96
|
+
const { handle } = context;
|
|
97
|
+
const d = cacheDrivers[handle];
|
|
98
|
+
if (!d || !items?.length)
|
|
99
|
+
return;
|
|
100
|
+
if (items[0]._cacheUpdatedAt)
|
|
101
|
+
return;
|
|
102
|
+
const now = Date.now();
|
|
103
|
+
await d.putMany(items.map((item) => ({ ...item, _cacheUpdatedAt: now })));
|
|
104
|
+
},
|
|
105
|
+
async afterPut(items, ctx, computedContext) {
|
|
106
|
+
const { handle } = computedContext;
|
|
107
|
+
const d = cacheDrivers[handle];
|
|
108
|
+
if (!d)
|
|
109
|
+
return;
|
|
110
|
+
const now = Date.now();
|
|
111
|
+
await d.putMany(items.map((item) => item.doc).map((item) => ({ ...item, _cacheUpdatedAt: now })));
|
|
112
|
+
}
|
|
113
|
+
};
|
|
114
|
+
};
|
|
115
|
+
function normalizeOptions(options) {
|
|
116
|
+
return {
|
|
117
|
+
driver: memory(),
|
|
118
|
+
maxAge: 300,
|
|
119
|
+
staleWhileRevalidate: 0,
|
|
120
|
+
entities: {},
|
|
121
|
+
...options
|
|
122
|
+
};
|
|
123
|
+
}
|
package/integrations/node.cjs
CHANGED
|
@@ -150,7 +150,7 @@ function getWhereFieldsFor(schema, type, fieldKey) {
|
|
|
150
150
|
throw new Error(`Unknown array type: ${fieldTypeName}`);
|
|
151
151
|
}
|
|
152
152
|
const commonWhereFields = [];
|
|
153
|
-
if (isRequired) commonWhereFields.push(`${name}_isNull?: boolean`);
|
|
153
|
+
if (!isRequired) commonWhereFields.push(`${name}_isNull?: boolean`);
|
|
154
154
|
if (isRelation) {
|
|
155
155
|
return [`${name}?: ${getRelationWhereType()}`, ...commonWhereFields];
|
|
156
156
|
}
|
package/integrations/node.mjs
CHANGED
|
@@ -156,7 +156,7 @@ function getWhereFieldsFor(schema, type, fieldKey) {
|
|
|
156
156
|
throw new Error(`Unknown array type: ${fieldTypeName}`);
|
|
157
157
|
}
|
|
158
158
|
const commonWhereFields = [];
|
|
159
|
-
if (isRequired)
|
|
159
|
+
if (!isRequired)
|
|
160
160
|
commonWhereFields.push(`${name}_isNull?: boolean`);
|
|
161
161
|
if (isRelation) {
|
|
162
162
|
return [`${name}?: ${getRelationWhereType()}`, ...commonWhereFields];
|
|
@@ -14,6 +14,10 @@ var _default = {
|
|
|
14
14
|
sanitizeFilepath(filepath);
|
|
15
15
|
return await _promises.default.mkdir(filepath, options);
|
|
16
16
|
},
|
|
17
|
+
async rm(filepath, options) {
|
|
18
|
+
sanitizeFilepath(filepath);
|
|
19
|
+
return await _promises.default.rm(filepath, options);
|
|
20
|
+
},
|
|
17
21
|
async rmdir(filepath, options) {
|
|
18
22
|
sanitizeFilepath(filepath);
|
|
19
23
|
return await _promises.default.rmdir(filepath, options);
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { FileSystemNode } from '../types';
|
|
2
2
|
declare const _default: {
|
|
3
3
|
mkdir(filepath: string, options?: any): Promise<any>;
|
|
4
|
+
rm(filepath: string, options?: any): Promise<any>;
|
|
4
5
|
rmdir(filepath: string, options?: any): Promise<any>;
|
|
5
6
|
readdir(filepath: string, options?: any): Promise<FileSystemNode[]>;
|
|
6
7
|
writeFile(filepath: string, data: string | Uint8Array, options?: any): Promise<any>;
|
|
@@ -7,6 +7,10 @@ export default {
|
|
|
7
7
|
sanitizeFilepath(filepath);
|
|
8
8
|
return await fs.mkdir(filepath, options);
|
|
9
9
|
},
|
|
10
|
+
async rm(filepath, options) {
|
|
11
|
+
sanitizeFilepath(filepath);
|
|
12
|
+
return await fs.rm(filepath, options);
|
|
13
|
+
},
|
|
10
14
|
async rmdir(filepath, options) {
|
|
11
15
|
sanitizeFilepath(filepath);
|
|
12
16
|
return await fs.rmdir(filepath, options);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "rads-db",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.94",
|
|
4
4
|
"files": [
|
|
5
5
|
"dist",
|
|
6
6
|
"drivers",
|
|
@@ -95,7 +95,7 @@
|
|
|
95
95
|
"test": "vitest --run && vitest typecheck --run",
|
|
96
96
|
"link-rads-db": "symlink-dir ./test/_rads-db ./node_modules/_rads-db",
|
|
97
97
|
"generate-test-schema": "rads-db",
|
|
98
|
-
"dev": "pnpm install && pnpm build && pnpm generate-test-schema && pnpm link-rads-db && vitest --ui",
|
|
98
|
+
"dev": "pnpm install && pnpm build && pnpm generate-test-schema && pnpm link-rads-db && vitest --ui --test-timeout 300000",
|
|
99
99
|
"lint": "cross-env NODE_ENV=production eslint src/**/*.* test/**/*.*",
|
|
100
100
|
"dev-typecheck": "pnpm install && pnpm build && pnpm generate-test-schema && pnpm link-rads-db && vitest typecheck --ui",
|
|
101
101
|
"build": "unbuild"
|