electrodb 2.4.1 → 2.5.0

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
@@ -1,6 +1,9 @@
1
-
1
+ import {ScanCommandInput, GetCommandInput, QueryCommandInput, DeleteCommandInput, BatchWriteCommandInput, UpdateCommandInput, UpdateCommand, PutCommandInput, BatchGetCommandInput, TransactWriteCommandInput, TransactGetCommandInput} from '@aws-sdk/lib-dynamodb';
2
2
  export type DocumentClientMethod = (parameters: any) => {promise: () => Promise<any>};
3
3
 
4
+ type TransactGetItem = Extract<Required<TransactGetCommandInput['TransactItems']>, Array<any>>[number];
5
+ type TransactWriteItem = Extract<Required<TransactWriteCommandInput['TransactItems']>, Array<any>>[number];
6
+
4
7
  export type DocumentClient = {
5
8
  get: DocumentClientMethod;
6
9
  put: DocumentClientMethod;
@@ -712,12 +715,89 @@ export interface RecordsActionOptions<A extends string,
712
715
  where: WhereClause<A,F,C,S,Item<A,F,C,S,S["attributes"]>,RecordsActionOptions<A,F,C,S,Items,IndexCompositeAttributes>>;
713
716
  }
714
717
 
718
+ export type TransactionItemCode = 'None' | 'ConditionalCheckFailed' | 'ItemCollectionSizeLimitExceeded' | 'TransactionConflict' | 'ProvisionedThroughputExceeded' | 'ThrottlingError' | 'ValidationError';
719
+
720
+ export type TransactionItem<T> = {
721
+ item: null | T;
722
+ rejected: boolean;
723
+ code: TransactionItemCode;
724
+ message?: string | undefined;
725
+ };
726
+
727
+ type CommittedTransactionResult<T, Params> =
728
+ & Params
729
+ & { [TransactionSymbol]: T };
730
+
715
731
  export interface SingleRecordOperationOptions<A extends string, F extends string, C extends string, S extends Schema<A,F,C>, ResponseType> {
716
732
  go: GoGetTerminal<A,F,C,S, ResponseType>;
717
733
  params: ParamTerminal<A,F,C,S,ResponseType>;
718
734
  where: WhereClause<A,F,C,S,Item<A,F,C,S,S["attributes"]>,SingleRecordOperationOptions<A,F,C,S,ResponseType>>;
719
735
  }
720
736
 
