@squiz/db-lib 1.71.2 → 1.72.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/CHANGELOG.md +19 -0
 - package/lib/AbstractRepository.d.ts +2 -0
 - package/lib/AbstractRepository.d.ts.map +1 -0
 - package/lib/AbstractRepository.integration.spec.d.ts +1 -0
 - package/lib/AbstractRepository.integration.spec.d.ts.map +1 -0
 - package/lib/AbstractRepository.integration.spec.js +118 -0
 - package/lib/AbstractRepository.integration.spec.js.map +1 -0
 - package/lib/AbstractRepository.js +187 -0
 - package/lib/AbstractRepository.js.map +1 -0
 - package/lib/ConnectionManager.d.ts +1 -0
 - package/lib/ConnectionManager.d.ts.map +1 -0
 - package/lib/ConnectionManager.js +58 -0
 - package/lib/ConnectionManager.js.map +1 -0
 - package/lib/Migrator.d.ts +1 -0
 - package/lib/Migrator.d.ts.map +1 -0
 - package/lib/Migrator.js +160 -0
 - package/lib/Migrator.js.map +1 -0
 - package/lib/PostgresErrorCodes.d.ts +1 -0
 - package/lib/PostgresErrorCodes.d.ts.map +1 -0
 - package/lib/PostgresErrorCodes.js +274 -0
 - package/lib/PostgresErrorCodes.js.map +1 -0
 - package/lib/Repositories.d.ts +1 -0
 - package/lib/Repositories.d.ts.map +1 -0
 - package/lib/Repositories.js +3 -0
 - package/lib/Repositories.js.map +1 -0
 - package/lib/dynamodb/AbstractDynamoDbRepository.d.ts +50 -9
 - package/lib/dynamodb/AbstractDynamoDbRepository.d.ts.map +1 -0
 - package/lib/dynamodb/AbstractDynamoDbRepository.js +456 -0
 - package/lib/dynamodb/AbstractDynamoDbRepository.js.map +1 -0
 - package/lib/dynamodb/AbstractDynamoDbRepository.spec.d.ts +1 -0
 - package/lib/dynamodb/AbstractDynamoDbRepository.spec.d.ts.map +1 -0
 - package/lib/dynamodb/AbstractDynamoDbRepository.spec.js +924 -0
 - package/lib/dynamodb/AbstractDynamoDbRepository.spec.js.map +1 -0
 - package/lib/dynamodb/DynamoDbManager.d.ts +1 -0
 - package/lib/dynamodb/DynamoDbManager.d.ts.map +1 -0
 - package/lib/dynamodb/DynamoDbManager.js +66 -0
 - package/lib/dynamodb/DynamoDbManager.js.map +1 -0
 - package/lib/dynamodb/getDynamoDbOptions.d.ts +1 -0
 - package/lib/dynamodb/getDynamoDbOptions.d.ts.map +1 -0
 - package/lib/dynamodb/getDynamoDbOptions.js +15 -0
 - package/lib/dynamodb/getDynamoDbOptions.js.map +1 -0
 - package/lib/error/DuplicateItemError.d.ts +1 -0
 - package/lib/error/DuplicateItemError.d.ts.map +1 -0
 - package/lib/error/DuplicateItemError.js +12 -0
 - package/lib/error/DuplicateItemError.js.map +1 -0
 - package/lib/error/InvalidDataFormatError.d.ts +1 -0
 - package/lib/error/InvalidDataFormatError.d.ts.map +1 -0
 - package/lib/error/InvalidDataFormatError.js +12 -0
 - package/lib/error/InvalidDataFormatError.js.map +1 -0
 - package/lib/error/InvalidDbSchemaError.d.ts +1 -0
 - package/lib/error/InvalidDbSchemaError.d.ts.map +1 -0
 - package/lib/error/InvalidDbSchemaError.js +12 -0
 - package/lib/error/InvalidDbSchemaError.js.map +1 -0
 - package/lib/error/MissingKeyValuesError.d.ts +1 -0
 - package/lib/error/MissingKeyValuesError.d.ts.map +1 -0
 - package/lib/error/MissingKeyValuesError.js +12 -0
 - package/lib/error/MissingKeyValuesError.js.map +1 -0
 - package/lib/error/TransactionError.d.ts +1 -0
 - package/lib/error/TransactionError.d.ts.map +1 -0
 - package/lib/error/TransactionError.js +12 -0
 - package/lib/error/TransactionError.js.map +1 -0
 - package/lib/getConnectionInfo.d.ts +1 -0
 - package/lib/getConnectionInfo.d.ts.map +1 -0
 - package/lib/getConnectionInfo.js +30 -0
 - package/lib/getConnectionInfo.js.map +1 -0
 - package/lib/index.d.ts +1 -0
 - package/lib/index.d.ts.map +1 -0
 - package/lib/index.js +33 -70416
 - package/lib/index.js.map +1 -7
 - package/package.json +5 -5
 - package/src/AbstractRepository.ts +26 -20
 - package/src/dynamodb/AbstractDynamoDbRepository.spec.ts +289 -37
 - package/src/dynamodb/AbstractDynamoDbRepository.ts +140 -31
 - package/src/dynamodb/getDynamoDbOptions.ts +1 -1
 - package/tsconfig.json +5 -2
 - package/tsconfig.tsbuildinfo +1 -1
 - package/build.js +0 -31
 
    
        package/package.json
    CHANGED
    
    | 
         @@ -1,6 +1,6 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            {
         
     | 
| 
       2 
2 
     | 
    
         
             
              "name": "@squiz/db-lib",
         
     | 
| 
       3 
     | 
    
         
            -
              "version": "1. 
     | 
| 
      
 3 
     | 
    
         
            +
              "version": "1.72.0",
         
     | 
| 
       4 
4 
     | 
    
         
             
              "description": "",
         
     | 
| 
       5 
5 
     | 
    
         
             
              "main": "lib/index.js",
         
     | 
| 
       6 
6 
     | 
    
         
             
              "private": false,
         
     | 
| 
         @@ -8,7 +8,7 @@ 
     | 
|
| 
       8 
8 
     | 
    
         
             
                "access": "public"
         
     | 
| 
       9 
9 
     | 
    
         
             
              },
         
     | 
| 
       10 
