rads-db 0.1.26 → 0.1.28

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -2,15 +2,12 @@
2
2
 
3
3
  const zod = require('zod');
4
4
  const _ = require('lodash');
5
- const pluralize = require('pluralize');
6
- const cosmos = require('@azure/cosmos');
7
5
  const uuid = require('uuid');
8
6
  const _radsDb = require('_rads-db');
9
7
 
10
8
  function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e.default : e; }
11
9
 
12
10
  const ___default = /*#__PURE__*/_interopDefaultCompat(_);
13
- const pluralize__default = /*#__PURE__*/_interopDefaultCompat(pluralize);
14
11
 
15
12
  function generateValidators(schema) {
16
13
  const zodSchemas = {};
@@ -117,7 +114,7 @@ const operatorFns = {
117
114
  return result;
118
115
  }
119
116
  };
120
- const memory = (schema, entity) => {
117
+ const memory = (options) => (schema, entity) => {
121
118
  let cache = {};
122
119
  function getItemById(id) {
123
120
  return cache[id] ?? null;
@@ -126,6 +123,7 @@ const memory = (schema, entity) => {
126
123
  return ids.map((id) => cache[id]);
127
124
  }
128
125
  const instance = {
126
+ driverName: "memory",
129
127
  clear() {
130
128
  cache = {};
131
129
  },
@@ -194,7 +192,7 @@ function getFilter(where, namePrefix = "") {
194
192
  return null;
195
193
  const andClauses = [];
196
194
  for (const key in where) {
197
- const [nameFromWhere, operator] = getWhereNameOperatorPair$1(key);
195
+ const [nameFromWhere, operator] = getWhereNameOperatorPair(key);
198
196
  const name = [namePrefix, nameFromWhere].filter((x) => x).join(".");
199
197
  const whereVal = where[key];
200
198
  if (whereVal == null)
@@ -207,7 +205,7 @@ function getFilter(where, namePrefix = "") {
207
205
  return null;
208
206
  return (x) => andClauses.every((ac) => ac(x));
209
207
  }
210
- function getWhereNameOperatorPair$1(whereKey) {
208
+ function getWhereNameOperatorPair(whereKey) {
211
209
  if (whereKey.startsWith("_type")) {
212
210
  const operator = whereKey.split("_")[2];
213
211
  return ["_type", operator];
@@ -270,338 +268,6 @@ function prepareArgs(args) {
270
268
  return { where, orderByProperty, orderByDirection, maxItemCount, cursor: args.cursor };
271
269
  }
272
270
 
273
- const restApi = (schema, entity, options) => {
274
- options = { baseUrl: "/api", fetch: globalThis.fetch, ...options };
275
- const fetch = options.fetch || global.fetch;
276
- if (!options.fetch)
277
- throw new Error('Please provide "fetch" argument to rest driver definition');
278
- const pluralEntityName = ___default.lowerFirst(pluralize__default(entity));
279
- const instance = {
280
- async getMany(args) {
281
- args = args || {};
282
- const response = await fetch(`${options.baseUrl}/${pluralEntityName}`, {
283
- method: "POST",
284
- body: JSON.stringify(args)
285
- });
286
- return await response?.json();
287
- },
288
- async putMany(item) {
289
- await fetch(`${options.baseUrl}/${pluralEntityName}`, {
290
- method: "PUT",
291
- body: JSON.stringify({ data: item })
292
- });
293
- }
294
- };
295
- return instance;
296
- };
297
-
298
- const cosmosClientCache = {};
299
- const databaseClientCache = {};
300
- const containerClientCache = {};
301
- const simpleSubclauseRegex = /^[a-z0-9_@]+.[a-z0-9_@]+ = [a-z0-9_@.]+$/i;
302
- const azureCosmos = (schema, entity, options) => {
303
- const client = getCosmosContainerClient(options);
304
- async function getItemByIds(ids, ctx) {
305
- const { query, parameters } = getCosmosQuery(schema, entity, { where: { id_in: ids } });
306
- const response = client.items.query({
307
- query,
308
- parameters: Object.keys(parameters).map((k) => ({ name: `@${k}`, value: parameters[k] }))
309
- });
310
- const r = await response.fetchAll();
311
- ctx?.log?.({ charge: r.requestCharge, request: query });
312
- return r.resources;
313
- }
314
- const instance = {
315
- async clear(ctx) {
316
- const responseIter = client.items.readAll();
317
- const items = await responseIter.fetchAll();
318
- ctx?.log?.({ charge: items.requestCharge, request: "readAll" });
319
- for (const r of items.resources) {
320
- await client.item(r.id, r._partition).delete();
321
- ctx?.log?.({ charge: items.requestCharge, request: `delete#${r._partition}|${r.id}` });
322
- }
323
- },
324
- async putMany(items, ctx) {
325
- for (const item of items) {
326
- const id = item?.id;
327
- if (!id)
328
- throw new Error(`You must provide an id`);
329
- const itemToPut = { _partition: entity, id, ...item };
330
- const response = await client.items.upsert(itemToPut);
331
- ctx?.log?.({ charge: response.requestCharge, request: `put#${itemToPut._partition}|${itemToPut.id}` });
332
- }
333
- },
334
- async getMany(args, ctx) {
335
- args = args || {};
336
- const where = args.where || {};
337
- const whereKeys = ___default.keys(where);
338
- if (whereKeys.length === 1) {
339
- if (whereKeys[0] === "id" && where.id != null) {
340
- const items = await getItemByIds([where.id], ctx);
341
- return { nodes: [items[0]].filter((x) => x), cursor: null };
342
- }
343
- if (whereKeys[0] === "id_in" && where.id_in != null) {
344
- const items = await getItemByIds(where.id_in, ctx);
345
- return { nodes: items.filter((x) => x), cursor: null };
346
- }
347
- }
348
- const { query, parameters } = getCosmosQuery(schema, entity, args);
349
- const response = client.items.query(
350
- {
351
- query,
352
- parameters: Object.keys(parameters).map((k) => ({ name: `@${k}`, value: parameters[k] }))
353
- },
354
- {
355
- continuationToken: args.cursor || void 0,
356
- continuationTokenLimitInKB: 4,
357
- maxItemCount: args.maxItemCount
358
- }
359
- );
360
- const page = await response.fetchNext();
361
- ctx?.log?.({ charge: page.requestCharge, request: query });
362
- return {
363
- nodes: page.resources,
364
- cursor: page.continuationToken || null
365
- };
366
- }
367
- };
368
- return instance;
369
- };
370
- function getCosmosQuery(schema, entity, args) {
371
- args = args || {};
372
- const where = args.where || {};
373
- const parameters = {};
374
- const whereClauses = [
375
- `r._partition = '${entity}'`,
376
- getCosmosQueryWhere({ schema, entity }, parameters, where)
377
- ].filter((x) => x);
378
- let orderByClause = "";
379
- if (args.orderBy) {
380
- const [orderPropFromOrderBy, orderDirection] = args.orderBy.split("_") || [];
381
- const orderProp = orderPropFromOrderBy === "value" ? `r["value"]` : `r.${orderPropFromOrderBy}`;
382
- orderByClause = `order by ${orderProp} ${orderDirection}`;
383
- }
384
- const query = `select * from r where ${whereClauses.join(" AND ")} ${orderByClause}`;
385
- return { query, parameters };
386
- }
387
- const operatorHandlers = {
388
- some: (ctx, parameters, whereArgs) => {
389
- const { name, namePrefix, whereVal } = whereArgs;
390
- const newCtx = { ...ctx, entity: ctx.schema[ctx.entity].fields[ctx.field].type };
391
- const subClause = getCosmosQueryWhere(newCtx, parameters, whereVal, `${namePrefix}${name}.`);
392
- if (subClause) {
393
- if (simpleSubclauseRegex.test(subClause)) {
394
- const parts = subClause.split(" ");
395
- const field = parts[0];
396
- const variable = parts[2];
397
- return `array_contains(${namePrefix}${name}, { ${field.split(".")[1]}: ${variable} }, true)`;
398
- }
399
- return `exists (select ${name} from ${name} in ${namePrefix}${name} where ${subClause})`;
400
- }
401
- return `array_length(${namePrefix}${name}) > 0`;
402
- },
403
- none: (ctx, parameters, whereArgs) => {
404
- const { name, namePrefix, whereVal } = whereArgs;
405
- const newCtx = { ...ctx, entity: ctx.schema[ctx.entity].fields[ctx.field].type };
406
- const subClause = getCosmosQueryWhere(newCtx, parameters, whereVal, `${namePrefix}${name}.`);
407
- if (subClause)
408
- return `not exists (select ${name} from ${name} in ${namePrefix}${name} where ${subClause})`;
409
- return `array_length(${namePrefix}${name}) = 0`;
410
- },
411
- and: (ctx, parameters, whereArgs) => {
412
- const { namePrefix, paramNamePrefix, whereVal } = whereArgs;
413
- if (!___default.isArray(whereVal))
414
- throw new Error(`Value for where._and must be an array`);
415
- const clauses = [];
416
- for (let i = 0; i < whereVal.length; i++) {
417
- const andQuery = getCosmosQueryWhere(ctx, parameters, whereVal[i], namePrefix, `${paramNamePrefix}and${i}_`);
418
- clauses.push(andQuery);
419
- }
420
- if (!clauses.length)
421
- return null;
422
- return `((${clauses.join(") and (")}))`;
423
- },
424
- not: (ctx, parameters, whereArgs) => {
425
- const { name, namePrefix, paramNamePrefix, whereVal } = whereArgs;
426
- const subClause = getCosmosQueryWhere(ctx, parameters, whereVal, `${namePrefix}${name}`, `${paramNamePrefix}not_`);
427
- if (!subClause)
428
- return null;
429
- return `not(${subClause})`;
430
- },
431
- or: (ctx, parameters, whereArgs) => {
432
- const { namePrefix, paramNamePrefix, whereVal } = whereArgs;
433
- if (!___default.isArray(whereVal))
434
- throw new Error(`Value for where._or must be an array`);
435
- const clauses = [];
436
- for (let i = 0; i < whereVal.length; i++) {
437
- const orQuery = getCosmosQueryWhere(ctx, parameters, whereVal[i], namePrefix, `${paramNamePrefix}or${i}_`);
438
- clauses.push(orQuery);
439
- }
440
- if (!clauses.length)
441
- return null;
442
- return `((${clauses.join(") or (")}))`;
443
- },
444
- isNull: (ctx, parameters, whereArgs) => {
445
- const { name, namePrefix, whereVal } = whereArgs;
446
- const n = `${namePrefix}${name}`;
447
- if (whereVal)
448
- return `(not (is_defined(${n})) or ${n} = null)`;
449
- return `(is_defined(${n}) and ${n} != null)`;
450
- },
451
- eq: (ctx, parameters, whereArgs) => {
452
- const { name, namePrefix, paramName, paramNamePrefix, whereVal } = whereArgs;
453
- const pn = `${paramNamePrefix}${paramName}`;
454
- parameters[pn] = whereVal;
455
- return `${namePrefix}${name} = @${pn}`;
456
- },
457
- in: (ctx, parameters, whereArgs) => {
458
- const { name, namePrefix, paramName, paramNamePrefix, whereVal } = whereArgs;
459
- const pn = `${paramNamePrefix}${paramName}`;
460
- parameters[pn] = whereVal;
461
- return `array_contains(@${pn}, ${namePrefix}${name})`;
462
- },
463
- startsWith: (ctx, parameters, whereArgs) => {
464
- const { name, namePrefix, paramName, paramNamePrefix, whereVal } = whereArgs;
465
- const pn = `${paramNamePrefix}${paramName}`;
466
- parameters[pn] = whereVal;
467
- return `startswith(${namePrefix}${name}, @${pn})`;
468
- },
469
- istartsWith: (ctx, parameters, whereArgs) => {
470
- const { name, namePrefix, paramName, paramNamePrefix, whereVal } = whereArgs;
471
- const pn = `${paramNamePrefix}${paramName}`;
472
- parameters[pn] = whereVal;
473
- return `startswith(${namePrefix}${name}, @${pn}, true)`;
474
- },
475
- endsWith: (ctx, parameters, whereArgs) => {
476
- const { name, namePrefix, paramName, paramNamePrefix, whereVal } = whereArgs;
477
- const pn = `${paramNamePrefix}${paramName}`;
478
- parameters[pn] = whereVal;
479
- return `endswith(${namePrefix}${name}, @${pn})`;
480
- },
481
- iendsWith: (ctx, parameters, whereArgs) => {
482
- const { name, namePrefix, paramName, paramNamePrefix, whereVal } = whereArgs;
483
- const pn = `${paramNamePrefix}${paramName}`;
484
- parameters[pn] = whereVal;
485
- return `endswith(${namePrefix}${name}, @${pn}, true)`;
486
- },
487
- contains: (ctx, parameters, whereArgs) => {
488
- const { name, namePrefix, paramName, paramNamePrefix, whereVal } = whereArgs;
489
- const fieldType = ctx.schema[ctx.entity].fields[ctx.field];
490
- const pn = `${paramNamePrefix}${paramName}`;
491
- parameters[pn] = whereVal;
492
- if (fieldType.isArray) {
493
- return `array_contains(${namePrefix}${name}, @${pn})`;
494
- }
495
- return `contains(${namePrefix}${name}, @${pn})`;
496
- },
497
- icontains: (ctx, parameters, whereArgs) => {
498
- const { name, namePrefix, paramName, paramNamePrefix, whereVal } = whereArgs;
499
- const pn = `${paramNamePrefix}${paramName}`;
500
- parameters[pn] = whereVal;
501
- return `contains(${namePrefix}${name}, @${pn}, true)`;
502
- },
503
- ieq: (ctx, parameters, whereArgs) => {
504
- const { name, namePrefix, paramName, paramNamePrefix, whereVal } = whereArgs;
505
- const pn = `${paramNamePrefix}${paramName}`;
506
- parameters[pn] = whereVal;
507
- return `stringequals(${namePrefix}${name}, @${pn}, true)`;
508
- },
509
- gt: (ctx, parameters, whereArgs) => {
510
- const { name, namePrefix, paramName, paramNamePrefix, whereVal } = whereArgs;
511
- const pn = `${paramNamePrefix}${paramName}`;
512
- parameters[pn] = whereVal;
513
- return `${namePrefix}${name} > @${pn}`;
514
- },
515
- gte: (ctx, parameters, whereArgs) => {
516
- const { name, namePrefix, paramName, paramNamePrefix, whereVal } = whereArgs;
517
- const pn = `${paramNamePrefix}${paramName}`;
518
- parameters[pn] = whereVal;
519
- return `${namePrefix}${name} >= @${pn}`;
520
- },
521
- lt: (ctx, parameters, whereArgs) => {
522
- const { name, namePrefix, paramName, paramNamePrefix, whereVal } = whereArgs;
523
- const pn = `${paramNamePrefix}${paramName}`;
524
- parameters[pn] = whereVal;
525
- return `${namePrefix}${name} < @${pn}`;
526
- },
527
- lte: (ctx, parameters, whereArgs) => {
528
- const { name, namePrefix, paramName, paramNamePrefix, whereVal } = whereArgs;
529
- const pn = `${paramNamePrefix}${paramName}`;
530
- parameters[pn] = whereVal;
531
- return `${namePrefix}${name} <= @${pn}`;
532
- }
533
- };
534
- function getCosmosQueryWhere(ctx, parameters, where, namePrefix = "r.", paramNamePrefix = "") {
535
- const whereClauses = [];
536
- for (const key in where) {
537
- const [nameFromWhere, operator] = getWhereNameOperatorPair(key);
538
- let name = nameFromWhere;
539
- if (name === "value") {
540
- name = `["${name}"]`;
541
- namePrefix = namePrefix.slice(0, -1);
542
- }
543
- const paramName = key;
544
- const whereVal = where[key];
545
- if (whereVal == null)
546
- continue;
547
- const f = getCosmosQueryWhereInner({ ...ctx, field: nameFromWhere }, parameters, {
548
- operator,
549
- whereVal,
550
- name,
551
- namePrefix,
552
- paramName,
553
- paramNamePrefix
554
- });
555
- if (f)
556
- whereClauses.push(f);
557
- }
558
- return whereClauses.join(" AND ");
559
- }
560
- function getCosmosQueryWhereInner(ctx, parameters, whereArgs) {
561
- const { operator, whereVal, name, namePrefix, paramName, paramNamePrefix } = whereArgs;
562
- if (!operator && ___default.isObject(whereVal)) {
563
- return getCosmosQueryWhere(ctx, parameters, whereVal, `${namePrefix}${name}.`, `${paramNamePrefix}${paramName}_`);
564
- }
565
- const fn = operatorHandlers[operator || "eq"];
566
- if (!fn)
567
- console.warn(`Unsupported operator: "${operator}"`);
568
- return fn(ctx, parameters, whereArgs);
569
- }
570
- function getCosmosContainerClient(options) {
571
- options = { databaseName: "main", containerName: "main", ...options };
572
- const { databaseName, containerName, endpoint } = options;
573
- const key = `${endpoint}|${databaseName}|${containerName}`;
574
- if (!containerClientCache[key]) {
575
- containerClientCache[key] = getCosmosDatabaseClient(options).container(containerName);
576
- }
577
- return containerClientCache[key];
578
- }
579
- function getCosmosDatabaseClient(options) {
580
- options = { databaseName: "main", containerName: "main", ...options };
581
- const { databaseName, endpoint } = options;
582
- const key = `${endpoint}|${databaseName}`;
583
- if (!databaseClientCache[key]) {
584
- databaseClientCache[key] = getCosmosAccountClient(options).database(databaseName);
585
- }
586
- return databaseClientCache[key];
587
- }
588
- function getCosmosAccountClient(options) {
589
- options = { databaseName: "main", containerName: "main", ...options };
590
- const { endpoint, accountKey } = options;
591
- const key = endpoint;
592
- if (!cosmosClientCache[key]) {
593
- cosmosClientCache[key] = new cosmos.CosmosClient({ endpoint, key: accountKey, ...options.options });
594
- }
595
- return cosmosClientCache[key];
596
- }
597
- function getWhereNameOperatorPair(whereKey) {
598
- if (whereKey.startsWith("_type")) {
599
- const operator = whereKey.split("_")[2];
600
- return ["_type", operator];
601
- }
602
- return whereKey.split("_");
603
- }
604
-
605
271
  const computedPresets = {
606
272
  createdAt: ({ doc }) => {
607
273
  return doc.createdAt || (/* @__PURE__ */ new Date()).toISOString();
@@ -818,11 +484,10 @@ async function handleEffectsAfterPut(ctx, docs, beforePutResults) {
818
484
  return Promise.all(ctx.effects[ctx.typeName].map((ef, i) => ef.afterPut(ctx, docs, beforePutResults[i])));
819
485
  }
820
486
 
821
- const driverConstructors = { memory, restApi, azureCosmos };
822
- const drivers = {};
823
487
  function generateMethods(schema, validators, options) {
488
+ const drivers = {};
824
489
  const db = { _schema: schema };
825
- const opts = { computed: {}, driver: { type: "memory" }, ...options };
490
+ const opts = { computed: {}, driver: memory(), ...options };
826
491
  const effects = {};
827
492
  for (const key in schema) {
828
493
  effects[key] = [];
@@ -835,8 +500,8 @@ function generateMethods(schema, validators, options) {
835
500
  const { handle } = schema[key];
836
501
  if (!handle)
837
502
  throw new Error(`Missing handle for entity ${key}`);
838
- const driverInstance = getDriverInstance(schema, key, opts.driver);
839
503
  const computedContext = { schema, typeName: key, validators, options: opts, drivers, effects };
504
+ const driverInstance = getDriverInstance(schema, key, opts.driver, drivers);
840
505
  db[handle] = {
841
506
  getAgg: async (args, ctx) => {
842
507
  if (!args?.agg)
@@ -847,16 +512,17 @@ function generateMethods(schema, validators, options) {
847
512
  get: async (args, ctx) => {
848
513
  args = args || {};
849
514
  const result = await driverInstance.get(args, ctx);
850
- if (args.include)
851
- await handleInclude(schema, key, args.include, [result]);
852
- await handleComputed(schema, key, opts, [result]);
515
+ if (result && args.include)
516
+ await handleInclude(computedContext, args.include, [result]);
517
+ if (result)
518
+ await handleComputed(schema, key, opts, [result]);
853
519
  return result;
854
520
  },
855
521
  getMany: async (args, ctx) => {
856
522
  args = args || {};
857
523
  const result = await driverInstance.getMany(args, ctx);
858
524
  if (args.include)
859
- await handleInclude(schema, key, args.include, result.nodes);
525
+ await handleInclude(computedContext, args.include, result.nodes);
860
526
  await handleComputed(schema, key, opts, result.nodes);
861
527
  return result;
862
528
  },
@@ -864,7 +530,7 @@ function generateMethods(schema, validators, options) {
864
530
  args = args || {};
865
531
  const result = await driverInstance.getAll(args, ctx);
866
532
  if (args.include)
867
- await handleInclude(schema, key, args.include, result);
533
+ await handleInclude(computedContext, args.include, result);
868
534
  await handleComputed(schema, key, opts, result);
869
535
  return result;
870
536
  },
@@ -910,16 +576,17 @@ function generateMethods(schema, validators, options) {
910
576
  }
911
577
  return db;
912
578
  }
913
- async function handleInclude(schema, entityName, include, result) {
579
+ async function handleInclude(computedContext, include, result) {
914
580
  if (!result || !result.length || !include)
915
581
  return;
916
- const fields = schema[entityName].fields || {};
582
+ const { schema, typeName, drivers } = computedContext;
583
+ const fields = schema[typeName].fields || {};
917
584
  const relationsToInclude = ___default.keys(include).filter((key) => include[key] && schema[fields[key].type].decorators.entity);
918
585
  const downloadRelationsPromises = relationsToInclude.map(async (fieldName) => {
919
- const typeName = fields[fieldName].type;
920
- const type = schema[typeName];
586
+ const typeName2 = fields[fieldName].type;
587
+ const type = schema[typeName2];
921
588
  if (!type)
922
- throw new Error(`Cannot find entity ${typeName}`);
589
+ throw new Error(`Cannot find entity ${typeName2}`);
923
590
  const idsToGet = /* @__PURE__ */ new Set();
924
591
  for (const item of result) {
925
592
  if (!item)
@@ -935,7 +602,7 @@ async function handleInclude(schema, entityName, include, result) {
935
602
  idsToGet.add(id);
936
603
  }
937
604
  }
938
- const driverInstance = getExistingDriverInstance(typeName);
605
+ const driverInstance = getExistingDriverInstance(typeName2, drivers);
939
606
  const relatedEntities = await driverInstance.getAll({ where: { id_in: [...idsToGet] } });
940
607
  const relatedEntitiesById = ___default.keyBy(relatedEntities, "id");
941
608
  for (const item of result) {
@@ -951,28 +618,27 @@ async function handleInclude(schema, entityName, include, result) {
951
618
  continue;
952
619
  const relatedEntity = relatedEntitiesById[id];
953
620
  if (!relatedEntity)
954
- console.warn(`Cannot find ${typeName} with id "${id}" (for ${entityName}.${fieldName} with id "${item.id}")`);
621
+ console.warn(`Cannot find ${typeName2} with id "${id}" (for ${typeName2}.${fieldName} with id "${item.id}")`);
955
622
  Object.assign(fv, relatedEntity);
956
623
  }
957
624
  }
958
625
  });
959
626
  await Promise.all(downloadRelationsPromises);
960
627
  }
961
- function getExistingDriverInstance(entityName) {
628
+ function getExistingDriverInstance(entityName, drivers) {
962
629
  if (!drivers[entityName]) {
963
630
  throw new Error(`Driver for entity ${entityName} was not found!`);
964
631
  }
965
632
  return drivers[entityName];
966
633
  }
967
- function getDriverInstance(schema, key, driver) {
634
+ function getDriverInstance(schema, key, driver, drivers) {
968
635
  if (!drivers[key]) {
969
636
  drivers[key] = getDriverInstanceInner(schema, key, driver);
970
637
  }
971
638
  return drivers[key];
972
639
  }
973
- function getDriverInstanceInner(schema, key, driver) {
974
- const driverConstructor = driverConstructors[driver.type];
975
- const driverInstance = driverConstructor(schema, key, driver);
640
+ function getDriverInstanceInner(schema, key, driverConstructor) {
641
+ const driverInstance = driverConstructor(schema, key);
976
642
  async function getAll(args, ctx) {
977
643
  const result = [];
978
644
  let cursor = args.cursor;
@@ -1010,7 +676,7 @@ function getDriverInstanceInner(schema, key, driver) {
1010
676
  await driverInstance.putMany([data], ctx);
1011
677
  },
1012
678
  async clear() {
1013
- console.error(`"clear" not supported for driver "${driver.type}"`);
679
+ console.error(`"clear" not supported for driver "${driverInstance.driverName}"`);
1014
680
  },
1015
681
  ...driverInstance
1016
682
  };
package/dist/index.d.ts CHANGED
@@ -73,11 +73,11 @@ interface ComputedDecoratorArgs {
73
73
  interface FieldDecoratorArgs {
74
74
  relation?: Function;
75
75
  }
76
+ type DriverConstructor = (schema: Schema, entity: string) => MinimalDriver;
76
77
  interface CreateRadsArgs {
77
78
  schema?: Schema;
78
- driver?: DriverOptions;
79
- drivers?: Record<string, DriverOptions>;
80
- defaultDriver?: string;
79
+ driver?: DriverConstructor;
80
+ drivers?: Record<string, DriverConstructor>;
81
81
  computed?: Record<string, Record<string, Function>>;
82
82
  context?: Record<string, any>;
83
83
  }
@@ -96,6 +96,7 @@ interface TypeDefinition {
96
96
  handlePlural?: string;
97
97
  }
98
98
  interface MinimalDriver {
99
+ driverName: string;
99
100
  putMany: (item: Record<string, any>[], ctx?: RadsRequestContext) => MaybePromise<void>;
100
101
  getMany: (args?: GetManyArgsAny, ctx?: RadsRequestContext) => MaybePromise<{
101
102
  nodes: Record<string, any>[];
@@ -136,7 +137,6 @@ interface PutEffect {
136
137
  }[], beforePutResult: any) => MaybePromise<any>;
137
138
  }
138
139
  interface RestDriverOptions {
139
- type: 'restApi';
140
140
  /** @default '/api' */
141
141
  baseUrl?: string;
142
142
  fetch?: (url: string, options?: {
@@ -146,10 +146,8 @@ interface RestDriverOptions {
146
146
  }) => any;
147
147
  }
148
148
  interface MemoryDriverOptions {
149
- type: 'memory';
150
149
  }
151
150
  interface AzureCosmosDriverOptions {
152
- type: 'azureCosmos';
153
151
  endpoint: string;
154
152
  accountKey?: string;
155
153
  databaseName?: string;
@@ -169,10 +167,10 @@ interface RadsRequestContext {
169
167
 
170
168
  declare function entity(meta?: EntityDecoratorArgs): (classConstructor: Function, _ctx?: ClassDecoratorContext<any>) => void;
171
169
  declare function field(meta?: FieldDecoratorArgs): (a: any, b?: ClassFieldDecoratorContext) => void;
172
- declare function precomputed(meta?: ComputedDecoratorArgs): (a: any, b?: ClassFieldDecoratorContext) => void;
170
+ declare function precomputed(meta?: ComputedDecoratorArgs): (a: any, b?: ClassFieldDecoratorContext | ClassDecoratorContext) => void;
173
171
  declare function computed(meta?: ComputedDecoratorArgs): (a: any, b?: ClassFieldDecoratorContext) => void;
174
172
 
175
173
  declare function createRads(args?: CreateRadsArgs): RadsDb;
176
174
  declare function getRestRoutes(db: RadsDb, prefix?: string): Record<string, Record<string, Function>>;
177
175
 
178
- export { AzureCosmosDriverOptions, Change, ComputedContext, ComputedDecoratorArgs, CreateRadsArgs, DeepPartial, Driver, DriverOptions, EntityDecoratorArgs, EntityMethods, FieldDecoratorArgs, FieldDefinition, GenerateClientNormalizedOptions, GenerateClientOptions, GetAggArgs, GetAggArgsAgg, GetAggArgsAny, GetAggResponse, GetArgs, GetArgsAny, GetArgsInclude, GetManyArgs, GetManyArgsAny, GetManyResponse, GetResponse, GetResponseInclude, GetResponseIncludeSelect, GetResponseNoInclude, MemoryDriverOptions, MinimalDriver, PutArgs, PutEffect, RadsRequestContext, RestDriverOptions, Schema, SchemaValidators, TypeDefinition, computed, createRads, entity, field, getRestRoutes, precomputed };
176
+ export { AzureCosmosDriverOptions, Change, ComputedContext, ComputedDecoratorArgs, CreateRadsArgs, DeepPartial, Driver, DriverConstructor, DriverOptions, EntityDecoratorArgs, EntityMethods, FieldDecoratorArgs, FieldDefinition, GenerateClientNormalizedOptions, GenerateClientOptions, GetAggArgs, GetAggArgsAgg, GetAggArgsAny, GetAggResponse, GetArgs, GetArgsAny, GetArgsInclude, GetManyArgs, GetManyArgsAny, GetManyResponse, GetResponse, GetResponseInclude, GetResponseIncludeSelect, GetResponseNoInclude, MemoryDriverOptions, MinimalDriver, PutArgs, PutEffect, RadsRequestContext, RestDriverOptions, Schema, SchemaValidators, TypeDefinition, computed, createRads, entity, field, getRestRoutes, precomputed };
package/dist/index.mjs CHANGED
@@ -1,7 +1,5 @@
1
1
  import { z } from 'zod';
2
2
  import _ from 'lodash';
3
- import pluralize from 'pluralize';
4
- import { CosmosClient } from '@azure/cosmos';
5
3
  import { v4 } from 'uuid';
6
4
  import { schema } from '_rads-db';
7
5
 
@@ -110,7 +108,7 @@ const operatorFns = {
110
108
  return result;
111
109
  }
112
110
  };
113
- const memory = (schema, entity) => {
111
+ const memory = (options) => (schema, entity) => {
114
112
  let cache = {};
115
113
  function getItemById(id) {
116
114
  return cache[id] ?? null;
@@ -119,6 +117,7 @@ const memory = (schema, entity) => {
119
117
  return ids.map((id) => cache[id]);
120
118
  }
121
119
  const instance = {
120
+ driverName: "memory",
122
121
  clear() {
123
122
  cache = {};
124
123
  },
@@ -187,7 +186,7 @@ function getFilter(where, namePrefix = "") {
187
186
  return null;
188
187
  const andClauses = [];
189
188
  for (const key in where) {
190
- const [nameFromWhere, operator] = getWhereNameOperatorPair$1(key);
189
+ const [nameFromWhere, operator] = getWhereNameOperatorPair(key);
191
190
  const name = [namePrefix, nameFromWhere].filter((x) => x).join(".");
192
191
  const whereVal = where[key];
193
192
  if (whereVal == null)
@@ -200,7 +199,7 @@ function getFilter(where, namePrefix = "") {
200
199
  return null;
201
200
  return (x) => andClauses.every((ac) => ac(x));
202
201
  }
203
- function getWhereNameOperatorPair$1(whereKey) {
202
+ function getWhereNameOperatorPair(whereKey) {
204
203
  if (whereKey.startsWith("_type")) {
205
204
  const operator = whereKey.split("_")[2];
206
205
  return ["_type", operator];
@@ -263,338 +262,6 @@ function prepareArgs(args) {
263
262
  return { where, orderByProperty, orderByDirection, maxItemCount, cursor: args.cursor };
264
263
  }
265
264
 
266
- const restApi = (schema, entity, options) => {
267
- options = { baseUrl: "/api", fetch: globalThis.fetch, ...options };
268
- const fetch = options.fetch || global.fetch;
269
- if (!options.fetch)
270
- throw new Error('Please provide "fetch" argument to rest driver definition');
271
- const pluralEntityName = _.lowerFirst(pluralize(entity));
272
- const instance = {
273
- async getMany(args) {
274
- args = args || {};
275
- const response = await fetch(`${options.baseUrl}/${pluralEntityName}`, {
276
- method: "POST",
277
- body: JSON.stringify(args)
278
- });
279
- return await response?.json();
280
- },
281
- async putMany(item) {
282
- await fetch(`${options.baseUrl}/${pluralEntityName}`, {
283
- method: "PUT",
284
- body: JSON.stringify({ data: item })
285
- });
286
- }
287
- };
288
- return instance;
289
- };
290
-
291
- const cosmosClientCache = {};
292
- const databaseClientCache = {};
293
- const containerClientCache = {};
294
- const simpleSubclauseRegex = /^[a-z0-9_@]+.[a-z0-9_@]+ = [a-z0-9_@.]+$/i;
295
- const azureCosmos = (schema, entity, options) => {
296
- const client = getCosmosContainerClient(options);
297
- async function getItemByIds(ids, ctx) {
298
- const { query, parameters } = getCosmosQuery(schema, entity, { where: { id_in: ids } });
299
- const response = client.items.query({
300
- query,
301
- parameters: Object.keys(parameters).map((k) => ({ name: `@${k}`, value: parameters[k] }))
302
- });
303
- const r = await response.fetchAll();
304
- ctx?.log?.({ charge: r.requestCharge, request: query });
305
- return r.resources;
306
- }
307
- const instance = {
308
- async clear(ctx) {
309
- const responseIter = client.items.readAll();
310
- const items = await responseIter.fetchAll();
311
- ctx?.log?.({ charge: items.requestCharge, request: "readAll" });
312
- for (const r of items.resources) {
313
- await client.item(r.id, r._partition).delete();
314
- ctx?.log?.({ charge: items.requestCharge, request: `delete#${r._partition}|${r.id}` });
315
- }
316
- },
317
- async putMany(items, ctx) {
318
- for (const item of items) {
319
- const id = item?.id;
320
- if (!id)
321
- throw new Error(`You must provide an id`);
322
- const itemToPut = { _partition: entity, id, ...item };
323
- const response = await client.items.upsert(itemToPut);
324
- ctx?.log?.({ charge: response.requestCharge, request: `put#${itemToPut._partition}|${itemToPut.id}` });
325
- }
326
- },
327
- async getMany(args, ctx) {
328
- args = args || {};
329
- const where = args.where || {};
330
- const whereKeys = _.keys(where);
331
- if (whereKeys.length === 1) {
332
- if (whereKeys[0] === "id" && where.id != null) {
333
- const items = await getItemByIds([where.id], ctx);
334
- return { nodes: [items[0]].filter((x) => x), cursor: null };
335
- }
336
- if (whereKeys[0] === "id_in" && where.id_in != null) {
337
- const items = await getItemByIds(where.id_in, ctx);
338
- return { nodes: items.filter((x) => x), cursor: null };
339
- }
340
- }
341
- const { query, parameters } = getCosmosQuery(schema, entity, args);
342
- const response = client.items.query(
343
- {
344
- query,
345
- parameters: Object.keys(parameters).map((k) => ({ name: `@${k}`, value: parameters[k] }))
346
- },
347
- {
348
- continuationToken: args.cursor || void 0,
349
- continuationTokenLimitInKB: 4,
350
- maxItemCount: args.maxItemCount
351
- }
352
- );
353
- const page = await response.fetchNext();
354
- ctx?.log?.({ charge: page.requestCharge, request: query });
355
- return {
356
- nodes: page.resources,
357
- cursor: page.continuationToken || null
358
- };
359
- }
360
- };
361
- return instance;
362
- };
363
- function getCosmosQuery(schema, entity, args) {
364
- args = args || {};
365
- const where = args.where || {};
366
- const parameters = {};
367
- const whereClauses = [
368
- `r._partition = '${entity}'`,
369
- getCosmosQueryWhere({ schema, entity }, parameters, where)
370
- ].filter((x) => x);
371
- let orderByClause = "";
372
- if (args.orderBy) {
373
- const [orderPropFromOrderBy, orderDirection] = args.orderBy.split("_") || [];
374
- const orderProp = orderPropFromOrderBy === "value" ? `r["value"]` : `r.${orderPropFromOrderBy}`;
375
- orderByClause = `order by ${orderProp} ${orderDirection}`;
376
- }
377
- const query = `select * from r where ${whereClauses.join(" AND ")} ${orderByClause}`;
378
- return { query, parameters };
379
- }
380
- const operatorHandlers = {
381
- some: (ctx, parameters, whereArgs) => {
382
- const { name, namePrefix, whereVal } = whereArgs;
383
- const newCtx = { ...ctx, entity: ctx.schema[ctx.entity].fields[ctx.field].type };
384
- const subClause = getCosmosQueryWhere(newCtx, parameters, whereVal, `${namePrefix}${name}.`);
385
- if (subClause) {
386
- if (simpleSubclauseRegex.test(subClause)) {
387
- const parts = subClause.split(" ");
388
- const field = parts[0];
389
- const variable = parts[2];
390
- return `array_contains(${namePrefix}${name}, { ${field.split(".")[1]}: ${variable} }, true)`;
391
- }
392
- return `exists (select ${name} from ${name} in ${namePrefix}${name} where ${subClause})`;
393
- }
394
- return `array_length(${namePrefix}${name}) > 0`;
395
- },
396
- none: (ctx, parameters, whereArgs) => {
397
- const { name, namePrefix, whereVal } = whereArgs;
398
- const newCtx = { ...ctx, entity: ctx.schema[ctx.entity].fields[ctx.field].type };
399
- const subClause = getCosmosQueryWhere(newCtx, parameters, whereVal, `${namePrefix}${name}.`);
400
- if (subClause)
401
- return `not exists (select ${name} from ${name} in ${namePrefix}${name} where ${subClause})`;
402
- return `array_length(${namePrefix}${name}) = 0`;
403
- },
404
- and: (ctx, parameters, whereArgs) => {
405
- const { namePrefix, paramNamePrefix, whereVal } = whereArgs;
406
- if (!_.isArray(whereVal))
407
- throw new Error(`Value for where._and must be an array`);
408
- const clauses = [];
409
- for (let i = 0; i < whereVal.length; i++) {
410
- const andQuery = getCosmosQueryWhere(ctx, parameters, whereVal[i], namePrefix, `${paramNamePrefix}and${i}_`);
411
- clauses.push(andQuery);
412
- }
413
- if (!clauses.length)
414
- return null;
415
- return `((${clauses.join(") and (")}))`;
416
- },
417
- not: (ctx, parameters, whereArgs) => {
418
- const { name, namePrefix, paramNamePrefix, whereVal } = whereArgs;
419
- const subClause = getCosmosQueryWhere(ctx, parameters, whereVal, `${namePrefix}${name}`, `${paramNamePrefix}not_`);
420
- if (!subClause)
421
- return null;
422
- return `not(${subClause})`;
423
- },
424
- or: (ctx, parameters, whereArgs) => {
425
- const { namePrefix, paramNamePrefix, whereVal } = whereArgs;
426
- if (!_.isArray(whereVal))
427
- throw new Error(`Value for where._or must be an array`);
428
- const clauses = [];
429
- for (let i = 0; i < whereVal.length; i++) {
430
- const orQuery = getCosmosQueryWhere(ctx, parameters, whereVal[i], namePrefix, `${paramNamePrefix}or${i}_`);
431
- clauses.push(orQuery);
432
- }
433
- if (!clauses.length)
434
- return null;
435
- return `((${clauses.join(") or (")}))`;
436
- },
437
- isNull: (ctx, parameters, whereArgs) => {
438
- const { name, namePrefix, whereVal } = whereArgs;
439
- const n = `${namePrefix}${name}`;
440
- if (whereVal)
441
- return `(not (is_defined(${n})) or ${n} = null)`;
442
- return `(is_defined(${n}) and ${n} != null)`;
443
- },
444
- eq: (ctx, parameters, whereArgs) => {
445
- const { name, namePrefix, paramName, paramNamePrefix, whereVal } = whereArgs;
446
- const pn = `${paramNamePrefix}${paramName}`;
447
- parameters[pn] = whereVal;
448
- return `${namePrefix}${name} = @${pn}`;
449
- },
450
- in: (ctx, parameters, whereArgs) => {
451
- const { name, namePrefix, paramName, paramNamePrefix, whereVal } = whereArgs;
452
- const pn = `${paramNamePrefix}${paramName}`;
453
- parameters[pn] = whereVal;
454
- return `array_contains(@${pn}, ${namePrefix}${name})`;
455
- },
456
- startsWith: (ctx, parameters, whereArgs) => {
457
- const { name, namePrefix, paramName, paramNamePrefix, whereVal } = whereArgs;
458
- const pn = `${paramNamePrefix}${paramName}`;
459
- parameters[pn] = whereVal;
460
- return `startswith(${namePrefix}${name}, @${pn})`;
461
- },
462
- istartsWith: (ctx, parameters, whereArgs) => {
463
- const { name, namePrefix, paramName, paramNamePrefix, whereVal } = whereArgs;
464
- const pn = `${paramNamePrefix}${paramName}`;
465
- parameters[pn] = whereVal;
466
- return `startswith(${namePrefix}${name}, @${pn}, true)`;
467
- },
468
- endsWith: (ctx, parameters, whereArgs) => {
469
- const { name, namePrefix, paramName, paramNamePrefix, whereVal } = whereArgs;
470
- const pn = `${paramNamePrefix}${paramName}`;
471
- parameters[pn] = whereVal;
472
- return `endswith(${namePrefix}${name}, @${pn})`;
473
- },
474
- iendsWith: (ctx, parameters, whereArgs) => {
475
- const { name, namePrefix, paramName, paramNamePrefix, whereVal } = whereArgs;
476
- const pn = `${paramNamePrefix}${paramName}`;
477
- parameters[pn] = whereVal;
478
- return `endswith(${namePrefix}${name}, @${pn}, true)`;
479
- },
480
- contains: (ctx, parameters, whereArgs) => {
481
- const { name, namePrefix, paramName, paramNamePrefix, whereVal } = whereArgs;
482
- const fieldType = ctx.schema[ctx.entity].fields[ctx.field];
483
- const pn = `${paramNamePrefix}${paramName}`;
484
- parameters[pn] = whereVal;
485
- if (fieldType.isArray) {
486
- return `array_contains(${namePrefix}${name}, @${pn})`;
487
- }
488
- return `contains(${namePrefix}${name}, @${pn})`;
489
- },
490
- icontains: (ctx, parameters, whereArgs) => {
491
- const { name, namePrefix, paramName, paramNamePrefix, whereVal } = whereArgs;
492
- const pn = `${paramNamePrefix}${paramName}`;
493
- parameters[pn] = whereVal;
494
- return `contains(${namePrefix}${name}, @${pn}, true)`;
495
- },
496
- ieq: (ctx, parameters, whereArgs) => {
497
- const { name, namePrefix, paramName, paramNamePrefix, whereVal } = whereArgs;
498
- const pn = `${paramNamePrefix}${paramName}`;
499
- parameters[pn] = whereVal;
500
- return `stringequals(${namePrefix}${name}, @${pn}, true)`;
501
- },
502
- gt: (ctx, parameters, whereArgs) => {
503
- const { name, namePrefix, paramName, paramNamePrefix, whereVal } = whereArgs;
504
- const pn = `${paramNamePrefix}${paramName}`;
505
- parameters[pn] = whereVal;
506
- return `${namePrefix}${name} > @${pn}`;
507
- },
508
- gte: (ctx, parameters, whereArgs) => {
509
- const { name, namePrefix, paramName, paramNamePrefix, whereVal } = whereArgs;
510
- const pn = `${paramNamePrefix}${paramName}`;
511
- parameters[pn] = whereVal;
512
- return `${namePrefix}${name} >= @${pn}`;
513
- },
514
- lt: (ctx, parameters, whereArgs) => {
515
- const { name, namePrefix, paramName, paramNamePrefix, whereVal } = whereArgs;
516
- const pn = `${paramNamePrefix}${paramName}`;
517
- parameters[pn] = whereVal;
518
- return `${namePrefix}${name} < @${pn}`;
519
- },
520
- lte: (ctx, parameters, whereArgs) => {
521
- const { name, namePrefix, paramName, paramNamePrefix, whereVal } = whereArgs;
522
- const pn = `${paramNamePrefix}${paramName}`;
523
- parameters[pn] = whereVal;
524
- return `${namePrefix}${name} <= @${pn}`;
525
- }
526
- };
527
- function getCosmosQueryWhere(ctx, parameters, where, namePrefix = "r.", paramNamePrefix = "") {
528
- const whereClauses = [];
529
- for (const key in where) {
530
- const [nameFromWhere, operator] = getWhereNameOperatorPair(key);
531
- let name = nameFromWhere;
532
- if (name === "value") {
533
- name = `["${name}"]`;
534
- namePrefix = namePrefix.slice(0, -1);
535
- }
536
- const paramName = key;
537
- const whereVal = where[key];
538
- if (whereVal == null)
539
- continue;
540
- const f = getCosmosQueryWhereInner({ ...ctx, field: nameFromWhere }, parameters, {
541
- operator,
542
- whereVal,
543
- name,
544
- namePrefix,
545
- paramName,
546
- paramNamePrefix
547
- });
548
- if (f)
549
- whereClauses.push(f);
550
- }
551
- return whereClauses.join(" AND ");
552
- }
553
- function getCosmosQueryWhereInner(ctx, parameters, whereArgs) {
554
- const { operator, whereVal, name, namePrefix, paramName, paramNamePrefix } = whereArgs;
555
- if (!operator && _.isObject(whereVal)) {
556
- return getCosmosQueryWhere(ctx, parameters, whereVal, `${namePrefix}${name}.`, `${paramNamePrefix}${paramName}_`);
557
- }
558
- const fn = operatorHandlers[operator || "eq"];
559
- if (!fn)
560
- console.warn(`Unsupported operator: "${operator}"`);
561
- return fn(ctx, parameters, whereArgs);
562
- }
563
- function getCosmosContainerClient(options) {
564
- options = { databaseName: "main", containerName: "main", ...options };
565
- const { databaseName, containerName, endpoint } = options;
566
- const key = `${endpoint}|${databaseName}|${containerName}`;
567
- if (!containerClientCache[key]) {
568
- containerClientCache[key] = getCosmosDatabaseClient(options).container(containerName);
569
- }
570
- return containerClientCache[key];
571
- }
572
- function getCosmosDatabaseClient(options) {
573
- options = { databaseName: "main", containerName: "main", ...options };
574
- const { databaseName, endpoint } = options;
575
- const key = `${endpoint}|${databaseName}`;
576
- if (!databaseClientCache[key]) {
577
- databaseClientCache[key] = getCosmosAccountClient(options).database(databaseName);
578
- }
579
- return databaseClientCache[key];
580
- }
581
- function getCosmosAccountClient(options) {
582
- options = { databaseName: "main", containerName: "main", ...options };
583
- const { endpoint, accountKey } = options;
584
- const key = endpoint;
585
- if (!cosmosClientCache[key]) {
586
- cosmosClientCache[key] = new CosmosClient({ endpoint, key: accountKey, ...options.options });
587
- }
588
- return cosmosClientCache[key];
589
- }
590
- function getWhereNameOperatorPair(whereKey) {
591
- if (whereKey.startsWith("_type")) {
592
- const operator = whereKey.split("_")[2];
593
- return ["_type", operator];
594
- }
595
- return whereKey.split("_");
596
- }
597
-
598
265
  const computedPresets = {
599
266
  createdAt: ({ doc }) => {
600
267
  return doc.createdAt || (/* @__PURE__ */ new Date()).toISOString();
@@ -811,11 +478,10 @@ async function handleEffectsAfterPut(ctx, docs, beforePutResults) {
811
478
  return Promise.all(ctx.effects[ctx.typeName].map((ef, i) => ef.afterPut(ctx, docs, beforePutResults[i])));
812
479
  }
813
480
 
814
- const driverConstructors = { memory, restApi, azureCosmos };
815
- const drivers = {};
816
481
  function generateMethods(schema, validators, options) {
482
+ const drivers = {};
817
483
  const db = { _schema: schema };
818
- const opts = { computed: {}, driver: { type: "memory" }, ...options };
484
+ const opts = { computed: {}, driver: memory(), ...options };
819
485
  const effects = {};
820
486
  for (const key in schema) {
821
487
  effects[key] = [];
@@ -828,8 +494,8 @@ function generateMethods(schema, validators, options) {
828
494
  const { handle } = schema[key];
829
495
  if (!handle)
830
496
  throw new Error(`Missing handle for entity ${key}`);
831
- const driverInstance = getDriverInstance(schema, key, opts.driver);
832
497
  const computedContext = { schema, typeName: key, validators, options: opts, drivers, effects };
498
+ const driverInstance = getDriverInstance(schema, key, opts.driver, drivers);
833
499
  db[handle] = {
834
500
  getAgg: async (args, ctx) => {
835
501
  if (!args?.agg)
@@ -840,16 +506,17 @@ function generateMethods(schema, validators, options) {
840
506
  get: async (args, ctx) => {
841
507
  args = args || {};
842
508
  const result = await driverInstance.get(args, ctx);
843
- if (args.include)
844
- await handleInclude(schema, key, args.include, [result]);
845
- await handleComputed(schema, key, opts, [result]);
509
+ if (result && args.include)
510
+ await handleInclude(computedContext, args.include, [result]);
511
+ if (result)
512
+ await handleComputed(schema, key, opts, [result]);
846
513
  return result;
847
514
  },
848
515
  getMany: async (args, ctx) => {
849
516
  args = args || {};
850
517
  const result = await driverInstance.getMany(args, ctx);
851
518
  if (args.include)
852
- await handleInclude(schema, key, args.include, result.nodes);
519
+ await handleInclude(computedContext, args.include, result.nodes);
853
520
  await handleComputed(schema, key, opts, result.nodes);
854
521
  return result;
855
522
  },
@@ -857,7 +524,7 @@ function generateMethods(schema, validators, options) {
857
524
  args = args || {};
858
525
  const result = await driverInstance.getAll(args, ctx);
859
526
  if (args.include)
860
- await handleInclude(schema, key, args.include, result);
527
+ await handleInclude(computedContext, args.include, result);
861
528
  await handleComputed(schema, key, opts, result);
862
529
  return result;
863
530
  },
@@ -903,16 +570,17 @@ function generateMethods(schema, validators, options) {
903
570
  }
904
571
  return db;
905
572
  }
906
- async function handleInclude(schema, entityName, include, result) {
573
+ async function handleInclude(computedContext, include, result) {
907
574
  if (!result || !result.length || !include)
908
575
  return;
909
- const fields = schema[entityName].fields || {};
576
+ const { schema, typeName, drivers } = computedContext;
577
+ const fields = schema[typeName].fields || {};
910
578
  const relationsToInclude = _.keys(include).filter((key) => include[key] && schema[fields[key].type].decorators.entity);
911
579
  const downloadRelationsPromises = relationsToInclude.map(async (fieldName) => {
912
- const typeName = fields[fieldName].type;
913
- const type = schema[typeName];
580
+ const typeName2 = fields[fieldName].type;
581
+ const type = schema[typeName2];
914
582
  if (!type)
915
- throw new Error(`Cannot find entity ${typeName}`);
583
+ throw new Error(`Cannot find entity ${typeName2}`);
916
584
  const idsToGet = /* @__PURE__ */ new Set();
917
585
  for (const item of result) {
918
586
  if (!item)
@@ -928,7 +596,7 @@ async function handleInclude(schema, entityName, include, result) {
928
596
  idsToGet.add(id);
929
597
  }
930
598
  }
931
- const driverInstance = getExistingDriverInstance(typeName);
599
+ const driverInstance = getExistingDriverInstance(typeName2, drivers);
932
600
  const relatedEntities = await driverInstance.getAll({ where: { id_in: [...idsToGet] } });
933
601
  const relatedEntitiesById = _.keyBy(relatedEntities, "id");
934
602
  for (const item of result) {
@@ -944,28 +612,27 @@ async function handleInclude(schema, entityName, include, result) {
944
612
  continue;
945
613
  const relatedEntity = relatedEntitiesById[id];
946
614
  if (!relatedEntity)
947
- console.warn(`Cannot find ${typeName} with id "${id}" (for ${entityName}.${fieldName} with id "${item.id}")`);
615
+ console.warn(`Cannot find ${typeName2} with id "${id}" (for ${typeName2}.${fieldName} with id "${item.id}")`);
948
616
  Object.assign(fv, relatedEntity);
949
617
  }
950
618
  }
951
619
  });
952
620
  await Promise.all(downloadRelationsPromises);
953
621
  }
954
- function getExistingDriverInstance(entityName) {
622
+ function getExistingDriverInstance(entityName, drivers) {
955
623
  if (!drivers[entityName]) {
956
624
  throw new Error(`Driver for entity ${entityName} was not found!`);
957
625
  }
958
626
  return drivers[entityName];
959
627
  }
960
- function getDriverInstance(schema, key, driver) {
628
+ function getDriverInstance(schema, key, driver, drivers) {
961
629
  if (!drivers[key]) {
962
630
  drivers[key] = getDriverInstanceInner(schema, key, driver);
963
631
  }
964
632
  return drivers[key];
965
633
  }
966
- function getDriverInstanceInner(schema, key, driver) {
967
- const driverConstructor = driverConstructors[driver.type];
968
- const driverInstance = driverConstructor(schema, key, driver);
634
+ function getDriverInstanceInner(schema, key, driverConstructor) {
635
+ const driverInstance = driverConstructor(schema, key);
969
636
  async function getAll(args, ctx) {
970
637
  const result = [];
971
638
  let cursor = args.cursor;
@@ -1003,7 +670,7 @@ function getDriverInstanceInner(schema, key, driver) {
1003
670
  await driverInstance.putMany([data], ctx);
1004
671
  },
1005
672
  async clear() {
1006
- console.error(`"clear" not supported for driver "${driver.type}"`);
673
+ console.error(`"clear" not supported for driver "${driverInstance.driverName}"`);
1007
674
  },
1008
675
  ...driverInstance
1009
676
  };
@@ -11,7 +11,7 @@ const cosmosClientCache = {};
11
11
  const databaseClientCache = {};
12
12
  const containerClientCache = {};
13
13
  const simpleSubclauseRegex = /^[a-z0-9_@]+.[a-z0-9_@]+ = [a-z0-9_@.]+$/i;
14
- var _default = (schema, entity, options) => {
14
+ var _default = options => (schema, entity) => {
15
15
  const client = getCosmosContainerClient(options);
16
16
  async function getItemByIds(ids, ctx) {
17
17
  const {
@@ -37,6 +37,7 @@ var _default = (schema, entity, options) => {
37
37
  return r.resources;
38
38
  }
39
39
  const instance = {
40
+ driverName: "azureCosmos",
40
41
  async clear(ctx) {
41
42
  const responseIter = client.items.readAll();
42
43
  const items = await responseIter.fetchAll();
@@ -1,2 +1,2 @@
1
- declare const _default: (schema: Schema, entity: string, options: AzureCosmosDriverOptions) => MinimalDriver;
1
+ declare const _default: (options: AzureCosmosDriverOptions) => (schema: Schema, entity: string) => MinimalDriver;
2
2
  export default _default;
@@ -4,7 +4,7 @@ const cosmosClientCache = {};
4
4
  const databaseClientCache = {};
5
5
  const containerClientCache = {};
6
6
  const simpleSubclauseRegex = /^[a-z0-9_@]+.[a-z0-9_@]+ = [a-z0-9_@.]+$/i;
7
- export default (schema, entity, options) => {
7
+ export default (options) => (schema, entity) => {
8
8
  const client = getCosmosContainerClient(options);
9
9
  async function getItemByIds(ids, ctx) {
10
10
  const { query, parameters } = getCosmosQuery(schema, entity, { where: { id_in: ids } });
@@ -17,6 +17,7 @@ export default (schema, entity, options) => {
17
17
  return r.resources;
18
18
  }
19
19
  const instance = {
20
+ driverName: "azureCosmos",
20
21
  async clear(ctx) {
21
22
  const responseIter = client.items.readAll();
22
23
  const items = await responseIter.fetchAll();
@@ -38,7 +38,7 @@ const operatorFns = {
38
38
  return result;
39
39
  }
40
40
  };
41
- var _default = (schema, entity) => {
41
+ var _default = options => (schema, entity) => {
42
42
  let cache = {};
43
43
  function getItemById(id) {
44
44
  return cache[id] ?? null;
@@ -47,6 +47,7 @@ var _default = (schema, entity) => {
47
47
  return ids.map(id => cache[id]);
48
48
  }
49
49
  const instance = {
50
+ driverName: "memory",
50
51
  clear() {
51
52
  cache = {};
52
53
  },
@@ -1,5 +1,5 @@
1
1
  import type { GetAggArgsAny, GetManyArgsAny } from '@/typesClientEngine';
2
- declare const _default: (schema: Schema, entity: string) => MinimalDriver;
2
+ declare const _default: (options?: any) => (schema: Schema, entity: string) => MinimalDriver;
3
3
  export default _default;
4
4
  export declare function getAggFromArray(array: any[], args: GetAggArgsAny): Record<string, any>;
5
5
  export declare function queryArray(array: any[], args: GetManyArgsAny): {
@@ -30,7 +30,7 @@ const operatorFns = {
30
30
  return result;
31
31
  }
32
32
  };
33
- export default (schema, entity) => {
33
+ export default (options) => (schema, entity) => {
34
34
  let cache = {};
35
35
  function getItemById(id) {
36
36
  return cache[id] ?? null;
@@ -39,6 +39,7 @@ export default (schema, entity) => {
39
39
  return ids.map((id) => cache[id]);
40
40
  }
41
41
  const instance = {
42
+ driverName: "memory",
42
43
  clear() {
43
44
  cache = {};
44
45
  },
@@ -7,7 +7,7 @@ module.exports = void 0;
7
7
  var _lodash = _interopRequireDefault(require("lodash"));
8
8
  var _pluralize = _interopRequireDefault(require("pluralize"));
9
9
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
10
- var _default = (schema, entity, options) => {
10
+ var _default = options => (schema, entity) => {
11
11
  options = {
12
12
  baseUrl: "/api",
13
13
  fetch: globalThis.fetch,
@@ -17,6 +17,7 @@ var _default = (schema, entity, options) => {
17
17
  if (!options.fetch) throw new Error('Please provide "fetch" argument to rest driver definition');
18
18
  const pluralEntityName = _lodash.default.lowerFirst((0, _pluralize.default)(entity));
19
19
  const instance = {
20
+ driverName: "restApi",
20
21
  async getMany(args) {
21
22
  args = args || {};
22
23
  const response = await fetch(`${options.baseUrl}/${pluralEntityName}`, {
@@ -1,2 +1,2 @@
1
- declare const _default: (schema: Schema, entity: string, options: RestDriverOptions) => MinimalDriver;
1
+ declare const _default: (options: RestDriverOptions) => (schema: Schema, entity: string) => MinimalDriver;
2
2
  export default _default;
@@ -1,12 +1,13 @@
1
1
  import _ from "lodash";
2
2
  import pluralize from "pluralize";
3
- export default (schema, entity, options) => {
3
+ export default (options) => (schema, entity) => {
4
4
  options = { baseUrl: "/api", fetch: globalThis.fetch, ...options };
5
5
  const fetch = options.fetch || global.fetch;
6
6
  if (!options.fetch)
7
7
  throw new Error('Please provide "fetch" argument to rest driver definition');
8
8
  const pluralEntityName = _.lowerFirst(pluralize(entity));
9
9
  const instance = {
10
+ driverName: "restApi",
10
11
  async getMany(args) {
11
12
  args = args || {};
12
13
  const response = await fetch(`${options.baseUrl}/${pluralEntityName}`, {
package/package.json CHANGED
@@ -28,7 +28,7 @@
28
28
  "require": "./integrations/*.cjs"
29
29
  }
30
30
  },
31
- "version": "0.1.26",
31
+ "version": "0.1.28",
32
32
  "description": "Say goodbye to boilerplate code and hello to efficient and elegant syntax.",
33
33
  "keywords": [],
34
34
  "author": "",