rads-db 3.1.9 → 3.1.12

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 (52) hide show
  1. package/README.md +19 -0
  2. package/dist/config.d.ts +1 -1
  3. package/dist/index.cjs +56 -22
  4. package/dist/index.d.ts +2 -2
  5. package/dist/index.mjs +56 -22
  6. package/dist/{types-9c3659f0.d.ts → types-9cb9d6e7.d.ts} +9 -0
  7. package/drivers/azureCosmos.cjs +57 -14
  8. package/drivers/azureCosmos.d.ts +1 -0
  9. package/drivers/azureCosmos.mjs +68 -40
  10. package/drivers/azureStorageBlob.cjs +2 -2
  11. package/drivers/azureStorageBlob.d.ts +1 -0
  12. package/drivers/azureStorageBlob.mjs +4 -8
  13. package/drivers/indexedDb.cjs +2 -2
  14. package/drivers/indexedDb.d.ts +1 -0
  15. package/drivers/indexedDb.mjs +6 -12
  16. package/drivers/memory.cjs +38 -21
  17. package/drivers/memory.d.ts +1 -0
  18. package/drivers/memory.mjs +61 -78
  19. package/drivers/restApi.cjs +1 -1
  20. package/drivers/restApi.d.ts +2 -1
  21. package/drivers/restApi.mjs +2 -4
  22. package/features/cache.cjs +2 -2
  23. package/features/cache.mjs +15 -30
  24. package/features/eventSourcing.cjs +2 -2
  25. package/features/eventSourcing.d.ts +1 -0
  26. package/features/eventSourcing.mjs +8 -16
  27. package/features/softDelete.cjs +1 -1
  28. package/features/softDelete.mjs +2 -4
  29. package/fileUploadDrivers/azureStorageBlob.cjs +1 -1
  30. package/fileUploadDrivers/cloudinary.cjs +1 -1
  31. package/fileUploadDrivers/memory.cjs +1 -1
  32. package/fileUploadDrivers/restApi.cjs +1 -1
  33. package/fileUploadDrivers/restApi.d.ts +1 -0
  34. package/fileUploadDrivers/restApi.mjs +1 -2
  35. package/fileUploadDrivers/supabaseStorage.cjs +1 -1
  36. package/fileUploadDrivers/supabaseStorage.mjs +3 -6
  37. package/integrations/node.cjs +2 -2
  38. package/integrations/node.mjs +12 -22
  39. package/integrations/nuxtModule.cjs +2 -3
  40. package/integrations/restEndpoints.cjs +1 -1
  41. package/integrations/restEndpoints.mjs +8 -16
  42. package/integrations/restEndpointsDev/restEndpointsDevLint.cjs +2 -3
  43. package/integrations/restEndpointsDev/restEndpointsDevLint.d.ts +1 -1
  44. package/integrations/restEndpointsDev/restEndpointsDevLint.mjs +5 -10
  45. package/integrations/restEndpointsDev.cjs +3 -4
  46. package/integrations/restEndpointsDev.d.ts +1 -1
  47. package/integrations/restEndpointsDev.mjs +9 -18
  48. package/integrations/restEndpointsDev2.cjs +3 -4
  49. package/integrations/restEndpointsDev2.d.ts +0 -1
  50. package/integrations/restEndpointsDev2.mjs +3 -6
  51. package/integrations/vite.mjs +3 -6
  52. 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/config.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { g as RadsConfig, T as TypeDefinition } from './types-9c3659f0.js';
1
+ import { g as RadsConfig, T as TypeDefinition } from './types-9cb9d6e7.js';
2
2
  import '_rads-db';
3
3
 
4
4
  declare function defineRadsConfig(config: RadsConfig): RadsConfig;
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
  }
