electrodb 3.6.2 → 3.7.1

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/index.d.ts CHANGED
@@ -30,6 +30,7 @@ export type DocumentClient =
30
30
  scan: DocumentClientMethod;
31
31
  transactGet: DocumentClientMethod;
32
32
  transactWrite: DocumentClientMethod;
33
+ query: DocumentClientMethod;
33
34
  }
34
35
  | {
35
36
  send: (command: any) => Promise<any>;
@@ -2631,6 +2632,7 @@ export interface QueryOptions {
2631
2632
  data?: "raw" | "includeKeys" | "attributes";
2632
2633
  order?: "asc" | "desc";
2633
2634
  consistent?: boolean;
2635
+ client?: DocumentClient;
2634
2636
  }
2635
2637
 
2636
2638
  // subset of QueryOptions
@@ -2720,6 +2722,7 @@ interface GoBatchGetTerminalOptions<Attributes> {
2720
2722
  listeners?: Array<ElectroEventListener>;
2721
2723
  logger?: ElectroEventListener;
2722
2724
  consistent?: boolean;
2725
+ client?: DocumentClient;
2723
2726
  }
2724
2727
 
2725
2728
  export type ExecutionOptionCompare = "keys" | "attributes" | "v2";
@@ -2751,6 +2754,7 @@ type ServiceQueryGoTerminalOptions<
2751
2754
  logger?: ElectroEventListener;
2752
2755
  order?: "asc" | "desc";
2753
2756
  consistent?: boolean;
2757
+ client?: DocumentClient;
2754
2758
  } & QueryExecutionComparisonParts &
