rads-db 3.1.6 → 3.1.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/config.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { g as RadsConfig, T as TypeDefinition } from './types-1bda441b.js';
1
+ import { g as RadsConfig, T as TypeDefinition } from './types-5bfcdf8f.js';
2
2
  import '_rads-db';
3
3
 
4
4
  declare function defineRadsConfig(config: RadsConfig): RadsConfig;
package/dist/index.cjs CHANGED
@@ -156,6 +156,20 @@ const operatorFns = {
156
156
  return true;
157
157
  },
158
158
  arrayContains: (x, w) => x?.includes(w),
159
+ isEmpty: (x, w) => {
160
+ if (!x) {
161
+ if (w === true)
162
+ return true;
163
+ if (w === false)
164
+ return false;
165
+ return true;
166
+ }
167
+ if (w === true)
168
+ return x?.length === 0;
169
+ if (w === false)
170
+ return x?.length > 0;
171
+ return true;
172
+ },
159
173
  isNull: (x, w) => {
160
174
  if (w === true)
161
175
  return x == null;
@@ -276,7 +290,18 @@ function getFilter(where, namePrefix = "") {
276
290
  }
277
291
  if (andClauses.length === 0)
278
292
  return null;
279
- return (x) => andClauses.every((ac) => ac(x));
293
+ return (x) => resolveAndClauses(andClauses, x);
294
+ }
295
+ function resolveAndClauses(andClauses, x) {
296
+ let result = true;
297
+ for (const ac of andClauses) {
298
+ const clauseResult = ac(x);
299
+ if (clauseResult === false)
300
+ return false;
301
+ if (clauseResult == null)
302
+ result = void 0;
303
+ }
304
+ return result;
280
305
  }