@@ -261,14 +268,14 @@ function queryArray(array, args) {
261
268
  if (!array)
262
269
  return array;
263
270
  let result = array;
264
- const { where, orderByProperty, orderByDirection, maxItemCount, cursor } = prepareArgs(args);
271
+ const { where, orderByProperties, orderByDirections, maxItemCount, cursor } = prepareArgs(args);
265
272
  const startIndex = Number(cursor) || 0;
266
273
  const endIndex = startIndex + maxItemCount;
267
274
  const f = getFilter(where);
268
275
  if (f)
269
276
  result = result.filter(f);
270
- if (orderByProperty)
271
- result = ___default.orderBy(result, [orderByProperty], [orderByDirection]);
277
+ if (orderByProperties)
278
+ result = ___default.orderBy(result, orderByProperties, orderByDirections);
272
279
  if (maxItemCount)
273
280
  result = result.slice(startIndex, endIndex);
274
281
  const newCursor = endIndex >= array.length ? null : endIndex;
@@ -355,15 +362,25 @@ function getFilterInner(operator, whereVal, name, namePrefix) {
355
362
  function prepareArgs(args) {
356
363
  args = args || {};
357
364
  const where = { ...args.where };
358
- let orderBy = args.orderBy || "";
359
- if (Array.isArray(orderBy))
360
- orderBy = orderBy[0] || "";
361
- const orderByParts = orderBy.split("_");
362
- const orderByProperty = orderByParts.slice(0, -1).join(".");
363
- const orderByDirection = orderByParts.slice(-1)[0];
365
+ const orderByProperties = [];
366
+ const orderByDirections = [];
367
+ if (args.orderBy) {
368
+ let orderBy = args.orderBy || "";
369
+ if (Array.isArray(orderBy))
370
+ orderBy = orderBy[0] || "";
371
+ const orderByParts = orderBy.split("_");
372
+ orderByProperties.push(orderByParts.slice(0, -1).join("."));
373
+ orderByDirections.push(orderByParts.slice(-1)[0]);
374
+ } else if (args.orderByArray) {
375
+ for (const order of args.orderByArray) {
376
+ const [property, direction] = order.split("_");
377
+ orderByProperties.push(property);
378
+ orderByDirections.push(direction);
379
+ }
380
+ }
364
381
  let maxItemCount = args.maxItemCount;
365
382
  maxItemCount = maxItemCount || 100;
366
- return { where, orderByProperty, orderByDirection, maxItemCount, cursor: args.cursor };
383
+ return { where, orderByProperties, orderByDirections, maxItemCount, cursor: args.cursor, pick: args.include };
367
384
  }
368
385
 
369
386
  const computedPresets = {
@@ -690,7 +707,7 @@ async function handleInclude(computedContext, include, result, ctx) {
690
707
  return;
691
708
  const { schema, typeName } = computedContext;
692
709
  const fields = schema[typeName].fields || {};
693
- const fieldsToInclude = ___default.keys(include).filter((key) => include[key]);
710
+ const fieldsToInclude = ___default.keys(include).filter((key) => include[key] && key !== "_pick");
694
711
  const nestedFieldsToInclude = fieldsToInclude.filter(
695
712
  (key) => !fields[key].isRelation && !fields[key].isInverseRelation && schema[fields[key].type]?.fields
696
713
  );
@@ -795,7 +812,7 @@ function getRadsDbMethods(key, computedContext, driverInstance) {
795
812
  const { precomputedFields } = entitySchema;
796
813
  async function getMany(args, ctx) {
797
814
  args = { ...args, where: { ...args?.where } };
798
- ctx = { ...options.context, ...ctx, method: "getMany" };
815
+ ctx = { ...options.context, ...ctx, method: "getMany", _isRecursiveRoot: !ctx?._isRecursiveRoot };
799
816
  let result2 = await beforeGet(args, ctx, computedContext);
800
817
  if (!result2)
801
818
  result2 = await driverInstance.getMany(args, ctx);
@@ -803,6 +820,8 @@ function getRadsDbMethods(key, computedContext, driverInstance) {
803
820
  await radsDbRelations.handleInclude(computedContext, args.include, result2.nodes, ctx);
804
821
  await handleComputed(computedContext, result2.nodes, ctx);
805
822
  await afterGet(result2.nodes, args, ctx, computedContext);
823
+ if (ctx._isRecursiveRoot && args.include?._pick)
824
+ result2.nodes = await pickPropsFromObjectAsync(result2.nodes, args.include);
806
825
  return result2;
807
826
  }
808
827
  async function putMany(docs, ctx) {
@@ -946,7 +965,7 @@ function getRadsDbMethods(key, computedContext, driverInstance) {
946
965
  },
947
966
  get: async (args, ctx) => {
948
967
  args = { ...args, where: { ...args?.where } };
949
- ctx = { ...options.context, ...ctx, method: "get" };
968
+ ctx = { ...options.context, ...ctx, method: "get", _isRecursiveRoot: !ctx?._isRecursiveRoot };
950
969
  let result2 = await beforeGet(args, ctx, computedContext);
951
970
  if (!result2)
952
971
  result2 = await driverInstance.get(args, ctx);
@@ -956,11 +975,13 @@ function getRadsDbMethods(key, computedContext, driverInstance) {
956
975
  if (result2)
957
976
  await handleComputed(computedContext, resultArray, ctx);
958
977
  await afterGet(resultArray, args, ctx, computedContext);
978
+ if (ctx._isRecursiveRoot && args.include?._pick)
979
+ result2 = await pickPropsFromObjectAsync(result2, args.include);
959
980
  return result2;
960
981
  },
961
982
  getAll: async (args, ctx) => {
962
983
  args = { ...args, where: { ...args?.where } };
963
- ctx = { ...options.context, ...ctx, method: "getAll" };
984
+ ctx = { ...options.context, ...ctx, method: "getAll", _isRecursiveRoot: !ctx?._isRecursiveRoot };
964
985
  let result2 = await beforeGet(args, ctx, computedContext);
965
986
  if (!result2)
966
987
  result2 = await driverInstance.getAll(args, ctx);
@@ -968,6 +989,9 @@ function getRadsDbMethods(key, computedContext, driverInstance) {
968
989
  await radsDbRelations.handleInclude(computedContext, args.include, result2, ctx);
969
990
  await handleComputed(computedContext, result2, ctx);
970
991
  await afterGet(result2, args, ctx, computedContext);
992
+ if (ctx._isRecursiveRoot && args.include?._pick) {
993
+ result2 = await pickPropsFromObjectAsync(result2, args.include);
994
+ }
971
995
  return result2;
972
996
  },
973
997
  verifyAll: async (args, ctx) => {
@@ -1043,6 +1067,18 @@ async function afterPut(items, ctx, computedContext) {
1043
1067
  await f.afterPut?.(items, ctx, computedContext);
1044
1068
  }
1045
1069
  }
1070
+ async function pickPropsFromObjectAsync(obj, args) {
1071
+ if (Array.isArray(obj)) {
1072
+ return Promise.all(obj.map((o) => pickPropsFromObjectAsync(o, args)));
1073
+ }
1074
+ const result = args._pick ? ___default.pick(obj, args._pick) : {};
1075
+ for (const key of Object.keys(args)) {
1076
+ if (key !== "_pick" && typeof args[key] === "object" && obj[key]) {
1077
+ result[key] = await pickPropsFromObjectAsync(obj[key], args[key]);
1078
+ }
1079
+ }
1080
+ return result;
1081
+ }
1046
1082
 
1047
1083
  function generateMethods(schema, validators, options) {
1048
1084
  const drivers = {};
@@ -1233,16 +1269,14 @@ const restApi = (options) => (schema, entity) => {
1233
1269
  if (!response.ok) {
1234
1270
  const msg = responseJson?.message || responseJson?.statusMessage || response.statusText || "Server error.";
1235
1271
  const err = new Error(msg);
1236
- if (responseJson?.code)
1237
- err.code = responseJson?.code;
1272
+ if (responseJson?.code) err.code = responseJson?.code;
1238
1273
  err.fetchResponseJson = responseJson;
1239
1274
  throw err;
1240
1275
  }
1241
1276
  return responseJson;
1242
1277
  }
1243
1278
  const { handlePlural } = schema[entity] || {};
1244
- if (!handlePlural)
1245
- throw new Error(`Entity ${entity} was not found in schema`);
1279
+ if (!handlePlural) throw new Error(`Entity ${entity} was not found in schema`);
1246
1280
  const instance = {
1247
1281
  driverName: "restApi",
1248
1282
  async getMany(args, ctx) {
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { E as EntityDecoratorArgs, U as UiDecoratorArgs, a as UiFieldDecoratorArgs, V as ValidateEntityDecoratorArgs, b as ValidateFieldDecoratorArgs, F as FieldDecoratorArgs, C as ComputedDecoratorArgs, S as Schema, D as DriverConstructor, c as Driver, d as ComputedContext, R as RadsRequestContext, e as CreateRadsDbArgs, f as CreateRadsDbClientArgs } from './types-9c3659f0.js';
2
- export { N as Change, x as ComputedContextGlobal, k as CreateRadsArgsDrivers, m as CreateRadsDbArgsNormalized, aj as DeepKeys, ae as DeepPartial, ac as DeepPartialWithNulls, ad as DeepPartialWithNullsItem, ak as EntityMethods, w as EnumDefinition, v as FieldDefinition, I as FileSystemNode, u as FileUploadArgs, q as FileUploadDriver, p as FileUploadResult, B as GenerateClientNormalizedOptions, A as GenerateClientOptions, a8 as Get, _ as GetAggArgs, $ as GetAggArgsAgg, a2 as GetAggArgsAny, a5 as GetAggResponse, Z as GetArgs, a1 as GetArgsAny, a4 as GetArgsInclude, O as GetManyArgs, a0 as GetManyArgsAny, a6 as GetManyResponse, a7 as GetResponse, a9 as GetResponseInclude, aa as GetResponseIncludeSelect, ab as GetResponseNoInclude, s as GetRestRoutesArgs, G as GetRestRoutesOptions, t as GetRestRoutesResponse, ag as InverseRelation, M as MinimalDriver, ai as Put, ah as PutArgs, P as PutEffect, g as RadsConfig, h as RadsConfigDataSource, r as RadsDbInstance, L as RadsFeature, y as RadsHookDoc, K as RadsUiSlotDefinition, J as RadsUiSlotName, H as RadsVitePluginOptions, af as Relation, i as RequiredFields, l as RestDriverOptions, z as RestFileUploadDriverOptions, n as SchemaLoadResult, o as SchemaValidators, T as TypeDefinition, j as ValidateStringDecoratorArgs, Q as VerifyManyArgs, a3 as VerifyManyArgsAny, X as VerifyManyResponse, Y as Where, W as WhereJsonContains } from './types-9c3659f0.js';
1
+ import { E as EntityDecoratorArgs, U as UiDecoratorArgs, a as UiFieldDecoratorArgs, V as ValidateEntityDecoratorArgs, b as ValidateFieldDecoratorArgs, F as FieldDecoratorArgs, C as ComputedDecoratorArgs, S as Schema, D as DriverConstructor, c as Driver, d as ComputedContext, R as RadsRequestContext, e as CreateRadsDbArgs, f as CreateRadsDbClientArgs } from './types-9cb9d6e7.js';
2
+ export { N as Change, x as ComputedContextGlobal, k as CreateRadsArgsDrivers, m as CreateRadsDbArgsNormalized, aj as DeepKeys, ae as DeepPartial, ac as DeepPartialWithNulls, ad as DeepPartialWithNullsItem, ak as EntityMethods, w as EnumDefinition, v as FieldDefinition, I as FileSystemNode, u as FileUploadArgs, q as FileUploadDriver, p as FileUploadResult, B as GenerateClientNormalizedOptions, A as GenerateClientOptions, a8 as Get, _ as GetAggArgs, $ as GetAggArgsAgg, a2 as GetAggArgsAny, a5 as GetAggResponse, Z as GetArgs, a1 as GetArgsAny, a4 as GetArgsInclude, O as GetManyArgs, a0 as GetManyArgsAny, a6 as GetManyResponse, a7 as GetResponse, a9 as GetResponseInclude, aa as GetResponseIncludeSelect, ab as GetResponseNoInclude, s as GetRestRoutesArgs, G as GetRestRoutesOptions, t as GetRestRoutesResponse, ag as InverseRelation, M as MinimalDriver, ai as Put, ah as PutArgs, P as PutEffect, g as RadsConfig, h as RadsConfigDataSource, r as RadsDbInstance, L as RadsFeature, y as RadsHookDoc, K as RadsUiSlotDefinition, J as RadsUiSlotName, H as RadsVitePluginOptions, af as Relation, i as RequiredFields, l as RestDriverOptions, z as RestFileUploadDriverOptions, n as SchemaLoadResult, o as SchemaValidators, T as TypeDefinition, j as ValidateStringDecoratorArgs, Q as VerifyManyArgs, a3 as VerifyManyArgsAny, X as VerifyManyResponse, Y as Where, W as WhereJsonContains } from './types-9cb9d6e7.js';
3
3
  import { RadsDb } from '_rads-db';
4
4
  export { RadsDb } from '_rads-db';
5
5
 
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
  }
@@ -254,14 +261,14 @@ function queryArray(array, args) {
254
261
  if (!array)
255
262
  return array;
256
263
  let result = array;
257
- const { where, orderByProperty, orderByDirection, maxItemCount, cursor } = prepareArgs(args);
264
+ const { where, orderByProperties, orderByDirections, maxItemCount, cursor } = prepareArgs(args);
258
265
  const startIndex = Number(cursor) || 0;
259
266
  const endIndex = startIndex + maxItemCount;
260
267
  const f = getFilter(where);
261
268
  if (f)
262
269
  result = result.filter(f);
263
- if (orderByProperty)
264
- result = _.orderBy(result, [orderByProperty], [orderByDirection]);
270
+ if (orderByProperties)
271
+ result = _.orderBy(result, orderByProperties, orderByDirections);
265
272
  if (maxItemCount)
266
273
  result = result.slice(startIndex, endIndex);
267
274
  const newCursor = endIndex >= array.length ? null : endIndex;
@@ -348,15 +355,25 @@ function getFilterInner(operator, whereVal, name, namePrefix) {
348
355
  function prepareArgs(args) {
349
356
  args = args || {};
350
357
  const where = { ...args.where };
351
- let orderBy = args.orderBy || "";
352
- if (Array.isArray(orderBy))
353
- orderBy = orderBy[0] || "";
354
- const orderByParts = orderBy.split("_");
355
- const orderByProperty = orderByParts.slice(0, -1).join(".");
356
- const orderByDirection = orderByParts.slice(-1)[0];
358
+ const orderByProperties = [];
359
+ const orderByDirections = [];
360
+ if (args.orderBy) {
361
+ let orderBy = args.orderBy || "";
362
+ if (Array.isArray(orderBy))
363
+ orderBy = orderBy[0] || "";
364
+ const orderByParts = orderBy.split("_");
365
+ orderByProperties.push(orderByParts.slice(0, -1).join("."));
366
+ orderByDirections.push(orderByParts.slice(-1)[0]);
367
+ } else if (args.orderByArray) {
368
+ for (const order of args.orderByArray) {
369
+ const [property, direction] = order.split("_");
370
+ orderByProperties.push(property);
371
+ orderByDirections.push(direction);
372
+ }
373
+ }
357
374
  let maxItemCount = args.maxItemCount;
358
375
  maxItemCount = maxItemCount || 100;
359
- return { where, orderByProperty, orderByDirection, maxItemCount, cursor: args.cursor };
376
+ return { where, orderByProperties, orderByDirections, maxItemCount, cursor: args.cursor, pick: args.include };
360
377
  }
361
378
 
362
379
  const computedPresets = {
@@ -683,7 +700,7 @@ async function handleInclude(computedContext, include, result, ctx) {
683
700
  return;
684
701
  const { schema, typeName } = computedContext;
685
702
  const fields = schema[typeName].fields || {};
686
- const fieldsToInclude = _.keys(include).filter((key) => include[key]);
703
+ const fieldsToInclude = _.keys(include).filter((key) => include[key] && key !== "_pick");
687
704
  const nestedFieldsToInclude = fieldsToInclude.filter(
688
705
  (key) => !fields[key].isRelation && !fields[key].isInverseRelation && schema[fields[key].type]?.fields
689
706
  );
@@ -788,7 +805,7 @@ function getRadsDbMethods(key, computedContext, driverInstance) {
788
805
  const { precomputedFields } = entitySchema;
789
806
  async function getMany(args, ctx) {
790
807
  args = { ...args, where: { ...args?.where } };
791
- ctx = { ...options.context, ...ctx, method: "getMany" };
808
+ ctx = { ...options.context, ...ctx, method: "getMany", _isRecursiveRoot: !ctx?._isRecursiveRoot };
792
809
  let result2 = await beforeGet(args, ctx, computedContext);
793
810
  if (!result2)
794
811
  result2 = await driverInstance.getMany(args, ctx);
@@ -796,6 +813,8 @@ function getRadsDbMethods(key, computedContext, driverInstance) {
796
813
  await radsDbRelations.handleInclude(computedContext, args.include, result2.nodes, ctx);
797
814
  await handleComputed(computedContext, result2.nodes, ctx);
798
815
  await afterGet(result2.nodes, args, ctx, computedContext);
816
+ if (ctx._isRecursiveRoot && args.include?._pick)
817
+ result2.nodes = await pickPropsFromObjectAsync(result2.nodes, args.include);
799
818
  return result2;
800
819
  }
801
820
  async function putMany(docs, ctx) {
@@ -939,7 +958,7 @@ function getRadsDbMethods(key, computedContext, driverInstance) {
939
958
  },
940
959
  get: async (args, ctx) => {
941
960
  args = { ...args, where: { ...args?.where } };
942
- ctx = { ...options.context, ...ctx, method: "get" };
961
+ ctx = { ...options.context, ...ctx, method: "get", _isRecursiveRoot: !ctx?._isRecursiveRoot };
943
962
  let result2 = await beforeGet(args, ctx, computedContext);
944
963
  if (!result2)
945
964
  result2 = await driverInstance.get(args, ctx);
@@ -949,11 +968,13 @@ function getRadsDbMethods(key, computedContext, driverInstance) {
949
968
  if (result2)
950
969
  await handleComputed(computedContext, resultArray, ctx);
951
970
  await afterGet(resultArray, args, ctx, computedContext);
971
+ if (ctx._isRecursiveRoot && args.include?._pick)
972
+ result2 = await pickPropsFromObjectAsync(result2, args.include);
952
973
  return result2;
953
974
  },
954
975
  getAll: async (args, ctx) => {
955
976
  args = { ...args, where: { ...args?.where } };
956
- ctx = { ...options.context, ...ctx, method: "getAll" };
977
+ ctx = { ...options.context, ...ctx, method: "getAll", _isRecursiveRoot: !ctx?._isRecursiveRoot };
957
978
  let result2 = await beforeGet(args, ctx, computedContext);
958
979
  if (!result2)
959
980
  result2 = await driverInstance.getAll(args, ctx);
@@ -961,6 +982,9 @@ function getRadsDbMethods(key, computedContext, driverInstance) {
961
982
  await radsDbRelations.handleInclude(computedContext, args.include, result2, ctx);
962
983
  await handleComputed(computedContext, result2, ctx);
963
984
  await afterGet(result2, args, ctx, computedContext);
985
+ if (ctx._isRecursiveRoot && args.include?._pick) {
986
+ result2 = await pickPropsFromObjectAsync(result2, args.include);
987
+ }
964
988
  return result2;
965
989
  },
966
990
  verifyAll: async (args, ctx) => {
@@ -1036,6 +1060,18 @@ async function afterPut(items, ctx, computedContext) {
1036
1060
  await f.afterPut?.(items, ctx, computedContext);
1037
1061
  }
1038
1062
  }
1063
+ async function pickPropsFromObjectAsync(obj, args) {
1064
+ if (Array.isArray(obj)) {
1065
+ return Promise.all(obj.map((o) => pickPropsFromObjectAsync(o, args)));
1066
+ }
1067
+ const result = args._pick ? _.pick(obj, args._pick) : {};
1068
+ for (const key of Object.keys(args)) {
1069
+ if (key !== "_pick" && typeof args[key] === "object" && obj[key]) {
1070
+ result[key] = await pickPropsFromObjectAsync(obj[key], args[key]);
1071
+ }
1072
+ }
1073
+ return result;
1074
+ }
1039
1075
 
1040
1076
  function generateMethods(schema, validators, options) {
1041
1077
  const drivers = {};
@@ -1226,16 +1262,14 @@ const restApi = (options) => (schema, entity) => {
1226
1262
  if (!response.ok) {
1227
1263
  const msg = responseJson?.message || responseJson?.statusMessage || response.statusText || "Server error.";
1228
1264
  const err = new Error(msg);
1229
- if (responseJson?.code)
1230
- err.code = responseJson?.code;
1265
+ if (responseJson?.code) err.code = responseJson?.code;
1231
1266
  err.fetchResponseJson = responseJson;
1232
1267
  throw err;
1233
1268
  }
1234
1269
  return responseJson;
1235
1270
  }
1236
1271
  const { handlePlural } = schema[entity] || {};
1237
- if (!handlePlural)
1238
- throw new Error(`Entity ${entity} was not found in schema`);
1272
+ if (!handlePlural) throw new Error(`Entity ${entity} was not found in schema`);
1239
1273
  const instance = {
1240
1274
  driverName: "restApi",
1241
1275
  async getMany(args, ctx) {
@@ -8,6 +8,7 @@ interface GetManyArgs<EN extends keyof EntityMeta> extends GetArgs<EN> {
8
8
  cursor?: string | null;
9
9
  maxItemCount?: number;
10
10
  orderBy?: string;
11
+ orderByArray?: OrderBy<EntityMeta[EN]>;
11
12
  }
12
13
  interface VerifyManyArgs<EN extends keyof EntityMeta> extends GetManyArgs<EN> {
13
14
  recompute?: string[];
@@ -122,6 +123,14 @@ interface EntityMethods<E, EN extends keyof EntityMeta> {
122
123
  verifyMany<A extends VerifyManyArgs<EN>>(args?: A, ctx?: RadsRequestContext): MaybePromise$1<VerifyManyResponse>;
123
124
  verifyAll<A extends VerifyManyArgs<EN>>(args?: A, ctx?: RadsRequestContext): MaybePromise$1<Pick<VerifyManyResponse, 'correctCount' | 'incorrectCount'>>;
124
125
  }
126
+ type Prev = [never, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, ...0[]];
127
+ type Primitive = string | number | boolean | symbol | null | undefined;
128
+ type OrderByDeepKeys<T, Prefix extends string = '', MaxDepth extends number = 5, Depth extends number = MaxDepth> = Depth extends 0 ? '' : T extends Primitive ? Prefix extends '' ? never : Prefix : T extends object ? {
129
+ [K in keyof T]-?: K extends string | number ? OrderByDeepKeys<T[K], `${Prefix}${K & string}`, MaxDepth, Prev[Depth]> : never;
130
+ }[keyof T] : never;
131
+ type TrimEnd<T extends string, S extends string> = T extends `${infer R}${S}` ? R : T;
132
+ type ValidOrderByKey<T> = TrimEnd<OrderByDeepKeys<T>, '.'>;
133
+ type OrderBy<T> = Array<`${ValidOrderByKey<T>}_${'asc' | 'desc'}`>;
125
134
 
126
135
  interface RadsConfig {
127
136
  dataSources: Record<string, RadsConfigDataSource>;
@@ -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
@@ -153,15 +154,12 @@ function getCosmosQuery(schema, entity, args) {
153
154
  schema,
154
155
  entity
155
156
  }, parameters, where)].filter(x => x);
156
- let orderByClause = "";
157
- if (args.orderBy) {
158
- const orderByParts = args.orderBy.split("_");
159
- const orderPropFromOrderBy = orderByParts.slice(0, -1).join(".");
160
- const orderDirection = orderByParts.at(-1);
161
- const orderProp = orderPropFromOrderBy === "value" ? `r["value"]` : `r.${orderPropFromOrderBy}`;
162
- orderByClause = `order by ${orderProp} ${orderDirection}`;
157
+ const orderByClause = getCosmosOrderBy(args);
158
+ let colums = "*";
159
+ if (args.include?._pick) {
160
+ colums = getCosmosSelectValue(args.include);
163
161
  }
164
- const query = `select * from r where ${whereClauses.join(" AND ")} ${orderByClause}`;
162
+ const query = `select ${colums} from r where ${whereClauses.join(" AND ")} ${orderByClause}`;
165
163
  return {
166
164
  query,
167
165
  parameters
@@ -461,6 +459,28 @@ const operatorHandlers = {
461
459
  return `${namePrefix}${name} <= @${pn}`;
462
460
  }
463
461
  };
462
+ function getCosmosOrderBy(args) {
463
+ let orderByClause = "";
464
+ if (args.orderByArray) {
465
+ orderByClause = `order by `;
466
+ const orderByColumns = [];
467
+ for (const order of args.orderByArray) {
468
+ orderByColumns.push(parseOrderBy(order));
469
+ }
470
+ orderByClause = orderByClause + orderByColumns.join(",");
471
+ } else if (args.orderBy) {
472
+ orderByClause = `order by ${parseOrderBy(args.orderBy)}`;
473
+ }
474
+ return orderByClause;
475
+ }
476
+ function parseOrderBy(order) {
477
+ const orderByParts = order.split("_");
478
+ const orderPropFromOrderBy = orderByParts.slice(0, -1).join(".");
479
+ const orderDirection = orderByParts.at(-1);
480
+ const orderProp = orderPropFromOrderBy === "value" ? `r["value"]` : `r.${orderPropFromOrderBy}`;
481
+ const ordr = `${orderProp} ${orderDirection}`;
482
+ return ordr;
483
+ }
464
484
  function getCosmosQueryWhere(ctx, parameters, where, namePrefix = "r.", paramNamePrefix = "") {
465
485
  const whereClauses = [];
466
486
  for (const key in where) {
@@ -589,4 +609,27 @@ async function bulkSendWithRetry(client, chunkToSend) {
589
609
  });
590
610
  }
591
611
  return responses;
612
+ }
613
+ function buildSelectValue(includeArgs, path = "r") {
614
+ const parts = [];
615
+ if (Array.isArray(includeArgs._pick)) {
616
+ for (const key of includeArgs._pick) {
617
+ parts.push(`${key}: ${path}.${key}`);
618
+ }
619
+ }
620
+ for (const key of Object.keys(includeArgs)) {
621
+ if (key === "_pick") continue;
622
+ const nested = includeArgs[key];
623
+ if (typeof nested === "object" && nested !== null) {
624
+ const nestedSelect = buildSelectValue(nested, `${path}.${key}`);
625
+ parts.push(`${key}: { ${nestedSelect} }`);
626
+ }
627
+ }
628
+ return parts.join(", ");
629
+ }
630
+ function getCosmosSelectValue(includeArgs) {
631
+ const projection = buildSelectValue(includeArgs);
632
+ return `VALUE {
633
+ ${projection}
634
+ } `;
592
635
  }
@@ -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;