10 
     | 
    
         
             
              "scripts": {
         
     | 
| 
       11 
     | 
    
         
            -
                "compile": " 
     | 
| 
      
 11 
     | 
    
         
            +
                "compile": "tsc -b",
         
     | 
| 
       12 
12 
     | 
    
         
             
                "test": "jest -c jest.config.ts --testMatch=\"**/*.spec.ts\" --testMatch=\"!**/*.integration.spec.ts\" --passWithNoTests",
         
     | 
| 
       13 
13 
     | 
    
         
             
                "test:integration": "jest --testMatch=\"**/*.integration.spec.ts\"",
         
     | 
| 
       14 
14 
     | 
    
         
             
                "test:update-snapshots": "jest -c jest.config.ts --updateSnapshot",
         
     | 
| 
         @@ -19,7 +19,7 @@ 
     | 
|
| 
       19 
19 
     | 
    
         
             
              "devDependencies": {
         
     | 
| 
       20 
20 
     | 
    
         
             
                "@types/jest": "28.1.8",
         
     | 
| 
       21 
21 
     | 
    
         
             
                "@types/node": "20.12.4",
         
     | 
| 
       22 
     | 
    
         
            -
                "@types/pg": "8. 
     | 
| 
      
 22 
     | 
    
         
            +
                "@types/pg": "^8.11.8",
         
     | 
| 
       23 
23 
     | 
    
         
             
                "aws-sdk-client-mock": "^4.0.0",
         
     | 
| 
       24 
24 
     | 
    
         
             
                "aws-sdk-client-mock-jest": "4.0.0",
         
     | 
| 
       25 
25 
     | 
    
         
             
                "eslint": "8.33.0",
         
     | 
| 
         @@ -36,9 +36,9 @@ 
     | 
|
| 
       36 
36 
     | 
    
         
             
                "@aws-sdk/client-secrets-manager": "3.651.1",
         
     | 
| 
       37 
37 
     | 
    
         
             
                "@aws-sdk/lib-dynamodb": "^3.651.1",
         
     | 
| 
       38 
38 
     | 
    
         
             
                "@opentelemetry/api": "^1.6.0",
         
     | 
| 
       39 
     | 
    
         
            -
                "@squiz/dx-common-lib": "^1. 
     | 
| 
      
 39 
     | 
    
         
            +
                "@squiz/dx-common-lib": "^1.69.0",
         
     | 
| 
       40 
40 
     | 
    
         
             
                "@squiz/dx-logger-lib": "^1.64.0",
         
     | 
| 
       41 
41 
     | 
    
         
             
                "dotenv": "16.0.3",
         
     | 
| 
       42 
     | 
    
         
            -
                "pg": "8. 
     | 
| 
      
 42 
     | 
    
         
            +
                "pg": "^8.12.0"
         
     | 
| 
       43 
43 
     | 
    
         
             
              }
         
     | 
| 
       44 
44 
     | 
    
         
             
            }
         
     | 
| 
         @@ -1,4 +1,4 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            import { PoolClient, Pool } from 'pg';
         
     | 
| 
      
 1 
     | 
    
         
            +
            import { PoolClient, Pool, escapeIdentifier } from 'pg';
         
     | 
| 
       2 
2 
     | 
    
         
             
            import { Repositories } from './Repositories';
         
     | 
| 
       3 
3 
     | 
    
         
             
            import { InvalidUpdateValueError } from '@squiz/dx-common-lib';
         
     | 
| 
       4 
4 
     | 
    
         | 
| 
         @@ -56,19 +56,29 @@ export abstract class AbstractRepository<SHAPE extends object, DATA_CLASS extend 
     | 
|
| 
       56 
56 
     | 
    
         
             
                return await this.pool.connect();
         
     | 
| 
       57 
57 
     | 
    
         
             
              }
         
     | 
| 
       58 
58 
     | 
    
         | 
| 
      
 59 
     | 
    
         
            +
              private sanitiseValue(value: Partial<SHAPE>) {
         
     | 
| 
      
 60 
     | 
    
         
            +
                const sanitisedValue = Object.entries(value)
         
     | 
| 
      
 61 
     | 
    
         
            +
                  .map(([key, value]) => [this.modelPropertyToSqlColumn[key as keyof SHAPE], value] as const)
         
     | 
| 
      
 62 
     | 
    
         
            +
                  .filter(([column, _v]) => !!column);
         
     | 
| 
      
 63 
     | 
    
         
            +
             
     | 
| 
      
 64 
     | 
    
         
            +
                const columns = sanitisedValue.map(([column]) => escapeIdentifier(column));
         
     | 
| 
      
 65 
     | 
    
         
            +
                const bindingParams = sanitisedValue.map((_, index) => `$${index + 1}`);
         
     | 
| 
      
 66 
     | 
    
         
            +
                const values = sanitisedValue.map(([_column, value]) => value);
         
     | 
| 
      
 67 
     | 
    
         
            +
             
     | 
| 
      
 68 
     | 
    
         
            +
                return {
         
     | 
| 
      
 69 
     | 
    
         
            +
                  columns,
         
     | 
| 
      
 70 
     | 
    
         
            +
                  bindingParams,
         
     | 
| 
      
 71 
     | 
    
         
            +
                  values,
         
     | 
| 
      
 72 
     | 
    
         
            +
                };
         
     | 
| 
      
 73 
     | 
    
         
            +
              }
         
     | 
| 
      
 74 
     | 
    
         
            +
             
     | 
| 
       59 
