mirror of
https://github.com/standardnotes/server
synced 2026-02-12 20:01:13 -05:00
Compare commits
73 Commits
@standardn
...
@standardn
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
85e0e2165f | ||
|
|
89ee103303 | ||
|
|
6b313947c3 | ||
|
|
fba8e6ce35 | ||
|
|
622c024547 | ||
|
|
2c51d92bab | ||
|
|
11ef2ef708 | ||
|
|
df793e07fd | ||
|
|
bae6eea3aa | ||
|
|
be17b67cc1 | ||
|
|
645a24d29b | ||
|
|
64962ce632 | ||
|
|
5120883691 | ||
|
|
0b4570ebee | ||
|
|
5bbdc7e426 | ||
|
|
a1d60630a0 | ||
|
|
e96fd6d69e | ||
|
|
1423b3fc35 | ||
|
|
fd10b4d585 | ||
|
|
8a79437668 | ||
|
|
85a87dc40a | ||
|
|
95aa0a0024 | ||
|
|
d0c44d1376 | ||
|
|
b0e31ff305 | ||
|
|
f11569ac53 | ||
|
|
fbf7a61bc9 | ||
|
|
2265165fa3 | ||
|
|
b216b17ef5 | ||
|
|
b2c7b924ac | ||
|
|
1349f950c9 | ||
|
|
f1c398a3a4 | ||
|
|
369231ff11 | ||
|
|
271dee5be6 | ||
|
|
a0c8f40e7b | ||
|
|
4db0aef0ff | ||
|
|
5ed9bd243f | ||
|
|
2c53306f5a | ||
|
|
a3624357dc | ||
|
|
afe0be31f2 | ||
|
|
71854b704d | ||
|
|
0907773d6f | ||
|
|
787eedc8af | ||
|
|
040a2b5e5f | ||
|
|
347ee275fa | ||
|
|
1c0a9e6726 | ||
|
|
c4f038ab9a | ||
|
|
3746ac5fc1 | ||
|
|
5c4353dd0c | ||
|
|
f64caed220 | ||
|
|
863d590292 | ||
|
|
0dcf64c82b | ||
|
|
48fd5c5ff6 | ||
|
|
84fa374072 | ||
|
|
2313b0b450 | ||
|
|
4fa6f579af | ||
|
|
08c1328932 | ||
|
|
4586308210 | ||
|
|
5aa561dcb2 | ||
|
|
e07612fe24 | ||
|
|
c9289204c4 | ||
|
|
51bb1081a6 | ||
|
|
25066bb33c | ||
|
|
bfdb176445 | ||
|
|
42233fa756 | ||
|
|
55de4319ed | ||
|
|
306f6edd4e | ||
|
|
bf55bbccd9 | ||
|
|
6e26c0a0be | ||
|
|
11bcd318ab | ||
|
|
2f6d19dc91 | ||
|
|
989e1ce175 | ||
|
|
1c2fd46401 | ||
|
|
b7967b34d1 |
13
.dockerignore
Normal file
13
.dockerignore
Normal file
@@ -0,0 +1,13 @@
|
||||
dist
|
||||
coverage
|
||||
|
||||
.yarn/*
|
||||
!.yarn/cache
|
||||
!.yarn/patches
|
||||
!.yarn/plugins
|
||||
!.yarn/releases
|
||||
!.yarn/unplugged
|
||||
!.yarn/sdks
|
||||
!.yarn/versions
|
||||
|
||||
data/*
|
||||
12
.env.sample
12
.env.sample
@@ -1,6 +1,18 @@
|
||||
######
|
||||
# DB #
|
||||
######
|
||||
|
||||
DB_HOST=db
|
||||
DB_PORT=3306
|
||||
DB_USERNAME=std_notes_user
|
||||
DB_PASSWORD=changeme123
|
||||
DB_DATABASE=standard_notes_db
|
||||
DB_DEBUG_LEVEL=all
|
||||
DB_MIGRATIONS_PATH=dist/migrations/*.js
|
||||
|
||||
#########
|
||||
# CACHE #
|
||||
#########
|
||||
|
||||
REDIS_PORT=6379
|
||||
REDIS_HOST=cache
|
||||
|
||||
21
.github/ci.env
vendored
Normal file
21
.github/ci.env
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
PUBLIC_FILES_SERVER_URL=http://localhost:3125
|
||||
DB_HOST=db
|
||||
DB_USERNAME=std_notes_user
|
||||
DB_PASSWORD=changeme123
|
||||
DB_DATABASE=standard_notes_db
|
||||
REDIS_PORT=6379
|
||||
REDIS_HOST=cache
|
||||
AUTH_SERVER_ACCESS_TOKEN_AGE=4
|
||||
AUTH_SERVER_REFRESH_TOKEN_AGE=10
|
||||
AUTH_SERVER_EPHEMERAL_SESSION_AGE=300
|
||||
SYNCING_SERVER_REVISIONS_FREQUENCY=5
|
||||
AUTH_SERVER_LOG_LEVEL=debug
|
||||
SYNCING_SERVER_LOG_LEVEL=debug
|
||||
FILES_SERVER_LOG_LEVEL=debug
|
||||
REVISIONS_SERVER_LOG_LEVEL=debug
|
||||
API_GATEWAY_LOG_LEVEL=debug
|
||||
|
||||
MYSQL_DATABASE=standard_notes_db
|
||||
MYSQL_USER=std_notes_user
|
||||
MYSQL_PASSWORD=changeme123
|
||||
MYSQL_ROOT_PASSWORD=changeme123
|
||||
10
.github/dependabot.yml
vendored
10
.github/dependabot.yml
vendored
@@ -55,6 +55,11 @@ updates:
|
||||
schedule:
|
||||
interval: "daily"
|
||||
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/packages/revisions"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/packages/scheduler"
|
||||
schedule:
|
||||
@@ -85,6 +90,11 @@ updates:
|
||||
schedule:
|
||||
interval: "daily"
|
||||
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/packages/websockets"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/packages/workspace"
|
||||
schedule:
|
||||
|
||||
8
.github/workflows/analytics.yml
vendored
8
.github/workflows/analytics.yml
vendored
@@ -11,9 +11,9 @@ on:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
call_server_utility_workflow:
|
||||
name: Server Utility
|
||||
uses: standardnotes/server/.github/workflows/common-server-utility.yml@main
|
||||
call_server_application_workflow:
|
||||
name: Server Application
|
||||
uses: standardnotes/server/.github/workflows/common-server-application.yml@main
|
||||
with:
|
||||
service_name: analytics
|
||||
workspace_name: "@standardnotes/analytics"
|
||||
@@ -22,7 +22,7 @@ jobs:
|
||||
secrets: inherit
|
||||
|
||||
newrelic:
|
||||
needs: call_server_utility_workflow
|
||||
needs: call_server_application_workflow
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
|
||||
1
.github/workflows/api-gateway.yml
vendored
1
.github/workflows/api-gateway.yml
vendored
@@ -17,7 +17,6 @@ jobs:
|
||||
with:
|
||||
service_name: api-gateway
|
||||
workspace_name: "@standardnotes/api-gateway"
|
||||
e2e_tag_parameter_name: api_gateway_image_tag
|
||||
deploy_worker: false
|
||||
package_path: packages/api-gateway
|
||||
secrets: inherit
|
||||
|
||||
1
.github/workflows/auth.yml
vendored
1
.github/workflows/auth.yml
vendored
@@ -17,7 +17,6 @@ jobs:
|
||||
with:
|
||||
service_name: auth
|
||||
workspace_name: "@standardnotes/auth-server"
|
||||
e2e_tag_parameter_name: auth_image_tag
|
||||
package_path: packages/auth
|
||||
secrets: inherit
|
||||
|
||||
|
||||
15
.github/workflows/common-docker-image.yml
vendored
15
.github/workflows/common-docker-image.yml
vendored
@@ -6,9 +6,6 @@ on:
|
||||
service_name:
|
||||
required: true
|
||||
type: string
|
||||
bundle_dir:
|
||||
required: true
|
||||
type: string
|
||||
package_path:
|
||||
required: true
|
||||
type: string
|
||||
@@ -32,13 +29,17 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Create Bundle Dir
|
||||
id: bundle-dir
|
||||
run: echo "temp_dir=$(mktemp -d -t ${{ inputs.service_name }}-${{ github.sha }}-XXXXXXX)" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Cache build
|
||||
id: cache-build
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
packages/**/dist
|
||||
${{ inputs.bundle_dir }}
|
||||
${{ steps.bundle-dir.outputs.temp_dir }}
|
||||
key: ${{ runner.os }}-${{ inputs.service_name }}-build-${{ github.sha }}
|
||||
|
||||
- name: Set up Node
|
||||
@@ -53,7 +54,7 @@ jobs:
|
||||
|
||||
- name: Bundle
|
||||
if: steps.cache-build.outputs.cache-hit != 'true'
|
||||
run: yarn workspace ${{ inputs.workspace_name }} bundle --no-compress --output-directory ${{ inputs.bundle_dir }}
|
||||
run: yarn workspace ${{ inputs.workspace_name }} bundle --no-compress --output-directory ${{ steps.bundle-dir.outputs.temp_dir }}
|
||||
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v2
|
||||
@@ -85,8 +86,8 @@ jobs:
|
||||
uses: docker/build-push-action@v3
|
||||
with:
|
||||
builder: ${{ steps.buildx.outputs.name }}
|
||||
context: ${{ inputs.bundle_dir }}
|
||||
file: ${{ inputs.bundle_dir }}/${{ inputs.package_path }}/Dockerfile
|
||||
context: ${{ steps.bundle-dir.outputs.temp_dir }}
|
||||
file: ${{ steps.bundle-dir.outputs.temp_dir }}/${{ inputs.package_path }}/Dockerfile
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: |
|
||||
|
||||
66
.github/workflows/common-e2e.yml
vendored
Normal file
66
.github/workflows/common-e2e.yml
vendored
Normal file
@@ -0,0 +1,66 @@
|
||||
name: Reusable Run E2E Test Suite Workflow
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
snjs_image_tag:
|
||||
type: string
|
||||
default: latest
|
||||
description: The Docker image tag used for SNJS container
|
||||
secrets:
|
||||
DOCKER_USERNAME:
|
||||
required: true
|
||||
DOCKER_PASSWORD:
|
||||
required: true
|
||||
AWS_ACCESS_KEY_ID:
|
||||
required: true
|
||||
AWS_SECRET_ACCESS_KEY:
|
||||
required: true
|
||||
|
||||
jobs:
|
||||
e2e:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
services:
|
||||
snjs:
|
||||
image: standardnotes/snjs:${{ inputs.snjs_image_tag }}
|
||||
ports:
|
||||
- 9001:9001
|
||||
mock-event-publisher:
|
||||
image: standardnotes/mock-event-publisher
|
||||
ports:
|
||||
- 3124:3000
|
||||
env:
|
||||
LOG_LEVEL: debug
|
||||
NODE_ENV: production
|
||||
VERSION: snjs-test
|
||||
SNS_TOPIC_ARN: arn:aws:sns:us-east-1:000000000000:payments-local-topic
|
||||
SNS_ENDPOINT: http://localstack:4566
|
||||
SNS_DISABLE_SSL: true
|
||||
SNS_SECRET_ACCESS_KEY: x
|
||||
SNS_ACCESS_KEY_ID: x
|
||||
SNS_AWS_REGION: us-east-1
|
||||
NEW_RELIC_ENABLED: false
|
||||
options: >-
|
||||
--name "mock-event-publisher"
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Set up Node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
registry-url: 'https://registry.npmjs.org'
|
||||
node-version-file: '.nvmrc'
|
||||
|
||||
- name: Run Server
|
||||
run: docker compose -f docker-compose.ci.yml up -d
|
||||
|
||||
- name: Wait for server to start
|
||||
run: docker/is-available.sh http://localhost:3123 $(pwd)/logs
|
||||
|
||||
- name: Connect external containers to self-hosted network
|
||||
run: docker network connect --alias mock-event-publisher standardnotes_self_hosted mock-event-publisher
|
||||
|
||||
- name: Run E2E Test Suite
|
||||
run: yarn dlx mocha-headless-chrome --timeout 1200000 -f http://localhost:9001/mocha/test.html
|
||||
47
.github/workflows/common-self-hosting.yml
vendored
Normal file
47
.github/workflows/common-self-hosting.yml
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
name: Reusable Publish Docker Self Hosting Image Workflow
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
secrets:
|
||||
DOCKER_USERNAME:
|
||||
required: true
|
||||
DOCKER_PASSWORD:
|
||||
required: true
|
||||
AWS_ACCESS_KEY_ID:
|
||||
required: true
|
||||
AWS_SECRET_ACCESS_KEY:
|
||||
required: true
|
||||
|
||||
jobs:
|
||||
publish:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- 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
|
||||
uses: docker/build-push-action@v3
|
||||
with:
|
||||
builder: ${{ steps.buildx.outputs.name }}
|
||||
context: .
|
||||
file: Dockerfile
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: |
|
||||
standardnotes/server:latest
|
||||
standardnotes/server:${{ github.sha }}
|
||||
169
.github/workflows/common-server-application.yml
vendored
169
.github/workflows/common-server-application.yml
vendored
@@ -17,9 +17,6 @@ on:
|
||||
required: false
|
||||
default: true
|
||||
type: boolean
|
||||
e2e_tag_parameter_name:
|
||||
required: false
|
||||
type: string
|
||||
package_path:
|
||||
required: true
|
||||
type: string
|
||||
@@ -36,177 +33,11 @@ on:
|
||||
required: true
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
outputs:
|
||||
temp_dir: ${{ steps.bundle-dir.outputs.temp_dir }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Create Bundle Dir
|
||||
id: bundle-dir
|
||||
run: echo "temp_dir=$(mktemp -d -t ${{ inputs.service_name }}-${{ github.sha }}-XXXXXXX)" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Cache build
|
||||
id: cache-build
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
packages/**/dist
|
||||
${{ steps.bundle-dir.outputs.temp_dir }}
|
||||
key: ${{ runner.os }}-${{ inputs.service_name }}-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
|
||||
run: yarn build ${{ inputs.package_path }}
|
||||
|
||||
- name: Bundle
|
||||
run: yarn workspace ${{ inputs.workspace_name }} bundle --no-compress --output-directory ${{ steps.bundle-dir.outputs.temp_dir }}
|
||||
|
||||
lint:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
needs: build
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Cache build
|
||||
id: cache-build
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
packages/**/dist
|
||||
${{ needs.build.outputs.temp_dir }}
|
||||
key: ${{ runner.os }}-${{ inputs.service_name }}-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 ${{ inputs.package_path }}
|
||||
|
||||
- name: Lint
|
||||
run: yarn lint:${{ inputs.service_name }}
|
||||
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
needs: build
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Cache build
|
||||
id: cache-build
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
packages/**/dist
|
||||
${{ needs.build.outputs.temp_dir }}
|
||||
key: ${{ runner.os }}-${{ inputs.service_name }}-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 ${{ inputs.package_path }}
|
||||
|
||||
- name: Test
|
||||
run: yarn test ${{ inputs.package_path }}
|
||||
|
||||
e2e:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
needs: build
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Cache build
|
||||
id: cache-build
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
packages/**/dist
|
||||
${{ needs.build.outputs.temp_dir }}
|
||||
key: ${{ runner.os }}-${{ inputs.service_name }}-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 ${{ inputs.package_path }}
|
||||
|
||||
- name: Bundle
|
||||
if: steps.cache-build.outputs.cache-hit != 'true'
|
||||
run: yarn workspace ${{ inputs.workspace_name }} bundle --no-compress --output-directory ${{ needs.build.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: ${{ needs.build.outputs.temp_dir }}
|
||||
file: ${{ needs.build.outputs.temp_dir }}/${{ inputs.package_path }}/Dockerfile
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: standardnotes/${{ inputs.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: '{"${{ inputs.e2e_tag_parameter_name }}": "${{ github.sha }}"}'
|
||||
propagate_failure: true
|
||||
trigger_workflow: true
|
||||
wait_workflow: true
|
||||
|
||||
publish:
|
||||
needs: [ build, test, lint, e2e ]
|
||||
|
||||
name: Publish Docker Image
|
||||
uses: standardnotes/server/.github/workflows/common-docker-image.yml@main
|
||||
with:
|
||||
service_name: ${{ inputs.service_name }}
|
||||
bundle_dir: ${{ needs.build.outputs.temp_dir }}
|
||||
package_path: ${{ inputs.package_path }}
|
||||
workspace_name: ${{ inputs.workspace_name }}
|
||||
secrets: inherit
|
||||
|
||||
164
.github/workflows/common-server-utility.yml
vendored
164
.github/workflows/common-server-utility.yml
vendored
@@ -1,164 +0,0 @@
|
||||
name: Reusable Server Utility Workflow
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
service_name:
|
||||
required: true
|
||||
type: string
|
||||
workspace_name:
|
||||
required: true
|
||||
type: string
|
||||
deploy_web:
|
||||
required: false
|
||||
default: true
|
||||
type: boolean
|
||||
deploy_worker:
|
||||
required: false
|
||||
default: true
|
||||
type: boolean
|
||||
package_path:
|
||||
required: true
|
||||
type: string
|
||||
secrets:
|
||||
DOCKER_USERNAME:
|
||||
required: true
|
||||
DOCKER_PASSWORD:
|
||||
required: true
|
||||
CI_PAT_TOKEN:
|
||||
required: true
|
||||
AWS_ACCESS_KEY_ID:
|
||||
required: true
|
||||
AWS_SECRET_ACCESS_KEY:
|
||||
required: true
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
outputs:
|
||||
temp_dir: ${{ steps.bundle-dir.outputs.temp_dir }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Create Bundle Dir
|
||||
id: bundle-dir
|
||||
run: echo "temp_dir=$(mktemp -d -t ${{ inputs.service_name }}-${{ github.sha }}-XXXXXXX)" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Cache build
|
||||
id: cache-build
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
packages/**/dist
|
||||
${{ steps.bundle-dir.outputs.temp_dir }}
|
||||
key: ${{ runner.os }}-${{ inputs.service_name }}-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
|
||||
run: yarn build ${{ inputs.package_path }}
|
||||
|
||||
- name: Bundle
|
||||
run: yarn workspace ${{ inputs.workspace_name }} bundle --no-compress --output-directory ${{ steps.bundle-dir.outputs.temp_dir }}
|
||||
|
||||
lint:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
needs: build
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Cache build
|
||||
id: cache-build
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
packages/**/dist
|
||||
${{ needs.build.outputs.temp_dir }}
|
||||
key: ${{ runner.os }}-${{ inputs.service_name }}-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 ${{ inputs.package_path }}
|
||||
|
||||
- name: Lint
|
||||
run: yarn lint:${{ inputs.service_name }}
|
||||
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
needs: build
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Cache build
|
||||
id: cache-build
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
packages/**/dist
|
||||
${{ needs.build.outputs.temp_dir }}
|
||||
key: ${{ runner.os }}-${{ inputs.service_name }}-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 ${{ inputs.package_path }}
|
||||
|
||||
- name: Test
|
||||
run: yarn test ${{ inputs.package_path }}
|
||||
|
||||
publish:
|
||||
needs: [ build, test, lint ]
|
||||
|
||||
name: Publish Docker Image
|
||||
uses: standardnotes/server/.github/workflows/common-docker-image.yml@main
|
||||
with:
|
||||
service_name: ${{ inputs.service_name }}
|
||||
bundle_dir: ${{ needs.build.outputs.temp_dir }}
|
||||
package_path: ${{ inputs.package_path }}
|
||||
workspace_name: ${{ inputs.workspace_name }}
|
||||
secrets: inherit
|
||||
|
||||
deploy-web:
|
||||
if: ${{ inputs.deploy_web }}
|
||||
|
||||
needs: publish
|
||||
|
||||
name: Deploy Web
|
||||
uses: standardnotes/server/.github/workflows/common-deploy.yml@main
|
||||
with:
|
||||
service_name: ${{ inputs.service_name }}
|
||||
docker_image: ${{ inputs.service_name }}:${{ github.sha }}
|
||||
secrets: inherit
|
||||
|
||||
deploy-worker:
|
||||
if: ${{ inputs.deploy_worker }}
|
||||
|
||||
needs: publish
|
||||
|
||||
name: Deploy Worker
|
||||
uses: standardnotes/server/.github/workflows/common-deploy.yml@main
|
||||
with:
|
||||
service_name: ${{ inputs.service_name }}-worker
|
||||
docker_image: ${{ inputs.service_name }}:${{ github.sha }}
|
||||
secrets: inherit
|
||||
17
.github/workflows/e2e-test-suite.yml
vendored
Normal file
17
.github/workflows/e2e-test-suite.yml
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
name: E2E Test Suite On Self Hosted Server
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
snjs_image_tag:
|
||||
type: string
|
||||
default: latest
|
||||
description: The Docker image tag used for SNJS container
|
||||
|
||||
jobs:
|
||||
e2e:
|
||||
name: E2E
|
||||
uses: standardnotes/server/.github/workflows/common-e2e.yml@main
|
||||
with:
|
||||
snjs_image_tag: ${{ inputs.snjs_image_tag }}
|
||||
secrets: inherit
|
||||
8
.github/workflows/event-store.yml
vendored
8
.github/workflows/event-store.yml
vendored
@@ -11,9 +11,9 @@ on:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
call_server_utility_workflow:
|
||||
name: Server Utility
|
||||
uses: standardnotes/server/.github/workflows/common-server-utility.yml@main
|
||||
call_server_application_workflow:
|
||||
name: Server Application
|
||||
uses: standardnotes/server/.github/workflows/common-server-application.yml@main
|
||||
with:
|
||||
service_name: event-store
|
||||
workspace_name: "@standardnotes/event-store"
|
||||
@@ -22,7 +22,7 @@ jobs:
|
||||
secrets: inherit
|
||||
|
||||
newrelic:
|
||||
needs: call_server_utility_workflow
|
||||
needs: call_server_application_workflow
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
|
||||
1
.github/workflows/files.yml
vendored
1
.github/workflows/files.yml
vendored
@@ -17,7 +17,6 @@ jobs:
|
||||
with:
|
||||
service_name: files
|
||||
workspace_name: "@standardnotes/files-server"
|
||||
e2e_tag_parameter_name: files_image_tag
|
||||
package_path: packages/files
|
||||
secrets: inherit
|
||||
|
||||
|
||||
79
.github/workflows/pr.yml
vendored
79
.github/workflows/pr.yml
vendored
@@ -89,81 +89,8 @@ jobs:
|
||||
run: yarn test
|
||||
|
||||
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
|
||||
|
||||
needs: build
|
||||
|
||||
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.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
|
||||
name: E2E
|
||||
uses: standardnotes/server/.github/workflows/common-e2e.yml@main
|
||||
secrets: inherit
|
||||
|
||||
103
.github/workflows/publish.yml
vendored
103
.github/workflows/publish.yml
vendored
@@ -5,9 +5,106 @@ on:
|
||||
branches: [ main ]
|
||||
|
||||
jobs:
|
||||
release_and_publish:
|
||||
build:
|
||||
if: contains(github.event.head_commit.message, 'chore(release)') == false
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Cache build
|
||||
id: cache-build
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
packages/**/dist
|
||||
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
|
||||
run: yarn build
|
||||
|
||||
lint:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
needs: build
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Cache build
|
||||
id: cache-build
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
packages/**/dist
|
||||
${{ needs.build.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: Lint
|
||||
run: yarn lint
|
||||
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
needs: build
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Cache build
|
||||
id: cache-build
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
packages/**/dist
|
||||
${{ needs.build.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: Test
|
||||
run: yarn test
|
||||
|
||||
e2e:
|
||||
needs: build
|
||||
name: E2E
|
||||
uses: standardnotes/server/.github/workflows/common-e2e.yml@main
|
||||
secrets: inherit
|
||||
|
||||
publish-self-hosting:
|
||||
needs: [ test, lint, e2e ]
|
||||
name: Publish Self Hosting Docker Image
|
||||
uses: standardnotes/server/.github/workflows/common-self-hosting.yml@main
|
||||
secrets: inherit
|
||||
|
||||
publish-services:
|
||||
needs: [ test, lint, e2e ]
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
@@ -34,7 +131,8 @@ jobs:
|
||||
registry-url: 'https://registry.npmjs.org'
|
||||
node-version-file: '.nvmrc'
|
||||
|
||||
- name: Build packages
|
||||
- name: Build
|
||||
if: steps.cache-build.outputs.cache-hit != 'true'
|
||||
run: yarn build
|
||||
|
||||
- name: Bump version
|
||||
@@ -44,4 +142,3 @@ jobs:
|
||||
run: yarn publish
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ${{ secrets.CI_NPM_TOKEN }}
|
||||
|
||||
|
||||
1
.github/workflows/revisions.yml
vendored
1
.github/workflows/revisions.yml
vendored
@@ -17,7 +17,6 @@ jobs:
|
||||
with:
|
||||
service_name: revisions
|
||||
workspace_name: "@standardnotes/revisions-server"
|
||||
e2e_tag_parameter_name: revisions_image_tag
|
||||
package_path: packages/revisions
|
||||
secrets: inherit
|
||||
|
||||
|
||||
8
.github/workflows/scheduler.yml
vendored
8
.github/workflows/scheduler.yml
vendored
@@ -11,9 +11,9 @@ on:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
call_server_utility_workflow:
|
||||
name: Server Utility
|
||||
uses: standardnotes/server/.github/workflows/common-server-utility.yml@main
|
||||
call_server_application_workflow:
|
||||
name: Server Application
|
||||
uses: standardnotes/server/.github/workflows/common-server-application.yml@main
|
||||
with:
|
||||
service_name: scheduler
|
||||
workspace_name: "@standardnotes/scheduler-server"
|
||||
@@ -22,7 +22,7 @@ jobs:
|
||||
secrets: inherit
|
||||
|
||||
newrelic:
|
||||
needs: call_server_utility_workflow
|
||||
needs: call_server_application_workflow
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
|
||||
1
.github/workflows/syncing-server.yml
vendored
1
.github/workflows/syncing-server.yml
vendored
@@ -17,7 +17,6 @@ jobs:
|
||||
with:
|
||||
service_name: syncing-server-js
|
||||
workspace_name: "@standardnotes/syncing-server"
|
||||
e2e_tag_parameter_name: syncing_server_js_image_tag
|
||||
package_path: packages/syncing-server
|
||||
secrets: inherit
|
||||
|
||||
|
||||
8
.github/workflows/websockets.yml
vendored
8
.github/workflows/websockets.yml
vendored
@@ -11,9 +11,9 @@ on:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
call_server_utility_workflow:
|
||||
name: Server Utility
|
||||
uses: standardnotes/server/.github/workflows/common-server-utility.yml@main
|
||||
call_server_application_workflow:
|
||||
name: Server Application
|
||||
uses: standardnotes/server/.github/workflows/common-server-application.yml@main
|
||||
with:
|
||||
service_name: websockets
|
||||
workspace_name: "@standardnotes/websockets-server"
|
||||
@@ -21,7 +21,7 @@ jobs:
|
||||
secrets: inherit
|
||||
|
||||
newrelic:
|
||||
needs: call_server_utility_workflow
|
||||
needs: call_server_application_workflow
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
|
||||
8
.github/workflows/workspace.yml
vendored
8
.github/workflows/workspace.yml
vendored
@@ -11,9 +11,9 @@ on:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
call_server_utility_workflow:
|
||||
name: Server Utility
|
||||
uses: standardnotes/server/.github/workflows/common-server-utility.yml@main
|
||||
call_server_application_workflow:
|
||||
name: Server Application
|
||||
uses: standardnotes/server/.github/workflows/common-server-application.yml@main
|
||||
with:
|
||||
service_name: workspace
|
||||
workspace_name: "@standardnotes/workspace-server"
|
||||
@@ -21,7 +21,7 @@ jobs:
|
||||
secrets: inherit
|
||||
|
||||
newrelic:
|
||||
needs: call_server_utility_workflow
|
||||
needs: call_server_application_workflow
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
|
||||
5
.gitignore
vendored
5
.gitignore
vendored
@@ -20,3 +20,8 @@ packages/files/uploads/*
|
||||
|
||||
data/*
|
||||
!data/.gitkeep
|
||||
|
||||
logs/*
|
||||
!logs/.gitkeep
|
||||
|
||||
docker-compose.yml
|
||||
|
||||
100
.pnp.cjs
generated
100
.pnp.cjs
generated
@@ -4501,13 +4501,11 @@ const RAW_RUNTIME_STATE =
|
||||
["@standardnotes/domain-core", "workspace:packages/domain-core"],\
|
||||
["@standardnotes/domain-events", "workspace:packages/domain-events"],\
|
||||
["@standardnotes/domain-events-infra", "workspace:packages/domain-events-infra"],\
|
||||
["@standardnotes/security", "workspace:packages/security"],\
|
||||
["@standardnotes/time", "workspace:packages/time"],\
|
||||
["@types/cors", "npm:2.8.12"],\
|
||||
["@types/dotenv", "npm:8.2.0"],\
|
||||
["@types/express", "npm:4.17.14"],\
|
||||
["@types/inversify-express-utils", "npm:2.0.0"],\
|
||||
["@types/ioredis", "npm:5.0.0"],\
|
||||
["@types/jest", "npm:29.1.1"],\
|
||||
["@types/newrelic", "npm:9.4.0"],\
|
||||
["@typescript-eslint/eslint-plugin", "virtual:c66bf20e88479ada0172094776519a9f51acc4731d22079b60a295bcec7ea42d5545cbce58a77a50d932bf953298799135e99707486e343da6d99ba1d167bdbd#npm:5.48.2"],\
|
||||
@@ -4516,17 +4514,15 @@ const RAW_RUNTIME_STATE =
|
||||
["eslint", "npm:8.32.0"],\
|
||||
["eslint-plugin-prettier", "virtual:c66bf20e88479ada0172094776519a9f51acc4731d22079b60a295bcec7ea42d5545cbce58a77a50d932bf953298799135e99707486e343da6d99ba1d167bdbd#npm:4.2.1"],\
|
||||
["express", "npm:4.18.2"],\
|
||||
["helmet", "npm:6.0.0"],\
|
||||
["inversify", "npm:6.0.1"],\
|
||||
["inversify-express-utils", "npm:6.4.3"],\
|
||||
["ioredis", "npm:5.2.4"],\
|
||||
["jest", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:29.1.2"],\
|
||||
["mysql2", "npm:3.0.1"],\
|
||||
["newrelic", "npm:9.8.0"],\
|
||||
["npm-check-updates", "npm:16.0.1"],\
|
||||
["reflect-metadata", "npm:0.1.13"],\
|
||||
["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"],\
|
||||
["winston", "npm:3.8.2"]\
|
||||
],\
|
||||
@@ -14489,6 +14485,100 @@ const RAW_RUNTIME_STATE =
|
||||
],\
|
||||
"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", {\
|
||||
"packageLocation": "./.yarn/__virtual__/typeorm-virtual-a38286c9d5/0/cache/typeorm-npm-0.3.10-4667857f33-749e1a6777.zip/node_modules/typeorm/",\
|
||||
"packageDependencies": [\
|
||||
|
||||
46
Dockerfile
Normal file
46
Dockerfile
Normal file
@@ -0,0 +1,46 @@
|
||||
FROM node:18.13.0-alpine
|
||||
|
||||
ENV NODE_ENV production
|
||||
|
||||
RUN apk add --update --no-cache \
|
||||
openssl \
|
||||
curl \
|
||||
bash \
|
||||
py3-pip
|
||||
|
||||
RUN pip install --no-cache-dir --upgrade supervisor
|
||||
|
||||
RUN mkdir -p /var/lib/server/logs
|
||||
|
||||
COPY docker/supervisord.conf /etc/supervisord.conf
|
||||
|
||||
COPY docker/docker-entrypoint.sh /usr/local/bin/
|
||||
|
||||
COPY . /opt/server
|
||||
|
||||
WORKDIR /opt/server
|
||||
|
||||
RUN corepack enable
|
||||
|
||||
RUN yarn install --immutable
|
||||
|
||||
RUN CI=true yarn build
|
||||
|
||||
RUN mkdir -p \
|
||||
/opt/bundled/syncing-server \
|
||||
/opt/bundled/auth \
|
||||
/opt/bundled/files \
|
||||
/opt/bundled/revisions \
|
||||
/opt/bundled/api-gateway
|
||||
|
||||
RUN yarn workspace @standardnotes/syncing-server bundle --no-compress --output-directory /opt/bundled/syncing-server
|
||||
RUN yarn workspace @standardnotes/auth-server bundle --no-compress --output-directory /opt/bundled/auth
|
||||
RUN yarn workspace @standardnotes/files-server bundle --no-compress --output-directory /opt/bundled/files
|
||||
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
|
||||
|
||||
WORKDIR /opt/bundled
|
||||
|
||||
RUN rm -rf /opt/server
|
||||
|
||||
ENTRYPOINT ["docker-entrypoint.sh"]
|
||||
58
docker-compose.ci.yml
Normal file
58
docker-compose.ci.yml
Normal file
@@ -0,0 +1,58 @@
|
||||
services:
|
||||
server:
|
||||
build: .
|
||||
env_file: .github/ci.env
|
||||
container_name: server-ci
|
||||
ports:
|
||||
- 3123:3000
|
||||
- 3125:3104
|
||||
volumes:
|
||||
- ./logs:/var/lib/server/logs
|
||||
networks:
|
||||
- standardnotes_self_hosted
|
||||
|
||||
localstack:
|
||||
image: localstack/localstack:1.3
|
||||
container_name: localstack-ci
|
||||
expose:
|
||||
- 4566
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- SERVICES=sns,sqs
|
||||
- DOCKER_HOST=unix:///var/run/docker.sock
|
||||
- HOSTNAME_EXTERNAL=localstack
|
||||
- LS_LOG=warn
|
||||
volumes:
|
||||
- ./docker/localstack_bootstrap.sh:/etc/localstack/init/ready.d/localstack_bootstrap.sh
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
networks:
|
||||
- standardnotes_self_hosted
|
||||
|
||||
db:
|
||||
image: mysql:8
|
||||
container_name: db-ci
|
||||
env_file: .github/ci.env
|
||||
expose:
|
||||
- 3306
|
||||
restart: unless-stopped
|
||||
command: --default-authentication-plugin=mysql_native_password --character-set-server=utf8mb4 --collation-server=utf8mb4_general_ci
|
||||
volumes:
|
||||
- ./data/mysql:/var/lib/mysql
|
||||
- ./data/import:/docker-entrypoint-initdb.d
|
||||
networks:
|
||||
- standardnotes_self_hosted
|
||||
|
||||
cache:
|
||||
image: redis:6.0-alpine
|
||||
container_name: cache-ci
|
||||
volumes:
|
||||
- ./data/redis/:/data
|
||||
expose:
|
||||
- 6379
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- standardnotes_self_hosted
|
||||
|
||||
networks:
|
||||
standardnotes_self_hosted:
|
||||
name: standardnotes_self_hosted
|
||||
62
docker-compose.example.yml
Normal file
62
docker-compose.example.yml
Normal file
@@ -0,0 +1,62 @@
|
||||
services:
|
||||
server:
|
||||
image: standardnotes/server
|
||||
env_file: .env.sample
|
||||
container_name: server_self_hosted
|
||||
ports:
|
||||
- 3000:3000
|
||||
- 3125:3104
|
||||
volumes:
|
||||
- ./logs:/var/lib/server/logs
|
||||
networks:
|
||||
- standardnotes_self_hosted
|
||||
|
||||
localstack:
|
||||
image: localstack/localstack:1.3
|
||||
container_name: localstack_self_hosted
|
||||
expose:
|
||||
- 4566
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- SERVICES=sns,sqs
|
||||
- DOCKER_HOST=unix:///var/run/docker.sock
|
||||
- HOSTNAME_EXTERNAL=localstack
|
||||
- LS_LOG=warn
|
||||
volumes:
|
||||
- ./docker/localstack_bootstrap.sh:/etc/localstack/init/ready.d/localstack_bootstrap.sh
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
networks:
|
||||
- standardnotes_self_hosted
|
||||
|
||||
db:
|
||||
image: mysql:8
|
||||
container_name: db_self_hosted
|
||||
environment:
|
||||
- MYSQL_DATABASE=standard_notes_db
|
||||
- MYSQL_USER=std_notes_user
|
||||
- MYSQL_ROOT_PASSWORD=changeme123
|
||||
- MYSQL_PASSWORD=changeme123
|
||||
expose:
|
||||
- 3306
|
||||
restart: unless-stopped
|
||||
command: --default-authentication-plugin=mysql_native_password --character-set-server=utf8mb4 --collation-server=utf8mb4_general_ci
|
||||
volumes:
|
||||
- ./data/mysql:/var/lib/mysql
|
||||
- ./data/import:/docker-entrypoint-initdb.d
|
||||
networks:
|
||||
- standardnotes_self_hosted
|
||||
|
||||
cache:
|
||||
image: redis:6.0-alpine
|
||||
container_name: cache_self_hosted
|
||||
volumes:
|
||||
- ./data/redis/:/data
|
||||
expose:
|
||||
- 6379
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- standardnotes_self_hosted
|
||||
|
||||
networks:
|
||||
standardnotes_self_hosted:
|
||||
name: standardnotes_self_hosted
|
||||
@@ -1,24 +0,0 @@
|
||||
version: '3.8'
|
||||
services:
|
||||
db:
|
||||
image: mysql:5.6
|
||||
environment:
|
||||
MYSQL_DATABASE: '${DB_DATABASE}'
|
||||
MYSQL_USER: '${DB_USERNAME}'
|
||||
MYSQL_PASSWORD: '${DB_PASSWORD}'
|
||||
MYSQL_ROOT_PASSWORD: '${DB_PASSWORD}'
|
||||
expose:
|
||||
- ${DB_PORT}:3306
|
||||
restart: unless-stopped
|
||||
command: --default-authentication-plugin=mysql_native_password --character-set-server=utf8 --collation-server=utf8_general_ci
|
||||
volumes:
|
||||
- ./data/mysql:/var/lib/mysql
|
||||
- ./data/import:/docker-entrypoint-initdb.d
|
||||
|
||||
cache:
|
||||
image: redis:6.0-alpine
|
||||
volumes:
|
||||
- ./data/redis/:/data
|
||||
expose:
|
||||
- ${REDIS_PORT}:6379
|
||||
restart: unless-stopped
|
||||
370
docker/docker-entrypoint.sh
Executable file
370
docker/docker-entrypoint.sh
Executable file
@@ -0,0 +1,370 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Setup environment variables
|
||||
|
||||
#########
|
||||
# PORTS #
|
||||
#########
|
||||
|
||||
export API_GATEWAY_PORT=3000
|
||||
|
||||
if [ -z "$SYNCING_SERVER_PORT" ]; then
|
||||
export SYNCING_SERVER_PORT=3101
|
||||
fi
|
||||
|
||||
if [ -z "$AUTH_SERVER_PORT" ]; then
|
||||
export AUTH_SERVER_PORT=3103
|
||||
fi
|
||||
|
||||
export FILES_SERVER_PORT=3104
|
||||
|
||||
if [ -z "$REVISIONS_SERVER_PORT" ]; then
|
||||
export REVISIONS_SERVER_PORT=3105
|
||||
fi
|
||||
|
||||
######
|
||||
# DB #
|
||||
######
|
||||
|
||||
if [ -z "$DB_HOST" ]; then
|
||||
export DB_HOST="db"
|
||||
fi
|
||||
if [ -z "$DB_PORT" ]; then
|
||||
export DB_PORT="3306"
|
||||
fi
|
||||
if [ -z "$DB_USERNAME" ]; then
|
||||
export DB_USERNAME="std_notes_user"
|
||||
fi
|
||||
if [ -z "$DB_PASSWORD" ]; then
|
||||
export DB_PASSWORD=$(openssl rand -hex 32)
|
||||
fi
|
||||
if [ -z "$DB_DATABASE" ]; then
|
||||
export DB_DATABASE="standard_notes_db"
|
||||
fi
|
||||
if [ -z "$DB_DEBUG_LEVEL" ]; then
|
||||
export DB_DEBUG_LEVEL="all"
|
||||
fi
|
||||
if [ -z "$DB_MIGRATIONS_PATH" ]; then
|
||||
export DB_MIGRATIONS_PATH="dist/migrations/*.js"
|
||||
fi
|
||||
|
||||
#########
|
||||
# CACHE #
|
||||
#########
|
||||
|
||||
if [ -z "$REDIS_PORT" ]; then
|
||||
export REDIS_PORT=6379
|
||||
fi
|
||||
|
||||
if [ -z "$REDIS_HOST" ]; then
|
||||
export REDIS_HOST="cache"
|
||||
fi
|
||||
|
||||
export REDIS_URL="redis://$REDIS_HOST"
|
||||
|
||||
##########
|
||||
# SHARED #
|
||||
##########
|
||||
|
||||
if [ -z "$AUTH_JWT_SECRET" ]; then
|
||||
export AUTH_JWT_SECRET=$(openssl rand -hex 32)
|
||||
fi
|
||||
|
||||
if [ -z "$VALET_TOKEN_SECRET" ]; then
|
||||
export VALET_TOKEN_SECRET=$(openssl rand -base64 32)
|
||||
fi
|
||||
|
||||
########
|
||||
# AUTH #
|
||||
########
|
||||
|
||||
if [ -z "$AUTH_SERVER_LOG_LEVEL" ]; then
|
||||
export AUTH_SERVER_LOG_LEVEL="info"
|
||||
fi
|
||||
export AUTH_SERVER_NODE_ENV="production"
|
||||
export AUTH_SERVER_VERSION="local"
|
||||
|
||||
if [ -z "$AUTH_SERVER_AUTH_JWT_TTL" ]; then
|
||||
export AUTH_SERVER_AUTH_JWT_TTL=60000
|
||||
fi
|
||||
|
||||
export AUTH_SERVER_JWT_SECRET=$AUTH_JWT_SECRET
|
||||
export AUTH_SERVER_LEGACY_JWT_SECRET=$(openssl rand -hex 32)
|
||||
|
||||
export AUTH_SERVER_NEW_RELIC_ENABLED=false
|
||||
export AUTH_SERVER_NEW_RELIC_APP_NAME=Auth
|
||||
export AUTH_SERVER_NEW_RELIC_NO_CONFIG_FILE=true
|
||||
|
||||
if [ -z "$AUTH_SERVER_DISABLE_USER_REGISTRATION" ]; then
|
||||
export AUTH_SERVER_DISABLE_USER_REGISTRATION=false
|
||||
fi
|
||||
|
||||
if [ -z "$AUTH_SERVER_PSEUDO_KEY_PARAMS_KEY" ]; then
|
||||
export AUTH_SERVER_PSEUDO_KEY_PARAMS_KEY=$(openssl rand -hex 32)
|
||||
fi
|
||||
|
||||
if [ -z "$AUTH_SERVER_ACCESS_TOKEN_AGE" ]; then
|
||||
export AUTH_SERVER_ACCESS_TOKEN_AGE=5184000
|
||||
fi
|
||||
if [ -z "$AUTH_SERVER_REFRESH_TOKEN_AGE" ]; then
|
||||
export AUTH_SERVER_REFRESH_TOKEN_AGE=31556926
|
||||
fi
|
||||
|
||||
if [ -z "$AUTH_SERVER_MAX_LOGIN_ATTEMPTS" ]; then
|
||||
export AUTH_SERVER_MAX_LOGIN_ATTEMPTS=6
|
||||
fi
|
||||
if [ -z "$AUTH_SERVER_FAILED_LOGIN_LOCKOUT" ]; then
|
||||
export AUTH_SERVER_FAILED_LOGIN_LOCKOUT=3600
|
||||
fi
|
||||
|
||||
if [ -z "$AUTH_SERVER_EPHEMERAL_SESSION_AGE" ]; then
|
||||
export AUTH_SERVER_EPHEMERAL_SESSION_AGE=259200
|
||||
fi
|
||||
|
||||
if [ -z "$AUTH_SERVER_ENCRYPTION_SERVER_KEY" ]; then
|
||||
export AUTH_SERVER_ENCRYPTION_SERVER_KEY=$(openssl rand -hex 32)
|
||||
fi
|
||||
|
||||
export AUTH_SERVER_SYNCING_SERVER_URL=http://localhost:$SYNCING_SERVER_PORT
|
||||
|
||||
# File Uploads
|
||||
if [ -z "$AUTH_SERVER_VALET_TOKEN_TTL" ]; then
|
||||
export AUTH_SERVER_VALET_TOKEN_TTL=7200
|
||||
fi
|
||||
|
||||
# Localstack Setup
|
||||
if [ -z "$AUTH_SERVER_SNS_TOPIC_ARN" ]; then
|
||||
export AUTH_SERVER_SNS_TOPIC_ARN="arn:aws:sns:us-east-1:000000000000:auth-local-topic"
|
||||
fi
|
||||
if [ -z "$AUTH_SERVER_SNS_ENDPOINT" ]; then
|
||||
export AUTH_SERVER_SNS_ENDPOINT="http://localstack:4566"
|
||||
fi
|
||||
if [ -z "$AUTH_SERVER_SNS_SECRET_ACCESS_KEY" ]; then
|
||||
export AUTH_SERVER_SNS_SECRET_ACCESS_KEY="x"
|
||||
fi
|
||||
if [ -z "$AUTH_SERVER_SNS_ACCESS_KEY_ID" ]; then
|
||||
export AUTH_SERVER_SNS_ACCESS_KEY_ID="x"
|
||||
fi
|
||||
if [ -z "$AUTH_SERVER_SNS_AWS_REGION" ]; then
|
||||
export AUTH_SERVER_SNS_AWS_REGION="us-east-1"
|
||||
fi
|
||||
if [ -z "$AUTH_SERVER_SQS_QUEUE_URL" ]; then
|
||||
export AUTH_SERVER_SQS_QUEUE_URL="http://localstack:4566/000000000000/auth-local-queue"
|
||||
fi
|
||||
if [ -z "$AUTH_SERVER_SQS_AWS_REGION" ]; then
|
||||
export AUTH_SERVER_SQS_AWS_REGION="us-east-1"
|
||||
fi
|
||||
if [ -z "$AUTH_SERVER_SQS_ACCESS_KEY_ID" ]; then
|
||||
export AUTH_SERVER_SQS_ACCESS_KEY_ID="x"
|
||||
fi
|
||||
if [ -z "$AUTH_SERVER_SQS_SECRET_ACCESS_KEY" ]; then
|
||||
export AUTH_SERVER_SQS_SECRET_ACCESS_KEY="x"
|
||||
fi
|
||||
if [ -z "$AUTH_SERVER_SQS_ENDPOINT" ]; then
|
||||
export AUTH_SERVER_SQS_ENDPOINT="http://localstack:4566"
|
||||
fi
|
||||
|
||||
# U2F Setup
|
||||
if [ -z "$AUTH_SERVER_U2F_RELYING_PARTY_ID" ]; then
|
||||
export AUTH_SERVER_U2F_RELYING_PARTY_ID="localhost"
|
||||
fi
|
||||
if [ -z "$AUTH_SERVER_U2F_RELYING_PARTY_NAME" ]; then
|
||||
export AUTH_SERVER_U2F_RELYING_PARTY_NAME="Standard Notes"
|
||||
fi
|
||||
if [ -z "$AUTH_SERVER_U2F_EXPECTED_ORIGIN" ]; then
|
||||
export AUTH_SERVER_U2F_EXPECTED_ORIGIN="http://localhost,http://localhost:3001"
|
||||
fi
|
||||
if [ -z "$AUTH_SERVER_U2F_REQUIRE_USER_VERIFICATION" ]; then
|
||||
export AUTH_SERVER_U2F_REQUIRE_USER_VERIFICATION=false
|
||||
fi
|
||||
|
||||
printenv | grep AUTH_SERVER_ | sed 's/AUTH_SERVER_//g' > /opt/bundled/auth/packages/auth/.env
|
||||
|
||||
##################
|
||||
# SYNCING SERVER #
|
||||
##################
|
||||
|
||||
if [ -z "$SYNCING_SERVER_LOG_LEVEL" ]; then
|
||||
export SYNCING_SERVER_LOG_LEVEL="info"
|
||||
fi
|
||||
export SYNCING_SERVER_NODE_ENV=production
|
||||
export SYNCING_SERVER_VERSION=local
|
||||
|
||||
if [ -z "$SYNCING_SERVER_SNS_TOPIC_ARN" ]; then
|
||||
export SYNCING_SERVER_SNS_TOPIC_ARN="arn:aws:sns:us-east-1:000000000000:syncing-server-local-topic"
|
||||
fi
|
||||
if [ -z "$SYNCING_SERVER_SNS_ENDPOINT" ]; then
|
||||
export SYNCING_SERVER_SNS_ENDPOINT="http://localstack:4566"
|
||||
fi
|
||||
if [ -z "$SYNCING_SERVER_SNS_SECRET_ACCESS_KEY" ]; then
|
||||
export SYNCING_SERVER_SNS_SECRET_ACCESS_KEY="x"
|
||||
fi
|
||||
if [ -z "$SYNCING_SERVER_SNS_ACCESS_KEY_ID" ]; then
|
||||
export SYNCING_SERVER_SNS_ACCESS_KEY_ID="x"
|
||||
fi
|
||||
if [ -z "$SYNCING_SERVER_SNS_AWS_REGION" ]; then
|
||||
export SYNCING_SERVER_SNS_AWS_REGION="us-east-1"
|
||||
fi
|
||||
if [ -z "$SYNCING_SERVER_SQS_QUEUE_URL" ]; then
|
||||
export SYNCING_SERVER_SQS_QUEUE_URL="http://localstack:4566/000000000000/syncing-server-local-queue"
|
||||
fi
|
||||
if [ -z "$SYNCING_SERVER_SQS_AWS_REGION" ]; then
|
||||
export SYNCING_SERVER_SQS_AWS_REGION="us-east-1"
|
||||
fi
|
||||
if [ -z "$SYNCING_SERVER_SQS_ACCESS_KEY_ID" ]; then
|
||||
export SYNCING_SERVER_SQS_ACCESS_KEY_ID="x"
|
||||
fi
|
||||
if [ -z "$SYNCING_SERVER_SQS_SECRET_ACCESS_KEY" ]; then
|
||||
export SYNCING_SERVER_SQS_SECRET_ACCESS_KEY="x"
|
||||
fi
|
||||
if [ -z "$SYNCING_SERVER_SQS_ENDPOINT" ]; then
|
||||
export SYNCING_SERVER_SQS_ENDPOINT="http://localstack:4566"
|
||||
fi
|
||||
|
||||
export SYNCING_SERVER_AUTH_SERVER_URL=http://localhost:$AUTH_SERVER_PORT
|
||||
|
||||
if [ -z "$SYNCING_SERVER_EMAIL_ATTACHMENT_MAX_BYTE_SIZE" ]; then
|
||||
export SYNCING_SERVER_EMAIL_ATTACHMENT_MAX_BYTE_SIZE=10485760
|
||||
fi
|
||||
|
||||
if [ -z "$SYNCING_SERVER_REVISIONS_FREQUENCY" ]; then
|
||||
export SYNCING_SERVER_REVISIONS_FREQUENCY=300
|
||||
fi
|
||||
|
||||
export SYNCING_SERVER_NEW_RELIC_ENABLED=false
|
||||
export SYNCING_SERVER_NEW_RELIC_APP_NAME="Syncing Server JS"
|
||||
export SYNCING_SERVER_NEW_RELIC_NO_CONFIG_FILE=true
|
||||
|
||||
if [ -z "$SYNCING_SERVER_FILE_UPLOAD_PATH" ]; then
|
||||
export SYNCING_SERVER_FILE_UPLOAD_PATH="data/uploads"
|
||||
fi
|
||||
|
||||
printenv | grep SYNCING_SERVER_ | sed 's/SYNCING_SERVER_//g' > /opt/bundled/syncing-server/packages/syncing-server/.env
|
||||
|
||||
|
||||
################
|
||||
# FILES SERVER #
|
||||
################
|
||||
|
||||
if [ -z "$FILES_SERVER_LOG_LEVEL" ]; then
|
||||
export FILES_SERVER_LOG_LEVEL="info"
|
||||
fi
|
||||
export FILES_SERVER_NODE_ENV="production"
|
||||
export FILES_SERVER_VERSION="local"
|
||||
|
||||
if [ -z "$FILES_SERVER_MAX_CHUNK_BYTES" ]; then
|
||||
export FILES_SERVER_MAX_CHUNK_BYTES=100000000
|
||||
fi
|
||||
|
||||
export FILES_SERVER_NEW_RELIC_ENABLED=false
|
||||
|
||||
if [ -z "$FILES_SERVER_SNS_TOPIC_ARN" ]; then
|
||||
export FILES_SERVER_SNS_TOPIC_ARN="arn:aws:sns:us-east-1:000000000000:files-local-topic"
|
||||
fi
|
||||
if [ -z "$FILES_SERVER_SNS_ENDPOINT" ]; then
|
||||
export FILES_SERVER_SNS_ENDPOINT="http://localstack:4566"
|
||||
fi
|
||||
if [ -z "$FILES_SERVER_SNS_SECRET_ACCESS_KEY" ]; then
|
||||
export FILES_SERVER_SNS_SECRET_ACCESS_KEY="x"
|
||||
fi
|
||||
if [ -z "$FILES_SERVER_SNS_ACCESS_KEY_ID" ]; then
|
||||
export FILES_SERVER_SNS_ACCESS_KEY_ID="x"
|
||||
fi
|
||||
if [ -z "$FILES_SERVER_SNS_AWS_REGION" ]; then
|
||||
export FILES_SERVER_SNS_AWS_REGION="us-east-1"
|
||||
fi
|
||||
if [ -z "$FILES_SERVER_SQS_QUEUE_URL" ]; then
|
||||
export FILES_SERVER_SQS_QUEUE_URL="http://localstack:4566/000000000000/files-local-queue"
|
||||
fi
|
||||
if [ -z "$FILES_SERVER_SQS_AWS_REGION" ]; then
|
||||
export FILES_SERVER_SQS_AWS_REGION="us-east-1"
|
||||
fi
|
||||
if [ -z "$FILES_SERVER_SQS_ACCESS_KEY_ID" ]; then
|
||||
export FILES_SERVER_SQS_ACCESS_KEY_ID="x"
|
||||
fi
|
||||
if [ -z "$FILES_SERVER_SQS_SECRET_ACCESS_KEY" ]; then
|
||||
export FILES_SERVER_SQS_SECRET_ACCESS_KEY="x"
|
||||
fi
|
||||
if [ -z "$FILES_SERVER_SQS_ENDPOINT" ]; then
|
||||
export FILES_SERVER_SQS_ENDPOINT="http://localstack:4566"
|
||||
fi
|
||||
|
||||
printenv | grep FILES_SERVER_ | sed 's/FILES_SERVER_//g' > /opt/bundled/files/packages/files/.env
|
||||
|
||||
#############
|
||||
# REVISIONS #
|
||||
#############
|
||||
|
||||
if [ -z "$REVISIONS_SERVER_LOG_LEVEL" ]; then
|
||||
export REVISIONS_SERVER_LOG_LEVEL="info"
|
||||
fi
|
||||
|
||||
export REVISIONS_SERVER_NODE_ENV="production"
|
||||
export REVISIONS_SERVER_VERSION="local"
|
||||
|
||||
export REVISIONS_SERVER_NEW_RELIC_ENABLED=false
|
||||
|
||||
if [ -z "$REVISIONS_SERVER_SNS_TOPIC_ARN" ]; then
|
||||
export REVISIONS_SERVER_SNS_TOPIC_ARN="arn:aws:sns:us-east-1:000000000000:revisions-server-local-topic"
|
||||
fi
|
||||
if [ -z "$REVISIONS_SERVER_SNS_ENDPOINT" ]; then
|
||||
export REVISIONS_SERVER_SNS_ENDPOINT="http://localstack:4566"
|
||||
fi
|
||||
if [ -z "$REVISIONS_SERVER_SNS_SECRET_ACCESS_KEY" ]; then
|
||||
export REVISIONS_SERVER_SNS_SECRET_ACCESS_KEY="x"
|
||||
fi
|
||||
if [ -z "$REVISIONS_SERVER_SNS_ACCESS_KEY_ID" ]; then
|
||||
export REVISIONS_SERVER_SNS_ACCESS_KEY_ID="x"
|
||||
fi
|
||||
if [ -z "$REVISIONS_SERVER_SNS_AWS_REGION" ]; then
|
||||
export REVISIONS_SERVER_SNS_AWS_REGION="us-east-1"
|
||||
fi
|
||||
if [ -z "$REVISIONS_SERVER_SQS_QUEUE_URL" ]; then
|
||||
export REVISIONS_SERVER_SQS_QUEUE_URL="http://localstack:4566/000000000000/revisions-server-local-queue"
|
||||
fi
|
||||
if [ -z "$REVISIONS_SERVER_SQS_AWS_REGION" ]; then
|
||||
export REVISIONS_SERVER_SQS_AWS_REGION="us-east-1"
|
||||
fi
|
||||
if [ -z "$REVISIONS_SERVER_SQS_ACCESS_KEY_ID" ]; then
|
||||
export REVISIONS_SERVER_SQS_ACCESS_KEY_ID="x"
|
||||
fi
|
||||
if [ -z "$REVISIONS_SERVER_SQS_SECRET_ACCESS_KEY" ]; then
|
||||
export REVISIONS_SERVER_SQS_SECRET_ACCESS_KEY="x"
|
||||
fi
|
||||
if [ -z "$REVISIONS_SERVER_SQS_ENDPOINT" ]; then
|
||||
export REVISIONS_SERVER_SQS_ENDPOINT="http://localstack:4566"
|
||||
fi
|
||||
|
||||
printenv | grep REVISIONS_SERVER_ | sed 's/REVISIONS_SERVER_//g' > /opt/bundled/revisions/packages/revisions/.env
|
||||
|
||||
###############
|
||||
# API GATEWAY #
|
||||
###############
|
||||
|
||||
if [ -z "$API_GATEWAY_LOG_LEVEL" ]; then
|
||||
export API_GATEWAY_LOG_LEVEL="info"
|
||||
fi
|
||||
export API_GATEWAY_NODE_ENV=production
|
||||
export API_GATEWAY_VERSION=local
|
||||
|
||||
export API_GATEWAY_NEW_RELIC_ENABLED=false
|
||||
export API_GATEWAY_NEW_RELIC_APP_NAME="API Gateway"
|
||||
export API_GATEWAY_NEW_RELIC_NO_CONFIG_FILE=true
|
||||
|
||||
export API_GATEWAY_SYNCING_SERVER_JS_URL=http://localhost:$SYNCING_SERVER_PORT
|
||||
export API_GATEWAY_AUTH_SERVER_URL=http://localhost:$AUTH_SERVER_PORT
|
||||
export API_GATEWAY_WORKSPACE_SERVER_URL=http://localhost:3004
|
||||
export API_GATEWAY_REVISIONS_SERVER_URL=http://localhost:3005
|
||||
if [ -z "$PUBLIC_FILES_SERVER_URL" ]; then
|
||||
export API_GATEWAY_FILES_SERVER_URL=http://localhost:$FILES_SERVER_PORT
|
||||
else
|
||||
export API_GATEWAY_FILES_SERVER_URL=$PUBLIC_FILES_SERVER_URL
|
||||
fi
|
||||
|
||||
printenv | grep API_GATEWAY_ | sed 's/API_GATEWAY_//g' > /opt/bundled/api-gateway/packages/api-gateway/.env
|
||||
|
||||
# Run supervisor
|
||||
|
||||
supervisord -c /etc/supervisord.conf
|
||||
|
||||
exec "$@"
|
||||
30
docker/is-available.sh
Executable file
30
docker/is-available.sh
Executable file
@@ -0,0 +1,30 @@
|
||||
#!/bin/bash
|
||||
|
||||
WAIT_FOR_URL="$1"
|
||||
shift
|
||||
LOGS_PATH="$1"
|
||||
shift
|
||||
|
||||
attempt=0
|
||||
while [ $attempt -le 120 ]; do
|
||||
attempt=$(( $attempt + 1 ))
|
||||
echo "# Waiting for all services to be up (attempt: $attempt) ..."
|
||||
ping_api_gateway_result=`curl -s $WAIT_FOR_URL | grep "Welcome"`
|
||||
if [ "$?" -eq "0" ]; then
|
||||
sleep 2 # for warmup
|
||||
echo "# All services are up!"
|
||||
exit 0
|
||||
break
|
||||
fi
|
||||
sleep 2
|
||||
done
|
||||
|
||||
echo "# Failed to wait for all services to be up!"
|
||||
|
||||
echo "# Errors:"
|
||||
tail -n 50 $LOGS_PATH/*.err
|
||||
|
||||
echo "# Logs:"
|
||||
tail -n 50 $LOGS_PATH/*.log
|
||||
|
||||
exit 1
|
||||
196
docker/localstack_bootstrap.sh
Executable file
196
docker/localstack_bootstrap.sh
Executable file
@@ -0,0 +1,196 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
echo "configuring sns/sqs"
|
||||
echo "==================="
|
||||
LOCALSTACK_HOST=localhost
|
||||
AWS_REGION=us-east-1
|
||||
LOCALSTACK_DUMMY_ID=000000000000
|
||||
|
||||
get_all_queues() {
|
||||
awslocal --endpoint-url=http://${LOCALSTACK_HOST}:4566 sqs list-queues
|
||||
}
|
||||
|
||||
create_queue() {
|
||||
local QUEUE_NAME_TO_CREATE=$1
|
||||
awslocal --endpoint-url=http://${LOCALSTACK_HOST}:4566 sqs create-queue --queue-name ${QUEUE_NAME_TO_CREATE}
|
||||
}
|
||||
|
||||
get_all_topics() {
|
||||
awslocal --endpoint-url=http://${LOCALSTACK_HOST}:4566 sns list-topics
|
||||
}
|
||||
|
||||
create_topic() {
|
||||
local TOPIC_NAME_TO_CREATE=$1
|
||||
awslocal --endpoint-url=http://${LOCALSTACK_HOST}:4566 sns create-topic --name ${TOPIC_NAME_TO_CREATE}
|
||||
}
|
||||
|
||||
link_queue_and_topic() {
|
||||
local TOPIC_ARN_TO_LINK=$1
|
||||
local QUEUE_ARN_TO_LINK=$2
|
||||
awslocal --endpoint-url=http://${LOCALSTACK_HOST}:4566 sns subscribe --topic-arn ${TOPIC_ARN_TO_LINK} --protocol sqs --notification-endpoint ${QUEUE_ARN_TO_LINK}
|
||||
}
|
||||
|
||||
get_queue_arn_from_name() {
|
||||
local QUEUE_NAME=$1
|
||||
echo "arn:aws:sns:${AWS_REGION}:${LOCALSTACK_DUMMY_ID}:$QUEUE_NAME"
|
||||
}
|
||||
|
||||
get_topic_arn_from_name() {
|
||||
local TOPIC_NAME=$1
|
||||
echo "arn:aws:sns:${AWS_REGION}:${LOCALSTACK_DUMMY_ID}:$TOPIC_NAME"
|
||||
}
|
||||
|
||||
PAYMENTS_TOPIC_NAME="payments-local-topic"
|
||||
|
||||
echo "creating topic $PAYMENTS_TOPIC_NAME"
|
||||
TOPIC_CREATED_RESULT=$(create_topic ${PAYMENTS_TOPIC_NAME})
|
||||
echo "created topic: $TOPIC_CREATED_RESULT"
|
||||
PAYMENTS_TOPIC_ARN=$(get_topic_arn_from_name $PAYMENTS_TOPIC_NAME)
|
||||
|
||||
SYNCING_SERVER_TOPIC_NAME="syncing-server-local-topic"
|
||||
|
||||
echo "creating topic $SYNCING_SERVER_TOPIC_NAME"
|
||||
TOPIC_CREATED_RESULT=$(create_topic ${SYNCING_SERVER_TOPIC_NAME})
|
||||
echo "created topic: $TOPIC_CREATED_RESULT"
|
||||
SYNCING_SERVER_TOPIC_ARN=$(get_topic_arn_from_name $SYNCING_SERVER_TOPIC_NAME)
|
||||
|
||||
AUTH_TOPIC_NAME="auth-local-topic"
|
||||
|
||||
echo "creating topic $AUTH_TOPIC_NAME"
|
||||
TOPIC_CREATED_RESULT=$(create_topic ${AUTH_TOPIC_NAME})
|
||||
echo "created topic: $TOPIC_CREATED_RESULT"
|
||||
AUTH_TOPIC_ARN=$(get_topic_arn_from_name $AUTH_TOPIC_NAME)
|
||||
|
||||
FILES_TOPIC_NAME="files-local-topic"
|
||||
|
||||
echo "creating topic $FILES_TOPIC_NAME"
|
||||
TOPIC_CREATED_RESULT=$(create_topic ${FILES_TOPIC_NAME})
|
||||
echo "created topic: $TOPIC_CREATED_RESULT"
|
||||
FILES_TOPIC_ARN=$(get_topic_arn_from_name $FILES_TOPIC_NAME)
|
||||
|
||||
ANALYTICS_TOPIC_NAME="analytics-local-topic"
|
||||
|
||||
echo "creating topic $ANALYTICS_TOPIC_NAME"
|
||||
TOPIC_CREATED_RESULT=$(create_topic ${ANALYTICS_TOPIC_NAME})
|
||||
echo "created topic: $TOPIC_CREATED_RESULT"
|
||||
ANALYTICS_TOPIC_ARN=$(get_topic_arn_from_name $ANALYTICS_TOPIC_NAME)
|
||||
|
||||
REVISIONS_TOPIC_NAME="revisions-server-local-topic"
|
||||
|
||||
echo "creating topic $REVISIONS_TOPIC_NAME"
|
||||
TOPIC_CREATED_RESULT=$(create_topic ${REVISIONS_TOPIC_NAME})
|
||||
echo "created topic: $TOPIC_CREATED_RESULT"
|
||||
REVISIONS_TOPIC_ARN=$(get_topic_arn_from_name $REVISIONS_TOPIC_NAME)
|
||||
|
||||
SCHEDULER_TOPIC_NAME="scheduler-local-topic"
|
||||
|
||||
echo "creating topic $SCHEDULER_TOPIC_NAME"
|
||||
TOPIC_CREATED_RESULT=$(create_topic ${SCHEDULER_TOPIC_NAME})
|
||||
echo "created topic: $TOPIC_CREATED_RESULT"
|
||||
SCHEDULER_TOPIC_ARN=$(get_topic_arn_from_name $SCHEDULER_TOPIC_NAME)
|
||||
|
||||
WORKSPACE_TOPIC_NAME="workspace-local-topic"
|
||||
|
||||
echo "creating topic $WORKSPACE_TOPIC_NAME"
|
||||
TOPIC_CREATED_RESULT=$(create_topic ${WORKSPACE_TOPIC_NAME})
|
||||
echo "created topic: $TOPIC_CREATED_RESULT"
|
||||
WORKSPACE_TOPIC_ARN=$(get_topic_arn_from_name $WORKSPACE_TOPIC_NAME)
|
||||
|
||||
QUEUE_NAME="analytics-local-queue"
|
||||
|
||||
echo "creating queue $QUEUE_NAME"
|
||||
QUEUE_URL=$(create_queue ${QUEUE_NAME})
|
||||
echo "created queue: $QUEUE_URL"
|
||||
ANALYTICS_QUEUE_ARN=$(get_queue_arn_from_name $QUEUE_NAME)
|
||||
|
||||
echo "linking topic $PAYMENTS_TOPIC_ARN to queue $ANALYTICS_QUEUE_ARN"
|
||||
LINKING_RESULT=$(link_queue_and_topic $PAYMENTS_TOPIC_ARN $ANALYTICS_QUEUE_ARN)
|
||||
echo "linking done:"
|
||||
echo "$LINKING_RESULT"
|
||||
|
||||
QUEUE_NAME="auth-local-queue"
|
||||
|
||||
echo "creating queue $QUEUE_NAME"
|
||||
QUEUE_URL=$(create_queue ${QUEUE_NAME})
|
||||
echo "created queue: $QUEUE_URL"
|
||||
AUTH_QUEUE_ARN=$(get_queue_arn_from_name $QUEUE_NAME)
|
||||
|
||||
echo "linking topic $PAYMENTS_TOPIC_ARN to queue $AUTH_QUEUE_ARN"
|
||||
LINKING_RESULT=$(link_queue_and_topic $PAYMENTS_TOPIC_ARN $AUTH_QUEUE_ARN)
|
||||
echo "linking done:"
|
||||
echo "$LINKING_RESULT"
|
||||
echo "linking topic $AUTH_TOPIC_ARN to queue $AUTH_QUEUE_ARN"
|
||||
LINKING_RESULT=$(link_queue_and_topic $AUTH_TOPIC_ARN $AUTH_QUEUE_ARN)
|
||||
echo "linking done:"
|
||||
echo "$LINKING_RESULT"
|
||||
echo "linking topic $FILES_TOPIC_ARN to queue $AUTH_QUEUE_ARN"
|
||||
LINKING_RESULT=$(link_queue_and_topic $FILES_TOPIC_ARN $AUTH_QUEUE_ARN)
|
||||
echo "linking done:"
|
||||
echo "$LINKING_RESULT"
|
||||
|
||||
QUEUE_NAME="files-local-queue"
|
||||
|
||||
echo "creating queue $QUEUE_NAME"
|
||||
QUEUE_URL=$(create_queue ${QUEUE_NAME})
|
||||
echo "created queue: $QUEUE_URL"
|
||||
FILES_QUEUE_ARN=$(get_queue_arn_from_name $QUEUE_NAME)
|
||||
|
||||
echo "linking topic $AUTH_TOPIC_ARN to queue $FILES_QUEUE_ARN"
|
||||
LINKING_RESULT=$(link_queue_and_topic $AUTH_TOPIC_ARN $FILES_QUEUE_ARN)
|
||||
echo "linking done:"
|
||||
echo "$LINKING_RESULT"
|
||||
|
||||
QUEUE_NAME="syncing-server-local-queue"
|
||||
|
||||
echo "creating queue $QUEUE_NAME"
|
||||
QUEUE_URL=$(create_queue ${QUEUE_NAME})
|
||||
echo "created queue: $QUEUE_URL"
|
||||
SYNCING_SERVER_QUEUE_ARN=$(get_queue_arn_from_name $QUEUE_NAME)
|
||||
|
||||
echo "linking topic $SYNCING_SERVER_TOPIC_ARN to queue $SYNCING_SERVER_QUEUE_ARN"
|
||||
LINKING_RESULT=$(link_queue_and_topic $SYNCING_SERVER_TOPIC_ARN $SYNCING_SERVER_QUEUE_ARN)
|
||||
echo "linking done:"
|
||||
echo "$LINKING_RESULT"
|
||||
|
||||
echo "linking topic $SYNCING_SERVER_TOPIC_ARN to queue $SYNCING_SERVER_QUEUE_ARN"
|
||||
LINKING_RESULT=$(link_queue_and_topic $SYNCING_SERVER_TOPIC_ARN $SYNCING_SERVER_QUEUE_ARN)
|
||||
echo "linking done:"
|
||||
echo "$LINKING_RESULT"
|
||||
echo "linking topic $AUTH_TOPIC_ARN to queue $SYNCING_SERVER_QUEUE_ARN"
|
||||
LINKING_RESULT=$(link_queue_and_topic $AUTH_TOPIC_ARN $SYNCING_SERVER_QUEUE_ARN)
|
||||
echo "linking done:"
|
||||
echo "$LINKING_RESULT"
|
||||
|
||||
QUEUE_NAME="revisions-server-local-queue"
|
||||
|
||||
echo "creating queue $QUEUE_NAME"
|
||||
QUEUE_URL=$(create_queue ${QUEUE_NAME})
|
||||
echo "created queue: $QUEUE_URL"
|
||||
REVISIONS_QUEUE_ARN=$(get_queue_arn_from_name $QUEUE_NAME)
|
||||
|
||||
echo "linking topic $SYNCING_SERVER_TOPIC_ARN to queue $REVISIONS_QUEUE_ARN"
|
||||
LINKING_RESULT=$(link_queue_and_topic $SYNCING_SERVER_TOPIC_ARN $REVISIONS_QUEUE_ARN)
|
||||
echo "linking done:"
|
||||
echo "$LINKING_RESULT"
|
||||
|
||||
QUEUE_NAME="scheduler-local-queue"
|
||||
|
||||
echo "creating queue $QUEUE_NAME"
|
||||
QUEUE_URL=$(create_queue ${QUEUE_NAME})
|
||||
echo "created queue: $QUEUE_URL"
|
||||
SCHEDULER_QUEUE_ARN=$(get_queue_arn_from_name $QUEUE_NAME)
|
||||
|
||||
QUEUE_NAME="workspace-local-queue"
|
||||
|
||||
echo "creating queue $QUEUE_NAME"
|
||||
QUEUE_URL=$(create_queue ${QUEUE_NAME})
|
||||
echo "created queue: $QUEUE_URL"
|
||||
WORKSPACE_QUEUE_ARN=$(get_queue_arn_from_name $QUEUE_NAME)
|
||||
|
||||
echo "all topics are:"
|
||||
echo "$(get_all_topics)"
|
||||
|
||||
echo "all queues are:"
|
||||
echo "$(get_all_queues)"
|
||||
75
docker/supervisord.conf
Normal file
75
docker/supervisord.conf
Normal file
@@ -0,0 +1,75 @@
|
||||
[supervisord]
|
||||
nodaemon=true
|
||||
logfile=/tmp/supervisord.log
|
||||
|
||||
[program:syncing-server]
|
||||
directory=/opt/bundled/syncing-server
|
||||
command=yarn workspace @standardnotes/syncing-server supervisor:start
|
||||
autostart=true
|
||||
autorestart=true
|
||||
stdout_logfile=/var/lib/server/logs/syncing-server.log
|
||||
stderr_logfile=/var/lib/server/logs/syncing-server.err
|
||||
|
||||
[program:syncing-server-worker]
|
||||
directory=/opt/bundled/syncing-server
|
||||
command=yarn workspace @standardnotes/syncing-server supervisor:worker
|
||||
autostart=true
|
||||
autorestart=true
|
||||
stdout_logfile=/var/lib/server/logs/syncing-server-worker.log
|
||||
stderr_logfile=/var/lib/server/logs/syncing-server-worker.err
|
||||
|
||||
[program:auth]
|
||||
directory=/opt/bundled/auth
|
||||
command=yarn workspace @standardnotes/auth-server supervisor:start
|
||||
autostart=true
|
||||
autorestart=true
|
||||
stdout_logfile=/var/lib/server/logs/auth.log
|
||||
stderr_logfile=/var/lib/server/logs/auth.err
|
||||
|
||||
[program:auth-worker]
|
||||
directory=/opt/bundled/auth
|
||||
command=yarn workspace @standardnotes/auth-server supervisor:worker
|
||||
autostart=true
|
||||
autorestart=true
|
||||
stdout_logfile=/var/lib/server/logs/auth-worker.log
|
||||
stderr_logfile=/var/lib/server/logs/auth-worker.err
|
||||
|
||||
[program:files]
|
||||
directory=/opt/bundled/files
|
||||
command=yarn workspace @standardnotes/files-server supervisor:start
|
||||
autostart=true
|
||||
autorestart=true
|
||||
stdout_logfile=/var/lib/server/logs/files.log
|
||||
stderr_logfile=/var/lib/server/logs/files.err
|
||||
|
||||
[program:files-worker]
|
||||
directory=/opt/bundled/files
|
||||
command=yarn workspace @standardnotes/files-server supervisor:worker
|
||||
autostart=true
|
||||
autorestart=true
|
||||
stdout_logfile=/var/lib/server/logs/files-worker.log
|
||||
stderr_logfile=/var/lib/server/logs/files-worker.err
|
||||
|
||||
[program:revisions]
|
||||
directory=/opt/bundled/revisions
|
||||
command=yarn workspace @standardnotes/revisions-server supervisor:start
|
||||
autostart=true
|
||||
autorestart=true
|
||||
stdout_logfile=/var/lib/server/logs/revisions.log
|
||||
stderr_logfile=/var/lib/server/logs/revisions.err
|
||||
|
||||
[program:revisions-worker]
|
||||
directory=/opt/bundled/revisions
|
||||
command=yarn workspace @standardnotes/revisions-server supervisor:worker
|
||||
autostart=true
|
||||
autorestart=true
|
||||
stdout_logfile=/var/lib/server/logs/revisions-worker.log
|
||||
stderr_logfile=/var/lib/server/logs/revisions-worker.err
|
||||
|
||||
[program:api-gateway]
|
||||
directory=/opt/bundled/api-gateway
|
||||
command=yarn workspace @standardnotes/api-gateway supervisor:start
|
||||
autostart=true
|
||||
autorestart=true
|
||||
stdout_logfile=/var/lib/server/logs/api-gateway.log
|
||||
stderr_logfile=/var/lib/server/logs/api-gateway.err
|
||||
13
docker/wait-for.sh
Executable file
13
docker/wait-for.sh
Executable file
@@ -0,0 +1,13 @@
|
||||
#!/bin/bash
|
||||
|
||||
WAIT_FOR_HOST="$1"
|
||||
shift
|
||||
WAIT_FOR_PORT="$1"
|
||||
shift
|
||||
|
||||
while ! nc -vz $WAIT_FOR_HOST $WAIT_FOR_PORT; do
|
||||
echo "$WAIT_FOR_HOST:$WAIT_FOR_PORT is unavailable yet - waiting for it to start"
|
||||
sleep 10
|
||||
done
|
||||
|
||||
echo "$WAIT_FOR_HOST:$WAIT_FOR_PORT is up. Proceeding to startup."
|
||||
0
logs/.gitkeep
Normal file
0
logs/.gitkeep
Normal file
22
package.json
22
package.json
@@ -12,30 +12,8 @@
|
||||
},
|
||||
"scripts": {
|
||||
"lint": "yarn workspaces foreach -p -j 10 --verbose run lint",
|
||||
"lint:auth": "yarn workspace @standardnotes/auth-server lint",
|
||||
"lint:scheduler": "yarn workspace @standardnotes/scheduler-server lint",
|
||||
"lint:syncing-server-js": "yarn workspace @standardnotes/syncing-server lint",
|
||||
"lint:files": "yarn workspace @standardnotes/files-server lint",
|
||||
"lint:api-gateway": "yarn workspace @standardnotes/api-gateway lint",
|
||||
"lint:event-store": "yarn workspace @standardnotes/event-store lint",
|
||||
"lint:websockets": "yarn workspace @standardnotes/websockets-server lint",
|
||||
"lint:workspace": "yarn workspace @standardnotes/workspace-server lint",
|
||||
"lint:analytics": "yarn workspace @standardnotes/analytics lint",
|
||||
"lint:revisions": "yarn workspace @standardnotes/revisions-server lint",
|
||||
"clean": "yarn workspaces foreach -p --verbose run clean",
|
||||
"setup:env": "cp .env.sample .env && yarn workspaces foreach -p --verbose run setup:env",
|
||||
"start:auth": "yarn workspace @standardnotes/auth-server start",
|
||||
"start:auth-worker": "yarn workspace @standardnotes/auth-server worker",
|
||||
"start:scheduler": "yarn workspace @standardnotes/scheduler-server worker",
|
||||
"start:syncing-server": "yarn workspace @standardnotes/syncing-server start",
|
||||
"start:syncing-server-worker": "yarn workspace @standardnotes/syncing-server worker",
|
||||
"start:files": "yarn workspace @standardnotes/files-server start",
|
||||
"start:files-worker": "yarn workspace @standardnotes/files-server worker",
|
||||
"start:api-gateway": "yarn workspace @standardnotes/api-gateway start",
|
||||
"start:websockets": "yarn workspace @standardnotes/websockets-server start",
|
||||
"start:workspace": "yarn workspace @standardnotes/workspace-server start",
|
||||
"start:analytics": "yarn workspace @standardnotes/analytics worker",
|
||||
"start:revisions": "yarn workspace @standardnotes/revisions-server start",
|
||||
"release": "lerna version --conventional-graduate --conventional-commits --yes -m \"chore(release): publish new version\"",
|
||||
"publish": "lerna publish from-git --yes --no-verify-access --loglevel verbose",
|
||||
"postversion": "./scripts/push-tags-one-by-one.sh",
|
||||
|
||||
@@ -13,7 +13,6 @@ DB_MIGRATIONS_PATH=dist/migrations/*.js
|
||||
ADMIN_EMAILS=test@standardnotes.com
|
||||
|
||||
REDIS_URL=redis://cache
|
||||
REDIS_EVENTS_CHANNEL=events
|
||||
|
||||
SNS_TOPIC_ARN=
|
||||
SNS_AWS_REGION=
|
||||
|
||||
@@ -3,6 +3,10 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [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
|
||||
|
||||
## [2.19.15](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.19.14...@standardnotes/analytics@2.19.15) (2023-01-30)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/analytics",
|
||||
"version": "2.19.15",
|
||||
"version": "2.19.16",
|
||||
"engines": {
|
||||
"node": ">=18.0.0 <19.0.0"
|
||||
},
|
||||
|
||||
@@ -15,9 +15,6 @@ import TYPES from './Types'
|
||||
import { AppDataSource } from './DataSource'
|
||||
import { DomainEventFactory } from '../Domain/Event/DomainEventFactory'
|
||||
import {
|
||||
RedisDomainEventPublisher,
|
||||
RedisDomainEventSubscriberFactory,
|
||||
RedisEventMessageHandler,
|
||||
SNSDomainEventPublisher,
|
||||
SQSDomainEventSubscriberFactory,
|
||||
SQSEventMessageHandler,
|
||||
@@ -95,22 +92,20 @@ export class ContainerConfigLoader {
|
||||
})
|
||||
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))
|
||||
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 = {
|
||||
@@ -130,10 +125,9 @@ export class ContainerConfigLoader {
|
||||
|
||||
// env vars
|
||||
container.bind(TYPES.REDIS_URL).toConstantValue(env.get('REDIS_URL'))
|
||||
container.bind(TYPES.SNS_TOPIC_ARN).toConstantValue(env.get('SNS_TOPIC_ARN', true))
|
||||
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', true))
|
||||
container.bind(TYPES.REDIS_EVENTS_CHANNEL).toConstantValue(env.get('REDIS_EVENTS_CHANNEL'))
|
||||
container.bind(TYPES.SQS_QUEUE_URL).toConstantValue(env.get('SQS_QUEUE_URL'))
|
||||
container.bind(TYPES.NEW_RELIC_ENABLED).toConstantValue(env.get('NEW_RELIC_ENABLED', true))
|
||||
container.bind(TYPES.ADMIN_EMAILS).toConstantValue(env.get('ADMIN_EMAILS').split(','))
|
||||
container.bind(TYPES.MIXPANEL_TOKEN).toConstantValue(env.get('MIXPANEL_TOKEN', true))
|
||||
@@ -149,17 +143,9 @@ export class ContainerConfigLoader {
|
||||
.toConstantValue(new RedisStatisticsStore(container.get(TYPES.PeriodKeyGenerator), container.get(TYPES.Redis)))
|
||||
container.bind<TimerInterface>(TYPES.Timer).toConstantValue(new Timer())
|
||||
|
||||
if (env.get('SNS_TOPIC_ARN', true)) {
|
||||
container
|
||||
.bind<SNSDomainEventPublisher>(TYPES.DomainEventPublisher)
|
||||
.toConstantValue(new SNSDomainEventPublisher(container.get(TYPES.SNS), container.get(TYPES.SNS_TOPIC_ARN)))
|
||||
} else {
|
||||
container
|
||||
.bind<RedisDomainEventPublisher>(TYPES.DomainEventPublisher)
|
||||
.toConstantValue(
|
||||
new RedisDomainEventPublisher(container.get(TYPES.Redis), container.get(TYPES.REDIS_EVENTS_CHANNEL)),
|
||||
)
|
||||
}
|
||||
container
|
||||
.bind<SNSDomainEventPublisher>(TYPES.DomainEventPublisher)
|
||||
.toConstantValue(new SNSDomainEventPublisher(container.get(TYPES.SNS), container.get(TYPES.SNS_TOPIC_ARN)))
|
||||
if (env.get('MIXPANEL_TOKEN', true)) {
|
||||
container.bind<Mixpanel>(TYPES.MixpanelClient).toConstantValue(Mixpanel.init(env.get('MIXPANEL_TOKEN', true)))
|
||||
}
|
||||
@@ -250,37 +236,22 @@ export class ContainerConfigLoader {
|
||||
['STATISTIC_PERSISTENCE_REQUESTED', container.get(TYPES.StatisticPersistenceRequestedEventHandler)],
|
||||
])
|
||||
|
||||
if (env.get('SQS_QUEUE_URL', true)) {
|
||||
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),
|
||||
),
|
||||
)
|
||||
} else {
|
||||
container
|
||||
.bind<DomainEventMessageHandlerInterface>(TYPES.DomainEventMessageHandler)
|
||||
.toConstantValue(new RedisEventMessageHandler(eventHandlers, container.get(TYPES.Logger)))
|
||||
container
|
||||
.bind<DomainEventSubscriberFactoryInterface>(TYPES.DomainEventSubscriberFactory)
|
||||
.toConstantValue(
|
||||
new RedisDomainEventSubscriberFactory(
|
||||
container.get(TYPES.Redis),
|
||||
container.get(TYPES.DomainEventMessageHandler),
|
||||
container.get(TYPES.REDIS_EVENTS_CHANNEL),
|
||||
),
|
||||
)
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@ const TYPES = {
|
||||
SNS_AWS_REGION: Symbol.for('SNS_AWS_REGION'),
|
||||
SQS_QUEUE_URL: Symbol.for('SQS_QUEUE_URL'),
|
||||
SQS_AWS_REGION: Symbol.for('SQS_AWS_REGION'),
|
||||
REDIS_EVENTS_CHANNEL: Symbol.for('REDIS_EVENTS_CHANNEL'),
|
||||
NEW_RELIC_ENABLED: Symbol.for('NEW_RELIC_ENABLED'),
|
||||
ADMIN_EMAILS: Symbol.for('ADMIN_EMAILS'),
|
||||
MIXPANEL_TOKEN: Symbol.for('MIXPANEL_TOKEN'),
|
||||
|
||||
@@ -27,7 +27,6 @@ NEW_RELIC_LOG_ENABLED=false
|
||||
NEW_RELIC_LOG_LEVEL=info
|
||||
|
||||
REDIS_URL=redis://cache
|
||||
REDIS_EVENTS_CHANNEL=events
|
||||
|
||||
# (Optional) Caching Cross Service Tokens
|
||||
CROSS_SERVICE_TOKEN_CACHE_TTL=
|
||||
|
||||
@@ -3,6 +3,22 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [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
|
||||
|
||||
* performance of startup sequence in supervisor controlled self-hosting setup ([5bbdc7e](https://github.com/standardnotes/api-gateway/commit/5bbdc7e426c436b17dc130e3c6d9163080561c76))
|
||||
|
||||
## [1.46.12](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.46.11...@standardnotes/api-gateway@1.46.12) (2023-02-09)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* optimize memory usage ([e96fd6d](https://github.com/standardnotes/api-gateway/commit/e96fd6d69e1252842b5c91b1bedefa36e5d4a232))
|
||||
|
||||
## [1.46.11](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.46.10...@standardnotes/api-gateway@1.46.11) (2023-02-06)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/api-gateway
|
||||
|
||||
## [1.46.10](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.46.9...@standardnotes/api-gateway@1.46.10) (2023-01-30)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/api-gateway
|
||||
|
||||
13
packages/api-gateway/docker/wait-for.sh
Executable file
13
packages/api-gateway/docker/wait-for.sh
Executable file
@@ -0,0 +1,13 @@
|
||||
#!/bin/bash
|
||||
|
||||
WAIT_FOR_HOST="$1"
|
||||
shift
|
||||
WAIT_FOR_PORT="$1"
|
||||
shift
|
||||
|
||||
while ! nc -vz $WAIT_FOR_HOST $WAIT_FOR_PORT; do
|
||||
echo "$WAIT_FOR_HOST:$WAIT_FOR_PORT is unavailable yet - waiting for it to start"
|
||||
sleep 10
|
||||
done
|
||||
|
||||
echo "$WAIT_FOR_HOST:$WAIT_FOR_PORT is up. Proceeding to startup."
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/api-gateway",
|
||||
"version": "1.46.10",
|
||||
"version": "1.46.13",
|
||||
"engines": {
|
||||
"node": ">=18.0.0 <19.0.0"
|
||||
},
|
||||
@@ -16,7 +16,9 @@
|
||||
"build": "tsc --build",
|
||||
"lint": "eslint . --ext .ts",
|
||||
"setup:env": "cp .env.sample .env",
|
||||
"wait-for:revisions": "docker/wait-for.sh localhost $REVISIONS_SERVER_PORT",
|
||||
"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/*'"
|
||||
},
|
||||
"dependencies": {
|
||||
|
||||
@@ -65,7 +65,6 @@ export class ContainerConfigLoader {
|
||||
.bind(TYPES.HTTP_CALL_TIMEOUT)
|
||||
.toConstantValue(env.get('HTTP_CALL_TIMEOUT', true) ? +env.get('HTTP_CALL_TIMEOUT', true) : 60_000)
|
||||
container.bind(TYPES.VERSION).toConstantValue(env.get('VERSION'))
|
||||
container.bind(TYPES.REDIS_EVENTS_CHANNEL).toConstantValue(env.get('REDIS_EVENTS_CHANNEL'))
|
||||
container.bind(TYPES.CROSS_SERVICE_TOKEN_CACHE_TTL).toConstantValue(+env.get('CROSS_SERVICE_TOKEN_CACHE_TTL', true))
|
||||
|
||||
// Middleware
|
||||
|
||||
@@ -14,7 +14,6 @@ const TYPES = {
|
||||
AUTH_JWT_SECRET: Symbol.for('AUTH_JWT_SECRET'),
|
||||
HTTP_CALL_TIMEOUT: Symbol.for('HTTP_CALL_TIMEOUT'),
|
||||
VERSION: Symbol.for('VERSION'),
|
||||
REDIS_EVENTS_CHANNEL: Symbol.for('REDIS_EVENTS_CHANNEL'),
|
||||
CROSS_SERVICE_TOKEN_CACHE_TTL: Symbol.for('CROSS_SERVICE_TOKEN_CACHE_TTL'),
|
||||
// Middleware
|
||||
AuthMiddleware: Symbol.for('AuthMiddleware'),
|
||||
|
||||
@@ -43,8 +43,6 @@ SQS_AWS_REGION=
|
||||
|
||||
SYNCING_SERVER_URL=http://syncing-server-js:3000
|
||||
|
||||
REDIS_EVENTS_CHANNEL=events
|
||||
|
||||
# (Optional) New Relic Setup
|
||||
NEW_RELIC_ENABLED=false
|
||||
NEW_RELIC_APP_NAME=Auth
|
||||
|
||||
@@ -3,6 +3,46 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [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
|
||||
|
||||
* performance of startup sequence in supervisor controlled self-hosting setup ([5bbdc7e](https://github.com/standardnotes/server/commit/5bbdc7e426c436b17dc130e3c6d9163080561c76))
|
||||
|
||||
## [1.87.13](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.87.12...@standardnotes/auth-server@1.87.13) (2023-02-09)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* optimize memory usage ([e96fd6d](https://github.com/standardnotes/server/commit/e96fd6d69e1252842b5c91b1bedefa36e5d4a232))
|
||||
|
||||
## [1.87.12](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.87.11...@standardnotes/auth-server@1.87.12) (2023-02-06)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/auth-server
|
||||
|
||||
## [1.87.11](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.87.10...@standardnotes/auth-server@1.87.11) (2023-02-02)
|
||||
|
||||
### Reverts
|
||||
|
||||
* Revert "fix(auth): disallow adding u2f devices if a user does not have 2fa enabled" ([bf55bbc](https://github.com/standardnotes/server/commit/bf55bbccd9ab1704671fa3980ede3bd0cc909833))
|
||||
|
||||
## [1.87.10](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.87.9...@standardnotes/auth-server@1.87.10) (2023-02-02)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **auth:** disallow adding u2f devices if a user does not have 2fa enabled ([11bcd31](https://github.com/standardnotes/server/commit/11bcd318abc71d5a1fa80b8beda109076e3b6dad))
|
||||
|
||||
## [1.87.9](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.87.8...@standardnotes/auth-server@1.87.9) (2023-02-02)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **auth:** verification rpid options ([989e1ce](https://github.com/standardnotes/server/commit/989e1ce175cf70718304dd2d2463949147bcc084))
|
||||
|
||||
## [1.87.8](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.87.7...@standardnotes/auth-server@1.87.8) (2023-02-02)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **auth:** allow defining multiple expected origins upon u2f registration and verification ([b7967b3](https://github.com/standardnotes/server/commit/b7967b34d1118534644a3e464e9e43267455519d))
|
||||
|
||||
## [1.87.7](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.87.6...@standardnotes/auth-server@1.87.7) (2023-01-30)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
13
packages/auth/docker/wait-for.sh
Executable file
13
packages/auth/docker/wait-for.sh
Executable file
@@ -0,0 +1,13 @@
|
||||
#!/bin/bash
|
||||
|
||||
WAIT_FOR_HOST="$1"
|
||||
shift
|
||||
WAIT_FOR_PORT="$1"
|
||||
shift
|
||||
|
||||
while ! nc -vz $WAIT_FOR_HOST $WAIT_FOR_PORT; do
|
||||
echo "$WAIT_FOR_HOST:$WAIT_FOR_PORT is unavailable yet - waiting for it to start"
|
||||
sleep 10
|
||||
done
|
||||
|
||||
echo "$WAIT_FOR_HOST:$WAIT_FOR_PORT is up. Proceeding to startup."
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/auth-server",
|
||||
"version": "1.87.7",
|
||||
"version": "1.87.14",
|
||||
"engines": {
|
||||
"node": ">=18.0.0 <19.0.0"
|
||||
},
|
||||
@@ -17,8 +17,12 @@
|
||||
"lint": "eslint . --ext .ts",
|
||||
"pretest": "yarn lint && yarn build",
|
||||
"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",
|
||||
"supervisor:start": "yarn wait-for:syncing-server && yarn node dist/bin/server.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",
|
||||
"stats": "yarn node dist/bin/stats.js",
|
||||
"daily-backup:email": "yarn node dist/bin/backup.js email daily",
|
||||
|
||||
@@ -90,9 +90,6 @@ import { FeatureService } from '../Domain/Feature/FeatureService'
|
||||
import { SettingServiceInterface } from '../Domain/Setting/SettingServiceInterface'
|
||||
import { ExtensionKeyGrantedEventHandler } from '../Domain/Handler/ExtensionKeyGrantedEventHandler'
|
||||
import {
|
||||
RedisDomainEventPublisher,
|
||||
RedisDomainEventSubscriberFactory,
|
||||
RedisEventMessageHandler,
|
||||
SNSDomainEventPublisher,
|
||||
SQSDomainEventSubscriberFactory,
|
||||
SQSEventMessageHandler,
|
||||
@@ -258,37 +255,33 @@ export class ContainerConfigLoader {
|
||||
|
||||
container.bind<TimerInterface>(TYPES.Timer).toConstantValue(new Timer())
|
||||
|
||||
if (env.get('SNS_TOPIC_ARN', true)) {
|
||||
const snsConfig: SNSClientConfig = {
|
||||
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))
|
||||
const snsConfig: SNSClientConfig = {
|
||||
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))
|
||||
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))
|
||||
|
||||
// Mapping
|
||||
container
|
||||
@@ -441,13 +434,12 @@ export class ContainerConfigLoader {
|
||||
container
|
||||
.bind(TYPES.DISABLE_USER_REGISTRATION)
|
||||
.toConstantValue(env.get('DISABLE_USER_REGISTRATION', true) === 'true')
|
||||
container.bind(TYPES.SNS_TOPIC_ARN).toConstantValue(env.get('SNS_TOPIC_ARN', true))
|
||||
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', true))
|
||||
container.bind(TYPES.SQS_QUEUE_URL).toConstantValue(env.get('SQS_QUEUE_URL'))
|
||||
container.bind(TYPES.USER_SERVER_REGISTRATION_URL).toConstantValue(env.get('USER_SERVER_REGISTRATION_URL', true))
|
||||
container.bind(TYPES.USER_SERVER_AUTH_KEY).toConstantValue(env.get('USER_SERVER_AUTH_KEY', true))
|
||||
container.bind(TYPES.USER_SERVER_CHANGE_EMAIL_URL).toConstantValue(env.get('USER_SERVER_CHANGE_EMAIL_URL', true))
|
||||
container.bind(TYPES.REDIS_EVENTS_CHANNEL).toConstantValue(env.get('REDIS_EVENTS_CHANNEL'))
|
||||
container.bind(TYPES.NEW_RELIC_ENABLED).toConstantValue(env.get('NEW_RELIC_ENABLED', true))
|
||||
container.bind(TYPES.SYNCING_SERVER_URL).toConstantValue(env.get('SYNCING_SERVER_URL'))
|
||||
container.bind(TYPES.VERSION).toConstantValue(env.get('VERSION'))
|
||||
@@ -463,7 +455,11 @@ export class ContainerConfigLoader {
|
||||
.toConstantValue(env.get('U2F_RELYING_PARTY_ID', true) ?? 'standardnotes.com')
|
||||
container
|
||||
.bind(TYPES.U2F_EXPECTED_ORIGIN)
|
||||
.toConstantValue(env.get('U2F_EXPECTED_ORIGIN', true) ?? 'https://app.standardnotes.com')
|
||||
.toConstantValue(
|
||||
env.get('U2F_EXPECTED_ORIGIN', true)
|
||||
? env.get('U2F_EXPECTED_ORIGIN', true).split(',')
|
||||
: ['https://app.standardnotes.com'],
|
||||
)
|
||||
container
|
||||
.bind(TYPES.U2F_REQUIRE_USER_VERIFICATION)
|
||||
.toConstantValue(env.get('U2F_REQUIRE_USER_VERIFICATION', true) === 'true')
|
||||
@@ -531,17 +527,9 @@ export class ContainerConfigLoader {
|
||||
.toConstantValue(new DeterministicSelector<boolean>())
|
||||
container.bind<UserSubscriptionServiceInterface>(TYPES.UserSubscriptionService).to(UserSubscriptionService)
|
||||
|
||||
if (env.get('SNS_TOPIC_ARN', true)) {
|
||||
container
|
||||
.bind<SNSDomainEventPublisher>(TYPES.DomainEventPublisher)
|
||||
.toConstantValue(new SNSDomainEventPublisher(container.get(TYPES.SNS), container.get(TYPES.SNS_TOPIC_ARN)))
|
||||
} else {
|
||||
container
|
||||
.bind<RedisDomainEventPublisher>(TYPES.DomainEventPublisher)
|
||||
.toConstantValue(
|
||||
new RedisDomainEventPublisher(container.get(TYPES.Redis), container.get(TYPES.REDIS_EVENTS_CHANNEL)),
|
||||
)
|
||||
}
|
||||
container
|
||||
.bind<SNSDomainEventPublisher>(TYPES.DomainEventPublisher)
|
||||
.toConstantValue(new SNSDomainEventPublisher(container.get(TYPES.SNS), container.get(TYPES.SNS_TOPIC_ARN)))
|
||||
|
||||
// use cases
|
||||
container
|
||||
@@ -799,37 +787,22 @@ export class ContainerConfigLoader {
|
||||
['EMAIL_SUBSCRIPTION_UNSUBSCRIBED', container.get(TYPES.EmailSubscriptionUnsubscribedEventHandler)],
|
||||
])
|
||||
|
||||
if (env.get('SQS_QUEUE_URL', true)) {
|
||||
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),
|
||||
),
|
||||
)
|
||||
} else {
|
||||
container
|
||||
.bind<DomainEventMessageHandlerInterface>(TYPES.DomainEventMessageHandler)
|
||||
.toConstantValue(new RedisEventMessageHandler(eventHandlers, container.get(TYPES.Logger)))
|
||||
container
|
||||
.bind<DomainEventSubscriberFactoryInterface>(TYPES.DomainEventSubscriberFactory)
|
||||
.toConstantValue(
|
||||
new RedisDomainEventSubscriberFactory(
|
||||
container.get(TYPES.Redis),
|
||||
container.get(TYPES.DomainEventMessageHandler),
|
||||
container.get(TYPES.REDIS_EVENTS_CHANNEL),
|
||||
),
|
||||
)
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
@@ -88,7 +88,6 @@ const TYPES = {
|
||||
USER_SERVER_REGISTRATION_URL: Symbol.for('USER_SERVER_REGISTRATION_URL'),
|
||||
USER_SERVER_AUTH_KEY: Symbol.for('USER_SERVER_AUTH_KEY'),
|
||||
USER_SERVER_CHANGE_EMAIL_URL: Symbol.for('USER_SERVER_CHANGE_EMAIL_URL'),
|
||||
REDIS_EVENTS_CHANNEL: Symbol.for('REDIS_EVENTS_CHANNEL'),
|
||||
NEW_RELIC_ENABLED: Symbol.for('NEW_RELIC_ENABLED'),
|
||||
SYNCING_SERVER_URL: Symbol.for('SYNCING_SERVER_URL'),
|
||||
VERSION: Symbol.for('VERSION'),
|
||||
|
||||
@@ -17,7 +17,7 @@ describe('VerifyAuthenticatorAuthenticationResponse', () => {
|
||||
authenticatorRepository,
|
||||
authenticatorChallengeRepository,
|
||||
'standardnotes.com',
|
||||
'https://app.standardnotes.com',
|
||||
['localhost', 'https://app.standardnotes.com'],
|
||||
true,
|
||||
)
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ export class VerifyAuthenticatorAuthenticationResponse implements UseCaseInterfa
|
||||
private authenticatorRepository: AuthenticatorRepositoryInterface,
|
||||
private authenticatorChallengeRepository: AuthenticatorChallengeRepositoryInterface,
|
||||
private relyingPartyId: string,
|
||||
private expectedOrigin: string,
|
||||
private expectedOrigin: string[],
|
||||
private requireUserVerification: boolean,
|
||||
) {}
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ describe('VerifyAuthenticatorRegistrationResponse', () => {
|
||||
authenticatorRepository,
|
||||
authenticatorChallengeRepository,
|
||||
'standardnotes.com',
|
||||
'https://app.standardnotes.com',
|
||||
['localhost', 'https://app.standardnotes.com'],
|
||||
true,
|
||||
)
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ export class VerifyAuthenticatorRegistrationResponse implements UseCaseInterface
|
||||
private authenticatorRepository: AuthenticatorRepositoryInterface,
|
||||
private authenticatorChallengeRepository: AuthenticatorChallengeRepositoryInterface,
|
||||
private relyingPartyId: string,
|
||||
private expectedOrigin: string,
|
||||
private expectedOrigin: string[],
|
||||
private requireUserVerification: boolean,
|
||||
) {}
|
||||
|
||||
|
||||
@@ -5,7 +5,6 @@ VERSION=development
|
||||
PORT=3000
|
||||
|
||||
REDIS_URL=redis://cache
|
||||
REDIS_EVENTS_CHANNEL=events
|
||||
|
||||
VALET_TOKEN_SECRET=change-me-!
|
||||
|
||||
|
||||
@@ -3,6 +3,22 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [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
|
||||
|
||||
* performance of startup sequence in supervisor controlled self-hosting setup ([5bbdc7e](https://github.com/standardnotes/files/commit/5bbdc7e426c436b17dc130e3c6d9163080561c76))
|
||||
|
||||
## [1.9.16](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.9.15...@standardnotes/files-server@1.9.16) (2023-02-09)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* optimize memory usage ([e96fd6d](https://github.com/standardnotes/files/commit/e96fd6d69e1252842b5c91b1bedefa36e5d4a232))
|
||||
|
||||
## [1.9.15](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.9.14...@standardnotes/files-server@1.9.15) (2023-02-06)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/files-server
|
||||
|
||||
## [1.9.14](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.9.13...@standardnotes/files-server@1.9.14) (2023-01-30)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
13
packages/files/docker/wait-for.sh
Executable file
13
packages/files/docker/wait-for.sh
Executable file
@@ -0,0 +1,13 @@
|
||||
#!/bin/bash
|
||||
|
||||
WAIT_FOR_HOST="$1"
|
||||
shift
|
||||
WAIT_FOR_PORT="$1"
|
||||
shift
|
||||
|
||||
while ! nc -vz $WAIT_FOR_HOST $WAIT_FOR_PORT; do
|
||||
echo "$WAIT_FOR_HOST:$WAIT_FOR_PORT is unavailable yet - waiting for it to start"
|
||||
sleep 10
|
||||
done
|
||||
|
||||
echo "$WAIT_FOR_HOST:$WAIT_FOR_PORT is up. Proceeding to startup."
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/files-server",
|
||||
"version": "1.9.14",
|
||||
"version": "1.9.17",
|
||||
"engines": {
|
||||
"node": ">=18.0.0 <19.0.0"
|
||||
},
|
||||
@@ -20,8 +20,12 @@
|
||||
"lint": "eslint . --ext .ts",
|
||||
"pretest": "yarn lint && yarn build",
|
||||
"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",
|
||||
"supervisor:start": "yarn wait-for:auth && yarn node dist/bin/server.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/*'"
|
||||
},
|
||||
"dependencies": {
|
||||
|
||||
@@ -14,9 +14,6 @@ import { Timer, TimerInterface } from '@standardnotes/time'
|
||||
import { DomainEventFactoryInterface } from '../Domain/Event/DomainEventFactoryInterface'
|
||||
import { DomainEventFactory } from '../Domain/Event/DomainEventFactory'
|
||||
import {
|
||||
RedisDomainEventPublisher,
|
||||
RedisDomainEventSubscriberFactory,
|
||||
RedisEventMessageHandler,
|
||||
SNSDomainEventPublisher,
|
||||
SQSDomainEventSubscriberFactory,
|
||||
SQSEventMessageHandler,
|
||||
@@ -61,13 +58,12 @@ export class ContainerConfigLoader {
|
||||
container.bind(TYPES.S3_BUCKET_NAME).toConstantValue(env.get('S3_BUCKET_NAME', true))
|
||||
container.bind(TYPES.S3_AWS_REGION).toConstantValue(env.get('S3_AWS_REGION', true))
|
||||
container.bind(TYPES.VALET_TOKEN_SECRET).toConstantValue(env.get('VALET_TOKEN_SECRET'))
|
||||
container.bind(TYPES.SNS_TOPIC_ARN).toConstantValue(env.get('SNS_TOPIC_ARN', true))
|
||||
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.REDIS_URL).toConstantValue(env.get('REDIS_URL'))
|
||||
container.bind(TYPES.REDIS_EVENTS_CHANNEL).toConstantValue(env.get('REDIS_EVENTS_CHANNEL'))
|
||||
container.bind(TYPES.MAX_CHUNK_BYTES).toConstantValue(+env.get('MAX_CHUNK_BYTES'))
|
||||
container.bind(TYPES.VERSION).toConstantValue(env.get('VERSION'))
|
||||
container.bind(TYPES.SQS_QUEUE_URL).toConstantValue(env.get('SQS_QUEUE_URL', true))
|
||||
container.bind(TYPES.SQS_QUEUE_URL).toConstantValue(env.get('SQS_QUEUE_URL'))
|
||||
container
|
||||
.bind(TYPES.FILE_UPLOAD_PATH)
|
||||
.toConstantValue(env.get('FILE_UPLOAD_PATH', true) ?? `${__dirname}/../../uploads`)
|
||||
@@ -161,17 +157,9 @@ export class ContainerConfigLoader {
|
||||
// repositories
|
||||
container.bind<UploadRepositoryInterface>(TYPES.UploadRepository).to(RedisUploadRepository)
|
||||
|
||||
if (env.get('SNS_TOPIC_ARN', true)) {
|
||||
container
|
||||
.bind<SNSDomainEventPublisher>(TYPES.DomainEventPublisher)
|
||||
.toConstantValue(new SNSDomainEventPublisher(container.get(TYPES.SNS), container.get(TYPES.SNS_TOPIC_ARN)))
|
||||
} else {
|
||||
container
|
||||
.bind<RedisDomainEventPublisher>(TYPES.DomainEventPublisher)
|
||||
.toConstantValue(
|
||||
new RedisDomainEventPublisher(container.get(TYPES.Redis), container.get(TYPES.REDIS_EVENTS_CHANNEL)),
|
||||
)
|
||||
}
|
||||
container
|
||||
.bind<SNSDomainEventPublisher>(TYPES.DomainEventPublisher)
|
||||
.toConstantValue(new SNSDomainEventPublisher(container.get(TYPES.SNS), container.get(TYPES.SNS_TOPIC_ARN)))
|
||||
|
||||
// Handlers
|
||||
container
|
||||
@@ -189,37 +177,22 @@ export class ContainerConfigLoader {
|
||||
],
|
||||
])
|
||||
|
||||
if (env.get('SQS_QUEUE_URL', true)) {
|
||||
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),
|
||||
),
|
||||
)
|
||||
} else {
|
||||
container
|
||||
.bind<DomainEventMessageHandlerInterface>(TYPES.DomainEventMessageHandler)
|
||||
.toConstantValue(new RedisEventMessageHandler(eventHandlers, container.get(TYPES.Logger)))
|
||||
container
|
||||
.bind<DomainEventSubscriberFactoryInterface>(TYPES.DomainEventSubscriberFactory)
|
||||
.toConstantValue(
|
||||
new RedisDomainEventSubscriberFactory(
|
||||
container.get(TYPES.Redis),
|
||||
container.get(TYPES.DomainEventMessageHandler),
|
||||
container.get(TYPES.REDIS_EVENTS_CHANNEL),
|
||||
),
|
||||
)
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
@@ -40,7 +40,6 @@ const TYPES = {
|
||||
SQS_AWS_REGION: Symbol.for('SQS_AWS_REGION'),
|
||||
VALET_TOKEN_SECRET: Symbol.for('VALET_TOKEN_SECRET'),
|
||||
REDIS_URL: Symbol.for('REDIS_URL'),
|
||||
REDIS_EVENTS_CHANNEL: Symbol.for('REDIS_EVENTS_CHANNEL'),
|
||||
MAX_CHUNK_BYTES: Symbol.for('MAX_CHUNK_BYTES'),
|
||||
VERSION: Symbol.for('VERSION'),
|
||||
NEW_RELIC_ENABLED: Symbol.for('NEW_RELIC_ENABLED'),
|
||||
|
||||
@@ -22,8 +22,6 @@ SQS_AWS_REGION=
|
||||
S3_AWS_REGION=
|
||||
S3_BACKUP_BUCKET_NAME=
|
||||
|
||||
REDIS_EVENTS_CHANNEL=revisions
|
||||
|
||||
# (Optional) New Relic Setup
|
||||
NEW_RELIC_ENABLED=false
|
||||
NEW_RELIC_APP_NAME="Revisions Server"
|
||||
|
||||
@@ -3,6 +3,45 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [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)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* performance of startup sequence in supervisor controlled self-hosting setup ([5bbdc7e](https://github.com/standardnotes/server/commit/5bbdc7e426c436b17dc130e3c6d9163080561c76))
|
||||
|
||||
## [1.10.29](https://github.com/standardnotes/server/compare/@standardnotes/revisions-server@1.10.28...@standardnotes/revisions-server@1.10.29) (2023-02-09)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* optimize memory usage ([e96fd6d](https://github.com/standardnotes/server/commit/e96fd6d69e1252842b5c91b1bedefa36e5d4a232))
|
||||
|
||||
## [1.10.28](https://github.com/standardnotes/server/compare/@standardnotes/revisions-server@1.10.27...@standardnotes/revisions-server@1.10.28) (2023-02-06)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/revisions-server
|
||||
|
||||
## [1.10.27](https://github.com/standardnotes/server/compare/@standardnotes/revisions-server@1.10.26...@standardnotes/revisions-server@1.10.27) (2023-01-30)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
@@ -4,22 +4,21 @@ import 'newrelic'
|
||||
|
||||
import * as Sentry from '@sentry/node'
|
||||
|
||||
import '../src/Infra/InversifyExpress/InversifyExpressRevisionsController'
|
||||
import '../src/Infra/InversifyExpress/InversifyExpressHealthCheckController'
|
||||
|
||||
import * as cors from 'cors'
|
||||
import { urlencoded, json, Request, Response, NextFunction, RequestHandler, ErrorRequestHandler } from 'express'
|
||||
import * as winston from 'winston'
|
||||
|
||||
import { InversifyExpressServer } from 'inversify-express-utils'
|
||||
import { ContainerConfigLoader } from '../src/Bootstrap/Container'
|
||||
import TYPES from '../src/Bootstrap/Types'
|
||||
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) => {
|
||||
const env: Env = new Env()
|
||||
env.load()
|
||||
const env: Env = container.get(TYPES.Env)
|
||||
|
||||
const server = new InversifyExpressServer(container)
|
||||
|
||||
|
||||
@@ -1,15 +1,13 @@
|
||||
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 { DomainEventSubscriberFactoryInterface } from '@standardnotes/domain-events'
|
||||
|
||||
const container = new ContainerConfigLoader()
|
||||
import TYPES from '../src/Bootstrap/Types'
|
||||
import { Env } from '../src/Bootstrap/Env'
|
||||
import { WorkerContainerConfigLoader } from '../src/Bootstrap/WorkerContainerConfigLoader'
|
||||
|
||||
const container = new WorkerContainerConfigLoader()
|
||||
void container.load().then((container) => {
|
||||
const env: Env = new Env()
|
||||
env.load()
|
||||
@@ -20,6 +18,4 @@ void container.load().then((container) => {
|
||||
|
||||
const subscriberFactory: DomainEventSubscriberFactoryInterface = container.get(TYPES.DomainEventSubscriberFactory)
|
||||
subscriberFactory.create().start()
|
||||
|
||||
setInterval(() => logger.info('Alive and kicking!'), 20 * 60 * 1000)
|
||||
})
|
||||
|
||||
13
packages/revisions/docker/wait-for.sh
Executable file
13
packages/revisions/docker/wait-for.sh
Executable file
@@ -0,0 +1,13 @@
|
||||
#!/bin/bash
|
||||
|
||||
WAIT_FOR_HOST="$1"
|
||||
shift
|
||||
WAIT_FOR_PORT="$1"
|
||||
shift
|
||||
|
||||
while ! nc -vz $WAIT_FOR_HOST $WAIT_FOR_PORT; do
|
||||
echo "$WAIT_FOR_HOST:$WAIT_FOR_PORT is unavailable yet - waiting for it to start"
|
||||
sleep 10
|
||||
done
|
||||
|
||||
echo "$WAIT_FOR_HOST:$WAIT_FOR_PORT is up. Proceeding to startup."
|
||||
@@ -4,8 +4,10 @@ export class init1669113322388 implements MigrationInterface {
|
||||
name = 'init1669113322388'
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await this.syncSchemaBetweenLegacyRevisions(queryRunner)
|
||||
|
||||
await queryRunner.query(
|
||||
'CREATE TABLE `revisions` (`uuid` varchar(36) NOT NULL, `item_uuid` varchar(36) NOT NULL, `user_uuid` varchar(36) NOT NULL, `content` mediumtext NULL, `content_type` varchar(255) NULL, `items_key_id` varchar(255) NULL, `enc_item_key` text NULL, `auth_hash` varchar(255) NULL, `creation_date` date NULL, `created_at` datetime(6) NULL, `updated_at` datetime(6) NULL, INDEX `item_uuid` (`item_uuid`), INDEX `user_uuid` (`user_uuid`), INDEX `creation_date` (`creation_date`), INDEX `created_at` (`created_at`), PRIMARY KEY (`uuid`)) ENGINE=InnoDB',
|
||||
'CREATE TABLE IF NOT EXISTS `revisions` (`uuid` varchar(36) NOT NULL, `item_uuid` varchar(36) NOT NULL, `user_uuid` varchar(36) NOT NULL, `content` mediumtext NULL, `content_type` varchar(255) NULL, `items_key_id` varchar(255) NULL, `enc_item_key` text NULL, `auth_hash` varchar(255) NULL, `creation_date` date NULL, `created_at` datetime(6) NULL, `updated_at` datetime(6) NULL, INDEX `item_uuid` (`item_uuid`), INDEX `user_uuid` (`user_uuid`), INDEX `creation_date` (`creation_date`), INDEX `created_at` (`created_at`), PRIMARY KEY (`uuid`)) ENGINE=InnoDB',
|
||||
)
|
||||
}
|
||||
|
||||
@@ -16,4 +18,16 @@ export class init1669113322388 implements MigrationInterface {
|
||||
await queryRunner.query('DROP INDEX `item_uuid` ON `revisions`')
|
||||
await queryRunner.query('DROP TABLE `revisions`')
|
||||
}
|
||||
|
||||
private async syncSchemaBetweenLegacyRevisions(queryRunner: QueryRunner): Promise<void> {
|
||||
const revisionsTableExistsQueryResult = await queryRunner.manager.query(
|
||||
'SELECT COUNT(*) as count FROM information_schema.tables WHERE table_schema = DATABASE() AND table_name = "revisions"',
|
||||
)
|
||||
const revisionsTableExists = revisionsTableExistsQueryResult[0].count === 1
|
||||
if (!revisionsTableExists) {
|
||||
return
|
||||
}
|
||||
|
||||
await queryRunner.query('ALTER TABLE `revisions` ADD COLUMN `user_uuid` varchar(36) NULL')
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,8 +4,21 @@ export class removeDateIndexes1669636497932 implements MigrationInterface {
|
||||
name = 'removeDateIndexes1669636497932'
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query('DROP INDEX `created_at` ON `revisions`')
|
||||
await queryRunner.query('DROP INDEX `creation_date` ON `revisions`')
|
||||
const indexRevisionsOnCreatedAt = await queryRunner.manager.query(
|
||||
'SHOW INDEX FROM `revisions` where `key_name` = "created_at"',
|
||||
)
|
||||
const indexRevisionsOnCreatedAtExist = indexRevisionsOnCreatedAt && indexRevisionsOnCreatedAt.length > 0
|
||||
if (indexRevisionsOnCreatedAtExist) {
|
||||
await queryRunner.query('DROP INDEX `created_at` ON `revisions`')
|
||||
}
|
||||
|
||||
const indexRevisionsOnCreationDate = await queryRunner.manager.query(
|
||||
'SHOW INDEX FROM `revisions` where `key_name` = "creation_date"',
|
||||
)
|
||||
const indexRevisionsOnCreationDateAtExist = indexRevisionsOnCreationDate && indexRevisionsOnCreationDate.length > 0
|
||||
if (indexRevisionsOnCreationDateAtExist) {
|
||||
await queryRunner.query('DROP INDEX `creation_date` ON `revisions`')
|
||||
}
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/revisions-server",
|
||||
"version": "1.10.27",
|
||||
"version": "1.11.2",
|
||||
"engines": {
|
||||
"node": ">=18.0.0 <19.0.0"
|
||||
},
|
||||
@@ -19,7 +19,11 @@
|
||||
"lint:fix": "eslint . --ext .ts --fix",
|
||||
"pretest": "yarn lint && yarn build",
|
||||
"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",
|
||||
"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"
|
||||
},
|
||||
"dependencies": {
|
||||
@@ -32,15 +36,12 @@
|
||||
"@standardnotes/domain-core": "workspace:^",
|
||||
"@standardnotes/domain-events": "workspace:*",
|
||||
"@standardnotes/domain-events-infra": "workspace:*",
|
||||
"@standardnotes/security": "workspace:^",
|
||||
"@standardnotes/time": "workspace:^",
|
||||
"cors": "2.8.5",
|
||||
"dotenv": "^16.0.1",
|
||||
"express": "^4.18.2",
|
||||
"helmet": "^6.0.0",
|
||||
"inversify": "^6.0.1",
|
||||
"inversify-express-utils": "^6.4.3",
|
||||
"ioredis": "^5.2.4",
|
||||
"mysql2": "^3.0.1",
|
||||
"newrelic": "^9.8.0",
|
||||
"reflect-metadata": "0.1.13",
|
||||
@@ -52,7 +53,6 @@
|
||||
"@types/dotenv": "^8.2.0",
|
||||
"@types/express": "^4.17.14",
|
||||
"@types/inversify-express-utils": "^2.0.0",
|
||||
"@types/ioredis": "^5.0.0",
|
||||
"@types/jest": "^29.1.1",
|
||||
"@types/newrelic": "^9.4.0",
|
||||
"@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,301 +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 {
|
||||
RedisDomainEventSubscriberFactory,
|
||||
RedisEventMessageHandler,
|
||||
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', true))
|
||||
container.bind(TYPES.REDIS_EVENTS_CHANNEL).toConstantValue(env.get('REDIS_EVENTS_CHANNEL'))
|
||||
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)],
|
||||
])
|
||||
|
||||
if (env.get('SQS_QUEUE_URL', true)) {
|
||||
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),
|
||||
),
|
||||
)
|
||||
} else {
|
||||
container
|
||||
.bind<DomainEventMessageHandlerInterface>(TYPES.DomainEventMessageHandler)
|
||||
.toConstantValue(new RedisEventMessageHandler(eventHandlers, container.get(TYPES.Logger)))
|
||||
container
|
||||
.bind<DomainEventSubscriberFactoryInterface>(TYPES.DomainEventSubscriberFactory)
|
||||
.toConstantValue(
|
||||
new RedisDomainEventSubscriberFactory(
|
||||
container.get(TYPES.Redis),
|
||||
container.get(TYPES.DomainEventMessageHandler),
|
||||
container.get(TYPES.REDIS_EVENTS_CHANNEL),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
return container
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,5 @@
|
||||
import { config, DotenvParseOutput } from 'dotenv'
|
||||
import { injectable } from 'inversify'
|
||||
|
||||
@injectable()
|
||||
export class Env {
|
||||
private env?: DotenvParseOutput
|
||||
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
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'
|
||||
|
||||
export class ServerContainerConfigLoader extends CommonContainerConfigLoader {
|
||||
override async load(): Promise<Container> {
|
||||
const container = await super.load()
|
||||
|
||||
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))
|
||||
})
|
||||
|
||||
// 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),
|
||||
)
|
||||
})
|
||||
|
||||
return container
|
||||
}
|
||||
}
|
||||
19
packages/revisions/src/Bootstrap/SimpleContainer.ts
Normal file
19
packages/revisions/src/Bootstrap/SimpleContainer.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
export class SimpleContainer {
|
||||
private services: Map<symbol, unknown> = new Map()
|
||||
|
||||
constructor() {
|
||||
this.services = new Map()
|
||||
}
|
||||
|
||||
public get<T>(key: symbol): T {
|
||||
if (!this.services.has(key)) {
|
||||
throw new Error(`Service ${key.toString()} not found`)
|
||||
}
|
||||
|
||||
return this.services.get(key) as T
|
||||
}
|
||||
|
||||
public set(key: symbol, value: unknown): void {
|
||||
this.services.set(key, value)
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
const TYPES = {
|
||||
DBConnection: Symbol.for('DBConnection'),
|
||||
Logger: Symbol.for('Logger'),
|
||||
Redis: Symbol.for('Redis'),
|
||||
SQS: Symbol.for('SQS'),
|
||||
S3: Symbol.for('S3'),
|
||||
Env: Symbol.for('Env'),
|
||||
// Map
|
||||
RevisionMetadataPersistenceMapper: Symbol.for('RevisionMetadataPersistenceMapper'),
|
||||
RevisionPersistenceMapper: Symbol.for('RevisionPersistenceMapper'),
|
||||
@@ -16,11 +16,8 @@ const TYPES = {
|
||||
RevisionRepository: Symbol.for('RevisionRepository'),
|
||||
DumpRepository: Symbol.for('DumpRepository'),
|
||||
// env vars
|
||||
REDIS_URL: Symbol.for('REDIS_URL'),
|
||||
SQS_QUEUE_URL: Symbol.for('SQS_QUEUE_URL'),
|
||||
SQS_AWS_REGION: Symbol.for('SQS_AWS_REGION'),
|
||||
REDIS_EVENTS_CHANNEL: Symbol.for('REDIS_EVENTS_CHANNEL'),
|
||||
AUTH_JWT_SECRET: Symbol.for('AUTH_JWT_SECRET'),
|
||||
S3_AWS_REGION: Symbol.for('S3_AWS_REGION'),
|
||||
S3_BACKUP_BUCKET_NAME: Symbol.for('S3_BACKUP_BUCKET_NAME'),
|
||||
NEW_RELIC_ENABLED: Symbol.for('NEW_RELIC_ENABLED'),
|
||||
@@ -43,8 +40,6 @@ const TYPES = {
|
||||
DomainEventSubscriberFactory: Symbol.for('DomainEventSubscriberFactory'),
|
||||
DomainEventMessageHandler: Symbol.for('DomainEventMessageHandler'),
|
||||
Timer: Symbol.for('Timer'),
|
||||
// Middleware
|
||||
ApiGatewayAuthMiddleware: Symbol.for('ApiGatewayAuthMiddleware'),
|
||||
}
|
||||
|
||||
export default TYPES
|
||||
|
||||
171
packages/revisions/src/Bootstrap/WorkerContainerConfigLoader.ts
Normal file
171
packages/revisions/src/Bootstrap/WorkerContainerConfigLoader.ts
Normal file
@@ -0,0 +1,171 @@
|
||||
import { SQSClient, SQSClientConfig } from '@aws-sdk/client-sqs'
|
||||
import { S3Client } from '@aws-sdk/client-s3'
|
||||
import { DomainEventHandlerInterface } from '@standardnotes/domain-events'
|
||||
import {
|
||||
SQSDomainEventSubscriberFactory,
|
||||
SQSEventMessageHandler,
|
||||
SQSNewRelicEventMessageHandler,
|
||||
} from '@standardnotes/domain-events-infra'
|
||||
import * as winston from 'winston'
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
const newrelicFormatter = require('@newrelic/winston-enricher')
|
||||
|
||||
import TYPES from './Types'
|
||||
import { RevisionItemStringMapper } from '../Mapping/RevisionItemStringMapper'
|
||||
import { ItemDumpedEventHandler } from '../Domain/Handler/ItemDumpedEventHandler'
|
||||
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 { Env } from './Env'
|
||||
import { SimpleContainer } from './SimpleContainer'
|
||||
import { MySQLRevisionRepository } from '../Infra/MySQL/MySQLRevisionRepository'
|
||||
import { AppDataSource } from './DataSource'
|
||||
import { TypeORMRevision } from '../Infra/TypeORM/TypeORMRevision'
|
||||
import { RevisionPersistenceMapper } from '../Mapping/RevisionPersistenceMapper'
|
||||
import { RevisionMetadataPersistenceMapper } from '../Mapping/RevisionMetadataPersistenceMapper'
|
||||
|
||||
export class WorkerContainerConfigLoader {
|
||||
async load(): Promise<SimpleContainer> {
|
||||
const env: Env = new Env()
|
||||
env.load()
|
||||
|
||||
await AppDataSource.initialize()
|
||||
|
||||
const simpleContainer = new SimpleContainer()
|
||||
|
||||
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' })],
|
||||
})
|
||||
|
||||
simpleContainer.set(TYPES.Logger, logger)
|
||||
|
||||
simpleContainer.set(TYPES.RevisionMetadataPersistenceMapper, new RevisionMetadataPersistenceMapper())
|
||||
|
||||
simpleContainer.set(TYPES.RevisionPersistenceMapper, new RevisionPersistenceMapper())
|
||||
|
||||
simpleContainer.set(TYPES.ORMRevisionRepository, AppDataSource.getRepository(TypeORMRevision))
|
||||
|
||||
simpleContainer.set(
|
||||
TYPES.RevisionRepository,
|
||||
new MySQLRevisionRepository(
|
||||
simpleContainer.get(TYPES.ORMRevisionRepository),
|
||||
simpleContainer.get(TYPES.RevisionMetadataPersistenceMapper),
|
||||
simpleContainer.get(TYPES.RevisionPersistenceMapper),
|
||||
simpleContainer.get(TYPES.Logger),
|
||||
),
|
||||
)
|
||||
|
||||
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),
|
||||
}
|
||||
}
|
||||
|
||||
simpleContainer.set(TYPES.SQS, 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),
|
||||
})
|
||||
}
|
||||
|
||||
simpleContainer.set(TYPES.S3, s3Client)
|
||||
|
||||
simpleContainer.set(TYPES.RevisionItemStringMapper, new RevisionItemStringMapper())
|
||||
|
||||
simpleContainer.set(TYPES.NEW_RELIC_ENABLED, env.get('NEW_RELIC_ENABLED', true))
|
||||
simpleContainer.set(TYPES.VERSION, env.get('VERSION'))
|
||||
simpleContainer.set(TYPES.SQS_QUEUE_URL, env.get('SQS_QUEUE_URL'))
|
||||
simpleContainer.set(TYPES.S3_AWS_REGION, env.get('S3_AWS_REGION', true))
|
||||
simpleContainer.set(TYPES.S3_BACKUP_BUCKET_NAME, env.get('S3_BACKUP_BUCKET_NAME', true))
|
||||
|
||||
const dumpRepository = env.get('S3_AWS_REGION', true)
|
||||
? new S3DumpRepository(
|
||||
simpleContainer.get(TYPES.S3_BACKUP_BUCKET_NAME),
|
||||
simpleContainer.get(TYPES.S3),
|
||||
simpleContainer.get(TYPES.RevisionItemStringMapper),
|
||||
)
|
||||
: new FSDumpRepository(simpleContainer.get(TYPES.RevisionItemStringMapper))
|
||||
|
||||
simpleContainer.set(TYPES.DumpRepository, dumpRepository)
|
||||
|
||||
simpleContainer.set(TYPES.CopyRevisions, new CopyRevisions(simpleContainer.get(TYPES.RevisionRepository)))
|
||||
|
||||
simpleContainer.set(
|
||||
TYPES.ItemDumpedEventHandler,
|
||||
new ItemDumpedEventHandler(
|
||||
simpleContainer.get(TYPES.DumpRepository),
|
||||
simpleContainer.get(TYPES.RevisionRepository),
|
||||
),
|
||||
)
|
||||
|
||||
simpleContainer.set(
|
||||
TYPES.AccountDeletionRequestedEventHandler,
|
||||
new AccountDeletionRequestedEventHandler(
|
||||
simpleContainer.get(TYPES.RevisionRepository),
|
||||
simpleContainer.get(TYPES.Logger),
|
||||
),
|
||||
)
|
||||
|
||||
simpleContainer.set(
|
||||
TYPES.RevisionsCopyRequestedEventHandler,
|
||||
new RevisionsCopyRequestedEventHandler(
|
||||
simpleContainer.get(TYPES.CopyRevisions),
|
||||
simpleContainer.get(TYPES.Logger),
|
||||
),
|
||||
)
|
||||
|
||||
simpleContainer.set(
|
||||
TYPES.RevisionsOwnershipUpdateRequestedEventHandler,
|
||||
new RevisionsOwnershipUpdateRequestedEventHandler(simpleContainer.get(TYPES.RevisionRepository)),
|
||||
)
|
||||
|
||||
const eventHandlers: Map<string, DomainEventHandlerInterface> = new Map([
|
||||
['ITEM_DUMPED', simpleContainer.get(TYPES.ItemDumpedEventHandler)],
|
||||
['ACCOUNT_DELETION_REQUESTED', simpleContainer.get(TYPES.AccountDeletionRequestedEventHandler)],
|
||||
['REVISIONS_COPY_REQUESTED', simpleContainer.get(TYPES.RevisionsCopyRequestedEventHandler)],
|
||||
[
|
||||
'REVISIONS_OWNERSHIP_UPDATE_REQUESTED',
|
||||
simpleContainer.get(TYPES.RevisionsOwnershipUpdateRequestedEventHandler),
|
||||
],
|
||||
])
|
||||
|
||||
const handler =
|
||||
env.get('NEW_RELIC_ENABLED', true) === 'true'
|
||||
? new SQSNewRelicEventMessageHandler(eventHandlers, simpleContainer.get(TYPES.Logger))
|
||||
: new SQSEventMessageHandler(eventHandlers, simpleContainer.get(TYPES.Logger))
|
||||
|
||||
simpleContainer.set(TYPES.DomainEventMessageHandler, handler)
|
||||
|
||||
simpleContainer.set(
|
||||
TYPES.DomainEventSubscriberFactory,
|
||||
new SQSDomainEventSubscriberFactory(
|
||||
simpleContainer.get(TYPES.SQS),
|
||||
simpleContainer.get(TYPES.SQS_QUEUE_URL),
|
||||
simpleContainer.get(TYPES.DomainEventMessageHandler),
|
||||
),
|
||||
)
|
||||
|
||||
return simpleContainer
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
import 'reflect-metadata'
|
||||
|
||||
import { AccountDeletionRequestedEvent } from '@standardnotes/domain-events'
|
||||
import { Logger } from 'winston'
|
||||
|
||||
import { AccountDeletionRequestedEventHandler } from './AccountDeletionRequestedEventHandler'
|
||||
import { RevisionRepositoryInterface } from '../Revision/RevisionRepositoryInterface'
|
||||
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
import { CrossServiceTokenData, TokenDecoderInterface } from '@standardnotes/security'
|
||||
import { NextFunction, Request, Response } from 'express'
|
||||
import { inject, injectable } from 'inversify'
|
||||
import { BaseMiddleware } from 'inversify-express-utils'
|
||||
import { Logger } from 'winston'
|
||||
|
||||
import TYPES from '../../Bootstrap/Types'
|
||||
|
||||
@injectable()
|
||||
export class InversifyExpressApiGatewayAuthMiddleware extends BaseMiddleware {
|
||||
constructor(
|
||||
@inject(TYPES.CrossServiceTokenDecoder) private tokenDecoder: TokenDecoderInterface<CrossServiceTokenData>,
|
||||
@inject(TYPES.Logger) private logger: Logger,
|
||||
) {
|
||||
super()
|
||||
}
|
||||
|
||||
async handler(request: Request, response: Response, next: NextFunction): Promise<void> {
|
||||
try {
|
||||
if (!request.headers['x-auth-token']) {
|
||||
this.logger.debug('ApiGatewayAuthMiddleware missing x-auth-token header.')
|
||||
|
||||
response.status(401).send({
|
||||
error: {
|
||||
tag: 'invalid-auth',
|
||||
message: 'Invalid login credentials.',
|
||||
},
|
||||
})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
const token: CrossServiceTokenData | undefined = this.tokenDecoder.decodeToken(
|
||||
request.headers['x-auth-token'] as string,
|
||||
)
|
||||
|
||||
if (token === undefined) {
|
||||
this.logger.debug('ApiGatewayAuthMiddleware authentication failure.')
|
||||
|
||||
response.status(401).send({
|
||||
error: {
|
||||
tag: 'invalid-auth',
|
||||
message: 'Invalid login credentials.',
|
||||
},
|
||||
})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
response.locals.user = token.user
|
||||
response.locals.roles = token.roles
|
||||
response.locals.session = token.session
|
||||
response.locals.readOnlyAccess = token.session?.readonly_access ?? false
|
||||
|
||||
return next()
|
||||
} catch (error) {
|
||||
return next(error)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
import { controller, httpGet } from 'inversify-express-utils'
|
||||
import { BaseHttpController, controller, httpGet } from 'inversify-express-utils'
|
||||
|
||||
@controller('/healthcheck')
|
||||
export class InversifyExpressHealthCheckController {
|
||||
export class InversifyExpressHealthCheckController extends BaseHttpController {
|
||||
@httpGet('/')
|
||||
public async get(): Promise<string> {
|
||||
return 'OK'
|
||||
|
||||
@@ -5,7 +5,7 @@ import { inject } from 'inversify'
|
||||
import TYPES from '../../Bootstrap/Types'
|
||||
import { RevisionsController } from '../../Controller/RevisionsController'
|
||||
|
||||
@controller('/items/:itemUuid/revisions', TYPES.ApiGatewayAuthMiddleware)
|
||||
@controller('/items/:itemUuid/revisions')
|
||||
export class InversifyExpressRevisionsController extends BaseHttpController {
|
||||
constructor(@inject(TYPES.RevisionsController) private revisionsController: RevisionsController) {
|
||||
super()
|
||||
|
||||
@@ -11,7 +11,6 @@ DB_DEBUG_LEVEL=all # "all" | "query" | "schema" | "error" | "warn" | "info" | "l
|
||||
DB_MIGRATIONS_PATH=dist/migrations/*.js
|
||||
|
||||
REDIS_URL=redis://cache
|
||||
REDIS_EVENTS_CHANNEL=events
|
||||
|
||||
SNS_TOPIC_ARN=
|
||||
SNS_AWS_REGION=
|
||||
|
||||
@@ -3,6 +3,10 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [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
|
||||
|
||||
## [1.16.18](https://github.com/standardnotes/server/compare/@standardnotes/scheduler-server@1.16.17...@standardnotes/scheduler-server@1.16.18) (2023-01-30)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/scheduler-server",
|
||||
"version": "1.16.18",
|
||||
"version": "1.16.19",
|
||||
"engines": {
|
||||
"node": ">=18.0.0 <19.0.0"
|
||||
},
|
||||
|
||||
@@ -14,9 +14,6 @@ import TYPES from './Types'
|
||||
import { AppDataSource } from './DataSource'
|
||||
import { DomainEventFactory } from '../Domain/Event/DomainEventFactory'
|
||||
import {
|
||||
RedisDomainEventPublisher,
|
||||
RedisDomainEventSubscriberFactory,
|
||||
RedisEventMessageHandler,
|
||||
SNSDomainEventPublisher,
|
||||
SQSDomainEventSubscriberFactory,
|
||||
SQSEventMessageHandler,
|
||||
@@ -110,10 +107,9 @@ export class ContainerConfigLoader {
|
||||
|
||||
// env vars
|
||||
container.bind(TYPES.REDIS_URL).toConstantValue(env.get('REDIS_URL'))
|
||||
container.bind(TYPES.SNS_TOPIC_ARN).toConstantValue(env.get('SNS_TOPIC_ARN', true))
|
||||
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', true))
|
||||
container.bind(TYPES.REDIS_EVENTS_CHANNEL).toConstantValue(env.get('REDIS_EVENTS_CHANNEL'))
|
||||
container.bind(TYPES.SQS_QUEUE_URL).toConstantValue(env.get('SQS_QUEUE_URL'))
|
||||
container.bind(TYPES.NEW_RELIC_ENABLED).toConstantValue(env.get('NEW_RELIC_ENABLED', true))
|
||||
|
||||
// Repositories
|
||||
@@ -145,17 +141,9 @@ export class ContainerConfigLoader {
|
||||
container.bind<TimerInterface>(TYPES.Timer).toConstantValue(new Timer())
|
||||
container.bind<JobDoneInterpreterInterface>(TYPES.JobDoneInterpreter).to(JobDoneInterpreter)
|
||||
|
||||
if (env.get('SNS_TOPIC_ARN', true)) {
|
||||
container
|
||||
.bind<SNSDomainEventPublisher>(TYPES.DomainEventPublisher)
|
||||
.toConstantValue(new SNSDomainEventPublisher(container.get(TYPES.SNS), container.get(TYPES.SNS_TOPIC_ARN)))
|
||||
} else {
|
||||
container
|
||||
.bind<RedisDomainEventPublisher>(TYPES.DomainEventPublisher)
|
||||
.toConstantValue(
|
||||
new RedisDomainEventPublisher(container.get(TYPES.Redis), container.get(TYPES.REDIS_EVENTS_CHANNEL)),
|
||||
)
|
||||
}
|
||||
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([
|
||||
['PREDICATE_VERIFIED', container.get(TYPES.PredicateVerifiedEventHandler)],
|
||||
@@ -164,37 +152,22 @@ export class ContainerConfigLoader {
|
||||
['EXIT_DISCOUNT_APPLIED', container.get(TYPES.ExitDiscountAppliedEventHandler)],
|
||||
])
|
||||
|
||||
if (env.get('SQS_QUEUE_URL', true)) {
|
||||
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),
|
||||
),
|
||||
)
|
||||
} else {
|
||||
container
|
||||
.bind<DomainEventMessageHandlerInterface>(TYPES.DomainEventMessageHandler)
|
||||
.toConstantValue(new RedisEventMessageHandler(eventHandlers, container.get(TYPES.Logger)))
|
||||
container
|
||||
.bind<DomainEventSubscriberFactoryInterface>(TYPES.DomainEventSubscriberFactory)
|
||||
.toConstantValue(
|
||||
new RedisDomainEventSubscriberFactory(
|
||||
container.get(TYPES.Redis),
|
||||
container.get(TYPES.DomainEventMessageHandler),
|
||||
container.get(TYPES.REDIS_EVENTS_CHANNEL),
|
||||
),
|
||||
)
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@ const TYPES = {
|
||||
SNS_AWS_REGION: Symbol.for('SNS_AWS_REGION'),
|
||||
SQS_QUEUE_URL: Symbol.for('SQS_QUEUE_URL'),
|
||||
SQS_AWS_REGION: Symbol.for('SQS_AWS_REGION'),
|
||||
REDIS_EVENTS_CHANNEL: Symbol.for('REDIS_EVENTS_CHANNEL'),
|
||||
NEW_RELIC_ENABLED: Symbol.for('NEW_RELIC_ENABLED'),
|
||||
// Repositories
|
||||
PredicateRepository: Symbol.for('PredicateRepository'),
|
||||
|
||||
@@ -24,8 +24,6 @@ SQS_AWS_REGION=
|
||||
S3_AWS_REGION=
|
||||
S3_BACKUP_BUCKET_NAME=
|
||||
|
||||
REDIS_EVENTS_CHANNEL=events
|
||||
|
||||
INTERNAL_DNS_REROUTE_ENABLED=false
|
||||
EXTENSIONS_SERVER_URL=http://extensions-server:3004
|
||||
AUTH_SERVER_URL=http://auth:3000
|
||||
|
||||
@@ -3,6 +3,16 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [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
|
||||
|
||||
* optimize memory usage ([e96fd6d](https://github.com/standardnotes/syncing-server-js/commit/e96fd6d69e1252842b5c91b1bedefa36e5d4a232))
|
||||
|
||||
## [1.29.14](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.29.13...@standardnotes/syncing-server@1.29.14) (2023-02-06)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/syncing-server
|
||||
|
||||
## [1.29.13](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.29.12...@standardnotes/syncing-server@1.29.13) (2023-01-30)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
13
packages/syncing-server/docker/wait-for.sh
Executable file
13
packages/syncing-server/docker/wait-for.sh
Executable file
@@ -0,0 +1,13 @@
|
||||
#!/bin/bash
|
||||
|
||||
WAIT_FOR_HOST="$1"
|
||||
shift
|
||||
WAIT_FOR_PORT="$1"
|
||||
shift
|
||||
|
||||
while ! nc -vz $WAIT_FOR_HOST $WAIT_FOR_PORT; do
|
||||
echo "$WAIT_FOR_HOST:$WAIT_FOR_PORT is unavailable yet - waiting for it to start"
|
||||
sleep 10
|
||||
done
|
||||
|
||||
echo "$WAIT_FOR_HOST:$WAIT_FOR_PORT is up. Proceeding to startup."
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/syncing-server",
|
||||
"version": "1.29.13",
|
||||
"version": "1.29.15",
|
||||
"engines": {
|
||||
"node": ">=18.0.0 <19.0.0"
|
||||
},
|
||||
@@ -19,8 +19,14 @@
|
||||
"lint:fix": "eslint . --ext .ts --fix",
|
||||
"pretest": "yarn lint && yarn build",
|
||||
"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",
|
||||
"supervisor:start": "yarn wait-for:infra && yarn node dist/bin/server.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",
|
||||
"revisions-ownership": "yarn node dist/bin/revisions.js",
|
||||
"upgrade:snjs": "yarn ncu -u '@standardnotes/*'"
|
||||
|
||||
@@ -54,9 +54,6 @@ import { UuidFilter } from '../Domain/Item/SaveRule/UuidFilter'
|
||||
import { ContentTypeFilter } from '../Domain/Item/SaveRule/ContentTypeFilter'
|
||||
import { ContentFilter } from '../Domain/Item/SaveRule/ContentFilter'
|
||||
import {
|
||||
RedisDomainEventPublisher,
|
||||
RedisDomainEventSubscriberFactory,
|
||||
RedisEventMessageHandler,
|
||||
SNSDomainEventPublisher,
|
||||
SQSDomainEventSubscriberFactory,
|
||||
SQSEventMessageHandler,
|
||||
@@ -192,10 +189,9 @@ export class ContainerConfigLoader {
|
||||
|
||||
// env vars
|
||||
container.bind(TYPES.REDIS_URL).toConstantValue(env.get('REDIS_URL'))
|
||||
container.bind(TYPES.SNS_TOPIC_ARN).toConstantValue(env.get('SNS_TOPIC_ARN', true))
|
||||
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', true))
|
||||
container.bind(TYPES.REDIS_EVENTS_CHANNEL).toConstantValue(env.get('REDIS_EVENTS_CHANNEL'))
|
||||
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)
|
||||
@@ -277,17 +273,9 @@ export class ContainerConfigLoader {
|
||||
}
|
||||
container.bind<RevisionServiceInterface>(TYPES.RevisionService).to(RevisionService)
|
||||
|
||||
if (env.get('SNS_TOPIC_ARN', true)) {
|
||||
container
|
||||
.bind<SNSDomainEventPublisher>(TYPES.DomainEventPublisher)
|
||||
.toConstantValue(new SNSDomainEventPublisher(container.get(TYPES.SNS), container.get(TYPES.SNS_TOPIC_ARN)))
|
||||
} else {
|
||||
container
|
||||
.bind<RedisDomainEventPublisher>(TYPES.DomainEventPublisher)
|
||||
.toConstantValue(
|
||||
new RedisDomainEventPublisher(container.get(TYPES.Redis), container.get(TYPES.REDIS_EVENTS_CHANNEL)),
|
||||
)
|
||||
}
|
||||
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)],
|
||||
@@ -301,37 +289,22 @@ export class ContainerConfigLoader {
|
||||
['ITEM_REVISION_CREATION_REQUESTED', container.get(TYPES.ItemRevisionCreationRequestedEventHandler)],
|
||||
])
|
||||
|
||||
if (env.get('SQS_QUEUE_URL', true)) {
|
||||
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),
|
||||
),
|
||||
)
|
||||
} else {
|
||||
container
|
||||
.bind<DomainEventMessageHandlerInterface>(TYPES.DomainEventMessageHandler)
|
||||
.toConstantValue(new RedisEventMessageHandler(eventHandlers, container.get(TYPES.Logger)))
|
||||
container
|
||||
.bind<DomainEventSubscriberFactoryInterface>(TYPES.DomainEventSubscriberFactory)
|
||||
.toConstantValue(
|
||||
new RedisDomainEventSubscriberFactory(
|
||||
container.get(TYPES.Redis),
|
||||
container.get(TYPES.DomainEventMessageHandler),
|
||||
container.get(TYPES.REDIS_EVENTS_CHANNEL),
|
||||
),
|
||||
)
|
||||
}
|
||||
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)
|
||||
|
||||
|
||||
@@ -24,7 +24,6 @@ const TYPES = {
|
||||
SNS_AWS_REGION: Symbol.for('SNS_AWS_REGION'),
|
||||
SQS_QUEUE_URL: Symbol.for('SQS_QUEUE_URL'),
|
||||
SQS_AWS_REGION: Symbol.for('SQS_AWS_REGION'),
|
||||
REDIS_EVENTS_CHANNEL: Symbol.for('REDIS_EVENTS_CHANNEL'),
|
||||
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'),
|
||||
|
||||
@@ -13,8 +13,6 @@ SNS_AWS_REGION=
|
||||
SQS_QUEUE_URL=
|
||||
SQS_AWS_REGION=
|
||||
|
||||
REDIS_EVENTS_CHANNEL=events
|
||||
|
||||
WEB_SOCKET_CONNECTION_TOKEN_SECRET=
|
||||
WEB_SOCKET_CONNECTION_TOKEN_TTL=
|
||||
|
||||
|
||||
@@ -3,6 +3,10 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.5.20](https://github.com/standardnotes/server/compare/@standardnotes/websockets-server@1.5.19...@standardnotes/websockets-server@1.5.20) (2023-02-06)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/websockets-server
|
||||
|
||||
## [1.5.19](https://github.com/standardnotes/server/compare/@standardnotes/websockets-server@1.5.18...@standardnotes/websockets-server@1.5.19) (2023-01-30)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/websockets-server",
|
||||
"version": "1.5.19",
|
||||
"version": "1.5.20",
|
||||
"engines": {
|
||||
"node": ">=18.0.0 <19.0.0"
|
||||
},
|
||||
|
||||
@@ -18,8 +18,6 @@ import { AddWebSocketsConnection } from '../Domain/UseCase/AddWebSocketsConnecti
|
||||
import { RemoveWebSocketsConnection } from '../Domain/UseCase/RemoveWebSocketsConnection/RemoveWebSocketsConnection'
|
||||
import { WebSocketsClientMessenger } from '../Infra/WebSockets/WebSocketsClientMessenger'
|
||||
import {
|
||||
RedisDomainEventSubscriberFactory,
|
||||
RedisEventMessageHandler,
|
||||
SQSDomainEventSubscriberFactory,
|
||||
SQSEventMessageHandler,
|
||||
SQSNewRelicEventMessageHandler,
|
||||
@@ -110,8 +108,7 @@ export class ContainerConfigLoader {
|
||||
.bind(TYPES.WEB_SOCKET_CONNECTION_TOKEN_TTL)
|
||||
.toConstantValue(+env.get('WEB_SOCKET_CONNECTION_TOKEN_TTL', true))
|
||||
container.bind(TYPES.REDIS_URL).toConstantValue(env.get('REDIS_URL'))
|
||||
container.bind(TYPES.SQS_QUEUE_URL).toConstantValue(env.get('SQS_QUEUE_URL', true))
|
||||
container.bind(TYPES.REDIS_EVENTS_CHANNEL).toConstantValue(env.get('REDIS_EVENTS_CHANNEL'))
|
||||
container.bind(TYPES.SQS_QUEUE_URL).toConstantValue(env.get('SQS_QUEUE_URL'))
|
||||
container.bind(TYPES.NEW_RELIC_ENABLED).toConstantValue(env.get('NEW_RELIC_ENABLED', true))
|
||||
container.bind(TYPES.WEBSOCKETS_API_URL).toConstantValue(env.get('WEBSOCKETS_API_URL', true))
|
||||
container.bind(TYPES.VERSION).toConstantValue(env.get('VERSION'))
|
||||
@@ -144,37 +141,22 @@ export class ContainerConfigLoader {
|
||||
['WEB_SOCKET_MESSAGE_REQUESTED', container.get(TYPES.WebSocketMessageRequestedEventHandler)],
|
||||
])
|
||||
|
||||
if (env.get('SQS_QUEUE_URL', true)) {
|
||||
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),
|
||||
),
|
||||
)
|
||||
} else {
|
||||
container
|
||||
.bind<DomainEventMessageHandlerInterface>(TYPES.DomainEventMessageHandler)
|
||||
.toConstantValue(new RedisEventMessageHandler(eventHandlers, container.get(TYPES.Logger)))
|
||||
container
|
||||
.bind<DomainEventSubscriberFactoryInterface>(TYPES.DomainEventSubscriberFactory)
|
||||
.toConstantValue(
|
||||
new RedisDomainEventSubscriberFactory(
|
||||
container.get(TYPES.Redis),
|
||||
container.get(TYPES.DomainEventMessageHandler),
|
||||
container.get(TYPES.REDIS_EVENTS_CHANNEL),
|
||||
),
|
||||
)
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
@@ -15,7 +15,6 @@ const TYPES = {
|
||||
REDIS_URL: Symbol.for('REDIS_URL'),
|
||||
SQS_QUEUE_URL: Symbol.for('SQS_QUEUE_URL'),
|
||||
SQS_AWS_REGION: Symbol.for('SQS_AWS_REGION'),
|
||||
REDIS_EVENTS_CHANNEL: Symbol.for('REDIS_EVENTS_CHANNEL'),
|
||||
NEW_RELIC_ENABLED: Symbol.for('NEW_RELIC_ENABLED'),
|
||||
WEBSOCKETS_API_URL: Symbol.for('WEBSOCKETS_API_URL'),
|
||||
VERSION: Symbol.for('VERSION'),
|
||||
|
||||
@@ -22,8 +22,6 @@ SNS_AWS_REGION=
|
||||
SQS_QUEUE_URL=
|
||||
SQS_AWS_REGION=
|
||||
|
||||
REDIS_EVENTS_CHANNEL=events
|
||||
|
||||
# (Optional) New Relic Setup
|
||||
NEW_RELIC_ENABLED=false
|
||||
NEW_RELIC_APP_NAME=Workspace
|
||||
|
||||
@@ -3,6 +3,10 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.19.23](https://github.com/standardnotes/server/compare/@standardnotes/workspace-server@1.19.22...@standardnotes/workspace-server@1.19.23) (2023-02-06)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/workspace-server
|
||||
|
||||
## [1.19.22](https://github.com/standardnotes/server/compare/@standardnotes/workspace-server@1.19.21...@standardnotes/workspace-server@1.19.22) (2023-01-30)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/workspace-server",
|
||||
"version": "1.19.22",
|
||||
"version": "1.19.23",
|
||||
"engines": {
|
||||
"node": ">=18.0.0 <19.0.0"
|
||||
},
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user