rads-db 0.1.0 → 0.1.2
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 +91 -18
- package/dist/index.d.ts +9 -4
- package/dist/index.mjs +91 -18
- package/drivers/memory.cjs +175 -0
- package/drivers/memory.d.ts +8 -0
- package/drivers/memory.mjs +161 -0
- package/drivers/restApi.cjs +37 -0
- package/drivers/restApi.d.ts +5 -0
- package/drivers/restApi.mjs +24 -0
- package/integrations/node.cjs +213 -0
- package/integrations/node.d.ts +1 -0
- package/integrations/node.mjs +168 -0
- package/integrations/nuxtModule.cjs +25 -0
- package/integrations/nuxtModule.d.ts +1 -0
- package/integrations/nuxtModule.mjs +16 -0
- package/integrations/nuxtModuleHandler.cjs +38 -0
- package/integrations/nuxtModuleHandler.d.ts +6 -0
- package/integrations/nuxtModuleHandler.mjs +28 -0
- package/integrations/vite.cjs +37 -0
- package/integrations/vite.d.ts +6 -0
- package/integrations/vite.mjs +31 -0
- package/package.json +4 -2
package/dist/index.cjs
CHANGED
|
@@ -31,27 +31,30 @@ function getZodSchema(zodSchemas, schema, key) {
|
|
|
31
31
|
}
|
|
32
32
|
const objectSchema = {};
|
|
33
33
|
for (const fieldName in type.fields) {
|
|
34
|
-
|
|
34
|
+
const shouldBeLazy = type.fields[fieldName].type === type.name;
|
|
35
|
+
objectSchema[fieldName] = getFieldZodSchema(zodSchemas, schema, type.fields[fieldName], shouldBeLazy);
|
|
35
36
|
}
|
|
36
37
|
return zod.z.object(objectSchema);
|
|
37
38
|
}
|
|
38
|
-
function getFieldZodSchema(zodSchemas, schema, field) {
|
|
39
|
-
let fieldSchema = getFieldZodSchemaBase(zodSchemas, schema, field);
|
|
39
|
+
function getFieldZodSchema(zodSchemas, schema, field, shouldBeLazy) {
|
|
40
|
+
let fieldSchema = getFieldZodSchemaBase(zodSchemas, schema, field, shouldBeLazy);
|
|
40
41
|
if (!field.isRequired)
|
|
41
42
|
fieldSchema = fieldSchema.optional();
|
|
42
43
|
if (field.defaultValue !== void 0)
|
|
43
44
|
fieldSchema = fieldSchema.default(field.defaultValue);
|
|
44
45
|
return fieldSchema;
|
|
45
46
|
}
|
|
46
|
-
function getFieldZodSchemaBase(zodSchemas, schema, field) {
|
|
47
|
+
function getFieldZodSchemaBase(zodSchemas, schema, field, shouldBeLazy) {
|
|
47
48
|
if (field.type === "string")
|
|
48
49
|
return zod.z.string();
|
|
49
50
|
if (field.type === "boolean")
|
|
50
51
|
return zod.z.boolean();
|
|
51
52
|
if (field.type === "number")
|
|
52
53
|
return zod.z.number();
|
|
53
|
-
if (schema[field.type])
|
|
54
|
-
|
|
54
|
+
if (schema[field.type]) {
|
|
55
|
+
const getSchema = () => getZodSchema(zodSchemas, schema, field.type);
|
|
56
|
+
return shouldBeLazy ? zod.z.lazy(getSchema) : getSchema();
|
|
57
|
+
}
|
|
55
58
|
throw new Error(`Unknown type: ${field.type}`);
|
|
56
59
|
}
|
|
57
60
|
|
|
@@ -242,7 +245,7 @@ const restApi = (schema, entity, options) => {
|
|
|
242
245
|
const driverConstructors = { memory, restApi };
|
|
243
246
|
const drivers = {};
|
|
244
247
|
function generateMethods(schema, validators, args) {
|
|
245
|
-
const
|
|
248
|
+
const db = { _schema: schema };
|
|
246
249
|
for (const key in schema) {
|
|
247
250
|
if (!schema[key].decorators.entity)
|
|
248
251
|
continue;
|
|
@@ -250,32 +253,79 @@ function generateMethods(schema, validators, args) {
|
|
|
250
253
|
if (!handle)
|
|
251
254
|
throw new Error(`Missing handle for entity ${key}`);
|
|
252
255
|
const driverInstance = getDriverInstance(schema, key, args?.driver || { type: "memory" });
|
|
253
|
-
|
|
256
|
+
db[handle] = {
|
|
254
257
|
get: async (args2) => {
|
|
255
|
-
|
|
258
|
+
args2 = { ...args2, maxItemCount: 1 };
|
|
259
|
+
const result = (await driverInstance.getMany(args2))?.nodes[0] || null;
|
|
260
|
+
if (args2.include)
|
|
261
|
+
await handleInclude(schema, key, args2.include, [result]);
|
|
262
|
+
return result;
|
|
256
263
|
},
|
|
257
264
|
getMany: async (args2) => {
|
|
258
|
-
|
|
265
|
+
args2 = args2 || {};
|
|
266
|
+
const result = await driverInstance.getMany(args2);
|
|
267
|
+
if (args2.include)
|
|
268
|
+
await handleInclude(schema, key, args2.include, result.nodes);
|
|
269
|
+
return result;
|
|
270
|
+
},
|
|
271
|
+
getAll: async (args2) => {
|
|
272
|
+
args2 = args2 || {};
|
|
273
|
+
const result = await driverInstance.getAll(args2);
|
|
274
|
+
if (args2.include)
|
|
275
|
+
await handleInclude(schema, key, args2.include, result);
|
|
276
|
+
return result;
|
|
259
277
|
},
|
|
260
278
|
put: async (item) => {
|
|
261
|
-
console.log("validating", item);
|
|
262
279
|
item = validators[key](item);
|
|
263
280
|
await driverInstance.putMany([item]);
|
|
264
281
|
return item;
|
|
265
282
|
},
|
|
266
283
|
putMany: async (items) => {
|
|
267
|
-
console.log("validating", items);
|
|
268
284
|
const itemsToSave = items.map((item) => validators[key](item));
|
|
269
285
|
await driverInstance.putMany(itemsToSave);
|
|
270
286
|
return itemsToSave;
|
|
271
287
|
}
|
|
272
|
-
// putMany:
|
|
273
|
-
// deleteMany:
|
|
274
|
-
// updateMany:
|
|
275
|
-
// verifyMany:
|
|
276
288
|
};
|
|
277
289
|
}
|
|
278
|
-
return
|
|
290
|
+
return db;
|
|
291
|
+
}
|
|
292
|
+
async function handleInclude(schema, entityName, include, result) {
|
|
293
|
+
if (!result || !result.length || !include)
|
|
294
|
+
return;
|
|
295
|
+
const fields = schema[entityName].fields || {};
|
|
296
|
+
const relationsToInclude = ___default.keys(include).filter((key) => include[key] && schema[fields[key].type].decorators.entity);
|
|
297
|
+
const downloadRelationsPromises = relationsToInclude.map(async (fieldName) => {
|
|
298
|
+
const typeName = fields[fieldName].type;
|
|
299
|
+
const type = schema[typeName];
|
|
300
|
+
if (!type)
|
|
301
|
+
throw new Error(`Cannot find entity ${typeName}`);
|
|
302
|
+
const idsToGet = /* @__PURE__ */ new Set();
|
|
303
|
+
for (const item of result) {
|
|
304
|
+
const id = item[fieldName]?.id;
|
|
305
|
+
if (!id)
|
|
306
|
+
continue;
|
|
307
|
+
idsToGet.add(id);
|
|
308
|
+
}
|
|
309
|
+
const driverInstance = getExistingDriverInstance(typeName);
|
|
310
|
+
const relatedEntities = await driverInstance.getAll({ where: { id_in: [...idsToGet] } });
|
|
311
|
+
const relatedEntitiesById = ___default.keyBy(relatedEntities, "id");
|
|
312
|
+
for (const item of result) {
|
|
313
|
+
const id = item[fieldName]?.id;
|
|
314
|
+
if (!id)
|
|
315
|
+
continue;
|
|
316
|
+
const relatedEntity = relatedEntitiesById[id];
|
|
317
|
+
if (!relatedEntity)
|
|
318
|
+
console.warn(`Cannot find ${typeName} with id "${id}" (for ${entityName}.${fieldName} with id "${item.id}")`);
|
|
319
|
+
item[fieldName] = relatedEntity;
|
|
320
|
+
}
|
|
321
|
+
});
|
|
322
|
+
await Promise.all(downloadRelationsPromises);
|
|
323
|
+
}
|
|
324
|
+
function getExistingDriverInstance(entityName) {
|
|
325
|
+
if (!drivers[entityName]) {
|
|
326
|
+
throw new Error(`Driver for entity ${entityName} was not found!`);
|
|
327
|
+
}
|
|
328
|
+
return drivers[entityName];
|
|
279
329
|
}
|
|
280
330
|
function getDriverInstance(schema, key, driver) {
|
|
281
331
|
if (!drivers[key]) {
|
|
@@ -285,7 +335,30 @@ function getDriverInstance(schema, key, driver) {
|
|
|
285
335
|
}
|
|
286
336
|
function getDriverInstanceInner(schema, key, driver) {
|
|
287
337
|
const driverConstructor = driverConstructors[driver.type];
|
|
288
|
-
|
|
338
|
+
const driverInstance = driverConstructor(schema, key, driver);
|
|
339
|
+
return {
|
|
340
|
+
...driverInstance,
|
|
341
|
+
async getAll(args) {
|
|
342
|
+
const result = [];
|
|
343
|
+
let cursor = args.cursor;
|
|
344
|
+
let maxItemCount = args.maxItemCount || 1e3;
|
|
345
|
+
if (maxItemCount < 1e3)
|
|
346
|
+
maxItemCount = 1e3;
|
|
347
|
+
for (let i = 0; i < 1e3; i++) {
|
|
348
|
+
const response = await driverInstance.getMany({ ...args, cursor, maxItemCount });
|
|
349
|
+
result.push(...response.nodes);
|
|
350
|
+
cursor = response.cursor;
|
|
351
|
+
if (cursor && cursor === response.cursor) {
|
|
352
|
+
throw new Error(
|
|
353
|
+
"Something is wrong - request for next page has returned the same cursor as before. Make sure that getMany() processes pagination correctly"
|
|
354
|
+
);
|
|
355
|
+
}
|
|
356
|
+
if (!cursor)
|
|
357
|
+
break;
|
|
358
|
+
}
|
|
359
|
+
return result;
|
|
360
|
+
}
|
|
361
|
+
};
|
|
289
362
|
}
|
|
290
363
|
|
|
291
364
|
function entity(meta) {
|
package/dist/index.d.ts
CHANGED
|
@@ -23,28 +23,32 @@ interface TypeDefinition {
|
|
|
23
23
|
handlePlural?: string;
|
|
24
24
|
}
|
|
25
25
|
type MaybePromise<T> = Promise<T> | T;
|
|
26
|
-
interface
|
|
26
|
+
interface MinimalDriver {
|
|
27
27
|
putMany: <T extends Record<string, any>>(item: T[]) => MaybePromise<void>;
|
|
28
28
|
getMany: (args: GetManyArgs) => MaybePromise<{
|
|
29
29
|
nodes: Record<string, any>[];
|
|
30
30
|
cursor: string | null;
|
|
31
31
|
}>;
|
|
32
32
|
}
|
|
33
|
+
interface Driver extends MinimalDriver {
|
|
34
|
+
getAll: (args: GetManyArgs) => MaybePromise<Record<string, any>[]>;
|
|
35
|
+
}
|
|
33
36
|
interface FieldDefinition {
|
|
34
37
|
name: string;
|
|
35
38
|
type: string;
|
|
36
39
|
defaultValue?: any;
|
|
37
40
|
isRequired?: boolean;
|
|
38
41
|
comment?: string;
|
|
42
|
+
decorators?: Record<string, Record<string, any>>;
|
|
39
43
|
}
|
|
40
|
-
interface GetManyArgs {
|
|
41
|
-
where?: Record<string, any>;
|
|
44
|
+
interface GetManyArgs extends GetArgs {
|
|
42
45
|
orderBy?: string;
|
|
43
46
|
maxItemCount?: number;
|
|
44
47
|
cursor?: string;
|
|
45
48
|
}
|
|
46
49
|
interface GetArgs {
|
|
47
50
|
where?: Record<string, any>;
|
|
51
|
+
include?: Record<string, any>;
|
|
48
52
|
}
|
|
49
53
|
interface EntityMethods<T = Record<string, any>> {
|
|
50
54
|
get: (args: GetArgs) => Promise<T>;
|
|
@@ -52,6 +56,7 @@ interface EntityMethods<T = Record<string, any>> {
|
|
|
52
56
|
nodes: T[];
|
|
53
57
|
cursor: string | null;
|
|
54
58
|
}>;
|
|
59
|
+
getAll: (args: GetManyArgs) => Promise<T[]>;
|
|
55
60
|
put: (data: T) => Promise<T>;
|
|
56
61
|
putMany: (data: T[]) => Promise<T[]>;
|
|
57
62
|
}
|
|
@@ -80,4 +85,4 @@ declare function field(meta?: FieldDecoratorArgs): (a: any, b?: ClassFieldDecora
|
|
|
80
85
|
declare function createRads(args: CreateRadsArgs): RadsDb;
|
|
81
86
|
declare function getRestRoutes(db: radsDb, prefix?: string): Record<string, Record<string, Function>>;
|
|
82
87
|
|
|
83
|
-
export { CreateRadsArgs, Driver, DriverOptions, EntityDecoratorArgs, EntityMethods, FieldDecoratorArgs, FieldDefinition, GetArgs, GetManyArgs, MemoryDriverOptions, RadsDb, RestDriverOptions, Schema, SchemaValidators, TypeDefinition, createRads, entity, field, getRestRoutes, radsDb };
|
|
88
|
+
export { CreateRadsArgs, Driver, DriverOptions, EntityDecoratorArgs, EntityMethods, FieldDecoratorArgs, FieldDefinition, GetArgs, GetManyArgs, MemoryDriverOptions, MinimalDriver, RadsDb, RestDriverOptions, Schema, SchemaValidators, TypeDefinition, createRads, entity, field, getRestRoutes, radsDb };
|
package/dist/index.mjs
CHANGED
|
@@ -24,27 +24,30 @@ function getZodSchema(zodSchemas, schema, key) {
|
|
|
24
24
|
}
|
|
25
25
|
const objectSchema = {};
|
|
26
26
|
for (const fieldName in type.fields) {
|
|
27
|
-
|
|
27
|
+
const shouldBeLazy = type.fields[fieldName].type === type.name;
|
|
28
|
+
objectSchema[fieldName] = getFieldZodSchema(zodSchemas, schema, type.fields[fieldName], shouldBeLazy);
|
|
28
29
|
}
|
|
29
30
|
return z.object(objectSchema);
|
|
30
31
|
}
|
|
31
|
-
function getFieldZodSchema(zodSchemas, schema, field) {
|
|
32
|
-
let fieldSchema = getFieldZodSchemaBase(zodSchemas, schema, field);
|
|
32
|
+
function getFieldZodSchema(zodSchemas, schema, field, shouldBeLazy) {
|
|
33
|
+
let fieldSchema = getFieldZodSchemaBase(zodSchemas, schema, field, shouldBeLazy);
|
|
33
34
|
if (!field.isRequired)
|
|
34
35
|
fieldSchema = fieldSchema.optional();
|
|
35
36
|
if (field.defaultValue !== void 0)
|
|
36
37
|
fieldSchema = fieldSchema.default(field.defaultValue);
|
|
37
38
|
return fieldSchema;
|
|
38
39
|
}
|
|
39
|
-
function getFieldZodSchemaBase(zodSchemas, schema, field) {
|
|
40
|
+
function getFieldZodSchemaBase(zodSchemas, schema, field, shouldBeLazy) {
|
|
40
41
|
if (field.type === "string")
|
|
41
42
|
return z.string();
|
|
42
43
|
if (field.type === "boolean")
|
|
43
44
|
return z.boolean();
|
|
44
45
|
if (field.type === "number")
|
|
45
46
|
return z.number();
|
|
46
|
-
if (schema[field.type])
|
|
47
|
-
|
|
47
|
+
if (schema[field.type]) {
|
|
48
|
+
const getSchema = () => getZodSchema(zodSchemas, schema, field.type);
|
|
49
|
+
return shouldBeLazy ? z.lazy(getSchema) : getSchema();
|
|
50
|
+
}
|
|
48
51
|
throw new Error(`Unknown type: ${field.type}`);
|
|
49
52
|
}
|
|
50
53
|
|
|
@@ -235,7 +238,7 @@ const restApi = (schema, entity, options) => {
|
|
|
235
238
|
const driverConstructors = { memory, restApi };
|
|
236
239
|
const drivers = {};
|
|
237
240
|
function generateMethods(schema, validators, args) {
|
|
238
|
-
const
|
|
241
|
+
const db = { _schema: schema };
|
|
239
242
|
for (const key in schema) {
|
|
240
243
|
if (!schema[key].decorators.entity)
|
|
241
244
|
continue;
|
|
@@ -243,32 +246,79 @@ function generateMethods(schema, validators, args) {
|
|
|
243
246
|
if (!handle)
|
|
244
247
|
throw new Error(`Missing handle for entity ${key}`);
|
|
245
248
|
const driverInstance = getDriverInstance(schema, key, args?.driver || { type: "memory" });
|
|
246
|
-
|
|
249
|
+
db[handle] = {
|
|
247
250
|
get: async (args2) => {
|
|
248
|
-
|
|
251
|
+
args2 = { ...args2, maxItemCount: 1 };
|
|
252
|
+
const result = (await driverInstance.getMany(args2))?.nodes[0] || null;
|
|
253
|
+
if (args2.include)
|
|
254
|
+
await handleInclude(schema, key, args2.include, [result]);
|
|
255
|
+
return result;
|
|
249
256
|
},
|
|
250
257
|
getMany: async (args2) => {
|
|
251
|
-
|
|
258
|
+
args2 = args2 || {};
|
|
259
|
+
const result = await driverInstance.getMany(args2);
|
|
260
|
+
if (args2.include)
|
|
261
|
+
await handleInclude(schema, key, args2.include, result.nodes);
|
|
262
|
+
return result;
|
|
263
|
+
},
|
|
264
|
+
getAll: async (args2) => {
|
|
265
|
+
args2 = args2 || {};
|
|
266
|
+
const result = await driverInstance.getAll(args2);
|
|
267
|
+
if (args2.include)
|
|
268
|
+
await handleInclude(schema, key, args2.include, result);
|
|
269
|
+
return result;
|
|
252
270
|
},
|
|
253
271
|
put: async (item) => {
|
|
254
|
-
console.log("validating", item);
|
|
255
272
|
item = validators[key](item);
|
|
256
273
|
await driverInstance.putMany([item]);
|
|
257
274
|
return item;
|
|
258
275
|
},
|
|
259
276
|
putMany: async (items) => {
|
|
260
|
-
console.log("validating", items);
|
|
261
277
|
const itemsToSave = items.map((item) => validators[key](item));
|
|
262
278
|
await driverInstance.putMany(itemsToSave);
|
|
263
279
|
return itemsToSave;
|
|
264
280
|
}
|
|
265
|
-
// putMany:
|
|
266
|
-
// deleteMany:
|
|
267
|
-
// updateMany:
|
|
268
|
-
// verifyMany:
|
|
269
281
|
};
|
|
270
282
|
}
|
|
271
|
-
return
|
|
283
|
+
return db;
|
|
284
|
+
}
|
|
285
|
+
async function handleInclude(schema, entityName, include, result) {
|
|
286
|
+
if (!result || !result.length || !include)
|
|
287
|
+
return;
|
|
288
|
+
const fields = schema[entityName].fields || {};
|
|
289
|
+
const relationsToInclude = _.keys(include).filter((key) => include[key] && schema[fields[key].type].decorators.entity);
|
|
290
|
+
const downloadRelationsPromises = relationsToInclude.map(async (fieldName) => {
|
|
291
|
+
const typeName = fields[fieldName].type;
|
|
292
|
+
const type = schema[typeName];
|
|
293
|
+
if (!type)
|
|
294
|
+
throw new Error(`Cannot find entity ${typeName}`);
|
|
295
|
+
const idsToGet = /* @__PURE__ */ new Set();
|
|
296
|
+
for (const item of result) {
|
|
297
|
+
const id = item[fieldName]?.id;
|
|
298
|
+
if (!id)
|
|
299
|
+
continue;
|
|
300
|
+
idsToGet.add(id);
|
|
301
|
+
}
|
|
302
|
+
const driverInstance = getExistingDriverInstance(typeName);
|
|
303
|
+
const relatedEntities = await driverInstance.getAll({ where: { id_in: [...idsToGet] } });
|
|
304
|
+
const relatedEntitiesById = _.keyBy(relatedEntities, "id");
|
|
305
|
+
for (const item of result) {
|
|
306
|
+
const id = item[fieldName]?.id;
|
|
307
|
+
if (!id)
|
|
308
|
+
continue;
|
|
309
|
+
const relatedEntity = relatedEntitiesById[id];
|
|
310
|
+
if (!relatedEntity)
|
|
311
|
+
console.warn(`Cannot find ${typeName} with id "${id}" (for ${entityName}.${fieldName} with id "${item.id}")`);
|
|
312
|
+
item[fieldName] = relatedEntity;
|
|
313
|
+
}
|
|
314
|
+
});
|
|
315
|
+
await Promise.all(downloadRelationsPromises);
|
|
316
|
+
}
|
|
317
|
+
function getExistingDriverInstance(entityName) {
|
|
318
|
+
if (!drivers[entityName]) {
|
|
319
|
+
throw new Error(`Driver for entity ${entityName} was not found!`);
|
|
320
|
+
}
|
|
321
|
+
return drivers[entityName];
|
|
272
322
|
}
|
|
273
323
|
function getDriverInstance(schema, key, driver) {
|
|
274
324
|
if (!drivers[key]) {
|
|
@@ -278,7 +328,30 @@ function getDriverInstance(schema, key, driver) {
|
|
|
278
328
|
}
|
|
279
329
|
function getDriverInstanceInner(schema, key, driver) {
|
|
280
330
|
const driverConstructor = driverConstructors[driver.type];
|
|
281
|
-
|
|
331
|
+
const driverInstance = driverConstructor(schema, key, driver);
|
|
332
|
+
return {
|
|
333
|
+
...driverInstance,
|
|
334
|
+
async getAll(args) {
|
|
335
|
+
const result = [];
|
|
336
|
+
let cursor = args.cursor;
|
|
337
|
+
let maxItemCount = args.maxItemCount || 1e3;
|
|
338
|
+
if (maxItemCount < 1e3)
|
|
339
|
+
maxItemCount = 1e3;
|
|
340
|
+
for (let i = 0; i < 1e3; i++) {
|
|
341
|
+
const response = await driverInstance.getMany({ ...args, cursor, maxItemCount });
|
|
342
|
+
result.push(...response.nodes);
|
|
343
|
+
cursor = response.cursor;
|
|
344
|
+
if (cursor && cursor === response.cursor) {
|
|
345
|
+
throw new Error(
|
|
346
|
+
"Something is wrong - request for next page has returned the same cursor as before. Make sure that getMany() processes pagination correctly"
|
|
347
|
+
);
|
|
348
|
+
}
|
|
349
|
+
if (!cursor)
|
|
350
|
+
break;
|
|
351
|
+
}
|
|
352
|
+
return result;
|
|
353
|
+
}
|
|
354
|
+
};
|
|
282
355
|
}
|
|
283
356
|
|
|
284
357
|
function entity(meta) {
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
module.exports = void 0;
|
|
7
|
+
var _lodash = _interopRequireDefault(require("lodash"));
|
|
8
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
9
|
+
const operatorFns = {
|
|
10
|
+
eq: (x, w) => x === w,
|
|
11
|
+
ieq: (x, w) => x?.toLowerCase() === w?.toLowerCase(),
|
|
12
|
+
in: (x, w) => w.includes(x),
|
|
13
|
+
startsWith: (x, w) => x?.startsWith(w),
|
|
14
|
+
istartsWith: (x, w) => x?.toLowerCase()?.startsWith(w.toLowerCase()),
|
|
15
|
+
endsWith: (x, w) => x?.endsWith(w),
|
|
16
|
+
iendsWith: (x, w) => x?.toLowerCase()?.endsWith(w.toLowerCase()),
|
|
17
|
+
contains: (x, w) => x?.includes(w),
|
|
18
|
+
icontains: (x, w) => x?.toLowerCase()?.includes(w.toLowerCase()),
|
|
19
|
+
isNull: (x, w) => {
|
|
20
|
+
if (w === true) return x == null;
|
|
21
|
+
if (w === false) return x != null;
|
|
22
|
+
return true;
|
|
23
|
+
},
|
|
24
|
+
gt: (x, w) => x > w,
|
|
25
|
+
gte: (x, w) => x >= w,
|
|
26
|
+
lt: (x, w) => x < w,
|
|
27
|
+
lte: (x, w) => x <= w,
|
|
28
|
+
between: (x, w) => {
|
|
29
|
+
const {
|
|
30
|
+
start,
|
|
31
|
+
end
|
|
32
|
+
} = w || {};
|
|
33
|
+
let result = true;
|
|
34
|
+
if (start) result = result && x >= start;
|
|
35
|
+
if (end) result = result && x >= end;
|
|
36
|
+
return result;
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
var _default = (schema, entity) => {
|
|
40
|
+
const cache = {};
|
|
41
|
+
function getItemById(id) {
|
|
42
|
+
return cache[id] ?? null;
|
|
43
|
+
}
|
|
44
|
+
function getItemByIds(ids) {
|
|
45
|
+
return ids.map(id => cache[id]);
|
|
46
|
+
}
|
|
47
|
+
return {
|
|
48
|
+
// getItemById,
|
|
49
|
+
// getItemByIds,
|
|
50
|
+
putMany(items) {
|
|
51
|
+
for (const item of items) {
|
|
52
|
+
if (!item?.id) throw new Error(`You must provide an id`);
|
|
53
|
+
cache[item.id] = item;
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
getMany(args) {
|
|
57
|
+
args = args || {};
|
|
58
|
+
const where = args.where || {};
|
|
59
|
+
const whereKeys = _lodash.default.keys(where);
|
|
60
|
+
if (whereKeys.length === 1) {
|
|
61
|
+
if (whereKeys[0] === "id") return {
|
|
62
|
+
nodes: [getItemById(where.id)].filter(x => x),
|
|
63
|
+
cursor: null
|
|
64
|
+
};
|
|
65
|
+
if (whereKeys[0] === "id_in") return {
|
|
66
|
+
nodes: getItemByIds(where.id_in).filter(x => x),
|
|
67
|
+
cursor: null
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
return queryArray(Object.values(cache), args);
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
};
|
|
74
|
+
module.exports = _default;
|
|
75
|
+
function queryArray(array, args) {
|
|
76
|
+
if (!array) return array;
|
|
77
|
+
let result = array;
|
|
78
|
+
const {
|
|
79
|
+
where,
|
|
80
|
+
orderByProperty,
|
|
81
|
+
orderByDirection,
|
|
82
|
+
maxItemCount,
|
|
83
|
+
cursor
|
|
84
|
+
} = prepareArgs(args);
|
|
85
|
+
const startIndex = Number(cursor) || 0;
|
|
86
|
+
const endIndex = startIndex + maxItemCount;
|
|
87
|
+
const f = getFilter(where);
|
|
88
|
+
if (f) result = result.filter(f);
|
|
89
|
+
if (orderByProperty) result = _lodash.default.orderBy(result, [orderByProperty], [orderByDirection]);
|
|
90
|
+
if (maxItemCount) result = result.slice(startIndex, endIndex);
|
|
91
|
+
const newCursor = endIndex >= array.length ? null : endIndex;
|
|
92
|
+
return {
|
|
93
|
+
nodes: result,
|
|
94
|
+
cursor: newCursor?.toString() || null
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
function getFilter(where, namePrefix = "") {
|
|
98
|
+
if (_lodash.default.isEmpty(where)) return null;
|
|
99
|
+
const andClauses = [];
|
|
100
|
+
for (const key in where) {
|
|
101
|
+
const [nameFromWhere, operator] = getWhereNameOperatorPair(key);
|
|
102
|
+
const name = [namePrefix, nameFromWhere].filter(x => x).join(".");
|
|
103
|
+
const whereVal = where[key];
|
|
104
|
+
if (whereVal == null) continue;
|
|
105
|
+
const f = getFilterInner(operator, whereVal, name, namePrefix);
|
|
106
|
+
if (f) andClauses.push(f);
|
|
107
|
+
}
|
|
108
|
+
if (andClauses.length === 0) return null;
|
|
109
|
+
return x => andClauses.every(ac => ac(x));
|
|
110
|
+
}
|
|
111
|
+
function getWhereNameOperatorPair(whereKey) {
|
|
112
|
+
if (whereKey.startsWith("_type")) {
|
|
113
|
+
const operator = whereKey.split("_")[2];
|
|
114
|
+
return ["_type", operator];
|
|
115
|
+
}
|
|
116
|
+
return whereKey.split("_");
|
|
117
|
+
}
|
|
118
|
+
function getFilterInner(operator, whereVal, name, namePrefix) {
|
|
119
|
+
if (!operator && _lodash.default.isObject(whereVal)) {
|
|
120
|
+
return getFilter(whereVal, name);
|
|
121
|
+
}
|
|
122
|
+
if (operator === "some") {
|
|
123
|
+
const f = getFilter(whereVal, namePrefix);
|
|
124
|
+
return f && (x => {
|
|
125
|
+
const val = _lodash.default.get(x, name);
|
|
126
|
+
return val === void 0 || val?.some(f);
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
if (operator === "none") {
|
|
130
|
+
const f = getFilter(whereVal, namePrefix);
|
|
131
|
+
return f && (x => !_lodash.default.get(x, name)?.some(f));
|
|
132
|
+
}
|
|
133
|
+
if (operator === "and") {
|
|
134
|
+
if (!_lodash.default.isArray(whereVal)) throw new Error(`Value for where._and must be an array`);
|
|
135
|
+
const newAndClauses = whereVal.map(whereValAnd => getFilter(whereValAnd, namePrefix)).flatMap(x => x ? [x] : []);
|
|
136
|
+
if (!newAndClauses.length) return null;
|
|
137
|
+
return x => newAndClauses.every(ac => ac(x));
|
|
138
|
+
}
|
|
139
|
+
if (operator === "not") {
|
|
140
|
+
const f = getFilter(whereVal, namePrefix);
|
|
141
|
+
return f && (x => !f(x));
|
|
142
|
+
}
|
|
143
|
+
if (operator === "or") {
|
|
144
|
+
if (!_lodash.default.isArray(whereVal)) throw new Error(`Value for where._or must be an array`);
|
|
145
|
+
const orClauses = whereVal.map(whereValOr => getFilter(whereValOr, namePrefix)).flatMap(x => x ? [x] : []);
|
|
146
|
+
if (!orClauses.length) return null;
|
|
147
|
+
return x => orClauses.some(oc => oc(x));
|
|
148
|
+
}
|
|
149
|
+
const operatorFn = operatorFns[operator || "eq"];
|
|
150
|
+
if (operatorFn) {
|
|
151
|
+
return x => operatorFn(_lodash.default.get(x, name), whereVal);
|
|
152
|
+
}
|
|
153
|
+
console.warn(`[rads-cache] Operator not supported: ${operator || "eq"}`);
|
|
154
|
+
return null;
|
|
155
|
+
}
|
|
156
|
+
function prepareArgs(args) {
|
|
157
|
+
args = args || {};
|
|
158
|
+
const where = {
|
|
159
|
+
...args.where
|
|
160
|
+
};
|
|
161
|
+
let orderBy = args.orderBy || "";
|
|
162
|
+
if (Array.isArray(orderBy)) orderBy = orderBy[0] || "";
|
|
163
|
+
const orderByParts = orderBy.split("_");
|
|
164
|
+
const orderByProperty = orderByParts.slice(0, -1).join(".");
|
|
165
|
+
const orderByDirection = orderByParts.slice(-1)[0];
|
|
166
|
+
let maxItemCount = args.maxItemCount;
|
|
167
|
+
maxItemCount = maxItemCount || 100;
|
|
168
|
+
return {
|
|
169
|
+
where,
|
|
170
|
+
orderByProperty,
|
|
171
|
+
orderByDirection,
|
|
172
|
+
maxItemCount,
|
|
173
|
+
cursor: args.cursor
|
|
174
|
+
};
|
|
175
|
+
}
|