@squiz/db-lib 1.2.1-alpha.95 → 1.2.1-alpha.97
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 +16 -0
- package/lib/AbstractRepository.d.ts +5 -3
- package/lib/PostgresErrorCodes.d.ts +268 -0
- package/lib/assertions/assertAssign.d.ts +4 -0
- package/lib/assertions/assertAssign.spec.d.ts +1 -0
- package/lib/assertions/assertAssignWithDefaultUndefinedValue.d.ts +4 -0
- package/lib/assertions/assertAssignWithDefaultUndefinedValue.spec.d.ts +1 -0
- package/lib/assertions/assertIsDefined.d.ts +1 -0
- package/lib/assertions/assertIsDefined.spec.d.ts +1 -0
- package/lib/assertions/assertIsMapOfStringString.d.ts +3 -0
- package/lib/assertions/assertIsMapOfStringString.spec.d.ts +1 -0
- package/lib/assertions/assertIsNotAnEmptyString.d.ts +1 -0
- package/lib/assertions/assertIsNotAnEmptyString.spec.d.ts +1 -0
- package/lib/assertions/assertIsObject.d.ts +1 -0
- package/lib/assertions/assertIsObject.spec.d.ts +1 -0
- package/lib/assertions/assertIsString.d.ts +1 -0
- package/lib/assertions/assertIsString.spec.d.ts +1 -0
- package/lib/index.d.ts +8 -0
- package/lib/index.js +12369 -1364
- package/lib/index.js.map +4 -4
- package/package.json +10 -9
- package/src/AbstractRepository.ts +11 -7
- package/src/Migrator.ts +13 -9
- package/src/PostgresErrorCodes.ts +270 -0
- package/src/assertions/assertAssign.spec.ts +18 -0
- package/src/assertions/assertAssign.ts +22 -0
- package/src/assertions/assertAssignWithDefaultUndefinedValue.spec.ts +31 -0
- package/src/assertions/assertAssignWithDefaultUndefinedValue.ts +17 -0
- package/src/assertions/assertIsDefined.spec.ts +19 -0
- package/src/assertions/assertIsDefined.ts +7 -0
- package/src/assertions/assertIsMapOfStringString.spec.ts +23 -0
- package/src/assertions/assertIsMapOfStringString.ts +29 -0
- package/src/assertions/assertIsNotAnEmptyString.spec.ts +25 -0
- package/src/assertions/assertIsNotAnEmptyString.ts +17 -0
- package/src/assertions/assertIsObject.spec.ts +17 -0
- package/src/assertions/assertIsObject.ts +11 -0
- package/src/assertions/assertIsString.spec.ts +16 -0
- package/src/assertions/assertIsString.ts +11 -0
- package/src/index.ts +14 -0
- package/tsconfig.json +5 -1
- package/tsconfig.tsbuildinfo +1 -1
    
        package/package.json
    CHANGED
    
    | @@ -1,13 +1,13 @@ | |
| 1 1 | 
             
            {
         | 
| 2 2 | 
             
              "name": "@squiz/db-lib",
         | 
| 3 | 
            -
              "version": "1.2.1-alpha. | 
| 3 | 
            +
              "version": "1.2.1-alpha.97",
         | 
| 4 4 | 
             
              "description": "",
         | 
| 5 5 | 
             
              "main": "lib/index.js",
         | 
| 6 6 | 
             
              "scripts": {
         | 
| 7 7 | 
             
                "start": "node ./lib/index.js",
         | 
| 8 8 | 
             
                "compile": "node build.js && npx tsc",
         | 
| 9 9 | 
             
                "lint": "eslint ./src --ext .ts",
         | 
| 10 | 
            -
                "test": " | 
| 10 | 
            +
                "test": "jest -c jest.config.ts",
         | 
| 11 11 | 
             
                "test:integration___": "jest -c jest.config.ts",
         | 
| 12 12 | 
             
                "test:update-snapshots": "jest -c jest.config.ts --updateSnapshot",
         | 
| 13 13 | 
             
                "clean": "rimraf \".tsbuildinfo\" \"./lib\""
         | 
| @@ -18,20 +18,21 @@ | |
| 18 18 | 
             
                "@types/jest": "28.1.6",
         | 
| 19 19 | 
             
                "@types/node": "17.0.27",
         | 
| 20 20 | 
             
                "@types/pg": "8.6.5",
         | 
| 21 | 
            -
                "esbuild": "0. | 
| 22 | 
            -
                "eslint": "8. | 
| 21 | 
            +
                "esbuild": "0.15.3",
         | 
| 22 | 
            +
                "eslint": "8.22.0",
         | 
| 23 23 | 
             
                "fs-extra": "10.1.0",
         | 
| 24 24 | 
             
                "jest": "28.1.3",
         | 
| 25 25 | 
             
                "rimraf": "3.0.2",
         | 
| 26 | 
            -
                "ts-jest": "28.0. | 
| 26 | 
            +
                "ts-jest": "28.0.7",
         | 
| 27 27 | 
             
                "ts-loader": "9.3.1",
         | 
| 28 | 
            -
                "ts-node": "10. | 
| 28 | 
            +
                "ts-node": "10.9.1",
         | 
| 29 29 | 
             
                "typescript": "4.7.4"
         | 
| 30 30 | 
             
              },
         | 
| 31 31 | 
             
              "dependencies": {
         | 
| 32 | 
            -
                "@aws-sdk/client-secrets-manager": " | 
| 32 | 
            +
                "@aws-sdk/client-secrets-manager": "3.121.0",
         | 
| 33 | 
            +
                "@squiz/dx-logger-lib": "^1.2.1-alpha.97",
         | 
| 33 34 | 
             
                "dotenv": "16.0.1",
         | 
| 34 | 
            -
                "pg": " | 
| 35 | 
            +
                "pg": "8.7.3"
         | 
| 35 36 | 
             
              },
         | 
| 36 | 
            -
              "gitHead": " | 
| 37 | 
            +
              "gitHead": "bf3e5580c5b09c3e46a5965da38e4ed4657463d4"
         | 
| 37 38 | 
             
            }
         | 