75 
     | 
    
         
             
              async create(value: SHAPE, transactionClient: PoolClient | null = null): Promise<SHAPE> {
         
     | 
| 
       60 
76 
     | 
    
         
             
                const valueAsClass = new this.classRef(value as Record<string, unknown>);
         
     | 
| 
       61 
     | 
    
         
            -
                const columns =  
     | 
| 
       62 
     | 
    
         
            -
                  .map((a) => `"${this.modelPropertyToSqlColumn[a as keyof SHAPE]}"`)
         
     | 
| 
       63 
     | 
    
         
            -
                  .join(', ');
         
     | 
| 
       64 
     | 
    
         
            -
             
     | 
| 
       65 
     | 
    
         
            -
                const values = Object.values(valueAsClass)
         
     | 
| 
       66 
     | 
    
         
            -
                  .map((a, index) => `$${index + 1}`)
         
     | 
| 
       67 
     | 
    
         
            -
                  .join(', ');
         
     | 
| 
      
 77 
     | 
    
         
            +
                const { columns, bindingParams, values } = this.sanitiseValue(valueAsClass);
         
     | 
| 
       68 
78 
     | 
    
         | 
| 
       69 
79 
     | 
    
         
             
                const result = await this.executeQuery(
         
     | 
| 
       70 
     | 
    
         
            -
                  `INSERT INTO ${this.tableName} (${columns}) VALUES (${ 
     | 
| 
       71 
     | 
    
         
            -
                   
     | 
| 
      
 80 
     | 
    
         
            +
                  `INSERT INTO ${this.tableName} (${columns.join(', ')}) VALUES (${bindingParams.join(', ')}) RETURNING *`,
         
     | 
| 
      
 81 
     | 
    
         
            +
                  values,
         
     | 
| 
       72 
82 
     | 
    
         
             
                  transactionClient,
         
     | 
| 
       73 
83 
     | 
    
         
             
                );
         
     | 
| 
       74 
84 
     | 
    
         | 
| 
         @@ -84,20 +94,16 @@ export abstract class AbstractRepository<SHAPE extends object, DATA_CLASS extend 
     | 
|
| 
       84 
94 
     | 
    
         
             
                  throw new InvalidUpdateValueError('Failed updating the repository, update values cannot be empty');
         
     | 
| 
       85 
95 
     | 
    
         
             
                }
         
     | 
| 
       86 
96 
     | 
    
         
             
                const whereValues = Object.values(where);
         
     | 
| 
       87 
     | 
    
         
            -
                const newValues =  
     | 
| 
       88 
     | 
    
         
            -
             
     | 
| 
       89 
     | 
    
         
            -
                const  
     | 
| 
       90 
     | 
    
         
            -
                  .map((a, index) => `"${this.modelPropertyToSqlColumn[a as keyof SHAPE]}" = $${index + 1}`)
         
     | 
| 
       91 
     | 
    
         
            -
                  .join(', ');
         
     | 
| 
       92 
     | 
    
         
            -
             
     | 
| 
       93 
     | 
    
         
            -
                const whereString = this.createWhereStringFromPartialModel(where, newValues.length);
         
     | 
| 
      
 97 
     | 
    
         
            +
                const newValues = this.sanitiseValue(newValue);
         
     | 
| 
      
 98 
     | 
    
         
            +
                const setValues = newValues.columns.map((c, i) => `${c} = ${newValues.bindingParams[i]}`);
         
     | 
| 
      
 99 
     | 
    
         
            +
                const whereString = this.createWhereStringFromPartialModel(where, setValues.length);
         
     | 
| 
       94 
100 
     | 
    
         | 
| 
       95 
101 
     | 
    
         
             
                const result = await this.executeQuery(
         
     | 
| 
       96 
102 
     | 
    
         
             
                  `UPDATE ${this.tableName} 
         
     | 
| 
       97 
     | 
    
         
            -
                    SET ${ 
     | 
| 
      
 103 
     | 
    
         
            +
                    SET ${setValues.join(', ')} 
         
     | 
| 
       98 
104 
     | 
    
         
             
                    WHERE ${whereString}
         
     | 
| 
       99 
105 
     | 
    
         
             
                    RETURNING *`,
         
     | 
| 
       100 
     | 
    
         
            -
                  [... 
     | 
| 
      
 106 
     | 
    
         
            +
                  [...newValues.values, ...whereValues],
         
     | 
| 
       101 
107 
     | 
    
         
             
                  transactionClient,
         
     | 
| 
       102 
108 
     | 
    
         
             
                );
         
     | 
| 
       103 
109 
     | 
    
         | 
| 
         @@ -112,7 +118,7 @@ export abstract class AbstractRepository<SHAPE extends object, DATA_CLASS extend 
     | 
|
| 
       112 
118 
     | 
    
         | 
| 
       113 
119 
     | 
    
         
             
                  const result = await client.query(`DELETE FROM ${this.tableName} WHERE ${whereString}`, Object.values(where));
         
     | 
| 
       114 
120 
     | 
    
         | 
| 
       115 
     | 
    
         
            -
                  return result.rowCount;
         
     | 
| 
      
 121 
     | 
    
         
            +
                  return result.rowCount ?? 0;
         
     | 
| 
       116 
122 
     | 
    
         
             
                } finally {
         
     | 
| 
       117 
123 
     | 
    
         
             
                  if (client && !transactionClient) {
         
     | 
| 
       118 
124 
     | 
    
         
             
                    client.release();
         
     | 
| 
         @@ -1,4 +1,4 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            import { AbstractDynamoDbRepository } from './AbstractDynamoDbRepository';
         
     | 
| 
      
 1 
     | 
    
         
            +
            import { AbstractDynamoDbRepository, QueryOptions } from './AbstractDynamoDbRepository';
         
     | 
| 
       2 
2 
     | 
    
         
             
            import {
         
     | 
| 
       3 
3 
     | 
    
         
             
              DeleteCommand,
         
     | 
| 
       4 
4 
     | 
    
         
             
              DeleteCommandInput,
         
     | 
| 
         @@ -14,6 +14,8 @@ import { 
     | 
|
| 
       14 
14 
     | 
    
         
             
              UpdateCommandInput,
         
     | 
| 
       15 
15 
     | 
    
         
             
              TransactWriteCommand,
         
     | 
| 
       16 
16 
     | 
    
         
             
              TransactWriteCommandInput,
         
     | 
| 
      
 17 
     | 
    
         
            +
              BatchGetCommand,
         
     | 
| 
      
 18 
     | 
    
         
            +
              BatchGetCommandInput,
         
     | 
| 
       17 
19 
     | 
    
         
             
            } from '@aws-sdk/lib-dynamodb';
         
     | 
| 
       18 
20 
     | 
    
         
             
            import { ConditionalCheckFailedException } from '@aws-sdk/client-dynamodb';
         
     | 
| 
       19 
21 
     | 
    
         
             
            import { DynamoDbManager, Transaction } from './DynamoDbManager';
         
     | 
| 
         @@ -245,13 +247,11 @@ describe('AbstractRepository', () => { 
     | 
|
| 
       245 
247 
     | 
    
         
             
                    ConditionExpression: `attribute_exists(pk)`,
         
     | 
| 
       246 
248 
     | 
    
         
             
                  };
         
     | 
| 
       247 
249 
     | 
    
         | 
| 
       248 
     | 
    
         
            -
                  const partialItemWithKeyFields = {
         
     | 
| 
       249 
     | 
    
         
            -
                    name: 'foo',
         
     | 
| 
       250 
     | 
    
         
            -
                  };
         
     | 
| 
       251 
250 
     | 
    
         
             
                  const updateItem = {
         
     | 
| 
      
 251 
     | 
    
         
            +
                    name: 'foo',
         
     | 
| 
       252 
252 
     | 
    
         
             
                    country: 'au-updated',
         
     | 
| 
       253 
253 
     | 
    
         
             
                  };
         
     | 
| 
       254 
     | 
    
         
            -
                  const result = await repository.updateItem( 
     | 
| 
      
 254 
     | 
    
         
            +
                  const result = await repository.updateItem(updateItem);
         
     | 
| 
       255 
255 
     | 
    
         
             
                  expect(ddbClientMock).toHaveReceivedNthCommandWith(2, UpdateCommand, input);
         
     | 
| 
       256 
256 
     | 
    
         
             
                  expect(result).toEqual(
         
     | 
| 
       257 
257 
     | 
    
         
             
                    new TestItem({
         
     | 
| 
         @@ -263,20 +263,49 @@ describe('AbstractRepository', () => { 
     | 
|
| 
       263 
263 
     | 
    
         
             
                  );
         
     | 
| 
       264 
264 
     | 
    
         
             
                });
         
     | 
| 
       265 
265 
     | 
    
         | 
| 
       266 
     | 
    
         
            -
                it('should  
     | 
| 
      
 266 
     | 
    
         
            +
                it('should not trigger update request if the input attributes are same as in the existing item', async () => {
         
     | 
| 
       267 
267 
     | 
    
         
             
                  ddbClientMock.on(GetCommand).resolves({
         
     | 
| 
       268 
268 
     | 
    
         
             
                    $metadata: {
         
     | 
| 
       269 
269 
     | 
    
         
             
                      httpStatusCode: 200,
         
     | 
| 
       270 
270 
     | 
    
         
             
                    },
         
     | 
| 
      
 271 
     | 
    
         
            +
                    Item: {
         
     | 
| 
      
 272 
     | 
    
         
            +
                      name: 'foo',
         
     | 
| 
      
 273 
     | 
    
         
            +
                      age: 99,
         
     | 
| 
      
 274 
     | 
    
         
            +
                      country: 'au',
         
     | 
| 
      
 275 
     | 
    
         
            +
                      data: {},
         
     | 
| 
      
 276 
     | 
    
         
            +
                    },
         
     | 
| 
       271 
277 
     | 
    
         
             
                  });
         
     | 
| 
      
 278 
     | 
    
         
            +
                  ddbClientMock.on(UpdateCommand).rejects(new Error('updateItem() called when not expected'));
         
     | 
| 
       272 
279 
     | 
    
         | 
| 
       273 
     | 
    
         
            -
                   
     | 
| 
      
 280 
     | 
    
         
            +
                  // update input attributes are same as in the existing item
         
     | 
| 
      
 281 
     | 
    
         
            +
                  const updateItem = {
         
     | 
| 
       274 
282 
     | 
    
         
             
                    name: 'foo',
         
     | 
| 
      
 283 
     | 
    
         
            +
                    country: 'au',
         
     | 
| 
       275 
284 
     | 
    
         
             
                  };
         
     | 
| 
      
 285 
     | 
    
         
            +
             
     | 
| 
      
 286 
     | 
    
         
            +
                  const result = await repository.updateItem(updateItem);
         
     | 
| 
      
 287 
     | 
    
         
            +
                  expect(result).toEqual(
         
     | 
| 
      
 288 
     | 
    
         
            +
                    new TestItem({
         
     | 
| 
      
 289 
     | 
    
         
            +
                      name: 'foo',
         
     | 
| 
      
 290 
     | 
    
         
            +
                      age: 99,
         
     | 
| 
      
 291 
     | 
    
         
            +
                      country: 'au',
         
     | 
| 
      
 292 
     | 
    
         
            +
                      data: {},
         
     | 
| 
      
 293 
     | 
    
         
            +
                    }),
         
     | 
| 
      
 294 
     | 
    
         
            +
                  );
         
     | 
| 
      
 295 
     | 
    
         
            +
                });
         
     | 
| 
      
 296 
     | 
    
         
            +
             
     | 
| 
      
 297 
     | 
    
         
            +
                it('should return undefined if item does does not exist', async () => {
         
     | 
| 
      
 298 
     | 
    
         
            +
                  ddbClientMock.on(GetCommand).resolves({
         
     | 
| 
      
 299 
     | 
    
         
            +
                    $metadata: {
         
     | 
| 
      
 300 
     | 
    
         
            +
                      httpStatusCode: 200,
         
     | 
| 
      
 301 
     | 
    
         
            +
                    },
         
     | 
| 
      
 302 
     | 
    
         
            +
                  });
         
     | 
| 
      
 303 
     | 
    
         
            +
             
     | 
| 
       276 
304 
     | 
    
         
             
                  const updateItem = {
         
     | 
| 
      
 305 
     | 
    
         
            +
                    name: 'foo',
         
     | 
| 
       277 
306 
     | 
    
         
             
                    country: 'au-updated',
         
     | 
| 
       278 
307 
     | 
    
         
             
                  };
         
     | 
| 
       279 
     | 
    
         
            -
                  const result = await repository.updateItem( 
     | 
| 
      
 308 
     | 
    
         
            +
                  const result = await repository.updateItem(updateItem);
         
     | 
| 
       280 
309 
     | 
    
         
             
                  expect(result).toEqual(undefined);
         
     | 
| 
       281 
310 
     | 
    
         
             
                });
         
     | 
| 
       282 
311 
     | 
    
         | 
| 
         @@ -300,13 +329,11 @@ describe('AbstractRepository', () => { 
     | 
|
| 
       300 
329 
     | 
    
         
             
                    }),
         
     | 
| 
       301 
330 
     | 
    
         
             
                  );
         
     | 
| 
       302 
331 
     | 
    
         | 
| 
       303 
     | 
    
         
            -
                  const partialItemWithKeyFields = {
         
     | 
| 
       304 
     | 
    
         
            -
                    name: 'foo',
         
     | 
| 
       305 
     | 
    
         
            -
                  };
         
     | 
| 
       306 
332 
     | 
    
         
             
                  const updateItem = {
         
     | 
| 
      
 333 
     | 
    
         
            +
                    name: 'foo',
         
     | 
| 
       307 
334 
     | 
    
         
             
                    country: 'au-updated',
         
     | 
| 
       308 
335 
     | 
    
         
             
                  };
         
     | 
| 
       309 
     | 
    
         
            -
                  const result = await repository.updateItem( 
     | 
| 
      
 336 
     | 
    
         
            +
                  const result = await repository.updateItem(updateItem);
         
     | 
| 
       310 
337 
     | 
    
         
             
                  expect(result).toEqual(undefined);
         
     | 
| 
       311 
338 
     | 
    
         
             
                });
         
     | 
| 
       312 
339 
     | 
    
         | 
| 
         @@ -323,15 +350,13 @@ describe('AbstractRepository', () => { 
     | 
|
| 
       323 
350 
     | 
    
         
             
                    },
         
     | 
| 
       324 
351 
     | 
    
         
             
                  });
         
     | 
| 
       325 
352 
     | 
    
         | 
| 
       326 
     | 
    
         
            -
                  const partialItemWithKeyFields = {
         
     | 
| 
       327 
     | 
    
         
            -
                    name: 'foo',
         
     | 
| 
       328 
     | 
    
         
            -
                  };
         
     | 
| 
       329 
353 
     | 
    
         
             
                  const updateItem = {
         
     | 
| 
      
 354 
     | 
    
         
            +
                    name: 'foo',
         
     | 
| 
       330 
355 
     | 
    
         
             
                    country: 61, // should be "string" type
         
     | 
| 
       331 
356 
     | 
    
         
             
                  };
         
     | 
| 
       332 
     | 
    
         
            -
                  await expect(
         
     | 
| 
       333 
     | 
    
         
            -
                     
     | 
| 
       334 
     | 
    
         
            -
                  ) 
     | 
| 
      
 357 
     | 
    
         
            +
                  await expect(repository.updateItem(updateItem as unknown as Partial<TestItem>)).rejects.toEqual(
         
     | 
| 
      
 358 
     | 
    
         
            +
                    new Error('Invalid "country"'),
         
     | 
| 
      
 359 
     | 
    
         
            +
                  );
         
     | 
| 
       335 
360 
     | 
    
         
             
                });
         
     | 
| 
       336 
361 
     | 
    
         | 
| 
       337 
362 
     | 
    
         
             
                it('should throw error if excess column in input', async () => {
         
     | 
| 
         @@ -347,26 +372,22 @@ describe('AbstractRepository', () => { 
     | 
|
| 
       347 
372 
     | 
    
         
             
                    },
         
     | 
| 
       348 
373 
     | 
    
         
             
                  });
         
     | 
| 
       349 
374 
     | 
    
         | 
| 
       350 
     | 
    
         
            -
                  const partialItemWithKeyFields = {
         
     | 
| 
       351 
     | 
    
         
            -
                    name: 'foo',
         
     | 
| 
       352 
     | 
    
         
            -
                  };
         
     | 
| 
       353 
375 
     | 
    
         
             
                  const updateItem = {
         
     | 
| 
      
 376 
     | 
    
         
            +
                    name: 'foo',
         
     | 
| 
       354 
377 
     | 
    
         
             
                    country: 'au-updated',
         
     | 
| 
       355 
378 
     | 
    
         
             
                    extra: '',
         
     | 
| 
       356 
379 
     | 
    
         
             
                  };
         
     | 
| 
       357 
     | 
    
         
            -
                  await expect(
         
     | 
| 
       358 
     | 
    
         
            -
                     
     | 
| 
       359 
     | 
    
         
            -
                  ) 
     | 
| 
      
 380 
     | 
    
         
            +
                  await expect(repository.updateItem(updateItem as unknown as Partial<TestItem>)).rejects.toEqual(
         
     | 
| 
      
 381 
     | 
    
         
            +
                    new InvalidDbSchemaError('Excess properties in entity test-item-entity: extra'),
         
     | 
| 
      
 382 
     | 
    
         
            +
                  );
         
     | 
| 
       360 
383 
     | 
    
         
             
                });
         
     | 
| 
       361 
384 
     | 
    
         | 
| 
       362 
385 
     | 
    
         
             
                it('should throw error if input does not includes key field(s)', async () => {
         
     | 
| 
       363 
     | 
    
         
            -
                  const partialItemWithKeyFields = {
         
     | 
| 
       364 
     | 
    
         
            -
                    age: 99,
         
     | 
| 
       365 
     | 
    
         
            -
                  };
         
     | 
| 
       366 
386 
     | 
    
         
             
                  const updateItem = {
         
     | 
| 
      
 387 
     | 
    
         
            +
                    age: 99,
         
     | 
| 
       367 
388 
     | 
    
         
             
                    country: 'au-updated', // should be "string" type
         
     | 
| 
       368 
389 
     | 
    
         
             
                  };
         
     | 
| 
       369 
     | 
    
         
            -
                  await expect(repository.updateItem( 
     | 
| 
      
 390 
     | 
    
         
            +
                  await expect(repository.updateItem(updateItem)).rejects.toEqual(
         
     | 
| 
       370 
391 
     | 
    
         
             
                    new MissingKeyValuesError('Key field "name" must be specified in the input item in entity test-item-entity'),
         
     | 
| 
       371 
392 
     | 
    
         
             
                  );
         
     | 
| 
       372 
393 
     | 
    
         
             
                });
         
     | 
| 
         @@ -473,6 +494,120 @@ describe('AbstractRepository', () => { 
     | 
|
| 
       473 
494 
     | 
    
         
             
                });
         
     | 
| 
       474 
495 
     | 
    
         
             
              });
         
     | 
| 
       475 
496 
     | 
    
         | 
| 
      
 497 
     | 
    
         
            +
              describe('getItems()', () => {
         
     | 
| 
      
 498 
     | 
    
         
            +
                it('should use BatchGetItem to get result', async () => {
         
     | 
| 
      
 499 
     | 
    
         
            +
                  ddbClientMock.on(BatchGetCommand).resolves({
         
     | 
| 
      
 500 
     | 
    
         
            +
                    $metadata: {
         
     | 
| 
      
 501 
     | 
    
         
            +
                      httpStatusCode: 200,
         
     | 
| 
      
 502 
     | 
    
         
            +
                    },
         
     | 
| 
      
 503 
     | 
    
         
            +
                    Responses: {
         
     | 
| 
      
 504 
     | 
    
         
            +
                      [TABLE_NAME]: [
         
     | 
| 
      
 505 
     | 
    
         
            +
                        {
         
     | 
| 
      
 506 
     | 
    
         
            +
                          name: 'foo',
         
     | 
| 
      
 507 
     | 
    
         
            +
                          age: 99,
         
     | 
| 
      
 508 
     | 
    
         
            +
                          country: 'au',
         
     | 
| 
      
 509 
     | 
    
         
            +
                          data: {},
         
     | 
| 
      
 510 
     | 
    
         
            +
                          data2: '{"foo":"bar","num":123}',
         
     | 
| 
      
 511 
     | 
    
         
            +
                        },
         
     | 
| 
      
 512 
     | 
    
         
            +
                        {
         
     | 
| 
      
 513 
     | 
    
         
            +
                          name: 'foo2',
         
     | 
| 
      
 514 
     | 
    
         
            +
                          age: 999,
         
     | 
| 
      
 515 
     | 
    
         
            +
                          country: 'au',
         
     | 
| 
      
 516 
     | 
    
         
            +
                          data: {},
         
     | 
| 
      
 517 
     | 
    
         
            +
                          data2: '{"foo":"bar","num":123}',
         
     | 
| 
      
 518 
     | 
    
         
            +
                        },
         
     | 
| 
      
 519 
     | 
    
         
            +
                      ],
         
     | 
| 
      
 520 
     | 
    
         
            +
                    },
         
     | 
| 
      
 521 
     | 
    
         
            +
                  });
         
     | 
| 
      
 522 
     | 
    
         
            +
                  const input: BatchGetCommandInput = {
         
     | 
| 
      
 523 
     | 
    
         
            +
                    RequestItems: {
         
     | 
| 
      
 524 
     | 
    
         
            +
                      [TABLE_NAME]: {
         
     | 
| 
      
 525 
     | 
    
         
            +
                        Keys: [
         
     | 
| 
      
 526 
     | 
    
         
            +
                          { pk: 'test_item#foo', sk: '#meta' },
         
     | 
| 
      
 527 
     | 
    
         
            +
                          { pk: 'test_item#foo2', sk: '#meta' },
         
     | 
| 
      
 528 
     | 
    
         
            +
                        ],
         
     | 
| 
      
 529 
     | 
    
         
            +
                      },
         
     | 
| 
      
 530 
     | 
    
         
            +
                    },
         
     | 
| 
      
 531 
     | 
    
         
            +
                  };
         
     | 
| 
      
 532 
     | 
    
         
            +
             
     | 
| 
      
 533 
     | 
    
         
            +
                  const requestItems = [{ name: 'foo' }, { name: 'foo2' }];
         
     | 
| 
      
 534 
     | 
    
         
            +
                  const result = await repository.getItems(requestItems);
         
     | 
| 
      
 535 
     | 
    
         
            +
                  expect(ddbClientMock).toHaveReceivedCommandWith(BatchGetCommand, input);
         
     | 
| 
      
 536 
     | 
    
         
            +
                  expect(result).toEqual([
         
     | 
| 
      
 537 
     | 
    
         
            +
                    new TestItem({
         
     | 
| 
      
 538 
     | 
    
         
            +
                      name: 'foo',
         
     | 
| 
      
 539 
     | 
    
         
            +
                      age: 99,
         
     | 
| 
      
 540 
     | 
    
         
            +
                      country: 'au',
         
     | 
| 
      
 541 
     | 
    
         
            +
                      data: {},
         
     | 
| 
      
 542 
     | 
    
         
            +
                      data2: {
         
     | 
| 
      
 543 
     | 
    
         
            +
                        foo: 'bar',
         
     | 
| 
      
 544 
     | 
    
         
            +
                        num: 123,
         
     | 
| 
      
 545 
     | 
    
         
            +
                      },
         
     | 
| 
      
 546 
     | 
    
         
            +
                    }),
         
     | 
| 
      
 547 
     | 
    
         
            +
                    new TestItem({
         
     | 
| 
      
 548 
     | 
    
         
            +
                      name: 'foo2',
         
     | 
| 
      
 549 
     | 
    
         
            +
                      age: 999,
         
     | 
| 
      
 550 
     | 
    
         
            +
                      country: 'au',
         
     | 
| 
      
 551 
     | 
    
         
            +
                      data: {},
         
     | 
| 
      
 552 
     | 
    
         
            +
                      data2: {
         
     | 
| 
      
 553 
     | 
    
         
            +
                        foo: 'bar',
         
     | 
| 
      
 554 
     | 
    
         
            +
                        num: 123,
         
     | 
| 
      
 555 
     | 
    
         
            +
                      },
         
     | 
| 
      
 556 
     | 
    
         
            +
                    }),
         
     | 
| 
      
 557 
     | 
    
         
            +
                  ]);
         
     | 
| 
      
 558 
     | 
    
         
            +
                });
         
     | 
| 
      
 559 
     | 
    
         
            +
             
     | 
| 
      
 560 
     | 
    
         
            +
                it('should request BatchGetItem in batch of 100 items to get result', async () => {
         
     | 
| 
      
 561 
     | 
    
         
            +
                  ddbClientMock.on(BatchGetCommand).resolves({
         
     | 
| 
      
 562 
     | 
    
         
            +
                    $metadata: {
         
     | 
| 
      
 563 
     | 
    
         
            +
                      httpStatusCode: 200,
         
     | 
| 
      
 564 
     | 
    
         
            +
                    },
         
     | 
| 
      
 565 
     | 
    
         
            +
                  });
         
     | 
| 
      
 566 
     | 
    
         
            +
             
     | 
| 
      
 567 
     | 
    
         
            +
                  const requestItems = [];
         
     | 
| 
      
 568 
     | 
    
         
            +
                  for (let i = 0; i < 120; i++) {
         
     | 
| 
      
 569 
     | 
    
         
            +
                    requestItems.push({ name: `foo${i}` });
         
     | 
| 
      
 570 
     | 
    
         
            +
                  }
         
     | 
| 
      
 571 
     | 
    
         
            +
                  // keys for first batch request
         
     | 
| 
      
 572 
     | 
    
         
            +
                  const keys1 = [];
         
     | 
| 
      
 573 
     | 
    
         
            +
                  for (let i = 0; i < 100; i++) {
         
     | 
| 
      
 574 
     | 
    
         
            +
                    keys1.push({ pk: `test_item#foo${i}`, sk: '#meta' });
         
     | 
| 
      
 575 
     | 
    
         
            +
                  }
         
     | 
| 
      
 576 
     | 
    
         
            +
                  // keys for second batch request
         
     | 
| 
      
 577 
     | 
    
         
            +
                  const keys2 = [];
         
     | 
| 
      
 578 
     | 
    
         
            +
                  for (let i = 100; i < 120; i++) {
         
     | 
| 
      
 579 
     | 
    
         
            +
                    keys2.push({ pk: `test_item#foo${i}`, sk: '#meta' });
         
     | 
| 
      
 580 
     | 
    
         
            +
                  }
         
     | 
| 
      
 581 
     | 
    
         
            +
             
     | 
| 
      
 582 
     | 
    
         
            +
                  const input1: BatchGetCommandInput = {
         
     | 
| 
      
 583 
     | 
    
         
            +
                    RequestItems: {
         
     | 
| 
      
 584 
     | 
    
         
            +
                      [TABLE_NAME]: {
         
     | 
| 
      
 585 
     | 
    
         
            +
                        Keys: keys1,
         
     | 
| 
      
 586 
     | 
    
         
            +
                      },
         
     | 
| 
      
 587 
     | 
    
         
            +
                    },
         
     | 
| 
      
 588 
     | 
    
         
            +
                  };
         
     | 
| 
      
 589 
     | 
    
         
            +
                  const input2: BatchGetCommandInput = {
         
     | 
| 
      
 590 
     | 
    
         
            +
                    RequestItems: {
         
     | 
| 
      
 591 
     | 
    
         
            +
                      [TABLE_NAME]: {
         
     | 
| 
      
 592 
     | 
    
         
            +
                        Keys: keys2,
         
     | 
| 
      
 593 
     | 
    
         
            +
                      },
         
     | 
| 
      
 594 
     | 
    
         
            +
                    },
         
     | 
| 
      
 595 
     | 
    
         
            +
                  };
         
     | 
| 
      
 596 
     | 
    
         
            +
             
     | 
| 
      
 597 
     | 
    
         
            +
                  await repository.getItems(requestItems);
         
     | 
| 
      
 598 
     | 
    
         
            +
                  expect(ddbClientMock).toHaveReceivedCommandTimes(BatchGetCommand, 2);
         
     | 
| 
      
 599 
     | 
    
         
            +
                  expect(ddbClientMock).toHaveReceivedNthCommandWith(1, BatchGetCommand, input1);
         
     | 
| 
      
 600 
     | 
    
         
            +
                  expect(ddbClientMock).toHaveReceivedNthCommandWith(2, BatchGetCommand, input2);
         
     | 
| 
      
 601 
     | 
    
         
            +
                });
         
     | 
