mirror of
https://github.com/standardnotes/server
synced 2026-02-08 17:01:17 -05:00
Compare commits
25 Commits
@standardn
...
@standardn
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b172177142 | ||
|
|
3fc11c5381 | ||
|
|
13cf896fe2 | ||
|
|
84ff915a56 | ||
|
|
74aedbccfe | ||
|
|
6e49298aea | ||
|
|
c1ba290e41 | ||
|
|
60e8974580 | ||
|
|
033eeda50a | ||
|
|
e7e34f3e16 | ||
|
|
7e1fcebdd8 | ||
|
|
fd4ee2123d | ||
|
|
62caa840ef | ||
|
|
565e890973 | ||
|
|
84c4642ced | ||
|
|
699164eba5 | ||
|
|
d86928f1b4 | ||
|
|
06fc077f1b | ||
|
|
97ba31f345 | ||
|
|
a8795defc1 | ||
|
|
1b35cf7a39 | ||
|
|
ed62ed516f | ||
|
|
b4f1c6f7f8 | ||
|
|
14e4ca70b4 | ||
|
|
12fa94539b |
43
.github/workflows/api-gateway.release.yml
vendored
43
.github/workflows/api-gateway.release.yml
vendored
@@ -16,13 +16,42 @@ jobs:
|
||||
|
||||
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'
|
||||
- run: yarn build
|
||||
- run: yarn lint:api-gateway
|
||||
|
||||
- name: Build
|
||||
run: yarn build
|
||||
|
||||
- name: Lint
|
||||
run: yarn lint:api-gateway
|
||||
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
|
||||
- name: Publish Docker image for E2E testing
|
||||
run: |
|
||||
yarn docker build @standardnotes/api-gateway -t standardnotes/api-gateway:${{ github.sha }}
|
||||
docker push standardnotes/api-gateway:${{ github.sha }}
|
||||
|
||||
- name: Run E2E test suite
|
||||
uses: convictional/trigger-workflow-and-wait@v1.6.1
|
||||
with:
|
||||
owner: standardnotes
|
||||
repo: e2e
|
||||
github_token: ${{ secrets.CI_PAT_TOKEN }}
|
||||
workflow_file_name: testing-with-stable-client.yml
|
||||
wait_interval: 30
|
||||
client_payload: '{"api_gateway_image_tag": "${{ github.sha }}"}'
|
||||
propagate_failure: true
|
||||
trigger_workflow: true
|
||||
wait_workflow: true
|
||||
|
||||
publish-aws-ecr:
|
||||
needs: test
|
||||
@@ -32,7 +61,7 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Build locally
|
||||
run: yarn build:api-gateway
|
||||
run: yarn build
|
||||
- name: Configure AWS credentials
|
||||
uses: aws-actions/configure-aws-credentials@v1
|
||||
with:
|
||||
@@ -62,17 +91,15 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Build locally
|
||||
run: yarn build:api-gateway
|
||||
run: yarn build
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
- name: Build, tag, and push image to Docker Hub
|
||||
- name: Publish Docker image as stable
|
||||
run: |
|
||||
yarn docker build @standardnotes/api-gateway -t standardnotes/api-gateway:${{ github.sha }}
|
||||
docker push standardnotes/api-gateway:${{ github.sha }}
|
||||
docker tag standardnotes/api-gateway:${{ github.sha }} standardnotes/api-gateway:latest
|
||||
yarn docker build @standardnotes/api-gateway -t standardnotes/api-gateway:latest
|
||||
docker push standardnotes/api-gateway:latest
|
||||
|
||||
deploy-web:
|
||||
|
||||
47
.github/workflows/auth.release.yml
vendored
47
.github/workflows/auth.release.yml
vendored
@@ -16,14 +16,45 @@ jobs:
|
||||
|
||||
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'
|
||||
- run: yarn build
|
||||
- run: yarn lint:auth
|
||||
- run: yarn test:auth
|
||||
|
||||
- name: Build
|
||||
run: yarn build
|
||||
|
||||
- name: Lint
|
||||
run: yarn lint:auth
|
||||
|
||||
- name: Test
|
||||
run: yarn test:auth
|
||||
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
|
||||
- name: Publish Docker image for E2E testing
|
||||
run: |
|
||||
yarn docker build @standardnotes/auth-server -t standardnotes/auth:${{ github.sha }}
|
||||
docker push standardnotes/auth:${{ github.sha }}
|
||||
|
||||
- name: Run E2E test suite
|
||||
uses: convictional/trigger-workflow-and-wait@v1.6.1
|
||||
with:
|
||||
owner: standardnotes
|
||||
repo: e2e
|
||||
github_token: ${{ secrets.CI_PAT_TOKEN }}
|
||||
workflow_file_name: testing-with-stable-client.yml
|
||||
wait_interval: 30
|
||||
client_payload: '{"auth_image_tag": "${{ github.sha }}"}'
|
||||
propagate_failure: true
|
||||
trigger_workflow: true
|
||||
wait_workflow: true
|
||||
|
||||
publish-aws-ecr:
|
||||
needs: test
|
||||
@@ -33,7 +64,7 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Build locally
|
||||
run: yarn build:auth
|
||||
run: yarn build
|
||||
- name: Configure AWS credentials
|
||||
uses: aws-actions/configure-aws-credentials@v1
|
||||
with:
|
||||
@@ -63,17 +94,15 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Build locally
|
||||
run: yarn build:auth
|
||||
run: yarn build
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
- name: Build, tag, and push image to Docker Hub
|
||||
- name: Publish Docker image as stable
|
||||
run: |
|
||||
yarn docker build @standardnotes/auth-server -t standardnotes/auth:${{ github.sha }}
|
||||
docker push standardnotes/auth:${{ github.sha }}
|
||||
docker tag standardnotes/auth:${{ github.sha }} standardnotes/auth:latest
|
||||
yarn docker build @standardnotes/auth-server -t standardnotes/auth:latest
|
||||
docker push standardnotes/auth:latest
|
||||
|
||||
deploy-web:
|
||||
|
||||
126
.github/workflows/event-store.release.yml
vendored
Normal file
126
.github/workflows/event-store.release.yml
vendored
Normal file
@@ -0,0 +1,126 @@
|
||||
name: Event Store
|
||||
|
||||
concurrency:
|
||||
group: event-store
|
||||
cancel-in-progress: true
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- '*standardnotes/event-store*'
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
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'
|
||||
- run: yarn build
|
||||
- run: yarn lint:event-store
|
||||
- run: yarn test:event-store
|
||||
|
||||
publish-aws-ecr:
|
||||
needs: test
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Build locally
|
||||
run: yarn build
|
||||
- name: Configure AWS credentials
|
||||
uses: aws-actions/configure-aws-credentials@v1
|
||||
with:
|
||||
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
aws-region: us-east-1
|
||||
- name: Login to Amazon ECR
|
||||
id: login-ecr
|
||||
uses: aws-actions/amazon-ecr-login@v1
|
||||
- name: Build, tag, and push image to Amazon ECR
|
||||
id: build-image
|
||||
env:
|
||||
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
|
||||
ECR_REPOSITORY: event-store
|
||||
IMAGE_TAG: ${{ github.sha }}
|
||||
run: |
|
||||
yarn docker build @standardnotes/event-store -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
|
||||
docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
|
||||
docker tag $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG $ECR_REGISTRY/$ECR_REPOSITORY:latest
|
||||
docker push $ECR_REGISTRY/$ECR_REPOSITORY:latest
|
||||
|
||||
publish-docker-hub:
|
||||
needs: test
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Build locally
|
||||
run: yarn build
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
- name: Build, tag, and push image to Docker Hub
|
||||
run: |
|
||||
yarn docker build @standardnotes/event-store -t standardnotes/event-store:${{ github.sha }}
|
||||
docker push standardnotes/event-store:${{ github.sha }}
|
||||
docker tag standardnotes/event-store:${{ github.sha }} standardnotes/event-store:latest
|
||||
docker push standardnotes/event-store:latest
|
||||
|
||||
deploy-worker:
|
||||
needs: publish-aws-ecr
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Configure AWS credentials
|
||||
uses: aws-actions/configure-aws-credentials@v1
|
||||
with:
|
||||
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
aws-region: us-east-1
|
||||
- name: PROD - Download task definition
|
||||
run: |
|
||||
aws ecs describe-task-definition --task-definition event-store-prod --query taskDefinition > task-definition.json
|
||||
- name: PROD - Fill in the new version in the Amazon ECS task definition
|
||||
run: |
|
||||
jq '(.containerDefinitions[] | select(.name=="event-store-prod") | .environment[] | select(.name=="VERSION")).value = "${{ github.sha }}"' task-definition.json > tmp.json && mv tmp.json task-definition.json
|
||||
- name: PROD - Fill in the new image ID in the Amazon ECS task definition
|
||||
id: task-def-prod
|
||||
uses: aws-actions/amazon-ecs-render-task-definition@v1
|
||||
with:
|
||||
task-definition: task-definition.json
|
||||
container-name: event-store-prod
|
||||
image: ${{ secrets.AWS_ECR_REGISTRY }}/event-store:${{ github.sha }}
|
||||
- name: PROD - Deploy Amazon ECS task definition
|
||||
uses: aws-actions/amazon-ecs-deploy-task-definition@v1
|
||||
with:
|
||||
task-definition: ${{ steps.task-def-prod.outputs.task-definition }}
|
||||
service: event-store-prod
|
||||
cluster: prod
|
||||
wait-for-service-stability: true
|
||||
|
||||
newrelic:
|
||||
needs: [ deploy-worker ]
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Create New Relic deployment marker for Worker
|
||||
uses: newrelic/deployment-marker-action@v1
|
||||
with:
|
||||
accountId: ${{ secrets.NEW_RELIC_ACCOUNT_ID }}
|
||||
apiKey: ${{ secrets.NEW_RELIC_API_KEY }}
|
||||
applicationId: ${{ secrets.NEW_RELIC_APPLICATION_ID_EVENT_STORE_PROD }}
|
||||
revision: "${{ github.sha }}"
|
||||
description: "Automated Deployment via Github Actions"
|
||||
user: "${{ github.actor }}"
|
||||
45
.github/workflows/files.release.yml
vendored
45
.github/workflows/files.release.yml
vendored
@@ -16,14 +16,45 @@ jobs:
|
||||
|
||||
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'
|
||||
- run: yarn build
|
||||
- run: yarn lint:files
|
||||
- run: yarn test:files
|
||||
|
||||
- name: Build
|
||||
run: yarn build
|
||||
|
||||
- name: Lint
|
||||
run: yarn lint:files
|
||||
|
||||
- name: Test
|
||||
run: yarn test:files
|
||||
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
|
||||
- name: Publish Docker image for E2E testing
|
||||
run: |
|
||||
yarn docker build @standardnotes/files-server -t standardnotes/files:${{ github.sha }}
|
||||
docker push standardnotes/files:${{ github.sha }}
|
||||
|
||||
- name: Run E2E test suite
|
||||
uses: convictional/trigger-workflow-and-wait@v1.6.1
|
||||
with:
|
||||
owner: standardnotes
|
||||
repo: e2e
|
||||
github_token: ${{ secrets.CI_PAT_TOKEN }}
|
||||
workflow_file_name: testing-with-stable-client.yml
|
||||
wait_interval: 30
|
||||
client_payload: '{"files_image_tag": "${{ github.sha }}"}'
|
||||
propagate_failure: true
|
||||
trigger_workflow: true
|
||||
wait_workflow: true
|
||||
|
||||
publish-aws-ecr:
|
||||
needs: test
|
||||
@@ -33,7 +64,7 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Build locally
|
||||
run: yarn build:files
|
||||
run: yarn build
|
||||
- name: Configure AWS credentials
|
||||
uses: aws-actions/configure-aws-credentials@v1
|
||||
with:
|
||||
@@ -63,7 +94,7 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Build locally
|
||||
run: yarn build:files
|
||||
run: yarn build
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
@@ -71,9 +102,7 @@ jobs:
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
- name: Build, tag, and push image to Docker Hub
|
||||
run: |
|
||||
yarn docker build @standardnotes/files-server -t standardnotes/files:${{ github.sha }}
|
||||
docker push standardnotes/files:${{ github.sha }}
|
||||
docker tag standardnotes/files:${{ github.sha }} standardnotes/files:latest
|
||||
yarn docker build @standardnotes/files-server -t standardnotes/files:latest
|
||||
docker push standardnotes/files:latest
|
||||
|
||||
deploy-web:
|
||||
|
||||
4
.github/workflows/scheduler.release.yml
vendored
4
.github/workflows/scheduler.release.yml
vendored
@@ -33,7 +33,7 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Build locally
|
||||
run: yarn build:scheduler
|
||||
run: yarn build
|
||||
- name: Configure AWS credentials
|
||||
uses: aws-actions/configure-aws-credentials@v1
|
||||
with:
|
||||
@@ -63,7 +63,7 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Build locally
|
||||
run: yarn build:scheduler
|
||||
run: yarn build
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
|
||||
45
.github/workflows/syncing-server.release.yml
vendored
45
.github/workflows/syncing-server.release.yml
vendored
@@ -16,14 +16,45 @@ jobs:
|
||||
|
||||
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'
|
||||
- run: yarn build
|
||||
- run: yarn lint:syncing-server
|
||||
- run: yarn test:syncing-server
|
||||
|
||||
- name: Build
|
||||
run: yarn build
|
||||
|
||||
- name: Lint
|
||||
run: yarn lint:syncing-server
|
||||
|
||||
- name: Test
|
||||
run: yarn test:syncing-server
|
||||
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
|
||||
- name: Publish Docker image for E2E testing
|
||||
run: |
|
||||
yarn docker build @standardnotes/syncing-server -t standardnotes/syncing-server-js:${{ github.sha }}
|
||||
docker push standardnotes/syncing-server-js:${{ github.sha }}
|
||||
|
||||
- name: Run E2E test suite
|
||||
uses: convictional/trigger-workflow-and-wait@v1.6.1
|
||||
with:
|
||||
owner: standardnotes
|
||||
repo: e2e
|
||||
github_token: ${{ secrets.CI_PAT_TOKEN }}
|
||||
workflow_file_name: testing-with-stable-client.yml
|
||||
wait_interval: 30
|
||||
client_payload: '{"syncing_server_js_image_tag": "${{ github.sha }}"}'
|
||||
propagate_failure: true
|
||||
trigger_workflow: true
|
||||
wait_workflow: true
|
||||
|
||||
publish-aws-ecr:
|
||||
needs: test
|
||||
@@ -33,7 +64,7 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Build locally
|
||||
run: yarn build:syncing-server
|
||||
run: yarn build
|
||||
- name: Configure AWS credentials
|
||||
uses: aws-actions/configure-aws-credentials@v1
|
||||
with:
|
||||
@@ -63,7 +94,7 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Build locally
|
||||
run: yarn build:syncing-server
|
||||
run: yarn build
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
@@ -71,9 +102,7 @@ jobs:
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
- name: Build, tag, and push image to Docker Hub
|
||||
run: |
|
||||
yarn docker build @standardnotes/syncing-server -t standardnotes/syncing-server-js:${{ github.sha }}
|
||||
docker push standardnotes/syncing-server-js:${{ github.sha }}
|
||||
docker tag standardnotes/syncing-server-js:${{ github.sha }} standardnotes/syncing-server-js:latest
|
||||
yarn docker build @standardnotes/syncing-server -t standardnotes/syncing-server-js:latest
|
||||
docker push standardnotes/syncing-server-js:latest
|
||||
|
||||
deploy-web:
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
.yarn/cache/@types-microtime-npm-2.1.0-111ed89518-6c23131fe4.zip
vendored
Normal file
BIN
.yarn/cache/@types-microtime-npm-2.1.0-111ed89518-6c23131fe4.zip
vendored
Normal file
Binary file not shown.
BIN
.yarn/cache/@types-nodemailer-npm-6.4.4-c5c500abe2-16ed1bad2c.zip
vendored
Normal file
BIN
.yarn/cache/@types-nodemailer-npm-6.4.4-c5c500abe2-16ed1bad2c.zip
vendored
Normal file
Binary file not shown.
BIN
.yarn/cache/enhanced-resolve-npm-5.10.0-7941304306-0bb9830704.zip
vendored
Normal file
BIN
.yarn/cache/enhanced-resolve-npm-5.10.0-7941304306-0bb9830704.zip
vendored
Normal file
Binary file not shown.
BIN
.yarn/cache/regenerator-runtime-npm-0.13.9-6d02340eec-65ed455fe5.zip
vendored
Normal file
BIN
.yarn/cache/regenerator-runtime-npm-0.13.9-6d02340eec-65ed455fe5.zip
vendored
Normal file
Binary file not shown.
BIN
.yarn/cache/tapable-npm-2.2.1-8cf5ff3039-3b7a1b4d86.zip
vendored
Normal file
BIN
.yarn/cache/tapable-npm-2.2.1-8cf5ff3039-3b7a1b4d86.zip
vendored
Normal file
Binary file not shown.
BIN
.yarn/cache/ts-loader-npm-9.3.1-634433ef6a-462a8ac315.zip
vendored
Normal file
BIN
.yarn/cache/ts-loader-npm-9.3.1-634433ef6a-462a8ac315.zip
vendored
Normal file
Binary file not shown.
@@ -17,11 +17,13 @@
|
||||
"lint:syncing-server": "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",
|
||||
"test": "yarn workspaces foreach -p -j 10 --verbose run test",
|
||||
"test:auth": "yarn workspace @standardnotes/auth-server test",
|
||||
"test:scheduler": "yarn workspace @standardnotes/scheduler-server test",
|
||||
"test:syncing-server": "yarn workspace @standardnotes/syncing-server test",
|
||||
"test:files": "yarn workspace @standardnotes/files-server test",
|
||||
"test:event-store": "yarn workspace @standardnotes/event-store test",
|
||||
"clean": "yarn workspaces foreach -p --verbose run clean",
|
||||
"setup:env": "cp .env.sample .env && yarn workspaces foreach -p --verbose run setup:env",
|
||||
"build": "yarn workspaces foreach -pt -j 10 --verbose run build",
|
||||
|
||||
1
packages/analytics/.eslintignore
Normal file
1
packages/analytics/.eslintignore
Normal file
@@ -0,0 +1 @@
|
||||
dist
|
||||
6
packages/analytics/.eslintrc
Normal file
6
packages/analytics/.eslintrc
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"extends": "../../.eslintrc",
|
||||
"parserOptions": {
|
||||
"project": "./linter.tsconfig.json"
|
||||
}
|
||||
}
|
||||
98
packages/analytics/CHANGELOG.md
Normal file
98
packages/analytics/CHANGELOG.md
Normal file
@@ -0,0 +1,98 @@
|
||||
# Change Log
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.8.1](https://github.com/standardnotes/server/compare/@standardnotes/analytics@1.8.0...@standardnotes/analytics@1.8.1) (2022-07-06)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* files included in distributable packages ([97ba31f](https://github.com/standardnotes/server/commit/97ba31f345fc95df0c15a348f0461fb9e5bcb923))
|
||||
|
||||
# 1.8.0 (2022-07-06)
|
||||
|
||||
### Features
|
||||
|
||||
* add analytics package ([14e4ca7](https://github.com/standardnotes/server/commit/14e4ca70b438dd3eaaa404bc0ca31d22a62b45be))
|
||||
|
||||
## [1.6.1](https://github.com/standardnotes/snjs/compare/@standardnotes/analytics@1.6.0...@standardnotes/analytics@1.6.1) (2022-07-04)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* add missing reflect-metadata package to all packages ([ce3a5bb](https://github.com/standardnotes/snjs/commit/ce3a5bbf3f1d2276ac4abc3eec3c6a44c8c3ba9b))
|
||||
|
||||
# [1.6.0](https://github.com/standardnotes/snjs/compare/@standardnotes/analytics@1.5.0...@standardnotes/analytics@1.6.0) (2022-06-02)
|
||||
|
||||
### Features
|
||||
|
||||
* refactor analytics store to handle different periods of time ([00d4f3f](https://github.com/standardnotes/snjs/commit/00d4f3f2f742b0deb5ef4cd415c672574cb3a911))
|
||||
|
||||
# [1.5.0](https://github.com/standardnotes/snjs/compare/@standardnotes/analytics@1.4.1...@standardnotes/analytics@1.5.0) (2022-06-01)
|
||||
|
||||
### Features
|
||||
|
||||
* add unmarking activities ([09cea1d](https://github.com/standardnotes/snjs/commit/09cea1d8e97dd83f2eaafaef5ff680aef8c5c3ff))
|
||||
|
||||
## [1.4.1](https://github.com/standardnotes/snjs/compare/@standardnotes/analytics@1.4.0...@standardnotes/analytics@1.4.1) (2022-06-01)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* rename analytics activity backup to email backup ([30d2db6](https://github.com/standardnotes/snjs/commit/30d2db63e5dec05b3f0976211c661d8aa0e04139))
|
||||
|
||||
# [1.4.0](https://github.com/standardnotes/snjs/compare/@standardnotes/analytics@1.3.1...@standardnotes/analytics@1.4.0) (2022-06-01)
|
||||
|
||||
### Features
|
||||
|
||||
* add calculating total counts of activites in analytics ([6ed659a](https://github.com/standardnotes/snjs/commit/6ed659a7c4411ce2555e4af96dc5473c3d03fd41))
|
||||
|
||||
## [1.3.1](https://github.com/standardnotes/snjs/compare/@standardnotes/analytics@1.3.0...@standardnotes/analytics@1.3.1) (2022-05-26)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* add backup analytics activity ([cf7ae68](https://github.com/standardnotes/snjs/commit/cf7ae68e13aa9403702340da8a3bca35e9273784))
|
||||
|
||||
# [1.3.0](https://github.com/standardnotes/snjs/compare/@standardnotes/analytics@1.2.0...@standardnotes/analytics@1.3.0) (2022-05-26)
|
||||
|
||||
### Features
|
||||
|
||||
* add calculating activity retention in analytics ([bc2f26d](https://github.com/standardnotes/snjs/commit/bc2f26d63a8ff0e2750b37bc1ee56297f6a8c98d))
|
||||
|
||||
# [1.2.0](https://github.com/standardnotes/snjs/compare/@standardnotes/analytics@1.1.0...@standardnotes/analytics@1.2.0) (2022-05-26)
|
||||
|
||||
### Features
|
||||
|
||||
* add activity indicators in analytics ([e6f5b5a](https://github.com/standardnotes/snjs/commit/e6f5b5afbff1f5f96adfcba42f4708fa74ac7f80))
|
||||
|
||||
# [1.1.0](https://github.com/standardnotes/snjs/compare/@standardnotes/analytics@1.0.7...@standardnotes/analytics@1.1.0) (2022-05-24)
|
||||
|
||||
### Features
|
||||
|
||||
* add marking activity in analytics ([#750](https://github.com/standardnotes/snjs/issues/750)) ([2a68fa6](https://github.com/standardnotes/snjs/commit/2a68fa6636c24e79443359d31a8427d50ca87cca))
|
||||
|
||||
## [1.0.7](https://github.com/standardnotes/snjs/compare/@standardnotes/analytics@1.0.5...@standardnotes/analytics@1.0.7) (2022-05-04)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/analytics
|
||||
|
||||
## [1.0.6](https://github.com/standardnotes/snjs/compare/@standardnotes/analytics@1.0.5...@standardnotes/analytics@1.0.6) (2022-05-04)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/analytics
|
||||
|
||||
## [1.0.5](https://github.com/standardnotes/snjs/compare/@standardnotes/analytics@1.0.4...@standardnotes/analytics@1.0.5) (2022-04-22)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/analytics
|
||||
|
||||
## [1.0.4](https://github.com/standardnotes/snjs/compare/@standardnotes/analytics@1.0.3...@standardnotes/analytics@1.0.4) (2022-04-15)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/analytics
|
||||
|
||||
## [1.0.3](https://github.com/standardnotes/snjs/compare/@standardnotes/analytics@1.0.2...@standardnotes/analytics@1.0.3) (2022-04-11)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/analytics
|
||||
|
||||
## [1.0.2](https://github.com/standardnotes/snjs/compare/@standardnotes/analytics@1.0.1...@standardnotes/analytics@1.0.2) (2022-03-31)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/analytics
|
||||
|
||||
## 1.0.1 (2022-03-10)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/analytics
|
||||
11
packages/analytics/jest.config.js
Normal file
11
packages/analytics/jest.config.js
Normal file
@@ -0,0 +1,11 @@
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
const base = require('../../jest.config');
|
||||
|
||||
module.exports = {
|
||||
...base,
|
||||
globals: {
|
||||
'ts-jest': {
|
||||
tsconfig: 'tsconfig.json',
|
||||
},
|
||||
},
|
||||
};
|
||||
4
packages/analytics/linter.tsconfig.json
Normal file
4
packages/analytics/linter.tsconfig.json
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"exclude": ["dist"]
|
||||
}
|
||||
40
packages/analytics/package.json
Normal file
40
packages/analytics/package.json
Normal file
@@ -0,0 +1,40 @@
|
||||
{
|
||||
"name": "@standardnotes/analytics",
|
||||
"version": "1.8.1",
|
||||
"engines": {
|
||||
"node": ">=14.0.0 <17.0.0"
|
||||
},
|
||||
"description": "Analytics tools for Standard Notes projects",
|
||||
"main": "dist/src/index.js",
|
||||
"author": "Standard Notes",
|
||||
"types": "dist/src/index.d.ts",
|
||||
"files": [
|
||||
"dist/src/**/*.js",
|
||||
"dist/src/**/*.d.ts"
|
||||
],
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"license": "AGPL-3.0-or-later",
|
||||
"scripts": {
|
||||
"clean": "rm -fr dist",
|
||||
"prestart": "yarn clean",
|
||||
"start": "tsc -p tsconfig.json --watch",
|
||||
"prebuild": "yarn clean",
|
||||
"build": "tsc -p tsconfig.json",
|
||||
"lint": "eslint . --ext .ts",
|
||||
"test:unit": "jest spec --coverage"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/ioredis": "^4.28.8",
|
||||
"@types/jest": "^27.4.1",
|
||||
"@typescript-eslint/eslint-plugin": "^5.30.0",
|
||||
"eslint-plugin-prettier": "^4.2.1",
|
||||
"ioredis": "^4.28.5",
|
||||
"jest": "^27.5.1",
|
||||
"ts-jest": "^27.1.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"reflect-metadata": "^0.1.13"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
export enum AnalyticsActivity {
|
||||
EditingItems = 'editing-items',
|
||||
Login = 'login',
|
||||
EmailUnbackedUpData = 'email-unbacked-up-data',
|
||||
EmailBackup = 'email-backup',
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
import { Period } from '../Time/Period'
|
||||
import { AnalyticsActivity } from './AnalyticsActivity'
|
||||
|
||||
export interface AnalyticsStoreInterface {
|
||||
unmarkActivity(activities: AnalyticsActivity[], analyticsId: number, periods: Period[]): Promise<void>
|
||||
markActivity(activities: AnalyticsActivity[], analyticsId: number, periods: Period[]): Promise<void>
|
||||
wasActivityDone(activity: AnalyticsActivity, analyticsId: number, period: Period): Promise<boolean>
|
||||
calculateActivityRetention(activity: AnalyticsActivity, firstPeriod: Period, secondPeriod: Period): Promise<number>
|
||||
calculateActivityTotalCount(activity: AnalyticsActivity, period: Period): Promise<number>
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
export interface StatisticsStoreInterface {
|
||||
incrementSNJSVersionUsage(snjsVersion: string): Promise<void>
|
||||
incrementApplicationVersionUsage(applicationVersion: string): Promise<void>
|
||||
incrementOutOfSyncIncidents(): Promise<void>
|
||||
getYesterdaySNJSUsage(): Promise<Array<{ version: string; count: number }>>
|
||||
getYesterdayApplicationUsage(): Promise<Array<{ version: string; count: number }>>
|
||||
getYesterdayOutOfSyncIncidents(): Promise<number>
|
||||
}
|
||||
10
packages/analytics/src/Domain/Time/Period.ts
Normal file
10
packages/analytics/src/Domain/Time/Period.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
export enum Period {
|
||||
Today,
|
||||
Yesterday,
|
||||
DayBeforeYesterday,
|
||||
ThisWeek,
|
||||
LastWeek,
|
||||
WeekBeforeLastWeek,
|
||||
ThisMonth,
|
||||
LastMonth,
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
import { Period } from './Period'
|
||||
import { PeriodKeyGenerator } from './PeriodKeyGenerator'
|
||||
|
||||
describe('PeriodKeyGenerator', () => {
|
||||
const createGenerator = () => new PeriodKeyGenerator()
|
||||
|
||||
beforeEach(() => {
|
||||
jest.useFakeTimers('modern')
|
||||
jest.setSystemTime(1653395155000)
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
jest.useRealTimers()
|
||||
})
|
||||
|
||||
it('should generate a period key for today', () => {
|
||||
expect(createGenerator().getPeriodKey(Period.Today)).toEqual('2022-5-24')
|
||||
})
|
||||
|
||||
it('should generate a period key for yesterday', () => {
|
||||
expect(createGenerator().getPeriodKey(Period.Yesterday)).toEqual('2022-5-23')
|
||||
})
|
||||
|
||||
it('should generate a period key for the day before yesterday', () => {
|
||||
expect(createGenerator().getPeriodKey(Period.DayBeforeYesterday)).toEqual('2022-5-22')
|
||||
})
|
||||
|
||||
it('should generate a period key for this week', () => {
|
||||
expect(createGenerator().getPeriodKey(Period.ThisWeek)).toEqual('2022-week-21')
|
||||
})
|
||||
|
||||
it('should generate a period key for last week', () => {
|
||||
expect(createGenerator().getPeriodKey(Period.LastWeek)).toEqual('2022-week-20')
|
||||
})
|
||||
|
||||
it('should generate a period key for the week before last week', () => {
|
||||
expect(createGenerator().getPeriodKey(Period.WeekBeforeLastWeek)).toEqual('2022-week-19')
|
||||
})
|
||||
|
||||
it('should generate a period key for this month', () => {
|
||||
expect(createGenerator().getPeriodKey(Period.ThisMonth)).toEqual('2022-5')
|
||||
})
|
||||
|
||||
it('should generate a period key for last month', () => {
|
||||
expect(createGenerator().getPeriodKey(Period.LastMonth)).toEqual('2022-4')
|
||||
})
|
||||
|
||||
it('should throw error on unsupported period', () => {
|
||||
let error = null
|
||||
try {
|
||||
createGenerator().getPeriodKey(42 as Period)
|
||||
} catch (caughtError) {
|
||||
error = caughtError
|
||||
}
|
||||
|
||||
expect(error).not.toBeNull()
|
||||
})
|
||||
})
|
||||
99
packages/analytics/src/Domain/Time/PeriodKeyGenerator.ts
Normal file
99
packages/analytics/src/Domain/Time/PeriodKeyGenerator.ts
Normal file
@@ -0,0 +1,99 @@
|
||||
import { Period } from './Period'
|
||||
import { PeriodKeyGeneratorInterface } from './PeriodKeyGeneratorInterface'
|
||||
|
||||
export class PeriodKeyGenerator implements PeriodKeyGeneratorInterface {
|
||||
getPeriodKey(period: Period): string {
|
||||
switch (period) {
|
||||
case Period.Today:
|
||||
return this.getDailyKey()
|
||||
case Period.Yesterday:
|
||||
return this.getDailyKey(this.getYesterdayDate())
|
||||
case Period.DayBeforeYesterday:
|
||||
return this.getDailyKey(this.getDayBeforeYesterdayDate())
|
||||
case Period.ThisWeek:
|
||||
return this.getWeeklyKey()
|
||||
case Period.LastWeek:
|
||||
return this.getWeeklyKey(this.getLastWeekDate())
|
||||
case Period.WeekBeforeLastWeek:
|
||||
return this.getWeeklyKey(this.getWeekBeforeLastWeekDate())
|
||||
case Period.ThisMonth:
|
||||
return this.getMonthlyKey()
|
||||
case Period.LastMonth:
|
||||
return this.getMonthlyKey(this.getLastMonthDate())
|
||||
default:
|
||||
throw new Error(`Unsuporrted period: ${period}`)
|
||||
}
|
||||
}
|
||||
|
||||
private getMonthlyKey(date?: Date): string {
|
||||
date = date ?? new Date()
|
||||
|
||||
return `${this.getYear(date)}-${this.getMonth(date)}`
|
||||
}
|
||||
|
||||
private getDailyKey(date?: Date): string {
|
||||
date = date ?? new Date()
|
||||
|
||||
return `${this.getYear(date)}-${this.getMonth(date)}-${this.getDayOfTheMonth(date)}`
|
||||
}
|
||||
|
||||
private getWeeklyKey(date?: Date): string {
|
||||
date = date ?? new Date()
|
||||
|
||||
const firstJanuary = new Date(date.getFullYear(), 0, 1)
|
||||
|
||||
const numberOfDaysPassed = Math.floor((date.getTime() - firstJanuary.getTime()) / (24 * 60 * 60 * 1000))
|
||||
|
||||
const weekNumber = Math.ceil((date.getDay() + 1 + numberOfDaysPassed) / 7)
|
||||
|
||||
return `${this.getYear(date)}-week-${weekNumber}`
|
||||
}
|
||||
|
||||
private getYear(date: Date): string {
|
||||
return date.getFullYear().toString()
|
||||
}
|
||||
|
||||
private getMonth(date: Date): string {
|
||||
return (date.getMonth() + 1).toString()
|
||||
}
|
||||
|
||||
private getDayOfTheMonth(date: Date): string {
|
||||
return date.getDate().toString()
|
||||
}
|
||||
|
||||
private getYesterdayDate(): Date {
|
||||
const yesterday = new Date()
|
||||
yesterday.setDate(new Date().getDate() - 1)
|
||||
|
||||
return yesterday
|
||||
}
|
||||
|
||||
private getDayBeforeYesterdayDate(): Date {
|
||||
const dayBeforeYesterday = new Date()
|
||||
dayBeforeYesterday.setDate(new Date().getDate() - 2)
|
||||
|
||||
return dayBeforeYesterday
|
||||
}
|
||||
|
||||
private getLastWeekDate(): Date {
|
||||
const yesterday = new Date()
|
||||
yesterday.setDate(new Date().getDate() - 7)
|
||||
|
||||
return yesterday
|
||||
}
|
||||
|
||||
private getLastMonthDate(): Date {
|
||||
const lastMonth = new Date()
|
||||
lastMonth.setDate(1)
|
||||
lastMonth.setMonth(lastMonth.getMonth() - 1)
|
||||
|
||||
return lastMonth
|
||||
}
|
||||
|
||||
private getWeekBeforeLastWeekDate(): Date {
|
||||
const yesterday = new Date()
|
||||
yesterday.setDate(new Date().getDate() - 14)
|
||||
|
||||
return yesterday
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
import { Period } from './Period'
|
||||
|
||||
export interface PeriodKeyGeneratorInterface {
|
||||
getPeriodKey(period: Period): string
|
||||
}
|
||||
6
packages/analytics/src/Domain/index.ts
Normal file
6
packages/analytics/src/Domain/index.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
export * from './Analytics/AnalyticsActivity'
|
||||
export * from './Analytics/AnalyticsStoreInterface'
|
||||
export * from './Statistics/StatisticsStoreInterface'
|
||||
export * from './Time/Period'
|
||||
export * from './Time/PeriodKeyGenerator'
|
||||
export * from './Time/PeriodKeyGeneratorInterface'
|
||||
131
packages/analytics/src/Infra/Redis/RedisAnalyticsStore.spec.ts
Normal file
131
packages/analytics/src/Infra/Redis/RedisAnalyticsStore.spec.ts
Normal file
@@ -0,0 +1,131 @@
|
||||
import * as IORedis from 'ioredis'
|
||||
import { Period } from '../../Domain'
|
||||
import { AnalyticsActivity } from '../../Domain/Analytics/AnalyticsActivity'
|
||||
import { PeriodKeyGeneratorInterface } from '../../Domain/Time/PeriodKeyGeneratorInterface'
|
||||
|
||||
import { RedisAnalyticsStore } from './RedisAnalyticsStore'
|
||||
|
||||
describe('RedisAnalyticsStore', () => {
|
||||
let redisClient: IORedis.Redis
|
||||
let pipeline: IORedis.Pipeline
|
||||
let periodKeyGenerator: PeriodKeyGeneratorInterface
|
||||
|
||||
const createStore = () => new RedisAnalyticsStore(periodKeyGenerator, redisClient)
|
||||
|
||||
beforeEach(() => {
|
||||
pipeline = {} as jest.Mocked<IORedis.Pipeline>
|
||||
pipeline.incr = jest.fn()
|
||||
pipeline.setbit = jest.fn()
|
||||
pipeline.exec = jest.fn()
|
||||
|
||||
redisClient = {} as jest.Mocked<IORedis.Redis>
|
||||
redisClient.pipeline = jest.fn().mockReturnValue(pipeline)
|
||||
redisClient.incr = jest.fn()
|
||||
redisClient.setbit = jest.fn()
|
||||
redisClient.getbit = jest.fn().mockReturnValue(1)
|
||||
redisClient.send_command = jest.fn()
|
||||
|
||||
periodKeyGenerator = {} as jest.Mocked<PeriodKeyGeneratorInterface>
|
||||
periodKeyGenerator.getPeriodKey = jest.fn().mockReturnValue('period-key')
|
||||
})
|
||||
|
||||
it('should calculate total count of activities', async () => {
|
||||
redisClient.bitcount = jest.fn().mockReturnValue(70)
|
||||
|
||||
expect(await createStore().calculateActivityTotalCount(AnalyticsActivity.EditingItems, Period.Yesterday)).toEqual(
|
||||
70,
|
||||
)
|
||||
|
||||
expect(redisClient.bitcount).toHaveBeenCalledWith('bitmap:action:editing-items:timespan:period-key')
|
||||
})
|
||||
|
||||
it('should calculate activity retention', async () => {
|
||||
redisClient.bitcount = jest.fn().mockReturnValueOnce(7).mockReturnValueOnce(10)
|
||||
|
||||
expect(
|
||||
await createStore().calculateActivityRetention(
|
||||
AnalyticsActivity.EditingItems,
|
||||
Period.DayBeforeYesterday,
|
||||
Period.Yesterday,
|
||||
),
|
||||
).toEqual(70)
|
||||
|
||||
expect(redisClient.send_command).toHaveBeenCalledWith(
|
||||
'BITOP',
|
||||
'AND',
|
||||
'bitmap:action:editing-items:timespan:period-key-period-key',
|
||||
'bitmap:action:editing-items:timespan:period-key',
|
||||
'bitmap:action:editing-items:timespan:period-key',
|
||||
)
|
||||
})
|
||||
|
||||
it('shoud tell if activity was done', async () => {
|
||||
await createStore().wasActivityDone(AnalyticsActivity.EditingItems, 123, Period.Yesterday)
|
||||
|
||||
expect(redisClient.getbit).toHaveBeenCalledWith('bitmap:action:editing-items:timespan:period-key', 123)
|
||||
})
|
||||
|
||||
it('should mark activity as done', async () => {
|
||||
await createStore().markActivity([AnalyticsActivity.EditingItems], 123, [Period.Today])
|
||||
|
||||
expect(pipeline.setbit).toBeCalledTimes(1)
|
||||
expect(pipeline.setbit).toHaveBeenNthCalledWith(1, 'bitmap:action:editing-items:timespan:period-key', 123, 1)
|
||||
expect(pipeline.exec).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('should mark activities as done', async () => {
|
||||
await createStore().markActivity([AnalyticsActivity.EditingItems, AnalyticsActivity.EmailUnbackedUpData], 123, [
|
||||
Period.Today,
|
||||
Period.ThisWeek,
|
||||
])
|
||||
|
||||
expect(pipeline.setbit).toBeCalledTimes(4)
|
||||
expect(pipeline.setbit).toHaveBeenNthCalledWith(1, 'bitmap:action:editing-items:timespan:period-key', 123, 1)
|
||||
expect(pipeline.setbit).toHaveBeenNthCalledWith(2, 'bitmap:action:editing-items:timespan:period-key', 123, 1)
|
||||
expect(pipeline.setbit).toHaveBeenNthCalledWith(
|
||||
3,
|
||||
'bitmap:action:email-unbacked-up-data:timespan:period-key',
|
||||
123,
|
||||
1,
|
||||
)
|
||||
expect(pipeline.setbit).toHaveBeenNthCalledWith(
|
||||
4,
|
||||
'bitmap:action:email-unbacked-up-data:timespan:period-key',
|
||||
123,
|
||||
1,
|
||||
)
|
||||
expect(pipeline.exec).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('should unmark activity as done', async () => {
|
||||
await createStore().unmarkActivity([AnalyticsActivity.EditingItems], 123, [Period.Today])
|
||||
|
||||
expect(pipeline.setbit).toBeCalledTimes(1)
|
||||
expect(pipeline.setbit).toHaveBeenNthCalledWith(1, 'bitmap:action:editing-items:timespan:period-key', 123, 0)
|
||||
expect(pipeline.exec).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('should unmark activities as done', async () => {
|
||||
await createStore().unmarkActivity([AnalyticsActivity.EditingItems, AnalyticsActivity.EmailUnbackedUpData], 123, [
|
||||
Period.Today,
|
||||
Period.ThisWeek,
|
||||
])
|
||||
|
||||
expect(pipeline.setbit).toBeCalledTimes(4)
|
||||
expect(pipeline.setbit).toHaveBeenNthCalledWith(1, 'bitmap:action:editing-items:timespan:period-key', 123, 0)
|
||||
expect(pipeline.setbit).toHaveBeenNthCalledWith(2, 'bitmap:action:editing-items:timespan:period-key', 123, 0)
|
||||
expect(pipeline.setbit).toHaveBeenNthCalledWith(
|
||||
3,
|
||||
'bitmap:action:email-unbacked-up-data:timespan:period-key',
|
||||
123,
|
||||
0,
|
||||
)
|
||||
expect(pipeline.setbit).toHaveBeenNthCalledWith(
|
||||
4,
|
||||
'bitmap:action:email-unbacked-up-data:timespan:period-key',
|
||||
123,
|
||||
0,
|
||||
)
|
||||
expect(pipeline.exec).toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
84
packages/analytics/src/Infra/Redis/RedisAnalyticsStore.ts
Normal file
84
packages/analytics/src/Infra/Redis/RedisAnalyticsStore.ts
Normal file
@@ -0,0 +1,84 @@
|
||||
import * as IORedis from 'ioredis'
|
||||
|
||||
import { Period } from '../../Domain/Time/Period'
|
||||
import { PeriodKeyGeneratorInterface } from '../../Domain/Time/PeriodKeyGeneratorInterface'
|
||||
import { AnalyticsActivity } from '../../Domain/Analytics/AnalyticsActivity'
|
||||
import { AnalyticsStoreInterface } from '../../Domain/Analytics/AnalyticsStoreInterface'
|
||||
|
||||
export class RedisAnalyticsStore implements AnalyticsStoreInterface {
|
||||
constructor(private periodKeyGenerator: PeriodKeyGeneratorInterface, private redisClient: IORedis.Redis) {}
|
||||
|
||||
async markActivity(activities: AnalyticsActivity[], analyticsId: number, periods: Period[]): Promise<void> {
|
||||
const pipeline = this.redisClient.pipeline()
|
||||
|
||||
for (const activity of activities) {
|
||||
for (const period of periods) {
|
||||
pipeline.setbit(
|
||||
`bitmap:action:${activity}:timespan:${this.periodKeyGenerator.getPeriodKey(period)}`,
|
||||
analyticsId,
|
||||
1,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
await pipeline.exec()
|
||||
}
|
||||
|
||||
async unmarkActivity(activities: AnalyticsActivity[], analyticsId: number, periods: Period[]): Promise<void> {
|
||||
const pipeline = this.redisClient.pipeline()
|
||||
|
||||
for (const activity of activities) {
|
||||
for (const period of periods) {
|
||||
pipeline.setbit(
|
||||
`bitmap:action:${activity}:timespan:${this.periodKeyGenerator.getPeriodKey(period)}`,
|
||||
analyticsId,
|
||||
0,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
await pipeline.exec()
|
||||
}
|
||||
|
||||
async wasActivityDone(activity: AnalyticsActivity, analyticsId: number, period: Period): Promise<boolean> {
|
||||
const bitValue = await this.redisClient.getbit(
|
||||
`bitmap:action:${activity}:timespan:${this.periodKeyGenerator.getPeriodKey(period)}`,
|
||||
analyticsId,
|
||||
)
|
||||
|
||||
return bitValue === 1
|
||||
}
|
||||
|
||||
async calculateActivityRetention(
|
||||
activity: AnalyticsActivity,
|
||||
firstPeriod: Period,
|
||||
secondPeriod: Period,
|
||||
): Promise<number> {
|
||||
const initialPeriodKey = this.periodKeyGenerator.getPeriodKey(firstPeriod)
|
||||
const subsequentPeriodKey = this.periodKeyGenerator.getPeriodKey(secondPeriod)
|
||||
|
||||
const diffKey = `bitmap:action:${activity}:timespan:${initialPeriodKey}-${subsequentPeriodKey}`
|
||||
|
||||
await this.redisClient.send_command(
|
||||
'BITOP',
|
||||
'AND',
|
||||
diffKey,
|
||||
`bitmap:action:${activity}:timespan:${initialPeriodKey}`,
|
||||
`bitmap:action:${activity}:timespan:${subsequentPeriodKey}`,
|
||||
)
|
||||
|
||||
const retainedTotalInActivity = await this.redisClient.bitcount(diffKey)
|
||||
|
||||
const initialTotalInActivity = await this.redisClient.bitcount(
|
||||
`bitmap:action:${activity}:timespan:${initialPeriodKey}`,
|
||||
)
|
||||
|
||||
return Math.ceil((retainedTotalInActivity * 100) / initialTotalInActivity)
|
||||
}
|
||||
|
||||
async calculateActivityTotalCount(activity: AnalyticsActivity, period: Period): Promise<number> {
|
||||
return this.redisClient.bitcount(
|
||||
`bitmap:action:${activity}:timespan:${this.periodKeyGenerator.getPeriodKey(period)}`,
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
import * as IORedis from 'ioredis'
|
||||
import { PeriodKeyGeneratorInterface } from '../../Domain'
|
||||
|
||||
import { RedisStatisticsStore } from './RedisStatisticsStore'
|
||||
|
||||
describe('RedisStatisticsStore', () => {
|
||||
let redisClient: IORedis.Redis
|
||||
let periodKeyGenerator: PeriodKeyGeneratorInterface
|
||||
let pipeline: IORedis.Pipeline
|
||||
|
||||
const createStore = () => new RedisStatisticsStore(periodKeyGenerator, redisClient)
|
||||
|
||||
beforeEach(() => {
|
||||
pipeline = {} as jest.Mocked<IORedis.Pipeline>
|
||||
pipeline.incr = jest.fn()
|
||||
pipeline.setbit = jest.fn()
|
||||
pipeline.exec = jest.fn()
|
||||
|
||||
redisClient = {} as jest.Mocked<IORedis.Redis>
|
||||
redisClient.pipeline = jest.fn().mockReturnValue(pipeline)
|
||||
redisClient.incr = jest.fn()
|
||||
redisClient.setbit = jest.fn()
|
||||
redisClient.getbit = jest.fn().mockReturnValue(1)
|
||||
redisClient.send_command = jest.fn()
|
||||
|
||||
periodKeyGenerator = {} as jest.Mocked<PeriodKeyGeneratorInterface>
|
||||
periodKeyGenerator.getPeriodKey = jest.fn().mockReturnValue('period-key')
|
||||
})
|
||||
|
||||
it('should get yesterday out of sync incidents', async () => {
|
||||
redisClient.get = jest.fn().mockReturnValue(1)
|
||||
|
||||
expect(await createStore().getYesterdayOutOfSyncIncidents()).toEqual(1)
|
||||
})
|
||||
|
||||
it('should default to 0 yesterday out of sync incidents', async () => {
|
||||
redisClient.get = jest.fn().mockReturnValue(null)
|
||||
|
||||
expect(await createStore().getYesterdayOutOfSyncIncidents()).toEqual(0)
|
||||
})
|
||||
|
||||
it('should get yesterday application version usage', async () => {
|
||||
redisClient.keys = jest
|
||||
.fn()
|
||||
.mockReturnValue([
|
||||
'count:action:application-request:1.2.3:timespan:2022-3-10',
|
||||
'count:action:application-request:2.3.4:timespan:2022-3-10',
|
||||
])
|
||||
redisClient.get = jest.fn().mockReturnValueOnce(3).mockReturnValueOnce(4)
|
||||
|
||||
expect(await createStore().getYesterdayApplicationUsage()).toEqual([
|
||||
{ count: 3, version: '1.2.3' },
|
||||
{ count: 4, version: '2.3.4' },
|
||||
])
|
||||
})
|
||||
|
||||
it('should get yesterday snjs version usage', async () => {
|
||||
redisClient.keys = jest
|
||||
.fn()
|
||||
.mockReturnValue([
|
||||
'count:action:snjs-request:1.2.3:timespan:2022-3-10',
|
||||
'count:action:snjs-request:2.3.4:timespan:2022-3-10',
|
||||
])
|
||||
redisClient.get = jest.fn().mockReturnValueOnce(3).mockReturnValueOnce(4)
|
||||
|
||||
expect(await createStore().getYesterdaySNJSUsage()).toEqual([
|
||||
{ count: 3, version: '1.2.3' },
|
||||
{ count: 4, version: '2.3.4' },
|
||||
])
|
||||
})
|
||||
|
||||
it('should increment application version usage', async () => {
|
||||
await createStore().incrementApplicationVersionUsage('1.2.3')
|
||||
|
||||
expect(pipeline.incr).toHaveBeenCalled()
|
||||
expect(pipeline.exec).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('should increment snjs version usage', async () => {
|
||||
await createStore().incrementSNJSVersionUsage('1.2.3')
|
||||
|
||||
expect(pipeline.incr).toHaveBeenCalled()
|
||||
expect(pipeline.exec).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('should increment out of sync incedent count', async () => {
|
||||
await createStore().incrementOutOfSyncIncidents()
|
||||
|
||||
expect(pipeline.incr).toHaveBeenCalled()
|
||||
expect(pipeline.exec).toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
99
packages/analytics/src/Infra/Redis/RedisStatisticsStore.ts
Normal file
99
packages/analytics/src/Infra/Redis/RedisStatisticsStore.ts
Normal file
@@ -0,0 +1,99 @@
|
||||
import * as IORedis from 'ioredis'
|
||||
|
||||
import { Period, PeriodKeyGeneratorInterface } from '../../Domain'
|
||||
|
||||
import { StatisticsStoreInterface } from '../../Domain/Statistics/StatisticsStoreInterface'
|
||||
|
||||
export class RedisStatisticsStore implements StatisticsStoreInterface {
|
||||
constructor(private periodKeyGenerator: PeriodKeyGeneratorInterface, private redisClient: IORedis.Redis) {}
|
||||
|
||||
async getYesterdayOutOfSyncIncidents(): Promise<number> {
|
||||
const count = await this.redisClient.get(
|
||||
`count:action:out-of-sync:timespan:${this.periodKeyGenerator.getPeriodKey(Period.Yesterday)}`,
|
||||
)
|
||||
|
||||
if (count === null) {
|
||||
return 0
|
||||
}
|
||||
|
||||
return +count
|
||||
}
|
||||
|
||||
async incrementOutOfSyncIncidents(): Promise<void> {
|
||||
const pipeline = this.redisClient.pipeline()
|
||||
|
||||
pipeline.incr(`count:action:out-of-sync:timespan:${this.periodKeyGenerator.getPeriodKey(Period.Today)}`)
|
||||
pipeline.incr(`count:action:out-of-sync:timespan:${this.periodKeyGenerator.getPeriodKey(Period.ThisWeek)}`)
|
||||
pipeline.incr(`count:action:out-of-sync:timespan:${this.periodKeyGenerator.getPeriodKey(Period.ThisMonth)}`)
|
||||
|
||||
await pipeline.exec()
|
||||
}
|
||||
|
||||
async getYesterdaySNJSUsage(): Promise<{ version: string; count: number }[]> {
|
||||
const keys = await this.redisClient.keys(
|
||||
`count:action:snjs-request:*:timespan:${this.periodKeyGenerator.getPeriodKey(Period.Yesterday)}`,
|
||||
)
|
||||
|
||||
return this.getRequestCountPerVersion(keys)
|
||||
}
|
||||
|
||||
async getYesterdayApplicationUsage(): Promise<{ version: string; count: number }[]> {
|
||||
const keys = await this.redisClient.keys(
|
||||
`count:action:application-request:*:timespan:${this.periodKeyGenerator.getPeriodKey(Period.Yesterday)}`,
|
||||
)
|
||||
|
||||
return this.getRequestCountPerVersion(keys)
|
||||
}
|
||||
|
||||
async incrementApplicationVersionUsage(applicationVersion: string): Promise<void> {
|
||||
const pipeline = this.redisClient.pipeline()
|
||||
|
||||
pipeline.incr(
|
||||
`count:action:application-request:${applicationVersion}:timespan:${this.periodKeyGenerator.getPeriodKey(
|
||||
Period.Today,
|
||||
)}`,
|
||||
)
|
||||
pipeline.incr(
|
||||
`count:action:application-request:${applicationVersion}:timespan:${this.periodKeyGenerator.getPeriodKey(
|
||||
Period.ThisWeek,
|
||||
)}`,
|
||||
)
|
||||
pipeline.incr(
|
||||
`count:action:application-request:${applicationVersion}:timespan:${this.periodKeyGenerator.getPeriodKey(
|
||||
Period.ThisMonth,
|
||||
)}`,
|
||||
)
|
||||
|
||||
await pipeline.exec()
|
||||
}
|
||||
|
||||
async incrementSNJSVersionUsage(snjsVersion: string): Promise<void> {
|
||||
const pipeline = this.redisClient.pipeline()
|
||||
|
||||
pipeline.incr(
|
||||
`count:action:snjs-request:${snjsVersion}:timespan:${this.periodKeyGenerator.getPeriodKey(Period.Today)}`,
|
||||
)
|
||||
pipeline.incr(
|
||||
`count:action:snjs-request:${snjsVersion}:timespan:${this.periodKeyGenerator.getPeriodKey(Period.ThisWeek)}`,
|
||||
)
|
||||
pipeline.incr(
|
||||
`count:action:snjs-request:${snjsVersion}:timespan:${this.periodKeyGenerator.getPeriodKey(Period.ThisMonth)}`,
|
||||
)
|
||||
|
||||
await pipeline.exec()
|
||||
}
|
||||
|
||||
private async getRequestCountPerVersion(keys: string[]): Promise<{ version: string; count: number }[]> {
|
||||
const statistics = []
|
||||
for (const key of keys) {
|
||||
const count = await this.redisClient.get(key)
|
||||
const version = key.split(':')[3]
|
||||
statistics.push({
|
||||
version,
|
||||
count: +(count as string),
|
||||
})
|
||||
}
|
||||
|
||||
return statistics
|
||||
}
|
||||
}
|
||||
2
packages/analytics/src/Infra/index.ts
Normal file
2
packages/analytics/src/Infra/index.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
export * from './Redis/RedisAnalyticsStore'
|
||||
export * from './Redis/RedisStatisticsStore'
|
||||
2
packages/analytics/src/index.ts
Normal file
2
packages/analytics/src/index.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
export * from './Domain'
|
||||
export * from './Infra'
|
||||
11
packages/analytics/tsconfig.json
Normal file
11
packages/analytics/tsconfig.json
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"composite": true,
|
||||
"outDir": "./dist",
|
||||
},
|
||||
"include": [
|
||||
"src/**/*"
|
||||
],
|
||||
"references": []
|
||||
}
|
||||
@@ -3,6 +3,40 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.6.1](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.6.0...@standardnotes/api-gateway@1.6.1) (2022-07-06)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/api-gateway
|
||||
|
||||
# [1.6.0](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.5.0...@standardnotes/api-gateway@1.6.0) (2022-07-06)
|
||||
|
||||
### Features
|
||||
|
||||
* add time package ([565e890](https://github.com/standardnotes/api-gateway/commit/565e890973b1d96544bb750fdd700d58f8dad088))
|
||||
|
||||
# [1.5.0](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.4.2...@standardnotes/api-gateway@1.5.0) (2022-07-06)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* deps to @standarnotes/security ([699164e](https://github.com/standardnotes/api-gateway/commit/699164eba553cd07fb50f7a06ae8991028167603))
|
||||
|
||||
### Features
|
||||
|
||||
* add security package ([d86928f](https://github.com/standardnotes/api-gateway/commit/d86928f1b4b5feda8c330ed8ee0bf9de0fc12ae7))
|
||||
|
||||
## [1.4.2](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.4.1...@standardnotes/api-gateway@1.4.2) (2022-07-06)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/api-gateway
|
||||
|
||||
## [1.4.1](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.4.0...@standardnotes/api-gateway@1.4.1) (2022-07-06)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/api-gateway
|
||||
|
||||
# [1.4.0](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.3.5...@standardnotes/api-gateway@1.4.0) (2022-07-06)
|
||||
|
||||
### Features
|
||||
|
||||
* add analytics package ([14e4ca7](https://github.com/standardnotes/api-gateway/commit/14e4ca70b438dd3eaaa404bc0ca31d22a62b45be))
|
||||
|
||||
## [1.3.5](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.3.4...@standardnotes/api-gateway@1.3.5) (2022-07-06)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/api-gateway",
|
||||
"version": "1.3.5",
|
||||
"version": "1.6.1",
|
||||
"engines": {
|
||||
"node": ">=16.0.0 <17.0.0"
|
||||
},
|
||||
@@ -24,11 +24,11 @@
|
||||
"dependencies": {
|
||||
"@newrelic/winston-enricher": "^2.1.0",
|
||||
"@sentry/node": "^7.3.0",
|
||||
"@standardnotes/analytics": "^1.6.0",
|
||||
"@standardnotes/auth": "3.19.4",
|
||||
"@standardnotes/analytics": "workspace:*",
|
||||
"@standardnotes/domain-events": "workspace:*",
|
||||
"@standardnotes/domain-events-infra": "workspace:*",
|
||||
"@standardnotes/time": "^1.7.1",
|
||||
"@standardnotes/security": "workspace:*",
|
||||
"@standardnotes/time": "workspace:*",
|
||||
"aws-sdk": "^2.1160.0",
|
||||
"axios": "0.24.0",
|
||||
"cors": "2.8.5",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { CrossServiceTokenData } from '@standardnotes/auth'
|
||||
import { CrossServiceTokenData } from '@standardnotes/security'
|
||||
import { TimerInterface } from '@standardnotes/time'
|
||||
import { NextFunction, Request, Response } from 'express'
|
||||
import { inject, injectable } from 'inversify'
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { OfflineUserTokenData, CrossServiceTokenData } from '@standardnotes/auth'
|
||||
import { OfflineUserTokenData, CrossServiceTokenData } from '@standardnotes/security'
|
||||
import { NextFunction, Request, Response } from 'express'
|
||||
import { inject, injectable } from 'inversify'
|
||||
import { BaseMiddleware } from 'inversify-express-utils'
|
||||
|
||||
@@ -3,6 +3,66 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [1.11.0](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.10.0...@standardnotes/auth-server@1.11.0) (2022-07-11)
|
||||
|
||||
### Features
|
||||
|
||||
* add event store package ([84ff915](https://github.com/standardnotes/server/commit/84ff915a565e8e64410c4bf97a30d359649825c7))
|
||||
|
||||
# [1.10.0](https://github.com/standardnotes/auth/compare/@standardnotes/auth-server@1.9.0...@standardnotes/auth-server@1.10.0) (2022-07-06)
|
||||
|
||||
### Features
|
||||
|
||||
* add sncryptio-node package ([60e8974](https://github.com/standardnotes/auth/commit/60e8974580d498e7edf80813c32268a8bf7eda39))
|
||||
|
||||
# [1.9.0](https://github.com/standardnotes/auth/compare/@standardnotes/auth-server@1.8.0...@standardnotes/auth-server@1.9.0) (2022-07-06)
|
||||
|
||||
### Features
|
||||
|
||||
* add settings package ([e7e34f3](https://github.com/standardnotes/auth/commit/e7e34f3e16eb865f083b7b49b2f8f83fd8af8de0))
|
||||
|
||||
# [1.8.0](https://github.com/standardnotes/auth/compare/@standardnotes/auth-server@1.7.0...@standardnotes/auth-server@1.8.0) (2022-07-06)
|
||||
|
||||
### Features
|
||||
|
||||
* add common package ([fd4ee21](https://github.com/standardnotes/auth/commit/fd4ee2123dc72b4d8755504d57bced608c1ab928))
|
||||
|
||||
# [1.7.0](https://github.com/standardnotes/auth/compare/@standardnotes/auth-server@1.6.0...@standardnotes/auth-server@1.7.0) (2022-07-06)
|
||||
|
||||
### Features
|
||||
|
||||
* add time package ([565e890](https://github.com/standardnotes/auth/commit/565e890973b1d96544bb750fdd700d58f8dad088))
|
||||
|
||||
# [1.6.0](https://github.com/standardnotes/auth/compare/@standardnotes/auth-server@1.5.1...@standardnotes/auth-server@1.6.0) (2022-07-06)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* deps to @standarnotes/security ([699164e](https://github.com/standardnotes/auth/commit/699164eba553cd07fb50f7a06ae8991028167603))
|
||||
|
||||
### Features
|
||||
|
||||
* add security package ([d86928f](https://github.com/standardnotes/auth/commit/d86928f1b4b5feda8c330ed8ee0bf9de0fc12ae7))
|
||||
|
||||
## [1.5.1](https://github.com/standardnotes/auth/compare/@standardnotes/auth-server@1.5.0...@standardnotes/auth-server@1.5.1) (2022-07-06)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/auth-server
|
||||
|
||||
# [1.5.0](https://github.com/standardnotes/auth/compare/@standardnotes/auth-server@1.4.0...@standardnotes/auth-server@1.5.0) (2022-07-06)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* scheduler to predicates imports ([1b35cf7](https://github.com/standardnotes/auth/commit/1b35cf7a392fbe6c4b49889f92ffab6ddd7bb181))
|
||||
|
||||
### Features
|
||||
|
||||
* add predicates package ([ed62ed5](https://github.com/standardnotes/auth/commit/ed62ed516f5cf8784975f41680366bf0518ce491))
|
||||
|
||||
# [1.4.0](https://github.com/standardnotes/auth/compare/@standardnotes/auth-server@1.3.14...@standardnotes/auth-server@1.4.0) (2022-07-06)
|
||||
|
||||
### Features
|
||||
|
||||
* add analytics package ([14e4ca7](https://github.com/standardnotes/auth/commit/14e4ca70b438dd3eaaa404bc0ca31d22a62b45be))
|
||||
|
||||
## [1.3.14](https://github.com/standardnotes/auth/compare/@standardnotes/auth-server@1.3.13...@standardnotes/auth-server@1.3.14) (2022-07-06)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/auth-server",
|
||||
"version": "1.3.14",
|
||||
"version": "1.11.0",
|
||||
"engines": {
|
||||
"node": ">=16.0.0 <17.0.0"
|
||||
},
|
||||
@@ -8,7 +8,6 @@
|
||||
"description": "Auth Server",
|
||||
"main": "dist/src/index.js",
|
||||
"typings": "dist/src/index.d.ts",
|
||||
"repository": "git@github.com:standardnotes/auth.git",
|
||||
"author": "Karol Sójko <karolsojko@standardnotes.com>",
|
||||
"license": "AGPL-3.0-or-later",
|
||||
"scripts": {
|
||||
@@ -33,19 +32,19 @@
|
||||
"dependencies": {
|
||||
"@newrelic/winston-enricher": "^2.1.0",
|
||||
"@sentry/node": "^7.3.0",
|
||||
"@standardnotes/analytics": "^1.6.0",
|
||||
"@standardnotes/analytics": "workspace:*",
|
||||
"@standardnotes/api": "^1.1.19",
|
||||
"@standardnotes/auth": "^3.19.4",
|
||||
"@standardnotes/common": "^1.23.1",
|
||||
"@standardnotes/common": "workspace:*",
|
||||
"@standardnotes/domain-events": "workspace:*",
|
||||
"@standardnotes/domain-events-infra": "workspace:*",
|
||||
"@standardnotes/features": "^1.47.0",
|
||||
"@standardnotes/predicates": "workspace:*",
|
||||
"@standardnotes/responses": "^1.6.39",
|
||||
"@standardnotes/scheduler": "^1.1.2",
|
||||
"@standardnotes/settings": "^1.15.0",
|
||||
"@standardnotes/security": "workspace:*",
|
||||
"@standardnotes/settings": "workspace:*",
|
||||
"@standardnotes/sncrypto-common": "^1.9.0",
|
||||
"@standardnotes/sncrypto-node": "^1.8.3",
|
||||
"@standardnotes/time": "^1.7.1",
|
||||
"@standardnotes/sncrypto-node": "workspace:*",
|
||||
"@standardnotes/time": "workspace:*",
|
||||
"aws-sdk": "^2.1159.0",
|
||||
"axios": "0.24.0",
|
||||
"bcryptjs": "2.4.3",
|
||||
|
||||
@@ -143,7 +143,7 @@ import {
|
||||
TokenEncoder,
|
||||
TokenEncoderInterface,
|
||||
ValetTokenData,
|
||||
} from '@standardnotes/auth'
|
||||
} from '@standardnotes/security'
|
||||
import { FileUploadedEventHandler } from '../Domain/Handler/FileUploadedEventHandler'
|
||||
import { CreateValetToken } from '../Domain/UseCase/CreateValetToken/CreateValetToken'
|
||||
import { CreateListedAccount } from '../Domain/UseCase/CreateListedAccount/CreateListedAccount'
|
||||
|
||||
@@ -3,7 +3,7 @@ import 'reflect-metadata'
|
||||
import { ApiGatewayAuthMiddleware } from './ApiGatewayAuthMiddleware'
|
||||
import { NextFunction, Request, Response } from 'express'
|
||||
import { Logger } from 'winston'
|
||||
import { CrossServiceTokenData, TokenDecoderInterface } from '@standardnotes/auth'
|
||||
import { CrossServiceTokenData, TokenDecoderInterface } from '@standardnotes/security'
|
||||
import { RoleName } from '@standardnotes/common'
|
||||
|
||||
describe('ApiGatewayAuthMiddleware', () => {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { CrossServiceTokenData, TokenDecoderInterface } from '@standardnotes/auth'
|
||||
import { CrossServiceTokenData, TokenDecoderInterface } from '@standardnotes/security'
|
||||
import { NextFunction, Request, Response } from 'express'
|
||||
import { inject, injectable } from 'inversify'
|
||||
import { BaseMiddleware } from 'inversify-express-utils'
|
||||
|
||||
@@ -3,7 +3,7 @@ import 'reflect-metadata'
|
||||
import { ApiGatewayOfflineAuthMiddleware } from './ApiGatewayOfflineAuthMiddleware'
|
||||
import { NextFunction, Request, Response } from 'express'
|
||||
import { Logger } from 'winston'
|
||||
import { OfflineUserTokenData, TokenDecoderInterface } from '@standardnotes/auth'
|
||||
import { OfflineUserTokenData, TokenDecoderInterface } from '@standardnotes/security'
|
||||
|
||||
describe('ApiGatewayOfflineAuthMiddleware', () => {
|
||||
let tokenDecoder: TokenDecoderInterface<OfflineUserTokenData>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { OfflineUserTokenData, TokenDecoderInterface } from '@standardnotes/auth'
|
||||
import { OfflineUserTokenData, TokenDecoderInterface } from '@standardnotes/security'
|
||||
import { NextFunction, Request, Response } from 'express'
|
||||
import { inject, injectable } from 'inversify'
|
||||
import { BaseMiddleware } from 'inversify-express-utils'
|
||||
|
||||
@@ -11,7 +11,7 @@ import { CreateOfflineSubscriptionTokenResponse } from '../Domain/UseCase/Create
|
||||
import { AuthenticateOfflineSubscriptionToken } from '../Domain/UseCase/AuthenticateOfflineSubscriptionToken/AuthenticateOfflineSubscriptionToken'
|
||||
import { OfflineUserSubscription } from '../Domain/Subscription/OfflineUserSubscription'
|
||||
import { GetUserOfflineSubscription } from '../Domain/UseCase/GetUserOfflineSubscription/GetUserOfflineSubscription'
|
||||
import { OfflineUserTokenData, TokenEncoderInterface } from '@standardnotes/auth'
|
||||
import { OfflineUserTokenData, TokenEncoderInterface } from '@standardnotes/security'
|
||||
import { SubscriptionName } from '@standardnotes/common'
|
||||
import { Logger } from 'winston'
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ import { AuthenticateOfflineSubscriptionToken } from '../Domain/UseCase/Authenti
|
||||
import { CreateOfflineSubscriptionToken } from '../Domain/UseCase/CreateOfflineSubscriptionToken/CreateOfflineSubscriptionToken'
|
||||
import { GetUserOfflineSubscription } from '../Domain/UseCase/GetUserOfflineSubscription/GetUserOfflineSubscription'
|
||||
import { Logger } from 'winston'
|
||||
import { OfflineUserTokenData, TokenEncoderInterface } from '@standardnotes/auth'
|
||||
import { OfflineUserTokenData, TokenEncoderInterface } from '@standardnotes/security'
|
||||
|
||||
@controller('/offline')
|
||||
export class OfflineController extends BaseHttpController {
|
||||
|
||||
@@ -10,7 +10,7 @@ import { GetActiveSessionsForUser } from '../Domain/UseCase/GetActiveSessionsFor
|
||||
import { AuthenticateRequest } from '../Domain/UseCase/AuthenticateRequest'
|
||||
import { User } from '../Domain/User/User'
|
||||
import { Role } from '../Domain/Role/Role'
|
||||
import { CrossServiceTokenData, TokenEncoderInterface } from '@standardnotes/auth'
|
||||
import { CrossServiceTokenData, TokenEncoderInterface } from '@standardnotes/security'
|
||||
import { GetUserAnalyticsId } from '../Domain/UseCase/GetUserAnalyticsId/GetUserAnalyticsId'
|
||||
|
||||
describe('SessionsController', () => {
|
||||
|
||||
@@ -16,7 +16,7 @@ import { Role } from '../Domain/Role/Role'
|
||||
import { User } from '../Domain/User/User'
|
||||
import { ProjectorInterface } from '../Projection/ProjectorInterface'
|
||||
import { SessionProjector } from '../Projection/SessionProjector'
|
||||
import { CrossServiceTokenData, TokenEncoderInterface } from '@standardnotes/auth'
|
||||
import { CrossServiceTokenData, TokenEncoderInterface } from '@standardnotes/security'
|
||||
import { RoleName } from '@standardnotes/common'
|
||||
import { GetUserAnalyticsId } from '../Domain/UseCase/GetUserAnalyticsId/GetUserAnalyticsId'
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Role } from '@standardnotes/auth'
|
||||
import { Role } from '@standardnotes/security'
|
||||
import { Request, Response } from 'express'
|
||||
import { inject } from 'inversify'
|
||||
import {
|
||||
|
||||
@@ -12,7 +12,7 @@ import { ProjectorInterface } from '../Projection/ProjectorInterface'
|
||||
import { Role } from '../Domain/Role/Role'
|
||||
import { SettingServiceInterface } from '../Domain/Setting/SettingServiceInterface'
|
||||
import { Setting } from '../Domain/Setting/Setting'
|
||||
import { CrossServiceTokenData, TokenEncoderInterface } from '@standardnotes/auth'
|
||||
import { CrossServiceTokenData, TokenEncoderInterface } from '@standardnotes/security'
|
||||
import { GetUserAnalyticsId } from '../Domain/UseCase/GetUserAnalyticsId/GetUserAnalyticsId'
|
||||
|
||||
describe('SubscriptionTokensController', () => {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { CrossServiceTokenData, TokenEncoderInterface } from '@standardnotes/auth'
|
||||
import { CrossServiceTokenData, TokenEncoderInterface } from '@standardnotes/security'
|
||||
import { ErrorTag, RoleName } from '@standardnotes/common'
|
||||
import { SettingName } from '@standardnotes/settings'
|
||||
import { Request, Response } from 'express'
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import 'reflect-metadata'
|
||||
|
||||
import { SessionTokenData, TokenEncoderInterface } from '@standardnotes/auth'
|
||||
import { SessionTokenData, TokenEncoderInterface } from '@standardnotes/security'
|
||||
import { Logger } from 'winston'
|
||||
|
||||
import { ProjectorInterface } from '../../Projection/ProjectorInterface'
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { SessionTokenData, TokenEncoderInterface } from '@standardnotes/auth'
|
||||
import { SessionTokenData, TokenEncoderInterface } from '@standardnotes/security'
|
||||
import { Uuid } from '@standardnotes/common'
|
||||
import * as crypto from 'crypto'
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { SessionTokenData, TokenEncoderInterface } from '@standardnotes/auth'
|
||||
import { SessionTokenData, TokenEncoderInterface } from '@standardnotes/security'
|
||||
import 'reflect-metadata'
|
||||
import { Logger } from 'winston'
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import 'reflect-metadata'
|
||||
|
||||
import { SessionTokenData, TokenEncoderInterface } from '@standardnotes/auth'
|
||||
import { SessionTokenData, TokenEncoderInterface } from '@standardnotes/security'
|
||||
import { SessionBody } from '@standardnotes/responses'
|
||||
import { Logger } from 'winston'
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ import {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
SessionTokenData,
|
||||
TokenEncoderInterface,
|
||||
} from '@standardnotes/auth'
|
||||
} from '@standardnotes/security'
|
||||
import { Uuid } from '@standardnotes/common'
|
||||
import { SessionBody } from '@standardnotes/responses'
|
||||
import { inject, injectable } from 'inversify'
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import 'reflect-metadata'
|
||||
|
||||
import { SessionTokenData, TokenDecoderInterface } from '@standardnotes/auth'
|
||||
import { SessionTokenData, TokenDecoderInterface } from '@standardnotes/security'
|
||||
|
||||
import { RevokedSession } from '../Session/RevokedSession'
|
||||
import { Session } from '../Session/Session'
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { SessionTokenData, TokenDecoderInterface } from '@standardnotes/auth'
|
||||
import { SessionTokenData, TokenDecoderInterface } from '@standardnotes/security'
|
||||
import { inject, injectable } from 'inversify'
|
||||
import TYPES from '../../Bootstrap/Types'
|
||||
import { SessionServiceInterface } from '../Session/SessionServiceInterface'
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import 'reflect-metadata'
|
||||
|
||||
import { EmailMessageIdentifier, RoleName } from '@standardnotes/common'
|
||||
import { PredicateName, PredicateAuthority, PredicateVerificationResult } from '@standardnotes/scheduler'
|
||||
import { PredicateName, PredicateAuthority, PredicateVerificationResult } from '@standardnotes/predicates'
|
||||
import { TimerInterface } from '@standardnotes/time'
|
||||
|
||||
import { DomainEventFactory } from './DomainEventFactory'
|
||||
|
||||
@@ -16,7 +16,7 @@ import {
|
||||
DomainEventService,
|
||||
EmailMessageRequestedEvent,
|
||||
} from '@standardnotes/domain-events'
|
||||
import { Predicate, PredicateVerificationResult } from '@standardnotes/scheduler'
|
||||
import { Predicate, PredicateVerificationResult } from '@standardnotes/predicates'
|
||||
import { TimerInterface } from '@standardnotes/time'
|
||||
import { inject, injectable } from 'inversify'
|
||||
import TYPES from '../../Bootstrap/Types'
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Uuid, RoleName, EmailMessageIdentifier } from '@standardnotes/common'
|
||||
import { Predicate, PredicateVerificationResult } from '@standardnotes/scheduler'
|
||||
import { Predicate, PredicateVerificationResult } from '@standardnotes/predicates'
|
||||
import {
|
||||
AccountDeletionRequestedEvent,
|
||||
CloudBackupRequestedEvent,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import 'reflect-metadata'
|
||||
|
||||
import { Role } from '@standardnotes/auth'
|
||||
import { Role } from '@standardnotes/security'
|
||||
import { RoleName, SubscriptionName } from '@standardnotes/common'
|
||||
|
||||
import { RoleToSubscriptionMapInterface } from '../Role/RoleToSubscriptionMapInterface'
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { DomainEventHandlerInterface, ExtensionKeyGrantedEvent } from '@standardnotes/domain-events'
|
||||
import { SettingName } from '@standardnotes/settings'
|
||||
import { OfflineFeaturesTokenData } from '@standardnotes/auth'
|
||||
import { OfflineFeaturesTokenData } from '@standardnotes/security'
|
||||
import { ContentDecoderInterface } from '@standardnotes/common'
|
||||
import { inject, injectable } from 'inversify'
|
||||
import { Logger } from 'winston'
|
||||
|
||||
@@ -7,7 +7,7 @@ import {
|
||||
PredicateVerificationRequestedEventPayload,
|
||||
PredicateVerifiedEvent,
|
||||
} from '@standardnotes/domain-events'
|
||||
import { Predicate, PredicateVerificationResult } from '@standardnotes/scheduler'
|
||||
import { Predicate, PredicateVerificationResult } from '@standardnotes/predicates'
|
||||
import { Logger } from 'winston'
|
||||
|
||||
import { DomainEventFactoryInterface } from '../Event/DomainEventFactoryInterface'
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { OfflineFeaturesTokenData } from '@standardnotes/auth'
|
||||
import { OfflineFeaturesTokenData } from '@standardnotes/security'
|
||||
import { DomainEventHandlerInterface, SubscriptionSyncRequestedEvent } from '@standardnotes/domain-events'
|
||||
import { inject, injectable } from 'inversify'
|
||||
import { Logger } from 'winston'
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import 'reflect-metadata'
|
||||
|
||||
import { TokenEncoderInterface, ValetTokenData } from '@standardnotes/auth'
|
||||
import { TokenEncoderInterface, ValetTokenData } from '@standardnotes/security'
|
||||
import { CreateValetToken } from './CreateValetToken'
|
||||
import { TimerInterface } from '@standardnotes/time'
|
||||
import { UserSubscription } from '../../Subscription/UserSubscription'
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { inject, injectable } from 'inversify'
|
||||
import { SubscriptionName } from '@standardnotes/common'
|
||||
import { TimerInterface } from '@standardnotes/time'
|
||||
import { TokenEncoderInterface, ValetTokenData } from '@standardnotes/auth'
|
||||
import { TokenEncoderInterface, ValetTokenData } from '@standardnotes/security'
|
||||
import { CreateValetTokenPayload, CreateValetTokenResponseData } from '@standardnotes/responses'
|
||||
import { SubscriptionSettingName } from '@standardnotes/settings'
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ import { VerifyMFA } from './VerifyMFA'
|
||||
import { Setting } from '../Setting/Setting'
|
||||
import { SettingServiceInterface } from '../Setting/SettingServiceInterface'
|
||||
import { SettingName } from '@standardnotes/settings'
|
||||
import { SelectorInterface } from '@standardnotes/auth'
|
||||
import { SelectorInterface } from '@standardnotes/security'
|
||||
import { LockRepositoryInterface } from '../User/LockRepositoryInterface'
|
||||
|
||||
describe('VerifyMFA', () => {
|
||||
|
||||
@@ -12,7 +12,7 @@ import { UseCaseInterface } from './UseCaseInterface'
|
||||
import { VerifyMFADTO } from './VerifyMFADTO'
|
||||
import { VerifyMFAResponse } from './VerifyMFAResponse'
|
||||
import { SettingServiceInterface } from '../Setting/SettingServiceInterface'
|
||||
import { SelectorInterface } from '@standardnotes/auth'
|
||||
import { SelectorInterface } from '@standardnotes/security'
|
||||
import { LockRepositoryInterface } from '../User/LockRepositoryInterface'
|
||||
|
||||
@injectable()
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import 'reflect-metadata'
|
||||
|
||||
import { PredicateName, PredicateVerificationResult, PredicateAuthority } from '@standardnotes/scheduler'
|
||||
import { PredicateName, PredicateVerificationResult, PredicateAuthority } from '@standardnotes/predicates'
|
||||
|
||||
import { Setting } from '../../Setting/Setting'
|
||||
import { SettingRepositoryInterface } from '../../Setting/SettingRepositoryInterface'
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Uuid } from '@standardnotes/common'
|
||||
import { PredicateName, PredicateVerificationResult } from '@standardnotes/scheduler'
|
||||
import { PredicateName, PredicateVerificationResult } from '@standardnotes/predicates'
|
||||
import { EmailBackupFrequency, SettingName } from '@standardnotes/settings'
|
||||
import { inject, injectable } from 'inversify'
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Uuid } from '@standardnotes/common'
|
||||
import { Predicate } from '@standardnotes/scheduler'
|
||||
import { Predicate } from '@standardnotes/predicates'
|
||||
|
||||
export type VerifyPredicateDTO = {
|
||||
predicate: Predicate
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { PredicateVerificationResult } from '@standardnotes/scheduler'
|
||||
import { PredicateVerificationResult } from '@standardnotes/predicates'
|
||||
|
||||
export type VerifyPredicateResponse = {
|
||||
predicateVerificationResult: PredicateVerificationResult
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import 'reflect-metadata'
|
||||
|
||||
import { SelectorInterface } from '@standardnotes/auth'
|
||||
import { SelectorInterface } from '@standardnotes/security'
|
||||
import { ProtocolVersion } from '@standardnotes/common'
|
||||
|
||||
import { KeyParamsFactory } from './KeyParamsFactory'
|
||||
|
||||
@@ -6,7 +6,7 @@ import { inject, injectable } from 'inversify'
|
||||
import TYPES from '../../Bootstrap/Types'
|
||||
import { KeyParamsFactoryInterface } from './KeyParamsFactoryInterface'
|
||||
import { User } from './User'
|
||||
import { SelectorInterface } from '@standardnotes/auth'
|
||||
import { SelectorInterface } from '@standardnotes/security'
|
||||
|
||||
@injectable()
|
||||
export class KeyParamsFactory implements KeyParamsFactoryInterface {
|
||||
|
||||
1
packages/common/.eslintignore
Normal file
1
packages/common/.eslintignore
Normal file
@@ -0,0 +1 @@
|
||||
dist
|
||||
6
packages/common/.eslintrc
Normal file
6
packages/common/.eslintrc
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"extends": "../../.eslintrc",
|
||||
"parserOptions": {
|
||||
"project": "./linter.tsconfig.json"
|
||||
}
|
||||
}
|
||||
264
packages/common/CHANGELOG.md
Normal file
264
packages/common/CHANGELOG.md
Normal file
@@ -0,0 +1,264 @@
|
||||
# Change Log
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# 1.25.0 (2022-07-06)
|
||||
|
||||
### Features
|
||||
|
||||
* add common package ([fd4ee21](https://github.com/standardnotes/server/commit/fd4ee2123dc72b4d8755504d57bced608c1ab928))
|
||||
|
||||
## [1.23.2](https://github.com/standardnotes/snjs/compare/@standardnotes/common@1.23.1...@standardnotes/common@1.23.2) (2022-07-04)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* add missing reflect-metadata package ([70aa494](https://github.com/standardnotes/snjs/commit/70aa4943a3fde70d4360055db22cb5388fc3f76e))
|
||||
|
||||
## [1.23.1](https://github.com/standardnotes/snjs/compare/@standardnotes/common@1.23.0...@standardnotes/common@1.23.1) (2022-06-27)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* add email message identifier for files email campaign ([affa300](https://github.com/standardnotes/snjs/commit/affa3005b6933165e262227282198310f0a65cb3))
|
||||
|
||||
# [1.23.0](https://github.com/standardnotes/snjs/compare/@standardnotes/common@1.22.0...@standardnotes/common@1.23.0) (2022-06-15)
|
||||
|
||||
### Features
|
||||
|
||||
* add email requested events ([4d501fa](https://github.com/standardnotes/snjs/commit/4d501faedad44ff23782db1704956a6c19365fb6))
|
||||
|
||||
# [1.22.0](https://github.com/standardnotes/snjs/compare/@standardnotes/common@1.21.0...@standardnotes/common@1.22.0) (2022-05-22)
|
||||
|
||||
### Features
|
||||
|
||||
* optional files navigation ([#745](https://github.com/standardnotes/snjs/issues/745)) ([8512166](https://github.com/standardnotes/snjs/commit/851216615478b57b11a570173f94ee598bec31c0))
|
||||
|
||||
# [1.21.0](https://github.com/standardnotes/snjs/compare/@standardnotes/common@1.20.1...@standardnotes/common@1.21.0) (2022-05-17)
|
||||
|
||||
### Features
|
||||
|
||||
* remove basic user role and core subscription plan ([#741](https://github.com/standardnotes/snjs/issues/741)) ([7800ecd](https://github.com/standardnotes/snjs/commit/7800ecd119e7bbb5872d48bd7806b5d0f5522c0e))
|
||||
|
||||
## [1.20.1](https://github.com/standardnotes/snjs/compare/@standardnotes/common@1.20.0...@standardnotes/common@1.20.1) (2022-05-16)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/common
|
||||
|
||||
# [1.20.0](https://github.com/standardnotes/snjs/compare/@standardnotes/common@1.19.8...@standardnotes/common@1.20.0) (2022-05-16)
|
||||
|
||||
### Features
|
||||
|
||||
* remove basic user role and core subscription plan names ([304e232](https://github.com/standardnotes/snjs/commit/304e232e738456a93374de869117b5579e8a8f57))
|
||||
|
||||
## [1.19.8](https://github.com/standardnotes/snjs/compare/@standardnotes/common@1.19.6...@standardnotes/common@1.19.8) (2022-05-04)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/common
|
||||
|
||||
## [1.19.7](https://github.com/standardnotes/snjs/compare/@standardnotes/common@1.19.6...@standardnotes/common@1.19.7) (2022-05-04)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/common
|
||||
|
||||
## [1.19.6](https://github.com/standardnotes/snjs/compare/@standardnotes/common@1.19.5...@standardnotes/common@1.19.6) (2022-04-22)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/common
|
||||
|
||||
## [1.19.5](https://github.com/standardnotes/snjs/compare/@standardnotes/common@1.19.4...@standardnotes/common@1.19.5) (2022-04-21)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* abort key recovery after aborted challenge ([#703](https://github.com/standardnotes/snjs/issues/703)) ([a67fb7e](https://github.com/standardnotes/snjs/commit/a67fb7e8cde41a5c9fadf545933e35d525faeaf0))
|
||||
|
||||
## [1.19.4](https://github.com/standardnotes/snjs/compare/@standardnotes/common@1.19.3...@standardnotes/common@1.19.4) (2022-04-15)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/common
|
||||
|
||||
## [1.19.3](https://github.com/standardnotes/snjs/compare/@standardnotes/common@1.19.2...@standardnotes/common@1.19.3) (2022-04-11)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/common
|
||||
|
||||
## [1.19.2](https://github.com/standardnotes/snjs/compare/@standardnotes/common@1.19.1...@standardnotes/common@1.19.2) (2022-04-01)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/common
|
||||
|
||||
## [1.19.1](https://github.com/standardnotes/snjs/compare/@standardnotes/common@1.19.0...@standardnotes/common@1.19.1) (2022-03-31)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/common
|
||||
|
||||
# [1.19.0](https://github.com/standardnotes/snjs/compare/@standardnotes/common@1.18.0...@standardnotes/common@1.19.0) (2022-03-31)
|
||||
|
||||
### Features
|
||||
|
||||
* encryption and models packages ([#679](https://github.com/standardnotes/snjs/issues/679)) ([5e03d48](https://github.com/standardnotes/snjs/commit/5e03d48aba7e3dd266117201139ab869b1f70cc9))
|
||||
|
||||
# [1.18.0](https://github.com/standardnotes/snjs/compare/@standardnotes/common@1.17.0...@standardnotes/common@1.18.0) (2022-03-30)
|
||||
|
||||
### Features
|
||||
|
||||
* files-beta role ([#678](https://github.com/standardnotes/snjs/issues/678)) ([f1ae62f](https://github.com/standardnotes/snjs/commit/f1ae62ff05e361dc551f1a0d047feabd129d0f76))
|
||||
|
||||
# [1.17.0](https://github.com/standardnotes/snjs/compare/@standardnotes/common@1.16.2...@standardnotes/common@1.17.0) (2022-03-22)
|
||||
|
||||
### Features
|
||||
|
||||
* add read only access error tag ([c3c7b4c](https://github.com/standardnotes/snjs/commit/c3c7b4c12f9b23dfc8e4bf1d4af43f6307f64190))
|
||||
|
||||
## [1.16.2](https://github.com/standardnotes/snjs/compare/@standardnotes/common@1.16.1...@standardnotes/common@1.16.2) (2022-03-21)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/common
|
||||
|
||||
## [1.16.1](https://github.com/standardnotes/snjs/compare/@standardnotes/common@1.16.0...@standardnotes/common@1.16.1) (2022-03-18)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* add demo user role ([aa7ebc8](https://github.com/standardnotes/snjs/commit/aa7ebc84ef1160688d2767b86a32719ce68a257b))
|
||||
|
||||
# [1.16.0](https://github.com/standardnotes/snjs/compare/@standardnotes/common@1.15.3...@standardnotes/common@1.16.0) (2022-03-16)
|
||||
|
||||
### Features
|
||||
|
||||
* delete file functionality ([#657](https://github.com/standardnotes/snjs/issues/657)) ([edec4f7](https://github.com/standardnotes/snjs/commit/edec4f7a65ef557ed5f47be4dddcf2b659ee28b4))
|
||||
|
||||
## [1.15.4](https://github.com/standardnotes/snjs/compare/@standardnotes/common@1.15.3...@standardnotes/common@1.15.4) (2022-03-16)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/common
|
||||
|
||||
## [1.15.3](https://github.com/standardnotes/snjs/compare/@standardnotes/common@1.15.1...@standardnotes/common@1.15.3) (2022-02-28)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* add pseudo change to get lerna to trigger ([41e6817](https://github.com/standardnotes/snjs/commit/41e6817bbf726b0932cdf16f58622328b9e42803))
|
||||
|
||||
## [1.15.2](https://github.com/standardnotes/snjs/compare/@standardnotes/common@1.15.1...@standardnotes/common@1.15.2) (2022-02-28)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* add pseudo change to get lerna to trigger ([41e6817](https://github.com/standardnotes/snjs/commit/41e6817bbf726b0932cdf16f58622328b9e42803))
|
||||
|
||||
## [1.15.1](https://github.com/standardnotes/snjs/compare/@standardnotes/common@1.15.0...@standardnotes/common@1.15.1) (2022-02-27)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/common
|
||||
|
||||
# [1.15.0](https://github.com/standardnotes/snjs/compare/@standardnotes/common@1.14.1...@standardnotes/common@1.15.0) (2022-02-25)
|
||||
|
||||
### Features
|
||||
|
||||
* extract core functionalities to separate packages ([#610](https://github.com/standardnotes/snjs/issues/610)) ([801547a](https://github.com/standardnotes/snjs/commit/801547a71614ad51a92fb249eaa184ed46a44aac))
|
||||
|
||||
## [1.14.1](https://github.com/standardnotes/snjs/compare/@standardnotes/common@1.14.0...@standardnotes/common@1.14.1) (2022-02-24)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/common
|
||||
|
||||
# [1.14.0](https://github.com/standardnotes/snjs/compare/@standardnotes/common@1.13.0...@standardnotes/common@1.14.0) (2022-02-22)
|
||||
|
||||
### Features
|
||||
|
||||
* extract services package ([#605](https://github.com/standardnotes/snjs/issues/605)) ([3966b10](https://github.com/standardnotes/snjs/commit/3966b10745c10ef5bb92871abb13ceb4ea631362))
|
||||
|
||||
# [1.13.0](https://github.com/standardnotes/snjs/compare/@standardnotes/common@1.12.0...@standardnotes/common@1.13.0) (2022-02-22)
|
||||
|
||||
### Features
|
||||
|
||||
* extract SNJS utils as a separate package ([#604](https://github.com/standardnotes/snjs/issues/604)) ([b28195c](https://github.com/standardnotes/snjs/commit/b28195c20be788eec8dabc44c5aff518f074cdd9))
|
||||
|
||||
# [1.12.0](https://github.com/standardnotes/snjs/compare/@standardnotes/common@1.11.0...@standardnotes/common@1.12.0) (2022-02-18)
|
||||
|
||||
### Features
|
||||
|
||||
* add item integrity hash model ([975474a](https://github.com/standardnotes/snjs/commit/975474a04c4b11edea381235fe38273db59fa770))
|
||||
|
||||
# [1.11.0](https://github.com/standardnotes/snjs/compare/@standardnotes/common@1.10.0...@standardnotes/common@1.11.0) (2022-02-16)
|
||||
|
||||
### Features
|
||||
|
||||
* add paid roles definition ([3432608](https://github.com/standardnotes/snjs/commit/34326086c16000397d994054e807dd3589b536db))
|
||||
|
||||
# [1.10.0](https://github.com/standardnotes/snjs/compare/@standardnotes/common@1.9.0...@standardnotes/common@1.10.0) (2022-02-10)
|
||||
|
||||
### Features
|
||||
|
||||
* move role names and suscription names from auth to common package ([5358c03](https://github.com/standardnotes/snjs/commit/5358c03ef113597bcdcf7b0f3e730c8014885a0f))
|
||||
|
||||
# [1.9.0](https://github.com/standardnotes/snjs/compare/@standardnotes/common@1.8.0...@standardnotes/common@1.9.0) (2022-02-07)
|
||||
|
||||
### Features
|
||||
|
||||
* dynamic features based on runtime env ([#590](https://github.com/standardnotes/snjs/issues/590)) ([060861a](https://github.com/standardnotes/snjs/commit/060861a6c5bc179e3e1987c2b63490888e153bbb))
|
||||
|
||||
# [1.8.0](https://github.com/standardnotes/snjs/compare/@standardnotes/common@1.7.0...@standardnotes/common@1.8.0) (2022-01-15)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* correct gitignore paths ([cefc0cf](https://github.com/standardnotes/snjs/commit/cefc0cfcf98e3e5378e055b8c46931b53b23195e))
|
||||
* include dist in static components ([d17ce0f](https://github.com/standardnotes/snjs/commit/d17ce0f67045c6e4c97bf4577709aa58794e72e6))
|
||||
|
||||
### Features
|
||||
|
||||
* remove server extension type ([#552](https://github.com/standardnotes/snjs/issues/552)) ([aa542f3](https://github.com/standardnotes/snjs/commit/aa542f3124c60fa81a0b271030b3c35415c54a62))
|
||||
|
||||
# 1.7.0 (2021-12-23)
|
||||
|
||||
### Features
|
||||
|
||||
* rename email backup setting to email backup frequency ([25e7b46](https://github.com/standardnotes/snjs/commit/25e7b4620834711ac7f513ae893898c5eab1af53))
|
||||
|
||||
## 1.6.3 (2021-12-23)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* lock package versions ([8aa2ce6](https://github.com/standardnotes/snjs/commit/8aa2ce676b57598ab72840adf851869d8e769022))
|
||||
|
||||
## 1.6.2 (2021-12-23)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* add publishing from package version by lerna ([80433d0](https://github.com/standardnotes/snjs/commit/80433d044f258095753482b8322d73aba3d9a9e4))
|
||||
|
||||
## 1.6.1 (2021-12-23)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* remove the ammend commit from lerna versioning ([f0400d9](https://github.com/standardnotes/snjs/commit/f0400d9a2f5a04eaece2e4c16da71166a2ddb251))
|
||||
|
||||
# 1.6.0 (2021-12-23)
|
||||
|
||||
### Features
|
||||
|
||||
* add one drive backup frequency setting ([#522](https://github.com/standardnotes/snjs/issues/522)) ([c27827f](https://github.com/standardnotes/snjs/commit/c27827f8c7969dd32511c9c75122ece372132c83))
|
||||
|
||||
## 1.5.4 (2021-12-23)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* remove running tests upon deployment - ensured on PR status checks ([#523](https://github.com/standardnotes/snjs/issues/523)) ([5c795d1](https://github.com/standardnotes/snjs/commit/5c795d17b583d02955773576384e622c3ef7f418))
|
||||
|
||||
## 1.5.3 (2021-12-23)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* pr template ([#518](https://github.com/standardnotes/snjs/issues/518)) ([b445bb6](https://github.com/standardnotes/snjs/commit/b445bb64841217ae27c2514887629235be95d2a3))
|
||||
|
||||
## 1.5.2 (2021-12-23)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* checkout with personal access token ([773c1ef](https://github.com/standardnotes/snjs/commit/773c1ef91c4452ad411e928342060dcb59428e3c))
|
||||
|
||||
## 1.5.1 (2021-12-22)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* gpg signing with CI StandardNotes user ([d72f61c](https://github.com/standardnotes/snjs/commit/d72f61c23cd15b31d37340cc756d16526634b9ee))
|
||||
|
||||
# 1.5.0 (2021-12-22)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* versioning and package dependencies ([#509](https://github.com/standardnotes/snjs/issues/509)) ([fe1df94](https://github.com/standardnotes/snjs/commit/fe1df94eff3e90bcf9ba0cf45bdc44ac49204c71))
|
||||
|
||||
### Features
|
||||
|
||||
* add content decoder to common package ([504cf10](https://github.com/standardnotes/snjs/commit/504cf10d83c9cba6e8ee79ce138847a293a2f9e0))
|
||||
* add ContentType to common package ([#401](https://github.com/standardnotes/snjs/issues/401)) ([1152c02](https://github.com/standardnotes/snjs/commit/1152c020e30e60996b4830b66e07ec4183bbac24))
|
||||
* add SN|Privileges to content types ([#444](https://github.com/standardnotes/snjs/issues/444)) ([0eee358](https://github.com/standardnotes/snjs/commit/0eee3581e5f9f41f227c824adc92a0e15b8fa4b4))
|
||||
* extract settings and common package ([#372](https://github.com/standardnotes/snjs/issues/372)) ([4f89688](https://github.com/standardnotes/snjs/commit/4f89688054cdae88c001287c9fb3431debd0136c))
|
||||
* remove legacy mfa ([#495](https://github.com/standardnotes/snjs/issues/495)) ([b0498f4](https://github.com/standardnotes/snjs/commit/b0498f4fad85367e1b57c6deacb5d313331bf8db))
|
||||
* upgrade node engine versions to latest active LTS ([#462](https://github.com/standardnotes/snjs/issues/462)) ([686fc15](https://github.com/standardnotes/snjs/commit/686fc15030d302b474ebb7ef1cd4dcc48ec42359))
|
||||
19
packages/common/jest.config.js
Normal file
19
packages/common/jest.config.js
Normal file
@@ -0,0 +1,19 @@
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
const base = require('../../jest.config');
|
||||
|
||||
module.exports = {
|
||||
...base,
|
||||
globals: {
|
||||
'ts-jest': {
|
||||
tsconfig: 'tsconfig.json',
|
||||
},
|
||||
},
|
||||
coverageThreshold: {
|
||||
global: {
|
||||
branches: 14,
|
||||
functions: 13,
|
||||
lines: 14,
|
||||
statements: 14
|
||||
}
|
||||
}
|
||||
};
|
||||
4
packages/common/linter.tsconfig.json
Normal file
4
packages/common/linter.tsconfig.json
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"exclude": ["dist"]
|
||||
}
|
||||
39
packages/common/package.json
Normal file
39
packages/common/package.json
Normal file
@@ -0,0 +1,39 @@
|
||||
{
|
||||
"name": "@standardnotes/common",
|
||||
"version": "1.25.0",
|
||||
"engines": {
|
||||
"node": ">=16.0.0 <17.0.0"
|
||||
},
|
||||
"description": "Common types and utilities for Standard Notes projects",
|
||||
"main": "dist/src/index.js",
|
||||
"author": "Standard Notes",
|
||||
"types": "dist/src/index.d.ts",
|
||||
"files": [
|
||||
"dist/src/**/*.js",
|
||||
"dist/src/**/*.d.ts"
|
||||
],
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"license": "AGPL-3.0-or-later",
|
||||
"scripts": {
|
||||
"clean": "rm -fr dist",
|
||||
"prestart": "yarn clean",
|
||||
"start": "tsc -p tsconfig.json --watch",
|
||||
"prebuild": "yarn clean",
|
||||
"build": "tsc -p tsconfig.json",
|
||||
"lint": "eslint . --ext .ts",
|
||||
"test:unit": "jest spec --coverage"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jest": "^27.4.1",
|
||||
"@types/node": "^18.0.0",
|
||||
"@typescript-eslint/eslint-plugin": "^5.30.0",
|
||||
"eslint-plugin-prettier": "^4.2.1",
|
||||
"jest": "^27.5.1",
|
||||
"ts-jest": "^27.1.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"reflect-metadata": "^0.1.13"
|
||||
}
|
||||
}
|
||||
37
packages/common/src/Domain/Content/ContentDecoder.spec.ts
Normal file
37
packages/common/src/Domain/Content/ContentDecoder.spec.ts
Normal file
@@ -0,0 +1,37 @@
|
||||
import 'reflect-metadata'
|
||||
|
||||
import { ContentDecoder } from './ContentDecoder'
|
||||
|
||||
describe('ContentDecoder', () => {
|
||||
const createDecoder = () => new ContentDecoder()
|
||||
|
||||
it('should decode content', () => {
|
||||
const content = '000eyJmb28iOiJiYXIifQ=='
|
||||
|
||||
expect(createDecoder().decode(content)).toEqual({
|
||||
foo: 'bar',
|
||||
})
|
||||
})
|
||||
|
||||
it('should decode content without padding', () => {
|
||||
const content = 'eyJmb28iOiJiYXIifQ=='
|
||||
|
||||
expect(createDecoder().decode(content, 0)).toEqual({
|
||||
foo: 'bar',
|
||||
})
|
||||
})
|
||||
|
||||
it('should encode content', () => {
|
||||
expect(
|
||||
createDecoder().encode({
|
||||
foo: 'bar',
|
||||
}),
|
||||
).toEqual('000eyJmb28iOiJiYXIifQ==')
|
||||
})
|
||||
|
||||
it('should return empty object on decoding failure', () => {
|
||||
const content = '032400eyJmb28iOiJiYXIifQ=='
|
||||
|
||||
expect(createDecoder().decode(content)).toEqual({})
|
||||
})
|
||||
})
|
||||
23
packages/common/src/Domain/Content/ContentDecoder.ts
Normal file
23
packages/common/src/Domain/Content/ContentDecoder.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
import { ContentDecoderInterface } from './ContentDecoderInterface'
|
||||
|
||||
export class ContentDecoder implements ContentDecoderInterface {
|
||||
decode(content: string, leftPaddingLength = 3): Record<string, unknown> {
|
||||
try {
|
||||
const contentToDecode = leftPaddingLength > 0 ? content.substring(leftPaddingLength) : content
|
||||
const contentBuffer = Buffer.from(contentToDecode, 'base64')
|
||||
const decodedContent = contentBuffer.toString()
|
||||
|
||||
return JSON.parse(decodedContent)
|
||||
} catch (error) {
|
||||
return {}
|
||||
}
|
||||
}
|
||||
|
||||
encode(content: Record<string, unknown>, leftPaddingLength = 3): string | undefined {
|
||||
const stringifiedContent = JSON.stringify(content)
|
||||
|
||||
const encodedContent = Buffer.from(stringifiedContent).toString('base64')
|
||||
|
||||
return encodedContent.padStart(encodedContent.length + leftPaddingLength, '0')
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
export interface ContentDecoderInterface {
|
||||
decode(content: string, leftPaddingLength?: number): Record<string, unknown>
|
||||
encode(content: Record<string, unknown>, leftPaddingLength?: number): string | undefined
|
||||
}
|
||||
44
packages/common/src/Domain/Content/ContentType.ts
Normal file
44
packages/common/src/Domain/Content/ContentType.ts
Normal file
@@ -0,0 +1,44 @@
|
||||
/* istanbul ignore file */
|
||||
export enum ContentType {
|
||||
Any = '*',
|
||||
Item = 'SF|Item',
|
||||
RootKey = 'SN|RootKey|NoSync',
|
||||
ItemsKey = 'SN|ItemsKey',
|
||||
EncryptedStorage = 'SN|EncryptedStorage',
|
||||
Privileges = 'SN|Privileges',
|
||||
Note = 'Note',
|
||||
Tag = 'Tag',
|
||||
SmartView = 'SN|SmartTag',
|
||||
Component = 'SN|Component',
|
||||
Editor = 'SN|Editor',
|
||||
ActionsExtension = 'Extension',
|
||||
UserPrefs = 'SN|UserPreferences',
|
||||
HistorySession = 'SN|HistorySession',
|
||||
Theme = 'SN|Theme',
|
||||
File = 'SN|File',
|
||||
FilesafeCredentials = 'SN|FileSafe|Credentials',
|
||||
FilesafeFileMetadata = 'SN|FileSafe|FileMetadata',
|
||||
FilesafeIntegration = 'SN|FileSafe|Integration',
|
||||
ExtensionRepo = 'SN|ExtensionRepo',
|
||||
Unknown = 'Unknown',
|
||||
}
|
||||
|
||||
export function DisplayStringForContentType(contentType: ContentType): string | undefined {
|
||||
const map: Partial<Record<ContentType, string>> = {
|
||||
[ContentType.ActionsExtension]: 'action-based extension',
|
||||
[ContentType.Component]: 'component',
|
||||
[ContentType.Editor]: 'editor',
|
||||
[ContentType.File]: 'file',
|
||||
[ContentType.FilesafeCredentials]: 'FileSafe credential',
|
||||
[ContentType.FilesafeFileMetadata]: 'FileSafe file',
|
||||
[ContentType.FilesafeIntegration]: 'FileSafe integration',
|
||||
[ContentType.ItemsKey]: 'encryption key',
|
||||
[ContentType.Note]: 'note',
|
||||
[ContentType.SmartView]: 'smart view',
|
||||
[ContentType.Tag]: 'tag',
|
||||
[ContentType.Theme]: 'theme',
|
||||
[ContentType.UserPrefs]: 'user preferences',
|
||||
}
|
||||
|
||||
return map[contentType]
|
||||
}
|
||||
2
packages/common/src/Domain/DataType/AnyRecord.ts
Normal file
2
packages/common/src/Domain/DataType/AnyRecord.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export type AnyRecord = Partial<Record<string, any>>
|
||||
@@ -0,0 +1 @@
|
||||
export type ApplicationIdentifier = string
|
||||
@@ -0,0 +1 @@
|
||||
export type MicrosecondsTimestamp = number
|
||||
1
packages/common/src/Domain/DataType/Uuid.ts
Normal file
1
packages/common/src/Domain/DataType/Uuid.ts
Normal file
@@ -0,0 +1 @@
|
||||
export type Uuid = string
|
||||
18
packages/common/src/Domain/Email/EmailMessageIdentifier.ts
Normal file
18
packages/common/src/Domain/Email/EmailMessageIdentifier.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
export enum EmailMessageIdentifier {
|
||||
WELCOME_EMAIL = 'WELCOME_EMAIL',
|
||||
ACCOUNT_CLAIM = 'ACCOUNT_CLAIM',
|
||||
ACTIVATION_CODE = 'ACTIVATION_CODE',
|
||||
VERSION_ADOPTION_REPORT = 'VERSION_ADOPTION_REPORT',
|
||||
FAILED_DROPBOX_BACKUP = 'FAILED_DROPBOX_BACKUP',
|
||||
FAILED_GOOGLE_DRIVE_BACKUP = 'FAILED_GOOGLE_DRIVE_BACKUP',
|
||||
FAILED_ONE_DRIVE_BACKUP = 'FAILED_ONE_DRIVE_BACKUP',
|
||||
DATA_BACKUP = 'DATA_BACKUP',
|
||||
FAILED_BACKUP_ATTACHMENT_TOO_BIG = 'FAILED_BACKUP_ATTACHMENT_TOO_BIG',
|
||||
OFFLINE_SUBSCRIPTION_ACCESS = 'OFFLINE_SUBSCRIPTION_ACCESS',
|
||||
SIGN_IN = 'SIGN_IN',
|
||||
SHARED_SUBSCRIPTION_INVITATION = 'SHARED_SUBSCRIPTION_INVITATION',
|
||||
ENCOURAGE_EMAIL_BACKUPS = 'ENCOURAGE_EMAIL_BACKUPS',
|
||||
ENCOURAGE_SUBSCRIPTION_PURCHASING = 'ENCOURAGE_SUBSCRIPTION_PURCHASING',
|
||||
EXIT_INTERVIEW = 'EXIT_INTERVIEW',
|
||||
MARKETING_CAMPAIGN_FILES = 'MARKETING_CAMPAIGN_FILES',
|
||||
}
|
||||
12
packages/common/src/Domain/Error/ErrorTag.ts
Normal file
12
packages/common/src/Domain/Error/ErrorTag.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
/* istanbul ignore file */
|
||||
export enum ErrorTag {
|
||||
MfaInvalid = 'mfa-invalid',
|
||||
MfaRequired = 'mfa-required',
|
||||
RefreshTokenInvalid = 'invalid-refresh-token',
|
||||
RefreshTokenExpired = 'expired-refresh-token',
|
||||
AccessTokenExpired = 'expired-access-token',
|
||||
ParametersInvalid = 'invalid-parameters',
|
||||
RevokedSession = 'revoked-session',
|
||||
AuthInvalid = 'invalid-auth',
|
||||
ReadOnlyAccess = 'read-only-access',
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
import { KeyParamsContent001 } from './KeyParamsContent001'
|
||||
import { KeyParamsContent002 } from './KeyParamsContent002'
|
||||
import { KeyParamsContent003 } from './KeyParamsContent003'
|
||||
import { KeyParamsContent004 } from './KeyParamsContent004'
|
||||
|
||||
export type AnyKeyParamsContent = KeyParamsContent001 | KeyParamsContent002 | KeyParamsContent003 | KeyParamsContent004
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user