2755
2759
  (
2756
2760
  | {
@@ -2819,6 +2823,7 @@ type GoQueryTerminalOptions<
2819
2823
  order?: "asc" | "desc";
2820
2824
  hydrate?: boolean;
2821
2825
  consistent?: boolean;
2826
+ client?: DocumentClient;
2822
2827
  } & QueryExecutionComparisonParts &
2823
2828
  (
2824
2829
  | {
@@ -2846,6 +2851,7 @@ interface TransactWriteQueryOptions {
2846
2851
  listeners?: Array<ElectroEventListener>;
2847
2852
  logger?: ElectroEventListener;
2848
2853
  response?: "all_old";
2854
+ client?: DocumentClient;
2849
2855
  }
2850
2856
 
2851
2857
  interface TransactGetQueryOptions<Attributes> {
@@ -2858,6 +2864,7 @@ interface TransactGetQueryOptions<Attributes> {
2858
2864
  listeners?: Array<ElectroEventListener>;
2859
2865
  logger?: ElectroEventListener;
2860
2866
  consistent?: boolean;
2867
+ client?: DocumentClient;
2861
2868
  }
2862
2869
 
2863
2870
  export type ParamTerminalOptions<Attributes> = {
@@ -3957,7 +3964,7 @@ export type NestedAttributes =
3957
3964
 
3958
3965
  export interface IndexWithSortKey {
3959
3966
  readonly sk: {
3960
- readonly field: string;
3967
+ readonly field?: string;
3961
3968
  readonly composite: ReadonlyArray<string>;
3962
3969
  readonly template?: string;
3963
3970
  };
@@ -3988,19 +3995,19 @@ export interface Schema<A extends string, F extends string, C extends string, P
3988
3995
  readonly projection?: "all" | "keys_only" | ReadonlyArray<P>;
3989
3996
  readonly index?: string;
3990
3997
  readonly scope?: string;
3991
- readonly type?: "clustered" | "isolated";
3998
+ readonly type?: "clustered" | "isolated" | "composite";
3992
3999
  readonly collection?: AccessPatternCollection<C>;
3993
4000
  readonly condition?: (composite: Record<string, unknown>) => boolean;
3994
4001
  readonly pk: {
3995
4002
  readonly casing?: KeyCasingOption;
3996
- readonly field: string;
4003
+ readonly field?: string;
3997
4004
  readonly composite: ReadonlyArray<F>;
3998
4005
  readonly template?: string;
3999
4006
  readonly cast?: KeyCastOption;
4000
4007
  };
4001
4008
  readonly sk?: {
4002
4009
  readonly casing?: KeyCasingOption;
4003
- readonly field: string;
4010
+ readonly field?: string;
4004
4011
  readonly composite: ReadonlyArray<F>;
4005
4012
  readonly template?: string;
4006
4013
  readonly cast?: KeyCastOption;
@@ -4084,7 +4091,7 @@ type ClusteredIndexNameMap<
4084
4091
  C extends string,
4085
4092
  S extends Schema<A, F, C>,
4086
4093
  > = {
4087
- [I in keyof S["indexes"] as S["indexes"][I] extends { type: "clustered" }
4094
+ [I in keyof S["indexes"] as S["indexes"][I] extends { type: "clustered" | "composite" }
4088
4095
  ? I
4089
4096
  : never]: S["indexes"][I]["collection"] extends AccessPatternCollection<
4090
4097
  infer Name
@@ -4101,7 +4108,7 @@ type IsolatedIndexNameMap<
4101
4108
  C extends string,
4102
4109
  S extends Schema<A, F, C>,
4103
4110
  > = {
4104
- [I in keyof S["indexes"] as S["indexes"][I] extends { type: "clustered" }
4111
+ [I in keyof S["indexes"] as S["indexes"][I] extends { type: "clustered" | "composite" }
4105
4112
  ? never
4106
4113
  : I]: S["indexes"][I]["collection"] extends AccessPatternCollection<
4107
4114
  infer Name
@@ -5898,9 +5905,14 @@ export class TransactGetEntity<
5898
5905
  type TransactWriteFunctionOptions = {
5899
5906
  token?: string;
5900
5907
  logger?: ElectroEventListener;
5908
+ client?: DocumentClient;
5901
5909
  };
5902
5910
 
5903
- type TransactGetFunctionOptions = {};
5911
+ type TransactGetFunctionOptions = {
5912
+ token?: string;
5913
+ logger?: ElectroEventListener;
5914
+ client?: DocumentClient;
5915
+ };
5904
5916
 
5905
5917
  type TransactWriteExtractedType<
5906
5918
  T extends readonly any[],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "electrodb",
3
- "version": "3.6.2",
3
+ "version": "3.7.1",
4
4
  "description": "A library to more easily create and interact with multiple entities and heretical relationships in dynamodb",
5
5
  "main": "index.js",
6
6
  "scripts": {
package/src/clauses.js CHANGED
@@ -22,6 +22,72 @@ const v = require("./validations");
22
22
  const e = require("./errors");
23
23
  const u = require("./util");
24
24
 
25
+ function handleNonIsolatedCollection(
26
+ entity,
27
+ state,
28
+ collection = "",
29
+ facets /* istanbul ignore next */ = {},
30
+ ) {
31
+ if (state.getError() !== null) {
32
+ return state;
33
+ }
34
+ try {
35
+ const { pk, sk } = state.getCompositeAttributes();
36
+ return state
37
+ .setMethod(MethodTypes.query)
38
+ .setCollection(collection)
39
+ .setPK(entity._expectFacets(facets, pk))
40
+ .ifSK(() => {
41
+ const { composites, unused } = state.identifyCompositeAttributes(
42
+ facets,
43
+ sk,
44
+ pk,
45
+ );
46
+ state.setSK(composites);
47
+ state.beforeBuildParams(({ options, state }) => {
48
+ const accessPattern =
49
+ entity.model.translations.indexes.fromIndexToAccessPattern[
50
+ state.query.index
51
+ ];
52
+
53
+ if (
54
+ options.compare === ComparisonTypes.attributes ||
55
+ options.compare === ComparisonTypes.v2
56
+ ) {
57
+ if (
58
+ !entity.model.indexes[accessPattern].sk.isFieldRef &&
59
+ sk.length > 1
60
+ ) {
61
+ state.filterProperties(FilterOperationNames.eq, {
62
+ ...unused,
63
+ ...composites,
64
+ });
65
+ }
66
+ }
67
+ });
68
+ })
69
+ .whenOptions(({ options, state }) => {
70
+ if (!options.ignoreOwnership && !state.getParams()) {
71
+ state.query.options.expressions.names = {
72
+ ...state.query.options.expressions.names,
73
+ ...state.query.options.identifiers.names,
74
+ };
75
+ state.query.options.expressions.values = {
76
+ ...state.query.options.expressions.values,
77
+ ...state.query.options.identifiers.values,
78
+ };
79
+ state.query.options.expressions.expression =
80
+ state.query.options.expressions.expression.length > 1
81
+ ? `(${state.query.options.expressions.expression}) AND ${state.query.options.identifiers.expression}`
82
+ : `${state.query.options.identifiers.expression}`;
83
+ }
84
+ });
85
+ } catch (err) {
86
+ state.setError(err);
87
+ return state;
88
+ }
89
+ }
90
+
25
91
  const methodChildren = {
26
92
  upsert: [
27
93
  "upsertSet",
@@ -86,6 +152,7 @@ let clauses = {
86
152
  "scan",
87
153
  "collection",
88
154
  "clusteredCollection",
155
+ "compositeCollection",
89
156
  "create",
90
157
  "remove",
91
158
  "patch",
@@ -94,6 +161,23 @@ let clauses = {
94
161
  "batchGet",
95
162
  ],
96
163
  },
164
+ compositeCollection: {
165
+ name: "compositeCollection",
166
+ action(
167
+ entity,
168
+ state,
169
+ collection = "",
170
+ facets /* istanbul ignore next */ = {},
171
+ ) {
172
+ return handleNonIsolatedCollection(
173
+ entity,
174
+ state.setType(QueryTypes.composite_collection),
175
+ collection,
176
+ facets,
177
+ );
178
+ },
179
+ children: ["between", "gte", "gt", "lte", "lt", "begins", "params", "go"],
180
+ },
97
181
  clusteredCollection: {
98
182
  name: "clusteredCollection",
99
183
  action(
@@ -102,65 +186,12 @@ let clauses = {
102
186
  collection = "",
103
187
  facets /* istanbul ignore next */ = {},
104
188
  ) {
105
- if (state.getError() !== null) {
106
- return state;
107
- }
108
- try {
109
- const { pk, sk } = state.getCompositeAttributes();
110
- return state
111
- .setType(QueryTypes.clustered_collection)
112
- .setMethod(MethodTypes.query)
113
- .setCollection(collection)
114
- .setPK(entity._expectFacets(facets, pk))
115
- .ifSK(() => {
116
- const { composites, unused } = state.identifyCompositeAttributes(
117
- facets,
118
- sk,
119
- pk,
120
- );
121
- state.setSK(composites);
122
- state.beforeBuildParams(({ options, state }) => {
123
- const accessPattern =
124
- entity.model.translations.indexes.fromIndexToAccessPattern[
125
- state.query.index
126
- ];
127
-
128
- if (
129
- options.compare === ComparisonTypes.attributes ||
130
- options.compare === ComparisonTypes.v2
131
- ) {
132
- if (
133
- !entity.model.indexes[accessPattern].sk.isFieldRef &&
134
- sk.length > 1
135
- ) {
136
- state.filterProperties(FilterOperationNames.eq, {
137
- ...unused,
138
- ...composites,
139
- });
140
- }
141
- }
142
- });
143
- })
144
- .whenOptions(({ options, state }) => {
145
- if (!options.ignoreOwnership && !state.getParams()) {
146
- state.query.options.expressions.names = {
147
- ...state.query.options.expressions.names,
148
- ...state.query.options.identifiers.names,
149
- };
150
- state.query.options.expressions.values = {
151
- ...state.query.options.expressions.values,
152
- ...state.query.options.identifiers.values,
153
- };
154
- state.query.options.expressions.expression =
155
- state.query.options.expressions.expression.length > 1
156
- ? `(${state.query.options.expressions.expression}) AND ${state.query.options.identifiers.expression}`
157
- : `${state.query.options.identifiers.expression}`;
158
- }
159
- });
160
- } catch (err) {
161
- state.setError(err);
162
- return state;
163
- }
189
+ return handleNonIsolatedCollection(
190
+ entity,
191
+ state.setType(QueryTypes.clustered_collection),
192
+ collection,
193
+ facets,
194
+ );
164
195
  },
165
196
  children: ["between", "gte", "gt", "lte", "lt", "begins", "params", "go"],
166
197
  },
@@ -1327,10 +1358,10 @@ let clauses = {
1327
1358
  return Promise.reject(state.error);
1328
1359
  }
1329
1360
  try {
1330
- if (entity.client === undefined) {
1361
+ if (entity.client === undefined && options.client === undefined) {
1331
1362
  throw new e.ElectroError(
1332
1363
  e.ErrorCodes.NoClientDefined,
1333
- "No client defined on model",
1364
+ "No client defined on model or provided in query options",
1334
1365
  );
1335
1366
  }
1336
1367
  options.terminalOperation = TerminalOperation.go;