rads-db 0.1.27 → 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 +8 -344
- package/dist/index.d.ts +6 -8
- package/dist/index.mjs +8 -343
- package/drivers/azureCosmos.cjs +2 -1
- package/drivers/azureCosmos.d.ts +1 -1
- package/drivers/azureCosmos.mjs +2 -1
- package/drivers/memory.cjs +2 -1
- package/drivers/memory.d.ts +1 -1
- package/drivers/memory.mjs +2 -1
- package/drivers/restApi.cjs +2 -1
- package/drivers/restApi.d.ts +1 -1
- package/drivers/restApi.mjs +2 -1
- package/package.json +1 -1
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
|
|
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
|
|
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
487
|
function generateMethods(schema, validators, options) {
|
|
823
488
|
const drivers = {};
|
|
824
489
|
const db = { _schema: schema };
|
|
825
|
-
const opts = { computed: {}, driver:
|
|
490
|
+
const opts = { computed: {}, driver: memory(), ...options };
|
|
826
491
|
const effects = {};
|
|
827
492
|
for (const key in schema) {
|
|
828
493
|
effects[key] = [];
|
|
@@ -972,9 +637,8 @@ function getDriverInstance(schema, key, driver, drivers) {
|
|
|
972
637
|
}
|
|
973
638
|
return drivers[key];
|
|
974
639
|
}
|
|
975
|
-
function getDriverInstanceInner(schema, key,
|
|
976
|
-
const
|
|
977
|
-
const driverInstance = driverConstructor(schema, key, driver);
|
|
640
|
+
function getDriverInstanceInner(schema, key, driverConstructor) {
|
|
641
|
+
const driverInstance = driverConstructor(schema, key);
|
|
978
642
|
async function getAll(args, ctx) {
|
|
979
643
|
const result = [];
|
|
980
644
|
let cursor = args.cursor;
|
|
@@ -1012,7 +676,7 @@ function getDriverInstanceInner(schema, key, driver) {
|
|
|
1012
676
|
await driverInstance.putMany([data], ctx);
|
|
1013
677
|
},
|
|
1014
678
|
async clear() {
|
|
1015
|
-
console.error(`"clear" not supported for driver "${
|
|
679
|
+
console.error(`"clear" not supported for driver "${driverInstance.driverName}"`);
|
|
1016
680
|
},
|
|
1017
681
|
...driverInstance
|
|
1018
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?:
|
|
79
|
-
drivers?: Record<string,
|
|
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
|
|
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
|
|
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
481
|
function generateMethods(schema, validators, options) {
|
|
816
482
|
const drivers = {};
|
|
817
483
|
const db = { _schema: schema };
|
|
818
|
-
const opts = { computed: {}, driver:
|
|
484
|
+
const opts = { computed: {}, driver: memory(), ...options };
|
|
819
485
|
const effects = {};
|
|
820
486
|
for (const key in schema) {
|
|
821
487
|
effects[key] = [];
|
|
@@ -965,9 +631,8 @@ function getDriverInstance(schema, key, driver, drivers) {
|
|
|
965
631
|
}
|
|
966
632
|
return drivers[key];
|
|
967
633
|
}
|
|
968
|
-
function getDriverInstanceInner(schema, key,
|
|
969
|
-
const
|
|
970
|
-
const driverInstance = driverConstructor(schema, key, driver);
|
|
634
|
+
function getDriverInstanceInner(schema, key, driverConstructor) {
|
|
635
|
+
const driverInstance = driverConstructor(schema, key);
|
|
971
636
|
async function getAll(args, ctx) {
|
|
972
637
|
const result = [];
|
|
973
638
|
let cursor = args.cursor;
|
|
@@ -1005,7 +670,7 @@ function getDriverInstanceInner(schema, key, driver) {
|
|
|
1005
670
|
await driverInstance.putMany([data], ctx);
|
|
1006
671
|
},
|
|
1007
672
|
async clear() {
|
|
1008
|
-
console.error(`"clear" not supported for driver "${
|
|
673
|
+
console.error(`"clear" not supported for driver "${driverInstance.driverName}"`);
|
|
1009
674
|
},
|
|
1010
675
|
...driverInstance
|
|
1011
676
|
};
|
package/drivers/azureCosmos.cjs
CHANGED
|
@@ -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
|
|
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();
|
package/drivers/azureCosmos.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
declare const _default: (schema: Schema, entity: string
|
|
1
|
+
declare const _default: (options: AzureCosmosDriverOptions) => (schema: Schema, entity: string) => MinimalDriver;
|
|
2
2
|
export default _default;
|
package/drivers/azureCosmos.mjs
CHANGED
|
@@ -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
|
|
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();
|
package/drivers/memory.cjs
CHANGED
|
@@ -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
|
},
|
package/drivers/memory.d.ts
CHANGED
|
@@ -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): {
|
package/drivers/memory.mjs
CHANGED
|
@@ -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
|
},
|
package/drivers/restApi.cjs
CHANGED
|
@@ -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
|
|
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}`, {
|
package/drivers/restApi.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
declare const _default: (schema: Schema, entity: string
|
|
1
|
+
declare const _default: (options: RestDriverOptions) => (schema: Schema, entity: string) => MinimalDriver;
|
|
2
2
|
export default _default;
|
package/drivers/restApi.mjs
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import _ from "lodash";
|
|
2
2
|
import pluralize from "pluralize";
|
|
3
|
-
export default (schema, entity
|
|
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}`, {
|