281
306
  function getWhereNameOperatorPair(whereKey) {
282
307
  if (whereKey.startsWith("_type")) {
@@ -290,14 +315,14 @@ function getFilterInner(operator, whereVal, name, namePrefix) {
290
315
  return getFilter(whereVal, name);
291
316
  }
292
317
  if (operator === "some") {
293
- const f = getFilter(whereVal, namePrefix);
318
+ const f = getFilter(whereVal);
294
319
  return f && ((x) => {
295
320
  const val = ___default.get(x, name);
296
- return val === void 0 || val?.some(f);
321
+ return val?.some(f);
297
322
  });
298
323
  }
299
324
  if (operator === "none") {
300
- const f = getFilter(whereVal, namePrefix);
325
+ const f = getFilter(whereVal);
301
326
  return f && ((x) => !___default.get(x, name)?.some(f));
302
327
  }
303
328
  if (operator === "and") {
@@ -310,7 +335,7 @@ function getFilterInner(operator, whereVal, name, namePrefix) {
310
335
  }
311
336
  if (operator === "not") {
312
337
  const f = getFilter(whereVal, namePrefix);
313
- return f && ((x) => !f(x));
338
+ return f && ((x) => f(x) === false);
314
339
  }
315
340
  if (operator === "or") {
316
341
  if (!___default.isArray(whereVal))
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { E as EntityDecoratorArgs, U as UiDecoratorArgs, a as UiFieldDecoratorArgs, V as ValidateEntityDecoratorArgs, b as ValidateFieldDecoratorArgs, F as FieldDecoratorArgs, C as ComputedDecoratorArgs, S as Schema, D as DriverConstructor, c as Driver, d as ComputedContext, R as RadsRequestContext, e as CreateRadsDbArgs, f as CreateRadsDbClientArgs } from './types-1bda441b.js';
2
- export { N as Change, x as ComputedContextGlobal, k as CreateRadsArgsDrivers, m as CreateRadsDbArgsNormalized, aj as DeepKeys, ae as DeepPartial, ac as DeepPartialWithNulls, ad as DeepPartialWithNullsItem, ak as EntityMethods, w as EnumDefinition, v as FieldDefinition, I as FileSystemNode, u as FileUploadArgs, q as FileUploadDriver, p as FileUploadResult, B as GenerateClientNormalizedOptions, A as GenerateClientOptions, a8 as Get, _ as GetAggArgs, $ as GetAggArgsAgg, a2 as GetAggArgsAny, a5 as GetAggResponse, Z as GetArgs, a1 as GetArgsAny, a4 as GetArgsInclude, O as GetManyArgs, a0 as GetManyArgsAny, a6 as GetManyResponse, a7 as GetResponse, a9 as GetResponseInclude, aa as GetResponseIncludeSelect, ab as GetResponseNoInclude, s as GetRestRoutesArgs, G as GetRestRoutesOptions, t as GetRestRoutesResponse, ag as InverseRelation, M as MinimalDriver, ai as Put, ah as PutArgs, P as PutEffect, g as RadsConfig, h as RadsConfigDataSource, r as RadsDbInstance, L as RadsFeature, y as RadsHookDoc, K as RadsUiSlotDefinition, J as RadsUiSlotName, H as RadsVitePluginOptions, af as Relation, i as RequiredFields, l as RestDriverOptions, z as RestFileUploadDriverOptions, n as SchemaLoadResult, o as SchemaValidators, T as TypeDefinition, j as ValidateStringDecoratorArgs, Q as VerifyManyArgs, a3 as VerifyManyArgsAny, X as VerifyManyResponse, Y as Where, W as WhereJsonContains } from './types-1bda441b.js';
1
+ import { E as EntityDecoratorArgs, U as UiDecoratorArgs, a as UiFieldDecoratorArgs, V as ValidateEntityDecoratorArgs, b as ValidateFieldDecoratorArgs, F as FieldDecoratorArgs, C as ComputedDecoratorArgs, S as Schema, D as DriverConstructor, c as Driver, d as ComputedContext, R as RadsRequestContext, e as CreateRadsDbArgs, f as CreateRadsDbClientArgs } from './types-5bfcdf8f.js';
2
+ export { N as Change, x as ComputedContextGlobal, k as CreateRadsArgsDrivers, m as CreateRadsDbArgsNormalized, aj as DeepKeys, ae as DeepPartial, ac as DeepPartialWithNulls, ad as DeepPartialWithNullsItem, ak as EntityMethods, w as EnumDefinition, v as FieldDefinition, I as FileSystemNode, u as FileUploadArgs, q as FileUploadDriver, p as FileUploadResult, B as GenerateClientNormalizedOptions, A as GenerateClientOptions, a8 as Get, _ as GetAggArgs, $ as GetAggArgsAgg, a2 as GetAggArgsAny, a5 as GetAggResponse, Z as GetArgs, a1 as GetArgsAny, a4 as GetArgsInclude, O as GetManyArgs, a0 as GetManyArgsAny, a6 as GetManyResponse, a7 as GetResponse, a9 as GetResponseInclude, aa as GetResponseIncludeSelect, ab as GetResponseNoInclude, s as GetRestRoutesArgs, G as GetRestRoutesOptions, t as GetRestRoutesResponse, ag as InverseRelation, M as MinimalDriver, ai as Put, ah as PutArgs, P as PutEffect, g as RadsConfig, h as RadsConfigDataSource, r as RadsDbInstance, L as RadsFeature, y as RadsHookDoc, K as RadsUiSlotDefinition, J as RadsUiSlotName, H as RadsVitePluginOptions, af as Relation, i as RequiredFields, l as RestDriverOptions, z as RestFileUploadDriverOptions, n as SchemaLoadResult, o as SchemaValidators, T as TypeDefinition, j as ValidateStringDecoratorArgs, Q as VerifyManyArgs, a3 as VerifyManyArgsAny, X as VerifyManyResponse, Y as Where, W as WhereJsonContains } from './types-5bfcdf8f.js';
3
3
  import { RadsDb } from '_rads-db';
4
4
  export { RadsDb } from '_rads-db';
5
5
 
package/dist/index.mjs CHANGED
@@ -149,6 +149,20 @@ const operatorFns = {
149
149
  return true;
150
150
  },
151
151
  arrayContains: (x, w) => x?.includes(w),
152
+ isEmpty: (x, w) => {
153
+ if (!x) {
154
+ if (w === true)
155
+ return true;
156
+ if (w === false)
157
+ return false;
158
+ return true;
159
+ }
160
+ if (w === true)
161
+ return x?.length === 0;
162
+ if (w === false)
163
+ return x?.length > 0;
164
+ return true;
165
+ },
152
166
  isNull: (x, w) => {
153
167
  if (w === true)
154
168
  return x == null;
@@ -269,7 +283,18 @@ function getFilter(where, namePrefix = "") {
269
283
  }
270
284
  if (andClauses.length === 0)
271
285
  return null;
272
- return (x) => andClauses.every((ac) => ac(x));
286
+ return (x) => resolveAndClauses(andClauses, x);
287
+ }
288
+ function resolveAndClauses(andClauses, x) {
289
+ let result = true;
290
+ for (const ac of andClauses) {
291
+ const clauseResult = ac(x);
292
+ if (clauseResult === false)
293
+ return false;
294
+ if (clauseResult == null)
295
+ result = void 0;
296
+ }
297
+ return result;
273
298
  }
274
299
  function getWhereNameOperatorPair(whereKey) {
275
300
  if (whereKey.startsWith("_type")) {
@@ -283,14 +308,14 @@ function getFilterInner(operator, whereVal, name, namePrefix) {
283
308
  return getFilter(whereVal, name);
284
309
  }
285
310
  if (operator === "some") {
286
- const f = getFilter(whereVal, namePrefix);
311
+ const f = getFilter(whereVal);
287
312
  return f && ((x) => {
288
313
  const val = _.get(x, name);
289
- return val === void 0 || val?.some(f);
314
+ return val?.some(f);
290
315
  });
291
316
  }
292
317
  if (operator === "none") {
293
- const f = getFilter(whereVal, namePrefix);
318
+ const f = getFilter(whereVal);
294
319
  return f && ((x) => !_.get(x, name)?.some(f));
295
320
  }
296
321
  if (operator === "and") {
@@ -303,7 +328,7 @@ function getFilterInner(operator, whereVal, name, namePrefix) {
303
328
  }
304
329
  if (operator === "not") {
305
330
  const f = getFilter(whereVal, namePrefix);
306
- return f && ((x) => !f(x));
331
+ return f && ((x) => f(x) === false);
307
332
  }
308
333
  if (operator === "or") {
309
334
  if (!_.isArray(whereVal))
@@ -146,6 +146,7 @@ interface ValidateStringDecoratorArgs {
146
146
  regex?: RegExp | string;
147
147
  minLength?: number;
148
148
  maxLength?: number;
149
+ maxSizeKb?: number;
149
150
  }
150
151
  interface UiFieldDecoratorArgs {
151
152
  /** User-friendly name of the entity (singular).
@@ -101,11 +101,16 @@ var _default = options => (schema, entity) => {
101
101
  nodes,
102
102
  cursor
103
103
  } = await getMany(args, ctx);
104
- for (const r of nodes) {
105
- const resp = await client.item(r.id, r._partition).delete();
104
+ for (const chunk of _lodash.default.chunk(nodes, 100)) {
105
+ const chunkToSend = chunk.map(x => ({
106
+ operationType: "Delete",
107
+ partitionKey: x._partition,
108
+ id: x.id
109
+ }));
110
+ const responses = await bulkSendWithRetry(client, chunkToSend);
106
111
  ctx?.log?.({
107
- charge: resp.requestCharge,
108
- request: `delete#${r._partition}|${r.id}`
112
+ charge: _lodash.default.sumBy(responses, r => r.requestCharge),
113
+ request: `delete#${chunk[0]._partition}[${chunk.length}]`
109
114
  });
110
115
  }
111
116
  return {
@@ -125,32 +130,11 @@ var _default = options => (schema, entity) => {
125
130
  });
126
131
  }
127
132
  for (const chunk of _lodash.default.chunk(itemsToPut, 100)) {
128
- let chunkToSend = chunk.map(x => ({
133
+ const chunkToSend = chunk.map(x => ({
129
134
  operationType: "Upsert",
130
135
  resourceBody: x
131
136
  }));
132
- const responses = [];
133
- for (let i = 0; i < 20; i++) {
134
- const response = await client.items.bulk(chunkToSend);
135
- const newChunkToSend = [];
136
- for (let i2 = 0; i2 < chunkToSend.length; i2++) {
137
- if (response[i2].statusCode !== 429) {
138
- responses.push(response[i2]);
139
- } else {
140
- newChunkToSend.push(chunkToSend[i2]);
141
- }
142
- }
143
- chunkToSend = newChunkToSend;
144
- if (chunkToSend.length === 0) break;
145
- const delay = 50 + i * 100;
146
- console.warn(`Db overloaded. Retrying after ${delay}ms...`);
147
- await new Promise(resolve => setTimeout(resolve, delay));
148
- }
149
- if (chunkToSend.length !== 0) {
150
- throw new _cosmos.RestError("Db oveloaded. Too many retries. Consider increasing database RU setting.", {
151
- code: "429"
152
- });
153
- }
137
+ const responses = await bulkSendWithRetry(client, chunkToSend);
154
138
  ctx?.log?.({
155
139
  charge: _lodash.default.sumBy(responses, r => r.requestCharge),
156
140
  request: `put#${chunk[0]._partition}[${chunk.length}]`
@@ -192,11 +176,7 @@ const operatorHandlers = {
192
176
  paramName,
193
177
  whereVal
194
178
  } = whereArgs;
195
- const newCtx = {
196
- ...ctx,
197
- entity: ctx.schema[ctx.entity].fields[ctx.field].type
198
- };
199
- const subClause = getCosmosQueryWhere(newCtx, parameters, whereVal, `${name}.`, `${paramNamePrefix}${paramName}_`);
179
+ const subClause = getCosmosQueryWhere(ctx, parameters, whereVal, `${name}.`, `${paramNamePrefix}${paramName}_`);
200
180
  if (subClause) {
201
181
  if (simpleSubclauseRegex.test(subClause)) {
202
182
  const parts = subClause.split(" ");
@@ -216,11 +196,7 @@ const operatorHandlers = {
216
196
  paramName,
217
197
  whereVal
218
198
  } = whereArgs;
219
- const newCtx = {
220
- ...ctx,
221
- entity: ctx.schema[ctx.entity].fields[ctx.field].type
222
- };
223
- const subClause = getCosmosQueryWhere(newCtx, parameters, whereVal, `${name}.`, `${paramNamePrefix}${paramName}_`);
199
+ const subClause = getCosmosQueryWhere(ctx, parameters, whereVal, `${name}.`, `${paramNamePrefix}${paramName}_`);
224
200
  if (subClause) return `not exists (select ${name} from ${name} in ${namePrefix}${name} where ${subClause})`;
225
201
  return `array_length(${namePrefix}${name}) = 0`;
226
202
  },
@@ -383,6 +359,16 @@ const operatorHandlers = {
383
359
  parameters[pn] = whereVal;
384
360
  return `array_contains(${namePrefix}${name}, @${pn})`;
385
361
  },
362
+ isEmpty: (ctx, parameters, whereArgs) => {
363
+ const {
364
+ name,
365
+ namePrefix,
366
+ whereVal
367
+ } = whereArgs;
368
+ const n = `${namePrefix}${name}`;
369
+ if (whereVal) return `(not (is_defined(${n})) or ${n} = null or array_length(${n}) = 0)`;
370
+ return `(is_defined(${n}) and ${n} != null and array_length(${n}) > 0)`;
371
+ },
386
372
  jsonContains: (ctx, parameters, whereArgs) => {
387
373
  const {
388
374
  name,
@@ -578,4 +564,29 @@ async function createDatabaseIfNotExists(options, client) {
578
564
  } catch (e) {
579
565
  console.error("Error initializing CosmosDb: ", e);
580
566
  }
567
+ }
568
+ async function bulkSendWithRetry(client, chunkToSend) {
569
+ const responses = [];
570
+ for (let i = 0; i < 20; i++) {
571
+ const response = await client.items.bulk(chunkToSend);
572
+ const newChunkToSend = [];
573
+ for (let i2 = 0; i2 < chunkToSend.length; i2++) {
574
+ if (response[i2].statusCode !== 429) {
575
+ responses.push(response[i2]);
576
+ } else {
577
+ newChunkToSend.push(chunkToSend[i2]);
578
+ }
579
+ }
580
+ chunkToSend = newChunkToSend;
581
+ if (chunkToSend.length === 0) break;
582
+ const delay = 50 + i * 100;
583
+ console.warn(`Db overloaded. Retrying after ${delay}ms...`);
584
+ await new Promise(resolve => setTimeout(resolve, delay));
585
+ }
586
+ if (chunkToSend.length !== 0) {
587
+ throw new _cosmos.RestError("Db oveloaded. Too many retries. Consider increasing database RU setting.", {
588
+ code: "429"
589
+ });
590
+ }
591
+ return responses;
581
592
  }
@@ -66,9 +66,17 @@ export default (options) => (schema, entity) => {
66
66
  getMany,
67
67
  async deleteMany(args, ctx) {
68
68
  const { nodes, cursor } = await getMany(args, ctx);
69
- for (const r of nodes) {
70
- const resp = await client.item(r.id, r._partition).delete();
71
- ctx?.log?.({ charge: resp.requestCharge, request: `delete#${r._partition}|${r.id}` });
69
+ for (const chunk of _.chunk(nodes, 100)) {
70
+ const chunkToSend = chunk.map((x) => ({
71
+ operationType: "Delete",
72
+ partitionKey: x._partition,
73
+ id: x.id
74
+ }));
75
+ const responses = await bulkSendWithRetry(client, chunkToSend);
76
+ ctx?.log?.({
77
+ charge: _.sumBy(responses, (r) => r.requestCharge),
78
+ request: `delete#${chunk[0]._partition}[${chunk.length}]`
79
+ });
72
80
  }
73
81
  return { nodes, cursor };
74
82
  },
@@ -81,33 +89,11 @@ export default (options) => (schema, entity) => {
81
89
  itemsToPut.push({ _partition: entity, id, ...item });
82
90
  }
83
91
  for (const chunk of _.chunk(itemsToPut, 100)) {
84
- let chunkToSend = chunk.map((x) => ({
92
+ const chunkToSend = chunk.map((x) => ({
85
93
  operationType: "Upsert",
86
94
  resourceBody: x
87
95
  }));
88
- const responses = [];
89
- for (let i = 0; i < 20; i++) {
90
- const response = await client.items.bulk(chunkToSend);
91
- const newChunkToSend = [];
92
- for (let i2 = 0; i2 < chunkToSend.length; i2++) {
93
- if (response[i2].statusCode !== 429) {
94
- responses.push(response[i2]);
95
- } else {
96
- newChunkToSend.push(chunkToSend[i2]);
97
- }
98
- }
99
- chunkToSend = newChunkToSend;
100
- if (chunkToSend.length === 0)
101
- break;
102
- const delay = 50 + i * 100;
103
- console.warn(`Db overloaded. Retrying after ${delay}ms...`);
104
- await new Promise((resolve) => setTimeout(resolve, delay));
105
- }
106
- if (chunkToSend.length !== 0) {
107
- throw new RestError("Db oveloaded. Too many retries. Consider increasing database RU setting.", {
108
- code: "429"
109
- });
110
- }
96
+ const responses = await bulkSendWithRetry(client, chunkToSend);
111
97
  ctx?.log?.({
112
98
  charge: _.sumBy(responses, (r) => r.requestCharge),
113
99
  request: `put#${chunk[0]._partition}[${chunk.length}]`
@@ -139,8 +125,7 @@ function getCosmosQuery(schema, entity, args) {
139
125
  const operatorHandlers = {
140
126
  some: (ctx, parameters, whereArgs) => {
141
127
  const { name, namePrefix, paramNamePrefix, paramName, whereVal } = whereArgs;
142
- const newCtx = { ...ctx, entity: ctx.schema[ctx.entity].fields[ctx.field].type };
143
- const subClause = getCosmosQueryWhere(newCtx, parameters, whereVal, `${name}.`, `${paramNamePrefix}${paramName}_`);
128
+ const subClause = getCosmosQueryWhere(ctx, parameters, whereVal, `${name}.`, `${paramNamePrefix}${paramName}_`);
144
129
  if (subClause) {
145
130
  if (simpleSubclauseRegex.test(subClause)) {
146
131
  const parts = subClause.split(" ");
@@ -154,8 +139,7 @@ const operatorHandlers = {
154
139
  },
155
140
  none: (ctx, parameters, whereArgs) => {
156
141
  const { name, namePrefix, paramNamePrefix, paramName, whereVal } = whereArgs;
157
- const newCtx = { ...ctx, entity: ctx.schema[ctx.entity].fields[ctx.field].type };
158
- const subClause = getCosmosQueryWhere(newCtx, parameters, whereVal, `${name}.`, `${paramNamePrefix}${paramName}_`);
142
+ const subClause = getCosmosQueryWhere(ctx, parameters, whereVal, `${name}.`, `${paramNamePrefix}${paramName}_`);
159
143
  if (subClause)
160
144
  return `not exists (select ${name} from ${name} in ${namePrefix}${name} where ${subClause})`;
161
145
  return `array_length(${namePrefix}${name}) = 0`;
@@ -254,6 +238,13 @@ const operatorHandlers = {
254
238
  parameters[pn] = whereVal;
255
239
  return `array_contains(${namePrefix}${name}, @${pn})`;
256
240
  },
241
+ isEmpty: (ctx, parameters, whereArgs) => {
242
+ const { name, namePrefix, whereVal } = whereArgs;
243
+ const n = `${namePrefix}${name}`;
244
+ if (whereVal)
245
+ return `(not (is_defined(${n})) or ${n} = null or array_length(${n}) = 0)`;
246
+ return `(is_defined(${n}) and ${n} != null and array_length(${n}) > 0)`;
247
+ },
257
248
  jsonContains: (ctx, parameters, whereArgs) => {
258
249
  const { name, namePrefix, paramName, paramNamePrefix, whereVal } = whereArgs;
259
250
  const { path, isNull, value } = whereVal;
@@ -385,3 +376,29 @@ async function createDatabaseIfNotExists(options, client) {
385
376
  console.error("Error initializing CosmosDb: ", e);
386
377
  }
387
378
  }
379
+ async function bulkSendWithRetry(client, chunkToSend) {
380
+ const responses = [];
381
+ for (let i = 0; i < 20; i++) {
382
+ const response = await client.items.bulk(chunkToSend);
383
+ const newChunkToSend = [];
384
+ for (let i2 = 0; i2 < chunkToSend.length; i2++) {
385
+ if (response[i2].statusCode !== 429) {
386
+ responses.push(response[i2]);
387
+ } else {
388
+ newChunkToSend.push(chunkToSend[i2]);
389
+ }
390
+ }
391
+ chunkToSend = newChunkToSend;
392
+ if (chunkToSend.length === 0)
393
+ break;
394
+ const delay = 50 + i * 100;
395
+ console.warn(`Db overloaded. Retrying after ${delay}ms...`);
396
+ await new Promise((resolve) => setTimeout(resolve, delay));
397
+ }
398
+ if (chunkToSend.length !== 0) {
399
+ throw new RestError("Db oveloaded. Too many retries. Consider increasing database RU setting.", {
400
+ code: "429"
401
+ });
402
+ }
403
+ return responses;
404
+ }
@@ -31,36 +31,50 @@ var _default = options => {
31
31
  const handle = schema[entity]?.handle;
32
32
  if (!handle) throw new Error(`Entity ${entity} not found`);
33
33
  dbWrapper.entities[handle] = true;
34
- return {
35
- driverName: "indexedDb",
36
- async getMany(args, ctx) {
37
- await initDbIfNeeded(dbName);
38
- const normalizedArgs = normalizeArgs(args);
39
- const dexieResult = applyArgsToDexieTable(dbWrapper.db.table(handle), normalizedArgs);
40
- let resultCursor;
41
- const newCursor = normalizedArgs.cursor + dexieResult.maxItemCount;
42
- let result = await dexieResult.collection.toArray();
43
- if (dexieResult.orderByProp) {
44
- result = _lodash.default.orderBy(result, [dexieResult.orderByProp], [dexieResult.orderByDirection.toLowerCase()]);
45
- if (dexieResult.maxItemCount) {
46
- if (result.length > newCursor) {
47
- resultCursor = newCursor;
48
- }
49
- result = result.slice(normalizedArgs.cursor, newCursor);
34
+ async function getMany(args, ctx) {
35
+ await initDbIfNeeded(dbName);
36
+ const normalizedArgs = normalizeArgs(args);
37
+ const dexieResult = applyArgsToDexieTable(dbWrapper.db.table(handle), normalizedArgs);
38
+ let resultCursor;
39
+ const newCursor = normalizedArgs.cursor + dexieResult.maxItemCount;
40
+ let result = await dexieResult.collection.toArray();
41
+ if (dexieResult.orderByProp) {
42
+ result = _lodash.default.orderBy(result, [dexieResult.orderByProp], [dexieResult.orderByDirection.toLowerCase()]);
43
+ if (dexieResult.maxItemCount) {
44
+ if (result.length > newCursor) {
45
+ resultCursor = newCursor;
50
46
  }
51
- return {
52
- nodes: result,
53
- cursor: resultCursor ? _lodash.default.toString(resultCursor) : null
54
- };
55
- }
56
- if (dexieResult.maxItemCount && result.length >= dexieResult.maxItemCount) {
57
- resultCursor = newCursor;
47
+ result = result.slice(normalizedArgs.cursor, newCursor);
58
48
  }
59
49
  return {
60
50
  nodes: result,
61
51
  cursor: resultCursor ? _lodash.default.toString(resultCursor) : null
62
52
  };
53
+ }
54
+ if (dexieResult.maxItemCount && result.length >= dexieResult.maxItemCount) {
55
+ resultCursor = newCursor;
56
+ }
57
+ return {
58
+ nodes: result,
59
+ cursor: resultCursor ? _lodash.default.toString(resultCursor) : null
60
+ };
61
+ }
62
+ return {
63
+ driverName: "indexedDb",
64
+ async deleteMany(args, ctx) {
65
+ await initDbIfNeeded(dbName);
66
+ const {
67
+ nodes,
68
+ cursor
69
+ } = await getMany(args, ctx);
70
+ const table = dbWrapper.db.table(handle);
71
+ await table.bulkDelete(nodes.map(x => x.id));
72
+ return {
73
+ nodes,
74
+ cursor
75
+ };
63
76
  },
77
+ getMany,
64
78
  async putMany(items, ctx) {
65
79
  await initDbIfNeeded(dbName);
66
80
  const table = dbWrapper.db.table(handle);
@@ -98,7 +112,7 @@ function applyArgsToDexieTable(table, args) {
98
112
  }
99
113
  const f = (0, _memory.getFilter)(where);
100
114
  if (f) {
101
- collection = collection.filter(f);
115
+ collection = collection.filter(x => f(x) || false);
102
116
  }
103
117
  if (maxItemCount && !orderByProp) {
104
118
  if (args.cursor) collection = collection.offset(_lodash.default.toNumber(args.cursor));
@@ -25,30 +25,38 @@ export default (options) => {
25
25
  if (!handle)
26
26
  throw new Error(`Entity ${entity} not found`);
27
27
  dbWrapper.entities[handle] = true;
28
- return {
29
- driverName: "indexedDb",
30
- async getMany(args, ctx) {
31
- await initDbIfNeeded(dbName);
32
- const normalizedArgs = normalizeArgs(args);
33
- const dexieResult = applyArgsToDexieTable(dbWrapper.db.table(handle), normalizedArgs);
34
- let resultCursor;
35
- const newCursor = normalizedArgs.cursor + dexieResult.maxItemCount;
36
- let result = await dexieResult.collection.toArray();
37
- if (dexieResult.orderByProp) {
38
- result = _.orderBy(result, [dexieResult.orderByProp], [dexieResult.orderByDirection.toLowerCase()]);
39
- if (dexieResult.maxItemCount) {
40
- if (result.length > newCursor) {
41
- resultCursor = newCursor;
42
- }
43
- result = result.slice(normalizedArgs.cursor, newCursor);
28
+ async function getMany(args, ctx) {
29
+ await initDbIfNeeded(dbName);
30
+ const normalizedArgs = normalizeArgs(args);
31
+ const dexieResult = applyArgsToDexieTable(dbWrapper.db.table(handle), normalizedArgs);
32
+ let resultCursor;
33
+ const newCursor = normalizedArgs.cursor + dexieResult.maxItemCount;
34
+ let result = await dexieResult.collection.toArray();
35
+ if (dexieResult.orderByProp) {
36
+ result = _.orderBy(result, [dexieResult.orderByProp], [dexieResult.orderByDirection.toLowerCase()]);
37
+ if (dexieResult.maxItemCount) {
38
+ if (result.length > newCursor) {
39
+ resultCursor = newCursor;
44
40
  }
45
- return { nodes: result, cursor: resultCursor ? _.toString(resultCursor) : null };
46
- }
47
- if (dexieResult.maxItemCount && result.length >= dexieResult.maxItemCount) {
48
- resultCursor = newCursor;
41
+ result = result.slice(normalizedArgs.cursor, newCursor);
49
42
  }
50
43
  return { nodes: result, cursor: resultCursor ? _.toString(resultCursor) : null };
44
+ }
45
+ if (dexieResult.maxItemCount && result.length >= dexieResult.maxItemCount) {
46
+ resultCursor = newCursor;
47
+ }
48
+ return { nodes: result, cursor: resultCursor ? _.toString(resultCursor) : null };
49
+ }
50
+ return {
51
+ driverName: "indexedDb",
52
+ async deleteMany(args, ctx) {
53
+ await initDbIfNeeded(dbName);
54
+ const { nodes, cursor } = await getMany(args, ctx);
55
+ const table = dbWrapper.db.table(handle);
56
+ await table.bulkDelete(nodes.map((x) => x.id));
57
+ return { nodes, cursor };
51
58
  },
59
+ getMany,
52
60
  async putMany(items, ctx) {
53
61
  await initDbIfNeeded(dbName);
54
62
  const table = dbWrapper.db.table(handle);
@@ -81,7 +89,7 @@ function applyArgsToDexieTable(table, args) {
81
89
  }
82
90
  const f = getFilter(where);
83
91
  if (f) {
84
- collection = collection.filter(f);
92
+ collection = collection.filter((x) => f(x) || false);
85
93
  }
86
94
  if (maxItemCount && !orderByProp) {
87
95
  if (args.cursor)
@@ -33,6 +33,16 @@ const operatorFns = {
33
33
  return true;
34
34
  },
35
35
  arrayContains: (x, w) => x?.includes(w),
36
+ isEmpty: (x, w) => {
37
+ if (!x) {
38
+ if (w === true) return true;
39
+ if (w === false) return false;
40
+ return true;
41
+ }
42
+ if (w === true) return x?.length === 0;
43
+ if (w === false) return x?.length > 0;
44
+ return true;
45
+ },
36
46
  isNull: (x, w) => {
37
47
  if (w === true) return x == null;
38
48
  if (w === false) return x != null;
@@ -154,7 +164,16 @@ function getFilter(where, namePrefix = "") {
154
164
  if (f) andClauses.push(f);
155
165
  }
156
166
  if (andClauses.length === 0) return null;
157
- return x => andClauses.every(ac => ac(x));
167
+ return x => resolveAndClauses(andClauses, x);
168
+ }
169
+ function resolveAndClauses(andClauses, x) {
170
+ let result = true;
171
+ for (const ac of andClauses) {
172
+ const clauseResult = ac(x);
173
+ if (clauseResult === false) return false;
174
+ if (clauseResult == null) result = void 0;
175
+ }
176
+ return result;
158
177
  }
159
178
  function getWhereNameOperatorPair(whereKey) {
160
179
  if (whereKey.startsWith("_type")) {
@@ -168,14 +187,14 @@ function getFilterInner(operator, whereVal, name, namePrefix) {
168
187
  return getFilter(whereVal, name);
169
188
  }
170
189
  if (operator === "some") {
171
- const f = getFilter(whereVal, namePrefix);
190
+ const f = getFilter(whereVal);
172
191
  return f && (x => {
173
192
  const val = _lodash.default.get(x, name);
174
- return val === void 0 || val?.some(f);
193
+ return val?.some(f);
175
194
  });
176
195
  }
177
196
  if (operator === "none") {
178
- const f = getFilter(whereVal, namePrefix);
197
+ const f = getFilter(whereVal);
179
198
  return f && (x => !_lodash.default.get(x, name)?.some(f));
180
199
  }
181
200
  if (operator === "and") {
@@ -186,7 +205,7 @@ function getFilterInner(operator, whereVal, name, namePrefix) {
186
205
  }
187
206
  if (operator === "not") {
188
207
  const f = getFilter(whereVal, namePrefix);
189
- return f && (x => !f(x));
208
+ return f && (x => f(x) === false);
190
209
  }
191
210
  if (operator === "or") {
192
211
  if (!_lodash.default.isArray(whereVal)) throw new Error(`Value for where._or must be an array`);
@@ -8,4 +8,4 @@ export declare function queryArray(array: any[], args: GetManyArgsAny): {
8
8
  nodes: any;
9
9
  cursor: any;
10
10
  };
11
- export declare function getFilter(where: Record<string, any>, namePrefix?: string): ((x: any) => boolean) | null;
11
+ export declare function getFilter(where: Record<string, any>, namePrefix?: string): ((x: any) => boolean | undefined) | null;
@@ -23,6 +23,20 @@ const operatorFns = {
23
23
  return true;
24
24
  },
25
25
  arrayContains: (x, w) => x?.includes(w),
26
+ isEmpty: (x, w) => {
27
+ if (!x) {
28
+ if (w === true)
29
+ return true;
30
+ if (w === false)
31
+ return false;
32
+ return true;
33
+ }
34
+ if (w === true)
35
+ return x?.length === 0;
36
+ if (w === false)
37
+ return x?.length > 0;
38
+ return true;
39
+ },
26
40
  isNull: (x, w) => {
27
41
  if (w === true)
28
42
  return x == null;
@@ -143,7 +157,18 @@ export function getFilter(where, namePrefix = "") {
143
157
  }
144
158
  if (andClauses.length === 0)
145
159
  return null;
146
- return (x) => andClauses.every((ac) => ac(x));
160
+ return (x) => resolveAndClauses(andClauses, x);
161
+ }
162
+ function resolveAndClauses(andClauses, x) {
163
+ let result = true;
164
+ for (const ac of andClauses) {
165
+ const clauseResult = ac(x);
166
+ if (clauseResult === false)
167
+ return false;
168
+ if (clauseResult == null)
169
+ result = void 0;
170
+ }
171
+ return result;
147
172
  }
148
173
  function getWhereNameOperatorPair(whereKey) {
149
174
  if (whereKey.startsWith("_type")) {
@@ -157,14 +182,14 @@ function getFilterInner(operator, whereVal, name, namePrefix) {
157
182
  return getFilter(whereVal, name);
158
183
  }
159
184
  if (operator === "some") {
160
- const f = getFilter(whereVal, namePrefix);
185
+ const f = getFilter(whereVal);
161
186
  return f && ((x) => {
162
187
  const val = _.get(x, name);
163
- return val === void 0 || val?.some(f);
188
+ return val?.some(f);
164
189
  });
165
190
  }
166
191
  if (operator === "none") {
167
- const f = getFilter(whereVal, namePrefix);
192
+ const f = getFilter(whereVal);
168
193
  return f && ((x) => !_.get(x, name)?.some(f));
169
194
  }
170
195
  if (operator === "and") {
@@ -177,7 +202,7 @@ function getFilterInner(operator, whereVal, name, namePrefix) {
177
202
  }
178
203
  if (operator === "not") {
179
204
  const f = getFilter(whereVal, namePrefix);
180
- return f && ((x) => !f(x));
205
+ return f && ((x) => f(x) === false);
181
206
  }
182
207
  if (operator === "or") {
183
208
  if (!_.isArray(whereVal))
@@ -205,9 +205,12 @@ function getWhereFieldsFor(schema, type, fieldKey) {
205
205
  const isPrimitive = !fieldType;
206
206
  const isEnum = !!fieldType?.enumValues;
207
207
  const isObject = !!fieldType?.fields;
208
- const isRelation = field.isRelation;
209
- const isRequired = field.isRequired;
210
- const isArray = field.isArray;
208
+ const {
209
+ isRelation,
210
+ isRequired,
211
+ isArray,
212
+ isChange
213
+ } = field;
211
214
  if (isArray) {
212
215
  const arrayWhereFields = [`${name}_isEmpty?: boolean`];
213
216
  if (!isRequired) arrayWhereFields.push(`${name}_isNull?: boolean`);
@@ -228,6 +231,9 @@ function getWhereFieldsFor(schema, type, fieldKey) {
228
231
  return [`${name}?: ${getRelationWhereType()}`, ...commonWhereFields];
229
232
  }
230
233
  if (isObject) {
234
+ if (isChange) {
235
+ return [`${name}?: Omit<${fieldTypeName}_Where, 'id'>`, `${name}_jsonContains?: WhereJsonContains`, ...commonWhereFields];
236
+ }
231
237
  return [`${name}?: ${fieldTypeName}_Where`, ...commonWhereFields];
232
238
  }
233
239
  if (isEnum) {
@@ -223,9 +223,7 @@ function getWhereFieldsFor(schema, type, fieldKey) {
223
223
  const isPrimitive = !fieldType;
224
224
  const isEnum = !!fieldType?.enumValues;
225
225
  const isObject = !!fieldType?.fields;
226
- const isRelation = field.isRelation;
227
- const isRequired = field.isRequired;
228
- const isArray = field.isArray;
226
+ const { isRelation, isRequired, isArray, isChange } = field;
229
227
  if (isArray) {
230
228
  const arrayWhereFields = [`${name}_isEmpty?: boolean`];
231
229
  if (!isRequired)
@@ -248,6 +246,13 @@ function getWhereFieldsFor(schema, type, fieldKey) {
248
246
  return [`${name}?: ${getRelationWhereType()}`, ...commonWhereFields];
249
247
  }
250
248
  if (isObject) {
249
+ if (isChange) {
250
+ return [
251
+ `${name}?: Omit<${fieldTypeName}_Where, 'id'>`,
252
+ `${name}_jsonContains?: WhereJsonContains`,
253
+ ...commonWhereFields
254
+ ];
255
+ }
251
256
  return [`${name}?: ${fieldTypeName}_Where`, ...commonWhereFields];
252
257
  }
253
258
  if (isEnum) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rads-db",
3
- "version": "3.1.6",
3
+ "version": "3.1.8",
4
4
  "packageManager": "pnpm@8.6.1",
5
5
  "description": "Say goodbye to boilerplate code and hello to efficient and elegant syntax.",
6
6
  "author": "",