mirror of
https://github.com/standardnotes/server
synced 2026-05-11 12:57:18 -04:00
Compare commits
33 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f24ee61d11 | |||
| 881a6967ac | |||
| a93f66c6ac | |||
| fdf4b29ae2 | |||
| d5f6ca0d2e | |||
| 12d9ccf28c | |||
| ffc270cc6f | |||
| 61e2e58297 | |||
| b68ede1f63 | |||
| d333c1393c | |||
| 35d6f2f961 | |||
| 3d619a0c61 | |||
| bda812f170 | |||
| 826719bb67 | |||
| 631101eae5 | |||
| fa0b9bf935 | |||
| 708af5e83c | |||
| 993d31167b | |||
| ac5fc7d28a | |||
| 73f3fad13d | |||
| 85e0e2165f | |||
| 89ee103303 | |||
| 6b313947c3 | |||
| fba8e6ce35 | |||
| 622c024547 | |||
| 2c51d92bab | |||
| 11ef2ef708 | |||
| df793e07fd | |||
| bae6eea3aa | |||
| be17b67cc1 | |||
| 645a24d29b | |||
| 64962ce632 | |||
| 5120883691 |
@@ -13,16 +13,9 @@ on:
|
|||||||
required: true
|
required: true
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
e2e:
|
|
||||||
name: E2E
|
|
||||||
uses: standardnotes/server/.github/workflows/common-e2e.yml@main
|
|
||||||
secrets: inherit
|
|
||||||
|
|
||||||
publish:
|
publish:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
needs: e2e
|
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
|
|||||||
@@ -94,3 +94,81 @@ jobs:
|
|||||||
name: E2E
|
name: E2E
|
||||||
uses: standardnotes/server/.github/workflows/common-e2e.yml@main
|
uses: standardnotes/server/.github/workflows/common-e2e.yml@main
|
||||||
secrets: inherit
|
secrets: inherit
|
||||||
|
|
||||||
|
legacy_e2e:
|
||||||
|
needs: build
|
||||||
|
name: Legacy E2E
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
application:
|
||||||
|
- { "service_name": "api-gateway", "workspace_name": "@standardnotes/api-gateway", "e2e_tag_parameter_name": "api_gateway_image_tag", "package_path": "packages/api-gateway" }
|
||||||
|
- { "service_name": "auth", "workspace_name": "@standardnotes/auth-server", "e2e_tag_parameter_name": "auth_image_tag", "package_path": "packages/auth" }
|
||||||
|
- { "service_name": "files", "workspace_name": "@standardnotes/files-server", "e2e_tag_parameter_name": "files_image_tag", "package_path": "packages/files" }
|
||||||
|
- { "service_name": "revisions", "workspace_name": "@standardnotes/revisions-server", "e2e_tag_parameter_name": "revisions_image_tag", "package_path": "packages/revisions"}
|
||||||
|
- { "service_name": "syncing-server-js", "workspace_name": "@standardnotes/syncing-server", "e2e_tag_parameter_name": "syncing_server_js_image_tag", "package_path": "packages/syncing-server" }
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Create Bundle Dir
|
||||||
|
id: bundle-dir
|
||||||
|
run: echo "temp_dir=$(mktemp -d -t ${{ matrix.application.service_name }}-${{ github.sha }}-XXXXXXX)" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
|
- name: Cache build
|
||||||
|
id: cache-build
|
||||||
|
uses: actions/cache@v3
|
||||||
|
with:
|
||||||
|
path: |
|
||||||
|
packages/**/dist
|
||||||
|
${{ needs.legacy_e2e.outputs.temp_dir }}
|
||||||
|
key: ${{ runner.os }}-build-${{ github.sha }}
|
||||||
|
|
||||||
|
- name: Set up Node
|
||||||
|
uses: actions/setup-node@v3
|
||||||
|
with:
|
||||||
|
registry-url: 'https://registry.npmjs.org'
|
||||||
|
node-version-file: '.nvmrc'
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
if: steps.cache-build.outputs.cache-hit != 'true'
|
||||||
|
run: yarn build
|
||||||
|
|
||||||
|
- name: Bundle
|
||||||
|
run: yarn workspace ${{ matrix.application.workspace_name }} bundle --no-compress --output-directory ${{ steps.bundle-dir.outputs.temp_dir }}
|
||||||
|
|
||||||
|
- name: Login to Docker Hub
|
||||||
|
uses: docker/login-action@v2
|
||||||
|
with:
|
||||||
|
username: ${{ secrets.DOCKER_USERNAME }}
|
||||||
|
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||||
|
- name: Set up QEMU
|
||||||
|
uses: docker/setup-qemu-action@master
|
||||||
|
with:
|
||||||
|
platforms: all
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
id: buildx
|
||||||
|
uses: docker/setup-buildx-action@master
|
||||||
|
|
||||||
|
- name: Publish Docker image for E2E testing
|
||||||
|
uses: docker/build-push-action@v3
|
||||||
|
with:
|
||||||
|
builder: ${{ steps.buildx.outputs.name }}
|
||||||
|
context: ${{ steps.bundle-dir.outputs.temp_dir }}
|
||||||
|
file: ${{ steps.bundle-dir.outputs.temp_dir }}/${{ matrix.application.package_path }}/Dockerfile
|
||||||
|
platforms: linux/amd64,linux/arm64
|
||||||
|
push: true
|
||||||
|
tags: standardnotes/${{ matrix.application.service_name }}:${{ github.sha }}
|
||||||
|
|
||||||
|
- name: Run E2E test suite
|
||||||
|
uses: convictional/trigger-workflow-and-wait@master
|
||||||
|
with:
|
||||||
|
owner: standardnotes
|
||||||
|
repo: self-hosted
|
||||||
|
github_token: ${{ secrets.CI_PAT_TOKEN }}
|
||||||
|
workflow_file_name: testing-with-updating-client-and-server.yml
|
||||||
|
wait_interval: 30
|
||||||
|
client_payload: '{"${{ matrix.application.e2e_tag_parameter_name }}": "${{ github.sha }}"}'
|
||||||
|
propagate_failure: true
|
||||||
|
trigger_workflow: true
|
||||||
|
wait_workflow: true
|
||||||
|
|||||||
@@ -88,15 +88,23 @@ jobs:
|
|||||||
- name: Test
|
- name: Test
|
||||||
run: yarn test
|
run: yarn test
|
||||||
|
|
||||||
|
e2e:
|
||||||
|
needs: build
|
||||||
|
name: E2E
|
||||||
|
uses: standardnotes/server/.github/workflows/common-e2e.yml@main
|
||||||
|
secrets: inherit
|
||||||
|
|
||||||
publish-self-hosting:
|
publish-self-hosting:
|
||||||
needs: [ test, lint ]
|
needs: [ test, lint, e2e ]
|
||||||
name: Publish Self Hosting Docker Image
|
name: Publish Self Hosting Docker Image
|
||||||
uses: standardnotes/server/.github/workflows/common-self-hosting.yml@main
|
uses: standardnotes/server/.github/workflows/common-self-hosting.yml@main
|
||||||
secrets: inherit
|
secrets: inherit
|
||||||
|
|
||||||
publish-services:
|
publish-services:
|
||||||
|
needs: [ test, lint, e2e ]
|
||||||
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: publish-self-hosting
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
|
|||||||
@@ -4507,7 +4507,6 @@ const RAW_RUNTIME_STATE =
|
|||||||
["@types/dotenv", "npm:8.2.0"],\
|
["@types/dotenv", "npm:8.2.0"],\
|
||||||
["@types/express", "npm:4.17.14"],\
|
["@types/express", "npm:4.17.14"],\
|
||||||
["@types/inversify-express-utils", "npm:2.0.0"],\
|
["@types/inversify-express-utils", "npm:2.0.0"],\
|
||||||
["@types/ioredis", "npm:5.0.0"],\
|
|
||||||
["@types/jest", "npm:29.1.1"],\
|
["@types/jest", "npm:29.1.1"],\
|
||||||
["@types/newrelic", "npm:9.4.0"],\
|
["@types/newrelic", "npm:9.4.0"],\
|
||||||
["@typescript-eslint/eslint-plugin", "virtual:c66bf20e88479ada0172094776519a9f51acc4731d22079b60a295bcec7ea42d5545cbce58a77a50d932bf953298799135e99707486e343da6d99ba1d167bdbd#npm:5.48.2"],\
|
["@typescript-eslint/eslint-plugin", "virtual:c66bf20e88479ada0172094776519a9f51acc4731d22079b60a295bcec7ea42d5545cbce58a77a50d932bf953298799135e99707486e343da6d99ba1d167bdbd#npm:5.48.2"],\
|
||||||
@@ -4516,17 +4515,15 @@ const RAW_RUNTIME_STATE =
|
|||||||
["eslint", "npm:8.32.0"],\
|
["eslint", "npm:8.32.0"],\
|
||||||
["eslint-plugin-prettier", "virtual:c66bf20e88479ada0172094776519a9f51acc4731d22079b60a295bcec7ea42d5545cbce58a77a50d932bf953298799135e99707486e343da6d99ba1d167bdbd#npm:4.2.1"],\
|
["eslint-plugin-prettier", "virtual:c66bf20e88479ada0172094776519a9f51acc4731d22079b60a295bcec7ea42d5545cbce58a77a50d932bf953298799135e99707486e343da6d99ba1d167bdbd#npm:4.2.1"],\
|
||||||
["express", "npm:4.18.2"],\
|
["express", "npm:4.18.2"],\
|
||||||
["helmet", "npm:6.0.0"],\
|
|
||||||
["inversify", "npm:6.0.1"],\
|
["inversify", "npm:6.0.1"],\
|
||||||
["inversify-express-utils", "npm:6.4.3"],\
|
["inversify-express-utils", "npm:6.4.3"],\
|
||||||
["ioredis", "npm:5.2.4"],\
|
|
||||||
["jest", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:29.1.2"],\
|
["jest", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:29.1.2"],\
|
||||||
["mysql2", "npm:3.0.1"],\
|
["mysql2", "npm:3.0.1"],\
|
||||||
["newrelic", "npm:9.8.0"],\
|
["newrelic", "npm:9.8.0"],\
|
||||||
["npm-check-updates", "npm:16.0.1"],\
|
["npm-check-updates", "npm:16.0.1"],\
|
||||||
["reflect-metadata", "npm:0.1.13"],\
|
["reflect-metadata", "npm:0.1.13"],\
|
||||||
["ts-jest", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:29.0.3"],\
|
["ts-jest", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:29.0.3"],\
|
||||||
["typeorm", "virtual:c66bf20e88479ada0172094776519a9f51acc4731d22079b60a295bcec7ea42d5545cbce58a77a50d932bf953298799135e99707486e343da6d99ba1d167bdbd#npm:0.3.10"],\
|
["typeorm", "virtual:365b8c88cdf194291829ee28b79556e2328175d26a621363e703848100bea0042e9500db2a1206c9bbc3a4a76a1d169639ef774b2ea3a1a98584a9936b58c6be#npm:0.3.10"],\
|
||||||
["typescript", "patch:typescript@npm%3A4.8.4#optional!builtin<compat/typescript>::version=4.8.4&hash=701156"],\
|
["typescript", "patch:typescript@npm%3A4.8.4#optional!builtin<compat/typescript>::version=4.8.4&hash=701156"],\
|
||||||
["winston", "npm:3.8.2"]\
|
["winston", "npm:3.8.2"]\
|
||||||
],\
|
],\
|
||||||
@@ -4691,7 +4688,6 @@ const RAW_RUNTIME_STATE =
|
|||||||
["@types/dotenv", "npm:8.2.0"],\
|
["@types/dotenv", "npm:8.2.0"],\
|
||||||
["@types/express", "npm:4.17.14"],\
|
["@types/express", "npm:4.17.14"],\
|
||||||
["@types/inversify-express-utils", "npm:2.0.0"],\
|
["@types/inversify-express-utils", "npm:2.0.0"],\
|
||||||
["@types/ioredis", "npm:5.0.0"],\
|
|
||||||
["@types/jest", "npm:29.1.1"],\
|
["@types/jest", "npm:29.1.1"],\
|
||||||
["@types/jsonwebtoken", "npm:9.0.1"],\
|
["@types/jsonwebtoken", "npm:9.0.1"],\
|
||||||
["@types/newrelic", "npm:9.4.0"],\
|
["@types/newrelic", "npm:9.4.0"],\
|
||||||
@@ -4708,7 +4704,6 @@ const RAW_RUNTIME_STATE =
|
|||||||
["helmet", "npm:6.0.0"],\
|
["helmet", "npm:6.0.0"],\
|
||||||
["inversify", "npm:6.0.1"],\
|
["inversify", "npm:6.0.1"],\
|
||||||
["inversify-express-utils", "npm:6.4.3"],\
|
["inversify-express-utils", "npm:6.4.3"],\
|
||||||
["ioredis", "npm:5.2.4"],\
|
|
||||||
["jest", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:29.1.2"],\
|
["jest", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:29.1.2"],\
|
||||||
["jsonwebtoken", "npm:9.0.0"],\
|
["jsonwebtoken", "npm:9.0.0"],\
|
||||||
["mysql2", "npm:3.0.1"],\
|
["mysql2", "npm:3.0.1"],\
|
||||||
@@ -4718,7 +4713,7 @@ const RAW_RUNTIME_STATE =
|
|||||||
["prettyjson", "npm:1.2.5"],\
|
["prettyjson", "npm:1.2.5"],\
|
||||||
["reflect-metadata", "npm:0.1.13"],\
|
["reflect-metadata", "npm:0.1.13"],\
|
||||||
["ts-jest", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:29.0.3"],\
|
["ts-jest", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:29.0.3"],\
|
||||||
["typeorm", "virtual:c66bf20e88479ada0172094776519a9f51acc4731d22079b60a295bcec7ea42d5545cbce58a77a50d932bf953298799135e99707486e343da6d99ba1d167bdbd#npm:0.3.10"],\
|
["typeorm", "virtual:365b8c88cdf194291829ee28b79556e2328175d26a621363e703848100bea0042e9500db2a1206c9bbc3a4a76a1d169639ef774b2ea3a1a98584a9936b58c6be#npm:0.3.10"],\
|
||||||
["typescript", "patch:typescript@npm%3A4.8.4#optional!builtin<compat/typescript>::version=4.8.4&hash=701156"],\
|
["typescript", "patch:typescript@npm%3A4.8.4#optional!builtin<compat/typescript>::version=4.8.4&hash=701156"],\
|
||||||
["ua-parser-js", "npm:1.0.32"],\
|
["ua-parser-js", "npm:1.0.32"],\
|
||||||
["uuid", "npm:9.0.0"],\
|
["uuid", "npm:9.0.0"],\
|
||||||
@@ -14489,6 +14484,100 @@ const RAW_RUNTIME_STATE =
|
|||||||
],\
|
],\
|
||||||
"linkType": "SOFT"\
|
"linkType": "SOFT"\
|
||||||
}],\
|
}],\
|
||||||
|
["virtual:365b8c88cdf194291829ee28b79556e2328175d26a621363e703848100bea0042e9500db2a1206c9bbc3a4a76a1d169639ef774b2ea3a1a98584a9936b58c6be#npm:0.3.10", {\
|
||||||
|
"packageLocation": "./.yarn/__virtual__/typeorm-virtual-6480afe6bc/0/cache/typeorm-npm-0.3.10-4667857f33-749e1a6777.zip/node_modules/typeorm/",\
|
||||||
|
"packageDependencies": [\
|
||||||
|
["typeorm", "virtual:365b8c88cdf194291829ee28b79556e2328175d26a621363e703848100bea0042e9500db2a1206c9bbc3a4a76a1d169639ef774b2ea3a1a98584a9936b58c6be#npm:0.3.10"],\
|
||||||
|
["@google-cloud/spanner", null],\
|
||||||
|
["@sap/hana-client", null],\
|
||||||
|
["@sqltools/formatter", "npm:1.2.5"],\
|
||||||
|
["@types/better-sqlite3", null],\
|
||||||
|
["@types/google-cloud__spanner", null],\
|
||||||
|
["@types/hdb-pool", null],\
|
||||||
|
["@types/ioredis", null],\
|
||||||
|
["@types/mongodb", null],\
|
||||||
|
["@types/mssql", null],\
|
||||||
|
["@types/mysql2", null],\
|
||||||
|
["@types/oracledb", null],\
|
||||||
|
["@types/pg", null],\
|
||||||
|
["@types/pg-native", null],\
|
||||||
|
["@types/pg-query-stream", null],\
|
||||||
|
["@types/redis", null],\
|
||||||
|
["@types/sap__hana-client", null],\
|
||||||
|
["@types/sql.js", null],\
|
||||||
|
["@types/sqlite3", null],\
|
||||||
|
["@types/ts-node", null],\
|
||||||
|
["@types/typeorm-aurora-data-api-driver", null],\
|
||||||
|
["app-root-path", "npm:3.1.0"],\
|
||||||
|
["better-sqlite3", null],\
|
||||||
|
["buffer", "npm:6.0.3"],\
|
||||||
|
["chalk", "npm:4.1.2"],\
|
||||||
|
["cli-highlight", "npm:2.1.11"],\
|
||||||
|
["date-fns", "npm:2.29.3"],\
|
||||||
|
["debug", "virtual:b86a9fb34323a98c6519528ed55faa0d9b44ca8879307c0b29aa384bde47ff59a7d0c9051b31246f14521dfb71ba3c5d6d0b35c29fffc17bf875aa6ad977d9e8#npm:4.3.4"],\
|
||||||
|
["dotenv", "npm:16.0.3"],\
|
||||||
|
["glob", "npm:7.2.3"],\
|
||||||
|
["hdb-pool", null],\
|
||||||
|
["ioredis", null],\
|
||||||
|
["js-yaml", "npm:4.1.0"],\
|
||||||
|
["mkdirp", "npm:1.0.4"],\
|
||||||
|
["mongodb", null],\
|
||||||
|
["mssql", null],\
|
||||||
|
["mysql2", "npm:3.0.1"],\
|
||||||
|
["oracledb", null],\
|
||||||
|
["pg", null],\
|
||||||
|
["pg-native", null],\
|
||||||
|
["pg-query-stream", null],\
|
||||||
|
["redis", null],\
|
||||||
|
["reflect-metadata", "npm:0.1.13"],\
|
||||||
|
["sha.js", "npm:2.4.11"],\
|
||||||
|
["sql.js", null],\
|
||||||
|
["sqlite3", null],\
|
||||||
|
["ts-node", null],\
|
||||||
|
["tslib", "npm:2.4.0"],\
|
||||||
|
["typeorm-aurora-data-api-driver", null],\
|
||||||
|
["uuid", "npm:8.3.2"],\
|
||||||
|
["xml2js", "npm:0.4.23"],\
|
||||||
|
["yargs", "npm:17.5.1"]\
|
||||||
|
],\
|
||||||
|
"packagePeers": [\
|
||||||
|
"@google-cloud/spanner",\
|
||||||
|
"@sap/hana-client",\
|
||||||
|
"@types/better-sqlite3",\
|
||||||
|
"@types/google-cloud__spanner",\
|
||||||
|
"@types/hdb-pool",\
|
||||||
|
"@types/ioredis",\
|
||||||
|
"@types/mongodb",\
|
||||||
|
"@types/mssql",\
|
||||||
|
"@types/mysql2",\
|
||||||
|
"@types/oracledb",\
|
||||||
|
"@types/pg-native",\
|
||||||
|
"@types/pg-query-stream",\
|
||||||
|
"@types/pg",\
|
||||||
|
"@types/redis",\
|
||||||
|
"@types/sap__hana-client",\
|
||||||
|
"@types/sql.js",\
|
||||||
|
"@types/sqlite3",\
|
||||||
|
"@types/ts-node",\
|
||||||
|
"@types/typeorm-aurora-data-api-driver",\
|
||||||
|
"better-sqlite3",\
|
||||||
|
"hdb-pool",\
|
||||||
|
"ioredis",\
|
||||||
|
"mongodb",\
|
||||||
|
"mssql",\
|
||||||
|
"mysql2",\
|
||||||
|
"oracledb",\
|
||||||
|
"pg-native",\
|
||||||
|
"pg-query-stream",\
|
||||||
|
"pg",\
|
||||||
|
"redis",\
|
||||||
|
"sql.js",\
|
||||||
|
"sqlite3",\
|
||||||
|
"ts-node",\
|
||||||
|
"typeorm-aurora-data-api-driver"\
|
||||||
|
],\
|
||||||
|
"linkType": "HARD"\
|
||||||
|
}],\
|
||||||
["virtual:c66bf20e88479ada0172094776519a9f51acc4731d22079b60a295bcec7ea42d5545cbce58a77a50d932bf953298799135e99707486e343da6d99ba1d167bdbd#npm:0.3.10", {\
|
["virtual:c66bf20e88479ada0172094776519a9f51acc4731d22079b60a295bcec7ea42d5545cbce58a77a50d932bf953298799135e99707486e343da6d99ba1d167bdbd#npm:0.3.10", {\
|
||||||
"packageLocation": "./.yarn/__virtual__/typeorm-virtual-a38286c9d5/0/cache/typeorm-npm-0.3.10-4667857f33-749e1a6777.zip/node_modules/typeorm/",\
|
"packageLocation": "./.yarn/__virtual__/typeorm-virtual-a38286c9d5/0/cache/typeorm-npm-0.3.10-4667857f33-749e1a6777.zip/node_modules/typeorm/",\
|
||||||
"packageDependencies": [\
|
"packageDependencies": [\
|
||||||
|
|||||||
@@ -39,4 +39,8 @@ RUN yarn workspace @standardnotes/files-server bundle --no-compress --output-dir
|
|||||||
RUN yarn workspace @standardnotes/revisions-server bundle --no-compress --output-directory /opt/bundled/revisions
|
RUN yarn workspace @standardnotes/revisions-server bundle --no-compress --output-directory /opt/bundled/revisions
|
||||||
RUN yarn workspace @standardnotes/api-gateway bundle --no-compress --output-directory /opt/bundled/api-gateway
|
RUN yarn workspace @standardnotes/api-gateway bundle --no-compress --output-directory /opt/bundled/api-gateway
|
||||||
|
|
||||||
|
WORKDIR /opt/bundled
|
||||||
|
|
||||||
|
RUN rm -rf /opt/server
|
||||||
|
|
||||||
ENTRYPOINT ["docker-entrypoint.sh"]
|
ENTRYPOINT ["docker-entrypoint.sh"]
|
||||||
|
|||||||
+19
-19
@@ -1,74 +1,74 @@
|
|||||||
[supervisord]
|
[supervisord]
|
||||||
nodaemon=true
|
nodaemon=true
|
||||||
logfile=/tmp/supervisord.log
|
logfile=/var/lib/server/logs/supervisord.log
|
||||||
|
|
||||||
[program:syncing-server]
|
[program:syncing-server]
|
||||||
directory=/opt/bundled/syncing-server
|
directory=/opt/bundled/syncing-server/packages/syncing-server
|
||||||
command=yarn workspace @standardnotes/syncing-server supervisor:start
|
command=/opt/bundled/syncing-server/packages/syncing-server/supervisor/supervisor-server.sh
|
||||||
autostart=true
|
autostart=true
|
||||||
autorestart=true
|
autorestart=true
|
||||||
stdout_logfile=/var/lib/server/logs/syncing-server.log
|
stdout_logfile=/var/lib/server/logs/syncing-server.log
|
||||||
stderr_logfile=/var/lib/server/logs/syncing-server.err
|
stderr_logfile=/var/lib/server/logs/syncing-server.err
|
||||||
|
|
||||||
[program:syncing-server-worker]
|
[program:syncing-server-worker]
|
||||||
directory=/opt/bundled/syncing-server
|
directory=/opt/bundled/syncing-server/packages/syncing-server
|
||||||
command=yarn workspace @standardnotes/syncing-server supervisor:worker
|
command=/opt/bundled/syncing-server/packages/syncing-server/supervisor/supervisor-worker.sh
|
||||||
autostart=true
|
autostart=true
|
||||||
autorestart=true
|
autorestart=true
|
||||||
stdout_logfile=/var/lib/server/logs/syncing-server-worker.log
|
stdout_logfile=/var/lib/server/logs/syncing-server-worker.log
|
||||||
stderr_logfile=/var/lib/server/logs/syncing-server-worker.err
|
stderr_logfile=/var/lib/server/logs/syncing-server-worker.err
|
||||||
|
|
||||||
[program:auth]
|
[program:auth]
|
||||||
directory=/opt/bundled/auth
|
directory=/opt/bundled/auth/packages/auth
|
||||||
command=yarn workspace @standardnotes/auth-server supervisor:start
|
command=/opt/bundled/auth/packages/auth/supervisor/supervisor-server.sh
|
||||||
autostart=true
|
autostart=true
|
||||||
autorestart=true
|
autorestart=true
|
||||||
stdout_logfile=/var/lib/server/logs/auth.log
|
stdout_logfile=/var/lib/server/logs/auth.log
|
||||||
stderr_logfile=/var/lib/server/logs/auth.err
|
stderr_logfile=/var/lib/server/logs/auth.err
|
||||||
|
|
||||||
[program:auth-worker]
|
[program:auth-worker]
|
||||||
directory=/opt/bundled/auth
|
directory=/opt/bundled/auth/packages/auth
|
||||||
command=yarn workspace @standardnotes/auth-server supervisor:worker
|
command=/opt/bundled/auth/packages/auth/supervisor/supervisor-worker.sh
|
||||||
autostart=true
|
autostart=true
|
||||||
autorestart=true
|
autorestart=true
|
||||||
stdout_logfile=/var/lib/server/logs/auth-worker.log
|
stdout_logfile=/var/lib/server/logs/auth-worker.log
|
||||||
stderr_logfile=/var/lib/server/logs/auth-worker.err
|
stderr_logfile=/var/lib/server/logs/auth-worker.err
|
||||||
|
|
||||||
[program:files]
|
[program:files]
|
||||||
directory=/opt/bundled/files
|
directory=/opt/bundled/files/packages/files
|
||||||
command=yarn workspace @standardnotes/files-server supervisor:start
|
command=/opt/bundled/files/packages/files/supervisor/supervisor-server.sh
|
||||||
autostart=true
|
autostart=true
|
||||||
autorestart=true
|
autorestart=true
|
||||||
stdout_logfile=/var/lib/server/logs/files.log
|
stdout_logfile=/var/lib/server/logs/files.log
|
||||||
stderr_logfile=/var/lib/server/logs/files.err
|
stderr_logfile=/var/lib/server/logs/files.err
|
||||||
|
|
||||||
[program:files-worker]
|
[program:files-worker]
|
||||||
directory=/opt/bundled/files
|
directory=/opt/bundled/files/packages/files
|
||||||
command=yarn workspace @standardnotes/files-server supervisor:worker
|
command=/opt/bundled/files/packages/files/supervisor/supervisor-worker.sh
|
||||||
autostart=true
|
autostart=true
|
||||||
autorestart=true
|
autorestart=true
|
||||||
stdout_logfile=/var/lib/server/logs/files-worker.log
|
stdout_logfile=/var/lib/server/logs/files-worker.log
|
||||||
stderr_logfile=/var/lib/server/logs/files-worker.err
|
stderr_logfile=/var/lib/server/logs/files-worker.err
|
||||||
|
|
||||||
[program:revisions]
|
[program:revisions]
|
||||||
directory=/opt/bundled/revisions
|
directory=/opt/bundled/revisions/packages/revisions
|
||||||
command=yarn workspace @standardnotes/revisions-server supervisor:start
|
command=/opt/bundled/revisions/packages/revisions/supervisor/supervisor-server.sh
|
||||||
autostart=true
|
autostart=true
|
||||||
autorestart=true
|
autorestart=true
|
||||||
stdout_logfile=/var/lib/server/logs/revisions.log
|
stdout_logfile=/var/lib/server/logs/revisions.log
|
||||||
stderr_logfile=/var/lib/server/logs/revisions.err
|
stderr_logfile=/var/lib/server/logs/revisions.err
|
||||||
|
|
||||||
[program:revisions-worker]
|
[program:revisions-worker]
|
||||||
directory=/opt/bundled/revisions
|
directory=/opt/bundled/revisions/packages/revisions
|
||||||
command=yarn workspace @standardnotes/revisions-server supervisor:worker
|
command=/opt/bundled/revisions/packages/revisions/supervisor/supervisor-worker.sh
|
||||||
autostart=true
|
autostart=true
|
||||||
autorestart=true
|
autorestart=true
|
||||||
stdout_logfile=/var/lib/server/logs/revisions-worker.log
|
stdout_logfile=/var/lib/server/logs/revisions-worker.log
|
||||||
stderr_logfile=/var/lib/server/logs/revisions-worker.err
|
stderr_logfile=/var/lib/server/logs/revisions-worker.err
|
||||||
|
|
||||||
[program:api-gateway]
|
[program:api-gateway]
|
||||||
directory=/opt/bundled/api-gateway
|
directory=/opt/bundled/api-gateway/packages/api-gateway
|
||||||
command=yarn workspace @standardnotes/api-gateway supervisor:start
|
command=/opt/bundled/api-gateway/packages/api-gateway/supervisor/supervisor-server.sh
|
||||||
autostart=true
|
autostart=true
|
||||||
autorestart=true
|
autorestart=true
|
||||||
stdout_logfile=/var/lib/server/logs/api-gateway.log
|
stdout_logfile=/var/lib/server/logs/api-gateway.log
|
||||||
|
|||||||
@@ -3,6 +3,12 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
# [2.20.0](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.19.16...@standardnotes/analytics@2.20.0) (2023-02-15)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* optimize memory on server utilities ([881a696](https://github.com/standardnotes/server/commit/881a6967aca57d68795af0792114f848ddddf120))
|
||||||
|
|
||||||
## [2.19.16](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.19.15...@standardnotes/analytics@2.19.16) (2023-02-06)
|
## [2.19.16](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.19.15...@standardnotes/analytics@2.19.16) (2023-02-06)
|
||||||
|
|
||||||
**Note:** Version bump only for package @standardnotes/analytics
|
**Note:** Version bump only for package @standardnotes/analytics
|
||||||
|
|||||||
@@ -8,10 +8,10 @@ ENV NODE_ENV production
|
|||||||
|
|
||||||
RUN corepack enable
|
RUN corepack enable
|
||||||
|
|
||||||
WORKDIR /workspace
|
|
||||||
|
|
||||||
COPY ./ /workspace
|
COPY ./ /workspace
|
||||||
|
|
||||||
|
WORKDIR /workspace/packages/analytics
|
||||||
|
|
||||||
ENTRYPOINT [ "/workspace/packages/analytics/docker/entrypoint.sh" ]
|
ENTRYPOINT [ "/workspace/packages/analytics/docker/entrypoint.sh" ]
|
||||||
|
|
||||||
CMD [ "start-worker" ]
|
CMD [ "start-worker" ]
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
'use strict'
|
||||||
|
|
||||||
|
const path = require('path')
|
||||||
|
|
||||||
|
const pnp = require(path.normalize(path.resolve(__dirname, '../../..', '.pnp.cjs'))).setup()
|
||||||
|
|
||||||
|
const index = require(path.normalize(path.resolve(__dirname, '../dist/bin/report.js')))
|
||||||
|
|
||||||
|
Object.defineProperty(exports, '__esModule', { value: true })
|
||||||
|
|
||||||
|
exports.default = index
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
'use strict'
|
||||||
|
|
||||||
|
const path = require('path')
|
||||||
|
|
||||||
|
const pnp = require(path.normalize(path.resolve(__dirname, '../../..', '.pnp.cjs'))).setup()
|
||||||
|
|
||||||
|
const index = require(path.normalize(path.resolve(__dirname, '../dist/bin/worker.js')))
|
||||||
|
|
||||||
|
Object.defineProperty(exports, '__esModule', { value: true })
|
||||||
|
|
||||||
|
exports.default = index
|
||||||
@@ -6,12 +6,12 @@ COMMAND=$1 && shift 1
|
|||||||
case "$COMMAND" in
|
case "$COMMAND" in
|
||||||
'start-worker' )
|
'start-worker' )
|
||||||
echo "[Docker] Starting Worker..."
|
echo "[Docker] Starting Worker..."
|
||||||
yarn workspace @standardnotes/analytics worker
|
node docker/entrypoint-worker.js
|
||||||
;;
|
;;
|
||||||
|
|
||||||
'report' )
|
'report' )
|
||||||
echo "[Docker] Starting Usage Report Generation..."
|
echo "[Docker] Starting Usage Report Generation..."
|
||||||
yarn workspace @standardnotes/analytics report
|
node docker/entrypoint-report.js
|
||||||
;;
|
;;
|
||||||
|
|
||||||
* )
|
* )
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@standardnotes/analytics",
|
"name": "@standardnotes/analytics",
|
||||||
"version": "2.19.16",
|
"version": "2.20.0",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18.0.0 <19.0.0"
|
"node": ">=18.0.0 <19.0.0"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -3,6 +3,22 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
# [1.48.0](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.47.1...@standardnotes/api-gateway@1.48.0) (2023-02-15)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* optimize memory usage ([#444](https://github.com/standardnotes/api-gateway/issues/444)) ([fdf4b29](https://github.com/standardnotes/api-gateway/commit/fdf4b29ae2717e9b5d1fba2722beb7621a7e5c37))
|
||||||
|
|
||||||
|
## [1.47.1](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.47.0...@standardnotes/api-gateway@1.47.1) (2023-02-14)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/api-gateway
|
||||||
|
|
||||||
|
# [1.47.0](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.46.13...@standardnotes/api-gateway@1.47.0) (2023-02-13)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **syncing-server:** refactor container config into server and worker ([#443](https://github.com/standardnotes/api-gateway/issues/443)) ([993d311](https://github.com/standardnotes/api-gateway/commit/993d31167b8b0ac11e3df530d2d1ee566940df6e))
|
||||||
|
|
||||||
## [1.46.13](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.46.12...@standardnotes/api-gateway@1.46.13) (2023-02-09)
|
## [1.46.13](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.46.12...@standardnotes/api-gateway@1.46.13) (2023-02-09)
|
||||||
|
|
||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
|
|||||||
@@ -8,10 +8,10 @@ ENV NODE_ENV production
|
|||||||
|
|
||||||
RUN corepack enable
|
RUN corepack enable
|
||||||
|
|
||||||
WORKDIR /workspace
|
|
||||||
|
|
||||||
COPY ./ /workspace
|
COPY ./ /workspace
|
||||||
|
|
||||||
|
WORKDIR /workspace/packages/api-gateway
|
||||||
|
|
||||||
ENTRYPOINT [ "/workspace/packages/api-gateway/docker/entrypoint.sh" ]
|
ENTRYPOINT [ "/workspace/packages/api-gateway/docker/entrypoint.sh" ]
|
||||||
|
|
||||||
CMD [ "start-web" ]
|
CMD [ "start-web" ]
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
'use strict'
|
||||||
|
|
||||||
|
const path = require('path')
|
||||||
|
|
||||||
|
const pnp = require(path.normalize(path.resolve(__dirname, '../../..', '.pnp.cjs'))).setup()
|
||||||
|
|
||||||
|
const index = require(path.normalize(path.resolve(__dirname, '../dist/bin/server.js')))
|
||||||
|
|
||||||
|
Object.defineProperty(exports, '__esModule', { value: true })
|
||||||
|
|
||||||
|
exports.default = index
|
||||||
@@ -4,16 +4,9 @@ set -e
|
|||||||
COMMAND=$1 && shift 1
|
COMMAND=$1 && shift 1
|
||||||
|
|
||||||
case "$COMMAND" in
|
case "$COMMAND" in
|
||||||
'start-local' )
|
|
||||||
echo "Building the project..."
|
|
||||||
yarn workspace @standardnotes/api-gateway build
|
|
||||||
echo "Starting Web..."
|
|
||||||
yarn workspace @standardnotes/api-gateway start
|
|
||||||
;;
|
|
||||||
|
|
||||||
'start-web' )
|
'start-web' )
|
||||||
echo "Starting Web..."
|
echo "Starting Web..."
|
||||||
yarn workspace @standardnotes/api-gateway start
|
node docker/entrypoint-server.js
|
||||||
;;
|
;;
|
||||||
|
|
||||||
* )
|
* )
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@standardnotes/api-gateway",
|
"name": "@standardnotes/api-gateway",
|
||||||
"version": "1.46.13",
|
"version": "1.48.0",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18.0.0 <19.0.0"
|
"node": ">=18.0.0 <19.0.0"
|
||||||
},
|
},
|
||||||
@@ -16,9 +16,7 @@
|
|||||||
"build": "tsc --build",
|
"build": "tsc --build",
|
||||||
"lint": "eslint . --ext .ts",
|
"lint": "eslint . --ext .ts",
|
||||||
"setup:env": "cp .env.sample .env",
|
"setup:env": "cp .env.sample .env",
|
||||||
"wait-for:revisions": "docker/wait-for.sh localhost $REVISIONS_SERVER_PORT",
|
|
||||||
"start": "yarn node dist/bin/server.js",
|
"start": "yarn node dist/bin/server.js",
|
||||||
"supervisor:start": "yarn wait-for:revisions && yarn node dist/bin/server.js",
|
|
||||||
"upgrade:snjs": "yarn ncu -u '@standardnotes/*'"
|
"upgrade:snjs": "yarn ncu -u '@standardnotes/*'"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|||||||
@@ -1,35 +1,41 @@
|
|||||||
import { Request, Response } from 'express'
|
import { BaseHttpController, controller, httpDelete, httpGet, results } from 'inversify-express-utils'
|
||||||
import { inject } from 'inversify'
|
|
||||||
import { BaseHttpController, controller, httpDelete, httpGet } from 'inversify-express-utils'
|
|
||||||
import TYPES from '../../Bootstrap/Types'
|
import TYPES from '../../Bootstrap/Types'
|
||||||
import { HttpServiceInterface } from '../../Service/Http/HttpServiceInterface'
|
|
||||||
|
|
||||||
@controller('/v1/items/:item_id/revisions', TYPES.AuthMiddleware)
|
@controller('/v1/items/:item_id/revisions', TYPES.AuthMiddleware)
|
||||||
export class RevisionsController extends BaseHttpController {
|
export class RevisionsController extends BaseHttpController {
|
||||||
constructor(@inject(TYPES.HTTPService) private httpService: HttpServiceInterface) {
|
|
||||||
super()
|
|
||||||
}
|
|
||||||
|
|
||||||
@httpGet('/')
|
@httpGet('/')
|
||||||
async getRevisions(request: Request, response: Response): Promise<void> {
|
async getRevisions(): Promise<results.JsonResult> {
|
||||||
await this.httpService.callSyncingServer(request, response, `items/${request.params.item_id}/revisions`)
|
return this.json(
|
||||||
|
{
|
||||||
|
error: {
|
||||||
|
message: 'Please update your client application.',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
410,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@httpGet('/:id')
|
@httpGet('/:id')
|
||||||
async getRevision(request: Request, response: Response): Promise<void> {
|
async getRevision(): Promise<results.JsonResult> {
|
||||||
await this.httpService.callSyncingServer(
|
return this.json(
|
||||||
request,
|
{
|
||||||
response,
|
error: {
|
||||||
`items/${request.params.item_id}/revisions/${request.params.id}`,
|
message: 'Please update your client application.',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
410,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@httpDelete('/:id')
|
@httpDelete('/:id')
|
||||||
async deleteRevision(request: Request, response: Response): Promise<void> {
|
async deleteRevision(): Promise<results.JsonResult> {
|
||||||
await this.httpService.callSyncingServer(
|
return this.json(
|
||||||
request,
|
{
|
||||||
response,
|
error: {
|
||||||
`items/${request.params.item_id}/revisions/${request.params.id}`,
|
message: 'Please update your client application.',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
410,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
sh supervisor/wait-for.sh localhost $SYNCING_SERVER_PORT
|
||||||
|
node docker/entrypoint-server.js
|
||||||
@@ -3,6 +3,16 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
# [1.88.0](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.87.15...@standardnotes/auth-server@1.88.0) (2023-02-15)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* optimize memory usage ([#444](https://github.com/standardnotes/server/issues/444)) ([fdf4b29](https://github.com/standardnotes/server/commit/fdf4b29ae2717e9b5d1fba2722beb7621a7e5c37))
|
||||||
|
|
||||||
|
## [1.87.15](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.87.14...@standardnotes/auth-server@1.87.15) (2023-02-14)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/auth-server
|
||||||
|
|
||||||
## [1.87.14](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.87.13...@standardnotes/auth-server@1.87.14) (2023-02-09)
|
## [1.87.14](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.87.13...@standardnotes/auth-server@1.87.14) (2023-02-09)
|
||||||
|
|
||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
|
|||||||
@@ -8,10 +8,10 @@ ENV NODE_ENV production
|
|||||||
|
|
||||||
RUN corepack enable
|
RUN corepack enable
|
||||||
|
|
||||||
WORKDIR /workspace
|
|
||||||
|
|
||||||
COPY ./ /workspace
|
COPY ./ /workspace
|
||||||
|
|
||||||
|
WORKDIR /workspace/packages/auth
|
||||||
|
|
||||||
ENTRYPOINT [ "/workspace/packages/auth/docker/entrypoint.sh" ]
|
ENTRYPOINT [ "/workspace/packages/auth/docker/entrypoint.sh" ]
|
||||||
|
|
||||||
CMD [ "start-web" ]
|
CMD [ "start-web" ]
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
'use strict'
|
||||||
|
|
||||||
|
const path = require('path')
|
||||||
|
|
||||||
|
const pnp = require(path.normalize(path.resolve(__dirname, '../../..', '.pnp.cjs'))).setup()
|
||||||
|
|
||||||
|
const index = require(path.normalize(path.resolve(__dirname, '../dist/bin/backup.js')))
|
||||||
|
|
||||||
|
Object.defineProperty(exports, '__esModule', { value: true })
|
||||||
|
|
||||||
|
exports.default = index
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
'use strict'
|
||||||
|
|
||||||
|
const path = require('path')
|
||||||
|
|
||||||
|
const pnp = require(path.normalize(path.resolve(__dirname, '../../..', '.pnp.cjs'))).setup()
|
||||||
|
|
||||||
|
const index = require(path.normalize(path.resolve(__dirname, '../dist/bin/cleanup.js')))
|
||||||
|
|
||||||
|
Object.defineProperty(exports, '__esModule', { value: true })
|
||||||
|
|
||||||
|
exports.default = index
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
'use strict'
|
||||||
|
|
||||||
|
const path = require('path')
|
||||||
|
|
||||||
|
const pnp = require(path.normalize(path.resolve(__dirname, '../../..', '.pnp.cjs'))).setup()
|
||||||
|
|
||||||
|
const index = require(path.normalize(path.resolve(__dirname, '../dist/bin/content.js')))
|
||||||
|
|
||||||
|
Object.defineProperty(exports, '__esModule', { value: true })
|
||||||
|
|
||||||
|
exports.default = index
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
'use strict'
|
||||||
|
|
||||||
|
const path = require('path')
|
||||||
|
|
||||||
|
const pnp = require(path.normalize(path.resolve(__dirname, '../../..', '.pnp.cjs'))).setup()
|
||||||
|
|
||||||
|
const index = require(path.normalize(path.resolve(__dirname, '../dist/bin/server.js')))
|
||||||
|
|
||||||
|
Object.defineProperty(exports, '__esModule', { value: true })
|
||||||
|
|
||||||
|
exports.default = index
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
'use strict'
|
||||||
|
|
||||||
|
const path = require('path')
|
||||||
|
|
||||||
|
const pnp = require(path.normalize(path.resolve(__dirname, '../../..', '.pnp.cjs'))).setup()
|
||||||
|
|
||||||
|
const index = require(path.normalize(path.resolve(__dirname, '../dist/bin/stats.js')))
|
||||||
|
|
||||||
|
Object.defineProperty(exports, '__esModule', { value: true })
|
||||||
|
|
||||||
|
exports.default = index
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
'use strict'
|
||||||
|
|
||||||
|
const path = require('path')
|
||||||
|
|
||||||
|
const pnp = require(path.normalize(path.resolve(__dirname, '../../..', '.pnp.cjs'))).setup()
|
||||||
|
|
||||||
|
const index = require(path.normalize(path.resolve(__dirname, '../dist/bin/user_email_backup.js')))
|
||||||
|
|
||||||
|
Object.defineProperty(exports, '__esModule', { value: true })
|
||||||
|
|
||||||
|
exports.default = index
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
'use strict'
|
||||||
|
|
||||||
|
const path = require('path')
|
||||||
|
|
||||||
|
const pnp = require(path.normalize(path.resolve(__dirname, '../../..', '.pnp.cjs'))).setup()
|
||||||
|
|
||||||
|
const index = require(path.normalize(path.resolve(__dirname, '../dist/bin/worker.js')))
|
||||||
|
|
||||||
|
Object.defineProperty(exports, '__esModule', { value: true })
|
||||||
|
|
||||||
|
exports.default = index
|
||||||
@@ -4,65 +4,60 @@ set -e
|
|||||||
COMMAND=$1 && shift 1
|
COMMAND=$1 && shift 1
|
||||||
|
|
||||||
case "$COMMAND" in
|
case "$COMMAND" in
|
||||||
'start-local' )
|
|
||||||
echo "[Docker] Starting Web..."
|
|
||||||
yarn workspace @standardnotes/auth-server start:local
|
|
||||||
;;
|
|
||||||
|
|
||||||
'start-web' )
|
'start-web' )
|
||||||
echo "[Docker] Starting Web..."
|
echo "[Docker] Starting Web..."
|
||||||
yarn workspace @standardnotes/auth-server start
|
node docker/entrypoint-server.js
|
||||||
;;
|
;;
|
||||||
|
|
||||||
'start-worker' )
|
'start-worker' )
|
||||||
echo "[Docker] Starting Worker..."
|
echo "[Docker] Starting Worker..."
|
||||||
yarn workspace @standardnotes/auth-server worker
|
node docker/entrypoint-worker.js
|
||||||
;;
|
;;
|
||||||
|
|
||||||
'cleanup' )
|
'cleanup' )
|
||||||
echo "[Docker] Starting Cleanup..."
|
echo "[Docker] Starting Cleanup..."
|
||||||
yarn workspace @standardnotes/auth-server cleanup
|
node docker/entrypoint-cleanup.js
|
||||||
;;
|
;;
|
||||||
|
|
||||||
'stats' )
|
'stats' )
|
||||||
echo "[Docker] Starting Persisting Stats..."
|
echo "[Docker] Starting Persisting Stats..."
|
||||||
yarn workspace @standardnotes/auth-server stats
|
node docker/entrypoint-stats.js
|
||||||
;;
|
;;
|
||||||
|
|
||||||
'email-daily-backup' )
|
'email-daily-backup' )
|
||||||
echo "[Docker] Starting Email Daily Backup..."
|
echo "[Docker] Starting Email Daily Backup..."
|
||||||
yarn workspace @standardnotes/auth-server daily-backup:email
|
node docker/entrypoint-backup.js email daily
|
||||||
;;
|
;;
|
||||||
|
|
||||||
'email-weekly-backup' )
|
'email-weekly-backup' )
|
||||||
echo "[Docker] Starting Email Weekly Backup..."
|
echo "[Docker] Starting Email Weekly Backup..."
|
||||||
yarn workspace @standardnotes/auth-server weekly-backup:email
|
node docker/entrypoint-backup.js email weekly
|
||||||
;;
|
;;
|
||||||
|
|
||||||
'email-backup' )
|
'email-backup' )
|
||||||
echo "[Docker] Starting Email Backup For Single User..."
|
echo "[Docker] Starting Email Backup For Single User..."
|
||||||
EMAIL=$1 && shift 1
|
EMAIL=$1 && shift 1
|
||||||
yarn workspace @standardnotes/auth-server user-email-backup $EMAIL
|
node docker/entrypoint-user-email-backup.js $EMAIL
|
||||||
;;
|
;;
|
||||||
|
|
||||||
'dropbox-daily-backup' )
|
'dropbox-daily-backup' )
|
||||||
echo "[Docker] Starting Dropbox Daily Backup..."
|
echo "[Docker] Starting Dropbox Daily Backup..."
|
||||||
yarn workspace @standardnotes/auth-server daily-backup:dropbox
|
node docker/entrypoint-backup.js dropbox daily
|
||||||
;;
|
;;
|
||||||
|
|
||||||
'google-drive-daily-backup' )
|
'google-drive-daily-backup' )
|
||||||
echo "[Docker] Starting Google Drive Daily Backup..."
|
echo "[Docker] Starting Google Drive Daily Backup..."
|
||||||
yarn workspace @standardnotes/auth-server daily-backup:google_drive
|
node docker/entrypoint-backup.js google_drive daily
|
||||||
;;
|
;;
|
||||||
|
|
||||||
'one-drive-daily-backup' )
|
'one-drive-daily-backup' )
|
||||||
echo "[Docker] Starting One Drive Daily Backup..."
|
echo "[Docker] Starting One Drive Daily Backup..."
|
||||||
yarn workspace @standardnotes/auth-server daily-backup:one_drive
|
node docker/entrypoint-backup.js one_drive daily
|
||||||
;;
|
;;
|
||||||
|
|
||||||
'content-recalculation' )
|
'content-recalculation' )
|
||||||
echo "[Docker] Starting Content Size Recalculation..."
|
echo "[Docker] Starting Content Size Recalculation..."
|
||||||
yarn workspace @standardnotes/auth-server content-recalculation
|
node docker/entrypoint-content.js
|
||||||
;;
|
;;
|
||||||
|
|
||||||
* )
|
* )
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@standardnotes/auth-server",
|
"name": "@standardnotes/auth-server",
|
||||||
"version": "1.87.14",
|
"version": "1.88.0",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18.0.0 <19.0.0"
|
"node": ">=18.0.0 <19.0.0"
|
||||||
},
|
},
|
||||||
@@ -17,12 +17,8 @@
|
|||||||
"lint": "eslint . --ext .ts",
|
"lint": "eslint . --ext .ts",
|
||||||
"pretest": "yarn lint && yarn build",
|
"pretest": "yarn lint && yarn build",
|
||||||
"test": "jest --coverage --config=./jest.config.js --maxWorkers=50%",
|
"test": "jest --coverage --config=./jest.config.js --maxWorkers=50%",
|
||||||
"wait-for:syncing-server": "docker/wait-for.sh localhost $SYNCING_SERVER_PORT",
|
|
||||||
"wait-for:auth": "docker/wait-for.sh localhost $AUTH_SERVER_PORT",
|
|
||||||
"start": "yarn node dist/bin/server.js",
|
"start": "yarn node dist/bin/server.js",
|
||||||
"supervisor:start": "yarn wait-for:syncing-server && yarn node dist/bin/server.js",
|
|
||||||
"worker": "yarn node dist/bin/worker.js",
|
"worker": "yarn node dist/bin/worker.js",
|
||||||
"supervisor:worker": "yarn wait-for:auth && yarn node dist/bin/worker.js",
|
|
||||||
"cleanup": "yarn node dist/bin/cleanup.js",
|
"cleanup": "yarn node dist/bin/cleanup.js",
|
||||||
"stats": "yarn node dist/bin/stats.js",
|
"stats": "yarn node dist/bin/stats.js",
|
||||||
"daily-backup:email": "yarn node dist/bin/backup.js email daily",
|
"daily-backup:email": "yarn node dist/bin/backup.js email daily",
|
||||||
|
|||||||
+6
@@ -0,0 +1,6 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
sh supervisor/wait-for.sh localhost $SYNCING_SERVER_PORT
|
||||||
|
node docker/entrypoint-server.js
|
||||||
+6
@@ -0,0 +1,6 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
sh supervisor/wait-for.sh localhost $AUTH_SERVER_PORT
|
||||||
|
node docker/entrypoint-worker.js
|
||||||
@@ -3,6 +3,12 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
# [1.7.0](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.6.68...@standardnotes/event-store@1.7.0) (2023-02-15)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* optimize memory on server utilities ([881a696](https://github.com/standardnotes/server/commit/881a6967aca57d68795af0792114f848ddddf120))
|
||||||
|
|
||||||
## [1.6.68](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.6.67...@standardnotes/event-store@1.6.68) (2023-01-30)
|
## [1.6.68](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.6.67...@standardnotes/event-store@1.6.68) (2023-01-30)
|
||||||
|
|
||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
|
|||||||
@@ -8,10 +8,10 @@ ENV NODE_ENV production
|
|||||||
|
|
||||||
RUN corepack enable
|
RUN corepack enable
|
||||||
|
|
||||||
WORKDIR /workspace
|
|
||||||
|
|
||||||
COPY ./ /workspace
|
COPY ./ /workspace
|
||||||
|
|
||||||
|
WORKDIR /workspace/packages/event-store
|
||||||
|
|
||||||
ENTRYPOINT [ "/workspace/packages/event-store/docker/entrypoint.sh" ]
|
ENTRYPOINT [ "/workspace/packages/event-store/docker/entrypoint.sh" ]
|
||||||
|
|
||||||
CMD [ "start-worker" ]
|
CMD [ "start-worker" ]
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
'use strict'
|
||||||
|
|
||||||
|
const path = require('path')
|
||||||
|
|
||||||
|
const pnp = require(path.normalize(path.resolve(__dirname, '../../..', '.pnp.cjs'))).setup()
|
||||||
|
|
||||||
|
const index = require(path.normalize(path.resolve(__dirname, '../dist/bin/worker.js')))
|
||||||
|
|
||||||
|
Object.defineProperty(exports, '__esModule', { value: true })
|
||||||
|
|
||||||
|
exports.default = index
|
||||||
@@ -6,7 +6,7 @@ COMMAND=$1 && shift 1
|
|||||||
case "$COMMAND" in
|
case "$COMMAND" in
|
||||||
'start-worker' )
|
'start-worker' )
|
||||||
echo "Starting Worker..."
|
echo "Starting Worker..."
|
||||||
yarn workspace @standardnotes/event-store worker
|
node docker/entrypoint-worker.js
|
||||||
;;
|
;;
|
||||||
|
|
||||||
* )
|
* )
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@standardnotes/event-store",
|
"name": "@standardnotes/event-store",
|
||||||
"version": "1.6.68",
|
"version": "1.7.0",
|
||||||
"description": "Event Store Service",
|
"description": "Event Store Service",
|
||||||
"private": true,
|
"private": true,
|
||||||
"main": "dist/src/index.js",
|
"main": "dist/src/index.js",
|
||||||
|
|||||||
@@ -3,6 +3,16 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
# [1.10.0](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.9.18...@standardnotes/files-server@1.10.0) (2023-02-15)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* optimize memory usage ([#444](https://github.com/standardnotes/files/issues/444)) ([fdf4b29](https://github.com/standardnotes/files/commit/fdf4b29ae2717e9b5d1fba2722beb7621a7e5c37))
|
||||||
|
|
||||||
|
## [1.9.18](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.9.17...@standardnotes/files-server@1.9.18) (2023-02-14)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/files-server
|
||||||
|
|
||||||
## [1.9.17](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.9.16...@standardnotes/files-server@1.9.17) (2023-02-09)
|
## [1.9.17](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.9.16...@standardnotes/files-server@1.9.17) (2023-02-09)
|
||||||
|
|
||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
|
|||||||
@@ -8,10 +8,10 @@ ENV NODE_ENV production
|
|||||||
|
|
||||||
RUN corepack enable
|
RUN corepack enable
|
||||||
|
|
||||||
WORKDIR /workspace
|
|
||||||
|
|
||||||
COPY ./ /workspace
|
COPY ./ /workspace
|
||||||
|
|
||||||
|
WORKDIR /workspace/packages/files
|
||||||
|
|
||||||
ENTRYPOINT [ "/workspace/packages/files/docker/entrypoint.sh" ]
|
ENTRYPOINT [ "/workspace/packages/files/docker/entrypoint.sh" ]
|
||||||
|
|
||||||
CMD [ "start-web" ]
|
CMD [ "start-web" ]
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
'use strict'
|
||||||
|
|
||||||
|
const path = require('path')
|
||||||
|
|
||||||
|
const pnp = require(path.normalize(path.resolve(__dirname, '../../..', '.pnp.cjs'))).setup()
|
||||||
|
|
||||||
|
const index = require(path.normalize(path.resolve(__dirname, '../dist/bin/server.js')))
|
||||||
|
|
||||||
|
Object.defineProperty(exports, '__esModule', { value: true })
|
||||||
|
|
||||||
|
exports.default = index
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
'use strict'
|
||||||
|
|
||||||
|
const path = require('path')
|
||||||
|
|
||||||
|
const pnp = require(path.normalize(path.resolve(__dirname, '../../..', '.pnp.cjs'))).setup()
|
||||||
|
|
||||||
|
const index = require(path.normalize(path.resolve(__dirname, '../dist/bin/worker.js')))
|
||||||
|
|
||||||
|
Object.defineProperty(exports, '__esModule', { value: true })
|
||||||
|
|
||||||
|
exports.default = index
|
||||||
@@ -4,19 +4,14 @@ set -e
|
|||||||
COMMAND=$1 && shift 1
|
COMMAND=$1 && shift 1
|
||||||
|
|
||||||
case "$COMMAND" in
|
case "$COMMAND" in
|
||||||
'start-local')
|
|
||||||
echo "Starting Web in Local Mode..."
|
|
||||||
yarn workspace @standardnotes/files-server start:local
|
|
||||||
;;
|
|
||||||
|
|
||||||
'start-web' )
|
'start-web' )
|
||||||
echo "Starting Web..."
|
echo "Starting Web..."
|
||||||
yarn workspace @standardnotes/files-server start
|
node docker/entrypoint-server.js
|
||||||
;;
|
;;
|
||||||
|
|
||||||
'start-worker' )
|
'start-worker' )
|
||||||
echo "Starting Worker..."
|
echo "Starting Worker..."
|
||||||
yarn workspace @standardnotes/files-server worker
|
node docker/entrypoint-worker.js
|
||||||
;;
|
;;
|
||||||
|
|
||||||
* )
|
* )
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@standardnotes/files-server",
|
"name": "@standardnotes/files-server",
|
||||||
"version": "1.9.17",
|
"version": "1.10.0",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18.0.0 <19.0.0"
|
"node": ">=18.0.0 <19.0.0"
|
||||||
},
|
},
|
||||||
@@ -20,12 +20,8 @@
|
|||||||
"lint": "eslint . --ext .ts",
|
"lint": "eslint . --ext .ts",
|
||||||
"pretest": "yarn lint && yarn build",
|
"pretest": "yarn lint && yarn build",
|
||||||
"test": "jest --coverage --config=./jest.config.js --maxWorkers=50%",
|
"test": "jest --coverage --config=./jest.config.js --maxWorkers=50%",
|
||||||
"wait-for:auth": "docker/wait-for.sh localhost $AUTH_SERVER_PORT",
|
|
||||||
"wait-for:files": "docker/wait-for.sh localhost $FILES_SERVER_PORT",
|
|
||||||
"start": "yarn node dist/bin/server.js",
|
"start": "yarn node dist/bin/server.js",
|
||||||
"supervisor:start": "yarn wait-for:auth && yarn node dist/bin/server.js",
|
|
||||||
"worker": "yarn node dist/bin/worker.js",
|
"worker": "yarn node dist/bin/worker.js",
|
||||||
"supervisor:worker": "yarn wait-for:files && yarn node dist/bin/worker.js",
|
|
||||||
"upgrade:snjs": "yarn ncu -u '@standardnotes/*'"
|
"upgrade:snjs": "yarn ncu -u '@standardnotes/*'"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|||||||
+7
@@ -0,0 +1,7 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
sh supervisor/wait-for.sh $DB_HOST $DB_PORT
|
||||||
|
sh supervisor/wait-for.sh $REDIS_HOST $REDIS_PORT
|
||||||
|
node docker/entrypoint-server.js
|
||||||
+6
@@ -0,0 +1,6 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
sh supervisor/wait-for.sh localhost $SYNCING_SERVER_PORT
|
||||||
|
node docker/entrypoint-worker.js
|
||||||
@@ -3,6 +3,57 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
# [1.12.0](https://github.com/standardnotes/server/compare/@standardnotes/revisions-server@1.11.6...@standardnotes/revisions-server@1.12.0) (2023-02-15)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* optimize memory usage ([#444](https://github.com/standardnotes/server/issues/444)) ([fdf4b29](https://github.com/standardnotes/server/commit/fdf4b29ae2717e9b5d1fba2722beb7621a7e5c37))
|
||||||
|
|
||||||
|
## [1.11.6](https://github.com/standardnotes/server/compare/@standardnotes/revisions-server@1.11.5...@standardnotes/revisions-server@1.11.6) (2023-02-14)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/revisions-server
|
||||||
|
|
||||||
|
## [1.11.5](https://github.com/standardnotes/server/compare/@standardnotes/revisions-server@1.11.4...@standardnotes/revisions-server@1.11.5) (2023-02-13)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **revisions:** api gateway middleware binding ([d333c13](https://github.com/standardnotes/server/commit/d333c1393c67899a6303dbec40527584cd1b48ab))
|
||||||
|
|
||||||
|
## [1.11.4](https://github.com/standardnotes/server/compare/@standardnotes/revisions-server@1.11.3...@standardnotes/revisions-server@1.11.4) (2023-02-13)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **revisions:** missing api gateway middleware ([826719b](https://github.com/standardnotes/server/commit/826719bb67dd403e4880ab61b25c92c4506e3c57))
|
||||||
|
|
||||||
|
## [1.11.3](https://github.com/standardnotes/server/compare/@standardnotes/revisions-server@1.11.2...@standardnotes/revisions-server@1.11.3) (2023-02-13)
|
||||||
|
|
||||||
|
### Reverts
|
||||||
|
|
||||||
|
* Revert "fix(revisions): remove inversify.js in favour of simple di container implementation (#442)" ([73f3fad](https://github.com/standardnotes/server/commit/73f3fad13da57619f008ed486c1d4114f3bad3b6)), closes [#442](https://github.com/standardnotes/server/issues/442)
|
||||||
|
|
||||||
|
## [1.11.2](https://github.com/standardnotes/server/compare/@standardnotes/revisions-server@1.11.1...@standardnotes/revisions-server@1.11.2) (2023-02-10)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **revisions:** remove inversify.js in favour of simple di container implementation ([#442](https://github.com/standardnotes/server/issues/442)) ([89ee103](https://github.com/standardnotes/server/commit/89ee103303651b2b181c3b79b7a500358165dcf2))
|
||||||
|
|
||||||
|
## [1.11.1](https://github.com/standardnotes/server/compare/@standardnotes/revisions-server@1.11.0...@standardnotes/revisions-server@1.11.1) (2023-02-10)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **revisions:** remove missing middleware binding ([622c024](https://github.com/standardnotes/server/commit/622c024547126a7580274d7e368f3787b809f7bc))
|
||||||
|
|
||||||
|
# [1.11.0](https://github.com/standardnotes/server/compare/@standardnotes/revisions-server@1.10.30...@standardnotes/revisions-server@1.11.0) (2023-02-10)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **revisions:** controller bindings ([645a24d](https://github.com/standardnotes/server/commit/645a24d29b2d1858251b80a8d453c98b955c79e3))
|
||||||
|
* **revisions:** remove the interval ping ([be17b67](https://github.com/standardnotes/server/commit/be17b67cc1ff27c62dfee571f7d85954c1401fda))
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **revisions:** refactor container to split worker and server containers ([5120883](https://github.com/standardnotes/server/commit/512088369152766027cb25f1566fd2295ab75ac3))
|
||||||
|
|
||||||
## [1.10.30](https://github.com/standardnotes/server/compare/@standardnotes/revisions-server@1.10.29...@standardnotes/revisions-server@1.10.30) (2023-02-09)
|
## [1.10.30](https://github.com/standardnotes/server/compare/@standardnotes/revisions-server@1.10.29...@standardnotes/revisions-server@1.10.30) (2023-02-09)
|
||||||
|
|
||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
|
|||||||
@@ -8,10 +8,10 @@ ENV NODE_ENV production
|
|||||||
|
|
||||||
RUN corepack enable
|
RUN corepack enable
|
||||||
|
|
||||||
WORKDIR /workspace
|
|
||||||
|
|
||||||
COPY ./ /workspace
|
COPY ./ /workspace
|
||||||
|
|
||||||
|
WORKDIR /workspace/packages/revisions
|
||||||
|
|
||||||
ENTRYPOINT [ "/workspace/packages/revisions/docker/entrypoint.sh" ]
|
ENTRYPOINT [ "/workspace/packages/revisions/docker/entrypoint.sh" ]
|
||||||
|
|
||||||
CMD [ "start-web" ]
|
CMD [ "start-web" ]
|
||||||
|
|||||||
@@ -4,22 +4,21 @@ import 'newrelic'
|
|||||||
|
|
||||||
import * as Sentry from '@sentry/node'
|
import * as Sentry from '@sentry/node'
|
||||||
|
|
||||||
import '../src/Infra/InversifyExpress/InversifyExpressRevisionsController'
|
|
||||||
import '../src/Infra/InversifyExpress/InversifyExpressHealthCheckController'
|
|
||||||
|
|
||||||
import * as cors from 'cors'
|
import * as cors from 'cors'
|
||||||
import { urlencoded, json, Request, Response, NextFunction, RequestHandler, ErrorRequestHandler } from 'express'
|
import { urlencoded, json, Request, Response, NextFunction, RequestHandler, ErrorRequestHandler } from 'express'
|
||||||
import * as winston from 'winston'
|
import * as winston from 'winston'
|
||||||
|
|
||||||
import { InversifyExpressServer } from 'inversify-express-utils'
|
import { InversifyExpressServer } from 'inversify-express-utils'
|
||||||
import { ContainerConfigLoader } from '../src/Bootstrap/Container'
|
|
||||||
import TYPES from '../src/Bootstrap/Types'
|
import TYPES from '../src/Bootstrap/Types'
|
||||||
import { Env } from '../src/Bootstrap/Env'
|
import { Env } from '../src/Bootstrap/Env'
|
||||||
|
import { ServerContainerConfigLoader } from '../src/Bootstrap/ServerContainerConfigLoader'
|
||||||
|
|
||||||
const container = new ContainerConfigLoader()
|
import '../src/Infra/InversifyExpress/InversifyExpressRevisionsController'
|
||||||
|
import '../src/Infra/InversifyExpress/InversifyExpressHealthCheckController'
|
||||||
|
|
||||||
|
const container = new ServerContainerConfigLoader()
|
||||||
void container.load().then((container) => {
|
void container.load().then((container) => {
|
||||||
const env: Env = new Env()
|
const env: Env = container.get(TYPES.Env)
|
||||||
env.load()
|
|
||||||
|
|
||||||
const server = new InversifyExpressServer(container)
|
const server = new InversifyExpressServer(container)
|
||||||
|
|
||||||
|
|||||||
@@ -4,12 +4,12 @@ import 'newrelic'
|
|||||||
|
|
||||||
import { Logger } from 'winston'
|
import { Logger } from 'winston'
|
||||||
|
|
||||||
import { ContainerConfigLoader } from '../src/Bootstrap/Container'
|
|
||||||
import TYPES from '../src/Bootstrap/Types'
|
import TYPES from '../src/Bootstrap/Types'
|
||||||
import { Env } from '../src/Bootstrap/Env'
|
import { Env } from '../src/Bootstrap/Env'
|
||||||
import { DomainEventSubscriberFactoryInterface } from '@standardnotes/domain-events'
|
import { DomainEventSubscriberFactoryInterface } from '@standardnotes/domain-events'
|
||||||
|
import { WorkerContainerConfigLoader } from '../src/Bootstrap/WorkerContainerConfigLoader'
|
||||||
|
|
||||||
const container = new ContainerConfigLoader()
|
const container = new WorkerContainerConfigLoader()
|
||||||
void container.load().then((container) => {
|
void container.load().then((container) => {
|
||||||
const env: Env = new Env()
|
const env: Env = new Env()
|
||||||
env.load()
|
env.load()
|
||||||
@@ -20,6 +20,4 @@ void container.load().then((container) => {
|
|||||||
|
|
||||||
const subscriberFactory: DomainEventSubscriberFactoryInterface = container.get(TYPES.DomainEventSubscriberFactory)
|
const subscriberFactory: DomainEventSubscriberFactoryInterface = container.get(TYPES.DomainEventSubscriberFactory)
|
||||||
subscriberFactory.create().start()
|
subscriberFactory.create().start()
|
||||||
|
|
||||||
setInterval(() => logger.info('Alive and kicking!'), 20 * 60 * 1000)
|
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
'use strict'
|
||||||
|
|
||||||
|
const path = require('path')
|
||||||
|
|
||||||
|
const pnp = require(path.normalize(path.resolve(__dirname, '../../..', '.pnp.cjs'))).setup()
|
||||||
|
|
||||||
|
const index = require(path.normalize(path.resolve(__dirname, '../dist/bin/server.js')))
|
||||||
|
|
||||||
|
Object.defineProperty(exports, '__esModule', { value: true })
|
||||||
|
|
||||||
|
exports.default = index
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
'use strict'
|
||||||
|
|
||||||
|
const path = require('path')
|
||||||
|
|
||||||
|
const pnp = require(path.normalize(path.resolve(__dirname, '../../..', '.pnp.cjs'))).setup()
|
||||||
|
|
||||||
|
const index = require(path.normalize(path.resolve(__dirname, '../dist/bin/worker.js')))
|
||||||
|
|
||||||
|
Object.defineProperty(exports, '__esModule', { value: true })
|
||||||
|
|
||||||
|
exports.default = index
|
||||||
@@ -6,12 +6,12 @@ COMMAND=$1 && shift 1
|
|||||||
case "$COMMAND" in
|
case "$COMMAND" in
|
||||||
'start-web' )
|
'start-web' )
|
||||||
echo "Starting Web..."
|
echo "Starting Web..."
|
||||||
yarn workspace @standardnotes/revisions-server start
|
node docker/entrypoint-server.js
|
||||||
;;
|
;;
|
||||||
|
|
||||||
'start-worker' )
|
'start-worker' )
|
||||||
echo "Starting Worker..."
|
echo "Starting Worker..."
|
||||||
yarn workspace @standardnotes/revisions-server worker
|
node docker/entrypoint-worker.js
|
||||||
;;
|
;;
|
||||||
|
|
||||||
* )
|
* )
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@standardnotes/revisions-server",
|
"name": "@standardnotes/revisions-server",
|
||||||
"version": "1.10.30",
|
"version": "1.12.0",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18.0.0 <19.0.0"
|
"node": ">=18.0.0 <19.0.0"
|
||||||
},
|
},
|
||||||
@@ -19,11 +19,7 @@
|
|||||||
"lint:fix": "eslint . --ext .ts --fix",
|
"lint:fix": "eslint . --ext .ts --fix",
|
||||||
"pretest": "yarn lint && yarn build",
|
"pretest": "yarn lint && yarn build",
|
||||||
"test": "jest --coverage --config=./jest.config.js --maxWorkers=50%",
|
"test": "jest --coverage --config=./jest.config.js --maxWorkers=50%",
|
||||||
"wait-for:files": "docker/wait-for.sh localhost $FILES_SERVER_PORT",
|
|
||||||
"wait-for:revisions": "docker/wait-for.sh localhost $REVISIONS_SERVER_PORT",
|
|
||||||
"start": "yarn node dist/bin/server.js",
|
"start": "yarn node dist/bin/server.js",
|
||||||
"supervisor:start": "yarn wait-for:files && yarn node dist/bin/server.js",
|
|
||||||
"supervisor:worker": "yarn wait-for:revisions && yarn node dist/bin/worker.js",
|
|
||||||
"worker": "yarn node dist/bin/worker.js"
|
"worker": "yarn node dist/bin/worker.js"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -41,10 +37,8 @@
|
|||||||
"cors": "2.8.5",
|
"cors": "2.8.5",
|
||||||
"dotenv": "^16.0.1",
|
"dotenv": "^16.0.1",
|
||||||
"express": "^4.18.2",
|
"express": "^4.18.2",
|
||||||
"helmet": "^6.0.0",
|
|
||||||
"inversify": "^6.0.1",
|
"inversify": "^6.0.1",
|
||||||
"inversify-express-utils": "^6.4.3",
|
"inversify-express-utils": "^6.4.3",
|
||||||
"ioredis": "^5.2.4",
|
|
||||||
"mysql2": "^3.0.1",
|
"mysql2": "^3.0.1",
|
||||||
"newrelic": "^9.8.0",
|
"newrelic": "^9.8.0",
|
||||||
"reflect-metadata": "0.1.13",
|
"reflect-metadata": "0.1.13",
|
||||||
@@ -56,7 +50,6 @@
|
|||||||
"@types/dotenv": "^8.2.0",
|
"@types/dotenv": "^8.2.0",
|
||||||
"@types/express": "^4.17.14",
|
"@types/express": "^4.17.14",
|
||||||
"@types/inversify-express-utils": "^2.0.0",
|
"@types/inversify-express-utils": "^2.0.0",
|
||||||
"@types/ioredis": "^5.0.0",
|
|
||||||
"@types/jest": "^29.1.1",
|
"@types/jest": "^29.1.1",
|
||||||
"@types/newrelic": "^9.4.0",
|
"@types/newrelic": "^9.4.0",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.48.2",
|
"@typescript-eslint/eslint-plugin": "^5.48.2",
|
||||||
|
|||||||
@@ -0,0 +1,80 @@
|
|||||||
|
import { MapperInterface } from '@standardnotes/domain-core'
|
||||||
|
import { Container, interfaces } from 'inversify'
|
||||||
|
import { Repository } from 'typeorm'
|
||||||
|
import * as winston from 'winston'
|
||||||
|
import { Revision } from '../Domain/Revision/Revision'
|
||||||
|
import { RevisionMetadata } from '../Domain/Revision/RevisionMetadata'
|
||||||
|
import { RevisionRepositoryInterface } from '../Domain/Revision/RevisionRepositoryInterface'
|
||||||
|
import { MySQLRevisionRepository } from '../Infra/MySQL/MySQLRevisionRepository'
|
||||||
|
import { TypeORMRevision } from '../Infra/TypeORM/TypeORMRevision'
|
||||||
|
import { RevisionMetadataPersistenceMapper } from '../Mapping/RevisionMetadataPersistenceMapper'
|
||||||
|
import { RevisionPersistenceMapper } from '../Mapping/RevisionPersistenceMapper'
|
||||||
|
import { AppDataSource } from './DataSource'
|
||||||
|
import { Env } from './Env'
|
||||||
|
import TYPES from './Types'
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||||
|
const newrelicFormatter = require('@newrelic/winston-enricher')
|
||||||
|
|
||||||
|
export class CommonContainerConfigLoader {
|
||||||
|
async load(): Promise<Container> {
|
||||||
|
const env: Env = new Env()
|
||||||
|
env.load()
|
||||||
|
|
||||||
|
const container = new Container({
|
||||||
|
defaultScope: 'Singleton',
|
||||||
|
})
|
||||||
|
|
||||||
|
await AppDataSource.initialize()
|
||||||
|
|
||||||
|
container.bind<Env>(TYPES.Env).toConstantValue(env)
|
||||||
|
|
||||||
|
container.bind<winston.Logger>(TYPES.Logger).toDynamicValue((context: interfaces.Context) => {
|
||||||
|
const env: Env = context.container.get(TYPES.Env)
|
||||||
|
|
||||||
|
const newrelicWinstonFormatter = newrelicFormatter(winston)
|
||||||
|
const winstonFormatters = [winston.format.splat(), winston.format.json()]
|
||||||
|
if (env.get('NEW_RELIC_ENABLED', true) === 'true') {
|
||||||
|
winstonFormatters.push(newrelicWinstonFormatter())
|
||||||
|
}
|
||||||
|
|
||||||
|
const logger = winston.createLogger({
|
||||||
|
level: env.get('LOG_LEVEL') || 'info',
|
||||||
|
format: winston.format.combine(...winstonFormatters),
|
||||||
|
transports: [new winston.transports.Console({ level: env.get('LOG_LEVEL') || 'info' })],
|
||||||
|
})
|
||||||
|
|
||||||
|
return logger
|
||||||
|
})
|
||||||
|
|
||||||
|
container.bind(TYPES.NEW_RELIC_ENABLED).toConstantValue(env.get('NEW_RELIC_ENABLED', true))
|
||||||
|
container.bind(TYPES.VERSION).toConstantValue(env.get('VERSION'))
|
||||||
|
|
||||||
|
// Map
|
||||||
|
container
|
||||||
|
.bind<MapperInterface<RevisionMetadata, TypeORMRevision>>(TYPES.RevisionMetadataPersistenceMapper)
|
||||||
|
.toDynamicValue(() => new RevisionMetadataPersistenceMapper())
|
||||||
|
container
|
||||||
|
.bind<MapperInterface<Revision, TypeORMRevision>>(TYPES.RevisionPersistenceMapper)
|
||||||
|
.toDynamicValue(() => new RevisionPersistenceMapper())
|
||||||
|
|
||||||
|
// ORM
|
||||||
|
container
|
||||||
|
.bind<Repository<TypeORMRevision>>(TYPES.ORMRevisionRepository)
|
||||||
|
.toDynamicValue(() => AppDataSource.getRepository(TypeORMRevision))
|
||||||
|
|
||||||
|
// Repositories
|
||||||
|
container
|
||||||
|
.bind<RevisionRepositoryInterface>(TYPES.RevisionRepository)
|
||||||
|
.toDynamicValue((context: interfaces.Context) => {
|
||||||
|
return new MySQLRevisionRepository(
|
||||||
|
context.container.get(TYPES.ORMRevisionRepository),
|
||||||
|
context.container.get(TYPES.RevisionMetadataPersistenceMapper),
|
||||||
|
context.container.get(TYPES.RevisionPersistenceMapper),
|
||||||
|
context.container.get(TYPES.Logger),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
return container
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,283 +0,0 @@
|
|||||||
import * as winston from 'winston'
|
|
||||||
import Redis from 'ioredis'
|
|
||||||
import { Timer, TimerInterface } from '@standardnotes/time'
|
|
||||||
import { SQSClient, SQSClientConfig } from '@aws-sdk/client-sqs'
|
|
||||||
import { S3Client } from '@aws-sdk/client-s3'
|
|
||||||
import { Container } from 'inversify'
|
|
||||||
import { Repository } from 'typeorm'
|
|
||||||
import {
|
|
||||||
DomainEventHandlerInterface,
|
|
||||||
DomainEventMessageHandlerInterface,
|
|
||||||
DomainEventSubscriberFactoryInterface,
|
|
||||||
} from '@standardnotes/domain-events'
|
|
||||||
import { TokenDecoderInterface, CrossServiceTokenData, TokenDecoder } from '@standardnotes/security'
|
|
||||||
import {
|
|
||||||
SQSDomainEventSubscriberFactory,
|
|
||||||
SQSEventMessageHandler,
|
|
||||||
SQSNewRelicEventMessageHandler,
|
|
||||||
} from '@standardnotes/domain-events-infra'
|
|
||||||
import { MapperInterface } from '@standardnotes/domain-core'
|
|
||||||
|
|
||||||
import { Env } from './Env'
|
|
||||||
import TYPES from './Types'
|
|
||||||
import { AppDataSource } from './DataSource'
|
|
||||||
import { InversifyExpressApiGatewayAuthMiddleware } from '../Infra/InversifyExpress/InversifyExpressApiGatewayAuthMiddleware'
|
|
||||||
import { RevisionsController } from '../Controller/RevisionsController'
|
|
||||||
import { GetRevisionsMetada } from '../Domain/UseCase/GetRevisionsMetada/GetRevisionsMetada'
|
|
||||||
import { RevisionRepositoryInterface } from '../Domain/Revision/RevisionRepositoryInterface'
|
|
||||||
import { MySQLRevisionRepository } from '../Infra/MySQL/MySQLRevisionRepository'
|
|
||||||
import { RevisionMetadataPersistenceMapper } from '../Mapping/RevisionMetadataPersistenceMapper'
|
|
||||||
import { TypeORMRevision } from '../Infra/TypeORM/TypeORMRevision'
|
|
||||||
import { RevisionMetadata } from '../Domain/Revision/RevisionMetadata'
|
|
||||||
import { Revision } from '../Domain/Revision/Revision'
|
|
||||||
import { RevisionItemStringMapper } from '../Mapping/RevisionItemStringMapper'
|
|
||||||
import { RevisionPersistenceMapper } from '../Mapping/RevisionPersistenceMapper'
|
|
||||||
import { ItemDumpedEventHandler } from '../Domain/Handler/ItemDumpedEventHandler'
|
|
||||||
import { DumpRepositoryInterface } from '../Domain/Dump/DumpRepositoryInterface'
|
|
||||||
import { S3DumpRepository } from '../Infra/S3/S3ItemDumpRepository'
|
|
||||||
import { FSDumpRepository } from '../Infra/FS/FSDumpRepository'
|
|
||||||
import { GetRevision } from '../Domain/UseCase/GetRevision/GetRevision'
|
|
||||||
import { DeleteRevision } from '../Domain/UseCase/DeleteRevision/DeleteRevision'
|
|
||||||
import { AccountDeletionRequestedEventHandler } from '../Domain/Handler/AccountDeletionRequestedEventHandler'
|
|
||||||
import { RevisionsCopyRequestedEventHandler } from '../Domain/Handler/RevisionsCopyRequestedEventHandler'
|
|
||||||
import { CopyRevisions } from '../Domain/UseCase/CopyRevisions/CopyRevisions'
|
|
||||||
import { RevisionsOwnershipUpdateRequestedEventHandler } from '../Domain/Handler/RevisionsOwnershipUpdateRequestedEventHandler'
|
|
||||||
import { RevisionHttpMapper } from '../Mapping/RevisionHttpMapper'
|
|
||||||
import { RevisionMetadataHttpMapper } from '../Mapping/RevisionMetadataHttpMapper'
|
|
||||||
import { GetRequiredRoleToViewRevision } from '../Domain/UseCase/GetRequiredRoleToViewRevision/GetRequiredRoleToViewRevision'
|
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
||||||
const newrelicFormatter = require('@newrelic/winston-enricher')
|
|
||||||
|
|
||||||
export class ContainerConfigLoader {
|
|
||||||
async load(): Promise<Container> {
|
|
||||||
const env: Env = new Env()
|
|
||||||
env.load()
|
|
||||||
|
|
||||||
const container = new Container()
|
|
||||||
|
|
||||||
await AppDataSource.initialize()
|
|
||||||
|
|
||||||
const redisUrl = env.get('REDIS_URL')
|
|
||||||
const isRedisInClusterMode = redisUrl.indexOf(',') > 0
|
|
||||||
let redis
|
|
||||||
if (isRedisInClusterMode) {
|
|
||||||
redis = new Redis.Cluster(redisUrl.split(','))
|
|
||||||
} else {
|
|
||||||
redis = new Redis(redisUrl)
|
|
||||||
}
|
|
||||||
|
|
||||||
container.bind(TYPES.Redis).toConstantValue(redis)
|
|
||||||
|
|
||||||
const newrelicWinstonFormatter = newrelicFormatter(winston)
|
|
||||||
const winstonFormatters = [winston.format.splat(), winston.format.json()]
|
|
||||||
if (env.get('NEW_RELIC_ENABLED', true) === 'true') {
|
|
||||||
winstonFormatters.push(newrelicWinstonFormatter())
|
|
||||||
}
|
|
||||||
|
|
||||||
const logger = winston.createLogger({
|
|
||||||
level: env.get('LOG_LEVEL') || 'info',
|
|
||||||
format: winston.format.combine(...winstonFormatters),
|
|
||||||
transports: [new winston.transports.Console({ level: env.get('LOG_LEVEL') || 'info' })],
|
|
||||||
})
|
|
||||||
container.bind<winston.Logger>(TYPES.Logger).toConstantValue(logger)
|
|
||||||
|
|
||||||
if (env.get('SQS_QUEUE_URL', true)) {
|
|
||||||
const sqsConfig: SQSClientConfig = {
|
|
||||||
region: env.get('SQS_AWS_REGION', true),
|
|
||||||
}
|
|
||||||
if (env.get('SQS_ENDPOINT', true)) {
|
|
||||||
sqsConfig.endpoint = env.get('SQS_ENDPOINT', true)
|
|
||||||
}
|
|
||||||
if (env.get('SQS_ACCESS_KEY_ID', true) && env.get('SQS_SECRET_ACCESS_KEY', true)) {
|
|
||||||
sqsConfig.credentials = {
|
|
||||||
accessKeyId: env.get('SQS_ACCESS_KEY_ID', true),
|
|
||||||
secretAccessKey: env.get('SQS_SECRET_ACCESS_KEY', true),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
container.bind<SQSClient>(TYPES.SQS).toConstantValue(new SQSClient(sqsConfig))
|
|
||||||
}
|
|
||||||
|
|
||||||
let s3Client = undefined
|
|
||||||
if (env.get('S3_AWS_REGION', true)) {
|
|
||||||
s3Client = new S3Client({
|
|
||||||
apiVersion: 'latest',
|
|
||||||
region: env.get('S3_AWS_REGION', true),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
container.bind<S3Client | undefined>(TYPES.S3).toConstantValue(s3Client)
|
|
||||||
|
|
||||||
container.bind<TimerInterface>(TYPES.Timer).toConstantValue(new Timer())
|
|
||||||
|
|
||||||
container
|
|
||||||
.bind<GetRequiredRoleToViewRevision>(TYPES.GetRequiredRoleToViewRevision)
|
|
||||||
.toConstantValue(new GetRequiredRoleToViewRevision(container.get(TYPES.Timer)))
|
|
||||||
|
|
||||||
// Map
|
|
||||||
container
|
|
||||||
.bind<MapperInterface<RevisionMetadata, TypeORMRevision>>(TYPES.RevisionMetadataPersistenceMapper)
|
|
||||||
.toConstantValue(new RevisionMetadataPersistenceMapper())
|
|
||||||
container
|
|
||||||
.bind<MapperInterface<Revision, TypeORMRevision>>(TYPES.RevisionPersistenceMapper)
|
|
||||||
.toConstantValue(new RevisionPersistenceMapper())
|
|
||||||
container
|
|
||||||
.bind<MapperInterface<Revision, string>>(TYPES.RevisionItemStringMapper)
|
|
||||||
.toConstantValue(new RevisionItemStringMapper())
|
|
||||||
container
|
|
||||||
.bind<
|
|
||||||
MapperInterface<
|
|
||||||
Revision,
|
|
||||||
{
|
|
||||||
uuid: string
|
|
||||||
item_uuid: string
|
|
||||||
content: string | null
|
|
||||||
content_type: string
|
|
||||||
items_key_id: string | null
|
|
||||||
enc_item_key: string | null
|
|
||||||
auth_hash: string | null
|
|
||||||
created_at: string
|
|
||||||
updated_at: string
|
|
||||||
}
|
|
||||||
>
|
|
||||||
>(TYPES.RevisionHttpMapper)
|
|
||||||
.toConstantValue(new RevisionHttpMapper())
|
|
||||||
container
|
|
||||||
.bind<
|
|
||||||
MapperInterface<
|
|
||||||
RevisionMetadata,
|
|
||||||
{
|
|
||||||
uuid: string
|
|
||||||
content_type: string
|
|
||||||
created_at: string
|
|
||||||
updated_at: string
|
|
||||||
}
|
|
||||||
>
|
|
||||||
>(TYPES.RevisionMetadataHttpMapper)
|
|
||||||
.toConstantValue(new RevisionMetadataHttpMapper(container.get(TYPES.GetRequiredRoleToViewRevision)))
|
|
||||||
|
|
||||||
// ORM
|
|
||||||
container
|
|
||||||
.bind<Repository<TypeORMRevision>>(TYPES.ORMRevisionRepository)
|
|
||||||
.toConstantValue(AppDataSource.getRepository(TypeORMRevision))
|
|
||||||
|
|
||||||
// env vars
|
|
||||||
container.bind(TYPES.REDIS_URL).toConstantValue(env.get('REDIS_URL'))
|
|
||||||
container.bind(TYPES.SQS_QUEUE_URL).toConstantValue(env.get('SQS_QUEUE_URL'))
|
|
||||||
container.bind(TYPES.AUTH_JWT_SECRET).toConstantValue(env.get('AUTH_JWT_SECRET'))
|
|
||||||
container.bind(TYPES.S3_AWS_REGION).toConstantValue(env.get('S3_AWS_REGION', true))
|
|
||||||
container.bind(TYPES.S3_BACKUP_BUCKET_NAME).toConstantValue(env.get('S3_BACKUP_BUCKET_NAME', true))
|
|
||||||
container.bind(TYPES.NEW_RELIC_ENABLED).toConstantValue(env.get('NEW_RELIC_ENABLED', true))
|
|
||||||
container.bind(TYPES.VERSION).toConstantValue(env.get('VERSION'))
|
|
||||||
|
|
||||||
// Repositories
|
|
||||||
container
|
|
||||||
.bind<RevisionRepositoryInterface>(TYPES.RevisionRepository)
|
|
||||||
.toConstantValue(
|
|
||||||
new MySQLRevisionRepository(
|
|
||||||
container.get(TYPES.ORMRevisionRepository),
|
|
||||||
container.get(TYPES.RevisionMetadataPersistenceMapper),
|
|
||||||
container.get(TYPES.RevisionPersistenceMapper),
|
|
||||||
container.get(TYPES.Logger),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
if (env.get('S3_AWS_REGION', true)) {
|
|
||||||
container
|
|
||||||
.bind<DumpRepositoryInterface>(TYPES.DumpRepository)
|
|
||||||
.toConstantValue(
|
|
||||||
new S3DumpRepository(
|
|
||||||
container.get(TYPES.S3_BACKUP_BUCKET_NAME),
|
|
||||||
container.get(TYPES.S3),
|
|
||||||
container.get(TYPES.RevisionItemStringMapper),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
container
|
|
||||||
.bind<DumpRepositoryInterface>(TYPES.DumpRepository)
|
|
||||||
.toConstantValue(new FSDumpRepository(container.get(TYPES.RevisionItemStringMapper)))
|
|
||||||
}
|
|
||||||
|
|
||||||
// use cases
|
|
||||||
container
|
|
||||||
.bind<GetRevisionsMetada>(TYPES.GetRevisionsMetada)
|
|
||||||
.toConstantValue(new GetRevisionsMetada(container.get(TYPES.RevisionRepository)))
|
|
||||||
container
|
|
||||||
.bind<GetRevision>(TYPES.GetRevision)
|
|
||||||
.toConstantValue(new GetRevision(container.get(TYPES.RevisionRepository)))
|
|
||||||
container
|
|
||||||
.bind<DeleteRevision>(TYPES.DeleteRevision)
|
|
||||||
.toConstantValue(new DeleteRevision(container.get(TYPES.RevisionRepository)))
|
|
||||||
container
|
|
||||||
.bind<CopyRevisions>(TYPES.CopyRevisions)
|
|
||||||
.toConstantValue(new CopyRevisions(container.get(TYPES.RevisionRepository)))
|
|
||||||
|
|
||||||
// Controller
|
|
||||||
container
|
|
||||||
.bind<RevisionsController>(TYPES.RevisionsController)
|
|
||||||
.toConstantValue(
|
|
||||||
new RevisionsController(
|
|
||||||
container.get(TYPES.GetRevisionsMetada),
|
|
||||||
container.get(TYPES.GetRevision),
|
|
||||||
container.get(TYPES.DeleteRevision),
|
|
||||||
container.get(TYPES.RevisionHttpMapper),
|
|
||||||
container.get(TYPES.RevisionMetadataHttpMapper),
|
|
||||||
container.get(TYPES.Logger),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
// Handlers
|
|
||||||
container
|
|
||||||
.bind<ItemDumpedEventHandler>(TYPES.ItemDumpedEventHandler)
|
|
||||||
.toConstantValue(
|
|
||||||
new ItemDumpedEventHandler(container.get(TYPES.DumpRepository), container.get(TYPES.RevisionRepository)),
|
|
||||||
)
|
|
||||||
container
|
|
||||||
.bind<AccountDeletionRequestedEventHandler>(TYPES.AccountDeletionRequestedEventHandler)
|
|
||||||
.toConstantValue(
|
|
||||||
new AccountDeletionRequestedEventHandler(container.get(TYPES.RevisionRepository), container.get(TYPES.Logger)),
|
|
||||||
)
|
|
||||||
container
|
|
||||||
.bind<RevisionsCopyRequestedEventHandler>(TYPES.RevisionsCopyRequestedEventHandler)
|
|
||||||
.toConstantValue(
|
|
||||||
new RevisionsCopyRequestedEventHandler(container.get(TYPES.CopyRevisions), container.get(TYPES.Logger)),
|
|
||||||
)
|
|
||||||
container
|
|
||||||
.bind<RevisionsOwnershipUpdateRequestedEventHandler>(TYPES.RevisionsOwnershipUpdateRequestedEventHandler)
|
|
||||||
.toConstantValue(new RevisionsOwnershipUpdateRequestedEventHandler(container.get(TYPES.RevisionRepository)))
|
|
||||||
|
|
||||||
// Services
|
|
||||||
container
|
|
||||||
.bind<TokenDecoderInterface<CrossServiceTokenData>>(TYPES.CrossServiceTokenDecoder)
|
|
||||||
.toConstantValue(new TokenDecoder<CrossServiceTokenData>(container.get(TYPES.AUTH_JWT_SECRET)))
|
|
||||||
|
|
||||||
// Middleware
|
|
||||||
container
|
|
||||||
.bind<InversifyExpressApiGatewayAuthMiddleware>(TYPES.ApiGatewayAuthMiddleware)
|
|
||||||
.to(InversifyExpressApiGatewayAuthMiddleware)
|
|
||||||
|
|
||||||
const eventHandlers: Map<string, DomainEventHandlerInterface> = new Map([
|
|
||||||
['ITEM_DUMPED', container.get(TYPES.ItemDumpedEventHandler)],
|
|
||||||
['ACCOUNT_DELETION_REQUESTED', container.get(TYPES.AccountDeletionRequestedEventHandler)],
|
|
||||||
['REVISIONS_COPY_REQUESTED', container.get(TYPES.RevisionsCopyRequestedEventHandler)],
|
|
||||||
['REVISIONS_OWNERSHIP_UPDATE_REQUESTED', container.get(TYPES.RevisionsOwnershipUpdateRequestedEventHandler)],
|
|
||||||
])
|
|
||||||
|
|
||||||
container
|
|
||||||
.bind<DomainEventMessageHandlerInterface>(TYPES.DomainEventMessageHandler)
|
|
||||||
.toConstantValue(
|
|
||||||
env.get('NEW_RELIC_ENABLED', true) === 'true'
|
|
||||||
? new SQSNewRelicEventMessageHandler(eventHandlers, container.get(TYPES.Logger))
|
|
||||||
: new SQSEventMessageHandler(eventHandlers, container.get(TYPES.Logger)),
|
|
||||||
)
|
|
||||||
container
|
|
||||||
.bind<DomainEventSubscriberFactoryInterface>(TYPES.DomainEventSubscriberFactory)
|
|
||||||
.toConstantValue(
|
|
||||||
new SQSDomainEventSubscriberFactory(
|
|
||||||
container.get(TYPES.SQS),
|
|
||||||
container.get(TYPES.SQS_QUEUE_URL),
|
|
||||||
container.get(TYPES.DomainEventMessageHandler),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
return container
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,112 @@
|
|||||||
|
import { Timer, TimerInterface } from '@standardnotes/time'
|
||||||
|
import { Container, interfaces } from 'inversify'
|
||||||
|
import { MapperInterface } from '@standardnotes/domain-core'
|
||||||
|
|
||||||
|
import TYPES from './Types'
|
||||||
|
import { RevisionsController } from '../Controller/RevisionsController'
|
||||||
|
import { GetRevisionsMetada } from '../Domain/UseCase/GetRevisionsMetada/GetRevisionsMetada'
|
||||||
|
import { RevisionMetadata } from '../Domain/Revision/RevisionMetadata'
|
||||||
|
import { Revision } from '../Domain/Revision/Revision'
|
||||||
|
import { GetRevision } from '../Domain/UseCase/GetRevision/GetRevision'
|
||||||
|
import { DeleteRevision } from '../Domain/UseCase/DeleteRevision/DeleteRevision'
|
||||||
|
import { RevisionHttpMapper } from '../Mapping/RevisionHttpMapper'
|
||||||
|
import { RevisionMetadataHttpMapper } from '../Mapping/RevisionMetadataHttpMapper'
|
||||||
|
import { GetRequiredRoleToViewRevision } from '../Domain/UseCase/GetRequiredRoleToViewRevision/GetRequiredRoleToViewRevision'
|
||||||
|
import { CommonContainerConfigLoader } from './CommonContainerConfigLoader'
|
||||||
|
import { ApiGatewayAuthMiddleware } from '../Controller/ApiGatewayAuthMiddleware'
|
||||||
|
import { CrossServiceTokenData, TokenDecoder, TokenDecoderInterface } from '@standardnotes/security'
|
||||||
|
import { Env } from './Env'
|
||||||
|
|
||||||
|
export class ServerContainerConfigLoader extends CommonContainerConfigLoader {
|
||||||
|
override async load(): Promise<Container> {
|
||||||
|
const container = await super.load()
|
||||||
|
|
||||||
|
const env: Env = container.get(TYPES.Env)
|
||||||
|
|
||||||
|
container.bind<TimerInterface>(TYPES.Timer).toDynamicValue(() => new Timer())
|
||||||
|
|
||||||
|
container
|
||||||
|
.bind<GetRequiredRoleToViewRevision>(TYPES.GetRequiredRoleToViewRevision)
|
||||||
|
.toDynamicValue((context: interfaces.Context) => {
|
||||||
|
return new GetRequiredRoleToViewRevision(context.container.get(TYPES.Timer))
|
||||||
|
})
|
||||||
|
|
||||||
|
// Map
|
||||||
|
container
|
||||||
|
.bind<
|
||||||
|
MapperInterface<
|
||||||
|
Revision,
|
||||||
|
{
|
||||||
|
uuid: string
|
||||||
|
item_uuid: string
|
||||||
|
content: string | null
|
||||||
|
content_type: string
|
||||||
|
items_key_id: string | null
|
||||||
|
enc_item_key: string | null
|
||||||
|
auth_hash: string | null
|
||||||
|
created_at: string
|
||||||
|
updated_at: string
|
||||||
|
}
|
||||||
|
>
|
||||||
|
>(TYPES.RevisionHttpMapper)
|
||||||
|
.toDynamicValue(() => new RevisionHttpMapper())
|
||||||
|
container
|
||||||
|
.bind<
|
||||||
|
MapperInterface<
|
||||||
|
RevisionMetadata,
|
||||||
|
{
|
||||||
|
uuid: string
|
||||||
|
content_type: string
|
||||||
|
created_at: string
|
||||||
|
updated_at: string
|
||||||
|
}
|
||||||
|
>
|
||||||
|
>(TYPES.RevisionMetadataHttpMapper)
|
||||||
|
.toDynamicValue((context: interfaces.Context) => {
|
||||||
|
return new RevisionMetadataHttpMapper(context.container.get(TYPES.GetRequiredRoleToViewRevision))
|
||||||
|
})
|
||||||
|
|
||||||
|
// use cases
|
||||||
|
container.bind<GetRevisionsMetada>(TYPES.GetRevisionsMetada).toDynamicValue((context: interfaces.Context) => {
|
||||||
|
return new GetRevisionsMetada(context.container.get(TYPES.RevisionRepository))
|
||||||
|
})
|
||||||
|
container.bind<GetRevision>(TYPES.GetRevision).toDynamicValue((context: interfaces.Context) => {
|
||||||
|
return new GetRevision(context.container.get(TYPES.RevisionRepository))
|
||||||
|
})
|
||||||
|
container.bind<DeleteRevision>(TYPES.DeleteRevision).toDynamicValue((context: interfaces.Context) => {
|
||||||
|
return new DeleteRevision(context.container.get(TYPES.RevisionRepository))
|
||||||
|
})
|
||||||
|
|
||||||
|
// env vars
|
||||||
|
container.bind(TYPES.AUTH_JWT_SECRET).toConstantValue(env.get('AUTH_JWT_SECRET'))
|
||||||
|
|
||||||
|
// Controller
|
||||||
|
container.bind<RevisionsController>(TYPES.RevisionsController).toDynamicValue((context: interfaces.Context) => {
|
||||||
|
return new RevisionsController(
|
||||||
|
context.container.get(TYPES.GetRevisionsMetada),
|
||||||
|
context.container.get(TYPES.GetRevision),
|
||||||
|
context.container.get(TYPES.DeleteRevision),
|
||||||
|
context.container.get(TYPES.RevisionHttpMapper),
|
||||||
|
context.container.get(TYPES.RevisionMetadataHttpMapper),
|
||||||
|
context.container.get(TYPES.Logger),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
container
|
||||||
|
.bind<TokenDecoderInterface<CrossServiceTokenData>>(TYPES.CrossServiceTokenDecoder)
|
||||||
|
.toDynamicValue((context: interfaces.Context) => {
|
||||||
|
return new TokenDecoder<CrossServiceTokenData>(context.container.get(TYPES.AUTH_JWT_SECRET))
|
||||||
|
})
|
||||||
|
|
||||||
|
container
|
||||||
|
.bind<ApiGatewayAuthMiddleware>(TYPES.ApiGatewayAuthMiddleware)
|
||||||
|
.toDynamicValue((context: interfaces.Context) => {
|
||||||
|
return new ApiGatewayAuthMiddleware(
|
||||||
|
context.container.get(TYPES.CrossServiceTokenDecoder),
|
||||||
|
context.container.get(TYPES.Logger),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
return container
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
const TYPES = {
|
const TYPES = {
|
||||||
DBConnection: Symbol.for('DBConnection'),
|
DBConnection: Symbol.for('DBConnection'),
|
||||||
Logger: Symbol.for('Logger'),
|
Logger: Symbol.for('Logger'),
|
||||||
Redis: Symbol.for('Redis'),
|
|
||||||
SQS: Symbol.for('SQS'),
|
SQS: Symbol.for('SQS'),
|
||||||
S3: Symbol.for('S3'),
|
S3: Symbol.for('S3'),
|
||||||
|
Env: Symbol.for('Env'),
|
||||||
// Map
|
// Map
|
||||||
RevisionMetadataPersistenceMapper: Symbol.for('RevisionMetadataPersistenceMapper'),
|
RevisionMetadataPersistenceMapper: Symbol.for('RevisionMetadataPersistenceMapper'),
|
||||||
RevisionPersistenceMapper: Symbol.for('RevisionPersistenceMapper'),
|
RevisionPersistenceMapper: Symbol.for('RevisionPersistenceMapper'),
|
||||||
@@ -16,10 +16,9 @@ const TYPES = {
|
|||||||
RevisionRepository: Symbol.for('RevisionRepository'),
|
RevisionRepository: Symbol.for('RevisionRepository'),
|
||||||
DumpRepository: Symbol.for('DumpRepository'),
|
DumpRepository: Symbol.for('DumpRepository'),
|
||||||
// env vars
|
// env vars
|
||||||
REDIS_URL: Symbol.for('REDIS_URL'),
|
AUTH_JWT_SECRET: Symbol.for('AUTH_JWT_SECRET'),
|
||||||
SQS_QUEUE_URL: Symbol.for('SQS_QUEUE_URL'),
|
SQS_QUEUE_URL: Symbol.for('SQS_QUEUE_URL'),
|
||||||
SQS_AWS_REGION: Symbol.for('SQS_AWS_REGION'),
|
SQS_AWS_REGION: Symbol.for('SQS_AWS_REGION'),
|
||||||
AUTH_JWT_SECRET: Symbol.for('AUTH_JWT_SECRET'),
|
|
||||||
S3_AWS_REGION: Symbol.for('S3_AWS_REGION'),
|
S3_AWS_REGION: Symbol.for('S3_AWS_REGION'),
|
||||||
S3_BACKUP_BUCKET_NAME: Symbol.for('S3_BACKUP_BUCKET_NAME'),
|
S3_BACKUP_BUCKET_NAME: Symbol.for('S3_BACKUP_BUCKET_NAME'),
|
||||||
NEW_RELIC_ENABLED: Symbol.for('NEW_RELIC_ENABLED'),
|
NEW_RELIC_ENABLED: Symbol.for('NEW_RELIC_ENABLED'),
|
||||||
@@ -32,6 +31,7 @@ const TYPES = {
|
|||||||
GetRequiredRoleToViewRevision: Symbol.for('GetRequiredRoleToViewRevision'),
|
GetRequiredRoleToViewRevision: Symbol.for('GetRequiredRoleToViewRevision'),
|
||||||
// Controller
|
// Controller
|
||||||
RevisionsController: Symbol.for('RevisionsController'),
|
RevisionsController: Symbol.for('RevisionsController'),
|
||||||
|
ApiGatewayAuthMiddleware: Symbol.for('ApiGatewayAuthMiddleware'),
|
||||||
// Handlers
|
// Handlers
|
||||||
ItemDumpedEventHandler: Symbol.for('ItemDumpedEventHandler'),
|
ItemDumpedEventHandler: Symbol.for('ItemDumpedEventHandler'),
|
||||||
AccountDeletionRequestedEventHandler: Symbol.for('AccountDeletionRequestedEventHandler'),
|
AccountDeletionRequestedEventHandler: Symbol.for('AccountDeletionRequestedEventHandler'),
|
||||||
@@ -42,8 +42,6 @@ const TYPES = {
|
|||||||
DomainEventSubscriberFactory: Symbol.for('DomainEventSubscriberFactory'),
|
DomainEventSubscriberFactory: Symbol.for('DomainEventSubscriberFactory'),
|
||||||
DomainEventMessageHandler: Symbol.for('DomainEventMessageHandler'),
|
DomainEventMessageHandler: Symbol.for('DomainEventMessageHandler'),
|
||||||
Timer: Symbol.for('Timer'),
|
Timer: Symbol.for('Timer'),
|
||||||
// Middleware
|
|
||||||
ApiGatewayAuthMiddleware: Symbol.for('ApiGatewayAuthMiddleware'),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default TYPES
|
export default TYPES
|
||||||
|
|||||||
@@ -0,0 +1,164 @@
|
|||||||
|
import { SQSClient, SQSClientConfig } from '@aws-sdk/client-sqs'
|
||||||
|
import { S3Client } from '@aws-sdk/client-s3'
|
||||||
|
import { Container, interfaces } from 'inversify'
|
||||||
|
import {
|
||||||
|
DomainEventHandlerInterface,
|
||||||
|
DomainEventMessageHandlerInterface,
|
||||||
|
DomainEventSubscriberFactoryInterface,
|
||||||
|
} from '@standardnotes/domain-events'
|
||||||
|
import {
|
||||||
|
SQSDomainEventSubscriberFactory,
|
||||||
|
SQSEventMessageHandler,
|
||||||
|
SQSNewRelicEventMessageHandler,
|
||||||
|
} from '@standardnotes/domain-events-infra'
|
||||||
|
import { MapperInterface } from '@standardnotes/domain-core'
|
||||||
|
|
||||||
|
import TYPES from './Types'
|
||||||
|
import { Revision } from '../Domain/Revision/Revision'
|
||||||
|
import { RevisionItemStringMapper } from '../Mapping/RevisionItemStringMapper'
|
||||||
|
import { ItemDumpedEventHandler } from '../Domain/Handler/ItemDumpedEventHandler'
|
||||||
|
import { DumpRepositoryInterface } from '../Domain/Dump/DumpRepositoryInterface'
|
||||||
|
import { S3DumpRepository } from '../Infra/S3/S3ItemDumpRepository'
|
||||||
|
import { FSDumpRepository } from '../Infra/FS/FSDumpRepository'
|
||||||
|
import { AccountDeletionRequestedEventHandler } from '../Domain/Handler/AccountDeletionRequestedEventHandler'
|
||||||
|
import { RevisionsCopyRequestedEventHandler } from '../Domain/Handler/RevisionsCopyRequestedEventHandler'
|
||||||
|
import { CopyRevisions } from '../Domain/UseCase/CopyRevisions/CopyRevisions'
|
||||||
|
import { RevisionsOwnershipUpdateRequestedEventHandler } from '../Domain/Handler/RevisionsOwnershipUpdateRequestedEventHandler'
|
||||||
|
import { CommonContainerConfigLoader } from './CommonContainerConfigLoader'
|
||||||
|
import { Env } from './Env'
|
||||||
|
|
||||||
|
export class WorkerContainerConfigLoader extends CommonContainerConfigLoader {
|
||||||
|
override async load(): Promise<Container> {
|
||||||
|
const container = await super.load()
|
||||||
|
|
||||||
|
const env: Env = container.get(TYPES.Env)
|
||||||
|
|
||||||
|
container.bind<SQSClient>(TYPES.SQS).toDynamicValue((context: interfaces.Context) => {
|
||||||
|
const env: Env = context.container.get(TYPES.Env)
|
||||||
|
|
||||||
|
const sqsConfig: SQSClientConfig = {
|
||||||
|
region: env.get('SQS_AWS_REGION'),
|
||||||
|
}
|
||||||
|
if (env.get('SQS_ENDPOINT', true)) {
|
||||||
|
sqsConfig.endpoint = env.get('SQS_ENDPOINT', true)
|
||||||
|
}
|
||||||
|
if (env.get('SQS_ACCESS_KEY_ID', true) && env.get('SQS_SECRET_ACCESS_KEY', true)) {
|
||||||
|
sqsConfig.credentials = {
|
||||||
|
accessKeyId: env.get('SQS_ACCESS_KEY_ID', true),
|
||||||
|
secretAccessKey: env.get('SQS_SECRET_ACCESS_KEY', true),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new SQSClient(sqsConfig)
|
||||||
|
})
|
||||||
|
|
||||||
|
container.bind<S3Client | undefined>(TYPES.S3).toDynamicValue((context: interfaces.Context) => {
|
||||||
|
const env: Env = context.container.get(TYPES.Env)
|
||||||
|
|
||||||
|
let s3Client = undefined
|
||||||
|
if (env.get('S3_AWS_REGION', true)) {
|
||||||
|
s3Client = new S3Client({
|
||||||
|
apiVersion: 'latest',
|
||||||
|
region: env.get('S3_AWS_REGION', true),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return s3Client
|
||||||
|
})
|
||||||
|
|
||||||
|
// Map
|
||||||
|
container
|
||||||
|
.bind<MapperInterface<Revision, string>>(TYPES.RevisionItemStringMapper)
|
||||||
|
.toDynamicValue(() => new RevisionItemStringMapper())
|
||||||
|
|
||||||
|
// env vars
|
||||||
|
container.bind(TYPES.SQS_QUEUE_URL).toConstantValue(env.get('SQS_QUEUE_URL'))
|
||||||
|
container.bind(TYPES.S3_AWS_REGION).toConstantValue(env.get('S3_AWS_REGION', true))
|
||||||
|
container.bind(TYPES.S3_BACKUP_BUCKET_NAME).toConstantValue(env.get('S3_BACKUP_BUCKET_NAME', true))
|
||||||
|
|
||||||
|
container.bind<DumpRepositoryInterface>(TYPES.DumpRepository).toDynamicValue((context: interfaces.Context) => {
|
||||||
|
const env: Env = context.container.get(TYPES.Env)
|
||||||
|
|
||||||
|
if (env.get('S3_AWS_REGION', true)) {
|
||||||
|
return new S3DumpRepository(
|
||||||
|
context.container.get(TYPES.S3_BACKUP_BUCKET_NAME),
|
||||||
|
context.container.get(TYPES.S3),
|
||||||
|
context.container.get(TYPES.RevisionItemStringMapper),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
return new FSDumpRepository(context.container.get(TYPES.RevisionItemStringMapper))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// use cases
|
||||||
|
container.bind<CopyRevisions>(TYPES.CopyRevisions).toDynamicValue((context: interfaces.Context) => {
|
||||||
|
return new CopyRevisions(context.container.get(TYPES.RevisionRepository))
|
||||||
|
})
|
||||||
|
|
||||||
|
// Handlers
|
||||||
|
container
|
||||||
|
.bind<ItemDumpedEventHandler>(TYPES.ItemDumpedEventHandler)
|
||||||
|
.toDynamicValue((context: interfaces.Context) => {
|
||||||
|
return new ItemDumpedEventHandler(
|
||||||
|
context.container.get(TYPES.DumpRepository),
|
||||||
|
context.container.get(TYPES.RevisionRepository),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
container
|
||||||
|
.bind<AccountDeletionRequestedEventHandler>(TYPES.AccountDeletionRequestedEventHandler)
|
||||||
|
.toDynamicValue((context: interfaces.Context) => {
|
||||||
|
return new AccountDeletionRequestedEventHandler(
|
||||||
|
context.container.get(TYPES.RevisionRepository),
|
||||||
|
context.container.get(TYPES.Logger),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
container
|
||||||
|
.bind<RevisionsCopyRequestedEventHandler>(TYPES.RevisionsCopyRequestedEventHandler)
|
||||||
|
.toDynamicValue((context: interfaces.Context) => {
|
||||||
|
return new RevisionsCopyRequestedEventHandler(
|
||||||
|
context.container.get(TYPES.CopyRevisions),
|
||||||
|
context.container.get(TYPES.Logger),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
container
|
||||||
|
.bind<RevisionsOwnershipUpdateRequestedEventHandler>(TYPES.RevisionsOwnershipUpdateRequestedEventHandler)
|
||||||
|
.toDynamicValue((context: interfaces.Context) => {
|
||||||
|
return new RevisionsOwnershipUpdateRequestedEventHandler(context.container.get(TYPES.RevisionRepository))
|
||||||
|
})
|
||||||
|
|
||||||
|
container
|
||||||
|
.bind<DomainEventMessageHandlerInterface>(TYPES.DomainEventMessageHandler)
|
||||||
|
.toDynamicValue((context: interfaces.Context) => {
|
||||||
|
const env: Env = context.container.get(TYPES.Env)
|
||||||
|
|
||||||
|
const eventHandlers: Map<string, DomainEventHandlerInterface> = new Map([
|
||||||
|
['ITEM_DUMPED', context.container.get(TYPES.ItemDumpedEventHandler)],
|
||||||
|
['ACCOUNT_DELETION_REQUESTED', context.container.get(TYPES.AccountDeletionRequestedEventHandler)],
|
||||||
|
['REVISIONS_COPY_REQUESTED', context.container.get(TYPES.RevisionsCopyRequestedEventHandler)],
|
||||||
|
[
|
||||||
|
'REVISIONS_OWNERSHIP_UPDATE_REQUESTED',
|
||||||
|
context.container.get(TYPES.RevisionsOwnershipUpdateRequestedEventHandler),
|
||||||
|
],
|
||||||
|
])
|
||||||
|
|
||||||
|
const handler =
|
||||||
|
env.get('NEW_RELIC_ENABLED', true) === 'true'
|
||||||
|
? new SQSNewRelicEventMessageHandler(eventHandlers, context.container.get(TYPES.Logger))
|
||||||
|
: new SQSEventMessageHandler(eventHandlers, context.container.get(TYPES.Logger))
|
||||||
|
|
||||||
|
return handler
|
||||||
|
})
|
||||||
|
|
||||||
|
container
|
||||||
|
.bind<DomainEventSubscriberFactoryInterface>(TYPES.DomainEventSubscriberFactory)
|
||||||
|
.toDynamicValue((context: interfaces.Context) => {
|
||||||
|
return new SQSDomainEventSubscriberFactory(
|
||||||
|
context.container.get(TYPES.SQS),
|
||||||
|
context.container.get(TYPES.SQS_QUEUE_URL),
|
||||||
|
context.container.get(TYPES.DomainEventMessageHandler),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
return container
|
||||||
|
}
|
||||||
|
}
|
||||||
+2
-9
@@ -1,17 +1,10 @@
|
|||||||
import { CrossServiceTokenData, TokenDecoderInterface } from '@standardnotes/security'
|
import { CrossServiceTokenData, TokenDecoderInterface } from '@standardnotes/security'
|
||||||
import { NextFunction, Request, Response } from 'express'
|
import { NextFunction, Request, Response } from 'express'
|
||||||
import { inject, injectable } from 'inversify'
|
|
||||||
import { BaseMiddleware } from 'inversify-express-utils'
|
import { BaseMiddleware } from 'inversify-express-utils'
|
||||||
import { Logger } from 'winston'
|
import { Logger } from 'winston'
|
||||||
|
|
||||||
import TYPES from '../../Bootstrap/Types'
|
export class ApiGatewayAuthMiddleware extends BaseMiddleware {
|
||||||
|
constructor(private tokenDecoder: TokenDecoderInterface<CrossServiceTokenData>, private logger: Logger) {
|
||||||
@injectable()
|
|
||||||
export class InversifyExpressApiGatewayAuthMiddleware extends BaseMiddleware {
|
|
||||||
constructor(
|
|
||||||
@inject(TYPES.CrossServiceTokenDecoder) private tokenDecoder: TokenDecoderInterface<CrossServiceTokenData>,
|
|
||||||
@inject(TYPES.Logger) private logger: Logger,
|
|
||||||
) {
|
|
||||||
super()
|
super()
|
||||||
}
|
}
|
||||||
|
|
||||||
+2
-2
@@ -1,7 +1,7 @@
|
|||||||
import { controller, httpGet } from 'inversify-express-utils'
|
import { BaseHttpController, controller, httpGet } from 'inversify-express-utils'
|
||||||
|
|
||||||
@controller('/healthcheck')
|
@controller('/healthcheck')
|
||||||
export class InversifyExpressHealthCheckController {
|
export class InversifyExpressHealthCheckController extends BaseHttpController {
|
||||||
@httpGet('/')
|
@httpGet('/')
|
||||||
public async get(): Promise<string> {
|
public async get(): Promise<string> {
|
||||||
return 'OK'
|
return 'OK'
|
||||||
|
|||||||
+7
@@ -0,0 +1,7 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
sh supervisor/wait-for.sh $DB_HOST $DB_PORT
|
||||||
|
sh supervisor/wait-for.sh $REDIS_HOST $REDIS_PORT
|
||||||
|
node docker/entrypoint-server.js
|
||||||
+6
@@ -0,0 +1,6 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
sh supervisor/wait-for.sh localhost $SYNCING_SERVER_PORT
|
||||||
|
node docker/entrypoint-worker.js
|
||||||
@@ -3,6 +3,12 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
# [1.17.0](https://github.com/standardnotes/server/compare/@standardnotes/scheduler-server@1.16.19...@standardnotes/scheduler-server@1.17.0) (2023-02-15)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* optimize memory on server utilities ([881a696](https://github.com/standardnotes/server/commit/881a6967aca57d68795af0792114f848ddddf120))
|
||||||
|
|
||||||
## [1.16.19](https://github.com/standardnotes/server/compare/@standardnotes/scheduler-server@1.16.18...@standardnotes/scheduler-server@1.16.19) (2023-02-06)
|
## [1.16.19](https://github.com/standardnotes/server/compare/@standardnotes/scheduler-server@1.16.18...@standardnotes/scheduler-server@1.16.19) (2023-02-06)
|
||||||
|
|
||||||
**Note:** Version bump only for package @standardnotes/scheduler-server
|
**Note:** Version bump only for package @standardnotes/scheduler-server
|
||||||
|
|||||||
@@ -8,10 +8,10 @@ ENV NODE_ENV production
|
|||||||
|
|
||||||
RUN corepack enable
|
RUN corepack enable
|
||||||
|
|
||||||
WORKDIR /workspace
|
|
||||||
|
|
||||||
COPY ./ /workspace
|
COPY ./ /workspace
|
||||||
|
|
||||||
|
WORKDIR /workspace/packages/scheduler
|
||||||
|
|
||||||
ENTRYPOINT [ "/workspace/packages/scheduler/docker/entrypoint.sh" ]
|
ENTRYPOINT [ "/workspace/packages/scheduler/docker/entrypoint.sh" ]
|
||||||
|
|
||||||
CMD [ "start-worker" ]
|
CMD [ "start-worker" ]
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
'use strict'
|
||||||
|
|
||||||
|
const path = require('path')
|
||||||
|
|
||||||
|
const pnp = require(path.normalize(path.resolve(__dirname, '../../..', '.pnp.cjs'))).setup()
|
||||||
|
|
||||||
|
const index = require(path.normalize(path.resolve(__dirname, '../dist/bin/verify.js')))
|
||||||
|
|
||||||
|
Object.defineProperty(exports, '__esModule', { value: true })
|
||||||
|
|
||||||
|
exports.default = index
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
'use strict'
|
||||||
|
|
||||||
|
const path = require('path')
|
||||||
|
|
||||||
|
const pnp = require(path.normalize(path.resolve(__dirname, '../../..', '.pnp.cjs'))).setup()
|
||||||
|
|
||||||
|
const index = require(path.normalize(path.resolve(__dirname, '../dist/bin/worker.js')))
|
||||||
|
|
||||||
|
Object.defineProperty(exports, '__esModule', { value: true })
|
||||||
|
|
||||||
|
exports.default = index
|
||||||
@@ -6,12 +6,12 @@ COMMAND=$1 && shift 1
|
|||||||
case "$COMMAND" in
|
case "$COMMAND" in
|
||||||
'start-worker' )
|
'start-worker' )
|
||||||
echo "Starting Worker..."
|
echo "Starting Worker..."
|
||||||
yarn workspace @standardnotes/scheduler-server worker
|
node docker/entrypoint-worker.js
|
||||||
;;
|
;;
|
||||||
|
|
||||||
'verify-jobs' )
|
'verify-jobs' )
|
||||||
echo "Starting jobs verification..."
|
echo "Starting jobs verification..."
|
||||||
yarn workspace @standardnotes/scheduler-server verify:jobs
|
node docker/entrypoint-verify.js
|
||||||
;;
|
;;
|
||||||
|
|
||||||
* )
|
* )
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@standardnotes/scheduler-server",
|
"name": "@standardnotes/scheduler-server",
|
||||||
"version": "1.16.19",
|
"version": "1.17.0",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18.0.0 <19.0.0"
|
"node": ">=18.0.0 <19.0.0"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -3,6 +3,28 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
# [1.31.0](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.30.2...@standardnotes/syncing-server@1.31.0) (2023-02-15)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* optimize memory usage ([#444](https://github.com/standardnotes/syncing-server-js/issues/444)) ([fdf4b29](https://github.com/standardnotes/syncing-server-js/commit/fdf4b29ae2717e9b5d1fba2722beb7621a7e5c37))
|
||||||
|
|
||||||
|
## [1.30.2](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.30.1...@standardnotes/syncing-server@1.30.2) (2023-02-14)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @standardnotes/syncing-server
|
||||||
|
|
||||||
|
## [1.30.1](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.30.0...@standardnotes/syncing-server@1.30.1) (2023-02-13)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* **syncing-server:** worker container configuration ([fa0b9bf](https://github.com/standardnotes/syncing-server-js/commit/fa0b9bf9353b78542ca02352cbb59232dadbe8b9))
|
||||||
|
|
||||||
|
# [1.30.0](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.29.15...@standardnotes/syncing-server@1.30.0) (2023-02-13)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* **syncing-server:** refactor container config into server and worker ([#443](https://github.com/standardnotes/syncing-server-js/issues/443)) ([993d311](https://github.com/standardnotes/syncing-server-js/commit/993d31167b8b0ac11e3df530d2d1ee566940df6e))
|
||||||
|
|
||||||
## [1.29.15](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.29.14...@standardnotes/syncing-server@1.29.15) (2023-02-09)
|
## [1.29.15](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.29.14...@standardnotes/syncing-server@1.29.15) (2023-02-09)
|
||||||
|
|
||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
|
|||||||
@@ -8,10 +8,10 @@ ENV NODE_ENV production
|
|||||||
|
|
||||||
RUN corepack enable
|
RUN corepack enable
|
||||||
|
|
||||||
WORKDIR /workspace
|
|
||||||
|
|
||||||
COPY ./ /workspace
|
COPY ./ /workspace
|
||||||
|
|
||||||
|
WORKDIR /workspace/packages/syncing-server
|
||||||
|
|
||||||
ENTRYPOINT [ "/workspace/packages/syncing-server/docker/entrypoint.sh" ]
|
ENTRYPOINT [ "/workspace/packages/syncing-server/docker/entrypoint.sh" ]
|
||||||
|
|
||||||
CMD [ "start-web" ]
|
CMD [ "start-web" ]
|
||||||
|
|||||||
@@ -4,11 +4,11 @@ import 'newrelic'
|
|||||||
|
|
||||||
import { Logger } from 'winston'
|
import { Logger } from 'winston'
|
||||||
|
|
||||||
import { ContainerConfigLoader } from '../src/Bootstrap/Container'
|
|
||||||
import TYPES from '../src/Bootstrap/Types'
|
import TYPES from '../src/Bootstrap/Types'
|
||||||
import { Env } from '../src/Bootstrap/Env'
|
import { Env } from '../src/Bootstrap/Env'
|
||||||
import { DomainEventFactoryInterface } from '../src/Domain/Event/DomainEventFactoryInterface'
|
import { DomainEventFactoryInterface } from '../src/Domain/Event/DomainEventFactoryInterface'
|
||||||
import { DomainEventPublisherInterface } from '@standardnotes/domain-events'
|
import { DomainEventPublisherInterface } from '@standardnotes/domain-events'
|
||||||
|
import { WorkerContainerConfigLoader } from '../src/Bootstrap/WorkerContainerConfigLoader'
|
||||||
|
|
||||||
const inputArgs = process.argv.slice(2)
|
const inputArgs = process.argv.slice(2)
|
||||||
const userUuid = inputArgs[0]
|
const userUuid = inputArgs[0]
|
||||||
@@ -20,7 +20,7 @@ const fixContentSize = async (
|
|||||||
await domainEventPublisher.publish(domainEventFactory.createUserContentSizeRecalculationRequestedEvent(userUuid))
|
await domainEventPublisher.publish(domainEventFactory.createUserContentSizeRecalculationRequestedEvent(userUuid))
|
||||||
}
|
}
|
||||||
|
|
||||||
const container = new ContainerConfigLoader()
|
const container = new WorkerContainerConfigLoader()
|
||||||
void container.load().then((container) => {
|
void container.load().then((container) => {
|
||||||
const env: Env = new Env()
|
const env: Env = new Env()
|
||||||
env.load()
|
env.load()
|
||||||
|
|||||||
@@ -1,136 +0,0 @@
|
|||||||
import 'reflect-metadata'
|
|
||||||
|
|
||||||
import 'newrelic'
|
|
||||||
|
|
||||||
import { Logger } from 'winston'
|
|
||||||
|
|
||||||
import { ContainerConfigLoader } from '../src/Bootstrap/Container'
|
|
||||||
import TYPES from '../src/Bootstrap/Types'
|
|
||||||
import { Env } from '../src/Bootstrap/Env'
|
|
||||||
import { DomainEventFactoryInterface } from '../src/Domain/Event/DomainEventFactoryInterface'
|
|
||||||
import { DomainEventPublisherInterface } from '@standardnotes/domain-events'
|
|
||||||
import { ItemRepositoryInterface } from '../src/Domain/Item/ItemRepositoryInterface'
|
|
||||||
import { ContentType } from '@standardnotes/common'
|
|
||||||
|
|
||||||
const fixRevisionsOwnership = async (
|
|
||||||
year: number,
|
|
||||||
month: number,
|
|
||||||
revisionsProcessingLimit: number,
|
|
||||||
itemRepository: ItemRepositoryInterface,
|
|
||||||
domainEventFactory: DomainEventFactoryInterface,
|
|
||||||
domainEventPublisher: DomainEventPublisherInterface,
|
|
||||||
logger: Logger,
|
|
||||||
): Promise<void> => {
|
|
||||||
const createdAfter = new Date(`${year}-${month}-1`)
|
|
||||||
const createdBefore = new Date(`${month !== 12 ? year : year + 1}-${month !== 12 ? month + 1 : 1}-1`)
|
|
||||||
|
|
||||||
logger.info(`[${createdAfter.toISOString()} - ${createdBefore.toISOString()}] Processing items`)
|
|
||||||
|
|
||||||
const itemsCount = await itemRepository.countAll({
|
|
||||||
createdBetween: [createdAfter, createdBefore],
|
|
||||||
selectString: 'item.uuid as uuid, item.user_uuid as userUuid',
|
|
||||||
contentType: [ContentType.Note, ContentType.File],
|
|
||||||
sortOrder: 'ASC',
|
|
||||||
sortBy: 'uuid',
|
|
||||||
})
|
|
||||||
|
|
||||||
logger.info(
|
|
||||||
`[${createdAfter.toISOString()} - ${createdBefore.toISOString()}] There are ${itemsCount} items to process.`,
|
|
||||||
)
|
|
||||||
|
|
||||||
const amountOfPages = Math.ceil(itemsCount / revisionsProcessingLimit)
|
|
||||||
const tenPercentOfPages = Math.ceil(amountOfPages / 10)
|
|
||||||
let itemsProcessedCounter = 0
|
|
||||||
let itemsSkippedCounter = 0
|
|
||||||
for (let page = 1; page <= amountOfPages; page++) {
|
|
||||||
if (page % tenPercentOfPages === 0) {
|
|
||||||
logger.info(
|
|
||||||
`[${createdAfter.toISOString()} - ${createdBefore.toISOString()}] Processing page ${page}/${amountOfPages} of items.`,
|
|
||||||
)
|
|
||||||
logger.info(
|
|
||||||
`[${createdAfter.toISOString()} - ${createdBefore.toISOString()}] Processed successfully/skipped items: ${itemsProcessedCounter}/${itemsSkippedCounter}.`,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
const items = await itemRepository.findAllRaw<{ uuid: string; userUuid: string }>({
|
|
||||||
createdBetween: [createdAfter, createdBefore],
|
|
||||||
selectString: 'item.uuid as uuid, item.user_uuid as userUuid',
|
|
||||||
contentType: [ContentType.Note, ContentType.File],
|
|
||||||
offset: (page - 1) * revisionsProcessingLimit,
|
|
||||||
limit: revisionsProcessingLimit,
|
|
||||||
sortOrder: 'ASC',
|
|
||||||
sortBy: 'uuid',
|
|
||||||
})
|
|
||||||
|
|
||||||
if (items.length === 0) {
|
|
||||||
logger.warn(
|
|
||||||
`[${createdAfter.toISOString()} - ${createdBefore.toISOString()}] No items fetched for offset ${
|
|
||||||
(page - 1) * revisionsProcessingLimit
|
|
||||||
} and limit ${revisionsProcessingLimit}.`,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const item of items) {
|
|
||||||
if (!item.userUuid || !item.uuid) {
|
|
||||||
itemsSkippedCounter++
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
await domainEventPublisher.publish(
|
|
||||||
domainEventFactory.createRevisionsOwnershipUpdateRequestedEvent({
|
|
||||||
userUuid: item.userUuid,
|
|
||||||
itemUuid: item.uuid,
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
|
|
||||||
itemsProcessedCounter++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const container = new ContainerConfigLoader()
|
|
||||||
void container.load().then((container) => {
|
|
||||||
const env: Env = new Env()
|
|
||||||
env.load()
|
|
||||||
|
|
||||||
const logger: Logger = container.get(TYPES.Logger)
|
|
||||||
|
|
||||||
logger.info('Starting revisions ownership fixing')
|
|
||||||
|
|
||||||
const itemRepository: ItemRepositoryInterface = container.get(TYPES.ItemRepository)
|
|
||||||
const domainEventFactory: DomainEventFactoryInterface = container.get(TYPES.DomainEventFactory)
|
|
||||||
const domainEventPublisher: DomainEventPublisherInterface = container.get(TYPES.DomainEventPublisher)
|
|
||||||
|
|
||||||
const years = env.get('REVISION_YEARS').split(',')
|
|
||||||
const months = env.get('REVISION_MONTHS').split(',')
|
|
||||||
const revisionsProcessingLimit = env.get('REVISIONS_PROCESSING_LIMIT')
|
|
||||||
|
|
||||||
const promises = []
|
|
||||||
for (const year of years) {
|
|
||||||
for (const month of months) {
|
|
||||||
promises.push(
|
|
||||||
fixRevisionsOwnership(
|
|
||||||
+year,
|
|
||||||
+month,
|
|
||||||
+revisionsProcessingLimit,
|
|
||||||
itemRepository,
|
|
||||||
domainEventFactory,
|
|
||||||
domainEventPublisher,
|
|
||||||
logger,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Promise.all(promises)
|
|
||||||
.then(() => {
|
|
||||||
logger.info('revisions ownership fix complete.')
|
|
||||||
|
|
||||||
process.exit(0)
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
|
||||||
logger.error(`Could not finish revisions ownership fix: ${error.message}`)
|
|
||||||
|
|
||||||
process.exit(1)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
@@ -6,7 +6,6 @@ import * as Sentry from '@sentry/node'
|
|||||||
import * as Tracing from '@sentry/tracing'
|
import * as Tracing from '@sentry/tracing'
|
||||||
|
|
||||||
import '../src/Controller/HealthCheckController'
|
import '../src/Controller/HealthCheckController'
|
||||||
import '../src/Controller/RevisionsController'
|
|
||||||
import '../src/Controller/ItemsController'
|
import '../src/Controller/ItemsController'
|
||||||
|
|
||||||
import helmet from 'helmet'
|
import helmet from 'helmet'
|
||||||
@@ -15,11 +14,11 @@ import { urlencoded, json, Request, Response, NextFunction, ErrorRequestHandler
|
|||||||
import * as winston from 'winston'
|
import * as winston from 'winston'
|
||||||
|
|
||||||
import { InversifyExpressServer } from 'inversify-express-utils'
|
import { InversifyExpressServer } from 'inversify-express-utils'
|
||||||
import { ContainerConfigLoader } from '../src/Bootstrap/Container'
|
|
||||||
import TYPES from '../src/Bootstrap/Types'
|
import TYPES from '../src/Bootstrap/Types'
|
||||||
import { Env } from '../src/Bootstrap/Env'
|
import { Env } from '../src/Bootstrap/Env'
|
||||||
|
import { ServerContainerConfigLoader } from '../src/Bootstrap/ServerContainerConfigLoader'
|
||||||
|
|
||||||
const container = new ContainerConfigLoader()
|
const container = new ServerContainerConfigLoader()
|
||||||
void container.load().then((container) => {
|
void container.load().then((container) => {
|
||||||
const env: Env = new Env()
|
const env: Env = new Env()
|
||||||
env.load()
|
env.load()
|
||||||
|
|||||||
@@ -4,12 +4,12 @@ import 'newrelic'
|
|||||||
|
|
||||||
import { Logger } from 'winston'
|
import { Logger } from 'winston'
|
||||||
|
|
||||||
import { ContainerConfigLoader } from '../src/Bootstrap/Container'
|
|
||||||
import TYPES from '../src/Bootstrap/Types'
|
import TYPES from '../src/Bootstrap/Types'
|
||||||
import { Env } from '../src/Bootstrap/Env'
|
import { Env } from '../src/Bootstrap/Env'
|
||||||
import { DomainEventSubscriberFactoryInterface } from '@standardnotes/domain-events'
|
import { DomainEventSubscriberFactoryInterface } from '@standardnotes/domain-events'
|
||||||
|
import { WorkerContainerConfigLoader } from '../src/Bootstrap/WorkerContainerConfigLoader'
|
||||||
|
|
||||||
const container = new ContainerConfigLoader()
|
const container = new WorkerContainerConfigLoader()
|
||||||
void container.load().then((container) => {
|
void container.load().then((container) => {
|
||||||
const env: Env = new Env()
|
const env: Env = new Env()
|
||||||
env.load()
|
env.load()
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
'use strict'
|
||||||
|
|
||||||
|
const path = require('path')
|
||||||
|
|
||||||
|
const pnp = require(path.normalize(path.resolve(__dirname, '../../..', '.pnp.cjs'))).setup()
|
||||||
|
|
||||||
|
const index = require(path.normalize(path.resolve(__dirname, '../dist/bin/content.js')))
|
||||||
|
|
||||||
|
Object.defineProperty(exports, '__esModule', { value: true })
|
||||||
|
|
||||||
|
exports.default = index
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
'use strict'
|
||||||
|
|
||||||
|
const path = require('path')
|
||||||
|
|
||||||
|
const pnp = require(path.normalize(path.resolve(__dirname, '../../..', '.pnp.cjs'))).setup()
|
||||||
|
|
||||||
|
const index = require(path.normalize(path.resolve(__dirname, '../dist/bin/server.js')))
|
||||||
|
|
||||||
|
Object.defineProperty(exports, '__esModule', { value: true })
|
||||||
|
|
||||||
|
exports.default = index
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
'use strict'
|
||||||
|
|
||||||
|
const path = require('path')
|
||||||
|
|
||||||
|
const pnp = require(path.normalize(path.resolve(__dirname, '../../..', '.pnp.cjs'))).setup()
|
||||||
|
|
||||||
|
const index = require(path.normalize(path.resolve(__dirname, '../dist/bin/worker.js')))
|
||||||
|
|
||||||
|
Object.defineProperty(exports, '__esModule', { value: true })
|
||||||
|
|
||||||
|
exports.default = index
|
||||||
@@ -4,30 +4,20 @@ set -e
|
|||||||
COMMAND=$1 && shift 1
|
COMMAND=$1 && shift 1
|
||||||
|
|
||||||
case "$COMMAND" in
|
case "$COMMAND" in
|
||||||
'start-local')
|
|
||||||
echo "[Docker] Starting Web in Local Mode..."
|
|
||||||
yarn workspace @standardnotes/syncing-server start:local
|
|
||||||
;;
|
|
||||||
|
|
||||||
'start-web' )
|
'start-web' )
|
||||||
echo "[Docker] Starting Web..."
|
echo "[Docker] Starting Web..."
|
||||||
yarn workspace @standardnotes/syncing-server start
|
node docker/entrypoint-server.js
|
||||||
;;
|
;;
|
||||||
|
|
||||||
'start-worker' )
|
'start-worker' )
|
||||||
echo "[Docker] Starting Worker..."
|
echo "[Docker] Starting Worker..."
|
||||||
yarn workspace @standardnotes/syncing-server worker
|
node docker/entrypoint-worker.js
|
||||||
;;
|
;;
|
||||||
|
|
||||||
'content-size-recalculate' )
|
'content-size-recalculate' )
|
||||||
echo "[Docker] Starting Content Size Recalculation..."
|
echo "[Docker] Starting Content Size Recalculation..."
|
||||||
USER_UUID=$1 && shift 1
|
USER_UUID=$1 && shift 1
|
||||||
yarn workspace @standardnotes/syncing-server content-size $USER_UUID
|
node docker/entrypoint-content.js $USER_UUID
|
||||||
;;
|
|
||||||
|
|
||||||
'revisions-ownership-fix' )
|
|
||||||
echo "[Docker] Starting Revisions Ownership Fixing..."
|
|
||||||
yarn workspace @standardnotes/syncing-server revisions-ownership
|
|
||||||
;;
|
;;
|
||||||
|
|
||||||
* )
|
* )
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@standardnotes/syncing-server",
|
"name": "@standardnotes/syncing-server",
|
||||||
"version": "1.29.15",
|
"version": "1.31.0",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18.0.0 <19.0.0"
|
"node": ">=18.0.0 <19.0.0"
|
||||||
},
|
},
|
||||||
@@ -19,16 +19,9 @@
|
|||||||
"lint:fix": "eslint . --ext .ts --fix",
|
"lint:fix": "eslint . --ext .ts --fix",
|
||||||
"pretest": "yarn lint && yarn build",
|
"pretest": "yarn lint && yarn build",
|
||||||
"test": "jest --coverage --config=./jest.config.js --maxWorkers=50%",
|
"test": "jest --coverage --config=./jest.config.js --maxWorkers=50%",
|
||||||
"wait-for:db": "docker/wait-for.sh $DB_HOST $DB_PORT",
|
|
||||||
"wait-for:cache": "docker/wait-for.sh $REDIS_HOST $REDIS_PORT",
|
|
||||||
"wait-for:infra": "yarn wait-for:db && yarn wait-for:cache",
|
|
||||||
"wait-for:syncing-server": "docker/wait-for.sh localhost $SYNCING_SERVER_PORT",
|
|
||||||
"start": "yarn node dist/bin/server.js",
|
"start": "yarn node dist/bin/server.js",
|
||||||
"supervisor:start": "yarn wait-for:infra && yarn node dist/bin/server.js",
|
|
||||||
"worker": "yarn node dist/bin/worker.js",
|
"worker": "yarn node dist/bin/worker.js",
|
||||||
"supervisor:worker": "yarn wait-for:syncing-server && yarn node dist/bin/worker.js",
|
|
||||||
"content-size": "yarn node dist/bin/content.js",
|
"content-size": "yarn node dist/bin/content.js",
|
||||||
"revisions-ownership": "yarn node dist/bin/revisions.js",
|
|
||||||
"upgrade:snjs": "yarn ncu -u '@standardnotes/*'"
|
"upgrade:snjs": "yarn ncu -u '@standardnotes/*'"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -54,7 +47,6 @@
|
|||||||
"helmet": "^6.0.0",
|
"helmet": "^6.0.0",
|
||||||
"inversify": "^6.0.1",
|
"inversify": "^6.0.1",
|
||||||
"inversify-express-utils": "^6.4.3",
|
"inversify-express-utils": "^6.4.3",
|
||||||
"ioredis": "^5.2.4",
|
|
||||||
"jsonwebtoken": "^9.0.0",
|
"jsonwebtoken": "^9.0.0",
|
||||||
"mysql2": "^3.0.1",
|
"mysql2": "^3.0.1",
|
||||||
"newrelic": "^9.8.0",
|
"newrelic": "^9.8.0",
|
||||||
@@ -71,7 +63,6 @@
|
|||||||
"@types/dotenv": "^8.2.0",
|
"@types/dotenv": "^8.2.0",
|
||||||
"@types/express": "^4.17.14",
|
"@types/express": "^4.17.14",
|
||||||
"@types/inversify-express-utils": "^2.0.0",
|
"@types/inversify-express-utils": "^2.0.0",
|
||||||
"@types/ioredis": "^5.0.0",
|
|
||||||
"@types/jest": "^29.1.1",
|
"@types/jest": "^29.1.1",
|
||||||
"@types/jsonwebtoken": "^9.0.1",
|
"@types/jsonwebtoken": "^9.0.1",
|
||||||
"@types/newrelic": "^9.4.0",
|
"@types/newrelic": "^9.4.0",
|
||||||
|
|||||||
@@ -0,0 +1,119 @@
|
|||||||
|
import * as winston from 'winston'
|
||||||
|
import { Container, interfaces } from 'inversify'
|
||||||
|
|
||||||
|
import { Env } from './Env'
|
||||||
|
import TYPES from './Types'
|
||||||
|
import { AppDataSource } from './DataSource'
|
||||||
|
import { SNSClient, SNSClientConfig } from '@aws-sdk/client-sns'
|
||||||
|
import { ItemRepositoryInterface } from '../Domain/Item/ItemRepositoryInterface'
|
||||||
|
import { MySQLItemRepository } from '../Infra/MySQL/MySQLItemRepository'
|
||||||
|
import { Repository } from 'typeorm'
|
||||||
|
import { Item } from '../Domain/Item/Item'
|
||||||
|
import { ItemProjection } from '../Projection/ItemProjection'
|
||||||
|
import { ProjectorInterface } from '../Projection/ProjectorInterface'
|
||||||
|
import { ItemProjector } from '../Projection/ItemProjector'
|
||||||
|
import { SNSDomainEventPublisher } from '@standardnotes/domain-events-infra'
|
||||||
|
import { DomainEventFactoryInterface } from '../Domain/Event/DomainEventFactoryInterface'
|
||||||
|
import { DomainEventFactory } from '../Domain/Event/DomainEventFactory'
|
||||||
|
import { Timer, TimerInterface } from '@standardnotes/time'
|
||||||
|
import { ItemTransferCalculatorInterface } from '../Domain/Item/ItemTransferCalculatorInterface'
|
||||||
|
import { ItemTransferCalculator } from '../Domain/Item/ItemTransferCalculator'
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||||
|
const newrelicFormatter = require('@newrelic/winston-enricher')
|
||||||
|
|
||||||
|
export class CommonContainerConfigLoader {
|
||||||
|
async load(): Promise<Container> {
|
||||||
|
const env: Env = new Env()
|
||||||
|
env.load()
|
||||||
|
|
||||||
|
const container = new Container({
|
||||||
|
defaultScope: 'Singleton',
|
||||||
|
})
|
||||||
|
|
||||||
|
await AppDataSource.initialize()
|
||||||
|
|
||||||
|
container.bind<Env>(TYPES.Env).toConstantValue(env)
|
||||||
|
|
||||||
|
container.bind<winston.Logger>(TYPES.Logger).toDynamicValue((context: interfaces.Context) => {
|
||||||
|
const env: Env = context.container.get(TYPES.Env)
|
||||||
|
|
||||||
|
const newrelicWinstonFormatter = newrelicFormatter(winston)
|
||||||
|
const winstonFormatters = [winston.format.splat(), winston.format.json()]
|
||||||
|
if (env.get('NEW_RELIC_ENABLED', true) === 'true') {
|
||||||
|
winstonFormatters.push(newrelicWinstonFormatter())
|
||||||
|
}
|
||||||
|
|
||||||
|
const logger = winston.createLogger({
|
||||||
|
level: env.get('LOG_LEVEL') || 'info',
|
||||||
|
format: winston.format.combine(...winstonFormatters),
|
||||||
|
transports: [new winston.transports.Console({ level: env.get('LOG_LEVEL') || 'info' })],
|
||||||
|
})
|
||||||
|
|
||||||
|
return logger
|
||||||
|
})
|
||||||
|
|
||||||
|
container.bind<SNSClient>(TYPES.SNS).toDynamicValue((context: interfaces.Context) => {
|
||||||
|
const env: Env = context.container.get(TYPES.Env)
|
||||||
|
|
||||||
|
const snsConfig: SNSClientConfig = {
|
||||||
|
apiVersion: 'latest',
|
||||||
|
region: env.get('SNS_AWS_REGION', true),
|
||||||
|
}
|
||||||
|
if (env.get('SNS_ENDPOINT', true)) {
|
||||||
|
snsConfig.endpoint = env.get('SNS_ENDPOINT', true)
|
||||||
|
}
|
||||||
|
if (env.get('SNS_ACCESS_KEY_ID', true) && env.get('SNS_SECRET_ACCESS_KEY', true)) {
|
||||||
|
snsConfig.credentials = {
|
||||||
|
accessKeyId: env.get('SNS_ACCESS_KEY_ID', true),
|
||||||
|
secretAccessKey: env.get('SNS_SECRET_ACCESS_KEY', true),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new SNSClient(snsConfig)
|
||||||
|
})
|
||||||
|
|
||||||
|
// Repositories
|
||||||
|
container.bind<ItemRepositoryInterface>(TYPES.ItemRepository).toDynamicValue((context: interfaces.Context) => {
|
||||||
|
return new MySQLItemRepository(context.container.get(TYPES.ORMItemRepository))
|
||||||
|
})
|
||||||
|
|
||||||
|
// ORM
|
||||||
|
container.bind<Repository<Item>>(TYPES.ORMItemRepository).toDynamicValue(() => AppDataSource.getRepository(Item))
|
||||||
|
|
||||||
|
// Projectors
|
||||||
|
container
|
||||||
|
.bind<ProjectorInterface<Item, ItemProjection>>(TYPES.ItemProjector)
|
||||||
|
.toDynamicValue((context: interfaces.Context) => {
|
||||||
|
return new ItemProjector(context.container.get(TYPES.Timer))
|
||||||
|
})
|
||||||
|
|
||||||
|
// env vars
|
||||||
|
container.bind(TYPES.SNS_TOPIC_ARN).toConstantValue(env.get('SNS_TOPIC_ARN'))
|
||||||
|
container.bind(TYPES.SNS_AWS_REGION).toConstantValue(env.get('SNS_AWS_REGION', true))
|
||||||
|
|
||||||
|
container.bind<TimerInterface>(TYPES.Timer).toDynamicValue(() => new Timer())
|
||||||
|
|
||||||
|
container
|
||||||
|
.bind<SNSDomainEventPublisher>(TYPES.DomainEventPublisher)
|
||||||
|
.toDynamicValue((context: interfaces.Context) => {
|
||||||
|
return new SNSDomainEventPublisher(context.container.get(TYPES.SNS), context.container.get(TYPES.SNS_TOPIC_ARN))
|
||||||
|
})
|
||||||
|
|
||||||
|
container
|
||||||
|
.bind<DomainEventFactoryInterface>(TYPES.DomainEventFactory)
|
||||||
|
.toDynamicValue((context: interfaces.Context) => {
|
||||||
|
return new DomainEventFactory(context.container.get(TYPES.Timer))
|
||||||
|
})
|
||||||
|
|
||||||
|
container
|
||||||
|
.bind<ItemTransferCalculatorInterface>(TYPES.ItemTransferCalculator)
|
||||||
|
.toDynamicValue((context: interfaces.Context) => {
|
||||||
|
return new ItemTransferCalculator(
|
||||||
|
context.container.get(TYPES.ItemRepository),
|
||||||
|
context.container.get(TYPES.Logger),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
return container
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,331 +0,0 @@
|
|||||||
import * as winston from 'winston'
|
|
||||||
import Redis from 'ioredis'
|
|
||||||
import { SQSClient, SQSClientConfig } from '@aws-sdk/client-sqs'
|
|
||||||
import { SNSClient, SNSClientConfig } from '@aws-sdk/client-sns'
|
|
||||||
import { S3Client } from '@aws-sdk/client-s3'
|
|
||||||
import { Container } from 'inversify'
|
|
||||||
import {
|
|
||||||
DomainEventHandlerInterface,
|
|
||||||
DomainEventMessageHandlerInterface,
|
|
||||||
DomainEventSubscriberFactoryInterface,
|
|
||||||
} from '@standardnotes/domain-events'
|
|
||||||
|
|
||||||
import { Env } from './Env'
|
|
||||||
import TYPES from './Types'
|
|
||||||
import { AuthMiddleware } from '../Controller/AuthMiddleware'
|
|
||||||
import { MySQLRevisionRepository } from '../Infra/MySQL/MySQLRevisionRepository'
|
|
||||||
import { Item } from '../Domain/Item/Item'
|
|
||||||
import { Revision } from '../Domain/Revision/Revision'
|
|
||||||
import { RevisionProjector } from '../Projection/RevisionProjector'
|
|
||||||
import { MySQLItemRepository } from '../Infra/MySQL/MySQLItemRepository'
|
|
||||||
import { ContentDecoder } from '../Domain/Item/ContentDecoder'
|
|
||||||
import { DomainEventFactory } from '../Domain/Event/DomainEventFactory'
|
|
||||||
import { SyncResponseFactory20161215 } from '../Domain/Item/SyncResponse/SyncResponseFactory20161215'
|
|
||||||
import { SyncResponseFactory20200115 } from '../Domain/Item/SyncResponse/SyncResponseFactory20200115'
|
|
||||||
import { SyncResponseFactoryResolverInterface } from '../Domain/Item/SyncResponse/SyncResponseFactoryResolverInterface'
|
|
||||||
import { SyncResponseFactoryResolver } from '../Domain/Item/SyncResponse/SyncResponseFactoryResolver'
|
|
||||||
import { ItemServiceInterface } from '../Domain/Item/ItemServiceInterface'
|
|
||||||
import { ItemService } from '../Domain/Item/ItemService'
|
|
||||||
import { AuthHttpServiceInterface } from '../Domain/Auth/AuthHttpServiceInterface'
|
|
||||||
import { AuthHttpService } from '../Infra/HTTP/AuthHttpService'
|
|
||||||
import { SyncItems } from '../Domain/UseCase/SyncItems'
|
|
||||||
import { ExtensionsHttpServiceInterface } from '../Domain/Extension/ExtensionsHttpServiceInterface'
|
|
||||||
import { ExtensionsHttpService } from '../Domain/Extension/ExtensionsHttpService'
|
|
||||||
import { ItemBackupServiceInterface } from '../Domain/Item/ItemBackupServiceInterface'
|
|
||||||
import { S3ItemBackupService } from '../Infra/S3/S3ItemBackupService'
|
|
||||||
import { DomainEventFactoryInterface } from '../Domain/Event/DomainEventFactoryInterface'
|
|
||||||
import { RevisionServiceInterface } from '../Domain/Revision/RevisionServiceInterface'
|
|
||||||
import { RevisionService } from '../Domain/Revision/RevisionService'
|
|
||||||
import { DuplicateItemSyncedEventHandler } from '../Domain/Handler/DuplicateItemSyncedEventHandler'
|
|
||||||
import { AccountDeletionRequestedEventHandler } from '../Domain/Handler/AccountDeletionRequestedEventHandler'
|
|
||||||
import { ItemProjector } from '../Projection/ItemProjector'
|
|
||||||
import { ItemConflictProjector } from '../Projection/ItemConflictProjector'
|
|
||||||
import { Timer, TimerInterface } from '@standardnotes/time'
|
|
||||||
import { ItemSaveValidatorInterface } from '../Domain/Item/SaveValidator/ItemSaveValidatorInterface'
|
|
||||||
import { ItemSaveValidator } from '../Domain/Item/SaveValidator/ItemSaveValidator'
|
|
||||||
import { OwnershipFilter } from '../Domain/Item/SaveRule/OwnershipFilter'
|
|
||||||
import { TimeDifferenceFilter } from '../Domain/Item/SaveRule/TimeDifferenceFilter'
|
|
||||||
import { ItemFactoryInterface } from '../Domain/Item/ItemFactoryInterface'
|
|
||||||
import { ItemFactory } from '../Domain/Item/ItemFactory'
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
||||||
const axios = require('axios')
|
|
||||||
import { AxiosInstance } from 'axios'
|
|
||||||
import { UuidFilter } from '../Domain/Item/SaveRule/UuidFilter'
|
|
||||||
import { ContentTypeFilter } from '../Domain/Item/SaveRule/ContentTypeFilter'
|
|
||||||
import { ContentFilter } from '../Domain/Item/SaveRule/ContentFilter'
|
|
||||||
import {
|
|
||||||
SNSDomainEventPublisher,
|
|
||||||
SQSDomainEventSubscriberFactory,
|
|
||||||
SQSEventMessageHandler,
|
|
||||||
SQSNewRelicEventMessageHandler,
|
|
||||||
} from '@standardnotes/domain-events-infra'
|
|
||||||
import { EmailBackupRequestedEventHandler } from '../Domain/Handler/EmailBackupRequestedEventHandler'
|
|
||||||
import { CloudBackupRequestedEventHandler } from '../Domain/Handler/CloudBackupRequestedEventHandler'
|
|
||||||
import { CheckIntegrity } from '../Domain/UseCase/CheckIntegrity/CheckIntegrity'
|
|
||||||
import { GetItem } from '../Domain/UseCase/GetItem/GetItem'
|
|
||||||
import { ItemTransferCalculatorInterface } from '../Domain/Item/ItemTransferCalculatorInterface'
|
|
||||||
import { ItemTransferCalculator } from '../Domain/Item/ItemTransferCalculator'
|
|
||||||
import { ProjectorInterface } from '../Projection/ProjectorInterface'
|
|
||||||
import { SavedItemProjection } from '../Projection/SavedItemProjection'
|
|
||||||
import { SavedItemProjector } from '../Projection/SavedItemProjector'
|
|
||||||
import { ItemProjection } from '../Projection/ItemProjection'
|
|
||||||
import { RevisionProjection } from '../Projection/RevisionProjection'
|
|
||||||
import { ItemConflict } from '../Domain/Item/ItemConflict'
|
|
||||||
import { ItemConflictProjection } from '../Projection/ItemConflictProjection'
|
|
||||||
import { AppDataSource } from './DataSource'
|
|
||||||
import { RevisionRepositoryInterface } from '../Domain/Revision/RevisionRepositoryInterface'
|
|
||||||
import { ItemRepositoryInterface } from '../Domain/Item/ItemRepositoryInterface'
|
|
||||||
import { Repository } from 'typeorm'
|
|
||||||
import { UserContentSizeRecalculationRequestedEventHandler } from '../Domain/Handler/UserContentSizeRecalculationRequestedEventHandler'
|
|
||||||
import { RevisionMetadataMap } from '../Domain/Map/RevisionMetadataMap'
|
|
||||||
import { MapperInterface } from '@standardnotes/domain-core'
|
|
||||||
import { RevisionMetadata } from '../Domain/Revision/RevisionMetadata'
|
|
||||||
import { SimpleRevisionProjection } from '../Projection/SimpleRevisionProjection'
|
|
||||||
import { ItemRevisionCreationRequestedEventHandler } from '../Domain/Handler/ItemRevisionCreationRequestedEventHandler'
|
|
||||||
import { FSItemBackupService } from '../Infra/FS/FSItemBackupService'
|
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
||||||
const newrelicFormatter = require('@newrelic/winston-enricher')
|
|
||||||
|
|
||||||
export class ContainerConfigLoader {
|
|
||||||
private readonly DEFAULT_CONTENT_SIZE_TRANSFER_LIMIT = 10_000_000
|
|
||||||
private readonly DEFAULT_MAX_ITEMS_LIMIT = 300
|
|
||||||
private readonly DEFAULT_FILE_UPLOAD_PATH = `${__dirname}/../../uploads`
|
|
||||||
|
|
||||||
async load(): Promise<Container> {
|
|
||||||
const env: Env = new Env()
|
|
||||||
env.load()
|
|
||||||
|
|
||||||
const container = new Container()
|
|
||||||
|
|
||||||
await AppDataSource.initialize()
|
|
||||||
|
|
||||||
const redisUrl = env.get('REDIS_URL')
|
|
||||||
const isRedisInClusterMode = redisUrl.indexOf(',') > 0
|
|
||||||
let redis
|
|
||||||
if (isRedisInClusterMode) {
|
|
||||||
redis = new Redis.Cluster(redisUrl.split(','))
|
|
||||||
} else {
|
|
||||||
redis = new Redis(redisUrl)
|
|
||||||
}
|
|
||||||
|
|
||||||
container.bind(TYPES.Redis).toConstantValue(redis)
|
|
||||||
|
|
||||||
const newrelicWinstonFormatter = newrelicFormatter(winston)
|
|
||||||
const winstonFormatters = [winston.format.splat(), winston.format.json()]
|
|
||||||
if (env.get('NEW_RELIC_ENABLED', true) === 'true') {
|
|
||||||
winstonFormatters.push(newrelicWinstonFormatter())
|
|
||||||
}
|
|
||||||
|
|
||||||
const logger = winston.createLogger({
|
|
||||||
level: env.get('LOG_LEVEL') || 'info',
|
|
||||||
format: winston.format.combine(...winstonFormatters),
|
|
||||||
transports: [new winston.transports.Console({ level: env.get('LOG_LEVEL') || 'info' })],
|
|
||||||
})
|
|
||||||
container.bind<winston.Logger>(TYPES.Logger).toConstantValue(logger)
|
|
||||||
|
|
||||||
if (env.get('SNS_TOPIC_ARN', true)) {
|
|
||||||
const snsConfig: SNSClientConfig = {
|
|
||||||
apiVersion: 'latest',
|
|
||||||
region: env.get('SNS_AWS_REGION', true),
|
|
||||||
}
|
|
||||||
if (env.get('SNS_ENDPOINT', true)) {
|
|
||||||
snsConfig.endpoint = env.get('SNS_ENDPOINT', true)
|
|
||||||
}
|
|
||||||
if (env.get('SNS_ACCESS_KEY_ID', true) && env.get('SNS_SECRET_ACCESS_KEY', true)) {
|
|
||||||
snsConfig.credentials = {
|
|
||||||
accessKeyId: env.get('SNS_ACCESS_KEY_ID', true),
|
|
||||||
secretAccessKey: env.get('SNS_SECRET_ACCESS_KEY', true),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
container.bind<SNSClient>(TYPES.SNS).toConstantValue(new SNSClient(snsConfig))
|
|
||||||
}
|
|
||||||
|
|
||||||
if (env.get('SQS_QUEUE_URL', true)) {
|
|
||||||
const sqsConfig: SQSClientConfig = {
|
|
||||||
region: env.get('SQS_AWS_REGION', true),
|
|
||||||
}
|
|
||||||
if (env.get('SQS_ENDPOINT', true)) {
|
|
||||||
sqsConfig.endpoint = env.get('SQS_ENDPOINT', true)
|
|
||||||
}
|
|
||||||
if (env.get('SQS_ACCESS_KEY_ID', true) && env.get('SQS_SECRET_ACCESS_KEY', true)) {
|
|
||||||
sqsConfig.credentials = {
|
|
||||||
accessKeyId: env.get('SQS_ACCESS_KEY_ID', true),
|
|
||||||
secretAccessKey: env.get('SQS_SECRET_ACCESS_KEY', true),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
container.bind<SQSClient>(TYPES.SQS).toConstantValue(new SQSClient(sqsConfig))
|
|
||||||
}
|
|
||||||
|
|
||||||
let s3Client = undefined
|
|
||||||
if (env.get('S3_AWS_REGION', true)) {
|
|
||||||
s3Client = new S3Client({
|
|
||||||
apiVersion: 'latest',
|
|
||||||
region: env.get('S3_AWS_REGION', true),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
container.bind<S3Client | undefined>(TYPES.S3).toConstantValue(s3Client)
|
|
||||||
|
|
||||||
// Repositories
|
|
||||||
container.bind<RevisionRepositoryInterface>(TYPES.RevisionRepository).to(MySQLRevisionRepository)
|
|
||||||
container.bind<ItemRepositoryInterface>(TYPES.ItemRepository).to(MySQLItemRepository)
|
|
||||||
|
|
||||||
// ORM
|
|
||||||
container
|
|
||||||
.bind<Repository<Revision>>(TYPES.ORMRevisionRepository)
|
|
||||||
.toConstantValue(AppDataSource.getRepository(Revision))
|
|
||||||
container.bind<Repository<Item>>(TYPES.ORMItemRepository).toConstantValue(AppDataSource.getRepository(Item))
|
|
||||||
|
|
||||||
// Middleware
|
|
||||||
container.bind<AuthMiddleware>(TYPES.AuthMiddleware).to(AuthMiddleware)
|
|
||||||
|
|
||||||
// Projectors
|
|
||||||
container.bind<ProjectorInterface<Revision, RevisionProjection>>(TYPES.RevisionProjector).to(RevisionProjector)
|
|
||||||
container.bind<ProjectorInterface<Item, ItemProjection>>(TYPES.ItemProjector).to(ItemProjector)
|
|
||||||
container.bind<ProjectorInterface<Item, SavedItemProjection>>(TYPES.SavedItemProjector).to(SavedItemProjector)
|
|
||||||
container
|
|
||||||
.bind<ProjectorInterface<ItemConflict, ItemConflictProjection>>(TYPES.ItemConflictProjector)
|
|
||||||
.to(ItemConflictProjector)
|
|
||||||
|
|
||||||
// env vars
|
|
||||||
container.bind(TYPES.REDIS_URL).toConstantValue(env.get('REDIS_URL'))
|
|
||||||
container.bind(TYPES.SNS_TOPIC_ARN).toConstantValue(env.get('SNS_TOPIC_ARN'))
|
|
||||||
container.bind(TYPES.SNS_AWS_REGION).toConstantValue(env.get('SNS_AWS_REGION', true))
|
|
||||||
container.bind(TYPES.SQS_QUEUE_URL).toConstantValue(env.get('SQS_QUEUE_URL'))
|
|
||||||
container.bind(TYPES.AUTH_JWT_SECRET).toConstantValue(env.get('AUTH_JWT_SECRET'))
|
|
||||||
container
|
|
||||||
.bind(TYPES.INTERNAL_DNS_REROUTE_ENABLED)
|
|
||||||
.toConstantValue(env.get('INTERNAL_DNS_REROUTE_ENABLED', true) === 'true')
|
|
||||||
container.bind(TYPES.EXTENSIONS_SERVER_URL).toConstantValue(env.get('EXTENSIONS_SERVER_URL', true))
|
|
||||||
container.bind(TYPES.AUTH_SERVER_URL).toConstantValue(env.get('AUTH_SERVER_URL'))
|
|
||||||
container.bind(TYPES.S3_AWS_REGION).toConstantValue(env.get('S3_AWS_REGION', true))
|
|
||||||
container.bind(TYPES.S3_BACKUP_BUCKET_NAME).toConstantValue(env.get('S3_BACKUP_BUCKET_NAME', true))
|
|
||||||
container.bind(TYPES.EMAIL_ATTACHMENT_MAX_BYTE_SIZE).toConstantValue(env.get('EMAIL_ATTACHMENT_MAX_BYTE_SIZE'))
|
|
||||||
container.bind(TYPES.REVISIONS_FREQUENCY).toConstantValue(env.get('REVISIONS_FREQUENCY'))
|
|
||||||
container.bind(TYPES.NEW_RELIC_ENABLED).toConstantValue(env.get('NEW_RELIC_ENABLED', true))
|
|
||||||
container.bind(TYPES.VERSION).toConstantValue(env.get('VERSION'))
|
|
||||||
container
|
|
||||||
.bind(TYPES.CONTENT_SIZE_TRANSFER_LIMIT)
|
|
||||||
.toConstantValue(
|
|
||||||
env.get('CONTENT_SIZE_TRANSFER_LIMIT', true)
|
|
||||||
? +env.get('CONTENT_SIZE_TRANSFER_LIMIT', true)
|
|
||||||
: this.DEFAULT_CONTENT_SIZE_TRANSFER_LIMIT,
|
|
||||||
)
|
|
||||||
container
|
|
||||||
.bind(TYPES.MAX_ITEMS_LIMIT)
|
|
||||||
.toConstantValue(
|
|
||||||
env.get('MAX_ITEMS_LIMIT', true) ? +env.get('MAX_ITEMS_LIMIT', true) : this.DEFAULT_MAX_ITEMS_LIMIT,
|
|
||||||
)
|
|
||||||
container
|
|
||||||
.bind(TYPES.FILE_UPLOAD_PATH)
|
|
||||||
.toConstantValue(
|
|
||||||
env.get('FILE_UPLOAD_PATH', true) ? env.get('FILE_UPLOAD_PATH', true) : this.DEFAULT_FILE_UPLOAD_PATH,
|
|
||||||
)
|
|
||||||
|
|
||||||
// use cases
|
|
||||||
container.bind<SyncItems>(TYPES.SyncItems).to(SyncItems)
|
|
||||||
container.bind<CheckIntegrity>(TYPES.CheckIntegrity).to(CheckIntegrity)
|
|
||||||
container.bind<GetItem>(TYPES.GetItem).to(GetItem)
|
|
||||||
|
|
||||||
// Handlers
|
|
||||||
container
|
|
||||||
.bind<DuplicateItemSyncedEventHandler>(TYPES.DuplicateItemSyncedEventHandler)
|
|
||||||
.to(DuplicateItemSyncedEventHandler)
|
|
||||||
container
|
|
||||||
.bind<AccountDeletionRequestedEventHandler>(TYPES.AccountDeletionRequestedEventHandler)
|
|
||||||
.to(AccountDeletionRequestedEventHandler)
|
|
||||||
container
|
|
||||||
.bind<EmailBackupRequestedEventHandler>(TYPES.EmailBackupRequestedEventHandler)
|
|
||||||
.to(EmailBackupRequestedEventHandler)
|
|
||||||
container
|
|
||||||
.bind<CloudBackupRequestedEventHandler>(TYPES.CloudBackupRequestedEventHandler)
|
|
||||||
.to(CloudBackupRequestedEventHandler)
|
|
||||||
container
|
|
||||||
.bind<UserContentSizeRecalculationRequestedEventHandler>(TYPES.UserContentSizeRecalculationRequestedEventHandler)
|
|
||||||
.to(UserContentSizeRecalculationRequestedEventHandler)
|
|
||||||
container
|
|
||||||
.bind<ItemRevisionCreationRequestedEventHandler>(TYPES.ItemRevisionCreationRequestedEventHandler)
|
|
||||||
.to(ItemRevisionCreationRequestedEventHandler)
|
|
||||||
|
|
||||||
// Map
|
|
||||||
container
|
|
||||||
.bind<MapperInterface<RevisionMetadata, SimpleRevisionProjection>>(TYPES.RevisionMetadataMap)
|
|
||||||
.to(RevisionMetadataMap)
|
|
||||||
|
|
||||||
// Services
|
|
||||||
container.bind<ContentDecoder>(TYPES.ContentDecoder).to(ContentDecoder)
|
|
||||||
container.bind<DomainEventFactoryInterface>(TYPES.DomainEventFactory).to(DomainEventFactory)
|
|
||||||
container.bind<AxiosInstance>(TYPES.HTTPClient).toConstantValue(axios.create())
|
|
||||||
container.bind<ItemServiceInterface>(TYPES.ItemService).to(ItemService)
|
|
||||||
container.bind<ItemTransferCalculatorInterface>(TYPES.ItemTransferCalculator).to(ItemTransferCalculator)
|
|
||||||
container.bind<TimerInterface>(TYPES.Timer).toConstantValue(new Timer())
|
|
||||||
container.bind<SyncResponseFactory20161215>(TYPES.SyncResponseFactory20161215).to(SyncResponseFactory20161215)
|
|
||||||
container.bind<SyncResponseFactory20200115>(TYPES.SyncResponseFactory20200115).to(SyncResponseFactory20200115)
|
|
||||||
container
|
|
||||||
.bind<SyncResponseFactoryResolverInterface>(TYPES.SyncResponseFactoryResolver)
|
|
||||||
.to(SyncResponseFactoryResolver)
|
|
||||||
container.bind<AuthHttpServiceInterface>(TYPES.AuthHttpService).to(AuthHttpService)
|
|
||||||
container.bind<ExtensionsHttpServiceInterface>(TYPES.ExtensionsHttpService).to(ExtensionsHttpService)
|
|
||||||
if (env.get('S3_AWS_REGION', true)) {
|
|
||||||
container.bind<ItemBackupServiceInterface>(TYPES.ItemBackupService).to(S3ItemBackupService)
|
|
||||||
} else {
|
|
||||||
container.bind<ItemBackupServiceInterface>(TYPES.ItemBackupService).to(FSItemBackupService)
|
|
||||||
}
|
|
||||||
container.bind<RevisionServiceInterface>(TYPES.RevisionService).to(RevisionService)
|
|
||||||
|
|
||||||
container
|
|
||||||
.bind<SNSDomainEventPublisher>(TYPES.DomainEventPublisher)
|
|
||||||
.toConstantValue(new SNSDomainEventPublisher(container.get(TYPES.SNS), container.get(TYPES.SNS_TOPIC_ARN)))
|
|
||||||
|
|
||||||
const eventHandlers: Map<string, DomainEventHandlerInterface> = new Map([
|
|
||||||
['DUPLICATE_ITEM_SYNCED', container.get(TYPES.DuplicateItemSyncedEventHandler)],
|
|
||||||
['ACCOUNT_DELETION_REQUESTED', container.get(TYPES.AccountDeletionRequestedEventHandler)],
|
|
||||||
['EMAIL_BACKUP_REQUESTED', container.get(TYPES.EmailBackupRequestedEventHandler)],
|
|
||||||
['CLOUD_BACKUP_REQUESTED', container.get(TYPES.CloudBackupRequestedEventHandler)],
|
|
||||||
[
|
|
||||||
'USER_CONTENT_SIZE_RECALCULATION_REQUESTED',
|
|
||||||
container.get(TYPES.UserContentSizeRecalculationRequestedEventHandler),
|
|
||||||
],
|
|
||||||
['ITEM_REVISION_CREATION_REQUESTED', container.get(TYPES.ItemRevisionCreationRequestedEventHandler)],
|
|
||||||
])
|
|
||||||
|
|
||||||
container
|
|
||||||
.bind<DomainEventMessageHandlerInterface>(TYPES.DomainEventMessageHandler)
|
|
||||||
.toConstantValue(
|
|
||||||
env.get('NEW_RELIC_ENABLED', true) === 'true'
|
|
||||||
? new SQSNewRelicEventMessageHandler(eventHandlers, container.get(TYPES.Logger))
|
|
||||||
: new SQSEventMessageHandler(eventHandlers, container.get(TYPES.Logger)),
|
|
||||||
)
|
|
||||||
container
|
|
||||||
.bind<DomainEventSubscriberFactoryInterface>(TYPES.DomainEventSubscriberFactory)
|
|
||||||
.toConstantValue(
|
|
||||||
new SQSDomainEventSubscriberFactory(
|
|
||||||
container.get(TYPES.SQS),
|
|
||||||
container.get(TYPES.SQS_QUEUE_URL),
|
|
||||||
container.get(TYPES.DomainEventMessageHandler),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
container.bind<ItemFactoryInterface>(TYPES.ItemFactory).to(ItemFactory)
|
|
||||||
|
|
||||||
container.bind<OwnershipFilter>(TYPES.OwnershipFilter).to(OwnershipFilter)
|
|
||||||
container.bind<TimeDifferenceFilter>(TYPES.TimeDifferenceFilter).to(TimeDifferenceFilter)
|
|
||||||
container.bind<UuidFilter>(TYPES.UuidFilter).to(UuidFilter)
|
|
||||||
container.bind<ContentTypeFilter>(TYPES.ContentTypeFilter).to(ContentTypeFilter)
|
|
||||||
container.bind<ContentFilter>(TYPES.ContentFilter).to(ContentFilter)
|
|
||||||
|
|
||||||
container
|
|
||||||
.bind<ItemSaveValidatorInterface>(TYPES.ItemSaveValidator)
|
|
||||||
.toConstantValue(
|
|
||||||
new ItemSaveValidator([
|
|
||||||
container.get(TYPES.OwnershipFilter),
|
|
||||||
container.get(TYPES.TimeDifferenceFilter),
|
|
||||||
container.get(TYPES.UuidFilter),
|
|
||||||
container.get(TYPES.ContentTypeFilter),
|
|
||||||
container.get(TYPES.ContentFilter),
|
|
||||||
]),
|
|
||||||
)
|
|
||||||
|
|
||||||
return container
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
import { DataSource, LoggerOptions } from 'typeorm'
|
import { DataSource, LoggerOptions } from 'typeorm'
|
||||||
import { Item } from '../Domain/Item/Item'
|
import { Item } from '../Domain/Item/Item'
|
||||||
import { Revision } from '../Domain/Revision/Revision'
|
|
||||||
import { Env } from './Env'
|
import { Env } from './Env'
|
||||||
|
|
||||||
const env: Env = new Env()
|
const env: Env = new Env()
|
||||||
@@ -45,7 +44,7 @@ export const AppDataSource = new DataSource({
|
|||||||
username: inReplicaMode ? undefined : env.get('DB_USERNAME'),
|
username: inReplicaMode ? undefined : env.get('DB_USERNAME'),
|
||||||
password: inReplicaMode ? undefined : env.get('DB_PASSWORD'),
|
password: inReplicaMode ? undefined : env.get('DB_PASSWORD'),
|
||||||
database: inReplicaMode ? undefined : env.get('DB_DATABASE'),
|
database: inReplicaMode ? undefined : env.get('DB_DATABASE'),
|
||||||
entities: [Item, Revision],
|
entities: [Item],
|
||||||
migrations: [env.get('DB_MIGRATIONS_PATH', true) ?? 'dist/migrations/*.js'],
|
migrations: [env.get('DB_MIGRATIONS_PATH', true) ?? 'dist/migrations/*.js'],
|
||||||
migrationsRun: true,
|
migrationsRun: true,
|
||||||
logging: <LoggerOptions>env.get('DB_DEBUG_LEVEL'),
|
logging: <LoggerOptions>env.get('DB_DEBUG_LEVEL'),
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
import { config, DotenvParseOutput } from 'dotenv'
|
import { config, DotenvParseOutput } from 'dotenv'
|
||||||
import { injectable } from 'inversify'
|
|
||||||
|
|
||||||
@injectable()
|
|
||||||
export class Env {
|
export class Env {
|
||||||
private env?: DotenvParseOutput
|
private env?: DotenvParseOutput
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,154 @@
|
|||||||
|
import { Container, interfaces } from 'inversify'
|
||||||
|
|
||||||
|
import { Env } from './Env'
|
||||||
|
import TYPES from './Types'
|
||||||
|
import { AuthMiddleware } from '../Controller/AuthMiddleware'
|
||||||
|
import { Item } from '../Domain/Item/Item'
|
||||||
|
import { SyncResponseFactory20161215 } from '../Domain/Item/SyncResponse/SyncResponseFactory20161215'
|
||||||
|
import { SyncResponseFactory20200115 } from '../Domain/Item/SyncResponse/SyncResponseFactory20200115'
|
||||||
|
import { SyncResponseFactoryResolverInterface } from '../Domain/Item/SyncResponse/SyncResponseFactoryResolverInterface'
|
||||||
|
import { SyncResponseFactoryResolver } from '../Domain/Item/SyncResponse/SyncResponseFactoryResolver'
|
||||||
|
import { ItemServiceInterface } from '../Domain/Item/ItemServiceInterface'
|
||||||
|
import { ItemService } from '../Domain/Item/ItemService'
|
||||||
|
import { SyncItems } from '../Domain/UseCase/SyncItems'
|
||||||
|
import { ItemConflictProjector } from '../Projection/ItemConflictProjector'
|
||||||
|
import { ItemSaveValidatorInterface } from '../Domain/Item/SaveValidator/ItemSaveValidatorInterface'
|
||||||
|
import { ItemSaveValidator } from '../Domain/Item/SaveValidator/ItemSaveValidator'
|
||||||
|
import { OwnershipFilter } from '../Domain/Item/SaveRule/OwnershipFilter'
|
||||||
|
import { TimeDifferenceFilter } from '../Domain/Item/SaveRule/TimeDifferenceFilter'
|
||||||
|
import { ItemFactoryInterface } from '../Domain/Item/ItemFactoryInterface'
|
||||||
|
import { ItemFactory } from '../Domain/Item/ItemFactory'
|
||||||
|
import { UuidFilter } from '../Domain/Item/SaveRule/UuidFilter'
|
||||||
|
import { ContentTypeFilter } from '../Domain/Item/SaveRule/ContentTypeFilter'
|
||||||
|
import { ContentFilter } from '../Domain/Item/SaveRule/ContentFilter'
|
||||||
|
import { CheckIntegrity } from '../Domain/UseCase/CheckIntegrity/CheckIntegrity'
|
||||||
|
import { GetItem } from '../Domain/UseCase/GetItem/GetItem'
|
||||||
|
import { ProjectorInterface } from '../Projection/ProjectorInterface'
|
||||||
|
import { SavedItemProjection } from '../Projection/SavedItemProjection'
|
||||||
|
import { SavedItemProjector } from '../Projection/SavedItemProjector'
|
||||||
|
import { ItemConflict } from '../Domain/Item/ItemConflict'
|
||||||
|
import { ItemConflictProjection } from '../Projection/ItemConflictProjection'
|
||||||
|
import { CommonContainerConfigLoader } from './CommonContainerConfigLoader'
|
||||||
|
|
||||||
|
export class ServerContainerConfigLoader extends CommonContainerConfigLoader {
|
||||||
|
private readonly DEFAULT_CONTENT_SIZE_TRANSFER_LIMIT = 10_000_000
|
||||||
|
private readonly DEFAULT_MAX_ITEMS_LIMIT = 300
|
||||||
|
|
||||||
|
override async load(): Promise<Container> {
|
||||||
|
const container = await super.load()
|
||||||
|
|
||||||
|
const env: Env = container.get(TYPES.Env)
|
||||||
|
|
||||||
|
// Middleware
|
||||||
|
container.bind<AuthMiddleware>(TYPES.AuthMiddleware).toDynamicValue((context: interfaces.Context) => {
|
||||||
|
return new AuthMiddleware(context.container.get(TYPES.AUTH_JWT_SECRET), context.container.get(TYPES.Logger))
|
||||||
|
})
|
||||||
|
|
||||||
|
// Projectors
|
||||||
|
container
|
||||||
|
.bind<ProjectorInterface<Item, SavedItemProjection>>(TYPES.SavedItemProjector)
|
||||||
|
.toDynamicValue((context: interfaces.Context) => {
|
||||||
|
return new SavedItemProjector(context.container.get(TYPES.Timer))
|
||||||
|
})
|
||||||
|
container
|
||||||
|
.bind<ProjectorInterface<ItemConflict, ItemConflictProjection>>(TYPES.ItemConflictProjector)
|
||||||
|
.toDynamicValue((context: interfaces.Context) => {
|
||||||
|
return new ItemConflictProjector(context.container.get(TYPES.ItemProjector))
|
||||||
|
})
|
||||||
|
|
||||||
|
// env vars
|
||||||
|
container.bind(TYPES.AUTH_JWT_SECRET).toConstantValue(env.get('AUTH_JWT_SECRET'))
|
||||||
|
container.bind(TYPES.REVISIONS_FREQUENCY).toConstantValue(env.get('REVISIONS_FREQUENCY'))
|
||||||
|
container.bind(TYPES.NEW_RELIC_ENABLED).toConstantValue(env.get('NEW_RELIC_ENABLED', true))
|
||||||
|
container.bind(TYPES.VERSION).toConstantValue(env.get('VERSION'))
|
||||||
|
container
|
||||||
|
.bind(TYPES.CONTENT_SIZE_TRANSFER_LIMIT)
|
||||||
|
.toConstantValue(
|
||||||
|
env.get('CONTENT_SIZE_TRANSFER_LIMIT', true)
|
||||||
|
? +env.get('CONTENT_SIZE_TRANSFER_LIMIT', true)
|
||||||
|
: this.DEFAULT_CONTENT_SIZE_TRANSFER_LIMIT,
|
||||||
|
)
|
||||||
|
container
|
||||||
|
.bind(TYPES.MAX_ITEMS_LIMIT)
|
||||||
|
.toConstantValue(
|
||||||
|
env.get('MAX_ITEMS_LIMIT', true) ? +env.get('MAX_ITEMS_LIMIT', true) : this.DEFAULT_MAX_ITEMS_LIMIT,
|
||||||
|
)
|
||||||
|
|
||||||
|
// use cases
|
||||||
|
container.bind<SyncItems>(TYPES.SyncItems).toDynamicValue((context: interfaces.Context) => {
|
||||||
|
return new SyncItems(context.container.get(TYPES.ItemService))
|
||||||
|
})
|
||||||
|
container.bind<CheckIntegrity>(TYPES.CheckIntegrity).toDynamicValue((context: interfaces.Context) => {
|
||||||
|
return new CheckIntegrity(context.container.get(TYPES.ItemRepository))
|
||||||
|
})
|
||||||
|
container.bind<GetItem>(TYPES.GetItem).toDynamicValue((context: interfaces.Context) => {
|
||||||
|
return new GetItem(context.container.get(TYPES.ItemRepository))
|
||||||
|
})
|
||||||
|
|
||||||
|
// Services
|
||||||
|
container.bind<ItemServiceInterface>(TYPES.ItemService).toDynamicValue((context: interfaces.Context) => {
|
||||||
|
return new ItemService(
|
||||||
|
context.container.get(TYPES.ItemSaveValidator),
|
||||||
|
context.container.get(TYPES.ItemFactory),
|
||||||
|
context.container.get(TYPES.ItemRepository),
|
||||||
|
context.container.get(TYPES.DomainEventPublisher),
|
||||||
|
context.container.get(TYPES.DomainEventFactory),
|
||||||
|
context.container.get(TYPES.REVISIONS_FREQUENCY),
|
||||||
|
context.container.get(TYPES.CONTENT_SIZE_TRANSFER_LIMIT),
|
||||||
|
context.container.get(TYPES.ItemTransferCalculator),
|
||||||
|
context.container.get(TYPES.Timer),
|
||||||
|
context.container.get(TYPES.ItemProjector),
|
||||||
|
context.container.get(TYPES.MAX_ITEMS_LIMIT),
|
||||||
|
context.container.get(TYPES.Logger),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
container
|
||||||
|
.bind<SyncResponseFactory20161215>(TYPES.SyncResponseFactory20161215)
|
||||||
|
.toDynamicValue((context: interfaces.Context) => {
|
||||||
|
return new SyncResponseFactory20161215(context.container.get(TYPES.ItemProjector))
|
||||||
|
})
|
||||||
|
container
|
||||||
|
.bind<SyncResponseFactory20200115>(TYPES.SyncResponseFactory20200115)
|
||||||
|
.toDynamicValue((context: interfaces.Context) => {
|
||||||
|
return new SyncResponseFactory20200115(
|
||||||
|
context.container.get(TYPES.ItemProjector),
|
||||||
|
context.container.get(TYPES.ItemConflictProjector),
|
||||||
|
context.container.get(TYPES.SavedItemProjector),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
container
|
||||||
|
.bind<SyncResponseFactoryResolverInterface>(TYPES.SyncResponseFactoryResolver)
|
||||||
|
.toDynamicValue((context: interfaces.Context) => {
|
||||||
|
return new SyncResponseFactoryResolver(
|
||||||
|
context.container.get(TYPES.SyncResponseFactory20161215),
|
||||||
|
context.container.get(TYPES.SyncResponseFactory20200115),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
container.bind<ItemFactoryInterface>(TYPES.ItemFactory).toDynamicValue((context: interfaces.Context) => {
|
||||||
|
return new ItemFactory(context.container.get(TYPES.Timer), context.container.get(TYPES.ItemProjector))
|
||||||
|
})
|
||||||
|
|
||||||
|
container.bind<OwnershipFilter>(TYPES.OwnershipFilter).toDynamicValue(() => new OwnershipFilter())
|
||||||
|
container
|
||||||
|
.bind<TimeDifferenceFilter>(TYPES.TimeDifferenceFilter)
|
||||||
|
.toDynamicValue((context: interfaces.Context) => new TimeDifferenceFilter(context.container.get(TYPES.Timer)))
|
||||||
|
container.bind<UuidFilter>(TYPES.UuidFilter).toDynamicValue(() => new UuidFilter())
|
||||||
|
container.bind<ContentTypeFilter>(TYPES.ContentTypeFilter).toDynamicValue(() => new ContentTypeFilter())
|
||||||
|
container.bind<ContentFilter>(TYPES.ContentFilter).toDynamicValue(() => new ContentFilter())
|
||||||
|
|
||||||
|
container
|
||||||
|
.bind<ItemSaveValidatorInterface>(TYPES.ItemSaveValidator)
|
||||||
|
.toDynamicValue((context: interfaces.Context) => {
|
||||||
|
return new ItemSaveValidator([
|
||||||
|
context.container.get(TYPES.OwnershipFilter),
|
||||||
|
context.container.get(TYPES.TimeDifferenceFilter),
|
||||||
|
context.container.get(TYPES.UuidFilter),
|
||||||
|
context.container.get(TYPES.ContentTypeFilter),
|
||||||
|
context.container.get(TYPES.ContentFilter),
|
||||||
|
])
|
||||||
|
})
|
||||||
|
|
||||||
|
return container
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,16 +5,14 @@ const TYPES = {
|
|||||||
SNS: Symbol.for('SNS'),
|
SNS: Symbol.for('SNS'),
|
||||||
SQS: Symbol.for('SQS'),
|
SQS: Symbol.for('SQS'),
|
||||||
S3: Symbol.for('S3'),
|
S3: Symbol.for('S3'),
|
||||||
|
Env: Symbol.for('Env'),
|
||||||
// Repositories
|
// Repositories
|
||||||
RevisionRepository: Symbol.for('RevisionRepository'),
|
|
||||||
ItemRepository: Symbol.for('ItemRepository'),
|
ItemRepository: Symbol.for('ItemRepository'),
|
||||||
// ORM
|
// ORM
|
||||||
ORMRevisionRepository: Symbol.for('ORMRevisionRepository'),
|
|
||||||
ORMItemRepository: Symbol.for('ORMItemRepository'),
|
ORMItemRepository: Symbol.for('ORMItemRepository'),
|
||||||
// Middleware
|
// Middleware
|
||||||
AuthMiddleware: Symbol.for('AuthMiddleware'),
|
AuthMiddleware: Symbol.for('AuthMiddleware'),
|
||||||
// Projectors
|
// Projectors
|
||||||
RevisionProjector: Symbol.for('RevisionProjector'),
|
|
||||||
ItemProjector: Symbol.for('ItemProjector'),
|
ItemProjector: Symbol.for('ItemProjector'),
|
||||||
SavedItemProjector: Symbol.for('SavedItemProjector'),
|
SavedItemProjector: Symbol.for('SavedItemProjector'),
|
||||||
ItemConflictProjector: Symbol.for('ItemConflictProjector'),
|
ItemConflictProjector: Symbol.for('ItemConflictProjector'),
|
||||||
@@ -25,7 +23,6 @@ const TYPES = {
|
|||||||
SQS_QUEUE_URL: Symbol.for('SQS_QUEUE_URL'),
|
SQS_QUEUE_URL: Symbol.for('SQS_QUEUE_URL'),
|
||||||
SQS_AWS_REGION: Symbol.for('SQS_AWS_REGION'),
|
SQS_AWS_REGION: Symbol.for('SQS_AWS_REGION'),
|
||||||
AUTH_JWT_SECRET: Symbol.for('AUTH_JWT_SECRET'),
|
AUTH_JWT_SECRET: Symbol.for('AUTH_JWT_SECRET'),
|
||||||
INTERNAL_DNS_REROUTE_ENABLED: Symbol.for('INTERNAL_DNS_REROUTE_ENABLED'),
|
|
||||||
EXTENSIONS_SERVER_URL: Symbol.for('EXTENSIONS_SERVER_URL'),
|
EXTENSIONS_SERVER_URL: Symbol.for('EXTENSIONS_SERVER_URL'),
|
||||||
AUTH_SERVER_URL: Symbol.for('AUTH_SERVER_URL'),
|
AUTH_SERVER_URL: Symbol.for('AUTH_SERVER_URL'),
|
||||||
S3_AWS_REGION: Symbol.for('S3_AWS_REGION'),
|
S3_AWS_REGION: Symbol.for('S3_AWS_REGION'),
|
||||||
@@ -46,10 +43,7 @@ const TYPES = {
|
|||||||
DuplicateItemSyncedEventHandler: Symbol.for('DuplicateItemSyncedEventHandler'),
|
DuplicateItemSyncedEventHandler: Symbol.for('DuplicateItemSyncedEventHandler'),
|
||||||
EmailBackupRequestedEventHandler: Symbol.for('EmailBackupRequestedEventHandler'),
|
EmailBackupRequestedEventHandler: Symbol.for('EmailBackupRequestedEventHandler'),
|
||||||
CloudBackupRequestedEventHandler: Symbol.for('CloudBackupRequestedEventHandler'),
|
CloudBackupRequestedEventHandler: Symbol.for('CloudBackupRequestedEventHandler'),
|
||||||
UserContentSizeRecalculationRequestedEventHandler: Symbol.for('UserContentSizeRecalculationRequestedEventHandler'),
|
|
||||||
ItemRevisionCreationRequestedEventHandler: Symbol.for('ItemRevisionCreationRequestedEventHandler'),
|
ItemRevisionCreationRequestedEventHandler: Symbol.for('ItemRevisionCreationRequestedEventHandler'),
|
||||||
// Map
|
|
||||||
RevisionMetadataMap: Symbol.for('RevisionMetadataMap'),
|
|
||||||
// Services
|
// Services
|
||||||
ContentDecoder: Symbol.for('ContentDecoder'),
|
ContentDecoder: Symbol.for('ContentDecoder'),
|
||||||
DomainEventPublisher: Symbol.for('DomainEventPublisher'),
|
DomainEventPublisher: Symbol.for('DomainEventPublisher'),
|
||||||
@@ -65,7 +59,6 @@ const TYPES = {
|
|||||||
AuthHttpService: Symbol.for('AuthHttpService'),
|
AuthHttpService: Symbol.for('AuthHttpService'),
|
||||||
ExtensionsHttpService: Symbol.for('ExtensionsHttpService'),
|
ExtensionsHttpService: Symbol.for('ExtensionsHttpService'),
|
||||||
ItemBackupService: Symbol.for('ItemBackupService'),
|
ItemBackupService: Symbol.for('ItemBackupService'),
|
||||||
RevisionService: Symbol.for('RevisionService'),
|
|
||||||
ItemSaveValidator: Symbol.for('ItemSaveValidator'),
|
ItemSaveValidator: Symbol.for('ItemSaveValidator'),
|
||||||
OwnershipFilter: Symbol.for('OwnershipFilter'),
|
OwnershipFilter: Symbol.for('OwnershipFilter'),
|
||||||
TimeDifferenceFilter: Symbol.for('TimeDifferenceFilter'),
|
TimeDifferenceFilter: Symbol.for('TimeDifferenceFilter'),
|
||||||
|
|||||||
@@ -0,0 +1,221 @@
|
|||||||
|
import { SQSClient, SQSClientConfig } from '@aws-sdk/client-sqs'
|
||||||
|
import { S3Client } from '@aws-sdk/client-s3'
|
||||||
|
import { Container, interfaces } from 'inversify'
|
||||||
|
import {
|
||||||
|
DomainEventHandlerInterface,
|
||||||
|
DomainEventMessageHandlerInterface,
|
||||||
|
DomainEventSubscriberFactoryInterface,
|
||||||
|
} from '@standardnotes/domain-events'
|
||||||
|
|
||||||
|
import { Env } from './Env'
|
||||||
|
import TYPES from './Types'
|
||||||
|
import { ContentDecoder } from '../Domain/Item/ContentDecoder'
|
||||||
|
import { AuthHttpServiceInterface } from '../Domain/Auth/AuthHttpServiceInterface'
|
||||||
|
import { AuthHttpService } from '../Infra/HTTP/AuthHttpService'
|
||||||
|
import { ExtensionsHttpServiceInterface } from '../Domain/Extension/ExtensionsHttpServiceInterface'
|
||||||
|
import { ExtensionsHttpService } from '../Domain/Extension/ExtensionsHttpService'
|
||||||
|
import { ItemBackupServiceInterface } from '../Domain/Item/ItemBackupServiceInterface'
|
||||||
|
import { S3ItemBackupService } from '../Infra/S3/S3ItemBackupService'
|
||||||
|
import { DuplicateItemSyncedEventHandler } from '../Domain/Handler/DuplicateItemSyncedEventHandler'
|
||||||
|
import { AccountDeletionRequestedEventHandler } from '../Domain/Handler/AccountDeletionRequestedEventHandler'
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||||
|
const axios = require('axios')
|
||||||
|
import { AxiosInstance } from 'axios'
|
||||||
|
import {
|
||||||
|
SQSDomainEventSubscriberFactory,
|
||||||
|
SQSEventMessageHandler,
|
||||||
|
SQSNewRelicEventMessageHandler,
|
||||||
|
} from '@standardnotes/domain-events-infra'
|
||||||
|
import { EmailBackupRequestedEventHandler } from '../Domain/Handler/EmailBackupRequestedEventHandler'
|
||||||
|
import { CloudBackupRequestedEventHandler } from '../Domain/Handler/CloudBackupRequestedEventHandler'
|
||||||
|
import { ItemRevisionCreationRequestedEventHandler } from '../Domain/Handler/ItemRevisionCreationRequestedEventHandler'
|
||||||
|
import { FSItemBackupService } from '../Infra/FS/FSItemBackupService'
|
||||||
|
import { CommonContainerConfigLoader } from './CommonContainerConfigLoader'
|
||||||
|
|
||||||
|
export class WorkerContainerConfigLoader extends CommonContainerConfigLoader {
|
||||||
|
private readonly DEFAULT_FILE_UPLOAD_PATH = `${__dirname}/../../uploads`
|
||||||
|
|
||||||
|
override async load(): Promise<Container> {
|
||||||
|
const container = await super.load()
|
||||||
|
|
||||||
|
const env: Env = container.get(TYPES.Env)
|
||||||
|
|
||||||
|
container.bind<SQSClient>(TYPES.SQS).toDynamicValue((context: interfaces.Context) => {
|
||||||
|
const env: Env = context.container.get(TYPES.Env)
|
||||||
|
|
||||||
|
const sqsConfig: SQSClientConfig = {
|
||||||
|
region: env.get('SQS_AWS_REGION'),
|
||||||
|
}
|
||||||
|
if (env.get('SQS_ENDPOINT', true)) {
|
||||||
|
sqsConfig.endpoint = env.get('SQS_ENDPOINT', true)
|
||||||
|
}
|
||||||
|
if (env.get('SQS_ACCESS_KEY_ID', true) && env.get('SQS_SECRET_ACCESS_KEY', true)) {
|
||||||
|
sqsConfig.credentials = {
|
||||||
|
accessKeyId: env.get('SQS_ACCESS_KEY_ID', true),
|
||||||
|
secretAccessKey: env.get('SQS_SECRET_ACCESS_KEY', true),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new SQSClient(sqsConfig)
|
||||||
|
})
|
||||||
|
|
||||||
|
container.bind<S3Client | undefined>(TYPES.S3).toDynamicValue((context: interfaces.Context) => {
|
||||||
|
const env: Env = context.container.get(TYPES.Env)
|
||||||
|
|
||||||
|
let s3Client = undefined
|
||||||
|
if (env.get('S3_AWS_REGION', true)) {
|
||||||
|
s3Client = new S3Client({
|
||||||
|
apiVersion: 'latest',
|
||||||
|
region: env.get('S3_AWS_REGION', true),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return s3Client
|
||||||
|
})
|
||||||
|
|
||||||
|
// env vars
|
||||||
|
container.bind(TYPES.SQS_QUEUE_URL).toConstantValue(env.get('SQS_QUEUE_URL'))
|
||||||
|
container.bind(TYPES.EXTENSIONS_SERVER_URL).toConstantValue(env.get('EXTENSIONS_SERVER_URL', true))
|
||||||
|
container.bind(TYPES.AUTH_SERVER_URL).toConstantValue(env.get('AUTH_SERVER_URL'))
|
||||||
|
container.bind(TYPES.S3_AWS_REGION).toConstantValue(env.get('S3_AWS_REGION', true))
|
||||||
|
container.bind(TYPES.S3_BACKUP_BUCKET_NAME).toConstantValue(env.get('S3_BACKUP_BUCKET_NAME', true))
|
||||||
|
container.bind(TYPES.EMAIL_ATTACHMENT_MAX_BYTE_SIZE).toConstantValue(env.get('EMAIL_ATTACHMENT_MAX_BYTE_SIZE'))
|
||||||
|
container.bind(TYPES.NEW_RELIC_ENABLED).toConstantValue(env.get('NEW_RELIC_ENABLED', true))
|
||||||
|
container.bind(TYPES.VERSION).toConstantValue(env.get('VERSION'))
|
||||||
|
container
|
||||||
|
.bind(TYPES.FILE_UPLOAD_PATH)
|
||||||
|
.toConstantValue(
|
||||||
|
env.get('FILE_UPLOAD_PATH', true) ? env.get('FILE_UPLOAD_PATH', true) : this.DEFAULT_FILE_UPLOAD_PATH,
|
||||||
|
)
|
||||||
|
|
||||||
|
// Handlers
|
||||||
|
container
|
||||||
|
.bind<DuplicateItemSyncedEventHandler>(TYPES.DuplicateItemSyncedEventHandler)
|
||||||
|
.toDynamicValue((context: interfaces.Context) => {
|
||||||
|
return new DuplicateItemSyncedEventHandler(
|
||||||
|
context.container.get(TYPES.ItemRepository),
|
||||||
|
context.container.get(TYPES.DomainEventFactory),
|
||||||
|
context.container.get(TYPES.DomainEventPublisher),
|
||||||
|
context.container.get(TYPES.Logger),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
container
|
||||||
|
.bind<AccountDeletionRequestedEventHandler>(TYPES.AccountDeletionRequestedEventHandler)
|
||||||
|
.toDynamicValue((context: interfaces.Context) => {
|
||||||
|
return new AccountDeletionRequestedEventHandler(
|
||||||
|
context.container.get(TYPES.ItemRepository),
|
||||||
|
context.container.get(TYPES.Logger),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
container
|
||||||
|
.bind<EmailBackupRequestedEventHandler>(TYPES.EmailBackupRequestedEventHandler)
|
||||||
|
.toDynamicValue((context: interfaces.Context) => {
|
||||||
|
return new EmailBackupRequestedEventHandler(
|
||||||
|
context.container.get(TYPES.ItemRepository),
|
||||||
|
context.container.get(TYPES.AuthHttpService),
|
||||||
|
context.container.get(TYPES.ItemBackupService),
|
||||||
|
context.container.get(TYPES.DomainEventPublisher),
|
||||||
|
context.container.get(TYPES.DomainEventFactory),
|
||||||
|
context.container.get(TYPES.EMAIL_ATTACHMENT_MAX_BYTE_SIZE),
|
||||||
|
context.container.get(TYPES.ItemTransferCalculator),
|
||||||
|
context.container.get(TYPES.S3_BACKUP_BUCKET_NAME),
|
||||||
|
context.container.get(TYPES.Logger),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
container
|
||||||
|
.bind<CloudBackupRequestedEventHandler>(TYPES.CloudBackupRequestedEventHandler)
|
||||||
|
.toDynamicValue((context: interfaces.Context) => {
|
||||||
|
return new CloudBackupRequestedEventHandler(
|
||||||
|
context.container.get(TYPES.ItemRepository),
|
||||||
|
context.container.get(TYPES.AuthHttpService),
|
||||||
|
context.container.get(TYPES.ExtensionsHttpService),
|
||||||
|
context.container.get(TYPES.ItemBackupService),
|
||||||
|
context.container.get(TYPES.EXTENSIONS_SERVER_URL),
|
||||||
|
context.container.get(TYPES.Logger),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
container
|
||||||
|
.bind<ItemRevisionCreationRequestedEventHandler>(TYPES.ItemRevisionCreationRequestedEventHandler)
|
||||||
|
.toDynamicValue((context: interfaces.Context) => {
|
||||||
|
return new ItemRevisionCreationRequestedEventHandler(
|
||||||
|
context.container.get(TYPES.ItemRepository),
|
||||||
|
context.container.get(TYPES.ItemBackupService),
|
||||||
|
context.container.get(TYPES.DomainEventFactory),
|
||||||
|
context.container.get(TYPES.DomainEventPublisher),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
// Services
|
||||||
|
container.bind<ContentDecoder>(TYPES.ContentDecoder).toDynamicValue(() => new ContentDecoder())
|
||||||
|
container.bind<AxiosInstance>(TYPES.HTTPClient).toDynamicValue(() => axios.create())
|
||||||
|
container.bind<AuthHttpServiceInterface>(TYPES.AuthHttpService).toDynamicValue((context: interfaces.Context) => {
|
||||||
|
return new AuthHttpService(context.container.get(TYPES.HTTPClient), context.container.get(TYPES.AUTH_SERVER_URL))
|
||||||
|
})
|
||||||
|
container
|
||||||
|
.bind<ExtensionsHttpServiceInterface>(TYPES.ExtensionsHttpService)
|
||||||
|
.toDynamicValue((context: interfaces.Context) => {
|
||||||
|
return new ExtensionsHttpService(
|
||||||
|
context.container.get(TYPES.HTTPClient),
|
||||||
|
context.container.get(TYPES.ItemRepository),
|
||||||
|
context.container.get(TYPES.ContentDecoder),
|
||||||
|
context.container.get(TYPES.DomainEventPublisher),
|
||||||
|
context.container.get(TYPES.DomainEventFactory),
|
||||||
|
context.container.get(TYPES.Logger),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
container
|
||||||
|
.bind<ItemBackupServiceInterface>(TYPES.ItemBackupService)
|
||||||
|
.toDynamicValue((context: interfaces.Context) => {
|
||||||
|
const env: Env = context.container.get(TYPES.Env)
|
||||||
|
|
||||||
|
if (env.get('S3_AWS_REGION', true)) {
|
||||||
|
return new S3ItemBackupService(
|
||||||
|
context.container.get(TYPES.S3_BACKUP_BUCKET_NAME),
|
||||||
|
context.container.get(TYPES.ItemProjector),
|
||||||
|
context.container.get(TYPES.Logger),
|
||||||
|
context.container.get(TYPES.S3),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
return new FSItemBackupService(
|
||||||
|
context.container.get(TYPES.FILE_UPLOAD_PATH),
|
||||||
|
context.container.get(TYPES.ItemProjector),
|
||||||
|
context.container.get(TYPES.Logger),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
container
|
||||||
|
.bind<DomainEventMessageHandlerInterface>(TYPES.DomainEventMessageHandler)
|
||||||
|
.toDynamicValue((context: interfaces.Context) => {
|
||||||
|
const env: Env = context.container.get(TYPES.Env)
|
||||||
|
|
||||||
|
const eventHandlers: Map<string, DomainEventHandlerInterface> = new Map([
|
||||||
|
['DUPLICATE_ITEM_SYNCED', context.container.get(TYPES.DuplicateItemSyncedEventHandler)],
|
||||||
|
['ACCOUNT_DELETION_REQUESTED', context.container.get(TYPES.AccountDeletionRequestedEventHandler)],
|
||||||
|
['EMAIL_BACKUP_REQUESTED', context.container.get(TYPES.EmailBackupRequestedEventHandler)],
|
||||||
|
['CLOUD_BACKUP_REQUESTED', context.container.get(TYPES.CloudBackupRequestedEventHandler)],
|
||||||
|
['ITEM_REVISION_CREATION_REQUESTED', context.container.get(TYPES.ItemRevisionCreationRequestedEventHandler)],
|
||||||
|
])
|
||||||
|
|
||||||
|
const handler =
|
||||||
|
env.get('NEW_RELIC_ENABLED', true) === 'true'
|
||||||
|
? new SQSNewRelicEventMessageHandler(eventHandlers, context.container.get(TYPES.Logger))
|
||||||
|
: new SQSEventMessageHandler(eventHandlers, context.container.get(TYPES.Logger))
|
||||||
|
|
||||||
|
return handler
|
||||||
|
})
|
||||||
|
|
||||||
|
container
|
||||||
|
.bind<DomainEventSubscriberFactoryInterface>(TYPES.DomainEventSubscriberFactory)
|
||||||
|
.toDynamicValue((context: interfaces.Context) => {
|
||||||
|
return new SQSDomainEventSubscriberFactory(
|
||||||
|
context.container.get(TYPES.SQS),
|
||||||
|
context.container.get(TYPES.SQS_QUEUE_URL),
|
||||||
|
context.container.get(TYPES.DomainEventMessageHandler),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
return container
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,19 +1,12 @@
|
|||||||
import { NextFunction, Request, Response } from 'express'
|
import { NextFunction, Request, Response } from 'express'
|
||||||
import { inject, injectable } from 'inversify'
|
|
||||||
import { BaseMiddleware } from 'inversify-express-utils'
|
import { BaseMiddleware } from 'inversify-express-utils'
|
||||||
import { verify } from 'jsonwebtoken'
|
import { verify } from 'jsonwebtoken'
|
||||||
import { CrossServiceTokenData } from '@standardnotes/security'
|
import { CrossServiceTokenData } from '@standardnotes/security'
|
||||||
import * as winston from 'winston'
|
import * as winston from 'winston'
|
||||||
import { RoleName } from '@standardnotes/domain-core'
|
import { RoleName } from '@standardnotes/domain-core'
|
||||||
|
|
||||||
import TYPES from '../Bootstrap/Types'
|
|
||||||
|
|
||||||
@injectable()
|
|
||||||
export class AuthMiddleware extends BaseMiddleware {
|
export class AuthMiddleware extends BaseMiddleware {
|
||||||
constructor(
|
constructor(private authJWTSecret: string, private logger: winston.Logger) {
|
||||||
@inject(TYPES.AUTH_JWT_SECRET) private authJWTSecret: string,
|
|
||||||
@inject(TYPES.Logger) private logger: winston.Logger,
|
|
||||||
) {
|
|
||||||
super()
|
super()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,99 +0,0 @@
|
|||||||
import 'reflect-metadata'
|
|
||||||
|
|
||||||
import { Revision } from '../Domain/Revision/Revision'
|
|
||||||
import * as express from 'express'
|
|
||||||
|
|
||||||
import { RevisionsController } from './RevisionsController'
|
|
||||||
import { results } from 'inversify-express-utils'
|
|
||||||
import { ProjectorInterface } from '../Projection/ProjectorInterface'
|
|
||||||
import { RevisionServiceInterface } from '../Domain/Revision/RevisionServiceInterface'
|
|
||||||
import { RevisionProjection } from '../Projection/RevisionProjection'
|
|
||||||
import { MapperInterface } from '@standardnotes/domain-core'
|
|
||||||
import { RevisionMetadata } from '../Domain/Revision/RevisionMetadata'
|
|
||||||
import { SimpleRevisionProjection } from '../Projection/SimpleRevisionProjection'
|
|
||||||
|
|
||||||
describe('RevisionsController', () => {
|
|
||||||
let revisionProjector: ProjectorInterface<Revision, RevisionProjection>
|
|
||||||
let revisionMap: MapperInterface<RevisionMetadata, SimpleRevisionProjection>
|
|
||||||
let revisionService: RevisionServiceInterface
|
|
||||||
let revision: Revision
|
|
||||||
let revisionMetadata: RevisionMetadata
|
|
||||||
let request: express.Request
|
|
||||||
let response: express.Response
|
|
||||||
|
|
||||||
const createController = () => new RevisionsController(revisionService, revisionProjector, revisionMap)
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
revision = {} as jest.Mocked<Revision>
|
|
||||||
|
|
||||||
revisionMetadata = {} as jest.Mocked<RevisionMetadata>
|
|
||||||
|
|
||||||
revisionMap = {} as jest.Mocked<MapperInterface<RevisionMetadata, SimpleRevisionProjection>>
|
|
||||||
|
|
||||||
revisionProjector = {} as jest.Mocked<ProjectorInterface<Revision, RevisionProjection>>
|
|
||||||
|
|
||||||
revisionService = {} as jest.Mocked<RevisionServiceInterface>
|
|
||||||
revisionService.getRevisionsMetadata = jest.fn().mockReturnValue([revisionMetadata])
|
|
||||||
revisionService.getRevision = jest.fn().mockReturnValue(revision)
|
|
||||||
revisionService.removeRevision = jest.fn().mockReturnValue(true)
|
|
||||||
|
|
||||||
request = {
|
|
||||||
params: {},
|
|
||||||
} as jest.Mocked<express.Request>
|
|
||||||
|
|
||||||
response = {
|
|
||||||
locals: {},
|
|
||||||
} as jest.Mocked<express.Response>
|
|
||||||
response.locals.user = {
|
|
||||||
uuid: '123',
|
|
||||||
}
|
|
||||||
response.locals.roleNames = ['BASIC_USER']
|
|
||||||
})
|
|
||||||
|
|
||||||
it('should return revisions for an item', async () => {
|
|
||||||
revisionMap.toProjection = jest.fn().mockReturnValue({ foo: 'bar' })
|
|
||||||
|
|
||||||
const revisionResponse = await createController().getRevisions(request, response)
|
|
||||||
|
|
||||||
expect(revisionResponse.json).toEqual([{ foo: 'bar' }])
|
|
||||||
})
|
|
||||||
|
|
||||||
it('should return a specific revision for an item', async () => {
|
|
||||||
revisionProjector.projectFull = jest.fn().mockReturnValue({ foo: 'bar' })
|
|
||||||
|
|
||||||
const httpResponse = <results.JsonResult>await createController().getRevision(request, response)
|
|
||||||
|
|
||||||
expect(httpResponse.json).toEqual({ foo: 'bar' })
|
|
||||||
})
|
|
||||||
|
|
||||||
it('should remove a specific revision for an item', async () => {
|
|
||||||
const httpResponse = await createController().deleteRevision(request, response)
|
|
||||||
|
|
||||||
expect(httpResponse).toBeInstanceOf(results.OkResult)
|
|
||||||
})
|
|
||||||
|
|
||||||
it('should not remove a specific revision for an item if it fails', async () => {
|
|
||||||
revisionService.removeRevision = jest.fn().mockReturnValue(false)
|
|
||||||
|
|
||||||
const httpResponse = await createController().deleteRevision(request, response)
|
|
||||||
|
|
||||||
expect(httpResponse).toBeInstanceOf(results.BadRequestResult)
|
|
||||||
})
|
|
||||||
|
|
||||||
it('should not remove a specific revision for an item the session is read only', async () => {
|
|
||||||
response.locals.readOnlyAccess = true
|
|
||||||
|
|
||||||
const httpResponse = await createController().deleteRevision(request, response)
|
|
||||||
const result = await httpResponse.executeAsync()
|
|
||||||
|
|
||||||
expect(result.statusCode).toEqual(401)
|
|
||||||
})
|
|
||||||
|
|
||||||
it('should return a 404 for a not found specific revision in an item', async () => {
|
|
||||||
revisionService.getRevision = jest.fn().mockReturnValue(null)
|
|
||||||
|
|
||||||
const httpResponse = await createController().getRevision(request, response)
|
|
||||||
|
|
||||||
expect(httpResponse).toBeInstanceOf(results.NotFoundResult)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
@@ -1,85 +0,0 @@
|
|||||||
import { Request, Response } from 'express'
|
|
||||||
import { BaseHttpController, controller, httpDelete, httpGet, results } from 'inversify-express-utils'
|
|
||||||
import { inject } from 'inversify'
|
|
||||||
|
|
||||||
import TYPES from '../Bootstrap/Types'
|
|
||||||
import { ProjectorInterface } from '../Projection/ProjectorInterface'
|
|
||||||
import { Revision } from '../Domain/Revision/Revision'
|
|
||||||
import { RevisionServiceInterface } from '../Domain/Revision/RevisionServiceInterface'
|
|
||||||
import { ErrorTag } from '@standardnotes/api'
|
|
||||||
import { RevisionProjection } from '../Projection/RevisionProjection'
|
|
||||||
import { MapperInterface } from '@standardnotes/domain-core'
|
|
||||||
import { RevisionMetadata } from '../Domain/Revision/RevisionMetadata'
|
|
||||||
import { SimpleRevisionProjection } from '../Projection/SimpleRevisionProjection'
|
|
||||||
|
|
||||||
@controller('/items/:itemUuid/revisions', TYPES.AuthMiddleware)
|
|
||||||
export class RevisionsController extends BaseHttpController {
|
|
||||||
constructor(
|
|
||||||
@inject(TYPES.RevisionService) private revisionService: RevisionServiceInterface,
|
|
||||||
@inject(TYPES.RevisionProjector) private revisionProjector: ProjectorInterface<Revision, RevisionProjection>,
|
|
||||||
@inject(TYPES.RevisionMetadataMap)
|
|
||||||
private revisionMetadataMap: MapperInterface<RevisionMetadata, SimpleRevisionProjection>,
|
|
||||||
) {
|
|
||||||
super()
|
|
||||||
}
|
|
||||||
|
|
||||||
@httpGet('/')
|
|
||||||
public async getRevisions(req: Request, response: Response): Promise<results.JsonResult> {
|
|
||||||
const metadatas = await this.revisionService.getRevisionsMetadata(response.locals.user.uuid, req.params.itemUuid)
|
|
||||||
|
|
||||||
const metadataProjections = []
|
|
||||||
for (const metadata of metadatas) {
|
|
||||||
metadataProjections.push(this.revisionMetadataMap.toProjection(metadata))
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.json(metadataProjections)
|
|
||||||
}
|
|
||||||
|
|
||||||
@httpGet('/:uuid')
|
|
||||||
public async getRevision(request: Request, response: Response): Promise<results.JsonResult | results.NotFoundResult> {
|
|
||||||
const revision = await this.revisionService.getRevision({
|
|
||||||
userRoles: response.locals.roleNames,
|
|
||||||
userUuid: response.locals.user.uuid,
|
|
||||||
itemUuid: request.params.itemUuid,
|
|
||||||
revisionUuid: request.params.uuid,
|
|
||||||
})
|
|
||||||
|
|
||||||
if (!revision) {
|
|
||||||
return this.notFound()
|
|
||||||
}
|
|
||||||
|
|
||||||
const revisionProjection = await this.revisionProjector.projectFull(revision)
|
|
||||||
|
|
||||||
return this.json(revisionProjection)
|
|
||||||
}
|
|
||||||
|
|
||||||
@httpDelete('/:uuid')
|
|
||||||
public async deleteRevision(
|
|
||||||
request: Request,
|
|
||||||
response: Response,
|
|
||||||
): Promise<results.BadRequestResult | results.OkResult | results.JsonResult> {
|
|
||||||
if (response.locals.readOnlyAccess) {
|
|
||||||
return this.json(
|
|
||||||
{
|
|
||||||
error: {
|
|
||||||
tag: ErrorTag.ReadOnlyAccess,
|
|
||||||
message: 'Session has read-only access.',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
401,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
const success = await this.revisionService.removeRevision({
|
|
||||||
userUuid: response.locals.user.uuid,
|
|
||||||
itemUuid: request.params.itemUuid,
|
|
||||||
revisionUuid: request.params.uuid,
|
|
||||||
})
|
|
||||||
|
|
||||||
if (!success) {
|
|
||||||
return this.badRequest()
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.ok()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -6,35 +6,13 @@ import {
|
|||||||
ItemDumpedEvent,
|
ItemDumpedEvent,
|
||||||
ItemRevisionCreationRequestedEvent,
|
ItemRevisionCreationRequestedEvent,
|
||||||
RevisionsCopyRequestedEvent,
|
RevisionsCopyRequestedEvent,
|
||||||
RevisionsOwnershipUpdateRequestedEvent,
|
|
||||||
UserContentSizeRecalculationRequestedEvent,
|
UserContentSizeRecalculationRequestedEvent,
|
||||||
} from '@standardnotes/domain-events'
|
} from '@standardnotes/domain-events'
|
||||||
import { TimerInterface } from '@standardnotes/time'
|
import { TimerInterface } from '@standardnotes/time'
|
||||||
import { inject, injectable } from 'inversify'
|
|
||||||
import TYPES from '../../Bootstrap/Types'
|
|
||||||
import { DomainEventFactoryInterface } from './DomainEventFactoryInterface'
|
import { DomainEventFactoryInterface } from './DomainEventFactoryInterface'
|
||||||
|
|
||||||
@injectable()
|
|
||||||
export class DomainEventFactory implements DomainEventFactoryInterface {
|
export class DomainEventFactory implements DomainEventFactoryInterface {
|
||||||
constructor(@inject(TYPES.Timer) private timer: TimerInterface) {}
|
constructor(private timer: TimerInterface) {}
|
||||||
|
|
||||||
createRevisionsOwnershipUpdateRequestedEvent(dto: {
|
|
||||||
userUuid: string
|
|
||||||
itemUuid: string
|
|
||||||
}): RevisionsOwnershipUpdateRequestedEvent {
|
|
||||||
return {
|
|
||||||
type: 'REVISIONS_OWNERSHIP_UPDATE_REQUESTED',
|
|
||||||
createdAt: this.timer.getUTCDate(),
|
|
||||||
meta: {
|
|
||||||
correlation: {
|
|
||||||
userIdentifier: dto.userUuid,
|
|
||||||
userIdentifierType: 'uuid',
|
|
||||||
},
|
|
||||||
origin: DomainEventService.SyncingServer,
|
|
||||||
},
|
|
||||||
payload: dto,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
createRevisionsCopyRequestedEvent(
|
createRevisionsCopyRequestedEvent(
|
||||||
userUuid: string,
|
userUuid: string,
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import {
|
|||||||
ItemDumpedEvent,
|
ItemDumpedEvent,
|
||||||
ItemRevisionCreationRequestedEvent,
|
ItemRevisionCreationRequestedEvent,
|
||||||
RevisionsCopyRequestedEvent,
|
RevisionsCopyRequestedEvent,
|
||||||
RevisionsOwnershipUpdateRequestedEvent,
|
|
||||||
UserContentSizeRecalculationRequestedEvent,
|
UserContentSizeRecalculationRequestedEvent,
|
||||||
} from '@standardnotes/domain-events'
|
} from '@standardnotes/domain-events'
|
||||||
|
|
||||||
@@ -31,8 +30,4 @@ export interface DomainEventFactoryInterface {
|
|||||||
userUuid: string,
|
userUuid: string,
|
||||||
dto: { originalItemUuid: string; newItemUuid: string },
|
dto: { originalItemUuid: string; newItemUuid: string },
|
||||||
): RevisionsCopyRequestedEvent
|
): RevisionsCopyRequestedEvent
|
||||||
createRevisionsOwnershipUpdateRequestedEvent(dto: {
|
|
||||||
userUuid: string
|
|
||||||
itemUuid: string
|
|
||||||
}): RevisionsOwnershipUpdateRequestedEvent
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,9 +2,8 @@ import { KeyParamsData } from '@standardnotes/responses'
|
|||||||
import { DomainEventInterface, DomainEventPublisherInterface } from '@standardnotes/domain-events'
|
import { DomainEventInterface, DomainEventPublisherInterface } from '@standardnotes/domain-events'
|
||||||
import { EmailLevel } from '@standardnotes/domain-core'
|
import { EmailLevel } from '@standardnotes/domain-core'
|
||||||
import { AxiosInstance } from 'axios'
|
import { AxiosInstance } from 'axios'
|
||||||
import { inject, injectable } from 'inversify'
|
|
||||||
import { Logger } from 'winston'
|
import { Logger } from 'winston'
|
||||||
import TYPES from '../../Bootstrap/Types'
|
|
||||||
import { DomainEventFactoryInterface } from '../Event/DomainEventFactoryInterface'
|
import { DomainEventFactoryInterface } from '../Event/DomainEventFactoryInterface'
|
||||||
import { ContentDecoderInterface } from '../Item/ContentDecoderInterface'
|
import { ContentDecoderInterface } from '../Item/ContentDecoderInterface'
|
||||||
import { ItemRepositoryInterface } from '../Item/ItemRepositoryInterface'
|
import { ItemRepositoryInterface } from '../Item/ItemRepositoryInterface'
|
||||||
@@ -15,15 +14,14 @@ import { getBody as googleDriveBody, getSubject as googleDriveSubject } from '..
|
|||||||
import { getBody as dropboxBody, getSubject as dropboxSubject } from '../Email/DropboxBackupFailed'
|
import { getBody as dropboxBody, getSubject as dropboxSubject } from '../Email/DropboxBackupFailed'
|
||||||
import { getBody as oneDriveBody, getSubject as oneDriveSubject } from '../Email/OneDriveBackupFailed'
|
import { getBody as oneDriveBody, getSubject as oneDriveSubject } from '../Email/OneDriveBackupFailed'
|
||||||
|
|
||||||
@injectable()
|
|
||||||
export class ExtensionsHttpService implements ExtensionsHttpServiceInterface {
|
export class ExtensionsHttpService implements ExtensionsHttpServiceInterface {
|
||||||
constructor(
|
constructor(
|
||||||
@inject(TYPES.HTTPClient) private httpClient: AxiosInstance,
|
private httpClient: AxiosInstance,
|
||||||
@inject(TYPES.ItemRepository) private itemRepository: ItemRepositoryInterface,
|
private itemRepository: ItemRepositoryInterface,
|
||||||
@inject(TYPES.ContentDecoder) private contentDecoder: ContentDecoderInterface,
|
private contentDecoder: ContentDecoderInterface,
|
||||||
@inject(TYPES.DomainEventPublisher) private domainEventPublisher: DomainEventPublisherInterface,
|
private domainEventPublisher: DomainEventPublisherInterface,
|
||||||
@inject(TYPES.DomainEventFactory) private domainEventFactory: DomainEventFactoryInterface,
|
private domainEventFactory: DomainEventFactoryInterface,
|
||||||
@inject(TYPES.Logger) private logger: Logger,
|
private logger: Logger,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async triggerCloudBackupOnExtensionsServer(dto: {
|
async triggerCloudBackupOnExtensionsServer(dto: {
|
||||||
|
|||||||
+1
-1
@@ -36,7 +36,7 @@ describe('AccountDeletionRequestedEventHandler', () => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should remove all items and revision for a user', async () => {
|
it('should remove all items for a user', async () => {
|
||||||
await createHandler().handle(event)
|
await createHandler().handle(event)
|
||||||
|
|
||||||
expect(itemRepository.deleteByUserUuid).toHaveBeenCalledWith('2-3-4')
|
expect(itemRepository.deleteByUserUuid).toHaveBeenCalledWith('2-3-4')
|
||||||
|
|||||||
@@ -1,15 +1,9 @@
|
|||||||
import { AccountDeletionRequestedEvent, DomainEventHandlerInterface } from '@standardnotes/domain-events'
|
import { AccountDeletionRequestedEvent, DomainEventHandlerInterface } from '@standardnotes/domain-events'
|
||||||
import { inject, injectable } from 'inversify'
|
|
||||||
import { Logger } from 'winston'
|
import { Logger } from 'winston'
|
||||||
import TYPES from '../../Bootstrap/Types'
|
|
||||||
import { ItemRepositoryInterface } from '../Item/ItemRepositoryInterface'
|
import { ItemRepositoryInterface } from '../Item/ItemRepositoryInterface'
|
||||||
|
|
||||||
@injectable()
|
|
||||||
export class AccountDeletionRequestedEventHandler implements DomainEventHandlerInterface {
|
export class AccountDeletionRequestedEventHandler implements DomainEventHandlerInterface {
|
||||||
constructor(
|
constructor(private itemRepository: ItemRepositoryInterface, private logger: Logger) {}
|
||||||
@inject(TYPES.ItemRepository) private itemRepository: ItemRepositoryInterface,
|
|
||||||
@inject(TYPES.Logger) private logger: Logger,
|
|
||||||
) {}
|
|
||||||
|
|
||||||
async handle(event: AccountDeletionRequestedEvent): Promise<void> {
|
async handle(event: AccountDeletionRequestedEvent): Promise<void> {
|
||||||
await this.itemRepository.deleteByUserUuid(event.payload.userUuid)
|
await this.itemRepository.deleteByUserUuid(event.payload.userUuid)
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
import { DomainEventHandlerInterface, CloudBackupRequestedEvent } from '@standardnotes/domain-events'
|
import { DomainEventHandlerInterface, CloudBackupRequestedEvent } from '@standardnotes/domain-events'
|
||||||
import { inject, injectable } from 'inversify'
|
|
||||||
|
|
||||||
import TYPES from '../../Bootstrap/Types'
|
|
||||||
import { ItemRepositoryInterface } from '../Item/ItemRepositoryInterface'
|
import { ItemRepositoryInterface } from '../Item/ItemRepositoryInterface'
|
||||||
import { ItemQuery } from '../Item/ItemQuery'
|
import { ItemQuery } from '../Item/ItemQuery'
|
||||||
import { AuthHttpServiceInterface } from '../Auth/AuthHttpServiceInterface'
|
import { AuthHttpServiceInterface } from '../Auth/AuthHttpServiceInterface'
|
||||||
@@ -11,15 +9,14 @@ import { ItemBackupServiceInterface } from '../Item/ItemBackupServiceInterface'
|
|||||||
import { Logger } from 'winston'
|
import { Logger } from 'winston'
|
||||||
import { KeyParamsData } from '@standardnotes/responses'
|
import { KeyParamsData } from '@standardnotes/responses'
|
||||||
|
|
||||||
@injectable()
|
|
||||||
export class CloudBackupRequestedEventHandler implements DomainEventHandlerInterface {
|
export class CloudBackupRequestedEventHandler implements DomainEventHandlerInterface {
|
||||||
constructor(
|
constructor(
|
||||||
@inject(TYPES.ItemRepository) private itemRepository: ItemRepositoryInterface,
|
private itemRepository: ItemRepositoryInterface,
|
||||||
@inject(TYPES.AuthHttpService) private authHttpService: AuthHttpServiceInterface,
|
private authHttpService: AuthHttpServiceInterface,
|
||||||
@inject(TYPES.ExtensionsHttpService) private extensionsHttpService: ExtensionsHttpServiceInterface,
|
private extensionsHttpService: ExtensionsHttpServiceInterface,
|
||||||
@inject(TYPES.ItemBackupService) private itemBackupService: ItemBackupServiceInterface,
|
private itemBackupService: ItemBackupServiceInterface,
|
||||||
@inject(TYPES.EXTENSIONS_SERVER_URL) private extensionsServerUrl: string,
|
private extensionsServerUrl: string,
|
||||||
@inject(TYPES.Logger) private logger: Logger,
|
private logger: Logger,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async handle(event: CloudBackupRequestedEvent): Promise<void> {
|
async handle(event: CloudBackupRequestedEvent): Promise<void> {
|
||||||
|
|||||||
@@ -3,19 +3,16 @@ import {
|
|||||||
DomainEventPublisherInterface,
|
DomainEventPublisherInterface,
|
||||||
DuplicateItemSyncedEvent,
|
DuplicateItemSyncedEvent,
|
||||||
} from '@standardnotes/domain-events'
|
} from '@standardnotes/domain-events'
|
||||||
import { inject, injectable } from 'inversify'
|
|
||||||
import { Logger } from 'winston'
|
import { Logger } from 'winston'
|
||||||
import TYPES from '../../Bootstrap/Types'
|
|
||||||
import { DomainEventFactoryInterface } from '../Event/DomainEventFactoryInterface'
|
import { DomainEventFactoryInterface } from '../Event/DomainEventFactoryInterface'
|
||||||
import { ItemRepositoryInterface } from '../Item/ItemRepositoryInterface'
|
import { ItemRepositoryInterface } from '../Item/ItemRepositoryInterface'
|
||||||
|
|
||||||
@injectable()
|
|
||||||
export class DuplicateItemSyncedEventHandler implements DomainEventHandlerInterface {
|
export class DuplicateItemSyncedEventHandler implements DomainEventHandlerInterface {
|
||||||
constructor(
|
constructor(
|
||||||
@inject(TYPES.ItemRepository) private itemRepository: ItemRepositoryInterface,
|
private itemRepository: ItemRepositoryInterface,
|
||||||
@inject(TYPES.DomainEventFactory) private domainEventFactory: DomainEventFactoryInterface,
|
private domainEventFactory: DomainEventFactoryInterface,
|
||||||
@inject(TYPES.DomainEventPublisher) private domainEventPublisher: DomainEventPublisherInterface,
|
private domainEventPublisher: DomainEventPublisherInterface,
|
||||||
@inject(TYPES.Logger) private logger: Logger,
|
private logger: Logger,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async handle(event: DuplicateItemSyncedEvent): Promise<void> {
|
async handle(event: DuplicateItemSyncedEvent): Promise<void> {
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user