diff --git a/.dockerignore b/.dockerignore index b559dad1..59178063 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,6 +1,7 @@ /Dockerfile **/Dockerfile docker-compose.yml +**/docker-compose.yml .dockerignore **/node_modules npm-debug.log @@ -8,6 +9,7 @@ npm-debug.log .next .git .env +**/.env **/dist # Rush temporary files common/deploy/ @@ -16,3 +18,11 @@ common/autoinstallers/*/.npmrc **/.rush/temp/ **/*.log + +*.db +*.db-shm +*.db-wal + +**/*.db +**/*.db-shm +**/*.db-wal diff --git a/.gitignore b/.gitignore index f45fc959..1d87f53a 100644 --- a/.gitignore +++ b/.gitignore @@ -71,3 +71,6 @@ common/autoinstallers/*/.npmrc dist .vscode/ docker-compose.yml +*.db +*.db-shm +*.db-wal diff --git a/README.md b/README.md index 54c0df39..d11971ee 100644 --- a/README.md +++ b/README.md @@ -122,6 +122,166 @@ To run tests across all apps and libraries in one command, a rush script has bee $ rush test ``` +## Multiple database engines support +VC-API backend supports: +- in-memory SQLite (default) +- SQLite persisted in a file +- Postgres (needs to be started separately) + +### In-memory SQLite +**This mode is not intended to be used by multiple load balanced VC-API service instances.** + +This is the default mode of operation. The database in this mode is purged and initiated everytime process is started. +No special +steps are required when upgrading versions of the VP-API. Every instance of the VC-API uses its own instance of this +database. + +Start your local VC-API instance with the following: +```shell +$ cd apps/vc-api +$ npm run start:dev +``` + +### SQLite +**This mode is not intended to be used by multiple load balanced VC-API service instances.** + +To activate data persistence for SQLite, set the following env variables: +```dotenv +DB_TYPE=SQLITE +SQLITE_FILE= +``` + +Start the VC-API: +```shell +$ cd apps/vc-api +$ npm run start:dev +``` + +### Postgres +To use Postgres database, start your local postgres server, for example with docker and `docker-compose.full.yaml` +located in the `apps/vc-api` folder: +```shell +$ cd apps/vc-api +$ docker compose -f docker-compose.full.yaml up +``` + +Set the following env variables: +```dotenv +DB_TYPE=POSTGRES +POSTGRES_DB_HOST=127.0.0.1 +POSTGRES_DB_PORT=5432 +POSTGRES_DB_USER=postgres +POSTGRES_DB_PASSWORD=postgres +POSTGRES_DB_NAME=vc-api +``` + +Start the VC-API: +```shell +$ cd apps/vc-api +$ npm run start:dev +``` + +## Database migrations + +Having database persisted on production makes it necessary to have database schema migration process in place when +upgrading VC-API version running. Thanks to the migrations feature of TypeORM, this can be automated. + +### Executing migrations after VC-API code updated + +#### WARNING!!! + +The following settings are recommended on production. These are also default application settings if not provided: +```dotenv +# below, if set to `true`, erases all data on every application start +DB_DROP_ON_START=false +# below is intended to be set to `true` only when developing locally +DB_SYNC_SCHEMA_ON_START=false +``` + +Execution of the database schema migrations is automated, so that only required migrations are executed to upgrade the +database schema. This can be done in two ways: + +#### By the application + +A VC-API service is able to execute migrations by itself when starting. To enable this feature the following env +variable is needed: +```dotenv +DB_RUN_MIGRATIONS=true +``` + +#### With npm script + +If you decide to disable execution of migrations by application, they can be executed manually: +```shell +$ cd apps/vc-api +$ npm run migration:run +``` + +### Creating new migrations after development + +The reccommended settings for development are: +```dotenv +DB_DROP_ON_START=true +DB_SYNC_SCHEMA_ON_START=true +DB_RUN_MIGRATIONS=true +``` + +This means that database schema will be dropped on every application restart, migrations executed and all entities +changes not reflected in migrations will be synchronised to the DB schema. This allows faster development. + +After completing chunk of work, for example when preparing a pull request to be reviewed and merged, another db +schema migration needs to be created and committed. + +**Warning!** Two sets of migrations need to be added. For SQLite and Postgres. + +To create migrations, you will need to: + +1. [drop db schemas](#dropping-schemas) for both Postgres and SQLite +2. stop your application instances if running +3. ensure your `.env` file contains valid settings for both Postgres and SQLite persisted in file +4. [execute](#executing-existing-migrations) existing migrations +5. [generate](#generating-new-migration-files) migration files +6. validate migration files - this should include executing all migrations (including new ones) and E2E tests for both + database engines SQLite and Postgres +7. commit migration files + +#### Dropping schemas +1. Remove your SQLite file. By default, it should be `apps/vc-api/sqlite.db`. +2. Start your Postgres instance from scratch. If you started it with `docker compose -f docker-compose.full.yaml up` +execute the following: + ```shell + $ cd apps/vc-api + $ docker compose -f docker-compose.full.yaml down -v + ``` + `-v` means volumes are to be removed - **this is important option here** + +#### Executing existing migrations +```shell +$ npm run migration:run:pg +``` +```shell +$ npm run migration:run:sqlite +``` + +#### Generating new migration files +```shell +npm run migration:generate:pg +``` +this should add a new migration file for Postgres to the `apps/vc-api/src/migrations/pg` folder + +and +```shell +npm run migration:generate:sqlite +``` + +this should add a new migration file for SQLite to the `apps/vc-api/src/migrations/sqlite` folder + +#### Warning +Migrations are executed in order of files sorted by name. Migration files start with a timestamp, for instance +`1671212337326-initial.ts`. If you are planning to merge your PR to the base branch, keep in mind that in some +situations you will need to delete and regenerate your migrations again to keep them in order with migrations added +in meantime to the base branch. + ## Contributing Guidelines See [contributing.md](./contributing.md) diff --git a/apps/vc-api/.env.example b/apps/vc-api/.env.example new file mode 100644 index 00000000..d1efab5b --- /dev/null +++ b/apps/vc-api/.env.example @@ -0,0 +1,16 @@ +DB_TYPE=SQLITE_IN_MEMORY + +#DB_TYPE=SQLITE +SQLITE_FILE=sqlite.db + +#DB_TYPE=POSTGRES +POSTGRES_DB_HOST=127.0.0.1 +POSTGRES_DB_PORT=5432 +POSTGRES_DB_USER=postgres +POSTGRES_DB_PASSWORD=postgres +POSTGRES_DB_NAME=vc-api + +#for DB_TYPE=POSTGRES or DB_TYPE=SQLITE +DB_DROP_ON_START=false +DB_SYNC_SCHEMA_ON_START=false +DB_RUN_MIGRATIONS=true diff --git a/apps/vc-api/Dockerfile b/apps/vc-api/Dockerfile index 8c31d5bf..381cca4b 100644 --- a/apps/vc-api/Dockerfile +++ b/apps/vc-api/Dockerfile @@ -28,9 +28,15 @@ RUN cp -R ./apps/vc-api/dist ./common/deploy/apps/vc-api FROM base as final ENV NODE_ENV=production + EXPOSE 3000 COPY --from=builder /app/common/deploy /app COPY license-header.txt /app +ENV DB_TYPE=SQLITE_IN_MEMORY + +VOLUME /data +ENV SQLITE_FILE=/data/sqlite.db + CMD ["node", "apps/vc-api/dist/src/main.js"] diff --git a/apps/vc-api/docker-compose.dev.yaml b/apps/vc-api/docker-compose.dev.yaml new file mode 100644 index 00000000..6502dae9 --- /dev/null +++ b/apps/vc-api/docker-compose.dev.yaml @@ -0,0 +1,22 @@ +version: '3.8' + +services: + postgres: + image: postgres:14-alpine + restart: unless-stopped + environment: + POSTGRES_PASSWORD: $POSTGRES_DB_PASSWORD + POSTGRES_USER: $POSTGRES_DB_USER + POSTGRES_DB: $POSTGRES_DB_NAME + ports: + - '127.0.0.1:5432:5432' + volumes: + - dev-postgres-data:/var/lib/postgresql/data + networks: + main: + +networks: + main: + +volumes: + dev-postgres-data: diff --git a/apps/vc-api/package.json b/apps/vc-api/package.json index f3a27e61..f572f32a 100644 --- a/apps/vc-api/package.json +++ b/apps/vc-api/package.json @@ -22,7 +22,12 @@ "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand", "test:e2e": "jest --config ./test/jest-e2e.json", "write-openapi": "ts-node ./scripts/write-open-api-json.ts && prettier -w docs/openapi.json", - "update-openapi": "npm run write-openapi; git add docs/openapi.json" + "update-openapi": "npm run write-openapi; git add docs/openapi.json", + "migration:generate:pg": "export DB_TYPE=POSTGRES; npm run migration:run && cd src/migrations/pg && typeorm-ts-node-commonjs -d ../../config/ormconfig.ts migration:generate -p", + "migration:generate:sqlite": "export DB_TYPE=SQLITE; npm run migration:run && cd src/migrations/sqlite && typeorm-ts-node-commonjs -d ../../config/ormconfig.ts migration:generate -p", + "migration:run": "typeorm-ts-node-commonjs -d src/config/ormconfig.ts migration:run", + "migration:run:pg": "export DB_TYPE=POSTGRES; typeorm-ts-node-commonjs -d src/config/ormconfig.ts migration:run", + "migration:run:sqlite": "export DB_TYPE=SQLITE; typeorm-ts-node-commonjs -d src/config/ormconfig.ts migration:run" }, "dependencies": { "@energyweb/ssi-did": "0.0.1", @@ -49,7 +54,9 @@ "@nestjs/axios": "^3.0.0", "@nestjs/serve-static": "^4.0.0", "joi": "^17.9.2", - "axios": "~1.4.0" + "axios": "~1.4.0", + "pg": "^8.0.0", + "dotenv": "^16.3.1" }, "devDependencies": { "@nestjs/cli": "^10.1.0", diff --git a/apps/vc-api/src/app.module.ts b/apps/vc-api/src/app.module.ts index fba48bfa..2cae1740 100644 --- a/apps/vc-api/src/app.module.ts +++ b/apps/vc-api/src/app.module.ts @@ -16,15 +16,16 @@ */ import { DynamicModule, Module } from '@nestjs/common'; -import { ConfigModule } from '@nestjs/config'; +import { ConfigModule, ConfigService } from '@nestjs/config'; import { KeyModule } from './key/key.module'; import { DidModule } from './did/did.module'; import { VcApiModule } from './vc-api/vc-api.module'; -import { TypeOrmSQLiteModule } from './in-memory-db'; +import { typeOrmConfigFactory } from './config/db'; import { ServeStaticModule } from '@nestjs/serve-static'; import { join } from 'path'; import { SeederModule } from './seeder/seeder.module'; import { envVarsValidationSchema } from './config/env-vars-validation-schema'; +import { TypeOrmModule } from '@nestjs/typeorm'; let config: DynamicModule; @@ -46,7 +47,13 @@ try { @Module({ imports: [ - TypeOrmSQLiteModule(), + TypeOrmModule.forRootAsync({ + imports: [ConfigModule], + inject: [ConfigService], + useFactory: (config) => ({ + ...typeOrmConfigFactory(config) + }) + }), KeyModule, DidModule, VcApiModule, diff --git a/apps/vc-api/src/config/db.ts b/apps/vc-api/src/config/db.ts new file mode 100644 index 00000000..21e5f4f9 --- /dev/null +++ b/apps/vc-api/src/config/db.ts @@ -0,0 +1,83 @@ +/* + * Copyright 2021, 2022 Energy Web Foundation + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +import { TypeOrmModule, TypeOrmModuleOptions } from '@nestjs/typeorm'; +import { ConfigService } from '@nestjs/config'; +import { DB_TYPES } from './env-vars-validation-schema'; +import * as path from 'path'; + +/** + * Inspired by https://dev.to/webeleon/unit-testing-nestjs-with-typeorm-in-memory-l6m + */ +const inMemoryDBConfig: TypeOrmModuleOptions = { + type: 'better-sqlite3', + database: ':memory:', + dropSchema: true, + synchronize: true, + keepConnectionAlive: true // https://github.com/nestjs/typeorm/issues/61 +}; + +const commonOptions = { + autoLoadEntities: true // https://docs.nestjs.com/techniques/database#auto-load-entities +}; + +export const typeOrmConfigFactory = (config: ConfigService): TypeOrmModuleOptions => { + if (config.get('DB_TYPE') === DB_TYPES.SQLITE_IN_MEMORY) { + return { + ...inMemoryDBConfig, + ...commonOptions + }; + } + + if (config.get('DB_TYPE') === DB_TYPES.SQLITE) { + const SQLITE_FILE = config.get('SQLITE_FILE'); + if (!SQLITE_FILE) { + throw new Error(`SQLITE_FILE not set`); + } + + // this is required because migration generation is executed from the migrations subfolder + const databaseFilePath = path.isAbsolute(SQLITE_FILE) + ? SQLITE_FILE + : path.resolve(__dirname, '../..', SQLITE_FILE); + + return { + type: 'better-sqlite3', + database: databaseFilePath, + dropSchema: config.get('DB_DROP_ON_START'), + synchronize: config.get('DB_SYNC_SCHEMA_ON_START'), + migrationsRun: config.get('DB_RUN_MIGRATIONS'), + migrations: [`${path.resolve(__dirname, '../migrations/sqlite')}/*.{ts,js}`], + ...commonOptions + }; + } + + if (config.get('DB_TYPE') === DB_TYPES.POSTGRES) { + return { + type: 'postgres', + host: config.get('POSTGRES_DB_HOST'), + port: +config.get('POSTGRES_DB_PORT'), + username: config.get('POSTGRES_DB_USER'), + password: config.get('POSTGRES_DB_PASSWORD'), + database: config.get('POSTGRES_DB_NAME'), + dropSchema: config.get('DB_DROP_ON_START'), + synchronize: config.get('DB_SYNC_SCHEMA_ON_START'), + migrationsRun: config.get('DB_RUN_MIGRATIONS'), + migrations: [`${path.resolve(__dirname, '../migrations/pg')}/*.{ts,js}`], + ...commonOptions + }; + } +}; diff --git a/apps/vc-api/src/config/env-vars-validation-schema.ts b/apps/vc-api/src/config/env-vars-validation-schema.ts index 844b1cdd..c1332e90 100644 --- a/apps/vc-api/src/config/env-vars-validation-schema.ts +++ b/apps/vc-api/src/config/env-vars-validation-schema.ts @@ -17,8 +17,40 @@ import * as Joi from 'joi'; +export enum DB_TYPES { + SQLITE_IN_MEMORY = 'SQLITE_IN_MEMORY', + SQLITE = 'SQLITE', + POSTGRES = 'POSTGRES' +} + export const envVarsValidationSchema = Joi.object({ NODE_ENV: Joi.string().valid('development', 'production', 'test').default('development'), PORT: Joi.number().integer().positive().default(3000), - BASE_URL: Joi.string().uri().default('http://localhost:3000') -}); + BASE_URL: Joi.string().uri().default('http://localhost:3000'), + DB_TYPE: Joi.string() + .valid(...Object.values(DB_TYPES)) + .default(DB_TYPES.SQLITE_IN_MEMORY) +}) + .when('.DB_TYPE', { + switch: [ + { is: Joi.required().valid(DB_TYPES.SQLITE), then: { SQLITE_FILE: Joi.string().required() } }, + { + is: Joi.required().valid(DB_TYPES.POSTGRES), + then: { + POSTGRES_DB_HOST: Joi.string().hostname().required(), + POSTGRES_DB_PORT: Joi.number().port().required(), + POSTGRES_DB_USER: Joi.string().required(), + POSTGRES_DB_PASSWORD: Joi.string().required(), + POSTGRES_DB_NAME: Joi.string().required() + } + } + ] + }) + .when('.DB_TYPE', { + is: Joi.required().valid(DB_TYPES.SQLITE, DB_TYPES.POSTGRES), + then: { + DB_DROP_ON_START: Joi.boolean().default(false), + DB_SYNC_SCHEMA_ON_START: Joi.boolean().default(false), + DB_RUN_MIGRATIONS: Joi.boolean().default(true) + } + }); diff --git a/apps/vc-api/src/config/ormconfig.ts b/apps/vc-api/src/config/ormconfig.ts new file mode 100644 index 00000000..f4a889e2 --- /dev/null +++ b/apps/vc-api/src/config/ormconfig.ts @@ -0,0 +1,48 @@ +/* + * Copyright 2021, 2022 Energy Web Foundation + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +import { config } from 'dotenv'; +import * as path from 'path'; + +config({ path: path.resolve(__dirname, '../../.env') }); + +import { DataSource, DataSourceOptions } from 'typeorm'; +import { typeOrmConfigFactory } from './db'; +import * as process from 'process'; +import { ConfigService } from '@nestjs/config'; +import { envVarsValidationSchema } from './env-vars-validation-schema'; + +const entities = [path.resolve(__dirname, '../**/*.entity.ts')]; + +const validationResults = envVarsValidationSchema.validate(process.env, { + allowUnknown: true, + abortEarly: false, + stripUnknown: true +}); + +if (validationResults.error) { + console.log('env variables errors:'); + console.log(validationResults.error.details.map((e) => ` ${e.message}`).join('\n')); + console.log('\nexiting'); + process.exit(1); +} + +module.exports = { + dataSource: new DataSource({ + ...typeOrmConfigFactory({ get: (key: string, def?: string) => process.env[key] || def } as ConfigService), + entities + } as DataSourceOptions) +}; diff --git a/apps/vc-api/src/did/did.controller.spec.ts b/apps/vc-api/src/did/did.controller.spec.ts index 34c9f445..ca791b89 100644 --- a/apps/vc-api/src/did/did.controller.spec.ts +++ b/apps/vc-api/src/did/did.controller.spec.ts @@ -17,13 +17,15 @@ import { Test, TestingModule } from '@nestjs/testing'; import { TypeOrmModule } from '@nestjs/typeorm'; -import { TypeOrmSQLiteModule } from '../in-memory-db'; import { KeyModule } from '../key/key.module'; import { DIDController } from './did.controller'; import { DIDService } from './did.service'; import { DIDDocumentEntity } from './entities/did-document.entity'; import { VerificationMethodEntity } from './entities/verification-method.entity'; import { DidMethod } from './types/did-method'; +import { typeOrmConfigFactory } from '../config/db'; +import { DB_TYPES } from '../config/env-vars-validation-schema'; +import { ConfigService } from '@nestjs/config'; describe('DidController', () => { let controller: DIDController; @@ -32,7 +34,13 @@ describe('DidController', () => { const module: TestingModule = await Test.createTestingModule({ imports: [ KeyModule, - TypeOrmSQLiteModule(), + TypeOrmModule.forRoot( + typeOrmConfigFactory({ + get: (key): Record => { + return { DB_TYPE: DB_TYPES.SQLITE_IN_MEMORY }[key]; + } + } as unknown as ConfigService) + ), TypeOrmModule.forFeature([DIDDocumentEntity, VerificationMethodEntity]) ], controllers: [DIDController], diff --git a/apps/vc-api/src/did/did.service.spec.ts b/apps/vc-api/src/did/did.service.spec.ts index 98a10711..cb31ab6c 100644 --- a/apps/vc-api/src/did/did.service.spec.ts +++ b/apps/vc-api/src/did/did.service.spec.ts @@ -17,12 +17,14 @@ import { Test, TestingModule } from '@nestjs/testing'; import { TypeOrmModule } from '@nestjs/typeorm'; -import { TypeOrmSQLiteModule } from '../in-memory-db'; +import { typeOrmConfigFactory } from '../config/db'; import { KeyModule } from '../key/key.module'; import { KeyService } from '../key/key.service'; import { DIDService } from './did.service'; import { DIDDocumentEntity } from './entities/did-document.entity'; import { VerificationMethodEntity } from './entities/verification-method.entity'; +import { ConfigService } from '@nestjs/config'; +import { DB_TYPES } from '../config/env-vars-validation-schema'; describe('DIDService', () => { let service: DIDService; @@ -32,7 +34,13 @@ describe('DIDService', () => { const module: TestingModule = await Test.createTestingModule({ imports: [ KeyModule, - TypeOrmSQLiteModule(), + TypeOrmModule.forRoot( + typeOrmConfigFactory({ + get: (key): Record => { + return { DB_TYPE: DB_TYPES.SQLITE_IN_MEMORY }[key]; + } + } as unknown as ConfigService) + ), TypeOrmModule.forFeature([DIDDocumentEntity, VerificationMethodEntity]) ], providers: [DIDService] diff --git a/apps/vc-api/src/in-memory-db.ts b/apps/vc-api/src/in-memory-db.ts deleted file mode 100644 index 24016047..00000000 --- a/apps/vc-api/src/in-memory-db.ts +++ /dev/null @@ -1,31 +0,0 @@ -/** - * Copyright 2021 - 2023 Energy Web Foundation - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -import { TypeOrmModule } from '@nestjs/typeorm'; - -/** - * Inspired by https://dev.to/webeleon/unit-testing-nestjs-with-typeorm-in-memory-l6m - */ -export const TypeOrmSQLiteModule = () => - TypeOrmModule.forRoot({ - type: 'better-sqlite3', - database: ':memory:', - dropSchema: true, - autoLoadEntities: true, // https://docs.nestjs.com/techniques/database#auto-load-entities - synchronize: true, - keepConnectionAlive: true // https://github.com/nestjs/typeorm/issues/61 - }); diff --git a/apps/vc-api/src/key/key.service.spec.ts b/apps/vc-api/src/key/key.service.spec.ts index a42f286e..3b571fd7 100644 --- a/apps/vc-api/src/key/key.service.spec.ts +++ b/apps/vc-api/src/key/key.service.spec.ts @@ -18,10 +18,12 @@ import { Test, TestingModule } from '@nestjs/testing'; import { TypeOrmModule } from '@nestjs/typeorm'; import { calculateJwkThumbprint, JWK } from 'jose'; -import { TypeOrmSQLiteModule } from '../in-memory-db'; +import { typeOrmConfigFactory } from '../config/db'; import { KeyPair } from './key-pair.entity'; import { keyType } from './key-types'; import { KeyService } from './key.service'; +import { DB_TYPES } from '../config/env-vars-validation-schema'; +import { ConfigService } from '@nestjs/config'; describe('KeyService', () => { let service: KeyService; @@ -29,7 +31,16 @@ describe('KeyService', () => { beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ - imports: [TypeOrmSQLiteModule(), TypeOrmModule.forFeature([KeyPair])], + imports: [ + TypeOrmModule.forRoot( + typeOrmConfigFactory({ + get: (key): Record => { + return { DB_TYPE: DB_TYPES.SQLITE_IN_MEMORY }[key]; + } + } as unknown as ConfigService) + ), + TypeOrmModule.forFeature([KeyPair]) + ], providers: [KeyService] }).compile(); diff --git a/apps/vc-api/src/migrations/pg/1671212337326-initial.ts b/apps/vc-api/src/migrations/pg/1671212337326-initial.ts new file mode 100644 index 00000000..2490841b --- /dev/null +++ b/apps/vc-api/src/migrations/pg/1671212337326-initial.ts @@ -0,0 +1,135 @@ +import { MigrationInterface, QueryRunner } from 'typeorm'; + +export class initial1671212337326 implements MigrationInterface { + name = 'initial1671212337326'; + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query(` + CREATE TABLE "verification_method_entity" ( + "id" text NOT NULL, + "type" text NOT NULL, + "controller" text NOT NULL, + "publicKeyJwk" text NOT NULL, + "didDocId" text, + CONSTRAINT "PK_505ddb773de428509f34ec87209" PRIMARY KEY ("id") + ) + `); + await queryRunner.query(` + CREATE TABLE "did_document_entity" ( + "id" text NOT NULL, + CONSTRAINT "PK_d96048f4c93be203eeff05ef404" PRIMARY KEY ("id") + ) + `); + await queryRunner.query(` + CREATE TABLE "key_pair" ( + "publicKeyThumbprint" text NOT NULL, + "privateKey" text NOT NULL, + "publicKey" text NOT NULL, + CONSTRAINT "PK_ece1198fe2393a8c259275a85d6" PRIMARY KEY ("publicKeyThumbprint") + ) + `); + await queryRunner.query(` + CREATE TABLE "presentation_review_entity" ( + "presentationReviewId" text NOT NULL, + "reviewStatus" text NOT NULL, + "VP" text, + CONSTRAINT "PK_c2c1ceaca83537e7ced45484865" PRIMARY KEY ("presentationReviewId") + ) + `); + await queryRunner.query(` + CREATE TABLE "vp_request_entity" ( + "challenge" text NOT NULL, + "query" text NOT NULL, + "interact" text NOT NULL, + CONSTRAINT "PK_7fd8f399d2d73c465a5d22861e7" PRIMARY KEY ("challenge") + ) + `); + await queryRunner.query(` + CREATE TABLE "presentation_submission_entity" ( + "id" SERIAL NOT NULL, + "verificationResult" text NOT NULL, + "vpHolder" text, + CONSTRAINT "PK_3c0c233f2d67daa3d5ee759ec71" PRIMARY KEY ("id") + ) + `); + await queryRunner.query(` + CREATE TABLE "transaction_entity" ( + "transactionId" text NOT NULL, + "exchangeId" text NOT NULL, + "callback" text NOT NULL, + "vpRequestChallenge" text, + "presentationReviewPresentationReviewId" text, + "presentationSubmissionId" integer, + CONSTRAINT "REL_5e96363fa922f4da9b2b047547" UNIQUE ("vpRequestChallenge"), + CONSTRAINT "REL_459beced792faed537ed4811ba" UNIQUE ("presentationReviewPresentationReviewId"), + CONSTRAINT "REL_e7ce43da4087c1785294a7fc75" UNIQUE ("presentationSubmissionId"), + CONSTRAINT "PK_3586b024b673dad2e0e3bd4f20d" PRIMARY KEY ("transactionId") + ) + `); + await queryRunner.query(` + CREATE TABLE "exchange_entity" ( + "exchangeId" text NOT NULL, + "oneTimeTransactionId" text, + "interactServiceDefinitions" text NOT NULL, + "query" text NOT NULL, + "callback" text NOT NULL, + CONSTRAINT "PK_6349a22c62ba5be8212099c7bbc" PRIMARY KEY ("exchangeId") + ) + `); + await queryRunner.query(` + ALTER TABLE "verification_method_entity" + ADD CONSTRAINT "FK_22a35d6fd3bd1da64cb0752cbb3" FOREIGN KEY ("didDocId") REFERENCES "did_document_entity"("id") ON DELETE NO ACTION ON UPDATE NO ACTION + `); + await queryRunner.query(` + ALTER TABLE "transaction_entity" + ADD CONSTRAINT "FK_5e96363fa922f4da9b2b0475477" FOREIGN KEY ("vpRequestChallenge") REFERENCES "vp_request_entity"("challenge") ON DELETE NO ACTION ON UPDATE NO ACTION + `); + await queryRunner.query(` + ALTER TABLE "transaction_entity" + ADD CONSTRAINT "FK_459beced792faed537ed4811ba8" FOREIGN KEY ("presentationReviewPresentationReviewId") REFERENCES "presentation_review_entity"("presentationReviewId") ON DELETE NO ACTION ON UPDATE NO ACTION + `); + await queryRunner.query(` + ALTER TABLE "transaction_entity" + ADD CONSTRAINT "FK_e7ce43da4087c1785294a7fc75d" FOREIGN KEY ("presentationSubmissionId") REFERENCES "presentation_submission_entity"("id") ON DELETE NO ACTION ON UPDATE NO ACTION + `); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(` + ALTER TABLE "transaction_entity" DROP CONSTRAINT "FK_e7ce43da4087c1785294a7fc75d" + `); + await queryRunner.query(` + ALTER TABLE "transaction_entity" DROP CONSTRAINT "FK_459beced792faed537ed4811ba8" + `); + await queryRunner.query(` + ALTER TABLE "transaction_entity" DROP CONSTRAINT "FK_5e96363fa922f4da9b2b0475477" + `); + await queryRunner.query(` + ALTER TABLE "verification_method_entity" DROP CONSTRAINT "FK_22a35d6fd3bd1da64cb0752cbb3" + `); + await queryRunner.query(` + DROP TABLE "exchange_entity" + `); + await queryRunner.query(` + DROP TABLE "transaction_entity" + `); + await queryRunner.query(` + DROP TABLE "presentation_submission_entity" + `); + await queryRunner.query(` + DROP TABLE "vp_request_entity" + `); + await queryRunner.query(` + DROP TABLE "presentation_review_entity" + `); + await queryRunner.query(` + DROP TABLE "key_pair" + `); + await queryRunner.query(` + DROP TABLE "did_document_entity" + `); + await queryRunner.query(` + DROP TABLE "verification_method_entity" + `); + } +} diff --git a/apps/vc-api/src/migrations/sqlite/1671212351075-initial.ts b/apps/vc-api/src/migrations/sqlite/1671212351075-initial.ts new file mode 100644 index 00000000..0b766462 --- /dev/null +++ b/apps/vc-api/src/migrations/sqlite/1671212351075-initial.ts @@ -0,0 +1,237 @@ +import { MigrationInterface, QueryRunner } from 'typeorm'; + +export class initial1671212351075 implements MigrationInterface { + name = 'initial1671212351075'; + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query(` + CREATE TABLE "key_pair" ( + "publicKeyThumbprint" text PRIMARY KEY NOT NULL, + "privateKey" text NOT NULL, + "publicKey" text NOT NULL + ) + `); + await queryRunner.query(` + CREATE TABLE "verification_method_entity" ( + "id" text PRIMARY KEY NOT NULL, + "type" text NOT NULL, + "controller" text NOT NULL, + "publicKeyJwk" text NOT NULL, + "didDocId" text + ) + `); + await queryRunner.query(` + CREATE TABLE "did_document_entity" ("id" text PRIMARY KEY NOT NULL) + `); + await queryRunner.query(` + CREATE TABLE "presentation_review_entity" ( + "presentationReviewId" text PRIMARY KEY NOT NULL, + "reviewStatus" text NOT NULL, + "VP" text + ) + `); + await queryRunner.query(` + CREATE TABLE "vp_request_entity" ( + "challenge" text PRIMARY KEY NOT NULL, + "query" text NOT NULL, + "interact" text NOT NULL + ) + `); + await queryRunner.query(` + CREATE TABLE "presentation_submission_entity" ( + "id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, + "verificationResult" text NOT NULL, + "vpHolder" text + ) + `); + await queryRunner.query(` + CREATE TABLE "transaction_entity" ( + "transactionId" text PRIMARY KEY NOT NULL, + "exchangeId" text NOT NULL, + "callback" text NOT NULL, + "vpRequestChallenge" text, + "presentationReviewPresentationReviewId" text, + "presentationSubmissionId" integer, + CONSTRAINT "REL_5e96363fa922f4da9b2b047547" UNIQUE ("vpRequestChallenge"), + CONSTRAINT "REL_459beced792faed537ed4811ba" UNIQUE ("presentationReviewPresentationReviewId"), + CONSTRAINT "REL_e7ce43da4087c1785294a7fc75" UNIQUE ("presentationSubmissionId") + ) + `); + await queryRunner.query(` + CREATE TABLE "exchange_entity" ( + "exchangeId" text PRIMARY KEY NOT NULL, + "oneTimeTransactionId" text, + "interactServiceDefinitions" text NOT NULL, + "query" text NOT NULL, + "callback" text NOT NULL + ) + `); + await queryRunner.query(` + CREATE TABLE "temporary_verification_method_entity" ( + "id" text PRIMARY KEY NOT NULL, + "type" text NOT NULL, + "controller" text NOT NULL, + "publicKeyJwk" text NOT NULL, + "didDocId" text, + CONSTRAINT "FK_22a35d6fd3bd1da64cb0752cbb3" FOREIGN KEY ("didDocId") REFERENCES "did_document_entity" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION + ) + `); + await queryRunner.query(` + INSERT INTO "temporary_verification_method_entity"( + "id", + "type", + "controller", + "publicKeyJwk", + "didDocId" + ) + SELECT "id", + "type", + "controller", + "publicKeyJwk", + "didDocId" + FROM "verification_method_entity" + `); + await queryRunner.query(` + DROP TABLE "verification_method_entity" + `); + await queryRunner.query(` + ALTER TABLE "temporary_verification_method_entity" + RENAME TO "verification_method_entity" + `); + await queryRunner.query(` + CREATE TABLE "temporary_transaction_entity" ( + "transactionId" text PRIMARY KEY NOT NULL, + "exchangeId" text NOT NULL, + "callback" text NOT NULL, + "vpRequestChallenge" text, + "presentationReviewPresentationReviewId" text, + "presentationSubmissionId" integer, + CONSTRAINT "REL_5e96363fa922f4da9b2b047547" UNIQUE ("vpRequestChallenge"), + CONSTRAINT "REL_459beced792faed537ed4811ba" UNIQUE ("presentationReviewPresentationReviewId"), + CONSTRAINT "REL_e7ce43da4087c1785294a7fc75" UNIQUE ("presentationSubmissionId"), + CONSTRAINT "FK_5e96363fa922f4da9b2b0475477" FOREIGN KEY ("vpRequestChallenge") REFERENCES "vp_request_entity" ("challenge") ON DELETE NO ACTION ON UPDATE NO ACTION, + CONSTRAINT "FK_459beced792faed537ed4811ba8" FOREIGN KEY ("presentationReviewPresentationReviewId") REFERENCES "presentation_review_entity" ("presentationReviewId") ON DELETE NO ACTION ON UPDATE NO ACTION, + CONSTRAINT "FK_e7ce43da4087c1785294a7fc75d" FOREIGN KEY ("presentationSubmissionId") REFERENCES "presentation_submission_entity" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION + ) + `); + await queryRunner.query(` + INSERT INTO "temporary_transaction_entity"( + "transactionId", + "exchangeId", + "callback", + "vpRequestChallenge", + "presentationReviewPresentationReviewId", + "presentationSubmissionId" + ) + SELECT "transactionId", + "exchangeId", + "callback", + "vpRequestChallenge", + "presentationReviewPresentationReviewId", + "presentationSubmissionId" + FROM "transaction_entity" + `); + await queryRunner.query(` + DROP TABLE "transaction_entity" + `); + await queryRunner.query(` + ALTER TABLE "temporary_transaction_entity" + RENAME TO "transaction_entity" + `); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(` + ALTER TABLE "transaction_entity" + RENAME TO "temporary_transaction_entity" + `); + await queryRunner.query(` + CREATE TABLE "transaction_entity" ( + "transactionId" text PRIMARY KEY NOT NULL, + "exchangeId" text NOT NULL, + "callback" text NOT NULL, + "vpRequestChallenge" text, + "presentationReviewPresentationReviewId" text, + "presentationSubmissionId" integer, + CONSTRAINT "REL_5e96363fa922f4da9b2b047547" UNIQUE ("vpRequestChallenge"), + CONSTRAINT "REL_459beced792faed537ed4811ba" UNIQUE ("presentationReviewPresentationReviewId"), + CONSTRAINT "REL_e7ce43da4087c1785294a7fc75" UNIQUE ("presentationSubmissionId") + ) + `); + await queryRunner.query(` + INSERT INTO "transaction_entity"( + "transactionId", + "exchangeId", + "callback", + "vpRequestChallenge", + "presentationReviewPresentationReviewId", + "presentationSubmissionId" + ) + SELECT "transactionId", + "exchangeId", + "callback", + "vpRequestChallenge", + "presentationReviewPresentationReviewId", + "presentationSubmissionId" + FROM "temporary_transaction_entity" + `); + await queryRunner.query(` + DROP TABLE "temporary_transaction_entity" + `); + await queryRunner.query(` + ALTER TABLE "verification_method_entity" + RENAME TO "temporary_verification_method_entity" + `); + await queryRunner.query(` + CREATE TABLE "verification_method_entity" ( + "id" text PRIMARY KEY NOT NULL, + "type" text NOT NULL, + "controller" text NOT NULL, + "publicKeyJwk" text NOT NULL, + "didDocId" text + ) + `); + await queryRunner.query(` + INSERT INTO "verification_method_entity"( + "id", + "type", + "controller", + "publicKeyJwk", + "didDocId" + ) + SELECT "id", + "type", + "controller", + "publicKeyJwk", + "didDocId" + FROM "temporary_verification_method_entity" + `); + await queryRunner.query(` + DROP TABLE "temporary_verification_method_entity" + `); + await queryRunner.query(` + DROP TABLE "exchange_entity" + `); + await queryRunner.query(` + DROP TABLE "transaction_entity" + `); + await queryRunner.query(` + DROP TABLE "presentation_submission_entity" + `); + await queryRunner.query(` + DROP TABLE "vp_request_entity" + `); + await queryRunner.query(` + DROP TABLE "presentation_review_entity" + `); + await queryRunner.query(` + DROP TABLE "did_document_entity" + `); + await queryRunner.query(` + DROP TABLE "verification_method_entity" + `); + await queryRunner.query(` + DROP TABLE "key_pair" + `); + } +} diff --git a/apps/vc-api/test/app.e2e-spec.ts b/apps/vc-api/test/app.e2e-spec.ts index 6ede3427..a942bc70 100644 --- a/apps/vc-api/test/app.e2e-spec.ts +++ b/apps/vc-api/test/app.e2e-spec.ts @@ -15,6 +15,8 @@ * along with this program. If not, see . */ +Object.assign(process.env, { DB_TYPE: 'SQLITE_IN_MEMORY' }); // overwriting the .env file settings + import { Test, TestingModule } from '@nestjs/testing'; import { INestApplication, ValidationPipe, VersioningType } from '@nestjs/common'; import { AppModule } from '../src/app.module'; diff --git a/common/config/rush/pnpm-lock.yaml b/common/config/rush/pnpm-lock.yaml index ee4bbf11..a0e8a198 100644 --- a/common/config/rush/pnpm-lock.yaml +++ b/common/config/rush/pnpm-lock.yaml @@ -143,6 +143,9 @@ dependencies: nock: specifier: ~13.3.1 version: 13.3.1 + pg: + specifier: ^8.0.0 + version: 8.11.3 prettier: specifier: ^2.8.8 version: 2.8.8 @@ -181,7 +184,7 @@ dependencies: version: 3.12.0 typeorm: specifier: ^0.3.17 - version: 0.3.17(better-sqlite3@8.4.0)(ts-node@10.9.1) + version: 0.3.17(better-sqlite3@8.4.0)(pg@8.11.3)(ts-node@10.9.1) typescript: specifier: ^4.8.0 version: 4.8.2 @@ -1520,7 +1523,7 @@ packages: '@nestjs/core': 10.0.4(@nestjs/common@10.0.4)(@nestjs/platform-express@10.0.4)(reflect-metadata@0.1.13)(rxjs@7.8.1) reflect-metadata: 0.1.13 rxjs: 7.8.1 - typeorm: 0.3.17(better-sqlite3@8.4.0)(ts-node@10.9.1) + typeorm: 0.3.17(better-sqlite3@8.4.0)(pg@8.11.3)(ts-node@10.9.1) uuid: 9.0.0 dev: false @@ -1852,34 +1855,6 @@ packages: '@types/yargs-parser': 21.0.0 dev: false - /@typescript-eslint/eslint-plugin@5.60.1(@typescript-eslint/parser@5.60.1)(eslint@8.22.0)(typescript@4.7.4): - resolution: {integrity: sha512-KSWsVvsJsLJv3c4e73y/Bzt7OpqMCADUO846bHcuWYSYM19bldbAeDv7dYyV0jwkbMfJ2XdlzwjhXtuD7OY6bw==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - '@typescript-eslint/parser': ^5.0.0 - eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@eslint-community/regexpp': 4.5.1 - '@typescript-eslint/parser': 5.60.1(eslint@8.22.0)(typescript@4.7.4) - '@typescript-eslint/scope-manager': 5.60.1 - '@typescript-eslint/type-utils': 5.60.1(eslint@8.22.0)(typescript@4.7.4) - '@typescript-eslint/utils': 5.60.1(eslint@8.22.0)(typescript@4.7.4) - debug: 4.3.4 - eslint: 8.22.0 - grapheme-splitter: 1.0.4 - ignore: 5.2.0 - natural-compare-lite: 1.4.0 - semver: 7.3.7 - tsutils: 3.21.0(typescript@4.7.4) - typescript: 4.7.4 - transitivePeerDependencies: - - supports-color - dev: false - /@typescript-eslint/eslint-plugin@5.60.1(@typescript-eslint/parser@5.60.1)(eslint@8.22.0)(typescript@4.8.2): resolution: {integrity: sha512-KSWsVvsJsLJv3c4e73y/Bzt7OpqMCADUO846bHcuWYSYM19bldbAeDv7dYyV0jwkbMfJ2XdlzwjhXtuD7OY6bw==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -1908,26 +1883,6 @@ packages: - supports-color dev: false - /@typescript-eslint/parser@5.60.1(eslint@8.22.0)(typescript@4.7.4): - resolution: {integrity: sha512-pHWlc3alg2oSMGwsU/Is8hbm3XFbcrb6P5wIxcQW9NsYBfnrubl/GhVVD/Jm/t8HXhA2WncoIRfBtnCgRGV96Q==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@typescript-eslint/scope-manager': 5.60.1 - '@typescript-eslint/types': 5.60.1 - '@typescript-eslint/typescript-estree': 5.60.1(typescript@4.7.4) - debug: 4.3.4 - eslint: 8.22.0 - typescript: 4.7.4 - transitivePeerDependencies: - - supports-color - dev: false - /@typescript-eslint/parser@5.60.1(eslint@8.22.0)(typescript@4.8.2): resolution: {integrity: sha512-pHWlc3alg2oSMGwsU/Is8hbm3XFbcrb6P5wIxcQW9NsYBfnrubl/GhVVD/Jm/t8HXhA2WncoIRfBtnCgRGV96Q==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -1956,26 +1911,6 @@ packages: '@typescript-eslint/visitor-keys': 5.60.1 dev: false - /@typescript-eslint/type-utils@5.60.1(eslint@8.22.0)(typescript@4.7.4): - resolution: {integrity: sha512-vN6UztYqIu05nu7JqwQGzQKUJctzs3/Hg7E2Yx8rz9J+4LgtIDFWjjl1gm3pycH0P3mHAcEUBd23LVgfrsTR8A==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - eslint: '*' - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@typescript-eslint/typescript-estree': 5.60.1(typescript@4.7.4) - '@typescript-eslint/utils': 5.60.1(eslint@8.22.0)(typescript@4.7.4) - debug: 4.3.4 - eslint: 8.22.0 - tsutils: 3.21.0(typescript@4.7.4) - typescript: 4.7.4 - transitivePeerDependencies: - - supports-color - dev: false - /@typescript-eslint/type-utils@5.60.1(eslint@8.22.0)(typescript@4.8.2): resolution: {integrity: sha512-vN6UztYqIu05nu7JqwQGzQKUJctzs3/Hg7E2Yx8rz9J+4LgtIDFWjjl1gm3pycH0P3mHAcEUBd23LVgfrsTR8A==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -2001,27 +1936,6 @@ packages: engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dev: false - /@typescript-eslint/typescript-estree@5.60.1(typescript@4.7.4): - resolution: {integrity: sha512-hkX70J9+2M2ZT6fhti5Q2FoU9zb+GeZK2SLP1WZlvUDqdMbEKhexZODD1WodNRyO8eS+4nScvT0dts8IdaBzfw==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@typescript-eslint/types': 5.60.1 - '@typescript-eslint/visitor-keys': 5.60.1 - debug: 4.3.4 - globby: 11.1.0 - is-glob: 4.0.3 - semver: 7.5.3 - tsutils: 3.21.0(typescript@4.7.4) - typescript: 4.7.4 - transitivePeerDependencies: - - supports-color - dev: false - /@typescript-eslint/typescript-estree@5.60.1(typescript@4.8.2): resolution: {integrity: sha512-hkX70J9+2M2ZT6fhti5Q2FoU9zb+GeZK2SLP1WZlvUDqdMbEKhexZODD1WodNRyO8eS+4nScvT0dts8IdaBzfw==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -2043,26 +1957,6 @@ packages: - supports-color dev: false - /@typescript-eslint/utils@5.60.1(eslint@8.22.0)(typescript@4.7.4): - resolution: {integrity: sha512-tiJ7FFdFQOWssFa3gqb94Ilexyw0JVxj6vBzaSpfN/8IhoKkDuSAenUKvsSHw2A/TMpJb26izIszTXaqygkvpQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 - dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.22.0) - '@types/json-schema': 7.0.11 - '@types/semver': 7.5.0 - '@typescript-eslint/scope-manager': 5.60.1 - '@typescript-eslint/types': 5.60.1 - '@typescript-eslint/typescript-estree': 5.60.1(typescript@4.7.4) - eslint: 8.22.0 - eslint-scope: 5.1.1 - semver: 7.5.3 - transitivePeerDependencies: - - supports-color - - typescript - dev: false - /@typescript-eslint/utils@5.60.1(eslint@8.22.0)(typescript@4.8.2): resolution: {integrity: sha512-tiJ7FFdFQOWssFa3gqb94Ilexyw0JVxj6vBzaSpfN/8IhoKkDuSAenUKvsSHw2A/TMpJb26izIszTXaqygkvpQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -2630,6 +2524,11 @@ packages: resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} dev: false + /buffer-writer@2.0.0: + resolution: {integrity: sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw==} + engines: {node: '>=4'} + dev: false + /buffer@5.7.1: resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} dependencies: @@ -3106,6 +3005,11 @@ packages: engines: {node: '>=12'} dev: false + /dotenv@16.3.1: + resolution: {integrity: sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==} + engines: {node: '>=12'} + dev: false + /ee-first@1.1.1: resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} dev: false @@ -5408,6 +5312,10 @@ packages: engines: {node: '>=6'} dev: false + /packet-reader@1.0.0: + resolution: {integrity: sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ==} + dev: false + /parent-module@1.0.1: resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} engines: {node: '>=6'} @@ -5488,6 +5396,70 @@ packages: engines: {node: '>=8'} dev: false + /pg-cloudflare@1.1.1: + resolution: {integrity: sha512-xWPagP/4B6BgFO+EKz3JONXv3YDgvkbVrGw2mTo3D6tVDQRh1e7cqVGvyR3BE+eQgAvx1XhW/iEASj4/jCWl3Q==} + requiresBuild: true + dev: false + optional: true + + /pg-connection-string@2.6.2: + resolution: {integrity: sha512-ch6OwaeaPYcova4kKZ15sbJ2hKb/VP48ZD2gE7i1J+L4MspCtBMAx8nMgz7bksc7IojCIIWuEhHibSMFH8m8oA==} + dev: false + + /pg-int8@1.0.1: + resolution: {integrity: sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==} + engines: {node: '>=4.0.0'} + dev: false + + /pg-pool@3.6.1(pg@8.11.3): + resolution: {integrity: sha512-jizsIzhkIitxCGfPRzJn1ZdcosIt3pz9Sh3V01fm1vZnbnCMgmGl5wvGGdNN2EL9Rmb0EcFoCkixH4Pu+sP9Og==} + peerDependencies: + pg: '>=8.0' + dependencies: + pg: 8.11.3 + dev: false + + /pg-protocol@1.6.0: + resolution: {integrity: sha512-M+PDm637OY5WM307051+bsDia5Xej6d9IR4GwJse1qA1DIhiKlksvrneZOYQq42OM+spubpcNYEo2FcKQrDk+Q==} + dev: false + + /pg-types@2.2.0: + resolution: {integrity: sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==} + engines: {node: '>=4'} + dependencies: + pg-int8: 1.0.1 + postgres-array: 2.0.0 + postgres-bytea: 1.0.0 + postgres-date: 1.0.7 + postgres-interval: 1.2.0 + dev: false + + /pg@8.11.3: + resolution: {integrity: sha512-+9iuvG8QfaaUrrph+kpF24cXkH1YOOUeArRNYIxq1viYHZagBxrTno7cecY1Fa44tJeZvaoG+Djpkc3JwehN5g==} + engines: {node: '>= 8.0.0'} + peerDependencies: + pg-native: '>=3.0.1' + peerDependenciesMeta: + pg-native: + optional: true + dependencies: + buffer-writer: 2.0.0 + packet-reader: 1.0.0 + pg-connection-string: 2.6.2 + pg-pool: 3.6.1(pg@8.11.3) + pg-protocol: 1.6.0 + pg-types: 2.2.0 + pgpass: 1.0.5 + optionalDependencies: + pg-cloudflare: 1.1.1 + dev: false + + /pgpass@1.0.5: + resolution: {integrity: sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==} + dependencies: + split2: 4.2.0 + dev: false + /picocolors@1.0.0: resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} dev: false @@ -5514,6 +5486,28 @@ packages: engines: {node: '>=4'} dev: false + /postgres-array@2.0.0: + resolution: {integrity: sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==} + engines: {node: '>=4'} + dev: false + + /postgres-bytea@1.0.0: + resolution: {integrity: sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==} + engines: {node: '>=0.10.0'} + dev: false + + /postgres-date@1.0.7: + resolution: {integrity: sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==} + engines: {node: '>=0.10.0'} + dev: false + + /postgres-interval@1.2.0: + resolution: {integrity: sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==} + engines: {node: '>=0.10.0'} + dependencies: + xtend: 4.0.2 + dev: false + /prebuild-install@7.1.1: resolution: {integrity: sha512-jAXscXWMcCK8GgCoHOfIr0ODh5ai8mj63L2nWrjuAgXE6tDyYGnx4/8o/rCgU+B4JSyZBKbeZqzhtwtC3ovxjw==} engines: {node: '>=10'} @@ -6000,6 +5994,11 @@ packages: engines: {node: '>= 8'} dev: false + /split2@4.2.0: + resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==} + engines: {node: '>= 10.x'} + dev: false + /sprintf-js@1.0.3: resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} dev: false @@ -6428,16 +6427,6 @@ packages: resolution: {integrity: sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==} dev: false - /tsutils@3.21.0(typescript@4.7.4): - resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==} - engines: {node: '>= 6'} - peerDependencies: - typescript: '>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta' - dependencies: - tslib: 1.14.1 - typescript: 4.7.4 - dev: false - /tsutils@3.21.0(typescript@4.8.2): resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==} engines: {node: '>= 6'} @@ -6500,7 +6489,7 @@ packages: resolution: {integrity: sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==} dev: false - /typeorm@0.3.17(better-sqlite3@8.4.0)(ts-node@10.9.1): + /typeorm@0.3.17(better-sqlite3@8.4.0)(pg@8.11.3)(ts-node@10.9.1): resolution: {integrity: sha512-UDjUEwIQalO9tWw9O2A4GU+sT3oyoUXheHJy4ft+RFdnRdQctdQ34L9SqE2p7LdwzafHx1maxT+bqXON+Qnmig==} engines: {node: '>= 12.9.0'} hasBin: true @@ -6569,6 +6558,7 @@ packages: dotenv: 16.1.4 glob: 8.1.0 mkdirp: 2.1.6 + pg: 8.11.3 reflect-metadata: 0.1.13 sha.js: 2.4.11 ts-node: 10.9.1(@types/node@20.3.2)(typescript@4.8.2) @@ -6579,12 +6569,6 @@ packages: - supports-color dev: false - /typescript@4.7.4: - resolution: {integrity: sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==} - engines: {node: '>=4.2.0'} - hasBin: true - dev: false - /typescript@4.8.2: resolution: {integrity: sha512-C0I1UsrrDHo2fYI5oaCGbSejwX4ch+9Y5jTQELvovfmFkK3HHSZJB8MSJcWLmCUBzQBchCrZ9rMRV6GuNrvGtw==} engines: {node: '>=4.2.0'} @@ -7054,7 +7038,7 @@ packages: dev: false file:projects/ssi-vc-api.tgz(@babel/core@7.18.13)(babel-jest@29.5.0)(express@4.18.2)(webpack@5.88.1): - resolution: {integrity: sha512-ykt6a+AfUSs0VCpLdIUaulTqJGs0CGlEnkSReLTLUVXJvaLolSJqDC8uCZao1rZrlkHQyQKZdeBiYEdUIvGywg==, tarball: file:projects/ssi-vc-api.tgz} + resolution: {integrity: sha512-9YEaoWassvSvi2uttwkCSF7jobCSlnHGrSkY/CTj62WJsYvj3CtdVN9UELAUwGkKhdvnJAgrCa1DE38jDzrzoQ==, tarball: file:projects/ssi-vc-api.tgz} id: file:projects/ssi-vc-api.tgz name: '@rush-temp/ssi-vc-api' version: 0.0.0 @@ -7086,6 +7070,7 @@ packages: class-transformer: 0.5.1 class-validator: 0.14.0 did-resolver: 4.1.0 + dotenv: 16.3.1 eslint: 8.22.0 eslint-config-prettier: 8.8.0(eslint@8.22.0) eslint-plugin-no-only-tests: 3.1.0 @@ -7094,6 +7079,7 @@ packages: joi: 17.9.2 jose: 4.14.4 nock: 13.3.1 + pg: 8.11.3 prettier: 2.8.8 reflect-metadata: 0.1.13 rimraf: 3.0.2 @@ -7104,7 +7090,7 @@ packages: ts-loader: 9.4.4(typescript@4.8.2)(webpack@5.88.1) ts-node: 10.9.1(@types/node@20.3.2)(typescript@4.8.2) tsconfig-paths: 4.2.0 - typeorm: 0.3.17(better-sqlite3@8.4.0)(ts-node@10.9.1) + typeorm: 0.3.17(better-sqlite3@8.4.0)(pg@8.11.3)(ts-node@10.9.1) typescript: 4.8.2 uuid: 9.0.0 transitivePeerDependencies: @@ -7132,7 +7118,6 @@ packages: - mysql2 - node-notifier - oracledb - - pg - pg-native - pg-query-stream - redis @@ -7146,14 +7131,14 @@ packages: dev: false file:projects/w3c-ccg-webkms.tgz: - resolution: {integrity: sha512-a4gEwLfs7nG2g7SZhAO9D4uYvjmGnHow7J6nqAdjPsKtf6Qd4BwHfKuw8V3hHfiu4awLe0usG3ZvqwlgvJvJ4A==, tarball: file:projects/w3c-ccg-webkms.tgz} + resolution: {integrity: sha512-2xrjQZ7xPr43lLGU+Jr74564meB716f5ScNSC4/MLCr/L+ysRXOZIBQMp1dVleBrrRn7zvYT2YU6DJLW0qhgEg==, tarball: file:projects/w3c-ccg-webkms.tgz} name: '@rush-temp/w3c-ccg-webkms' version: 0.0.0 dependencies: '@energyweb/eslint-config': 0.1.0(@typescript-eslint/eslint-plugin@5.60.1)(@typescript-eslint/parser@5.60.1)(eslint-config-prettier@8.8.0)(eslint-plugin-no-only-tests@3.1.0)(eslint@8.22.0) '@energyweb/prettier-config': 0.0.1(prettier@2.8.8) - '@typescript-eslint/eslint-plugin': 5.60.1(@typescript-eslint/parser@5.60.1)(eslint@8.22.0)(typescript@4.7.4) - '@typescript-eslint/parser': 5.60.1(eslint@8.22.0)(typescript@4.7.4) + '@typescript-eslint/eslint-plugin': 5.60.1(@typescript-eslint/parser@5.60.1)(eslint@8.22.0)(typescript@4.8.2) + '@typescript-eslint/parser': 5.60.1(eslint@8.22.0)(typescript@4.8.2) eslint: 8.22.0 eslint-config-prettier: 8.8.0(eslint@8.22.0) eslint-plugin-no-only-tests: 3.1.0 @@ -7163,5 +7148,6 @@ packages: typescript: 4.8.2 transitivePeerDependencies: - bufferutil + - supports-color - utf-8-validate dev: false