737
+ type GoGetTerminalTransaction<A extends string, F extends string, C extends string, S extends Schema<A,F,C>, ResponseItem, Params> = <Options extends TransactGetQueryOptions<keyof ResponseItem>>(options?: Options) =>
738
+ Options extends GoQueryTerminalOptions<infer Attr>
739
+ ? CommittedTransactionResult<{
740
+ [Name in keyof ResponseItem as Name extends Attr
741
+ ? Name
742
+ : never]: ResponseItem[Name]
743
+ }, Params>
744
+ : CommittedTransactionResult<ResponseItem, Params>
745
+
746
+ type GoSingleTerminalTransaction<A extends string, F extends string, C extends string, S extends Schema<A,F,C>, ResponseItem, Params> = <Options extends TransactWriteQueryOptions>(options?: Options) =>
747
+ CommittedTransactionResult<ResponseItem, Params>
748
+
749
+ export interface SingleRecordOperationOptionsTransaction<A extends string, F extends string, C extends string, S extends Schema<A,F,C>, ResponseType, Params> {
750
+ commit: GoSingleTerminalTransaction<A,F,C,S, ResponseType, Params>;
751
+ where: WhereClause<A,F,C,S,Item<A,F,C,S,S["attributes"]>,SingleRecordOperationOptionsTransaction<A,F,C,S,ResponseType, Params>>;
752
+ }
753
+
754
+ export interface GetOperationOptionsTransaction<A extends string, F extends string, C extends string, S extends Schema<A,F,C>, ResponseType, Params> {
755
+ commit: GoGetTerminalTransaction<A,F,C,S, ResponseType, Params>;
756
+ }
757
+
758
+ export type DeleteRecordOperationGoTransaction<ResponseType, Options = TransactWriteQueryOptions> = <T = ResponseType>(options?: Options) => CommittedTransactionResult<T, TransactWriteItem>;
759
+
760
+ export interface DeleteRecordOperationOptionsTransaction<A extends string, F extends string, C extends string, S extends Schema<A,F,C>, ResponseType> {
761
+ commit: DeleteRecordOperationGoTransaction<ResponseType, TransactWriteQueryOptions>;
762
+ where: WhereClause<A,F,C,S,Item<A,F,C,S,S["attributes"]>,DeleteRecordOperationOptionsTransaction<A,F,C,S,ResponseType>>;
763
+ }
764
+
765
+ export type PutRecordGoTransaction<ResponseType, Options = TransactWriteQueryOptions> = <T = ResponseType>(options?: Options) => CommittedTransactionResult<T, TransactWriteItem>;
766
+
767
+ export interface PutRecordOperationOptionsTransaction<A extends string, F extends string, C extends string, S extends Schema<A,F,C>, ResponseType> {
768
+ commit: PutRecordGoTransaction<ResponseType, TransactWriteQueryOptions>;
769
+ where: WhereClause<A, F, C, S, Item<A, F, C, S, S["attributes"]>, PutRecordOperationOptionsTransaction<A, F, C, S, ResponseType>>;
770
+ }
771
+
772
+ export interface UpsertRecordOperationOptionsTransaction<A extends string, F extends string, C extends string, S extends Schema<A,F,C>, ResponseType> {
773
+ commit: PutRecordGoTransaction<ResponseType, TransactWriteQueryOptions>;
774
+ where: WhereClause<A, F, C, S, Item<A, F, C, S, S["attributes"]>, UpsertRecordOperationOptionsTransaction<A, F, C, S, ResponseType>>;
775
+ }
776
+
777
+ export type UpdateRecordGoTransaction<ResponseType> = <T = ResponseType, Options extends TransactWriteQueryOptions = TransactWriteQueryOptions>(options?: Options) => CommittedTransactionResult<Partial<T>, TransactWriteItem>
778
+
779
+ export interface SetRecordActionOptionsTransaction<A extends string, F extends string, C extends string, S extends Schema<A,F,C>, SetAttr,IndexCompositeAttributes,TableItem> {
780
+ commit: UpdateRecordGoTransaction<TableItem>;
781
+ params: ParamRecord<UpdateQueryParams>;
782
+ set: SetRecordTransaction<A,F,C,S, SetItem<A,F,C,S>,IndexCompositeAttributes,TableItem>;
783
+ remove: RemoveRecordTransaction<A,F,C,S, Array<keyof SetItem<A,F,C,S>>,IndexCompositeAttributes,TableItem>;
784
+ add: SetRecordTransaction<A,F,C,S, AddItem<A,F,C,S>,IndexCompositeAttributes,TableItem>;
785
+ subtract: SetRecordTransaction<A,F,C,S, SubtractItem<A,F,C,S>,IndexCompositeAttributes,TableItem>;
786
+ append: SetRecordTransaction<A,F,C,S, AppendItem<A,F,C,S>,IndexCompositeAttributes,TableItem>;
787
+ delete: SetRecordTransaction<A,F,C,S, DeleteItem<A,F,C,S>,IndexCompositeAttributes,TableItem>;
788
+ data: DataUpdateMethodRecordTransaction<A,F,C,S, Item<A,F,C,S,S["attributes"]>,IndexCompositeAttributes,TableItem>;
789
+ where: WhereClause<A,F,C,S, Item<A,F,C,S,S["attributes"]>,SetRecordActionOptionsTransaction<A,F,C,S,SetAttr,IndexCompositeAttributes,TableItem>>;
790
+ }
791
+
792
+ export type RemoveRecordTransaction<A extends string, F extends string, C extends string, S extends Schema<A,F,C>, RemoveAttr, IndexCompositeAttributes, TableItem> = (properties: RemoveAttr) =>
793
+ SetRecordActionOptionsTransaction<A,F,C,S, RemoveAttr, IndexCompositeAttributes, TableItem>;
794
+
795
+ export type SetRecordTransaction<A extends string, F extends string, C extends string, S extends Schema<A,F,C>, SetAttr, IndexCompositeAttributes, TableItem> = (properties: SetAttr) =>
796
+ SetRecordActionOptionsTransaction<A,F,C,S, SetAttr, IndexCompositeAttributes, TableItem>;
797
+
798
+ export type DataUpdateMethodRecordTransaction<A extends string, F extends string, C extends string, S extends Schema<A,F,C>, SetAttr, IndexCompositeAttributes, TableItem> =
799
+ DataUpdateMethod<A,F,C,S, UpdateData<A,F,C,S>, SetRecordActionOptionsTransaction<A,F,C,S, SetAttr, IndexCompositeAttributes, TableItem>>
800
+
721
801
  export interface BatchGetRecordOperationOptions<A extends string, F extends string, C extends string, S extends Schema<A,F,C>, ResponseType> {
722
802
  go: GoBatchGetTerminal<A,F,C,S,ResponseType>
723
803
  params: ParamTerminal<A,F,C,S,ResponseType>;
@@ -915,6 +995,28 @@ interface GoQueryTerminalOptions<Attributes> {
915
995
  order?: 'asc' | 'desc';
916
996
  }
917
997
 
998
+ interface TransactWriteQueryOptions {
999
+ data?: 'raw' | 'includeKeys' | 'attributes';
1000
+ table?: string;
1001
+ params?: object;
1002
+ originalErr?: boolean;
1003
+ ignoreOwnership?: boolean;
1004
+ listeners?: Array<ElectroEventListener>;
1005
+ logger?: ElectroEventListener;
1006
+ response?: 'all_old';
1007
+ }
1008
+
1009
+ interface TransactGetQueryOptions<Attributes> {
1010
+ data?: 'raw' | 'includeKeys' | 'attributes';
1011
+ table?: string;
1012
+ params?: object;
1013
+ originalErr?: boolean;
1014
+ ignoreOwnership?: boolean;
1015
+ attributes?: ReadonlyArray<Attributes>;
1016
+ listeners?: Array<ElectroEventListener>;
1017
+ logger?: ElectroEventListener;
1018
+ }
1019
+
918
1020
  export interface ParamTerminalOptions<Attributes> {
919
1021
  table?: string;
920
1022
  limit?: number;
@@ -2151,6 +2253,7 @@ export declare const WhereSymbol: unique symbol;
2151
2253
  export declare const UpdateDataSymbol: unique symbol;
2152
2254
  export declare const CustomAttributeSymbol: unique symbol;
2153
2255
  export declare const OpaquePrimitiveSymbol: unique symbol;
2256
+ export declare const TransactionSymbol: unique symbol;
2154
2257
 
2155
2258
  export type WhereAttributeSymbol<T extends any> =
2156
2259
  { [WhereSymbol]: void }
@@ -2257,6 +2360,10 @@ export type EntityConfiguration = {
2257
2360
  client?: DocumentClient;
2258
2361
  listeners?: Array<ElectroEventListener>;
2259
2362
  logger?: ElectroEventListener;
2363
+ identifiers?: {
2364
+ entity?: string;
2365
+ version?: string;
2366
+ },
2260
2367
  };
2261
2368
 
2262
2369
  export class Entity<A extends string, F extends string, C extends string, S extends Schema<A,F,C>> {
@@ -2331,6 +2438,80 @@ export class Entity<A extends string, F extends string, C extends string, S exte
2331
2438
  client: any;
2332
2439
  }
2333
2440
 
2441
+
2442
+ export class TransactWriteEntity<A extends string, F extends string, C extends string, S extends Schema<A,F,C>> {
2443
+ readonly schema: S;
2444
+ constructor(schema: S);
2445
+
2446
+ check(key: AllTableIndexCompositeAttributes<A,F,C,S>): SingleRecordOperationOptionsTransaction<A,F,C,S, ResponseItem<A,F,C,S>, TransactWriteItem>;
2447
+ delete(key: AllTableIndexCompositeAttributes<A,F,C,S>): DeleteRecordOperationOptionsTransaction<A,F,C,S, ResponseItem<A,F,C,S>>;
2448
+ remove(key: AllTableIndexCompositeAttributes<A,F,C,S>): DeleteRecordOperationOptionsTransaction<A,F,C,S, ResponseItem<A,F,C,S>>
2449
+ put(record: PutItem<A,F,C,S>): PutRecordOperationOptionsTransaction<A,F,C,S, ResponseItem<A,F,C,S>>;
2450
+ create(record: PutItem<A,F,C,S>): PutRecordOperationOptionsTransaction<A,F,C,S, ResponseItem<A,F,C,S>>
2451
+ upsert(record: PutItem<A,F,C,S>): UpsertRecordOperationOptionsTransaction<A,F,C,S, ResponseItem<A,F,C,S>>;
2452
+ update(key: AllTableIndexCompositeAttributes<A,F,C,S>): {
2453
+ set: SetRecordTransaction<A,F,C,S, SetItem<A,F,C,S>, TableIndexCompositeAttributes<A,F,C,S>, ResponseItem<A,F,C,S>>;
2454
+ remove: RemoveRecordTransaction<A,F,C,S, RemoveItem<A,F,C,S>, TableIndexCompositeAttributes<A,F,C,S>, ResponseItem<A,F,C,S>>;
2455
+ add: SetRecordTransaction<A,F,C,S, AddItem<A,F,C,S>, TableIndexCompositeAttributes<A,F,C,S>, ResponseItem<A,F,C,S>>;
2456
+ subtract: SetRecordTransaction<A,F,C,S, SubtractItem<A,F,C,S>, TableIndexCompositeAttributes<A,F,C,S>, ResponseItem<A,F,C,S>>;
2457
+ append: SetRecordTransaction<A,F,C,S, AppendItem<A,F,C,S>, TableIndexCompositeAttributes<A,F,C,S>, ResponseItem<A,F,C,S>>;
2458
+ delete: SetRecordTransaction<A,F,C,S, DeleteItem<A,F,C,S>, TableIndexCompositeAttributes<A,F,C,S>, ResponseItem<A,F,C,S>>;
2459
+ data: DataUpdateMethodRecordTransaction<A,F,C,S, Item<A,F,C,S,S["attributes"]>, TableIndexCompositeAttributes<A,F,C,S>, ResponseItem<A,F,C,S>>;
2460
+ };
2461
+ patch(key: AllTableIndexCompositeAttributes<A,F,C,S>): {
2462
+ set: SetRecordTransaction<A,F,C,S, SetItem<A,F,C,S>, TableIndexCompositeAttributes<A,F,C,S>, ResponseItem<A,F,C,S>>;
2463
+ remove: RemoveRecordTransaction<A,F,C,S, RemoveItem<A,F,C,S>, TableIndexCompositeAttributes<A,F,C,S>, ResponseItem<A,F,C,S>>;
2464
+ add: SetRecordTransaction<A,F,C,S, AddItem<A,F,C,S>, TableIndexCompositeAttributes<A,F,C,S>, ResponseItem<A,F,C,S>>;
2465
+ subtract: SetRecordTransaction<A,F,C,S, SubtractItem<A,F,C,S>, TableIndexCompositeAttributes<A,F,C,S>, ResponseItem<A,F,C,S>>;
2466
+ append: SetRecordTransaction<A,F,C,S, AppendItem<A,F,C,S>, TableIndexCompositeAttributes<A,F,C,S>, ResponseItem<A,F,C,S>>;
2467
+ delete: SetRecordTransaction<A,F,C,S, DeleteItem<A,F,C,S>, TableIndexCompositeAttributes<A,F,C,S>, ResponseItem<A,F,C,S>>;
2468
+ data: DataUpdateMethodRecordTransaction<A,F,C,S, Item<A,F,C,S,S["attributes"]>, TableIndexCompositeAttributes<A,F,C,S>, ResponseItem<A,F,C,S>>;
2469
+ };
2470
+ }
2471
+
2472
+ export class TransactGetEntity<A extends string, F extends string, C extends string, S extends Schema<A,F,C>> {
2473
+ readonly schema: S;
2474
+ constructor(schema: S);
2475
+
2476
+ get(key: AllTableIndexCompositeAttributes<A,F,C,S>): GetOperationOptionsTransaction<A,F,C,S, ResponseItem<A,F,C,S>, TransactGetItem>;
2477
+ }
2478
+
2479
+ type TransactWriteFunctionOptions = {
2480
+ token?: string;
2481
+ };
2482
+
2483
+ type TransactGetFunctionOptions = {};
2484
+
2485
+ type TransactWriteExtractedType<T extends readonly any[], A extends readonly any[] = []> =
2486
+ T extends [infer F, ...infer R] ?
2487
+ F extends CommittedTransactionResult<infer V, TransactWriteItem>
2488
+ ? TransactWriteExtractedType<R, [...A, TransactionItem<V>]>
2489
+ : never
2490
+ : A;
2491
+
2492
+ type TransactGetExtractedType<T extends readonly any[], A extends readonly any[] = []> =
2493
+ T extends [infer F, ...infer R] ?
2494
+ F extends CommittedTransactionResult<infer V, TransactGetItem>
2495
+ ? TransactWriteExtractedType<R, [...A, TransactionItem<V>]>
2496
+ : never
2497
+ : A
2498
+
2499
+ type TransactWriteEntities<E extends {[name: string]: Entity<any, any, any, any>}> = {
2500
+ [EntityName in keyof E]: E[EntityName] extends Entity<infer A, infer F, infer C, infer S>
2501
+ ? TransactWriteEntity<A,F,C,S>
2502
+ : never;
2503
+ }
2504
+
2505
+ type TransactGetEntities<E extends {[name: string]: Entity<any, any, any, any>}> = {
2506
+ [EntityName in keyof E]: E[EntityName] extends Entity<infer A, infer F, infer C, infer S>
2507
+ ? TransactGetEntity<A,F,C,S>
2508
+ : never;
2509
+ }
2510
+
2511
+ type TransactWriteFunction<E extends {[name: string]: Entity<any, any, any, any>}, T, R extends ReadonlyArray<CommittedTransactionResult<T, TransactWriteItem>> > = (entities: TransactWriteEntities<E>) => [...R];
2512
+
2513
+ type TransactGetFunction<E extends {[name: string]: Entity<any, any, any, any>}, T, R extends ReadonlyArray<CommittedTransactionResult<T, TransactGetItem>> > = (entities: TransactGetEntities<E>) => [...R];
2514
+
2334
2515
  export type ServiceConfiguration = {
2335
2516
  table?: string;
2336
2517
  client?: DocumentClient;
@@ -2338,11 +2519,46 @@ export type ServiceConfiguration = {
2338
2519
  logger?: ElectroEventListener;
2339
2520
  };
2340
2521
 
2522
+ declare function createWriteTransaction<E extends {[name: string]: Entity<any, any, any, any>}, T, R extends ReadonlyArray<CommittedTransactionResult<T, TransactWriteItem>>>(entities: E, fn: TransactWriteFunction<E,T,R>): {
2523
+ go: (options?: TransactWriteFunctionOptions) => Promise<{
2524
+ canceled: boolean;
2525
+ data: TransactWriteExtractedType<R>
2526
+ }>;
2527
+ params: <O extends TransactWriteFunctionOptions = TransactWriteFunctionOptions>(options?: O) => TransactWriteCommandInput
2528
+ }
2529
+
2530
+ declare function createGetTransaction<E extends {[name: string]: Entity<any, any, any, any>},T, R extends ReadonlyArray<CommittedTransactionResult<T, TransactGetItem>>>(entities: E, fn: TransactGetFunction<E,T,R>): {
2531
+ go: (options?: TransactGetFunctionOptions) => Promise<{
2532
+ canceled: boolean;
2533
+ data: TransactGetExtractedType<R>
2534
+ }>;
2535
+ params: <O extends TransactGetFunctionOptions = TransactGetFunctionOptions>(options?: O) => TransactGetCommandInput
2536
+ };
2537
+
2341
2538
  export class Service<E extends {[name: string]: Entity<any, any, any, any>}> {
2342
2539
  entities: E;
2343
2540
  collections:
2344
2541
  ClusteredCollectionQueries<E, ClusteredCollectionAssociations<E>>
2345
2542
  & IsolatedCollectionQueries<E, IsolatedCollectionAssociations<E>>
2543
+
2544
+ transaction: {
2545
+ write: <T, R extends ReadonlyArray<CommittedTransactionResult<T, TransactWriteItem>>>(fn: TransactWriteFunction<E,T,R>) => {
2546
+ go: (options?: TransactWriteFunctionOptions) => Promise<{
2547
+ canceled: boolean;
2548
+ data: TransactWriteExtractedType<R>
2549
+ }>;
2550
+ params: <O extends TransactWriteFunctionOptions = TransactWriteFunctionOptions>(options?: O) => TransactWriteCommandInput
2551
+ };
2552
+
2553
+ get: <T, R extends ReadonlyArray<CommittedTransactionResult<T, TransactGetItem>>>(fn: TransactGetFunction<E,T,R>) => {
2554
+ go: (options?: TransactGetFunctionOptions) => Promise<{
2555
+ canceled: boolean;
2556
+ data: TransactGetExtractedType<R>
2557
+ }>;
2558
+ params: <O extends TransactGetFunctionOptions = TransactGetFunctionOptions>(options?: O) => TransactGetCommandInput
2559
+ };
2560
+ }
2561
+
2346
2562
  constructor(entities: E, config?: ServiceConfiguration);
2347
2563
 
2348
2564
  setTableName(tableName: string): void;
@@ -2374,4 +2590,4 @@ declare function CustomAttributeType<T>(
2374
2590
  ? OpaquePrimitiveTypeName<T>
2375
2591
  : CustomAttributeTypeName<T>;
2376
2592
 
2377
- declare function createSchema<A extends string, F extends string, C extends string, S extends Schema<A,F,C>>(schema: S): S
2593
+ declare function createSchema<A extends string, F extends string, C extends string, S extends Schema<A,F,C>>(schema: S): S
package/index.js CHANGED
@@ -1,5 +1,6 @@
1
1
  const { Entity } = require("./src/entity");
2
2
  const { Service } = require("./src/service");
3
+ const { createGetTransaction, createWriteTransaction } = require('./src/transaction');
3
4
  const { createCustomAttribute, CustomAttributeType, createSchema } = require('./src/schema');
4
5
  const { ElectroError, ElectroValidationError, ElectroUserValidationError, ElectroAttributeValidationError } = require('./src/errors');
5
6
 
@@ -11,4 +12,6 @@ module.exports = {
11
12
  CustomAttributeType,
12
13
  createCustomAttribute,
13
14
  ElectroValidationError,
15
+ createGetTransaction,
16
+ createWriteTransaction,
14
17
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "electrodb",
3
- "version": "2.4.1",
3
+ "version": "2.5.0",
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
@@ -1,4 +1,4 @@
1
- const { QueryTypes, MethodTypes, ItemOperations, ExpressionTypes, TableIndex, TerminalOperation, KeyTypes, IndexTypes } = require("./types");
1
+ const { QueryTypes, MethodTypes, ItemOperations, ExpressionTypes, TransactionCommitSymbol, TransactionOperations, TerminalOperation, KeyTypes, IndexTypes } = require("./types");
2
2
  const {AttributeOperationProxy, UpdateOperations, FilterOperationNames} = require("./operations");
3
3
  const {UpdateExpression} = require("./update");
4
4
  const {FilterExpression} = require("./where");
@@ -28,7 +28,7 @@ function batchAction(action, type, entity, state, payload) {
28
28
  let clauses = {
29
29
  index: {
30
30
  name: "index",
31
- children: ["get", "delete", "update", "query", "upsert", "put", "scan", "collection", "clusteredCollection", "create", "remove", "patch", "batchPut", "batchDelete", "batchGet"],
31
+ children: ["check", "get", "delete", "update", "query", "upsert", "put", "scan", "collection", "clusteredCollection", "create", "remove", "patch", "batchPut", "batchDelete", "batchGet"],
32
32
  },
33
33
  clusteredCollection: {
34
34
  name: "clusteredCollection",
@@ -37,7 +37,7 @@ let clauses = {
37
37
  return state;
38
38
  }
39
39
  try {
40
- const {pk, sk} = state.getCompositeAttributes();
40
+ const { pk, sk } = state.getCompositeAttributes();
41
41
  return state
42
42
  .setType(QueryTypes.clustered_collection)
43
43
  .setMethod(MethodTypes.query)
@@ -50,6 +50,22 @@ let clauses = {
50
50
  if (sk.length > 1) {
51
51
  state.filterProperties(FilterOperationNames.eq, {...unused, ...composites});
52
52
  }
53
+ })
54
+ .whenOptions(({ options, state }) => {
55
+ if (!options.ignoreOwnership) {
56
+ state.query.options.expressions.names = {
57
+ ...state.query.options.expressions.names,
58
+ ...state.query.options.identifiers.names,
59
+ };
60
+ state.query.options.expressions.values = {
61
+ ...state.query.options.expressions.values,
62
+ ...state.query.options.identifiers.values,
63
+ };
64
+ state.query.options.expressions.expression =
65
+ state.query.options.expressions.expression.length > 1
66
+ ? `(${state.query.options.expressions.expression}) AND ${state.query.options.identifiers.expression}`
67
+ : `${state.query.options.identifiers.expression}`;
68
+ }
53
69
  });
54
70
 
55
71
  } catch(err) {
@@ -72,7 +88,23 @@ let clauses = {
72
88
  .setType(QueryTypes.collection)
73
89
  .setMethod(MethodTypes.query)
74
90
  .setCollection(collection)
75
- .setPK(entity._expectFacets(facets, pk));
91
+ .setPK(entity._expectFacets(facets, pk))
92
+ .whenOptions(({ options, state }) => {
93
+ if (!options.ignoreOwnership) {
94
+ state.query.options.expressions.names = {
95
+ ...state.query.options.expressions.names,
96
+ ...state.query.options.identifiers.names,
97
+ };
98
+ state.query.options.expressions.values = {
99
+ ...state.query.options.expressions.values,
100
+ ...state.query.options.identifiers.values,
101
+ };
102
+ state.query.options.expressions.expression =
103
+ state.query.options.expressions.expression.length > 1
104
+ ? `(${state.query.options.expressions.expression}) AND ${state.query.options.identifiers.expression}`
105
+ : `${state.query.options.identifiers.expression}`;
106
+ }
107
+ });
76
108
  } catch(err) {
77
109
  state.setError(err);
78
110
  return state;
@@ -87,7 +119,13 @@ let clauses = {
87
119
  return state;
88
120
  }
89
121
  try {
90
- return state.setMethod(MethodTypes.scan);
122
+ return state.setMethod(MethodTypes.scan)
123
+ .whenOptions(({ state, options }) => {
124
+ if (!options.ignoreOwnership) {
125
+ state.unsafeApplyFilter(FilterOperationNames.eq, entity.identifiers.entity, entity.getName());
126
+ state.unsafeApplyFilter(FilterOperationNames.eq, entity.identifiers.version, entity.getVersion());
127
+ }
128
+ });
91
129
  } catch(err) {
92
130
  state.setError(err);
93
131
  return state;
@@ -118,7 +156,15 @@ let clauses = {
118
156
  return state;
119
157
  }
120
158
  },
121
- children: ["params", "go"],
159
+ children: ["params", "go", "commit"],
160
+ },
161
+ check: {
162
+ name: 'check',
163
+ action(...params) {
164
+ return clauses.get.action(...params)
165
+ .setMethod(MethodTypes.check);
166
+ },
167
+ children: ["commit"],
122
168
  },
123
169
  batchGet: {
124
170
  name: "batchGet",
@@ -152,7 +198,7 @@ let clauses = {
152
198
  return state;
153
199
  }
154
200
  },
155
- children: ["where", "params", "go"],
201
+ children: ["where", "params", "go", "commit"],
156
202
  },
157
203
  remove: {
158
204
  name: "remove",
@@ -182,7 +228,7 @@ let clauses = {
182
228
  return state;
183
229
  }
184
230
  },
185
- children: ["where", "params", "go"],
231
+ children: ["where", "params", "go", "commit"],
186
232
  },
187
233
  upsert: {
188
234
  name: 'upsert',
@@ -207,7 +253,7 @@ let clauses = {
207
253
  return state;
208
254
  }
209
255
  },
210
- children: ["params", "go", "where"],
256
+ children: ["params", "go", "where", "commit"],
211
257
  },
212
258
  put: {
213
259
  name: "put",
@@ -233,7 +279,7 @@ let clauses = {
233
279
  return state;
234
280
  }
235
281
  },
236
- children: ["params", "go"],
282
+ children: ["params", "go", "commit"],
237
283
  },
238
284
  batchPut: {
239
285
  name: "batchPut",
@@ -269,7 +315,7 @@ let clauses = {
269
315
  return state;
270
316
  }
271
317
  },
272
- children: ["params", "go"],
318
+ children: ["params", "go", "commit"],
273
319
  },
274
320
  patch: {
275
321
  name: "patch",
@@ -298,7 +344,7 @@ let clauses = {
298
344
  return state;
299
345
  }
300
346
  },
301
- children: ["set", "append","updateRemove", "updateDelete", "add", "subtract", "data"],
347
+ children: ["set", "append","updateRemove", "updateDelete", "add", "subtract", "data", "commit"],
302
348
  },
303
349
  update: {
304
350
  name: "update",
@@ -321,7 +367,7 @@ let clauses = {
321
367
  return state;
322
368
  }
323
369
  },
324
- children: ["data", "set", "append", "add", "updateRemove", "updateDelete", "go", "params", "subtract"],
370
+ children: ["data", "set", "append", "add", "updateRemove", "updateDelete", "go", "params", "subtract", "commit"],
325
371
  },
326
372
  data: {
327
373
  name: "data",
@@ -351,7 +397,7 @@ let clauses = {
351
397
  return state;
352
398
  }
353
399
  },
354
- children: ["data", "set", "append", "add", "updateRemove", "updateDelete", "go", "params", "subtract"],
400
+ children: ["data", "set", "append", "add", "updateRemove", "updateDelete", "go", "params", "subtract", "commit"],
355
401
  },
356
402
  set: {
357
403
  name: "set",
@@ -368,7 +414,7 @@ let clauses = {
368
414
  return state;
369
415
  }
370
416
  },
371
- children: ["data", "set", "append", "add", "updateRemove", "updateDelete", "go", "params", "subtract"],
417
+ children: ["data", "set", "append", "add", "updateRemove", "updateDelete", "go", "params", "subtract", "commit"],
372
418
  },