| 
      
 602 
     | 
    
         
            +
             
     | 
| 
      
 603 
     | 
    
         
            +
                it('should throw error if any input item does not includes key field(s)', async () => {
         
     | 
| 
      
 604 
     | 
    
         
            +
                  const requestItems = [{ name: 'foo' }, { age: 22 }];
         
     | 
| 
      
 605 
     | 
    
         
            +
                  await expect(repository.getItems(requestItems)).rejects.toEqual(
         
     | 
| 
      
 606 
     | 
    
         
            +
                    new MissingKeyValuesError('Key field "name" must be specified in the input item in entity test-item-entity'),
         
     | 
| 
      
 607 
     | 
    
         
            +
                  );
         
     | 
| 
      
 608 
     | 
    
         
            +
                });
         
     | 
| 
      
 609 
     | 
    
         
            +
              });
         
     | 
| 
      
 610 
     | 
    
         
            +
             
     | 
| 
       476 
611 
     | 
    
         
             
              describe('queryItems()', () => {
         
     | 
| 
       477 
612 
     | 
    
         
             
                it('should return the items if found', async () => {
         
     | 
| 
       478 
613 
     | 
    
         
             
                  ddbClientMock.on(QueryCommand).resolves({
         
     | 
| 
         @@ -555,8 +690,7 @@ describe('AbstractRepository', () => { 
     | 
|
| 
       555 
690 
     | 
    
         
             
                  };
         
     | 
| 
       556 
691 
     | 
    
         | 
| 
       557 
692 
     | 
    
         
             
                  const partialItem = { name: 'foo' };
         
     | 
| 
       558 
     | 
    
         
            -
                  const  
     | 
| 
       559 
     | 
    
         
            -
                  const _result = await repository.queryItems(partialItem, useSortKey);
         
     | 
| 
      
 693 
     | 
    
         
            +
                  const _result = await repository.queryItems(partialItem, { useSortKey: true });
         
     | 
| 
       560 
694 
     | 
    
         
             
                  expect(ddbClientMock).toHaveReceivedCommandWith(QueryCommand, input);
         
     | 
| 
       561 
695 
     | 
    
         
             
                });
         
     | 
| 
       562 
696 
     | 
    
         | 
| 
         @@ -595,7 +729,7 @@ describe('AbstractRepository', () => { 
     | 
|
| 
       595 
729 
     | 
    
         | 
| 
       596 
730 
     | 
    
         
             
                  const partialItem = { country: 'au' };
         
     | 
| 
       597 
731 
     | 
    
         
             
                  const useSortKey = false;
         
     | 
| 
       598 
     | 
    
         
            -
                  const result = await repository.queryItems(partialItem, useSortKey, index);
         
     | 
| 
      
 732 
     | 
    
         
            +
                  const result = await repository.queryItems(partialItem, { useSortKey, index });
         
     | 
| 
       599 
733 
     | 
    
         
             
                  expect(ddbClientMock).toHaveReceivedCommandWith(QueryCommand, input);
         
     | 
| 
       600 
734 
     | 
    
         
             
                  expect(result).toEqual([
         
     | 
| 
       601 
735 
     | 
    
         
             
                    new TestItem({
         
     | 
| 
         @@ -636,14 +770,134 @@ describe('AbstractRepository', () => { 
     | 
|
| 
       636 
770 
     | 
    
         | 
| 
       637 
771 
     | 
    
         
             
                  const partialItem = { age: 99, country: 'au' };
         
     | 
| 
       638 
772 
     | 
    
         
             
                  const useSortKey = true;
         
     | 
| 
       639 
     | 
    
         
            -
                  const _result = await repository.queryItems(partialItem, useSortKey, index);
         
     | 
| 
      
 773 
     | 
    
         
            +
                  const _result = await repository.queryItems(partialItem, { useSortKey, index });
         
     | 
| 
      
 774 
     | 
    
         
            +
                  expect(ddbClientMock).toHaveReceivedCommandWith(QueryCommand, input);
         
     | 
| 
      
 775 
     | 
    
         
            +
                });
         
     | 
| 
      
 776 
     | 
    
         
            +
             
     | 
| 
      
 777 
     | 
    
         
            +
                it('should set input query correctly when "filter - begins_with" query option is set', async () => {
         
     | 
| 
      
 778 
     | 
    
         
            +
                  ddbClientMock.on(QueryCommand).resolves({
         
     | 
| 
      
 779 
     | 
    
         
            +
                    $metadata: {
         
     | 
| 
      
 780 
     | 
    
         
            +
                      httpStatusCode: 200,
         
     | 
| 
      
 781 
     | 
    
         
            +
                    },
         
     | 
| 
      
 782 
     | 
    
         
            +
                  });
         
     | 
| 
      
 783 
     | 
    
         
            +
                  const input: QueryCommandInput = {
         
     | 
| 
      
 784 
     | 
    
         
            +
                    TableName: TABLE_NAME,
         
     | 
| 
      
 785 
     | 
    
         
            +
                    KeyConditionExpression: '#pkName = :pkValue AND begins_with(#skName, :skValue)',
         
     | 
| 
      
 786 
     | 
    
         
            +
                    ExpressionAttributeNames: {
         
     | 
| 
      
 787 
     | 
    
         
            +
                      '#pkName': 'pk',
         
     | 
| 
      
 788 
     | 
    
         
            +
                      '#skName': 'sk',
         
     | 
| 
      
 789 
     | 
    
         
            +
                    },
         
     | 
| 
      
 790 
     | 
    
         
            +
                    ExpressionAttributeValues: {
         
     | 
| 
      
 791 
     | 
    
         
            +
                      ':pkValue': 'test_item#foo',
         
     | 
| 
      
 792 
     | 
    
         
            +
                      ':skValue': 'keyword-x',
         
     | 
| 
      
 793 
     | 
    
         
            +
                    },
         
     | 
| 
      
 794 
     | 
    
         
            +
                  };
         
     | 
| 
      
 795 
     | 
    
         
            +
             
     | 
| 
      
 796 
     | 
    
         
            +
                  const partialItem = { name: 'foo' };
         
     | 
| 
      
 797 
     | 
    
         
            +
                  const queryOptions: QueryOptions = {
         
     | 
| 
      
 798 
     | 
    
         
            +
                    filter: {
         
     | 
| 
      
 799 
     | 
    
         
            +
                      type: 'begins_with',
         
     | 
| 
      
 800 
     | 
    
         
            +
                      keyword: 'keyword-x',
         
     | 
| 
      
 801 
     | 
    
         
            +
                    },
         
     | 
| 
      
 802 
     | 
    
         
            +
                  };
         
     | 
| 
      
 803 
     | 
    
         
            +
                  await repository.queryItems(partialItem, queryOptions);
         
     | 
| 
      
 804 
     | 
    
         
            +
                  expect(ddbClientMock).toHaveReceivedCommandWith(QueryCommand, input);
         
     | 
| 
      
 805 
     | 
    
         
            +
                });
         
     | 
| 
      
 806 
     | 
    
         
            +
             
     | 
| 
      
 807 
     | 
    
         
            +
                it('should throw error invalid "filter" query option is set', async () => {
         
     | 
| 
      
 808 
     | 
    
         
            +
                  ddbClientMock.on(QueryCommand).resolves({
         
     | 
| 
      
 809 
     | 
    
         
            +
                    $metadata: {
         
     | 
| 
      
 810 
     | 
    
         
            +
                      httpStatusCode: 200,
         
     | 
| 
      
 811 
     | 
    
         
            +
                    },
         
     | 
| 
      
 812 
     | 
    
         
            +
                  });
         
     | 
| 
      
 813 
     | 
    
         
            +
                  const partialItem = { name: 'foo' };
         
     | 
| 
      
 814 
     | 
    
         
            +
                  const queryOptions = {
         
     | 
| 
      
 815 
     | 
    
         
            +
                    filter: {
         
     | 
| 
      
 816 
     | 
    
         
            +
                      type: 'invalid-type',
         
     | 
| 
      
 817 
     | 
    
         
            +
                      keyword: 'keyword-x',
         
     | 
| 
      
 818 
     | 
    
         
            +
                    },
         
     | 
| 
      
 819 
     | 
    
         
            +
                  } as unknown as QueryOptions;
         
     | 
| 
      
 820 
     | 
    
         
            +
                  await expect(repository.queryItems(partialItem, queryOptions)).rejects.toEqual(
         
     | 
| 
      
 821 
     | 
    
         
            +
                    new Error(`Invalid query filter type: invalid-type`),
         
     | 
| 
      
 822 
     | 
    
         
            +
                  );
         
     | 
| 
      
 823 
     | 
    
         
            +
                });
         
     | 
| 
      
 824 
     | 
    
         
            +
             
     | 
| 
      
 825 
     | 
    
         
            +
                it('should set input query correctly when "limit" query option is set', async () => {
         
     | 
| 
      
 826 
     | 
    
         
            +
                  ddbClientMock.on(QueryCommand).resolves({
         
     | 
| 
      
 827 
     | 
    
         
            +
                    $metadata: {
         
     | 
| 
      
 828 
     | 
    
         
            +
                      httpStatusCode: 200,
         
     | 
| 
      
 829 
     | 
    
         
            +
                    },
         
     | 
| 
      
 830 
     | 
    
         
            +
                  });
         
     | 
| 
      
 831 
     | 
    
         
            +
                  const input: QueryCommandInput = {
         
     | 
| 
      
 832 
     | 
    
         
            +
                    TableName: TABLE_NAME,
         
     | 
| 
      
 833 
     | 
    
         
            +
                    KeyConditionExpression: '#pkName = :pkValue',
         
     | 
| 
      
 834 
     | 
    
         
            +
                    ExpressionAttributeNames: {
         
     | 
| 
      
 835 
     | 
    
         
            +
                      '#pkName': 'pk',
         
     | 
| 
      
 836 
     | 
    
         
            +
                    },
         
     | 
| 
      
 837 
     | 
    
         
            +
                    ExpressionAttributeValues: {
         
     | 
| 
      
 838 
     | 
    
         
            +
                      ':pkValue': 'test_item#foo',
         
     | 
| 
      
 839 
     | 
    
         
            +
                    },
         
     | 
| 
      
 840 
     | 
    
         
            +
                    Limit: 33,
         
     | 
| 
      
 841 
     | 
    
         
            +
                  };
         
     | 
| 
      
 842 
     | 
    
         
            +
             
     | 
| 
      
 843 
     | 
    
         
            +
                  const partialItem = { name: 'foo' };
         
     | 
| 
      
 844 
     | 
    
         
            +
                  const queryOptions = { limit: 33 };
         
     | 
| 
      
 845 
     | 
    
         
            +
                  await repository.queryItems(partialItem, queryOptions);
         
     | 
| 
      
 846 
     | 
    
         
            +
                  expect(ddbClientMock).toHaveReceivedCommandWith(QueryCommand, input);
         
     | 
| 
      
 847 
     | 
    
         
            +
                });
         
     | 
| 
      
 848 
     | 
    
         
            +
             
     | 
| 
      
 849 
     | 
    
         
            +
                it('should set input query correctly when "order asc" query option is set', async () => {
         
     | 
| 
      
 850 
     | 
    
         
            +
                  ddbClientMock.on(QueryCommand).resolves({
         
     | 
| 
      
 851 
     | 
    
         
            +
                    $metadata: {
         
     | 
| 
      
 852 
     | 
    
         
            +
                      httpStatusCode: 200,
         
     | 
| 
      
 853 
     | 
    
         
            +
                    },
         
     | 
| 
      
 854 
     | 
    
         
            +
                  });
         
     | 
| 
      
 855 
     | 
    
         
            +
                  const input: QueryCommandInput = {
         
     | 
| 
      
 856 
     | 
    
         
            +
                    TableName: TABLE_NAME,
         
     | 
| 
      
 857 
     | 
    
         
            +
                    KeyConditionExpression: '#pkName = :pkValue',
         
     | 
| 
      
 858 
     | 
    
         
            +
                    ExpressionAttributeNames: {
         
     | 
| 
      
 859 
     | 
    
         
            +
                      '#pkName': 'pk',
         
     | 
| 
      
 860 
     | 
    
         
            +
                    },
         
     | 
| 
      
 861 
     | 
    
         
            +
                    ExpressionAttributeValues: {
         
     | 
| 
      
 862 
     | 
    
         
            +
                      ':pkValue': 'test_item#foo',
         
     | 
| 
      
 863 
     | 
    
         
            +
                    },
         
     | 
| 
      
 864 
     | 
    
         
            +
                    ScanIndexForward: true,
         
     | 
| 
      
 865 
     | 
    
         
            +
                  };
         
     | 
| 
      
 866 
     | 
    
         
            +
             
     | 
| 
      
 867 
     | 
    
         
            +
                  const partialItem = { name: 'foo' };
         
     | 
| 
      
 868 
     | 
    
         
            +
                  const queryOptions = { order: 'asc' } as unknown as QueryOptions;
         
     | 
| 
      
 869 
     | 
    
         
            +
                  await repository.queryItems(partialItem, queryOptions);
         
     | 
| 
      
 870 
     | 
    
         
            +
                  expect(ddbClientMock).toHaveReceivedCommandWith(QueryCommand, input);
         
     | 
| 
      
 871 
     | 
    
         
            +
                });
         
     | 
| 
      
 872 
     | 
    
         
            +
             
     | 
| 
      
 873 
     | 
    
         
            +
                it('should set input query correctly when "order desc" query option is set', async () => {
         
     | 
| 
      
 874 
     | 
    
         
            +
                  ddbClientMock.on(QueryCommand).resolves({
         
     | 
| 
      
 875 
     | 
    
         
            +
                    $metadata: {
         
     | 
| 
      
 876 
     | 
    
         
            +
                      httpStatusCode: 200,
         
     | 
| 
      
 877 
     | 
    
         
            +
                    },
         
     | 
| 
      
 878 
     | 
    
         
            +
                  });
         
     | 
| 
      
 879 
     | 
    
         
            +
                  const input: QueryCommandInput = {
         
     | 
| 
      
 880 
     | 
    
         
            +
                    TableName: TABLE_NAME,
         
     | 
| 
      
 881 
     | 
    
         
            +
                    KeyConditionExpression: '#pkName = :pkValue',
         
     | 
| 
      
 882 
     | 
    
         
            +
                    ExpressionAttributeNames: {
         
     | 
| 
      
 883 
     | 
    
         
            +
                      '#pkName': 'pk',
         
     | 
| 
      
 884 
     | 
    
         
            +
                    },
         
     | 
| 
      
 885 
     | 
    
         
            +
                    ExpressionAttributeValues: {
         
     | 
| 
      
 886 
     | 
    
         
            +
                      ':pkValue': 'test_item#foo',
         
     | 
| 
      
 887 
     | 
    
         
            +
                    },
         
     | 
| 
      
 888 
     | 
    
         
            +
                    ScanIndexForward: false,
         
     | 
| 
      
 889 
     | 
    
         
            +
                  };
         
     | 
| 
      
 890 
     | 
    
         
            +
             
     | 
| 
      
 891 
     | 
    
         
            +
                  const partialItem = { name: 'foo' };
         
     | 
| 
      
 892 
     | 
    
         
            +
                  const queryOptions = { order: 'desc' } as unknown as QueryOptions;
         
     | 
| 
      
 893 
     | 
    
         
            +
                  await repository.queryItems(partialItem, queryOptions);
         
     | 
| 
       640 
894 
     | 
    
         
             
                  expect(ddbClientMock).toHaveReceivedCommandWith(QueryCommand, input);
         
     | 
| 
       641 
895 
     | 
    
         
             
                });
         
     | 
| 
       642 
896 
     | 
    
         | 
| 
       643 
897 
     | 
    
         
             
                it('should throw error for invalid index query', async () => {
         
     | 
| 
       644 
898 
     | 
    
         
             
                  const index = 'undefined-index';
         
     | 
| 
       645 
899 
     | 
    
         
             
                  const partialItem = { age: 99, country: 'au' };
         
     | 
| 
       646 
     | 
    
         
            -
                  await expect(repository.queryItems(partialItem,  
     | 
| 
      
 900 
     | 
    
         
            +
                  await expect(repository.queryItems(partialItem, { index })).rejects.toEqual(
         
     | 
| 
       647 
901 
     | 
    
         
             
                    new MissingKeyValuesError(`Table index '${index}' not defined on entity test-item-entity`),
         
     | 
| 
       648 
902 
     | 
    
         
             
                  );
         
     | 
| 
       649 
903 
     | 
    
         
             
                });
         
     | 
| 
         @@ -659,7 +913,7 @@ describe('AbstractRepository', () => { 
     | 
|
| 
       659 
913 
     | 
    
         
             
                  const partialItem = { name: 'foo' };
         
     | 
| 
       660 
914 
     | 
    
         
             
                  const useSortKey = false;
         
     | 
| 
       661 
915 
     | 
    
         
             
                  const index = 'gsi1_pk-gsi1_sk-index';
         
     | 
| 
       662 
     | 
    
         
            -
                  await expect(repository.queryItems(partialItem, useSortKey, index)).rejects.toEqual(
         
     | 
| 
      
 916 
     | 
    
         
            +
                  await expect(repository.queryItems(partialItem, { useSortKey, index })).rejects.toEqual(
         
     | 
| 
       663 
917 
     | 
    
         
             
                    new MissingKeyValuesError(`Key field "country" must be specified in the input item in entity test-item-entity`),
         
     | 
| 
       664 
918 
     | 
    
         
             
                  );
         
     | 
| 
       665 
919 
     | 
    
         
             
                });
         
     | 
| 
         @@ -668,7 +922,7 @@ describe('AbstractRepository', () => { 
     | 
|
| 
       668 
922 
     | 
    
         
             
                  const partialItem = { country: 'au' };
         
     | 
| 
       669 
923 
     | 
    
         
             
                  const useSortKey = true;
         
     | 
| 
       670 
924 
     | 
    
         
             
                  const index = 'gsi1_pk-gsi1_sk-index';
         
     | 
| 
       671 
     | 
    
         
            -
                  await expect(repository.queryItems(partialItem, useSortKey, index)).rejects.toEqual(
         
     | 
| 
      
 925 
     | 
    
         
            +
                  await expect(repository.queryItems(partialItem, { useSortKey, index })).rejects.toEqual(
         
     | 
| 
       672 
926 
     | 
    
         
             
                    new MissingKeyValuesError(`Key field "age" must be specified in the input item in entity test-item-entity`),
         
     | 
| 
       673 
927 
     | 
    
         
             
                  );
         
     | 
| 
       674 
928 
     | 
    
         
             
                });
         
     | 
| 
         @@ -752,8 +1006,6 @@ describe('AbstractRepository', () => { 
     | 
|
| 
       752 
1006 
     | 
    
         
             
                    await repository.updateItem(
         
     | 
| 
       753 
1007 
     | 
    
         
             
                      {
         
     | 
| 
       754 
1008 
     | 
    
         
             
                        name: 'foo2',
         
     | 
| 
       755 
     | 
    
         
            -
                      },
         
     | 
| 
       756 
     | 
    
         
            -
                      {
         
     | 
| 
       757 
1009 
     | 
    
         
             
                        age: 55,
         
     | 
| 
       758 
1010 
     | 
    
         
             
                      },
         
     | 
| 
       759 
1011 
     | 
    
         
             
                      transaction,
         
     |