rads-db 3.1.9 → 3.1.11
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/README.md +19 -0
- package/dist/index.cjs +37 -13
- package/dist/index.mjs +37 -13
- package/drivers/azureCosmos.cjs +35 -7
- package/drivers/azureCosmos.d.ts +1 -0
- package/drivers/azureCosmos.mjs +46 -33
- package/drivers/azureStorageBlob.cjs +2 -2
- package/drivers/azureStorageBlob.d.ts +1 -0
- package/drivers/azureStorageBlob.mjs +4 -8
- package/drivers/indexedDb.cjs +2 -2
- package/drivers/indexedDb.d.ts +1 -0
- package/drivers/indexedDb.mjs +6 -12
- package/drivers/memory.cjs +18 -11
- package/drivers/memory.d.ts +1 -0
- package/drivers/memory.mjs +46 -73
- package/drivers/restApi.cjs +1 -1
- package/drivers/restApi.d.ts +2 -1
- package/drivers/restApi.mjs +2 -4
- package/features/cache.cjs +2 -2
- package/features/cache.mjs +15 -30
- package/features/eventSourcing.cjs +2 -2
- package/features/eventSourcing.d.ts +1 -0
- package/features/eventSourcing.mjs +8 -16
- package/features/softDelete.cjs +1 -1
- package/features/softDelete.mjs +2 -4
- package/fileUploadDrivers/azureStorageBlob.cjs +1 -1
- package/fileUploadDrivers/cloudinary.cjs +1 -1
- package/fileUploadDrivers/memory.cjs +1 -1
- package/fileUploadDrivers/restApi.cjs +1 -1
- package/fileUploadDrivers/restApi.d.ts +1 -0
- package/fileUploadDrivers/restApi.mjs +1 -2
- package/fileUploadDrivers/supabaseStorage.cjs +1 -1
- package/fileUploadDrivers/supabaseStorage.mjs +3 -6
- package/integrations/node.cjs +2 -2
- package/integrations/node.mjs +12 -22
- package/integrations/nuxtModule.cjs +2 -3
- package/integrations/restEndpoints.cjs +1 -1
- package/integrations/restEndpoints.mjs +8 -16
- package/integrations/restEndpointsDev/restEndpointsDevLint.cjs +2 -3
- package/integrations/restEndpointsDev/restEndpointsDevLint.d.ts +1 -1
- package/integrations/restEndpointsDev/restEndpointsDevLint.mjs +5 -10
- package/integrations/restEndpointsDev.cjs +3 -4
- package/integrations/restEndpointsDev.d.ts +1 -1
- package/integrations/restEndpointsDev.mjs +9 -18
- package/integrations/restEndpointsDev2.cjs +3 -4
- package/integrations/restEndpointsDev2.d.ts +0 -1
- package/integrations/restEndpointsDev2.mjs +3 -6
- package/integrations/vite.mjs +3 -6
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -53,3 +53,22 @@ Consensus among the developer community is to use “simple” ORM, and use raw
|
|
|
53
53
|
We wanted to have features that are not supported in current ORMs:
|
|
54
54
|
|
|
55
55
|
- [This](https://medium.com/@rogerpadillac/in-search-of-the-perfect-orm-e01fcc9bce3d) article gives good overview
|
|
56
|
+
|
|
57
|
+
# Development tips
|
|
58
|
+
|
|
59
|
+
## Usage with `npm link`
|
|
60
|
+
|
|
61
|
+
When you want to test changes in this package, it may be useful to test with `pnpm link`.
|
|
62
|
+
|
|
63
|
+
But due to specifics of how this package uses peer dependencies, it won't work well.
|
|
64
|
+
|
|
65
|
+
Use file protocol instead:
|
|
66
|
+
|
|
67
|
+
```
|
|
68
|
+
// package.json
|
|
69
|
+
{
|
|
70
|
+
"dependencies": {
|
|
71
|
+
"rads-db": "file:../rads-db"
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
```
|
package/dist/index.cjs
CHANGED
|
@@ -204,10 +204,17 @@ const memory = (options) => (schema, entity) => {
|
|
|
204
204
|
const where = args.where || {};
|
|
205
205
|
const whereKeys = ___default.keys(where);
|
|
206
206
|
if (whereKeys.length === 1) {
|
|
207
|
-
if (whereKeys[0] === "id")
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
207
|
+
if (whereKeys[0] === "id") {
|
|
208
|
+
const node = ___default.cloneDeep([getItemById(where.id)].filter((x) => x));
|
|
209
|
+
return { nodes: node, cursor: null };
|
|
210
|
+
}
|
|
211
|
+
if (whereKeys[0] === "id_in") {
|
|
212
|
+
const nodes = ___default.cloneDeep(getItemByIds(where.id_in).filter((x) => x));
|
|
213
|
+
return {
|
|
214
|
+
nodes,
|
|
215
|
+
cursor: null
|
|
216
|
+
};
|
|
217
|
+
}
|
|
211
218
|
}
|
|
212
219
|
return queryArray(Object.values(itemsById), args);
|
|
213
220
|
}
|
|
@@ -363,7 +370,7 @@ function prepareArgs(args) {
|
|
|
363
370
|
const orderByDirection = orderByParts.slice(-1)[0];
|
|
364
371
|
let maxItemCount = args.maxItemCount;
|
|
365
372
|
maxItemCount = maxItemCount || 100;
|
|
366
|
-
return { where, orderByProperty, orderByDirection, maxItemCount, cursor: args.cursor };
|
|
373
|
+
return { where, orderByProperty, orderByDirection, maxItemCount, cursor: args.cursor, pick: args.include };
|
|
367
374
|
}
|
|
368
375
|
|
|
369
376
|
const computedPresets = {
|
|
@@ -690,7 +697,7 @@ async function handleInclude(computedContext, include, result, ctx) {
|
|
|
690
697
|
return;
|
|
691
698
|
const { schema, typeName } = computedContext;
|
|
692
699
|
const fields = schema[typeName].fields || {};
|
|
693
|
-
const fieldsToInclude = ___default.keys(include).filter((key) => include[key]);
|
|
700
|
+
const fieldsToInclude = ___default.keys(include).filter((key) => include[key] && key !== "_pick");
|
|
694
701
|
const nestedFieldsToInclude = fieldsToInclude.filter(
|
|
695
702
|
(key) => !fields[key].isRelation && !fields[key].isInverseRelation && schema[fields[key].type]?.fields
|
|
696
703
|
);
|
|
@@ -795,7 +802,7 @@ function getRadsDbMethods(key, computedContext, driverInstance) {
|
|
|
795
802
|
const { precomputedFields } = entitySchema;
|
|
796
803
|
async function getMany(args, ctx) {
|
|
797
804
|
args = { ...args, where: { ...args?.where } };
|
|
798
|
-
ctx = { ...options.context, ...ctx, method: "getMany" };
|
|
805
|
+
ctx = { ...options.context, ...ctx, method: "getMany", _isRecursiveRoot: !ctx?._isRecursiveRoot };
|
|
799
806
|
let result2 = await beforeGet(args, ctx, computedContext);
|
|
800
807
|
if (!result2)
|
|
801
808
|
result2 = await driverInstance.getMany(args, ctx);
|
|
@@ -803,6 +810,8 @@ function getRadsDbMethods(key, computedContext, driverInstance) {
|
|
|
803
810
|
await radsDbRelations.handleInclude(computedContext, args.include, result2.nodes, ctx);
|
|
804
811
|
await handleComputed(computedContext, result2.nodes, ctx);
|
|
805
812
|
await afterGet(result2.nodes, args, ctx, computedContext);
|
|
813
|
+
if (ctx._isRecursiveRoot && args.include?._pick)
|
|
814
|
+
result2.nodes = await pickPropsFromObjectAsync(result2.nodes, args.include);
|
|
806
815
|
return result2;
|
|
807
816
|
}
|
|
808
817
|
async function putMany(docs, ctx) {
|
|
@@ -946,7 +955,7 @@ function getRadsDbMethods(key, computedContext, driverInstance) {
|
|
|
946
955
|
},
|
|
947
956
|
get: async (args, ctx) => {
|
|
948
957
|
args = { ...args, where: { ...args?.where } };
|
|
949
|
-
ctx = { ...options.context, ...ctx, method: "get" };
|
|
958
|
+
ctx = { ...options.context, ...ctx, method: "get", _isRecursiveRoot: !ctx?._isRecursiveRoot };
|
|
950
959
|
let result2 = await beforeGet(args, ctx, computedContext);
|
|
951
960
|
if (!result2)
|
|
952
961
|
result2 = await driverInstance.get(args, ctx);
|
|
@@ -956,11 +965,13 @@ function getRadsDbMethods(key, computedContext, driverInstance) {
|
|
|
956
965
|
if (result2)
|
|
957
966
|
await handleComputed(computedContext, resultArray, ctx);
|
|
958
967
|
await afterGet(resultArray, args, ctx, computedContext);
|
|
968
|
+
if (ctx._isRecursiveRoot && args.include?._pick)
|
|
969
|
+
result2 = await pickPropsFromObjectAsync(result2, args.include);
|
|
959
970
|
return result2;
|
|
960
971
|
},
|
|
961
972
|
getAll: async (args, ctx) => {
|
|
962
973
|
args = { ...args, where: { ...args?.where } };
|
|
963
|
-
ctx = { ...options.context, ...ctx, method: "getAll" };
|
|
974
|
+
ctx = { ...options.context, ...ctx, method: "getAll", _isRecursiveRoot: !ctx?._isRecursiveRoot };
|
|
964
975
|
let result2 = await beforeGet(args, ctx, computedContext);
|
|
965
976
|
if (!result2)
|
|
966
977
|
result2 = await driverInstance.getAll(args, ctx);
|
|
@@ -968,6 +979,9 @@ function getRadsDbMethods(key, computedContext, driverInstance) {
|
|
|
968
979
|
await radsDbRelations.handleInclude(computedContext, args.include, result2, ctx);
|
|
969
980
|
await handleComputed(computedContext, result2, ctx);
|
|
970
981
|
await afterGet(result2, args, ctx, computedContext);
|
|
982
|
+
if (ctx._isRecursiveRoot && args.include?._pick) {
|
|
983
|
+
result2 = await pickPropsFromObjectAsync(result2, args.include);
|
|
984
|
+
}
|
|
971
985
|
return result2;
|
|
972
986
|
},
|
|
973
987
|
verifyAll: async (args, ctx) => {
|
|
@@ -1043,6 +1057,18 @@ async function afterPut(items, ctx, computedContext) {
|
|
|
1043
1057
|
await f.afterPut?.(items, ctx, computedContext);
|
|
1044
1058
|
}
|
|
1045
1059
|
}
|
|
1060
|
+
async function pickPropsFromObjectAsync(obj, args) {
|
|
1061
|
+
if (Array.isArray(obj)) {
|
|
1062
|
+
return Promise.all(obj.map((o) => pickPropsFromObjectAsync(o, args)));
|
|
1063
|
+
}
|
|
1064
|
+
const result = args._pick ? ___default.pick(obj, args._pick) : {};
|
|
1065
|
+
for (const key of Object.keys(args)) {
|
|
1066
|
+
if (key !== "_pick" && typeof args[key] === "object" && obj[key]) {
|
|
1067
|
+
result[key] = await pickPropsFromObjectAsync(obj[key], args[key]);
|
|
1068
|
+
}
|
|
1069
|
+
}
|
|
1070
|
+
return result;
|
|
1071
|
+
}
|
|
1046
1072
|
|
|
1047
1073
|
function generateMethods(schema, validators, options) {
|
|
1048
1074
|
const drivers = {};
|
|
@@ -1233,16 +1259,14 @@ const restApi = (options) => (schema, entity) => {
|
|
|
1233
1259
|
if (!response.ok) {
|
|
1234
1260
|
const msg = responseJson?.message || responseJson?.statusMessage || response.statusText || "Server error.";
|
|
1235
1261
|
const err = new Error(msg);
|
|
1236
|
-
if (responseJson?.code)
|
|
1237
|
-
err.code = responseJson?.code;
|
|
1262
|
+
if (responseJson?.code) err.code = responseJson?.code;
|
|
1238
1263
|
err.fetchResponseJson = responseJson;
|
|
1239
1264
|
throw err;
|
|
1240
1265
|
}
|
|
1241
1266
|
return responseJson;
|
|
1242
1267
|
}
|
|
1243
1268
|
const { handlePlural } = schema[entity] || {};
|
|
1244
|
-
if (!handlePlural)
|
|
1245
|
-
throw new Error(`Entity ${entity} was not found in schema`);
|
|
1269
|
+
if (!handlePlural) throw new Error(`Entity ${entity} was not found in schema`);
|
|
1246
1270
|
const instance = {
|
|
1247
1271
|
driverName: "restApi",
|
|
1248
1272
|
async getMany(args, ctx) {
|
package/dist/index.mjs
CHANGED
|
@@ -197,10 +197,17 @@ const memory = (options) => (schema, entity) => {
|
|
|
197
197
|
const where = args.where || {};
|
|
198
198
|
const whereKeys = _.keys(where);
|
|
199
199
|
if (whereKeys.length === 1) {
|
|
200
|
-
if (whereKeys[0] === "id")
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
200
|
+
if (whereKeys[0] === "id") {
|
|
201
|
+
const node = _.cloneDeep([getItemById(where.id)].filter((x) => x));
|
|
202
|
+
return { nodes: node, cursor: null };
|
|
203
|
+
}
|
|
204
|
+
if (whereKeys[0] === "id_in") {
|
|
205
|
+
const nodes = _.cloneDeep(getItemByIds(where.id_in).filter((x) => x));
|
|
206
|
+
return {
|
|
207
|
+
nodes,
|
|
208
|
+
cursor: null
|
|
209
|
+
};
|
|
210
|
+
}
|
|
204
211
|
}
|
|
205
212
|
return queryArray(Object.values(itemsById), args);
|
|
206
213
|
}
|
|
@@ -356,7 +363,7 @@ function prepareArgs(args) {
|
|
|
356
363
|
const orderByDirection = orderByParts.slice(-1)[0];
|
|
357
364
|
let maxItemCount = args.maxItemCount;
|
|
358
365
|
maxItemCount = maxItemCount || 100;
|
|
359
|
-
return { where, orderByProperty, orderByDirection, maxItemCount, cursor: args.cursor };
|
|
366
|
+
return { where, orderByProperty, orderByDirection, maxItemCount, cursor: args.cursor, pick: args.include };
|
|
360
367
|
}
|
|
361
368
|
|
|
362
369
|
const computedPresets = {
|
|
@@ -683,7 +690,7 @@ async function handleInclude(computedContext, include, result, ctx) {
|
|
|
683
690
|
return;
|
|
684
691
|
const { schema, typeName } = computedContext;
|
|
685
692
|
const fields = schema[typeName].fields || {};
|
|
686
|
-
const fieldsToInclude = _.keys(include).filter((key) => include[key]);
|
|
693
|
+
const fieldsToInclude = _.keys(include).filter((key) => include[key] && key !== "_pick");
|
|
687
694
|
const nestedFieldsToInclude = fieldsToInclude.filter(
|
|
688
695
|
(key) => !fields[key].isRelation && !fields[key].isInverseRelation && schema[fields[key].type]?.fields
|
|
689
696
|
);
|
|
@@ -788,7 +795,7 @@ function getRadsDbMethods(key, computedContext, driverInstance) {
|
|
|
788
795
|
const { precomputedFields } = entitySchema;
|
|
789
796
|
async function getMany(args, ctx) {
|
|
790
797
|
args = { ...args, where: { ...args?.where } };
|
|
791
|
-
ctx = { ...options.context, ...ctx, method: "getMany" };
|
|
798
|
+
ctx = { ...options.context, ...ctx, method: "getMany", _isRecursiveRoot: !ctx?._isRecursiveRoot };
|
|
792
799
|
let result2 = await beforeGet(args, ctx, computedContext);
|
|
793
800
|
if (!result2)
|
|
794
801
|
result2 = await driverInstance.getMany(args, ctx);
|
|
@@ -796,6 +803,8 @@ function getRadsDbMethods(key, computedContext, driverInstance) {
|
|
|
796
803
|
await radsDbRelations.handleInclude(computedContext, args.include, result2.nodes, ctx);
|
|
797
804
|
await handleComputed(computedContext, result2.nodes, ctx);
|
|
798
805
|
await afterGet(result2.nodes, args, ctx, computedContext);
|
|
806
|
+
if (ctx._isRecursiveRoot && args.include?._pick)
|
|
807
|
+
result2.nodes = await pickPropsFromObjectAsync(result2.nodes, args.include);
|
|
799
808
|
return result2;
|
|
800
809
|
}
|
|
801
810
|
async function putMany(docs, ctx) {
|
|
@@ -939,7 +948,7 @@ function getRadsDbMethods(key, computedContext, driverInstance) {
|
|
|
939
948
|
},
|
|
940
949
|
get: async (args, ctx) => {
|
|
941
950
|
args = { ...args, where: { ...args?.where } };
|
|
942
|
-
ctx = { ...options.context, ...ctx, method: "get" };
|
|
951
|
+
ctx = { ...options.context, ...ctx, method: "get", _isRecursiveRoot: !ctx?._isRecursiveRoot };
|
|
943
952
|
let result2 = await beforeGet(args, ctx, computedContext);
|
|
944
953
|
if (!result2)
|
|
945
954
|
result2 = await driverInstance.get(args, ctx);
|
|
@@ -949,11 +958,13 @@ function getRadsDbMethods(key, computedContext, driverInstance) {
|
|
|
949
958
|
if (result2)
|
|
950
959
|
await handleComputed(computedContext, resultArray, ctx);
|
|
951
960
|
await afterGet(resultArray, args, ctx, computedContext);
|
|
961
|
+
if (ctx._isRecursiveRoot && args.include?._pick)
|
|
962
|
+
result2 = await pickPropsFromObjectAsync(result2, args.include);
|
|
952
963
|
return result2;
|
|
953
964
|
},
|
|
954
965
|
getAll: async (args, ctx) => {
|
|
955
966
|
args = { ...args, where: { ...args?.where } };
|
|
956
|
-
ctx = { ...options.context, ...ctx, method: "getAll" };
|
|
967
|
+
ctx = { ...options.context, ...ctx, method: "getAll", _isRecursiveRoot: !ctx?._isRecursiveRoot };
|
|
957
968
|
let result2 = await beforeGet(args, ctx, computedContext);
|
|
958
969
|
if (!result2)
|
|
959
970
|
result2 = await driverInstance.getAll(args, ctx);
|
|
@@ -961,6 +972,9 @@ function getRadsDbMethods(key, computedContext, driverInstance) {
|
|
|
961
972
|
await radsDbRelations.handleInclude(computedContext, args.include, result2, ctx);
|
|
962
973
|
await handleComputed(computedContext, result2, ctx);
|
|
963
974
|
await afterGet(result2, args, ctx, computedContext);
|
|
975
|
+
if (ctx._isRecursiveRoot && args.include?._pick) {
|
|
976
|
+
result2 = await pickPropsFromObjectAsync(result2, args.include);
|
|
977
|
+
}
|
|
964
978
|
return result2;
|
|
965
979
|
},
|
|
966
980
|
verifyAll: async (args, ctx) => {
|
|
@@ -1036,6 +1050,18 @@ async function afterPut(items, ctx, computedContext) {
|
|
|
1036
1050
|
await f.afterPut?.(items, ctx, computedContext);
|
|
1037
1051
|
}
|
|
1038
1052
|
}
|
|
1053
|
+
async function pickPropsFromObjectAsync(obj, args) {
|
|
1054
|
+
if (Array.isArray(obj)) {
|
|
1055
|
+
return Promise.all(obj.map((o) => pickPropsFromObjectAsync(o, args)));
|
|
1056
|
+
}
|
|
1057
|
+
const result = args._pick ? _.pick(obj, args._pick) : {};
|
|
1058
|
+
for (const key of Object.keys(args)) {
|
|
1059
|
+
if (key !== "_pick" && typeof args[key] === "object" && obj[key]) {
|
|
1060
|
+
result[key] = await pickPropsFromObjectAsync(obj[key], args[key]);
|
|
1061
|
+
}
|
|
1062
|
+
}
|
|
1063
|
+
return result;
|
|
1064
|
+
}
|
|
1039
1065
|
|
|
1040
1066
|
function generateMethods(schema, validators, options) {
|
|
1041
1067
|
const drivers = {};
|
|
@@ -1226,16 +1252,14 @@ const restApi = (options) => (schema, entity) => {
|
|
|
1226
1252
|
if (!response.ok) {
|
|
1227
1253
|
const msg = responseJson?.message || responseJson?.statusMessage || response.statusText || "Server error.";
|
|
1228
1254
|
const err = new Error(msg);
|
|
1229
|
-
if (responseJson?.code)
|
|
1230
|
-
err.code = responseJson?.code;
|
|
1255
|
+
if (responseJson?.code) err.code = responseJson?.code;
|
|
1231
1256
|
err.fetchResponseJson = responseJson;
|
|
1232
1257
|
throw err;
|
|
1233
1258
|
}
|
|
1234
1259
|
return responseJson;
|
|
1235
1260
|
}
|
|
1236
1261
|
const { handlePlural } = schema[entity] || {};
|
|
1237
|
-
if (!handlePlural)
|
|
1238
|
-
throw new Error(`Entity ${entity} was not found in schema`);
|
|
1262
|
+
if (!handlePlural) throw new Error(`Entity ${entity} was not found in schema`);
|
|
1239
1263
|
const instance = {
|
|
1240
1264
|
driverName: "restApi",
|
|
1241
1265
|
async getMany(args, ctx) {
|
package/drivers/azureCosmos.cjs
CHANGED
|
@@ -3,10 +3,10 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
|
|
6
|
+
|
|
7
7
|
var _cosmos = require("@azure/cosmos");
|
|
8
8
|
var _lodash = _interopRequireDefault(require("lodash"));
|
|
9
|
-
function _interopRequireDefault(
|
|
9
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
10
10
|
const cosmosClientCache = {};
|
|
11
11
|
const databaseClientCache = {};
|
|
12
12
|
const containerClientCache = {};
|
|
@@ -24,14 +24,15 @@ var _default = options => (schema, entity) => {
|
|
|
24
24
|
if (options.createDatabaseIfNotExists) {
|
|
25
25
|
createDatabaseIfNotExists(normalizedOptions, client.database.client);
|
|
26
26
|
}
|
|
27
|
-
async function getItemByIds(ids, ctx) {
|
|
27
|
+
async function getItemByIds(ids, ctx, include) {
|
|
28
28
|
const {
|
|
29
29
|
query,
|
|
30
30
|
parameters
|
|
31
31
|
} = getCosmosQuery(schema, entity, {
|
|
32
32
|
where: {
|
|
33
33
|
id_in: ids
|
|
34
|
-
}
|
|
34
|
+
},
|
|
35
|
+
include
|
|
35
36
|
});
|
|
36
37
|
const response = client.items.query({
|
|
37
38
|
query,
|
|
@@ -53,14 +54,14 @@ var _default = options => (schema, entity) => {
|
|
|
53
54
|
const whereKeys = _lodash.default.keys(where);
|
|
54
55
|
if (whereKeys.length === 1) {
|
|
55
56
|
if (whereKeys[0] === "id" && where.id != null) {
|
|
56
|
-
const items = await getItemByIds([where.id], ctx);
|
|
57
|
+
const items = await getItemByIds([where.id], ctx, args.include);
|
|
57
58
|
return {
|
|
58
59
|
nodes: [items[0]].filter(x => x),
|
|
59
60
|
cursor: null
|
|
60
61
|
};
|
|
61
62
|
}
|
|
62
63
|
if (whereKeys[0] === "id_in" && where.id_in != null) {
|
|
63
|
-
const items = await getItemByIds(where.id_in, ctx);
|
|
64
|
+
const items = await getItemByIds(where.id_in, ctx, args.include);
|
|
64
65
|
return {
|
|
65
66
|
nodes: items.filter(x => x),
|
|
66
67
|
cursor: null
|
|
@@ -161,7 +162,11 @@ function getCosmosQuery(schema, entity, args) {
|
|
|
161
162
|
const orderProp = orderPropFromOrderBy === "value" ? `r["value"]` : `r.${orderPropFromOrderBy}`;
|
|
162
163
|
orderByClause = `order by ${orderProp} ${orderDirection}`;
|
|
163
164
|
}
|
|
164
|
-
|
|
165
|
+
let colums = "*";
|
|
166
|
+
if (args.include?._pick) {
|
|
167
|
+
colums = getCosmosSelectValue(args.include);
|
|
168
|
+
}
|
|
169
|
+
const query = `select ${colums} from r where ${whereClauses.join(" AND ")} ${orderByClause}`;
|
|
165
170
|
return {
|
|
166
171
|
query,
|
|
167
172
|
parameters
|
|
@@ -589,4 +594,27 @@ async function bulkSendWithRetry(client, chunkToSend) {
|
|
|
589
594
|
});
|
|
590
595
|
}
|
|
591
596
|
return responses;
|
|
597
|
+
}
|
|
598
|
+
function buildSelectValue(includeArgs, path = "r") {
|
|
599
|
+
const parts = [];
|
|
600
|
+
if (Array.isArray(includeArgs._pick)) {
|
|
601
|
+
for (const key of includeArgs._pick) {
|
|
602
|
+
parts.push(`${key}: ${path}.${key}`);
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
for (const key of Object.keys(includeArgs)) {
|
|
606
|
+
if (key === "_pick") continue;
|
|
607
|
+
const nested = includeArgs[key];
|
|
608
|
+
if (typeof nested === "object" && nested !== null) {
|
|
609
|
+
const nestedSelect = buildSelectValue(nested, `${path}.${key}`);
|
|
610
|
+
parts.push(`${key}: { ${nestedSelect} }`);
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
return parts.join(", ");
|
|
614
|
+
}
|
|
615
|
+
function getCosmosSelectValue(includeArgs) {
|
|
616
|
+
const projection = buildSelectValue(includeArgs);
|
|
617
|
+
return `VALUE {
|
|
618
|
+
${projection}
|
|
619
|
+
} `;
|
|
592
620
|
}
|
package/drivers/azureCosmos.d.ts
CHANGED
package/drivers/azureCosmos.mjs
CHANGED
|
@@ -17,8 +17,8 @@ export default (options) => (schema, entity) => {
|
|
|
17
17
|
if (options.createDatabaseIfNotExists) {
|
|
18
18
|
createDatabaseIfNotExists(normalizedOptions, client.database.client);
|
|
19
19
|
}
|
|
20
|
-
async function getItemByIds(ids, ctx) {
|
|
21
|
-
const { query, parameters } = getCosmosQuery(schema, entity, { where: { id_in: ids } });
|
|
20
|
+
async function getItemByIds(ids, ctx, include) {
|
|
21
|
+
const { query, parameters } = getCosmosQuery(schema, entity, { where: { id_in: ids }, include });
|
|
22
22
|
const response = client.items.query({
|
|
23
23
|
query,
|
|
24
24
|
parameters: Object.keys(parameters).map((k) => ({ name: `@${k}`, value: parameters[k] }))
|
|
@@ -33,11 +33,11 @@ export default (options) => (schema, entity) => {
|
|
|
33
33
|
const whereKeys = _.keys(where);
|
|
34
34
|
if (whereKeys.length === 1) {
|
|
35
35
|
if (whereKeys[0] === "id" && where.id != null) {
|
|
36
|
-
const items = await getItemByIds([where.id], ctx);
|
|
36
|
+
const items = await getItemByIds([where.id], ctx, args.include);
|
|
37
37
|
return { nodes: [items[0]].filter((x) => x), cursor: null };
|
|
38
38
|
}
|
|
39
39
|
if (whereKeys[0] === "id_in" && where.id_in != null) {
|
|
40
|
-
const items = await getItemByIds(where.id_in, ctx);
|
|
40
|
+
const items = await getItemByIds(where.id_in, ctx, args.include);
|
|
41
41
|
return { nodes: items.filter((x) => x), cursor: null };
|
|
42
42
|
}
|
|
43
43
|
}
|
|
@@ -84,8 +84,7 @@ export default (options) => (schema, entity) => {
|
|
|
84
84
|
const itemsToPut = [];
|
|
85
85
|
for (const item of items) {
|
|
86
86
|
const id = item?.id;
|
|
87
|
-
if (!id)
|
|
88
|
-
throw new Error(`You must provide an id`);
|
|
87
|
+
if (!id) throw new Error(`You must provide an id`);
|
|
89
88
|
itemsToPut.push({ _partition: entity, id, ...item });
|
|
90
89
|
}
|
|
91
90
|
for (const chunk of _.chunk(itemsToPut, 100)) {
|
|
@@ -119,7 +118,11 @@ function getCosmosQuery(schema, entity, args) {
|
|
|
119
118
|
const orderProp = orderPropFromOrderBy === "value" ? `r["value"]` : `r.${orderPropFromOrderBy}`;
|
|
120
119
|
orderByClause = `order by ${orderProp} ${orderDirection}`;
|
|
121
120
|
}
|
|
122
|
-
|
|
121
|
+
let colums = "*";
|
|
122
|
+
if (args.include?._pick) {
|
|
123
|
+
colums = getCosmosSelectValue(args.include);
|
|
124
|
+
}
|
|
125
|
+
const query = `select ${colums} from r where ${whereClauses.join(" AND ")} ${orderByClause}`;
|
|
123
126
|
return { query, parameters };
|
|
124
127
|
}
|
|
125
128
|
const operatorHandlers = {
|
|
@@ -140,48 +143,41 @@ const operatorHandlers = {
|
|
|
140
143
|
none: (ctx, parameters, whereArgs) => {
|
|
141
144
|
const { name, namePrefix, paramNamePrefix, paramName, whereVal } = whereArgs;
|
|
142
145
|
const subClause = getCosmosQueryWhere(ctx, parameters, whereVal, `${name}.`, `${paramNamePrefix}${paramName}_`);
|
|
143
|
-
if (subClause)
|
|
144
|
-
return `not exists (select ${name} from ${name} in ${namePrefix}${name} where ${subClause})`;
|
|
146
|
+
if (subClause) return `not exists (select ${name} from ${name} in ${namePrefix}${name} where ${subClause})`;
|
|
145
147
|
return `array_length(${namePrefix}${name}) = 0`;
|
|
146
148
|
},
|
|
147
149
|
and: (ctx, parameters, whereArgs) => {
|
|
148
150
|
const { namePrefix, paramNamePrefix, whereVal } = whereArgs;
|
|
149
|
-
if (!_.isArray(whereVal))
|
|
150
|
-
throw new Error(`Value for where._and must be an array`);
|
|
151
|
+
if (!_.isArray(whereVal)) throw new Error(`Value for where._and must be an array`);
|
|
151
152
|
const clauses = [];
|
|
152
153
|
for (let i = 0; i < whereVal.length; i++) {
|
|
153
154
|
const andQuery = getCosmosQueryWhere(ctx, parameters, whereVal[i], namePrefix, `${paramNamePrefix}and${i}_`);
|
|
154
155
|
clauses.push(andQuery);
|
|
155
156
|
}
|
|
156
|
-
if (!clauses.length)
|
|
157
|
-
return null;
|
|
157
|
+
if (!clauses.length) return null;
|
|
158
158
|
return `((${clauses.join(") and (")}))`;
|
|
159
159
|
},
|
|
160
160
|
not: (ctx, parameters, whereArgs) => {
|
|
161
161
|
const { name, namePrefix, paramNamePrefix, whereVal } = whereArgs;
|
|
162
162
|
const subClause = getCosmosQueryWhere(ctx, parameters, whereVal, `${namePrefix}${name}`, `${paramNamePrefix}not_`);
|
|
163
|
-
if (!subClause)
|
|
164
|
-
return null;
|
|
163
|
+
if (!subClause) return null;
|
|
165
164
|
return `not(${subClause})`;
|
|
166
165
|
},
|
|
167
166
|
or: (ctx, parameters, whereArgs) => {
|
|
168
167
|
const { namePrefix, paramNamePrefix, whereVal } = whereArgs;
|
|
169
|
-
if (!_.isArray(whereVal))
|
|
170
|
-
throw new Error(`Value for where._or must be an array`);
|
|
168
|
+
if (!_.isArray(whereVal)) throw new Error(`Value for where._or must be an array`);
|
|
171
169
|
const clauses = [];
|
|
172
170
|
for (let i = 0; i < whereVal.length; i++) {
|
|
173
171
|
const orQuery = getCosmosQueryWhere(ctx, parameters, whereVal[i], namePrefix, `${paramNamePrefix}or${i}_`);
|
|
174
172
|
clauses.push(orQuery);
|
|
175
173
|
}
|
|
176
|
-
if (!clauses.length)
|
|
177
|
-
return null;
|
|
174
|
+
if (!clauses.length) return null;
|
|
178
175
|
return `((${clauses.join(") or (")}))`;
|
|
179
176
|
},
|
|
180
177
|
isNull: (ctx, parameters, whereArgs) => {
|
|
181
178
|
const { name, namePrefix, whereVal } = whereArgs;
|
|
182
179
|
const n = `${namePrefix}${name}`;
|
|
183
|
-
if (whereVal)
|
|
184
|
-
return `(not (is_defined(${n})) or ${n} = null)`;
|
|
180
|
+
if (whereVal) return `(not (is_defined(${n})) or ${n} = null)`;
|
|
185
181
|
return `(is_defined(${n}) and ${n} != null)`;
|
|
186
182
|
},
|
|
187
183
|
eq: (ctx, parameters, whereArgs) => {
|
|
@@ -241,17 +237,14 @@ const operatorHandlers = {
|
|
|
241
237
|
isEmpty: (ctx, parameters, whereArgs) => {
|
|
242
238
|
const { name, namePrefix, whereVal } = whereArgs;
|
|
243
239
|
const n = `${namePrefix}${name}`;
|
|
244
|
-
if (whereVal)
|
|
245
|
-
return `(not (is_defined(${n})) or ${n} = null or array_length(${n}) = 0)`;
|
|
240
|
+
if (whereVal) return `(not (is_defined(${n})) or ${n} = null or array_length(${n}) = 0)`;
|
|
246
241
|
return `(is_defined(${n}) and ${n} != null and array_length(${n}) > 0)`;
|
|
247
242
|
},
|
|
248
243
|
jsonContains: (ctx, parameters, whereArgs) => {
|
|
249
244
|
const { name, namePrefix, paramName, paramNamePrefix, whereVal } = whereArgs;
|
|
250
245
|
const { path, isNull, value } = whereVal;
|
|
251
|
-
if (!path)
|
|
252
|
-
|
|
253
|
-
if (!sanitizePathRegex.test(path))
|
|
254
|
-
throw new Error(`Invalid path ${path}`);
|
|
246
|
+
if (!path) return "";
|
|
247
|
+
if (!sanitizePathRegex.test(path)) throw new Error(`Invalid path ${path}`);
|
|
255
248
|
const pn = `${paramNamePrefix}${paramName}`;
|
|
256
249
|
parameters[pn] = whereVal;
|
|
257
250
|
const fullPath = `${namePrefix}${name}.${path}`;
|
|
@@ -310,8 +303,7 @@ function getCosmosQueryWhere(ctx, parameters, where, namePrefix = "r.", paramNam
|
|
|
310
303
|
}
|
|
311
304
|
const paramName = key;
|
|
312
305
|
const whereVal = where[key];
|
|
313
|
-
if (whereVal == null)
|
|
314
|
-
continue;
|
|
306
|
+
if (whereVal == null) continue;
|
|
315
307
|
const f = getCosmosQueryWhereInner({ ...ctx, field: nameFromWhere }, parameters, {
|
|
316
308
|
operator,
|
|
317
309
|
whereVal,
|
|
@@ -320,8 +312,7 @@ function getCosmosQueryWhere(ctx, parameters, where, namePrefix = "r.", paramNam
|
|
|
320
312
|
paramName,
|
|
321
313
|
paramNamePrefix
|
|
322
314
|
});
|
|
323
|
-
if (f)
|
|
324
|
-
whereClauses.push(f);
|
|
315
|
+
if (f) whereClauses.push(f);
|
|
325
316
|
}
|
|
326
317
|
return whereClauses.join(" AND ");
|
|
327
318
|
}
|
|
@@ -389,8 +380,7 @@ async function bulkSendWithRetry(client, chunkToSend) {
|
|
|
389
380
|
}
|
|
390
381
|
}
|
|
391
382
|
chunkToSend = newChunkToSend;
|
|
392
|
-
if (chunkToSend.length === 0)
|
|
393
|
-
break;
|
|
383
|
+
if (chunkToSend.length === 0) break;
|
|
394
384
|
const delay = 50 + i * 100;
|
|
395
385
|
console.warn(`Db overloaded. Retrying after ${delay}ms...`);
|
|
396
386
|
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
@@ -402,3 +392,26 @@ async function bulkSendWithRetry(client, chunkToSend) {
|
|
|
402
392
|
}
|
|
403
393
|
return responses;
|
|
404
394
|
}
|
|
395
|
+
function buildSelectValue(includeArgs, path = "r") {
|
|
396
|
+
const parts = [];
|
|
397
|
+
if (Array.isArray(includeArgs._pick)) {
|
|
398
|
+
for (const key of includeArgs._pick) {
|
|
399
|
+
parts.push(`${key}: ${path}.${key}`);
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
for (const key of Object.keys(includeArgs)) {
|
|
403
|
+
if (key === "_pick") continue;
|
|
404
|
+
const nested = includeArgs[key];
|
|
405
|
+
if (typeof nested === "object" && nested !== null) {
|
|
406
|
+
const nestedSelect = buildSelectValue(nested, `${path}.${key}`);
|
|
407
|
+
parts.push(`${key}: { ${nestedSelect} }`);
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
return parts.join(", ");
|
|
411
|
+
}
|
|
412
|
+
function getCosmosSelectValue(includeArgs) {
|
|
413
|
+
const projection = buildSelectValue(includeArgs);
|
|
414
|
+
return `VALUE {
|
|
415
|
+
${projection}
|
|
416
|
+
} `;
|
|
417
|
+
}
|
|
@@ -3,10 +3,10 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
|
|
6
|
+
|
|
7
7
|
var _storageBlob = require("@azure/storage-blob");
|
|
8
8
|
var _lodash = _interopRequireDefault(require("lodash"));
|
|
9
|
-
function _interopRequireDefault(
|
|
9
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
10
10
|
const blobServiceClientCache = {};
|
|
11
11
|
const containerClientCache = {};
|
|
12
12
|
var _default = options => (schema, entity) => {
|
|
@@ -15,8 +15,7 @@ export default (options) => (schema, entity) => {
|
|
|
15
15
|
ctx?.log?.({ requestId: downloadResponse.requestId, charge: str.length, request: `download ${name}` });
|
|
16
16
|
return JSON.parse(str);
|
|
17
17
|
} catch (e) {
|
|
18
|
-
if (e?.statusCode === 404)
|
|
19
|
-
return void 0;
|
|
18
|
+
if (e?.statusCode === 404) return void 0;
|
|
20
19
|
throw e;
|
|
21
20
|
}
|
|
22
21
|
}
|
|
@@ -41,8 +40,7 @@ export default (options) => (schema, entity) => {
|
|
|
41
40
|
return { nodes: items.filter((x) => x), cursor: null };
|
|
42
41
|
}
|
|
43
42
|
}
|
|
44
|
-
if (whereKeys.length > 1)
|
|
45
|
-
throw new Error("Complex queries are not supported by azureStorageBlob");
|
|
43
|
+
if (whereKeys.length > 1) throw new Error("Complex queries are not supported by azureStorageBlob");
|
|
46
44
|
const iterator = containerClient.listBlobsFlat({}).byPage({ maxPageSize: args.maxItemCount || 30, continuationToken: args.cursor || void 0 });
|
|
47
45
|
for await (const page of iterator) {
|
|
48
46
|
ctx?.log?.({
|
|
@@ -81,8 +79,7 @@ export default (options) => (schema, entity) => {
|
|
|
81
79
|
async putMany(items, ctx) {
|
|
82
80
|
for (const item of items) {
|
|
83
81
|
const id = item?.id;
|
|
84
|
-
if (!id)
|
|
85
|
-
throw new Error(`You must provide an id`);
|
|
82
|
+
if (!id) throw new Error(`You must provide an id`);
|
|
86
83
|
const blobName = getBlobName(entity, item);
|
|
87
84
|
const itemToPut = item;
|
|
88
85
|
const blobClient = containerClient.getBlockBlobClient(blobName);
|
|
@@ -95,8 +92,7 @@ export default (options) => (schema, entity) => {
|
|
|
95
92
|
return instance;
|
|
96
93
|
};
|
|
97
94
|
function getBlobName(entity, item) {
|
|
98
|
-
if (!item.id)
|
|
99
|
-
throw new Error("Item must have an id");
|
|
95
|
+
if (!item.id) throw new Error("Item must have an id");
|
|
100
96
|
return `${entity}/${item.id}.json`;
|
|
101
97
|
}
|
|
102
98
|
async function blobOrStreamToString(response) {
|
package/drivers/indexedDb.cjs
CHANGED
|
@@ -3,11 +3,11 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
|
|
6
|
+
|
|
7
7
|
var _dexie = _interopRequireDefault(require("dexie"));
|
|
8
8
|
var _lodash = _interopRequireDefault(require("lodash"));
|
|
9
9
|
var _memory = require("./memory.cjs");
|
|
10
|
-
function _interopRequireDefault(
|
|
10
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
11
11
|
const dbs = {};
|
|
12
12
|
const tableOperatorFns = {
|
|
13
13
|
eq: (where, value) => where.equals(value),
|
package/drivers/indexedDb.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { DexieOptions } from 'dexie';
|
|
2
|
+
import type { MinimalDriver, Schema } from 'rads-db';
|
|
2
3
|
declare const _default: (options?: IndexedDbDriverOptions) => (schema: Schema, entity: string) => MinimalDriver;
|
|
3
4
|
export default _default;
|
|
4
5
|
export interface IndexedDbDriverOptions {
|