373
419
  append: {
374
420
  name: "append",
@@ -385,7 +431,7 @@ let clauses = {
385
431
  return state;
386
432
  }
387
433
  },
388
- children: ["data", "set", "append", "add", "updateRemove", "updateDelete", "go", "params", "subtract"],
434
+ children: ["data", "set", "append", "add", "updateRemove", "updateDelete", "go", "params", "subtract", "commit"],
389
435
  },
390
436
  updateRemove: {
391
437
  name: "remove",
@@ -405,7 +451,7 @@ let clauses = {
405
451
  return state;
406
452
  }
407
453
  },
408
- children: ["data", "set", "append", "add", "updateRemove", "updateDelete", "go", "params", "subtract"],
454
+ children: ["data", "set", "append", "add", "updateRemove", "updateDelete", "go", "params", "subtract", "commit"],
409
455
  },
410
456
  updateDelete: {
411
457
  name: "delete",
@@ -422,7 +468,7 @@ let clauses = {
422
468
  return state;
423
469
  }
424
470
  },
425
- children: ["data", "set", "append", "add", "updateRemove", "updateDelete", "go", "params", "subtract"],
471
+ children: ["data", "set", "append", "add", "updateRemove", "updateDelete", "go", "params", "subtract", "commit"],
426
472
  },
