rads-db 0.1.103 → 0.1.105
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/drivers/indexedDb.cjs +186 -470
- package/drivers/indexedDb.d.ts +7 -9
- package/drivers/indexedDb.mjs +159 -294
- package/drivers/memory.cjs +1 -0
- package/drivers/memory.d.ts +1 -0
- package/drivers/memory.mjs +1 -1
- package/package.json +7 -1
package/drivers/indexedDb.cjs
CHANGED
|
@@ -4,500 +4,216 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
module.exports = void 0;
|
|
7
|
-
var
|
|
7
|
+
var _dexie = _interopRequireDefault(require("dexie"));
|
|
8
8
|
var _lodash = _interopRequireDefault(require("lodash"));
|
|
9
|
+
var _memory = require("./memory.cjs");
|
|
9
10
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
10
|
-
const
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
ctx?.log?.({
|
|
34
|
-
charge: r.requestCharge,
|
|
35
|
-
request: query
|
|
36
|
-
});
|
|
37
|
-
return r.resources;
|
|
38
|
-
}
|
|
39
|
-
async function getMany(args, ctx) {
|
|
40
|
-
args = args || {};
|
|
41
|
-
const where = args.where || {};
|
|
42
|
-
const whereKeys = _lodash.default.keys(where);
|
|
43
|
-
if (whereKeys.length === 1) {
|
|
44
|
-
if (whereKeys[0] === "id" && where.id != null) {
|
|
45
|
-
const items = await getItemByIds([where.id], ctx);
|
|
46
|
-
return {
|
|
47
|
-
nodes: [items[0]].filter(x => x),
|
|
48
|
-
cursor: null
|
|
49
|
-
};
|
|
50
|
-
}
|
|
51
|
-
if (whereKeys[0] === "id_in" && where.id_in != null) {
|
|
52
|
-
const items = await getItemByIds(where.id_in, ctx);
|
|
53
|
-
return {
|
|
54
|
-
nodes: items.filter(x => x),
|
|
55
|
-
cursor: null
|
|
56
|
-
};
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
const {
|
|
60
|
-
query,
|
|
61
|
-
parameters
|
|
62
|
-
} = getCosmosQuery(schema, entity, args);
|
|
63
|
-
const response = client.items.query({
|
|
64
|
-
query,
|
|
65
|
-
parameters: Object.keys(parameters).map(k => ({
|
|
66
|
-
name: `@${k}`,
|
|
67
|
-
value: parameters[k]
|
|
68
|
-
}))
|
|
69
|
-
}, {
|
|
70
|
-
continuationToken: args.cursor || void 0,
|
|
71
|
-
continuationTokenLimitInKB: 4,
|
|
72
|
-
maxItemCount: args.maxItemCount
|
|
73
|
-
});
|
|
74
|
-
const page = await response.fetchNext();
|
|
75
|
-
ctx?.log?.({
|
|
76
|
-
charge: page.requestCharge,
|
|
77
|
-
request: query
|
|
78
|
-
});
|
|
11
|
+
const dbs = {};
|
|
12
|
+
const tableOperatorFns = {
|
|
13
|
+
eq: (where, value) => where.equals(value),
|
|
14
|
+
ieq: (where, value) => where.equalsIgnoreCase(value),
|
|
15
|
+
in: (where, value) => where.anyOf(value),
|
|
16
|
+
startsWith: (where, value) => where.startsWith(value),
|
|
17
|
+
istartsWith: (where, value) => where.startsWithIgnoreCase(value),
|
|
18
|
+
gt: (where, value) => where.above(value),
|
|
19
|
+
lt: (where, value) => where.below(value)
|
|
20
|
+
};
|
|
21
|
+
const tableOperatorNotFns = {
|
|
22
|
+
eq: (where, value) => where.notEqual(value),
|
|
23
|
+
in: (where, value) => where.noneOf(value),
|
|
24
|
+
gt: (where, value) => where.belowOrEqual(value),
|
|
25
|
+
lt: (where, value) => where.aboveOrEqual(value)
|
|
26
|
+
};
|
|
27
|
+
var _default = options => {
|
|
28
|
+
const dbName = options?.dbName || "db";
|
|
29
|
+
const dbWrapper = getDb(options);
|
|
30
|
+
return (schema, entity) => {
|
|
31
|
+
const handle = schema[entity]?.handle;
|
|
32
|
+
if (!handle) throw new Error(`Entity ${entity} not found`);
|
|
33
|
+
dbWrapper.entities[handle] = true;
|
|
79
34
|
return {
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
request: `delete#${r._partition}|${r.id}`
|
|
101
|
-
});
|
|
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);
|
|
50
|
+
}
|
|
51
|
+
return {
|
|
52
|
+
nodes: result,
|
|
53
|
+
cursor: resultCursor ? _lodash.default.toString(resultCursor) : null
|
|
54
|
+
};
|
|
102
55
|
}
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
if (!id) throw new Error(`You must provide an id`);
|
|
110
|
-
const itemToPut = {
|
|
111
|
-
_partition: entity,
|
|
112
|
-
id,
|
|
113
|
-
...item
|
|
56
|
+
if (dexieResult.maxItemCount && result.length >= dexieResult.maxItemCount) {
|
|
57
|
+
resultCursor = newCursor;
|
|
58
|
+
}
|
|
59
|
+
return {
|
|
60
|
+
nodes: result,
|
|
61
|
+
cursor: resultCursor ? _lodash.default.toString(resultCursor) : null
|
|
114
62
|
};
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
63
|
+
},
|
|
64
|
+
async putMany(items, ctx) {
|
|
65
|
+
await initDbIfNeeded(dbName);
|
|
66
|
+
const table = dbWrapper.db.table(handle);
|
|
67
|
+
await table.bulkPut(items);
|
|
120
68
|
}
|
|
121
|
-
}
|
|
69
|
+
};
|
|
122
70
|
};
|
|
123
|
-
return instance;
|
|
124
71
|
};
|
|
125
72
|
module.exports = _default;
|
|
126
|
-
function
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
73
|
+
function applyArgsToDexieTable(table, args) {
|
|
74
|
+
const {
|
|
75
|
+
where,
|
|
76
|
+
orderByProperty,
|
|
77
|
+
orderByDirection,
|
|
78
|
+
maxItemCount
|
|
79
|
+
} = args;
|
|
80
|
+
let orderByProp = orderByProperty;
|
|
81
|
+
const indexedProps = ["id", ...table.schema.indexes.map(idx => idx.name)];
|
|
82
|
+
let collection;
|
|
83
|
+
for (const ip of indexedProps) {
|
|
84
|
+
collection = applyTableFiltering(table, where, ip);
|
|
85
|
+
if (collection) {
|
|
86
|
+
break;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
if (!collection && orderByProp) {
|
|
90
|
+
if (indexedProps.includes(orderByProp)) {
|
|
91
|
+
collection = table.orderBy(orderByProp);
|
|
92
|
+
if (orderByDirection === "desc") collection = collection.reverse();
|
|
93
|
+
orderByProp = "";
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
if (!collection) {
|
|
97
|
+
collection = table.toCollection();
|
|
98
|
+
}
|
|
99
|
+
const f = (0, _memory.getFilter)(where);
|
|
100
|
+
if (f) {
|
|
101
|
+
collection = collection.filter(f);
|
|
102
|
+
}
|
|
103
|
+
if (maxItemCount && !orderByProp) {
|
|
104
|
+
if (args.cursor) collection = collection.offset(_lodash.default.toNumber(args.cursor));
|
|
105
|
+
collection = collection.limit(maxItemCount);
|
|
141
106
|
}
|
|
142
|
-
const query = `select * from r where ${whereClauses.join(" AND ")} ${orderByClause}`;
|
|
143
107
|
return {
|
|
144
|
-
|
|
145
|
-
|
|
108
|
+
collection,
|
|
109
|
+
orderByProp,
|
|
110
|
+
orderByDirection,
|
|
111
|
+
maxItemCount
|
|
146
112
|
};
|
|
147
113
|
}
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
name,
|
|
152
|
-
namePrefix,
|
|
153
|
-
paramNamePrefix,
|
|
154
|
-
paramName,
|
|
155
|
-
whereVal
|
|
156
|
-
} = whereArgs;
|
|
157
|
-
const newCtx = {
|
|
158
|
-
...ctx,
|
|
159
|
-
entity: ctx.schema[ctx.entity].fields[ctx.field].type
|
|
160
|
-
};
|
|
161
|
-
const subClause = getCosmosQueryWhere(newCtx, parameters, whereVal, `${name}.`, `${paramNamePrefix}${paramName}_`);
|
|
162
|
-
if (subClause) {
|
|
163
|
-
if (simpleSubclauseRegex.test(subClause)) {
|
|
164
|
-
const parts = subClause.split(" ");
|
|
165
|
-
const field = parts[0];
|
|
166
|
-
const variable = parts[2];
|
|
167
|
-
return `array_contains(${namePrefix}${name}, { ${field.split(".")[1]}: ${variable} }, true)`;
|
|
168
|
-
}
|
|
169
|
-
return `exists (select ${name} from ${name} in ${namePrefix}${name} where ${subClause})`;
|
|
170
|
-
}
|
|
171
|
-
return `array_length(${namePrefix}${name}) > 0`;
|
|
172
|
-
},
|
|
173
|
-
none: (ctx, parameters, whereArgs) => {
|
|
174
|
-
const {
|
|
175
|
-
name,
|
|
176
|
-
namePrefix,
|
|
177
|
-
paramNamePrefix,
|
|
178
|
-
paramName,
|
|
179
|
-
whereVal
|
|
180
|
-
} = whereArgs;
|
|
181
|
-
const newCtx = {
|
|
182
|
-
...ctx,
|
|
183
|
-
entity: ctx.schema[ctx.entity].fields[ctx.field].type
|
|
184
|
-
};
|
|
185
|
-
const subClause = getCosmosQueryWhere(newCtx, parameters, whereVal, `${name}.`, `${paramNamePrefix}${paramName}_`);
|
|
186
|
-
if (subClause) return `not exists (select ${name} from ${name} in ${namePrefix}${name} where ${subClause})`;
|
|
187
|
-
return `array_length(${namePrefix}${name}) = 0`;
|
|
188
|
-
},
|
|
189
|
-
and: (ctx, parameters, whereArgs) => {
|
|
190
|
-
const {
|
|
191
|
-
namePrefix,
|
|
192
|
-
paramNamePrefix,
|
|
193
|
-
whereVal
|
|
194
|
-
} = whereArgs;
|
|
195
|
-
if (!_lodash.default.isArray(whereVal)) throw new Error(`Value for where._and must be an array`);
|
|
196
|
-
const clauses = [];
|
|
197
|
-
for (let i = 0; i < whereVal.length; i++) {
|
|
198
|
-
const andQuery = getCosmosQueryWhere(ctx, parameters, whereVal[i], namePrefix, `${paramNamePrefix}and${i}_`);
|
|
199
|
-
clauses.push(andQuery);
|
|
200
|
-
}
|
|
201
|
-
if (!clauses.length) return null;
|
|
202
|
-
return `((${clauses.join(") and (")}))`;
|
|
203
|
-
},
|
|
204
|
-
not: (ctx, parameters, whereArgs) => {
|
|
205
|
-
const {
|
|
206
|
-
name,
|
|
207
|
-
namePrefix,
|
|
208
|
-
paramNamePrefix,
|
|
209
|
-
whereVal
|
|
210
|
-
} = whereArgs;
|
|
211
|
-
const subClause = getCosmosQueryWhere(ctx, parameters, whereVal, `${namePrefix}${name}`, `${paramNamePrefix}not_`);
|
|
212
|
-
if (!subClause) return null;
|
|
213
|
-
return `not(${subClause})`;
|
|
214
|
-
},
|
|
215
|
-
or: (ctx, parameters, whereArgs) => {
|
|
216
|
-
const {
|
|
217
|
-
namePrefix,
|
|
218
|
-
paramNamePrefix,
|
|
219
|
-
whereVal
|
|
220
|
-
} = whereArgs;
|
|
221
|
-
if (!_lodash.default.isArray(whereVal)) throw new Error(`Value for where._or must be an array`);
|
|
222
|
-
const clauses = [];
|
|
223
|
-
for (let i = 0; i < whereVal.length; i++) {
|
|
224
|
-
const orQuery = getCosmosQueryWhere(ctx, parameters, whereVal[i], namePrefix, `${paramNamePrefix}or${i}_`);
|
|
225
|
-
clauses.push(orQuery);
|
|
226
|
-
}
|
|
227
|
-
if (!clauses.length) return null;
|
|
228
|
-
return `((${clauses.join(") or (")}))`;
|
|
229
|
-
},
|
|
230
|
-
isNull: (ctx, parameters, whereArgs) => {
|
|
231
|
-
const {
|
|
232
|
-
name,
|
|
233
|
-
namePrefix,
|
|
234
|
-
whereVal
|
|
235
|
-
} = whereArgs;
|
|
236
|
-
const n = `${namePrefix}${name}`;
|
|
237
|
-
if (whereVal) return `(not (is_defined(${n})) or ${n} = null)`;
|
|
238
|
-
return `(is_defined(${n}) and ${n} != null)`;
|
|
239
|
-
},
|
|
240
|
-
eq: (ctx, parameters, whereArgs) => {
|
|
241
|
-
const {
|
|
242
|
-
name,
|
|
243
|
-
namePrefix,
|
|
244
|
-
paramName,
|
|
245
|
-
paramNamePrefix,
|
|
246
|
-
whereVal
|
|
247
|
-
} = whereArgs;
|
|
248
|
-
const pn = `${paramNamePrefix}${paramName}`;
|
|
249
|
-
parameters[pn] = whereVal;
|
|
250
|
-
return `${namePrefix}${name} = @${pn}`;
|
|
251
|
-
},
|
|
252
|
-
in: (ctx, parameters, whereArgs) => {
|
|
253
|
-
const {
|
|
254
|
-
name,
|
|
255
|
-
namePrefix,
|
|
256
|
-
paramName,
|
|
257
|
-
paramNamePrefix,
|
|
258
|
-
whereVal
|
|
259
|
-
} = whereArgs;
|
|
260
|
-
const pn = `${paramNamePrefix}${paramName}`;
|
|
261
|
-
parameters[pn] = whereVal;
|
|
262
|
-
return `array_contains(@${pn}, ${namePrefix}${name})`;
|
|
263
|
-
},
|
|
264
|
-
startsWith: (ctx, parameters, whereArgs) => {
|
|
265
|
-
const {
|
|
266
|
-
name,
|
|
267
|
-
namePrefix,
|
|
268
|
-
paramName,
|
|
269
|
-
paramNamePrefix,
|
|
270
|
-
whereVal
|
|
271
|
-
} = whereArgs;
|
|
272
|
-
const pn = `${paramNamePrefix}${paramName}`;
|
|
273
|
-
parameters[pn] = whereVal;
|
|
274
|
-
return `startswith(${namePrefix}${name}, @${pn})`;
|
|
275
|
-
},
|
|
276
|
-
istartsWith: (ctx, parameters, whereArgs) => {
|
|
277
|
-
const {
|
|
278
|
-
name,
|
|
279
|
-
namePrefix,
|
|
280
|
-
paramName,
|
|
281
|
-
paramNamePrefix,
|
|
282
|
-
whereVal
|
|
283
|
-
} = whereArgs;
|
|
284
|
-
const pn = `${paramNamePrefix}${paramName}`;
|
|
285
|
-
parameters[pn] = whereVal;
|
|
286
|
-
return `startswith(${namePrefix}${name}, @${pn}, true)`;
|
|
287
|
-
},
|
|
288
|
-
endsWith: (ctx, parameters, whereArgs) => {
|
|
289
|
-
const {
|
|
290
|
-
name,
|
|
291
|
-
namePrefix,
|
|
292
|
-
paramName,
|
|
293
|
-
paramNamePrefix,
|
|
294
|
-
whereVal
|
|
295
|
-
} = whereArgs;
|
|
296
|
-
const pn = `${paramNamePrefix}${paramName}`;
|
|
297
|
-
parameters[pn] = whereVal;
|
|
298
|
-
return `endswith(${namePrefix}${name}, @${pn})`;
|
|
299
|
-
},
|
|
300
|
-
iendsWith: (ctx, parameters, whereArgs) => {
|
|
301
|
-
const {
|
|
302
|
-
name,
|
|
303
|
-
namePrefix,
|
|
304
|
-
paramName,
|
|
305
|
-
paramNamePrefix,
|
|
306
|
-
whereVal
|
|
307
|
-
} = whereArgs;
|
|
308
|
-
const pn = `${paramNamePrefix}${paramName}`;
|
|
309
|
-
parameters[pn] = whereVal;
|
|
310
|
-
return `endswith(${namePrefix}${name}, @${pn}, true)`;
|
|
311
|
-
},
|
|
312
|
-
contains: (ctx, parameters, whereArgs) => {
|
|
313
|
-
const {
|
|
314
|
-
name,
|
|
315
|
-
namePrefix,
|
|
316
|
-
paramName,
|
|
317
|
-
paramNamePrefix,
|
|
318
|
-
whereVal
|
|
319
|
-
} = whereArgs;
|
|
320
|
-
const fieldType = ctx.schema[ctx.entity].fields[ctx.field];
|
|
321
|
-
const pn = `${paramNamePrefix}${paramName}`;
|
|
322
|
-
parameters[pn] = whereVal;
|
|
323
|
-
if (fieldType.isArray) {
|
|
324
|
-
return `array_contains(${namePrefix}${name}, @${pn})`;
|
|
325
|
-
}
|
|
326
|
-
return `contains(${namePrefix}${name}, @${pn})`;
|
|
327
|
-
},
|
|
328
|
-
icontains: (ctx, parameters, whereArgs) => {
|
|
329
|
-
const {
|
|
330
|
-
name,
|
|
331
|
-
namePrefix,
|
|
332
|
-
paramName,
|
|
333
|
-
paramNamePrefix,
|
|
334
|
-
whereVal
|
|
335
|
-
} = whereArgs;
|
|
336
|
-
const pn = `${paramNamePrefix}${paramName}`;
|
|
337
|
-
parameters[pn] = whereVal;
|
|
338
|
-
return `contains(${namePrefix}${name}, @${pn}, true)`;
|
|
339
|
-
},
|
|
340
|
-
ieq: (ctx, parameters, whereArgs) => {
|
|
341
|
-
const {
|
|
342
|
-
name,
|
|
343
|
-
namePrefix,
|
|
344
|
-
paramName,
|
|
345
|
-
paramNamePrefix,
|
|
346
|
-
whereVal
|
|
347
|
-
} = whereArgs;
|
|
348
|
-
const pn = `${paramNamePrefix}${paramName}`;
|
|
349
|
-
parameters[pn] = whereVal;
|
|
350
|
-
return `stringequals(${namePrefix}${name}, @${pn}, true)`;
|
|
351
|
-
},
|
|
352
|
-
gt: (ctx, parameters, whereArgs) => {
|
|
353
|
-
const {
|
|
354
|
-
name,
|
|
355
|
-
namePrefix,
|
|
356
|
-
paramName,
|
|
357
|
-
paramNamePrefix,
|
|
358
|
-
whereVal
|
|
359
|
-
} = whereArgs;
|
|
360
|
-
const pn = `${paramNamePrefix}${paramName}`;
|
|
361
|
-
parameters[pn] = whereVal;
|
|
362
|
-
return `${namePrefix}${name} > @${pn}`;
|
|
363
|
-
},
|
|
364
|
-
gte: (ctx, parameters, whereArgs) => {
|
|
365
|
-
const {
|
|
366
|
-
name,
|
|
367
|
-
namePrefix,
|
|
368
|
-
paramName,
|
|
369
|
-
paramNamePrefix,
|
|
370
|
-
whereVal
|
|
371
|
-
} = whereArgs;
|
|
372
|
-
const pn = `${paramNamePrefix}${paramName}`;
|
|
373
|
-
parameters[pn] = whereVal;
|
|
374
|
-
return `${namePrefix}${name} >= @${pn}`;
|
|
375
|
-
},
|
|
376
|
-
lt: (ctx, parameters, whereArgs) => {
|
|
377
|
-
const {
|
|
378
|
-
name,
|
|
379
|
-
namePrefix,
|
|
380
|
-
paramName,
|
|
381
|
-
paramNamePrefix,
|
|
382
|
-
whereVal
|
|
383
|
-
} = whereArgs;
|
|
384
|
-
const pn = `${paramNamePrefix}${paramName}`;
|
|
385
|
-
parameters[pn] = whereVal;
|
|
386
|
-
return `${namePrefix}${name} < @${pn}`;
|
|
387
|
-
},
|
|
388
|
-
lte: (ctx, parameters, whereArgs) => {
|
|
389
|
-
const {
|
|
390
|
-
name,
|
|
391
|
-
namePrefix,
|
|
392
|
-
paramName,
|
|
393
|
-
paramNamePrefix,
|
|
394
|
-
whereVal
|
|
395
|
-
} = whereArgs;
|
|
396
|
-
const pn = `${paramNamePrefix}${paramName}`;
|
|
397
|
-
parameters[pn] = whereVal;
|
|
398
|
-
return `${namePrefix}${name} <= @${pn}`;
|
|
114
|
+
function applyTableFiltering(table, where, fieldName) {
|
|
115
|
+
if (["isArchived", "_type"].includes(fieldName)) {
|
|
116
|
+
return void 0;
|
|
399
117
|
}
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
namePrefix = namePrefix.slice(0, -1);
|
|
118
|
+
for (const operatorKey in tableOperatorFns) {
|
|
119
|
+
const operator = operatorKey === "eq" ? null : operatorKey;
|
|
120
|
+
const whereKey = [fieldName, operator].filter(x => x).join("_");
|
|
121
|
+
const whereVal = _lodash.default.get(where, whereKey);
|
|
122
|
+
if (whereVal != null) {
|
|
123
|
+
const whereClause = table.where(fieldName);
|
|
124
|
+
_lodash.default.set(where, whereKey, void 0);
|
|
125
|
+
return tableOperatorFns[operatorKey](whereClause, whereVal);
|
|
409
126
|
}
|
|
410
|
-
const paramName = key;
|
|
411
|
-
const whereVal = where[key];
|
|
412
|
-
if (whereVal == null) continue;
|
|
413
|
-
const f = getCosmosQueryWhereInner({
|
|
414
|
-
...ctx,
|
|
415
|
-
field: nameFromWhere
|
|
416
|
-
}, parameters, {
|
|
417
|
-
operator,
|
|
418
|
-
whereVal,
|
|
419
|
-
name,
|
|
420
|
-
namePrefix,
|
|
421
|
-
paramName,
|
|
422
|
-
paramNamePrefix
|
|
423
|
-
});
|
|
424
|
-
if (f) whereClauses.push(f);
|
|
425
127
|
}
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
} = whereArgs;
|
|
437
|
-
if (!operator && _lodash.default.isObject(whereVal)) {
|
|
438
|
-
return getCosmosQueryWhere(ctx, parameters, whereVal, `${namePrefix}${name}.`, `${paramNamePrefix}${paramName}_`);
|
|
128
|
+
for (const operatorKey in tableOperatorNotFns) {
|
|
129
|
+
const operator = operatorKey === "eq" ? null : operatorKey;
|
|
130
|
+
const whereKey = [fieldName, operator].filter(x => x).join("_");
|
|
131
|
+
const whereKeyNot = `_not.${whereKey}`;
|
|
132
|
+
const whereValNot = _lodash.default.get(where, whereKeyNot);
|
|
133
|
+
if (whereValNot != null) {
|
|
134
|
+
const whereClause = table.where(fieldName);
|
|
135
|
+
_lodash.default.set(where, whereKeyNot, void 0);
|
|
136
|
+
return tableOperatorNotFns[operatorKey](whereClause, whereValNot);
|
|
137
|
+
}
|
|
439
138
|
}
|
|
440
|
-
const fn = operatorHandlers[operator || "eq"];
|
|
441
|
-
if (!fn) console.warn(`Unsupported operator: "${operator}"`);
|
|
442
|
-
return fn(ctx, parameters, whereArgs);
|
|
443
139
|
}
|
|
444
|
-
function
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
140
|
+
function normalizeArgs(args) {
|
|
141
|
+
if (!args) args = {};
|
|
142
|
+
const where = _lodash.default.cloneDeep(args.where) || {};
|
|
143
|
+
let orderBy = args.orderBy || "";
|
|
144
|
+
if (_lodash.default.isArray(orderBy)) orderBy = orderBy[0] || "";
|
|
145
|
+
const orderByParts = orderBy.split("_");
|
|
146
|
+
const orderByProperty = orderByParts.slice(0, -1).join(".");
|
|
147
|
+
const orderByDirection = orderByParts.slice(-1)[0];
|
|
148
|
+
const maxItemCount = args.maxItemCount || 100;
|
|
149
|
+
return {
|
|
150
|
+
where,
|
|
151
|
+
orderByProperty,
|
|
152
|
+
orderByDirection,
|
|
153
|
+
maxItemCount,
|
|
154
|
+
cursor: args.cursor ? _lodash.default.toNumber(args.cursor) : 0
|
|
449
155
|
};
|
|
450
|
-
const {
|
|
451
|
-
databaseName,
|
|
452
|
-
containerName,
|
|
453
|
-
endpoint
|
|
454
|
-
} = options;
|
|
455
|
-
const key = `${endpoint}|${databaseName}|${containerName}`;
|
|
456
|
-
if (!containerClientCache[key]) {
|
|
457
|
-
containerClientCache[key] = getCosmosDatabaseClient(options).container(containerName);
|
|
458
|
-
}
|
|
459
|
-
return containerClientCache[key];
|
|
460
156
|
}
|
|
461
|
-
function
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
...options
|
|
466
|
-
};
|
|
467
|
-
const {
|
|
468
|
-
databaseName,
|
|
469
|
-
endpoint
|
|
470
|
-
} = options;
|
|
471
|
-
const key = `${endpoint}|${databaseName}`;
|
|
472
|
-
if (!databaseClientCache[key]) {
|
|
473
|
-
databaseClientCache[key] = getCosmosAccountClient(options).database(databaseName);
|
|
157
|
+
async function initDbIfNeeded(dbName) {
|
|
158
|
+
const dbWrapper = dbs[dbName];
|
|
159
|
+
if (!dbWrapper.initPromise) {
|
|
160
|
+
dbWrapper.initPromise = initDbInner(dbName);
|
|
474
161
|
}
|
|
475
|
-
return
|
|
162
|
+
return dbWrapper.initPromise;
|
|
476
163
|
}
|
|
477
|
-
function
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
...options
|
|
164
|
+
async function initDbInner(dbName) {
|
|
165
|
+
const dbWrapper = dbs[dbName];
|
|
166
|
+
const stores = {
|
|
167
|
+
_system: "id"
|
|
482
168
|
};
|
|
483
|
-
const {
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
169
|
+
for (const entity in dbWrapper.entities) {
|
|
170
|
+
stores[entity] = "id";
|
|
171
|
+
}
|
|
172
|
+
let db = new _dexie.default(dbWrapper.driverOptions.dbName, dbWrapper.driverOptions.dexieOptions);
|
|
173
|
+
db.version(1).stores(stores);
|
|
174
|
+
let systemTable = db._system;
|
|
175
|
+
const invalidateCounter = dbWrapper.driverOptions.invalidateCounter;
|
|
176
|
+
const currentVersionObject = await systemTable.get("_versionObject");
|
|
177
|
+
if (!currentVersionObject) {
|
|
178
|
+
await systemTable.put({
|
|
179
|
+
id: "_versionObject",
|
|
180
|
+
stores,
|
|
181
|
+
version: 1,
|
|
182
|
+
invalidateCounter
|
|
183
|
+
});
|
|
184
|
+
} else if (!_lodash.default.isEqual(currentVersionObject.invalidateCounter, invalidateCounter)) {
|
|
185
|
+
await db.delete();
|
|
186
|
+
db = new _dexie.default(dbWrapper.driverOptions.dbName, dbWrapper.driverOptions.dexieOptions);
|
|
187
|
+
db.version(1).stores(stores);
|
|
188
|
+
systemTable = db._system;
|
|
189
|
+
await systemTable.put({
|
|
190
|
+
id: "_versionObject",
|
|
191
|
+
stores,
|
|
192
|
+
version: 1,
|
|
193
|
+
invalidateCounter
|
|
194
|
+
});
|
|
195
|
+
} else if (!_lodash.default.isEqual(currentVersionObject.stores, stores)) {
|
|
196
|
+
const newVersion = currentVersionObject.version + 1;
|
|
197
|
+
db.version(newVersion).stores(stores);
|
|
198
|
+
await systemTable.put({
|
|
199
|
+
id: "_versionObject",
|
|
200
|
+
stores,
|
|
201
|
+
version: newVersion
|
|
493
202
|
});
|
|
494
203
|
}
|
|
495
|
-
|
|
204
|
+
dbWrapper.db = db;
|
|
496
205
|
}
|
|
497
|
-
function
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
206
|
+
function getDb(options) {
|
|
207
|
+
const dbName = options?.dbName || "db";
|
|
208
|
+
if (dbs[dbName]?.db) dbs[dbName].db?.close();
|
|
209
|
+
dbs[dbName] = {
|
|
210
|
+
entities: {},
|
|
211
|
+
driverOptions: {
|
|
212
|
+
dbName,
|
|
213
|
+
dexieOptions: void 0,
|
|
214
|
+
invalidateCounter: 0,
|
|
215
|
+
...options
|
|
216
|
+
}
|
|
217
|
+
};
|
|
218
|
+
return dbs[dbName];
|
|
503
219
|
}
|
package/drivers/indexedDb.d.ts
CHANGED
|
@@ -1,10 +1,8 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
|
|
3
|
-
endpoint: string;
|
|
4
|
-
accountKey?: string;
|
|
5
|
-
databaseName?: string;
|
|
6
|
-
containerName?: string;
|
|
7
|
-
options?: Omit<CosmosClientOptions, 'key' | 'endpoint'>;
|
|
8
|
-
}
|
|
9
|
-
declare const _default: (options: AzureCosmosDriverOptions) => (schema: Schema, entity: string) => MinimalDriver;
|
|
1
|
+
import type { DexieOptions } from 'dexie';
|
|
2
|
+
declare const _default: (options?: IndexedDbDriverOptions) => (schema: Schema, entity: string) => MinimalDriver;
|
|
10
3
|
export default _default;
|
|
4
|
+
export interface IndexedDbDriverOptions {
|
|
5
|
+
dbName?: string;
|
|
6
|
+
invalidateCounter?: number;
|
|
7
|
+
dexieOptions?: DexieOptions;
|
|
8
|
+
}
|
package/drivers/indexedDb.mjs
CHANGED
|
@@ -1,314 +1,179 @@
|
|
|
1
|
-
import
|
|
1
|
+
import Dexie from "dexie";
|
|
2
2
|
import _ from "lodash";
|
|
3
|
-
|
|
4
|
-
const
|
|
5
|
-
const
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
if (whereKeys[0] === "id_in" && where.id_in != null) {
|
|
29
|
-
const items = await getItemByIds(where.id_in, ctx);
|
|
30
|
-
return { nodes: items.filter((x) => x), cursor: null };
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
const { query, parameters } = getCosmosQuery(schema, entity, args);
|
|
34
|
-
const response = client.items.query(
|
|
35
|
-
{
|
|
36
|
-
query,
|
|
37
|
-
parameters: Object.keys(parameters).map((k) => ({ name: `@${k}`, value: parameters[k] }))
|
|
38
|
-
},
|
|
39
|
-
{
|
|
40
|
-
continuationToken: args.cursor || void 0,
|
|
41
|
-
continuationTokenLimitInKB: 4,
|
|
42
|
-
maxItemCount: args.maxItemCount
|
|
43
|
-
}
|
|
44
|
-
);
|
|
45
|
-
const page = await response.fetchNext();
|
|
46
|
-
ctx?.log?.({ charge: page.requestCharge, request: query });
|
|
3
|
+
import { getFilter } from "./memory.mjs";
|
|
4
|
+
const dbs = {};
|
|
5
|
+
const tableOperatorFns = {
|
|
6
|
+
eq: (where, value) => where.equals(value),
|
|
7
|
+
ieq: (where, value) => where.equalsIgnoreCase(value),
|
|
8
|
+
in: (where, value) => where.anyOf(value),
|
|
9
|
+
startsWith: (where, value) => where.startsWith(value),
|
|
10
|
+
istartsWith: (where, value) => where.startsWithIgnoreCase(value),
|
|
11
|
+
gt: (where, value) => where.above(value),
|
|
12
|
+
lt: (where, value) => where.below(value)
|
|
13
|
+
};
|
|
14
|
+
const tableOperatorNotFns = {
|
|
15
|
+
eq: (where, value) => where.notEqual(value),
|
|
16
|
+
in: (where, value) => where.noneOf(value),
|
|
17
|
+
gt: (where, value) => where.belowOrEqual(value),
|
|
18
|
+
lt: (where, value) => where.aboveOrEqual(value)
|
|
19
|
+
};
|
|
20
|
+
export default (options) => {
|
|
21
|
+
const dbName = options?.dbName || "db";
|
|
22
|
+
const dbWrapper = getDb(options);
|
|
23
|
+
return (schema, entity) => {
|
|
24
|
+
const handle = schema[entity]?.handle;
|
|
25
|
+
if (!handle)
|
|
26
|
+
throw new Error(`Entity ${entity} not found`);
|
|
27
|
+
dbWrapper.entities[handle] = true;
|
|
47
28
|
return {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
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);
|
|
44
|
+
}
|
|
45
|
+
return { nodes: result, cursor: resultCursor ? _.toString(resultCursor) : null };
|
|
62
46
|
}
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
const response = await client.items.upsert(itemToPut);
|
|
73
|
-
ctx?.log?.({ charge: response.requestCharge, request: `put#${itemToPut._partition}|${itemToPut.id}` });
|
|
47
|
+
if (dexieResult.maxItemCount && result.length >= dexieResult.maxItemCount) {
|
|
48
|
+
resultCursor = newCursor;
|
|
49
|
+
}
|
|
50
|
+
return { nodes: result, cursor: resultCursor ? _.toString(resultCursor) : null };
|
|
51
|
+
},
|
|
52
|
+
async putMany(items, ctx) {
|
|
53
|
+
await initDbIfNeeded(dbName);
|
|
54
|
+
const table = dbWrapper.db.table(handle);
|
|
55
|
+
await table.bulkPut(items);
|
|
74
56
|
}
|
|
75
|
-
}
|
|
57
|
+
};
|
|
76
58
|
};
|
|
77
|
-
return instance;
|
|
78
59
|
};
|
|
79
|
-
function
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
const
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
if (args.orderBy) {
|
|
89
|
-
const orderByParts = args.orderBy.split("_");
|
|
90
|
-
const orderPropFromOrderBy = orderByParts.slice(0, -1).join(".");
|
|
91
|
-
const orderDirection = orderByParts.at(-1);
|
|
92
|
-
const orderProp = orderPropFromOrderBy === "value" ? `r["value"]` : `r.${orderPropFromOrderBy}`;
|
|
93
|
-
orderByClause = `order by ${orderProp} ${orderDirection}`;
|
|
94
|
-
}
|
|
95
|
-
const query = `select * from r where ${whereClauses.join(" AND ")} ${orderByClause}`;
|
|
96
|
-
return { query, parameters };
|
|
97
|
-
}
|
|
98
|
-
const operatorHandlers = {
|
|
99
|
-
some: (ctx, parameters, whereArgs) => {
|
|
100
|
-
const { name, namePrefix, paramNamePrefix, paramName, whereVal } = whereArgs;
|
|
101
|
-
const newCtx = { ...ctx, entity: ctx.schema[ctx.entity].fields[ctx.field].type };
|
|
102
|
-
const subClause = getCosmosQueryWhere(newCtx, parameters, whereVal, `${name}.`, `${paramNamePrefix}${paramName}_`);
|
|
103
|
-
if (subClause) {
|
|
104
|
-
if (simpleSubclauseRegex.test(subClause)) {
|
|
105
|
-
const parts = subClause.split(" ");
|
|
106
|
-
const field = parts[0];
|
|
107
|
-
const variable = parts[2];
|
|
108
|
-
return `array_contains(${namePrefix}${name}, { ${field.split(".")[1]}: ${variable} }, true)`;
|
|
109
|
-
}
|
|
110
|
-
return `exists (select ${name} from ${name} in ${namePrefix}${name} where ${subClause})`;
|
|
111
|
-
}
|
|
112
|
-
return `array_length(${namePrefix}${name}) > 0`;
|
|
113
|
-
},
|
|
114
|
-
none: (ctx, parameters, whereArgs) => {
|
|
115
|
-
const { name, namePrefix, paramNamePrefix, paramName, whereVal } = whereArgs;
|
|
116
|
-
const newCtx = { ...ctx, entity: ctx.schema[ctx.entity].fields[ctx.field].type };
|
|
117
|
-
const subClause = getCosmosQueryWhere(newCtx, parameters, whereVal, `${name}.`, `${paramNamePrefix}${paramName}_`);
|
|
118
|
-
if (subClause)
|
|
119
|
-
return `not exists (select ${name} from ${name} in ${namePrefix}${name} where ${subClause})`;
|
|
120
|
-
return `array_length(${namePrefix}${name}) = 0`;
|
|
121
|
-
},
|
|
122
|
-
and: (ctx, parameters, whereArgs) => {
|
|
123
|
-
const { namePrefix, paramNamePrefix, whereVal } = whereArgs;
|
|
124
|
-
if (!_.isArray(whereVal))
|
|
125
|
-
throw new Error(`Value for where._and must be an array`);
|
|
126
|
-
const clauses = [];
|
|
127
|
-
for (let i = 0; i < whereVal.length; i++) {
|
|
128
|
-
const andQuery = getCosmosQueryWhere(ctx, parameters, whereVal[i], namePrefix, `${paramNamePrefix}and${i}_`);
|
|
129
|
-
clauses.push(andQuery);
|
|
60
|
+
function applyArgsToDexieTable(table, args) {
|
|
61
|
+
const { where, orderByProperty, orderByDirection, maxItemCount } = args;
|
|
62
|
+
let orderByProp = orderByProperty;
|
|
63
|
+
const indexedProps = ["id", ...table.schema.indexes.map((idx) => idx.name)];
|
|
64
|
+
let collection;
|
|
65
|
+
for (const ip of indexedProps) {
|
|
66
|
+
collection = applyTableFiltering(table, where, ip);
|
|
67
|
+
if (collection) {
|
|
68
|
+
break;
|
|
130
69
|
}
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
if (!subClause)
|
|
139
|
-
return null;
|
|
140
|
-
return `not(${subClause})`;
|
|
141
|
-
},
|
|
142
|
-
or: (ctx, parameters, whereArgs) => {
|
|
143
|
-
const { namePrefix, paramNamePrefix, whereVal } = whereArgs;
|
|
144
|
-
if (!_.isArray(whereVal))
|
|
145
|
-
throw new Error(`Value for where._or must be an array`);
|
|
146
|
-
const clauses = [];
|
|
147
|
-
for (let i = 0; i < whereVal.length; i++) {
|
|
148
|
-
const orQuery = getCosmosQueryWhere(ctx, parameters, whereVal[i], namePrefix, `${paramNamePrefix}or${i}_`);
|
|
149
|
-
clauses.push(orQuery);
|
|
70
|
+
}
|
|
71
|
+
if (!collection && orderByProp) {
|
|
72
|
+
if (indexedProps.includes(orderByProp)) {
|
|
73
|
+
collection = table.orderBy(orderByProp);
|
|
74
|
+
if (orderByDirection === "desc")
|
|
75
|
+
collection = collection.reverse();
|
|
76
|
+
orderByProp = "";
|
|
150
77
|
}
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
return `startswith(${namePrefix}${name}, @${pn})`;
|
|
179
|
-
},
|
|
180
|
-
istartsWith: (ctx, parameters, whereArgs) => {
|
|
181
|
-
const { name, namePrefix, paramName, paramNamePrefix, whereVal } = whereArgs;
|
|
182
|
-
const pn = `${paramNamePrefix}${paramName}`;
|
|
183
|
-
parameters[pn] = whereVal;
|
|
184
|
-
return `startswith(${namePrefix}${name}, @${pn}, true)`;
|
|
185
|
-
},
|
|
186
|
-
endsWith: (ctx, parameters, whereArgs) => {
|
|
187
|
-
const { name, namePrefix, paramName, paramNamePrefix, whereVal } = whereArgs;
|
|
188
|
-
const pn = `${paramNamePrefix}${paramName}`;
|
|
189
|
-
parameters[pn] = whereVal;
|
|
190
|
-
return `endswith(${namePrefix}${name}, @${pn})`;
|
|
191
|
-
},
|
|
192
|
-
iendsWith: (ctx, parameters, whereArgs) => {
|
|
193
|
-
const { name, namePrefix, paramName, paramNamePrefix, whereVal } = whereArgs;
|
|
194
|
-
const pn = `${paramNamePrefix}${paramName}`;
|
|
195
|
-
parameters[pn] = whereVal;
|
|
196
|
-
return `endswith(${namePrefix}${name}, @${pn}, true)`;
|
|
197
|
-
},
|
|
198
|
-
contains: (ctx, parameters, whereArgs) => {
|
|
199
|
-
const { name, namePrefix, paramName, paramNamePrefix, whereVal } = whereArgs;
|
|
200
|
-
const fieldType = ctx.schema[ctx.entity].fields[ctx.field];
|
|
201
|
-
const pn = `${paramNamePrefix}${paramName}`;
|
|
202
|
-
parameters[pn] = whereVal;
|
|
203
|
-
if (fieldType.isArray) {
|
|
204
|
-
return `array_contains(${namePrefix}${name}, @${pn})`;
|
|
78
|
+
}
|
|
79
|
+
if (!collection) {
|
|
80
|
+
collection = table.toCollection();
|
|
81
|
+
}
|
|
82
|
+
const f = getFilter(where);
|
|
83
|
+
if (f) {
|
|
84
|
+
collection = collection.filter(f);
|
|
85
|
+
}
|
|
86
|
+
if (maxItemCount && !orderByProp) {
|
|
87
|
+
if (args.cursor)
|
|
88
|
+
collection = collection.offset(_.toNumber(args.cursor));
|
|
89
|
+
collection = collection.limit(maxItemCount);
|
|
90
|
+
}
|
|
91
|
+
return { collection, orderByProp, orderByDirection, maxItemCount };
|
|
92
|
+
}
|
|
93
|
+
function applyTableFiltering(table, where, fieldName) {
|
|
94
|
+
if (["isArchived", "_type"].includes(fieldName)) {
|
|
95
|
+
return void 0;
|
|
96
|
+
}
|
|
97
|
+
for (const operatorKey in tableOperatorFns) {
|
|
98
|
+
const operator = operatorKey === "eq" ? null : operatorKey;
|
|
99
|
+
const whereKey = [fieldName, operator].filter((x) => x).join("_");
|
|
100
|
+
const whereVal = _.get(where, whereKey);
|
|
101
|
+
if (whereVal != null) {
|
|
102
|
+
const whereClause = table.where(fieldName);
|
|
103
|
+
_.set(where, whereKey, void 0);
|
|
104
|
+
return tableOperatorFns[operatorKey](whereClause, whereVal);
|
|
205
105
|
}
|
|
206
|
-
return `contains(${namePrefix}${name}, @${pn})`;
|
|
207
|
-
},
|
|
208
|
-
icontains: (ctx, parameters, whereArgs) => {
|
|
209
|
-
const { name, namePrefix, paramName, paramNamePrefix, whereVal } = whereArgs;
|
|
210
|
-
const pn = `${paramNamePrefix}${paramName}`;
|
|
211
|
-
parameters[pn] = whereVal;
|
|
212
|
-
return `contains(${namePrefix}${name}, @${pn}, true)`;
|
|
213
|
-
},
|
|
214
|
-
ieq: (ctx, parameters, whereArgs) => {
|
|
215
|
-
const { name, namePrefix, paramName, paramNamePrefix, whereVal } = whereArgs;
|
|
216
|
-
const pn = `${paramNamePrefix}${paramName}`;
|
|
217
|
-
parameters[pn] = whereVal;
|
|
218
|
-
return `stringequals(${namePrefix}${name}, @${pn}, true)`;
|
|
219
|
-
},
|
|
220
|
-
gt: (ctx, parameters, whereArgs) => {
|
|
221
|
-
const { name, namePrefix, paramName, paramNamePrefix, whereVal } = whereArgs;
|
|
222
|
-
const pn = `${paramNamePrefix}${paramName}`;
|
|
223
|
-
parameters[pn] = whereVal;
|
|
224
|
-
return `${namePrefix}${name} > @${pn}`;
|
|
225
|
-
},
|
|
226
|
-
gte: (ctx, parameters, whereArgs) => {
|
|
227
|
-
const { name, namePrefix, paramName, paramNamePrefix, whereVal } = whereArgs;
|
|
228
|
-
const pn = `${paramNamePrefix}${paramName}`;
|
|
229
|
-
parameters[pn] = whereVal;
|
|
230
|
-
return `${namePrefix}${name} >= @${pn}`;
|
|
231
|
-
},
|
|
232
|
-
lt: (ctx, parameters, whereArgs) => {
|
|
233
|
-
const { name, namePrefix, paramName, paramNamePrefix, whereVal } = whereArgs;
|
|
234
|
-
const pn = `${paramNamePrefix}${paramName}`;
|
|
235
|
-
parameters[pn] = whereVal;
|
|
236
|
-
return `${namePrefix}${name} < @${pn}`;
|
|
237
|
-
},
|
|
238
|
-
lte: (ctx, parameters, whereArgs) => {
|
|
239
|
-
const { name, namePrefix, paramName, paramNamePrefix, whereVal } = whereArgs;
|
|
240
|
-
const pn = `${paramNamePrefix}${paramName}`;
|
|
241
|
-
parameters[pn] = whereVal;
|
|
242
|
-
return `${namePrefix}${name} <= @${pn}`;
|
|
243
106
|
}
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
const
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
107
|
+
for (const operatorKey in tableOperatorNotFns) {
|
|
108
|
+
const operator = operatorKey === "eq" ? null : operatorKey;
|
|
109
|
+
const whereKey = [fieldName, operator].filter((x) => x).join("_");
|
|
110
|
+
const whereKeyNot = `_not.${whereKey}`;
|
|
111
|
+
const whereValNot = _.get(where, whereKeyNot);
|
|
112
|
+
if (whereValNot != null) {
|
|
113
|
+
const whereClause = table.where(fieldName);
|
|
114
|
+
_.set(where, whereKeyNot, void 0);
|
|
115
|
+
return tableOperatorNotFns[operatorKey](whereClause, whereValNot);
|
|
253
116
|
}
|
|
254
|
-
const paramName = key;
|
|
255
|
-
const whereVal = where[key];
|
|
256
|
-
if (whereVal == null)
|
|
257
|
-
continue;
|
|
258
|
-
const f = getCosmosQueryWhereInner({ ...ctx, field: nameFromWhere }, parameters, {
|
|
259
|
-
operator,
|
|
260
|
-
whereVal,
|
|
261
|
-
name,
|
|
262
|
-
namePrefix,
|
|
263
|
-
paramName,
|
|
264
|
-
paramNamePrefix
|
|
265
|
-
});
|
|
266
|
-
if (f)
|
|
267
|
-
whereClauses.push(f);
|
|
268
117
|
}
|
|
269
|
-
return whereClauses.join(" AND ");
|
|
270
118
|
}
|
|
271
|
-
function
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
119
|
+
function normalizeArgs(args) {
|
|
120
|
+
if (!args)
|
|
121
|
+
args = {};
|
|
122
|
+
const where = _.cloneDeep(args.where) || {};
|
|
123
|
+
let orderBy = args.orderBy || "";
|
|
124
|
+
if (_.isArray(orderBy))
|
|
125
|
+
orderBy = orderBy[0] || "";
|
|
126
|
+
const orderByParts = orderBy.split("_");
|
|
127
|
+
const orderByProperty = orderByParts.slice(0, -1).join(".");
|
|
128
|
+
const orderByDirection = orderByParts.slice(-1)[0];
|
|
129
|
+
const maxItemCount = args.maxItemCount || 100;
|
|
130
|
+
return {
|
|
131
|
+
where,
|
|
132
|
+
orderByProperty,
|
|
133
|
+
orderByDirection,
|
|
134
|
+
maxItemCount,
|
|
135
|
+
cursor: args.cursor ? _.toNumber(args.cursor) : 0
|
|
136
|
+
};
|
|
280
137
|
}
|
|
281
|
-
function
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
if (!containerClientCache[key]) {
|
|
286
|
-
containerClientCache[key] = getCosmosDatabaseClient(options).container(containerName);
|
|
138
|
+
async function initDbIfNeeded(dbName) {
|
|
139
|
+
const dbWrapper = dbs[dbName];
|
|
140
|
+
if (!dbWrapper.initPromise) {
|
|
141
|
+
dbWrapper.initPromise = initDbInner(dbName);
|
|
287
142
|
}
|
|
288
|
-
return
|
|
143
|
+
return dbWrapper.initPromise;
|
|
289
144
|
}
|
|
290
|
-
function
|
|
291
|
-
|
|
292
|
-
const
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
145
|
+
async function initDbInner(dbName) {
|
|
146
|
+
const dbWrapper = dbs[dbName];
|
|
147
|
+
const stores = {
|
|
148
|
+
_system: "id"
|
|
149
|
+
};
|
|
150
|
+
for (const entity in dbWrapper.entities) {
|
|
151
|
+
stores[entity] = "id";
|
|
296
152
|
}
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
const
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
153
|
+
let db = new Dexie(dbWrapper.driverOptions.dbName, dbWrapper.driverOptions.dexieOptions);
|
|
154
|
+
db.version(1).stores(stores);
|
|
155
|
+
let systemTable = db._system;
|
|
156
|
+
const invalidateCounter = dbWrapper.driverOptions.invalidateCounter;
|
|
157
|
+
const currentVersionObject = await systemTable.get("_versionObject");
|
|
158
|
+
if (!currentVersionObject) {
|
|
159
|
+
await systemTable.put({ id: "_versionObject", stores, version: 1, invalidateCounter });
|
|
160
|
+
} else if (!_.isEqual(currentVersionObject.invalidateCounter, invalidateCounter)) {
|
|
161
|
+
await db.delete();
|
|
162
|
+
db = new Dexie(dbWrapper.driverOptions.dbName, dbWrapper.driverOptions.dexieOptions);
|
|
163
|
+
db.version(1).stores(stores);
|
|
164
|
+
systemTable = db._system;
|
|
165
|
+
await systemTable.put({ id: "_versionObject", stores, version: 1, invalidateCounter });
|
|
166
|
+
} else if (!_.isEqual(currentVersionObject.stores, stores)) {
|
|
167
|
+
const newVersion = currentVersionObject.version + 1;
|
|
168
|
+
db.version(newVersion).stores(stores);
|
|
169
|
+
await systemTable.put({ id: "_versionObject", stores, version: newVersion });
|
|
305
170
|
}
|
|
306
|
-
|
|
171
|
+
dbWrapper.db = db;
|
|
307
172
|
}
|
|
308
|
-
function
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
}
|
|
313
|
-
return
|
|
173
|
+
function getDb(options) {
|
|
174
|
+
const dbName = options?.dbName || "db";
|
|
175
|
+
if (dbs[dbName]?.db)
|
|
176
|
+
dbs[dbName].db?.close();
|
|
177
|
+
dbs[dbName] = { entities: {}, driverOptions: { dbName, dexieOptions: void 0, invalidateCounter: 0, ...options } };
|
|
178
|
+
return dbs[dbName];
|
|
314
179
|
}
|
package/drivers/memory.cjs
CHANGED
|
@@ -5,6 +5,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
module.exports = void 0;
|
|
7
7
|
exports.getAggFromArray = getAggFromArray;
|
|
8
|
+
exports.getFilter = getFilter;
|
|
8
9
|
exports.queryArray = queryArray;
|
|
9
10
|
var _lodash = _interopRequireDefault(require("lodash"));
|
|
10
11
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
package/drivers/memory.d.ts
CHANGED
package/drivers/memory.mjs
CHANGED
|
@@ -106,7 +106,7 @@ export function queryArray(array, args) {
|
|
|
106
106
|
const newCursor = endIndex >= array.length ? null : endIndex;
|
|
107
107
|
return { nodes: _.cloneDeep(result), cursor: newCursor?.toString() || null };
|
|
108
108
|
}
|
|
109
|
-
function getFilter(where, namePrefix = "") {
|
|
109
|
+
export function getFilter(where, namePrefix = "") {
|
|
110
110
|
if (_.isEmpty(where))
|
|
111
111
|
return null;
|
|
112
112
|
const andClauses = [];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "rads-db",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.105",
|
|
4
4
|
"files": [
|
|
5
5
|
"dist",
|
|
6
6
|
"drivers",
|
|
@@ -48,6 +48,7 @@
|
|
|
48
48
|
"peerDependencies": {
|
|
49
49
|
"@azure/cosmos": ">=3",
|
|
50
50
|
"@azure/storage-blob": ">=12",
|
|
51
|
+
"dexie": ">=3",
|
|
51
52
|
"h3": ">=1.6.0",
|
|
52
53
|
"typescript": ">=5.0.0"
|
|
53
54
|
},
|
|
@@ -60,6 +61,9 @@
|
|
|
60
61
|
},
|
|
61
62
|
"h3": {
|
|
62
63
|
"optional": true
|
|
64
|
+
},
|
|
65
|
+
"dexie": {
|
|
66
|
+
"optional": true
|
|
63
67
|
}
|
|
64
68
|
},
|
|
65
69
|
"packageManager": "pnpm@8.6.1",
|
|
@@ -72,7 +76,9 @@
|
|
|
72
76
|
"@types/uuid": "^9.0.2",
|
|
73
77
|
"@vitest/ui": "^0.31.0",
|
|
74
78
|
"cross-env": "^7.0.3",
|
|
79
|
+
"dexie": "^3.2.4",
|
|
75
80
|
"eslint-plugin-tyrecheck": "^2.54.4",
|
|
81
|
+
"fake-indexeddb": "^5.0.1",
|
|
76
82
|
"rads-db": "link:.",
|
|
77
83
|
"simple-git-hooks": "^2.8.1",
|
|
78
84
|
"symlink-dir": "^5.1.1",
|