| @@ -17,24 +17,27 @@ export type Repository<T> = Reader<T> & Writer<T>; | |
| 17 17 | 
             
            export abstract class AbstractRepository<T> implements Reader<T>, Writer<T> {
         | 
| 18 18 | 
             
              protected tableName: string;
         | 
| 19 19 |  | 
| 20 | 
            +
              /** object where the key is the model property name amd the value is sql column name */
         | 
| 20 21 | 
             
              protected modelPropertyToSqlColumn: { [key in keyof T]: string };
         | 
| 21 | 
            -
               | 
| 22 | 
            +
              /** object where the key is the sql column name and the value is the model property name */
         | 
| 23 | 
            +
              protected sqlColumnToModelProperty: { [key: string]: string };
         | 
| 22 24 |  | 
| 23 25 | 
             
              constructor(
         | 
| 24 26 | 
             
                protected repositories: Repositories,
         | 
| 25 27 | 
             
                protected pool: Pool,
         | 
| 26 28 | 
             
                tableName: string,
         | 
| 27 29 | 
             
                mapping: { [key in keyof T]: string },
         | 
| 28 | 
            -
                protected classRef: { new (): T },
         | 
| 30 | 
            +
                protected classRef: { new (data?: Record<string, unknown>): T },
         | 
| 29 31 | 
             
              ) {
         | 
| 30 32 | 
             
                this.tableName = `"${tableName}"`;
         | 
| 31 33 |  | 
| 32 34 | 
             
                this.modelPropertyToSqlColumn = mapping;
         | 
| 35 | 
            +
             | 
| 33 36 | 
             
                this.sqlColumnToModelProperty = Object.entries(mapping).reduce((prev, curr) => {
         | 
| 34 | 
            -
                  const [modelProp, columnName] = curr as [ | 
| 37 | 
            +
                  const [modelProp, columnName] = curr as [string, string];
         | 
| 35 38 | 
             
                  prev[columnName] = modelProp;
         | 
| 36 39 | 
             
                  return prev;
         | 
| 37 | 
            -
                }, {} as { [key: string]:  | 
| 40 | 
            +
                }, {} as { [key: string]: string });
         | 
| 38 41 | 
             
              }
         | 
| 39 42 |  | 
| 40 43 | 
             
              protected async getConnection(): Promise<PoolClient> {
         | 
| @@ -131,13 +134,14 @@ export abstract class AbstractRepository<T> implements Reader<T>, Writer<T> { | |
| 131 134 | 
             
              }
         | 
| 132 135 |  | 
| 133 136 | 
             
              protected createAndHydrateModel(row: any): T {
         | 
| 134 | 
            -
                const  | 
| 137 | 
            +
                const inputData: Record<string, unknown> = {};
         | 
| 135 138 |  | 
| 136 139 | 
             
                for (const key of Object.keys(row)) {
         | 
| 137 | 
            -
                   | 
| 140 | 
            +
                  const translatedKey = this.sqlColumnToModelProperty[key];
         | 
| 141 | 
            +
                  inputData[translatedKey] = row[key];
         | 
| 138 142 | 
             
                }
         | 
| 139 143 |  | 
| 140 | 
            -
                return  | 
| 144 | 
            +
                return new this.classRef(inputData);
         | 
| 141 145 | 
             
              }
         | 
| 142 146 |  | 
| 143 147 | 
             
              async findOne(item: Partial<T>): Promise<T | undefined> {
         | 
    
        package/src/Migrator.ts
    CHANGED
    
    | @@ -1,11 +1,15 @@ | |
| 1 1 | 
             
            import fs from 'fs/promises';
         | 
| 2 2 | 
             
            import { PoolClient } from 'pg';
         | 
| 3 3 | 
             
            import path from 'path';
         | 
| 4 | 
            +
            import os from 'os';
         | 
| 5 | 
            +
            import { getLogger } from '@squiz/dx-logger-lib';
         | 
| 4 6 |  | 
| 5 7 | 
             
            // Be carful about changing this value. This needs to be consistent across deployments
         | 
| 6 8 | 
             
            // this ID is used to signal other running instances that a migration is executing.
         | 
| 7 9 | 
             
            const MIGRATION_ADVISORY_LOCK = 4569465;
         | 
| 8 10 |  | 
| 11 | 
            +
            const logger = getLogger({ name: 'db-migrator', meta: { pid: process.pid, hostname: os.hostname() } });
         | 
| 12 | 
            +
             | 
| 9 13 | 
             
            export class Migrator {
         | 
| 10 14 | 
             
              constructor(protected migrationDir: string, protected migrationList: string[], protected pool: PoolClient) {}
         | 
| 11 15 |  | 
| @@ -25,15 +29,15 @@ export class Migrator { | |
| 25 29 | 
             
              protected async applyMigration(migration: string, sql: string) {
         | 
| 26 30 | 
             
                try {
         | 
| 27 31 | 
             
                  const result = await this.pool.query(sql);
         | 
| 28 | 
            -
                   | 
| 32 | 
            +
                  logger.info('Applying ' + migration);
         | 
| 29 33 |  | 
| 30 34 | 
             
                  if (result.rowCount !== undefined) {
         | 
| 31 | 
            -
                     | 
| 35 | 
            +
                    logger.info('affected rows', result.rowCount);
         | 
| 32 36 | 
             
                  }
         | 
| 33 37 |  | 
| 34 38 | 
             
                  await this.pool.query('insert into __migrations__ (id) values ($1)', [migration]);
         | 
| 35 39 | 
             
                } catch (e) {
         | 
| 36 | 
            -
                   | 
| 40 | 
            +
                  logger.info('error occurred running migration', migration, e);
         | 
| 37 41 | 
             
                  throw e;
         | 
| 38 42 | 
             
                }
         | 
| 39 43 | 
             
              }
         | 
| @@ -79,18 +83,18 @@ export class Migrator { | |
| 79 83 | 
             
                  const lockObtained = await this.tryToObtainLock();
         | 
| 80 84 |  | 
| 81 85 | 
             
                  if (lockObtained === false) {
         | 
| 82 | 
            -
                     | 
| 86 | 
            +
                    logger.info('migration already running');
         | 
| 83 87 | 
             
                    await sleep(500);
         | 
| 84 88 | 
             
                    return await this.migrate();
         | 
| 85 89 | 
             
                  }
         | 
| 86 90 |  | 
| 87 91 | 
             
                  await this.runMigrations();
         | 
| 88 | 
            -
                   | 
| 92 | 
            +
                  logger.info('completed migration');
         | 
| 89 93 | 
             
                  await this.releaseLock();
         | 
| 90 94 |  | 
| 91 95 | 
             
                  this.dispose();
         | 
| 92 96 | 
             
                } catch (e) {
         | 
| 93 | 
            -
                   | 
| 97 | 
            +
                  logger.info('migration failed releasing lock');
         | 
| 94 98 | 
             
                  await this.releaseLock();
         | 
| 95 99 | 
             
                  throw e;
         | 
| 96 100 | 
             
                }
         | 
| @@ -101,11 +105,11 @@ export class Migrator { | |
| 101 105 | 
             
                const pending = await this.getPending(this.migrationList, appliedMigrations);
         | 
| 102 106 |  | 
| 103 107 | 
             
                if (pending.length === 0) {
         | 
| 104 | 
            -
                   | 
| 108 | 
            +
                  logger.info('No pending migrations');
         | 
| 105 109 | 
             
                  return;
         | 
| 106 110 | 
             
                }
         | 
| 107 111 |  | 
| 108 | 
            -
                 | 
| 112 | 
            +
                logger.info('Pending migrations:\n\t', pending.join('\n\t'));
         | 
| 109 113 |  | 
| 110 114 | 
             
                for (const migration of pending) {
         | 
| 111 115 | 
             
                  await this.runMigration(migration);
         | 
| @@ -121,7 +125,7 @@ export class Migrator { | |
| 121 125 |  | 
| 122 126 | 
             
                  await this.pool.query('COMMIT');
         | 
| 123 127 | 
             
                } catch (e) {
         | 
| 124 | 
            -
                   | 
| 128 | 
            +
                  logger.error('migration failed', migration, e);
         | 
| 125 129 | 
             
                  await this.pool.query('ROLLBACK');
         | 
| 126 130 | 
             
                  throw e;
         | 
| 127 131 | 
             
                }
         | 
| @@ -0,0 +1,270 @@ | |
| 1 | 
            +
            // See https://github.com/postgres/postgres/blob/master/src/backend/utils/errcodes.txt
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            export enum PostgresErrorCode {
         | 
| 4 | 
            +
              SUCCESSFUL_COMPLETION = '00000',
         | 
| 5 | 
            +
              WARNING = '01000',
         | 
| 6 | 
            +
              WARNING_DYNAMIC_RESULT_SETS_RETURNED = '0100C',
         | 
| 7 | 
            +
              WARNING_IMPLICIT_ZERO_BIT_PADDING = '01008',
         | 
| 8 | 
            +
              WARNING_NULL_VALUE_ELIMINATED_IN_SET_FUNCTION = '01003',
         | 
| 9 | 
            +
              WARNING_PRIVILEGE_NOT_GRANTED = '01007',
         | 
| 10 | 
            +
              WARNING_PRIVILEGE_NOT_REVOKED = '01006',
         | 
| 11 | 
            +
              WARNING_STRING_DATA_RIGHT_TRUNCATION = '01004',
         | 
| 12 | 
            +
              WARNING_DEPRECATED_FEATURE = '01P01',
         | 
| 13 | 
            +
              NO_DATA = '02000',
         | 
| 14 | 
            +
              NO_ADDITIONAL_DYNAMIC_RESULT_SETS_RETURNED = '02001',
         | 
| 15 | 
            +
              SQL_STATEMENT_NOT_YET_COMPLETE = '03000',
         | 
| 16 | 
            +
              CONNECTION_EXCEPTION = '08000',
         | 
| 17 | 
            +
              CONNECTION_DOES_NOT_EXIST = '08003',
         | 
| 18 | 
            +
              CONNECTION_FAILURE = '08006',
         | 
| 19 | 
            +
              SQLCLIENT_UNABLE_TO_ESTABLISH_SQLCONNECTION = '08001',
         | 
| 20 | 
            +
              SQLSERVER_REJECTED_ESTABLISHMENT_OF_SQLCONNECTION = '08004',
         | 
| 21 | 
            +
              TRANSACTION_RESOLUTION_UNKNOWN = '08007',
         | 
| 22 | 
            +
              PROTOCOL_VIOLATION = '08P01',
         | 
| 23 | 
            +
              TRIGGERED_ACTION_EXCEPTION = '09000',
         | 
| 24 | 
            +
              FEATURE_NOT_SUPPORTED = '0A000',
         | 
| 25 | 
            +
              INVALID_TRANSACTION_INITIATION = '0B000',
         | 
| 26 | 
            +
              LOCATOR_EXCEPTION = '0F000',
         | 
| 27 | 
            +
              L_E_INVALID_SPECIFICATION = '0F001',
         | 
| 28 | 
            +
              INVALID_GRANTOR = '0L000',
         | 
| 29 | 
            +
              INVALID_GRANT_OPERATION = '0LP01',
         | 
| 30 | 
            +
              INVALID_ROLE_SPECIFICATION = '0P000',
         | 
| 31 | 
            +
              DIAGNOSTICS_EXCEPTION = '0Z000',
         | 
| 32 | 
            +
              STACKED_DIAGNOSTICS_ACCESSED_WITHOUT_ACTIVE_HANDLER = '0Z002',
         | 
| 33 | 
            +
              CASE_NOT_FOUND = '20000',
         | 
| 34 | 
            +
              CARDINALITY_VIOLATION = '21000',
         | 
| 35 | 
            +
              DATA_EXCEPTION = '22000',
         | 
| 36 | 
            +
              ARRAY_ELEMENT_ERROR = '2202E',
         | 
| 37 | 
            +
              ARRAY_SUBSCRIPT_ERROR = '2202E',
         | 
| 38 | 
            +
              CHARACTER_NOT_IN_REPERTOIRE = '22021',
         | 
| 39 | 
            +
              DATETIME_FIELD_OVERFLOW = '22008',
         | 
| 40 | 
            +
              DATETIME_VALUE_OUT_OF_RANGE = '22008',
         | 
| 41 | 
            +
              DIVISION_BY_ZERO = '22012',
         | 
| 42 | 
            +
              ERROR_IN_ASSIGNMENT = '22005',
         | 
| 43 | 
            +
              ESCAPE_CHARACTER_CONFLICT = '2200B',
         | 
| 44 | 
            +
              INDICATOR_OVERFLOW = '22022',
         | 
| 45 | 
            +
              INTERVAL_FIELD_OVERFLOW = '22015',
         | 
| 46 | 
            +
              INVALID_ARGUMENT_FOR_LOG = '2201E',
         | 
| 47 | 
            +
              INVALID_ARGUMENT_FOR_NTILE = '22014',
         | 
| 48 | 
            +
              INVALID_ARGUMENT_FOR_NTH_VALUE = '22016',
         | 
| 49 | 
            +
              INVALID_ARGUMENT_FOR_POWER_FUNCTION = '2201F',
         | 
| 50 | 
            +
              INVALID_ARGUMENT_FOR_WIDTH_BUCKET_FUNCTION = '2201G',
         | 
| 51 | 
            +
              INVALID_CHARACTER_VALUE_FOR_CAST = '22018',
         | 
| 52 | 
            +
              INVALID_DATETIME_FORMAT = '22007',
         | 
| 53 | 
            +
              INVALID_ESCAPE_CHARACTER = '22019',
         | 
| 54 | 
            +
              INVALID_ESCAPE_OCTET = '2200D',
         | 
| 55 | 
            +
              INVALID_ESCAPE_SEQUENCE = '22025',
         | 
| 56 | 
            +
              NONSTANDARD_USE_OF_ESCAPE_CHARACTER = '22P06',
         | 
| 57 | 
            +
              INVALID_INDICATOR_PARAMETER_VALUE = '22010',
         | 
| 58 | 
            +
              INVALID_PARAMETER_VALUE = '22023',
         | 
| 59 | 
            +
              INVALID_PRECEDING_OR_FOLLOWING_SIZE = '22013',
         | 
| 60 | 
            +
              INVALID_REGULAR_EXPRESSION = '2201B',
         | 
| 61 | 
            +
              INVALID_ROW_COUNT_IN_LIMIT_CLAUSE = '2201W',
         | 
| 62 | 
            +
              INVALID_ROW_COUNT_IN_RESULT_OFFSET_CLAUSE = '2201X',
         | 
| 63 | 
            +
              INVALID_TABLESAMPLE_ARGUMENT = '2202H',
         | 
| 64 | 
            +
              INVALID_TABLESAMPLE_REPEAT = '2202G',
         | 
| 65 | 
            +
              INVALID_TIME_ZONE_DISPLACEMENT_VALUE = '22009',
         | 
| 66 | 
            +
              INVALID_USE_OF_ESCAPE_CHARACTER = '2200C',
         | 
| 67 | 
            +
              MOST_SPECIFIC_TYPE_MISMATCH = '2200G',
         | 
| 68 | 
            +
              NULL_VALUE_NOT_ALLOWED = '22004',
         | 
| 69 | 
            +
              NULL_VALUE_NO_INDICATOR_PARAMETER = '22002',
         | 
| 70 | 
            +
              NUMERIC_VALUE_OUT_OF_RANGE = '22003',
         | 
| 71 | 
            +
              SEQUENCE_GENERATOR_LIMIT_EXCEEDED = '2200H',
         | 
| 72 | 
            +
              STRING_DATA_LENGTH_MISMATCH = '22026',
         | 
| 73 | 
            +
              STRING_DATA_RIGHT_TRUNCATION = '22001',
         | 
| 74 | 
            +
              SUBSTRING_ERROR = '22011',
         | 
| 75 | 
            +
              TRIM_ERROR = '22027',
         | 
| 76 | 
            +
              UNTERMINATED_C_STRING = '22024',
         | 
| 77 | 
            +
              ZERO_LENGTH_CHARACTER_STRING = '2200F',
         | 
| 78 | 
            +
              FLOATING_POINT_EXCEPTION = '22P01',
         | 
| 79 | 
            +
              INVALID_TEXT_REPRESENTATION = '22P02',
         | 
| 80 | 
            +
              INVALID_BINARY_REPRESENTATION = '22P03',
         | 
| 81 | 
            +
              BAD_COPY_FILE_FORMAT = '22P04',
         | 
| 82 | 
            +
              UNTRANSLATABLE_CHARACTER = '22P05',
         | 
| 83 | 
            +
              NOT_AN_XML_DOCUMENT = '2200L',
         | 
| 84 | 
            +
              INVALID_XML_DOCUMENT = '2200M',
         | 
| 85 | 
            +
              INVALID_XML_CONTENT = '2200N',
         | 
| 86 | 
            +
              INVALID_XML_COMMENT = '2200S',
         | 
| 87 | 
            +
              INVALID_XML_PROCESSING_INSTRUCTION = '2200T',
         | 
| 88 | 
            +
              DUPLICATE_JSON_OBJECT_KEY_VALUE = '22030',
         | 
| 89 | 
            +
              INVALID_ARGUMENT_FOR_SQL_JSON_DATETIME_FUNCTION = '22031',
         | 
| 90 | 
            +
              INVALID_JSON_TEXT = '22032',
         | 
| 91 | 
            +
              INVALID_SQL_JSON_SUBSCRIPT = '22033',
         | 
| 92 | 
            +
              MORE_THAN_ONE_SQL_JSON_ITEM = '22034',
         | 
| 93 | 
            +
              NO_SQL_JSON_ITEM = '22035',
         | 
| 94 | 
            +
              NON_NUMERIC_SQL_JSON_ITEM = '22036',
         | 
| 95 | 
            +
              NON_UNIQUE_KEYS_IN_A_JSON_OBJECT = '22037',
         | 
| 96 | 
            +
              SINGLETON_SQL_JSON_ITEM_REQUIRED = '22038',
         | 
| 97 | 
            +
              SQL_JSON_ARRAY_NOT_FOUND = '22039',
         | 
| 98 | 
            +
              SQL_JSON_MEMBER_NOT_FOUND = '2203A',
         | 
| 99 | 
            +
              SQL_JSON_NUMBER_NOT_FOUND = '2203B',
         | 
| 100 | 
            +
              SQL_JSON_OBJECT_NOT_FOUND = '2203C',
         | 
| 101 | 
            +
              TOO_MANY_JSON_ARRAY_ELEMENTS = '2203D',
         | 
| 102 | 
            +
              TOO_MANY_JSON_OBJECT_MEMBERS = '2203E',
         | 
| 103 | 
            +
              SQL_JSON_SCALAR_REQUIRED = '2203F',
         | 
| 104 | 
            +
              SQL_JSON_ITEM_CANNOT_BE_CAST_TO_TARGET_TYPE = '2203G',
         | 
| 105 | 
            +
              INTEGRITY_CONSTRAINT_VIOLATION = '23000',
         | 
| 106 | 
            +
              RESTRICT_VIOLATION = '23001',
         | 
| 107 | 
            +
              NOT_NULL_VIOLATION = '23502',
         | 
| 108 | 
            +
              FOREIGN_KEY_VIOLATION = '23503',
         | 
| 109 | 
            +
              UNIQUE_VIOLATION = '23505',
         | 
| 110 | 
            +
              CHECK_VIOLATION = '23514',
         | 
| 111 | 
            +
              EXCLUSION_VIOLATION = '23P01',
         | 
| 112 | 
            +
              INVALID_CURSOR_STATE = '24000',
         | 
| 113 | 
            +
              INVALID_TRANSACTION_STATE = '25000',
         | 
| 114 | 
            +
              ACTIVE_SQL_TRANSACTION = '25001',
         | 
| 115 | 
            +
              BRANCH_TRANSACTION_ALREADY_ACTIVE = '25002',
         | 
| 116 | 
            +
              HELD_CURSOR_REQUIRES_SAME_ISOLATION_LEVEL = '25008',
         | 
| 117 | 
            +
              INAPPROPRIATE_ACCESS_MODE_FOR_BRANCH_TRANSACTION = '25003',
         | 
| 118 | 
            +
              INAPPROPRIATE_ISOLATION_LEVEL_FOR_BRANCH_TRANSACTION = '25004',
         | 
| 119 | 
            +
              NO_ACTIVE_SQL_TRANSACTION_FOR_BRANCH_TRANSACTION = '25005',
         | 
| 120 | 
            +
              READ_ONLY_SQL_TRANSACTION = '25006',
         | 
| 121 | 
            +
              SCHEMA_AND_DATA_STATEMENT_MIXING_NOT_SUPPORTED = '25007',
         | 
| 122 | 
            +
              NO_ACTIVE_SQL_TRANSACTION = '25P01',
         | 
| 123 | 
            +
              IN_FAILED_SQL_TRANSACTION = '25P02',
         | 
| 124 | 
            +
              IDLE_IN_TRANSACTION_SESSION_TIMEOUT = '25P03',
         | 
| 125 | 
            +
              INVALID_SQL_STATEMENT_NAME = '26000',
         | 
| 126 | 
            +
              TRIGGERED_DATA_CHANGE_VIOLATION = '27000',
         | 
| 127 | 
            +
              INVALID_AUTHORIZATION_SPECIFICATION = '28000',
         | 
| 128 | 
            +
              INVALID_PASSWORD = '28P01',
         | 
| 129 | 
            +
              DEPENDENT_PRIVILEGE_DESCRIPTORS_STILL_EXIST = '2B000',
         | 
| 130 | 
            +
              DEPENDENT_OBJECTS_STILL_EXIST = '2BP01',
         | 
| 131 | 
            +
              INVALID_TRANSACTION_TERMINATION = '2D000',
         | 
| 132 | 
            +
              SQL_ROUTINE_EXCEPTION = '2F000',
         | 
| 133 | 
            +
              S_R_E_FUNCTION_EXECUTED_NO_RETURN_STATEMENT = '2F005',
         | 
| 134 | 
            +
              S_R_E_MODIFYING_SQL_DATA_NOT_PERMITTED = '2F002',
         | 
| 135 | 
            +
              S_R_E_PROHIBITED_SQL_STATEMENT_ATTEMPTED = '2F003',
         | 
| 136 | 
            +
              S_R_E_READING_SQL_DATA_NOT_PERMITTED = '2F004',
         | 
| 137 | 
            +
              INVALID_CURSOR_NAME = '34000',
         | 
| 138 | 
            +
              EXTERNAL_ROUTINE_EXCEPTION = '38000',
         | 
| 139 | 
            +
              E_R_E_CONTAINING_SQL_NOT_PERMITTED = '38001',
         | 
| 140 | 
            +
              E_R_E_MODIFYING_SQL_DATA_NOT_PERMITTED = '38002',
         | 
| 141 | 
            +
              E_R_E_PROHIBITED_SQL_STATEMENT_ATTEMPTED = '38003',
         | 
| 142 | 
            +
              E_R_E_READING_SQL_DATA_NOT_PERMITTED = '38004',
         | 
| 143 | 
            +
              EXTERNAL_ROUTINE_INVOCATION_EXCEPTION = '39000',
         | 
| 144 | 
            +
              E_R_I_E_INVALID_SQLSTATE_RETURNED = '39001',
         | 
| 145 | 
            +
              E_R_I_E_NULL_VALUE_NOT_ALLOWED = '39004',
         | 
| 146 | 
            +
              E_R_I_E_TRIGGER_PROTOCOL_VIOLATED = '39P01',
         | 
| 147 | 
            +
              E_R_I_E_SRF_PROTOCOL_VIOLATED = '39P02',
         | 
| 148 | 
            +
              E_R_I_E_EVENT_TRIGGER_PROTOCOL_VIOLATED = '39P03',
         | 
| 149 | 
            +
              SAVEPOINT_EXCEPTION = '3B000',
         | 
| 150 | 
            +
              S_E_INVALID_SPECIFICATION = '3B001',
         | 
| 151 | 
            +
              INVALID_CATALOG_NAME = '3D000',
         | 
| 152 | 
            +
              INVALID_SCHEMA_NAME = '3F000',
         | 
| 153 | 
            +
              TRANSACTION_ROLLBACK = '40000',
         | 
| 154 | 
            +
              T_R_INTEGRITY_CONSTRAINT_VIOLATION = '40002',
         | 
| 155 | 
            +
              T_R_SERIALIZATION_FAILURE = '40001',
         | 
| 156 | 
            +
              T_R_STATEMENT_COMPLETION_UNKNOWN = '40003',
         | 
| 157 | 
            +
              T_R_DEADLOCK_DETECTED = '40P01',
         | 
| 158 | 
            +
              SYNTAX_ERROR_OR_ACCESS_RULE_VIOLATION = '42000',
         | 
| 159 | 
            +
              SYNTAX_ERROR = '42601',
         | 
| 160 | 
            +
              INSUFFICIENT_PRIVILEGE = '42501',
         | 
| 161 | 
            +
              CANNOT_COERCE = '42846',
         | 
| 162 | 
            +
              GROUPING_ERROR = '42803',
         | 
| 163 | 
            +
              WINDOWING_ERROR = '42P20',
         | 
| 164 | 
            +
              INVALID_RECURSION = '42P19',
         | 
| 165 | 
            +
              INVALID_FOREIGN_KEY = '42830',
         | 
| 166 | 
            +
              INVALID_NAME = '42602',
         | 
| 167 | 
            +
              NAME_TOO_LONG = '42622',
         | 
| 168 | 
            +
              RESERVED_NAME = '42939',
         | 
| 169 | 
            +
              DATATYPE_MISMATCH = '42804',
         | 
| 170 | 
            +
              INDETERMINATE_DATATYPE = '42P18',
         | 
| 171 | 
            +
              COLLATION_MISMATCH = '42P21',
         | 
| 172 | 
            +
              INDETERMINATE_COLLATION = '42P22',
         | 
| 173 | 
            +
              WRONG_OBJECT_TYPE = '42809',
         | 
| 174 | 
            +
              GENERATED_ALWAYS = '428C9',
         | 
| 175 | 
            +
              UNDEFINED_COLUMN = '42703',
         | 
| 176 | 
            +
              UNDEFINED_CURSOR = '34000',
         | 
| 177 | 
            +
              UNDEFINED_DATABASE = '3D000',
         | 
| 178 | 
            +
              UNDEFINED_FUNCTION = '42883',
         | 
| 179 | 
            +
              UNDEFINED_PSTATEMENT = '26000',
         | 
| 180 | 
            +
              UNDEFINED_SCHEMA = '3F000',
         | 
| 181 | 
            +
              UNDEFINED_TABLE = '42P01',
         | 
| 182 | 
            +
              UNDEFINED_PARAMETER = '42P02',
         | 
| 183 | 
            +
              UNDEFINED_OBJECT = '42704',
         | 
| 184 | 
            +
              DUPLICATE_COLUMN = '42701',
         | 
| 185 | 
            +
              DUPLICATE_CURSOR = '42P03',
         | 
| 186 | 
            +
              DUPLICATE_DATABASE = '42P04',
         | 
| 187 | 
            +
              DUPLICATE_FUNCTION = '42723',
         | 
| 188 | 
            +
              DUPLICATE_PSTATEMENT = '42P05',
         | 
| 189 | 
            +
              DUPLICATE_SCHEMA = '42P06',
         | 
| 190 | 
            +
              DUPLICATE_TABLE = '42P07',
         | 
| 191 | 
            +
              DUPLICATE_ALIAS = '42712',
         | 
| 192 | 
            +
              DUPLICATE_OBJECT = '42710',
         | 
| 193 | 
            +
              AMBIGUOUS_COLUMN = '42702',
         | 
| 194 | 
            +
              AMBIGUOUS_FUNCTION = '42725',
         | 
| 195 | 
            +
              AMBIGUOUS_PARAMETER = '42P08',
         | 
| 196 | 
            +
              AMBIGUOUS_ALIAS = '42P09',
         | 
| 197 | 
            +
              INVALID_COLUMN_REFERENCE = '42P10',
         | 
| 198 | 
            +
              INVALID_COLUMN_DEFINITION = '42611',
         | 
| 199 | 
            +
              INVALID_CURSOR_DEFINITION = '42P11',
         | 
| 200 | 
            +
              INVALID_DATABASE_DEFINITION = '42P12',
         | 
| 201 | 
            +
              INVALID_FUNCTION_DEFINITION = '42P13',
         | 
| 202 | 
            +
              INVALID_PSTATEMENT_DEFINITION = '42P14',
         | 
| 203 | 
            +
              INVALID_SCHEMA_DEFINITION = '42P15',
         | 
| 204 | 
            +
              INVALID_TABLE_DEFINITION = '42P16',
         | 
| 205 | 
            +
              INVALID_OBJECT_DEFINITION = '42P17',
         | 
| 206 | 
            +
              WITH_CHECK_OPTION_VIOLATION = '44000',
         | 
| 207 | 
            +
              INSUFFICIENT_RESOURCES = '53000',
         | 
| 208 | 
            +
              DISK_FULL = '53100',
         | 
| 209 | 
            +
              OUT_OF_MEMORY = '53200',
         | 
| 210 | 
            +
              TOO_MANY_CONNECTIONS = '53300',
         | 
| 211 | 
            +
              CONFIGURATION_LIMIT_EXCEEDED = '53400',
         | 
| 212 | 
            +
              PROGRAM_LIMIT_EXCEEDED = '54000',
         | 
| 213 | 
            +
              STATEMENT_TOO_COMPLEX = '54001',
         | 
| 214 | 
            +
              TOO_MANY_COLUMNS = '54011',
         | 
| 215 | 
            +
              TOO_MANY_ARGUMENTS = '54023',
         | 
| 216 | 
            +
              OBJECT_NOT_IN_PREREQUISITE_STATE = '55000',
         | 
| 217 | 
            +
              OBJECT_IN_USE = '55006',
         | 
| 218 | 
            +
              CANT_CHANGE_RUNTIME_PARAM = '55P02',
         | 
| 219 | 
            +
              LOCK_NOT_AVAILABLE = '55P03',
         | 
| 220 | 
            +
              UNSAFE_NEW_ENUM_VALUE_USAGE = '55P04',
         | 
| 221 | 
            +
              OPERATOR_INTERVENTION = '57000',
         | 
| 222 | 
            +
              QUERY_CANCELED = '57014',
         | 
| 223 | 
            +
              ADMIN_SHUTDOWN = '57P01',
         | 
| 224 | 
            +
              CRASH_SHUTDOWN = '57P02',
         | 
| 225 | 
            +
              CANNOT_CONNECT_NOW = '57P03',
         | 
| 226 | 
            +
              DATABASE_DROPPED = '57P04',
         | 
| 227 | 
            +
              IDLE_SESSION_TIMEOUT = '57P05',
         | 
| 228 | 
            +
              SYSTEM_ERROR = '58000',
         | 
| 229 | 
            +
              IO_ERROR = '58030',
         | 
| 230 | 
            +
              UNDEFINED_FILE = '58P01',
         | 
| 231 | 
            +
              DUPLICATE_FILE = '58P02',
         | 
| 232 | 
            +
              SNAPSHOT_TOO_OLD = '72000',
         | 
| 233 | 
            +
              CONFIG_FILE_ERROR = 'F0000',
         | 
| 234 | 
            +
              LOCK_FILE_EXISTS = 'F0001',
         | 
| 235 | 
            +
              FDW_ERROR = 'HV000',
         | 
| 236 | 
            +
              FDW_COLUMN_NAME_NOT_FOUND = 'HV005',
         | 
| 237 | 
            +
              FDW_DYNAMIC_PARAMETER_VALUE_NEEDED = 'HV002',
         | 
| 238 | 
            +
              FDW_FUNCTION_SEQUENCE_ERROR = 'HV010',
         | 
| 239 | 
            +
              FDW_INCONSISTENT_DESCRIPTOR_INFORMATION = 'HV021',
         | 
| 240 | 
            +
              FDW_INVALID_ATTRIBUTE_VALUE = 'HV024',
         | 
| 241 | 
            +
              FDW_INVALID_COLUMN_NAME = 'HV007',
         | 
| 242 | 
            +
              FDW_INVALID_COLUMN_NUMBER = 'HV008',
         | 
| 243 | 
            +
              FDW_INVALID_DATA_TYPE = 'HV004',
         | 
| 244 | 
            +
              FDW_INVALID_DATA_TYPE_DESCRIPTORS = 'HV006',
         | 
| 245 | 
            +
              FDW_INVALID_DESCRIPTOR_FIELD_IDENTIFIER = 'HV091',
         | 
| 246 | 
            +
              FDW_INVALID_HANDLE = 'HV00B',
         | 
| 247 | 
            +
              FDW_INVALID_OPTION_INDEX = 'HV00C',
         | 
| 248 | 
            +
              FDW_INVALID_OPTION_NAME = 'HV00D',
         | 
| 249 | 
            +
              FDW_INVALID_STRING_LENGTH_OR_BUFFER_LENGTH = 'HV090',
         | 
| 250 | 
            +
              FDW_INVALID_STRING_FORMAT = 'HV00A',
         | 
| 251 | 
            +
              FDW_INVALID_USE_OF_NULL_POINTER = 'HV009',
         | 
| 252 | 
            +
              FDW_TOO_MANY_HANDLES = 'HV014',
         | 
| 253 | 
            +
              FDW_OUT_OF_MEMORY = 'HV001',
         | 
| 254 | 
            +
              FDW_NO_SCHEMAS = 'HV00P',
         | 
| 255 | 
            +
              FDW_OPTION_NAME_NOT_FOUND = 'HV00J',
         | 
| 256 | 
            +
              FDW_REPLY_HANDLE = 'HV00K',
         | 
| 257 | 
            +
              FDW_SCHEMA_NOT_FOUND = 'HV00Q',
         | 
| 258 | 
            +
              FDW_TABLE_NOT_FOUND = 'HV00R',
         | 
| 259 | 
            +
              FDW_UNABLE_TO_CREATE_EXECUTION = 'HV00L',
         | 
| 260 | 
            +
              FDW_UNABLE_TO_CREATE_REPLY = 'HV00M',
         | 
| 261 | 
            +
              FDW_UNABLE_TO_ESTABLISH_CONNECTION = 'HV00N',
         | 
| 262 | 
            +
              PLPGSQL_ERROR = 'P0000',
         | 
| 263 | 
            +
              RAISE_EXCEPTION = 'P0001',
         | 
| 264 | 
            +
              NO_DATA_FOUND = 'P0002',
         | 
| 265 | 
            +
              TOO_MANY_ROWS = 'P0003',
         | 
| 266 | 
            +
              ASSERT_FAILURE = 'P0004',
         | 
| 267 | 
            +
              INTERNAL_ERROR = 'XX000',
         | 
| 268 | 
            +
              DATA_CORRUPTED = 'XX001',
         | 
| 269 | 
            +
              INDEX_CORRUPTED = 'XX002',
         | 
| 270 | 
            +
            }
         | 
| @@ -0,0 +1,18 @@ | |
| 1 | 
            +
            import { assertAssign } from './assertAssign';
         | 
| 2 | 
            +
            import { assertIsString } from './assertIsString';
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            describe('assertAssign', () => {
         | 
| 5 | 
            +
              it('should assert the input meets an assertion function and return if valid', () => {
         | 
| 6 | 
            +
                expect(assertAssign('123', assertIsString)).toEqual('123');
         | 
| 7 | 
            +
              });
         | 
| 8 | 
            +
             | 
| 9 | 
            +
              it('should assert the input meets an assertion function and throw if not valid', () => {
         | 
| 10 | 
            +
                expect(() => assertAssign(123, assertIsString)).toThrowErrorMatchingInlineSnapshot(`"value is not a string"`);
         | 
| 11 | 
            +
              });
         | 
| 12 | 
            +
             | 
| 13 | 
            +
              it('should allow custom error message', () => {
         | 
| 14 | 
            +
                expect(() => assertAssign(123, assertIsString, 'custom error')).toThrowErrorMatchingInlineSnapshot(
         | 
| 15 | 
            +
                  `"custom error"`,
         | 
| 16 | 
            +
                );
         | 
| 17 | 
            +
              });
         | 
| 18 | 
            +
            });
         | 
| @@ -0,0 +1,22 @@ | |
| 1 | 
            +
            import { AssertionError } from 'assert';
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            /**
         | 
| 4 | 
            +
             * Assert and return unknown value as known type
         | 
| 5 | 
            +
             */
         | 
| 6 | 
            +
            export function assertAssign<T>(
         | 
| 7 | 
            +
              value: unknown,
         | 
| 8 | 
            +
              assertionFunc: (val: unknown) => asserts val is T,
         | 
| 9 | 
            +
              errorMessage?: string,
         | 
| 10 | 
            +
            ): T {
         | 
| 11 | 
            +
              try {
         | 
| 12 | 
            +
                assertionFunc(value);
         | 
| 13 | 
            +
              } catch (e) {
         | 
| 14 | 
            +
                if (errorMessage) {
         | 
| 15 | 
            +
                  throw new AssertionError({ message: errorMessage });
         | 
| 16 | 
            +
                } else {
         | 
| 17 | 
            +
                  throw e;
         | 
| 18 | 
            +
                }
         | 
| 19 | 
            +
              }
         | 
| 20 | 
            +
             | 
| 21 | 
            +
              return value;
         | 
| 22 | 
            +
            }
         | 
| @@ -0,0 +1,31 @@ | |
| 1 | 
            +
            import { assertAssignWithDefaultUndefinedValue } from './assertAssignWithDefaultUndefinedValue';
         | 
| 2 | 
            +
            import { assertIsObject } from './assertIsObject';
         | 
| 3 | 
            +
            import { assertIsString } from './assertIsString';
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            describe('assertAssignWithDefaultUndefinedValue', () => {
         | 
| 6 | 
            +
              it('should assert the input meets an assertion function and return if valid', () => {
         | 
| 7 | 
            +
                expect(assertAssignWithDefaultUndefinedValue('123', assertIsString, 'xx')).toEqual('123');
         | 
| 8 | 
            +
              });
         | 
| 9 | 
            +
             | 
| 10 | 
            +
              it('should return default value if input is undefined', () => {
         | 
| 11 | 
            +
                expect(assertAssignWithDefaultUndefinedValue(undefined, assertIsString, 'xx')).toEqual('xx');
         | 
| 12 | 
            +
              });
         | 
| 13 | 
            +
             | 
| 14 | 
            +
              it('should handle different types of type assertions', () => {
         | 
| 15 | 
            +
                expect(assertAssignWithDefaultUndefinedValue(undefined, assertIsObject, { default: 'hello' })).toEqual({
         | 
| 16 | 
            +
                  default: 'hello',
         | 
| 17 | 
            +
                });
         | 
| 18 | 
            +
              });
         | 
| 19 | 
            +
             | 
| 20 | 
            +
              it('should assert the input meets an assertion function and throw if not valid', () => {
         | 
| 21 | 
            +
                expect(() => assertAssignWithDefaultUndefinedValue(123, assertIsString, 'xx')).toThrowErrorMatchingInlineSnapshot(
         | 
| 22 | 
            +
                  `"value is not a string"`,
         | 
| 23 | 
            +
                );
         | 
| 24 | 
            +
              });
         | 
| 25 | 
            +
             | 
| 26 | 
            +
              it('should allow custom error message', () => {
         | 
| 27 | 
            +
                expect(() =>
         | 
| 28 | 
            +
                  assertAssignWithDefaultUndefinedValue(123, assertIsString, 'xx', 'custom error'),
         | 
| 29 | 
            +
                ).toThrowErrorMatchingInlineSnapshot(`"custom error"`);
         | 
| 30 | 
            +
              });
         | 
| 31 | 
            +
            });
         | 
| @@ -0,0 +1,17 @@ | |
| 1 | 
            +
            import { assertAssign } from './assertAssign';
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            /**
         | 
| 4 | 
            +
             * If value is undefined, return default value otherwise assert it meets assertion rule
         | 
| 5 | 
            +
             */
         | 
| 6 | 
            +
            export function assertAssignWithDefaultUndefinedValue<T>(
         | 
| 7 | 
            +
              value: unknown,
         | 
| 8 | 
            +
              assertionFunc: (val: unknown) => asserts val is T,
         | 
| 9 | 
            +
              defaultValue: T,
         | 
| 10 | 
            +
              errorMessage?: string,
         | 
| 11 | 
            +
            ): T {
         | 
| 12 | 
            +
              if (value === undefined || value === null) {
         | 
| 13 | 
            +
                return defaultValue;
         | 
| 14 | 
            +
              }
         | 
| 15 | 
            +
             | 
| 16 | 
            +
              return assertAssign(value, assertionFunc, errorMessage);
         | 
| 17 | 
            +
            }
         | 
| @@ -0,0 +1,19 @@ | |
| 1 | 
            +
            import { assertIsDefined } from './assertIsDefined';
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            describe('assertIsDefined', () => {
         | 
| 4 | 
            +
              it('should throw an assertion error if input is undefined', () => {
         | 
| 5 | 
            +
                expect(() => assertIsDefined(undefined)).toThrowErrorMatchingInlineSnapshot(
         | 
| 6 | 
            +
                  `"Expected 'val' to be defined, but received undefined"`,
         | 
| 7 | 
            +
                );
         | 
| 8 | 
            +
              });
         | 
| 9 | 
            +
             | 
| 10 | 
            +
              it('should throw an assertion error if input is null', () => {
         | 
| 11 | 
            +
                expect(() => assertIsDefined(null)).toThrowErrorMatchingInlineSnapshot(
         | 
| 12 | 
            +
                  `"Expected 'val' to be defined, but received null"`,
         | 
| 13 | 
            +
                );
         | 
| 14 | 
            +
              });
         | 
| 15 | 
            +
             | 
| 16 | 
            +
              it('should return "void" or undefined if valid', () => {
         | 
| 17 | 
            +
                expect(assertIsDefined(123)).toBeUndefined();
         | 
| 18 | 
            +
              });
         | 
| 19 | 
            +
            });
         | 
| @@ -0,0 +1,7 @@ | |
| 1 | 
            +
            import { AssertionError } from 'assert';
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            export function assertIsDefined<T>(value: T): asserts value is NonNullable<T> {
         | 
| 4 | 
            +
              if (value === undefined || value === null) {
         | 
| 5 | 
            +
                throw new AssertionError({ message: `Expected 'val' to be defined, but received ${value}` });
         | 
| 6 | 
            +
              }
         | 
| 7 | 
            +
            }
         | 
| @@ -0,0 +1,23 @@ | |
| 1 | 
            +
            import { assertIsMapOfStringString } from './assertIsMapOfStringString';
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            describe('assertIsMapOfStringString', () => {
         | 
| 4 | 
            +
              it('should not throw if input is an object with only string values', () => {
         | 
| 5 | 
            +
                expect(assertIsMapOfStringString({ prop: 'aa' })).toBeUndefined();
         | 
| 6 | 
            +
              });
         | 
| 7 | 
            +
              it('should not throw if input is an empty object', () => {
         | 
| 8 | 
            +
                expect(assertIsMapOfStringString({})).toBeUndefined();
         | 
| 9 | 
            +
              });
         | 
| 10 | 
            +
             | 
| 11 | 
            +
              it("should throw if object property isn't a string", () => {
         | 
| 12 | 
            +
                expect(() => assertIsMapOfStringString({ prop: 123 })).toThrowErrorMatchingInlineSnapshot(
         | 
| 13 | 
            +
                  `"property prop is not type of string"`,
         | 
| 14 | 
            +
                );
         | 
| 15 | 
            +
              });
         | 
| 16 | 
            +
             | 
| 17 | 
            +
              it('should throw if input is not an object', () => {
         | 
| 18 | 
            +
                expect(() => assertIsMapOfStringString(123)).toThrowErrorMatchingInlineSnapshot(`"value is not a string"`);
         | 
| 19 | 
            +
                expect(() => assertIsMapOfStringString(undefined)).toThrowErrorMatchingInlineSnapshot(
         | 
| 20 | 
            +
                  `"value cannot be null or undefined"`,
         | 
| 21 | 
            +
                );
         | 
| 22 | 
            +
              });
         | 
| 23 | 
            +
            });
         | 
| @@ -0,0 +1,29 @@ | |
| 1 | 
            +
            import { AssertionError } from 'assert';
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            export function assertIsMapOfStringString(value: unknown): asserts value is { [key: string]: string } {
         | 
| 4 | 
            +
              if (!value) {
         | 
| 5 | 
            +
                throw new AssertionError({
         | 
| 6 | 
            +
                  actual: value,
         | 
| 7 | 
            +
                  expected: 'not null',
         | 
| 8 | 
            +
                  message: 'value cannot be null or undefined',
         | 
| 9 | 
            +
                });
         | 
| 10 | 
            +
              }
         | 
| 11 | 
            +
             | 
| 12 | 
            +
              if (typeof value !== 'object') {
         | 
| 13 | 
            +
                throw new AssertionError({
         | 
| 14 | 
            +
                  actual: value,
         | 
| 15 | 
            +
                  expected: 'string',
         | 
| 16 | 
            +
                  message: 'value is not a string',
         | 
| 17 | 
            +
                });
         | 
| 18 | 
            +
              }
         | 
| 19 | 
            +
             | 
| 20 | 
            +
              for (const [key, propValue] of Object.entries(value)) {
         | 
| 21 | 
            +
                if (typeof propValue !== 'string') {
         | 
| 22 | 
            +
                  throw new AssertionError({
         | 
| 23 | 
            +
                    actual: typeof propValue,
         | 
| 24 | 
            +
                    expected: 'string',
         | 
| 25 | 
            +
                    message: `property ${key} is not type of string`,
         | 
| 26 | 
            +
                  });
         | 
| 27 | 
            +
                }
         | 
| 28 | 
            +
              }
         | 
| 29 | 
            +
            }
         | 
| @@ -0,0 +1,25 @@ | |
| 1 | 
            +
            import { assertIsNotAnEmptyString } from './assertIsNotAnEmptyString';
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            describe('assertIsNotAnEmptyString', () => {
         | 
| 4 | 
            +
              it('should throw if input value is not a string', () => {
         | 
| 5 | 
            +
                expect(() => assertIsNotAnEmptyString(null)).toThrowErrorMatchingInlineSnapshot(`"value is not a string"`);
         | 
| 6 | 
            +
                expect(() => assertIsNotAnEmptyString(undefined)).toThrowErrorMatchingInlineSnapshot(`"value is not a string"`);
         | 
| 7 | 
            +
                expect(() => assertIsNotAnEmptyString(132)).toThrowErrorMatchingInlineSnapshot(`"value is not a string"`);
         | 
| 8 | 
            +
                expect(() => assertIsNotAnEmptyString({})).toThrowErrorMatchingInlineSnapshot(`"value is not a string"`);
         | 
| 9 | 
            +
                expect(() => assertIsNotAnEmptyString(['aa'])).toThrowErrorMatchingInlineSnapshot(`"value is not a string"`);
         | 
| 10 | 
            +
              });
         | 
| 11 | 
            +
             | 
| 12 | 
            +
              it('should throw if input is empty string', () => {
         | 
| 13 | 
            +
                expect(() => assertIsNotAnEmptyString('')).toThrowErrorMatchingInlineSnapshot(`"string cannot be empty"`);
         | 
| 14 | 
            +
              });
         | 
| 15 | 
            +
             | 
| 16 | 
            +
              it('should throw if input is whitespace string', () => {
         | 
| 17 | 
            +
                expect(() => assertIsNotAnEmptyString(' ')).toThrowErrorMatchingInlineSnapshot(`"string cannot be empty"`);
         | 
| 18 | 
            +
                expect(() => assertIsNotAnEmptyString('     ')).toThrowErrorMatchingInlineSnapshot(`"string cannot be empty"`);
         | 
| 19 | 
            +
              });
         | 
| 20 | 
            +
             | 
| 21 | 
            +
              it('should not throw if string of length >= 1 is passed in', () => {
         | 
| 22 | 
            +
                expect(assertIsNotAnEmptyString('1')).toBeUndefined();
         | 
| 23 | 
            +
                expect(assertIsNotAnEmptyString('11111')).toBeUndefined();
         | 
| 24 | 
            +
              });
         | 
| 25 | 
            +
            });
         | 
| @@ -0,0 +1,17 @@ | |
| 1 | 
            +
            import { AssertionError } from 'assert';
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            export function assertIsNotAnEmptyString(val: any): asserts val is string {
         | 
| 4 | 
            +
              if (typeof val !== 'string') {
         | 
| 5 | 
            +
                throw new AssertionError({
         | 
| 6 | 
            +
                  actual: typeof val,
         | 
| 7 | 
            +
                  expected: 'string',
         | 
| 8 | 
            +
                  message: 'value is not a string',
         | 
| 9 | 
            +
                });
         | 
| 10 | 
            +
              }
         | 
| 11 | 
            +
             | 
| 12 | 
            +
              if (val.trim().length === 0) {
         | 
| 13 | 
            +
                throw new AssertionError({
         | 
| 14 | 
            +
                  message: 'string cannot be empty',
         | 
| 15 | 
            +
                });
         | 
| 16 | 
            +
              }
         | 
| 17 | 
            +
            }
         |