427
473
  add: {
428
474
  name: "add",
@@ -439,7 +485,7 @@ let clauses = {
439
485
  return state;
440
486
  }
441
487
  },
442
- children: ["data", "set", "append", "add", "updateRemove", "updateDelete", "go", "params", "subtract"],
488
+ children: ["data", "set", "append", "add", "updateRemove", "updateDelete", "go", "params", "subtract", "commit"],
443
489
  },
444
490
  subtract: {
445
491
  name: "subtract",
@@ -456,7 +502,7 @@ let clauses = {
456
502
  return state;
457
503
  }
458
504
  },
459
- children: ["data", "set", "append", "add", "updateRemove", "updateDelete", "go", "params", "subtract"],
505
+ children: ["data", "set", "append", "add", "updateRemove", "updateDelete", "go", "params", "subtract", "commit"],
460
506
  },
461
507
  query: {
462
508
  name: "query",
@@ -478,10 +524,13 @@ let clauses = {
478
524
  if (sk.length > 1) {
479
525
  state.filterProperties(FilterOperationNames.eq, {...unused, ...composites});
480
526
  }
481
- if (state.query.options.indexType === IndexTypes.clustered && Object.keys(composites).length < sk.length) {
482
- state.unsafeApplyFilter(FilterOperationNames.eq, entity.identifiers.entity, entity.getName())
483
- .unsafeApplyFilter(FilterOperationNames.eq, entity.identifiers.version, entity.getVersion());
484
- }
527
+
528
+ state.whenOptions(({ options, state }) => {
529
+ if (state.query.options.indexType === IndexTypes.clustered && Object.keys(composites).length < sk.length && !options.ignoreOwnership) {
530
+ state.unsafeApplyFilter(FilterOperationNames.eq, entity.identifiers.entity, entity.getName())
531
+ .unsafeApplyFilter(FilterOperationNames.eq, entity.identifiers.version, entity.getVersion());
532
+ }
533
+ });
485
534
  });
