diff --git a/apps/holder-app/project.json b/apps/holder-app/project.json index e60a73a9..e9724827 100644 --- a/apps/holder-app/project.json +++ b/apps/holder-app/project.json @@ -6,6 +6,14 @@ "sourceRoot": "apps/holder-app/src", "tags": [], "targets": { + "init": { + "executor": "nx:run-commands", + "options": { + "commands": [ + "cp apps/holder-app/src/assets/config/config.example.js apps/holder-app/src/assets/config/config.js" + ] + } + }, "build": { "executor": "@angular-devkit/build-angular:application", "outputs": ["{options.outputPath}"], @@ -86,10 +94,10 @@ "dependsOn": ["build"], "options": { "engine": "docker", + "push": true, "metadata": { "images": ["ghcr.io/cre8/wallet/holder-app"], "load": true, - "push": false, "tags": ["latest"] } } diff --git a/apps/holder-backend/Dockerfile b/apps/holder-backend/Dockerfile index 5d7f5c56..23e790db 100644 --- a/apps/holder-backend/Dockerfile +++ b/apps/holder-backend/Dockerfile @@ -4,7 +4,7 @@ FROM docker.io/node:lts-alpine as deps RUN apk add --no-cache libc6-compat WORKDIR /usr/src/app COPY dist/apps/holder-backend/package*.json ./ -COPY dist/apps/holder-backend/pnpm-lock.yaml ./ +COPY pnpm-lock.yaml ./ COPY patches ./patches RUN npm install -g pnpm@8.15.8 RUN pnpm install --prod diff --git a/apps/holder-backend/package.json b/apps/holder-backend/package.json new file mode 100644 index 00000000..4e98bb0b --- /dev/null +++ b/apps/holder-backend/package.json @@ -0,0 +1,11 @@ +{ + "dependencies": { + "@sphereon/pex": "^3.3.3", + "pg": "^8.11.5" + }, + "pnpm": { + "patchedDependencies": { + "@sphereon/pex@3.3.3": "patches/@sphereon__pex@3.3.3.patch" + } + } +} diff --git a/apps/holder-backend/project.json b/apps/holder-backend/project.json index 2b314376..a8b9771b 100644 --- a/apps/holder-backend/project.json +++ b/apps/holder-backend/project.json @@ -5,6 +5,14 @@ "projectType": "application", "tags": [], "targets": { + "init": { + "executor": "nx:run-commands", + "options": { + "commands": [ + "cp apps/holder-backend/.env.example apps/holder-backend/.env" + ] + } + }, "serve": { "executor": "@nx/js:node", "defaultConfiguration": "development", @@ -25,17 +33,11 @@ "dependsOn": ["build"], "options": { "engine": "docker", + "push": true, "metadata": { - "images": ["holder-backend"], + "images": ["ghcr.io/cre8/wallet/holder-backend"], "load": true, - "push": false, - "tags": [ - "type=schedule", - "type=ref,event=branch", - "type=ref,event=tag", - "type=ref,event=pr", - "type=sha,prefix=sha-" - ] + "tags": ["latest"] } } } diff --git a/apps/holder-backend/src/app/app.controller.ts b/apps/holder-backend/src/app/app.controller.ts index d4a599e3..980c2552 100644 --- a/apps/holder-backend/src/app/app.controller.ts +++ b/apps/holder-backend/src/app/app.controller.ts @@ -1,11 +1,18 @@ import { Controller, Get } from '@nestjs/common'; +import { ApiOperation } from '@nestjs/swagger'; import { Public } from 'nest-keycloak-connect'; @Controller() export class AppController { + /** + * Health check endpoint + * @returns + */ + @ApiOperation({ summary: 'Health check endpoint' }) @Public() @Get('health') health() { + //TODO: for a better health check, use https://docs.nestjs.com/recipes/terminus#setting-up-a-healthcheck return 'ok'; } } diff --git a/apps/holder-backend/src/main.ts b/apps/holder-backend/src/main.ts index 4afbbe36..eb370039 100644 --- a/apps/holder-backend/src/main.ts +++ b/apps/holder-backend/src/main.ts @@ -1,3 +1,4 @@ +import 'tslib'; import { ValidationPipe } from '@nestjs/common'; import { NestFactory } from '@nestjs/core'; import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger'; diff --git a/apps/issuer-backend/.env.example b/apps/issuer-backend/.env.example index 8626271e..8e319382 100644 --- a/apps/issuer-backend/.env.example +++ b/apps/issuer-backend/.env.example @@ -13,4 +13,4 @@ DB_NAME=tmp/db.sqlite CREDENTIALS_FOLDER=config/issuer-backend -KM_FOLDER=tmp/issuer/ +KM_FOLDER=tmp/issuer/keys diff --git a/apps/issuer-backend/Dockerfile b/apps/issuer-backend/Dockerfile index 5d7f5c56..cb6a9975 100644 --- a/apps/issuer-backend/Dockerfile +++ b/apps/issuer-backend/Dockerfile @@ -3,8 +3,8 @@ FROM docker.io/node:lts-alpine as deps # Check https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine to understand why libc6-compat might be needed. RUN apk add --no-cache libc6-compat WORKDIR /usr/src/app -COPY dist/apps/holder-backend/package*.json ./ -COPY dist/apps/holder-backend/pnpm-lock.yaml ./ +COPY dist/apps/issuer-backend/package.json ./ +COPY pnpm-lock.yaml ./ COPY patches ./patches RUN npm install -g pnpm@8.15.8 RUN pnpm install --prod @@ -17,7 +17,7 @@ ENV PORT 3000 WORKDIR /usr/src/app COPY --from=deps /usr/src/app/node_modules ./node_modules COPY --from=deps /usr/src/app/package.json ./package.json -COPY dist/apps/holder-backend . +COPY dist/apps/issuer-backend . RUN chown -R node:node . USER node EXPOSE 3000 diff --git a/apps/issuer-backend/package.json b/apps/issuer-backend/package.json new file mode 100644 index 00000000..bc950b1d --- /dev/null +++ b/apps/issuer-backend/package.json @@ -0,0 +1,11 @@ +{ + "dependencies": { + "sqlite3": "^5.1.7", + "@sphereon/pex": "^3.3.3" + }, + "pnpm": { + "patchedDependencies": { + "@sphereon/pex@3.3.3": "patches/@sphereon__pex@3.3.3.patch" + } + } +} diff --git a/apps/issuer-backend/project.json b/apps/issuer-backend/project.json index 05945356..8f2eb2a8 100644 --- a/apps/issuer-backend/project.json +++ b/apps/issuer-backend/project.json @@ -5,6 +5,14 @@ "projectType": "application", "tags": [], "targets": { + "init": { + "executor": "nx:run-commands", + "options": { + "commands": [ + "cp apps/issuer-backend/.env.example apps/issuer-backend/.env" + ] + } + }, "serve": { "executor": "@nx/js:node", "defaultConfiguration": "development", @@ -25,10 +33,10 @@ "dependsOn": ["build"], "options": { "engine": "docker", + "push": true, "metadata": { "images": ["ghcr.io/cre8/wallet/issuer-backend"], "load": true, - "push": false, "tags": ["latest"] } } diff --git a/apps/issuer-backend/src/main.ts b/apps/issuer-backend/src/main.ts index 97cf0caa..7019eee2 100644 --- a/apps/issuer-backend/src/main.ts +++ b/apps/issuer-backend/src/main.ts @@ -1,3 +1,4 @@ +import 'tslib'; import { NestFactory } from '@nestjs/core'; import { AppModule } from './app/app.module'; import { ValidationPipe } from '@nestjs/common'; diff --git a/apps/issuer-backend/webpack.config.js b/apps/issuer-backend/webpack.config.js index fdba56a4..74f00383 100644 --- a/apps/issuer-backend/webpack.config.js +++ b/apps/issuer-backend/webpack.config.js @@ -14,6 +14,7 @@ module.exports = { assets: ['./src/assets'], optimization: false, outputHashing: 'none', + generatePackageJson: true, transformers: [{ name: '@nestjs/swagger/plugin' }], }), ], diff --git a/apps/issuer-frontend/project.json b/apps/issuer-frontend/project.json index f9c9e6f2..32fdaafb 100644 --- a/apps/issuer-frontend/project.json +++ b/apps/issuer-frontend/project.json @@ -86,10 +86,10 @@ "dependsOn": ["build"], "options": { "engine": "docker", + "push": true, "metadata": { "images": ["ghcr.io/cre8/wallet/issuer-frontend"], "load": true, - "push": false, "tags": ["latest"] } } diff --git a/apps/verifier-backend/.env.example b/apps/verifier-backend/.env.example index abc370aa..2692945b 100644 --- a/apps/verifier-backend/.env.example +++ b/apps/verifier-backend/.env.example @@ -10,4 +10,4 @@ KEYCLOAK_CLIENT_ID=issuer CREDENTIALS_FOLDER=config/verifier -KM_FOLDER=tmp/verifier/ +KM_FOLDER=tmp/verifier/keys diff --git a/apps/verifier-backend/Dockerfile b/apps/verifier-backend/Dockerfile index 5d7f5c56..2a714845 100644 --- a/apps/verifier-backend/Dockerfile +++ b/apps/verifier-backend/Dockerfile @@ -3,8 +3,8 @@ FROM docker.io/node:lts-alpine as deps # Check https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine to understand why libc6-compat might be needed. RUN apk add --no-cache libc6-compat WORKDIR /usr/src/app -COPY dist/apps/holder-backend/package*.json ./ -COPY dist/apps/holder-backend/pnpm-lock.yaml ./ +COPY dist/apps/verifier-backend/package.json ./ +COPY pnpm-lock.yaml ./ COPY patches ./patches RUN npm install -g pnpm@8.15.8 RUN pnpm install --prod @@ -17,7 +17,7 @@ ENV PORT 3000 WORKDIR /usr/src/app COPY --from=deps /usr/src/app/node_modules ./node_modules COPY --from=deps /usr/src/app/package.json ./package.json -COPY dist/apps/holder-backend . +COPY dist/apps/verifier-backend . RUN chown -R node:node . USER node EXPOSE 3000 diff --git a/apps/verifier-backend/package.json b/apps/verifier-backend/package.json new file mode 100644 index 00000000..40e8b840 --- /dev/null +++ b/apps/verifier-backend/package.json @@ -0,0 +1,10 @@ +{ + "dependencies": { + "@sphereon/pex": "^3.3.3" + }, + "pnpm": { + "patchedDependencies": { + "@sphereon/pex@3.3.3": "patches/@sphereon__pex@3.3.3.patch" + } + } +} diff --git a/apps/verifier-backend/project.json b/apps/verifier-backend/project.json index 4b9a23bb..951052be 100644 --- a/apps/verifier-backend/project.json +++ b/apps/verifier-backend/project.json @@ -5,6 +5,14 @@ "projectType": "application", "tags": [], "targets": { + "init": { + "executor": "nx:run-commands", + "options": { + "commands": [ + "cp apps/verifier-backend/.env.example apps/verifier-backend/.env" + ] + } + }, "serve": { "executor": "@nx/js:node", "defaultConfiguration": "development", @@ -25,10 +33,10 @@ "dependsOn": ["build"], "options": { "engine": "docker", + "push": true, "metadata": { "images": ["ghcr.io/cre8/wallet/verifier-backend"], "load": true, - "push": false, "tags": ["latest"] } } diff --git a/apps/verifier-backend/src/app/verifier/relying-party-manager.service.ts b/apps/verifier-backend/src/app/verifier/relying-party-manager.service.ts index e35305dc..1e7097cd 100644 --- a/apps/verifier-backend/src/app/verifier/relying-party-manager.service.ts +++ b/apps/verifier-backend/src/app/verifier/relying-party-manager.service.ts @@ -1,7 +1,6 @@ import { Inject, Injectable } from '@nestjs/common'; import { ES256, digest } from '@sd-jwt/crypto-nodejs'; import { - EcdsaSignature, JWK, JWTPayload, PassBy, diff --git a/apps/verifier-backend/src/main.ts b/apps/verifier-backend/src/main.ts index 97cf0caa..7019eee2 100644 --- a/apps/verifier-backend/src/main.ts +++ b/apps/verifier-backend/src/main.ts @@ -1,3 +1,4 @@ +import 'tslib'; import { NestFactory } from '@nestjs/core'; import { AppModule } from './app/app.module'; import { ValidationPipe } from '@nestjs/common'; diff --git a/apps/verifier-frontend/project.json b/apps/verifier-frontend/project.json index 46c0ed7a..6682d973 100644 --- a/apps/verifier-frontend/project.json +++ b/apps/verifier-frontend/project.json @@ -86,10 +86,10 @@ "dependsOn": ["build"], "options": { "engine": "docker", + "push": true, "metadata": { "images": ["ghcr.io/cre8/wallet/verifier-frontend"], "load": true, - "push": false, "tags": ["latest"] } } diff --git a/docker-compose.yml b/docker-compose.yml index 6e49091b..ae44ee47 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -143,11 +143,6 @@ services: image: ghcr.io/cre8/wallet/holder-backend env_file: - .env - build: - context: . - dockerfile: docker/node.Dockerfile - args: - - PROJECT=backend ports: - 3000:3000 healthcheck: diff --git a/docker/browser.Dockerfile b/docker/browser.Dockerfile deleted file mode 100644 index fa52a00a..00000000 --- a/docker/browser.Dockerfile +++ /dev/null @@ -1,36 +0,0 @@ -FROM node:20-slim AS base -ENV PNPM_HOME="/pnpm" -ENV PATH="$PNPM_HOME:$PATH" -RUN corepack enable -ARG PROJECT - -FROM base AS build -# the downside of this is that is can not cache the node_modules since a change to all elements will trigger a cache invalidation -COPY . /usr/src/app -WORKDIR /usr/src/app -RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --frozen-lockfile -# build the project -RUN pnpm --filter=${PROJECT} run build -# deploy the project -RUN pnpm deploy --filter=${PROJECT} --prod /app - -FROM georgjung/nginx-brotli:1.23.3 -ARG PROJECT -ARG SUB_PROJECT -WORKDIR /usr/share/nginx/html -RUN mkdir -p /etc/nginx && \ - echo 'events {}' > /etc/nginx/nginx.conf && \ - echo 'http {' >> /etc/nginx/nginx.conf && \ - echo ' include /etc/nginx/mime.types;' >> /etc/nginx/nginx.conf && \ - echo ' server {' >> /etc/nginx/nginx.conf && \ - echo ' listen 80;' >> /etc/nginx/nginx.conf && \ - echo ' root /usr/share/nginx/html;' >> /etc/nginx/nginx.conf && \ - echo ' index index.html;' >> /etc/nginx/nginx.conf && \ - echo ' location / {' >> /etc/nginx/nginx.conf && \ - echo ' try_files $uri $uri/ /index.html =404;' >> /etc/nginx/nginx.conf && \ - echo ' }' >> /etc/nginx/nginx.conf && \ - echo ' }' >> /etc/nginx/nginx.conf && \ - echo '}' >> /etc/nginx/nginx.conf -COPY --from=build /usr/src/app/dist/apps/${PROJECT}/browser . -# copy the 3rd party licenses -COPY --from=build /usr/src/app/dist/apps/${PROJECT}/3rdpartylicenses.txt . diff --git a/docker/node.Dockerfile b/docker/node.Dockerfile deleted file mode 100644 index be09e74d..00000000 --- a/docker/node.Dockerfile +++ /dev/null @@ -1,26 +0,0 @@ -FROM node:20-slim AS base -ENV PNPM_HOME="/pnpm" -ENV PATH="$PNPM_HOME:$PATH" -RUN corepack enable -ARG PROJECT - -FROM base AS build -# the downside of this is that is can not cache the node_modules since a change to all elements will trigger a cache invalidation -COPY . /usr/src/app -WORKDIR /usr/src/app -ARG PROJECT -RUN --mount=type=cache,id=pnpm,target=/pnpm/store pnpm install --frozen-lockfile -# build the project -RUN pnpm --filter=${PROJECT} run build -# deploy the project -RUN pnpm deploy --filter=${PROJECT} --prod /app - -FROM base AS deploy -ARG PROJECT -COPY --from=build /app/node_modules /app/node_modules -COPY --from=build /app/package.json /app/package.json -COPY --from=build /usr/src/app/apps/${PROJECT}/dist /app/dist -WORKDIR /app -EXPOSE 3000 -CMD [ "node", "dist/main.js" ] -# healthcheck are done via docker compose since curl is not installed \ No newline at end of file diff --git a/docs/development.md b/docs/development.md index 7b59e40c..aa0f9202 100644 --- a/docs/development.md +++ b/docs/development.md @@ -1,9 +1,19 @@ # Development +## Technical design decisions +Typescript as programming language: large community and good support for wallet related libraries. Of course it does not perform as good as Rust, but it's easier to write and maintain for the current state of the project. It is possible to write different parts of the project in Rust or any other language later on. + +Angular as frontend framework: All frontend applications are written in Angular. There was no intention to build a react native application so far, but it is possible to do so. Since the client is primarily job is to render information and not to execute business actions, other clients like a react native app, vanilla js or even a flutter app can be implemented. + +Nestjs as backend framework: Nestjs is one of the popular frameworks for nodejs. The build in database connection, the openAPI support and the easy validation of incoming requests are the main reasons to use it. It is also possible to write the backend in Rust or any other language later on. + +NX as monorepo manager: NX is a great tool to manage a monorepo. It is possible to share code between the applications and to define the jobs for building, testing and linting in one place. It is also possible to define the dependencies between the applications and to run the jobs in the right order. + ## Requirements - node v20 (https://nodejs.org/en/download/package-manager) -- pnpm v9 -- enabled corepack via `corepack enable` (comes with node) +- pnpm v8 (v9 has some issues with the nx workspace) + +For an easy development setup, it is recommend to use vscode with the nx plugin to start tasks like building, testing and linting or to generate new code. You can also use Webstorm with the nx plugin, [see here](https://nx.dev/getting-started/editor-setup#official-integrations). ### Keycloak (OIDC provider) @@ -46,4 +56,4 @@ To build the plugin for production, run `pnpm run build:extension`. The output w ## Backend All endpoints are available via the `http://localhost:3000` address. A swagger endpoint is available at `http://localhost:3000/api` where you can authenticate with your keycloak user credentials. Don't forget to have an `.env` file in the folder to configure the application, it will not use the `.env` file in the root folder. -You can either use a postgres or sqlite database. In case of using postgres, there is one defined in the `docker-compose.yml` in the root folder. Don't forget to sync the credentials in the root `.env` file and the one in the backend folder to get a successful connection. \ No newline at end of file +You can either use a postgres or sqlite database. In case of using postgres, there is one defined in the `docker-compose.yml` in the root folder. Don't forget to sync the credentials in the root `.env` file and the one in the backend folder to get a successful connection. diff --git a/docs/running-docker.md b/docs/running-docker.md index 3287822f..9e182712 100644 --- a/docs/running-docker.md +++ b/docs/running-docker.md @@ -2,13 +2,24 @@ To run the docker compose setup, copy the `.env.example` to `.env` in the root folder. Modify the values if required. ## Building containers -Running `docker compose build` will build the images locally. This is required if you want to run your modified apps. The typescript code gets compiled during the image build process, so there is no need to run `pnpm install` or any other build command before this. +The containers are built via the tasks in each nx app like: +```bash +nx run holder-app:container +``` +To build multiple project at once, you can use the run many command: +```bash +nx run-many --target=container --all +``` + +By default the containers are built with the `latest` tag and will not be pushed to the registry. When pushed to the `main` branch of the repo, the github action will push the latest version to the registry. ## Configs -The configuration of the pwa client is mounted from the `config/holder/config.js` file, this allows to change the endpoints to the different services without the need to recompile the app. +The configuration of the pwa client is mounted from the `config/holder-frontend/config.js` file, this allows to change the endpoints to the different services without the need to recompile the app. ## Known limitations -right now running it locally via docker can cause some problems since `localhost` is used to interact with some services. +right now running it locally via docker can cause some problems since `localhost` is used to interact with some services. The web application want a JWT with the audience of `http://localhost:8080`, the keycloak instance. But the backendends that are running in docker communicate with the keycloak instance via `http://keycloak:8080`. This problem can be solved by +- using a public available keycloak instance +- running the backend services locally as a node application and not inside docker ## Vault To secure your keys, you are able to use [vault by hashicorp](https://developer.hashicorp.com/vault), otherwise the keys are either stored in the filesystem for the issuer and verifier or in the unencrypted database for the wallet. @@ -33,7 +44,9 @@ TODO: we also need key management for the accounts to support multiple keys, bec ### Using in the issuer and verifier -TODO: not implemented yet. +The key management for the issuer and verifier can also be managed via keycloak. Right now a unique key id has to be generated by yourself and passed in the `.env` file. The services will generate a key pair and store it in the vault instance. For know multi key support for one instance is not supported, so the issuer/verifier has to use one key each (but both could technically use the same key). + +```yml ### Production use Update the docker container like this: @@ -56,4 +69,4 @@ Update the docker container like this: VAULT_ADDR: http://127.0.0.1:8200 entrypoint: vault server -config=/vault/config/config.hcl ``` -Get familiar with the [vault deployment guide](https://developer.hashicorp.com/vault/tutorials/getting-started/getting-started-deploy). This current documentation is not fully covered to run vault in production! \ No newline at end of file +Get familiar with the [vault deployment guide](https://developer.hashicorp.com/vault/tutorials/getting-started/getting-started-deploy). This current documentation is not fully covered to run vault in production! diff --git a/libs/relying-party-shared/src/lib/key/filesystem-key.service.ts b/libs/relying-party-shared/src/lib/key/filesystem-key.service.ts index bb8d1216..7132874c 100644 --- a/libs/relying-party-shared/src/lib/key/filesystem-key.service.ts +++ b/libs/relying-party-shared/src/lib/key/filesystem-key.service.ts @@ -47,7 +47,7 @@ export class FileSystemKeyService implements KeyService { private async getKeys() { let privateKey: JWK; let publicKey: JWK; - const folder = join(this.configService.get('KM_FOLDER') as string, 'keys'); + const folder = this.configService.get('KM_FOLDER'); if (!existsSync(folder)) { mkdirSync(folder, { recursive: true }); } diff --git a/package.json b/package.json index 84155b40..1a9dc081 100644 --- a/package.json +++ b/package.json @@ -110,6 +110,7 @@ "jsqr": "^1.4.0", "nest-keycloak-connect": "^1.10.0", "ng-flex-layout": "17.3.7-beta.1", + "pg": "^8.11.5", "qrcode": "^1.5.3", "reflect-metadata": "^0.1.13", "rxjs": "^7.8.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2d90503a..f4cfa03e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -136,6 +136,9 @@ dependencies: ng-flex-layout: specifier: 17.3.7-beta.1 version: 17.3.7-beta.1(@angular/cdk@17.3.7)(@angular/common@17.3.7)(@angular/core@17.3.7)(@angular/platform-browser@17.3.7)(rxjs@7.8.1) + pg: + specifier: ^8.11.5 + version: 8.11.5 qrcode: specifier: ^1.5.3 version: 1.5.3 @@ -153,7 +156,7 @@ dependencies: version: 2.6.2 typeorm: specifier: ^0.3.20 - version: 0.3.20(sqlite3@5.1.7)(ts-node@10.9.1) + version: 0.3.20(pg@8.11.5)(sqlite3@5.1.7)(ts-node@10.9.1) uuid: specifier: ^9.0.1 version: 9.0.1 @@ -5021,7 +5024,7 @@ packages: '@nestjs/core': 10.3.8(@nestjs/common@10.3.8)(@nestjs/platform-express@10.3.8)(reflect-metadata@0.1.14)(rxjs@7.8.1) reflect-metadata: 0.1.14 rxjs: 7.8.1 - typeorm: 0.3.20(sqlite3@5.1.7)(ts-node@10.9.1) + typeorm: 0.3.20(pg@8.11.5)(sqlite3@5.1.7)(ts-node@10.9.1) uuid: 9.0.1 dev: false @@ -13914,6 +13917,68 @@ packages: dev: false optional: true + /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.4: + resolution: {integrity: sha512-v+Z7W/0EO707aNMaAEfiGnGL9sxxumwLl2fJvCQtMn9Fxsg+lPpPkdcyBSv/KFgpGdYkMfn+EI1Or2EHjpgLCA==} + dev: false + + /pg-int8@1.0.1: + resolution: {integrity: sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==} + engines: {node: '>=4.0.0'} + dev: false + + /pg-pool@3.6.2(pg@8.11.5): + resolution: {integrity: sha512-Htjbg8BlwXqSBQ9V8Vjtc+vzf/6fVUuak/3/XXKA9oxZprwW3IMDQTGHP+KDmVL7rtd+R1QjbnCFPuTHm3G4hg==} + peerDependencies: + pg: '>=8.0' + dependencies: + pg: 8.11.5 + dev: false + + /pg-protocol@1.6.1: + resolution: {integrity: sha512-jPIlvgoD63hrEuihvIg+tJhoGjUsLPn6poJY9N5CnlPd91c2T18T/9zBtLxZSb1EhYxBRoZJtzScCaWlYLtktg==} + 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.5: + resolution: {integrity: sha512-jqgNHSKL5cbDjFlHyYsCXmQDrfIX/3RsNwYqpd4N0Kt8niLuNoRNH+aazv6cOd43gPh9Y4DjQCtb+X0MH0Hvnw==} + engines: {node: '>= 8.0.0'} + peerDependencies: + pg-native: '>=3.0.1' + peerDependenciesMeta: + pg-native: + optional: true + dependencies: + pg-connection-string: 2.6.4 + pg-pool: 3.6.2(pg@8.11.5) + pg-protocol: 1.6.1 + 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: true @@ -14425,6 +14490,28 @@ packages: source-map-js: 1.2.0 dev: true + /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.2: resolution: {integrity: sha512-UnNke3IQb6sgarcZIDU3gbMeTp/9SSU1DAIkil7PrqG1vZlBtY5msYccSKSHDqa3hNg436IXK+SNImReuA1wEQ==} engines: {node: '>=10'} @@ -15422,6 +15509,11 @@ packages: - supports-color dev: true + /split2@4.2.0: + resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==} + engines: {node: '>= 10.x'} + dev: false + /sprintf-js@1.0.3: resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} dev: true @@ -16217,7 +16309,7 @@ packages: /typedarray@0.0.6: resolution: {integrity: sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==} - /typeorm@0.3.20(sqlite3@5.1.7)(ts-node@10.9.1): + /typeorm@0.3.20(pg@8.11.5)(sqlite3@5.1.7)(ts-node@10.9.1): resolution: {integrity: sha512-sJ0T08dV5eoZroaq9uPKBoNcGslHBR4E4y+EBHs//SiGbblGe7IeduP/IH4ddCcj0qp3PHwDwGnuvqEAnKlq/Q==} engines: {node: '>=16.13.0'} hasBin: true @@ -16285,6 +16377,7 @@ packages: dotenv: 16.4.5 glob: 10.3.12 mkdirp: 2.1.6 + pg: 8.11.5 reflect-metadata: 0.2.2 sha.js: 2.4.11 sqlite3: 5.1.7