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.
Files changed (49) hide show
  1. package/README.md +19 -0
  2. package/dist/index.cjs +37 -13
  3. package/dist/index.mjs +37 -13
  4. package/drivers/azureCosmos.cjs +35 -7
  5. package/drivers/azureCosmos.d.ts +1 -0
  6. package/drivers/azureCosmos.mjs +46 -33
  7. package/drivers/azureStorageBlob.cjs +2 -2
  8. package/drivers/azureStorageBlob.d.ts +1 -0
  9. package/drivers/azureStorageBlob.mjs +4 -8
  10. package/drivers/indexedDb.cjs +2 -2
  11. package/drivers/indexedDb.d.ts +1 -0
  12. package/drivers/indexedDb.mjs +6 -12
  13. package/drivers/memory.cjs +18 -11
  14. package/drivers/memory.d.ts +1 -0
  15. package/drivers/memory.mjs +46 -73
  16. package/drivers/restApi.cjs +1 -1
  17. package/drivers/restApi.d.ts +2 -1
  18. package/drivers/restApi.mjs +2 -4
  19. package/features/cache.cjs +2 -2
  20. package/features/cache.mjs +15 -30
  21. package/features/eventSourcing.cjs +2 -2
  22. package/features/eventSourcing.d.ts +1 -0
  23. package/features/eventSourcing.mjs +8 -16
  24. package/features/softDelete.cjs +1 -1
  25. package/features/softDelete.mjs +2 -4
  26. package/fileUploadDrivers/azureStorageBlob.cjs +1 -1
  27. package/fileUploadDrivers/cloudinary.cjs +1 -1
  28. package/fileUploadDrivers/memory.cjs +1 -1
  29. package/fileUploadDrivers/restApi.cjs +1 -1
  30. package/fileUploadDrivers/restApi.d.ts +1 -0
  31. package/fileUploadDrivers/restApi.mjs +1 -2
  32. package/fileUploadDrivers/supabaseStorage.cjs +1 -1
  33. package/fileUploadDrivers/supabaseStorage.mjs +3 -6
  34. package/integrations/node.cjs +2 -2
  35. package/integrations/node.mjs +12 -22
  36. package/integrations/nuxtModule.cjs +2 -3
  37. package/integrations/restEndpoints.cjs +1 -1
  38. package/integrations/restEndpoints.mjs +8 -16
  39. package/integrations/restEndpointsDev/restEndpointsDevLint.cjs +2 -3
  40. package/integrations/restEndpointsDev/restEndpointsDevLint.d.ts +1 -1
  41. package/integrations/restEndpointsDev/restEndpointsDevLint.mjs +5 -10
  42. package/integrations/restEndpointsDev.cjs +3 -4
  43. package/integrations/restEndpointsDev.d.ts +1 -1
  44. package/integrations/restEndpointsDev.mjs +9 -18
  45. package/integrations/restEndpointsDev2.cjs +3 -4
  46. package/integrations/restEndpointsDev2.d.ts +0 -1
  47. package/integrations/restEndpointsDev2.mjs +3 -6
  48. package/integrations/vite.mjs +3 -6
  49. 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
- return { nodes: ___default.cloneDeep([getItemById(where.id)].filter((x) => x)), cursor: null };
209
- if (whereKeys[0] === "id_in")
210
- return { nodes: ___default.cloneDeep(getItemByIds(where.id_in).filter((x) => x)), cursor: null };
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
- return { nodes: _.cloneDeep([getItemById(where.id)].filter((x) => x)), cursor: null };
202
- if (whereKeys[0] === "id_in")
203
- return { nodes: _.cloneDeep(getItemByIds(where.id_in).filter((x) => x)), cursor: null };
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) {
@@ -3,10 +3,10 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- module.exports = void 0;
6
+
7
7
  var _cosmos = require("@azure/cosmos");
8
8
  var _lodash = _interopRequireDefault(require("lodash"));
9
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
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
- const query = `select * from r where ${whereClauses.join(" AND ")} ${orderByClause}`;
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
  }
@@ -1,4 +1,5 @@
1
1
  import type { CosmosClientOptions } from '@azure/cosmos';
2
+ import type { Schema } from 'rads-db';
2
3
  interface AzureCosmosDriverOptions {
3
4
  /** HTTPS endpoint of your cosmosdb instance. For example, https://mydb.documents.azure.com:443/ */
4
5
  endpoint: string;
@@ -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
- const query = `select * from r where ${whereClauses.join(" AND ")} ${orderByClause}`;
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
- return "";
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
- module.exports = void 0;
6
+
7
7
  var _storageBlob = require("@azure/storage-blob");
8
8
  var _lodash = _interopRequireDefault(require("lodash"));
9
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
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) => {
@@ -1,4 +1,5 @@
1
1
  import type { StoragePipelineOptions } from '@azure/storage-blob';
2
+ import type { Schema } from 'rads-db';
2
3
  interface AzureStorageBlobDriverOptions {
3
4
  connectionString: string;
4
5
  defaultContainer?: string;
@@ -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) {
@@ -3,11 +3,11 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- module.exports = void 0;
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(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
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),
@@ -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 {