486
535
  } catch(err) {
487
536
  state.setError(err);
@@ -621,6 +670,35 @@ let clauses = {
621
670
  },
622
671
  children: ["go", "params"],
623
672
  },
673
+ commit: {
674
+ name: 'commit',
675
+ action(entity, state, options) {
676
+ if (state.getError() !== null) {
677
+ throw state.error;
678
+ }
679
+
680
+ const results = clauses.params.action(entity, state, {
681
+ ...options,
682
+ _returnOptions: true,
683
+ _isTransaction: true,
684
+ });
685
+
686
+ const method = TransactionOperations[state.query.method];
687
+ if (!method) {
688
+ throw new Error('Invalid commit method');
689
+ }
690
+
691
+ return {
692
+ [method]: results.params,
693
+ [TransactionCommitSymbol]: () => {
694
+ return {
695
+ entity,
696
+ }
697
+ },
698
+ }
699
+ },
700
+ children: [],
701
+ },
624
702
  params: {
625
703
  name: "params",
626
704
  action(entity, state, options = {}) {
@@ -632,20 +710,29 @@ let clauses = {
632
710
  throw new e.ElectroError(e.ErrorCodes.MissingTable, `Table name not defined. Table names must be either defined on the model, instance configuration, or as a query option.`);
633
711
  }
634
712
  const method = state.getMethod();
713
+ const normalizedOptions = entity._normalizeExecutionOptions({
714
+ provided: [ state.getOptions(), state.query.options, options ],
715
+ context: { operation: options._isTransaction ? MethodTypes.transactWrite : undefined }
716
+ });
717
+ state.applyWithOptions(normalizedOptions);
635
718
  let results;
636
719
  switch (method) {
637
- case MethodTypes.query:
638
- results = entity._queryParams(state, options);
720
+ case MethodTypes.query: {
721
+ results = entity._queryParams(state, normalizedOptions);
639
722
  break;
640
- case MethodTypes.batchWrite:
641
- results = entity._batchWriteParams(state, options);
642
- break
643
- case MethodTypes.batchGet:
644
- results = entity._batchGetParams(state, options);
723
+ }
724
+ case MethodTypes.batchWrite: {
725
+ results = entity._batchWriteParams(state, normalizedOptions);
645
726
  break;
646
- default:
647
- results = entity._params(state, options);
727
+ }
728
+ case MethodTypes.batchGet: {
729
+ results = entity._batchGetParams(state, normalizedOptions);
730
+ break;
731
+ }
732
+ default: {
733
+ results = entity._params(state, normalizedOptions);
648
734
  break;
735
+ }
649
736
  }
650
737
 
651
738
  if (method === MethodTypes.update && results.ExpressionAttributeValues && Object.keys(results.ExpressionAttributeValues).length === 0) {
@@ -653,6 +740,14 @@ let clauses = {
653
740
  // todo: change the getValues() method to return undefined in this case (would potentially require a more generous refactor)
654
741
  delete results.ExpressionAttributeValues;
655
742
  }
743
+
744
+ if (options._returnOptions) {
745
+ return {
746
+ params: results,
747
+ options: normalizedOptions,
748
+ }
749
+ }
750
+
656
751
  return results;
657
752
  } catch(err) {
658
753
  throw err;
@@ -671,9 +766,8 @@ let clauses = {
671
766
  throw new e.ElectroError(e.ErrorCodes.NoClientDefined, "No client defined on model");
672
767
  }
673
768
  options.terminalOperation = TerminalOperation.go;
674
- let params = clauses.params.action(entity, state, options);
675
- let {config} = entity._applyParameterOptions({}, state.getOptions(), options);
676
- return entity.go(state.getMethod(), params, config);
769
+ const paramResults = clauses.params.action(entity, state, { ...options, _returnOptions: true });
770
+ return entity.go(state.getMethod(), paramResults.params, paramResults.options);
677
771
  } catch(err) {
678
772
  return Promise.reject(err);
679
773
  }
@@ -718,6 +812,7 @@ class ChainState {
718
812
  options,
719
813
  };
720
814
  this.subStates = [];
815
+ this.applyAfterOptions = [];
721
816
  this.hasSortKey = hasSortKey;
722
817
  this.prev = null;
723
818
  this.self = null;
@@ -911,6 +1006,18 @@ class ChainState {
911
1006
  this.query.put.data = {...this.query.put.data, ...data};
912
1007
  return this;
913
1008
  }
1009
+
1010
+ whenOptions(fn) {
1011
+ if (v.isFunction(fn)) {
1012
+ this.applyAfterOptions.push((options) => {
1013
+ fn({ options, state: this });
1014
+ });
1015
+ }
1016
+ }
1017
+
1018
+ applyWithOptions(options = {}) {
1019
+ this.applyAfterOptions.forEach((fn) => fn(options));
1020
+ }
914
1021
  }
915
1022
 
916
1023
  module.exports = {