mirror of
https://github.com/standardnotes/server
synced 2026-01-25 02:01:08 -05:00
Compare commits
33 Commits
@standardn
...
@standardn
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a986ee1ccb | ||
|
|
868b7d149a | ||
|
|
b1763b539e | ||
|
|
d21517abe6 | ||
|
|
7ef6765d5b | ||
|
|
11492977c9 | ||
|
|
4c45f1d2e5 | ||
|
|
55702bfcfa | ||
|
|
1236a594b5 | ||
|
|
9cf746f6af | ||
|
|
44a9ade3fc | ||
|
|
7064bd4c4c | ||
|
|
a02a26ebdc | ||
|
|
b92af6cec6 | ||
|
|
3091177700 | ||
|
|
be8838d338 | ||
|
|
84e8a5cc6e | ||
|
|
d5db578bfd | ||
|
|
7429f5c8e9 | ||
|
|
8c6cf9651d | ||
|
|
8668fec33d | ||
|
|
76e34131fb | ||
|
|
3c40ee4b4a | ||
|
|
5abd7ae32c | ||
|
|
09b3f9a0d7 | ||
|
|
19455ba6a7 | ||
|
|
7d042689f0 | ||
|
|
f43fbf1584 | ||
|
|
24c0cb8366 | ||
|
|
2236cc3828 | ||
|
|
039d44718a | ||
|
|
f075cd8c4d | ||
|
|
d133c5aacd |
5
.github/dependabot.yml
vendored
5
.github/dependabot.yml
vendored
@@ -85,6 +85,11 @@ updates:
|
||||
schedule:
|
||||
interval: "daily"
|
||||
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/packages/workspace"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
schedule:
|
||||
|
||||
2
.github/workflows/snjs.upgrade.event.yml
vendored
2
.github/workflows/snjs.upgrade.event.yml
vendored
@@ -24,7 +24,7 @@ jobs:
|
||||
git config --global user.name "standardci"
|
||||
git config --global user.email "ci@standardnotes.com"
|
||||
- name: Import GPG key
|
||||
uses: crazy-max/ghaction-import-gpg@v4
|
||||
uses: crazy-max/ghaction-import-gpg@v5
|
||||
with:
|
||||
gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY }}
|
||||
passphrase: ${{ secrets.PASSPHRASE }}
|
||||
|
||||
206
.github/workflows/workspace.release.yml
vendored
Normal file
206
.github/workflows/workspace.release.yml
vendored
Normal file
@@ -0,0 +1,206 @@
|
||||
name: Workspace Server
|
||||
|
||||
concurrency:
|
||||
group: workspace
|
||||
cancel-in-progress: true
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- '*standardnotes/workspace-server*'
|
||||
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'
|
||||
|
||||
- name: Build
|
||||
run: yarn build
|
||||
|
||||
- name: Lint
|
||||
run: yarn lint:workspace
|
||||
|
||||
- name: Test
|
||||
run: yarn test:workspace
|
||||
|
||||
- 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/workspace-server -t standardnotes/workspace:${{ github.sha }}
|
||||
docker push standardnotes/workspace:${{ github.sha }}
|
||||
|
||||
- name: Run E2E test suite
|
||||
uses: convictional/trigger-workflow-and-wait@v1.6.3
|
||||
with:
|
||||
owner: standardnotes
|
||||
repo: e2e
|
||||
github_token: ${{ secrets.CI_PAT_TOKEN }}
|
||||
workflow_file_name: testing-with-stable-client.yml
|
||||
wait_interval: 30
|
||||
client_payload: '{"workspace_image_tag": "${{ github.sha }}"}'
|
||||
propagate_failure: true
|
||||
trigger_workflow: true
|
||||
wait_workflow: true
|
||||
|
||||
publish-aws-ecr:
|
||||
needs: 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'
|
||||
- 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: workspace
|
||||
IMAGE_TAG: ${{ github.sha }}
|
||||
run: |
|
||||
yarn docker build @standardnotes/workspace-server -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: Set up Node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
registry-url: 'https://registry.npmjs.org'
|
||||
node-version-file: '.nvmrc'
|
||||
- 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: Publish Docker image as stable
|
||||
run: |
|
||||
yarn docker build @standardnotes/workspace-server -t standardnotes/workspace:latest
|
||||
docker push standardnotes/workspace:latest
|
||||
|
||||
deploy-web:
|
||||
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: Download task definition
|
||||
run: |
|
||||
aws ecs describe-task-definition --task-definition workspace-prod --query taskDefinition > task-definition.json
|
||||
- name: Fill in the new version in the Amazon ECS task definition
|
||||
run: |
|
||||
jq '(.containerDefinitions[] | select(.name=="workspace-prod") | .environment[] | select(.name=="VERSION")).value = "${{ github.sha }}"' task-definition.json > tmp.json && mv tmp.json task-definition.json
|
||||
- name: 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: workspace-prod
|
||||
image: ${{ secrets.AWS_ECR_REGISTRY }}/workspace:${{ github.sha }}
|
||||
- name: 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: workspace-prod
|
||||
cluster: prod
|
||||
wait-for-service-stability: true
|
||||
|
||||
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: Download task definition
|
||||
run: |
|
||||
aws ecs describe-task-definition --task-definition workspace-worker-prod --query taskDefinition > task-definition.json
|
||||
- name: Fill in the new version in the Amazon ECS task definition
|
||||
run: |
|
||||
jq '(.containerDefinitions[] | select(.name=="workspace-worker-prod") | .environment[] | select(.name=="VERSION")).value = "${{ github.sha }}"' task-definition.json > tmp.json && mv tmp.json task-definition.json
|
||||
- name: 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: workspace-worker-prod
|
||||
image: ${{ secrets.AWS_ECR_REGISTRY }}/workspace:${{ github.sha }}
|
||||
- name: 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: workspace-worker-prod
|
||||
cluster: prod
|
||||
wait-for-service-stability: true
|
||||
|
||||
newrelic:
|
||||
needs: [ deploy-web, deploy-worker ]
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Create New Relic deployment marker for Web
|
||||
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_WORKSPACE_WEB_PROD }}
|
||||
revision: "${{ github.sha }}"
|
||||
description: "Automated Deployment via Github Actions"
|
||||
user: "${{ github.actor }}"
|
||||
- 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_WORKSPACE_WORKER_PROD }}
|
||||
revision: "${{ github.sha }}"
|
||||
description: "Automated Deployment via Github Actions"
|
||||
user: "${{ github.actor }}"
|
||||
BIN
.yarn/cache/@babel-plugin-syntax-jsx-npm-7.18.6-3e378d5f11-6d37ea9729.zip
vendored
Normal file
BIN
.yarn/cache/@babel-plugin-syntax-jsx-npm-7.18.6-3e378d5f11-6d37ea9729.zip
vendored
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
.yarn/cache/@jest-core-npm-29.1.2-35babb0cf6-a986c0a1a9.zip
vendored
Normal file
BIN
.yarn/cache/@jest-core-npm-29.1.2-35babb0cf6-a986c0a1a9.zip
vendored
Normal file
Binary file not shown.
Binary file not shown.
BIN
.yarn/cache/@jest-environment-npm-29.1.2-882fefe268-0846142900.zip
vendored
Normal file
BIN
.yarn/cache/@jest-environment-npm-29.1.2-882fefe268-0846142900.zip
vendored
Normal file
Binary file not shown.
Binary file not shown.
BIN
.yarn/cache/@jest-expect-npm-29.1.2-15666996b5-e7c5db9f95.zip
vendored
Normal file
BIN
.yarn/cache/@jest-expect-npm-29.1.2-15666996b5-e7c5db9f95.zip
vendored
Normal file
Binary file not shown.
Binary file not shown.
BIN
.yarn/cache/@jest-expect-utils-npm-29.1.2-4ea76b5f23-31c2a690b5.zip
vendored
Normal file
BIN
.yarn/cache/@jest-expect-utils-npm-29.1.2-4ea76b5f23-31c2a690b5.zip
vendored
Normal file
Binary file not shown.
Binary file not shown.
BIN
.yarn/cache/@jest-fake-timers-npm-29.1.2-b675511ad8-a5331ffdaa.zip
vendored
Normal file
BIN
.yarn/cache/@jest-fake-timers-npm-29.1.2-b675511ad8-a5331ffdaa.zip
vendored
Normal file
Binary file not shown.
Binary file not shown.
BIN
.yarn/cache/@jest-globals-npm-29.1.2-7d43900c81-4baffd630e.zip
vendored
Normal file
BIN
.yarn/cache/@jest-globals-npm-29.1.2-7d43900c81-4baffd630e.zip
vendored
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
.yarn/cache/@jest-schemas-npm-29.0.0-5d6c90262d-41355c78f0.zip
vendored
Normal file
BIN
.yarn/cache/@jest-schemas-npm-29.0.0-5d6c90262d-41355c78f0.zip
vendored
Normal file
Binary file not shown.
Binary file not shown.
BIN
.yarn/cache/@jest-source-map-npm-29.0.0-ab558ac87f-dd97bc5826.zip
vendored
Normal file
BIN
.yarn/cache/@jest-source-map-npm-29.0.0-ab558ac87f-dd97bc5826.zip
vendored
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
.yarn/cache/@jest-test-sequencer-npm-29.1.2-be7322c48e-5e08406319.zip
vendored
Normal file
BIN
.yarn/cache/@jest-test-sequencer-npm-29.1.2-be7322c48e-5e08406319.zip
vendored
Normal file
Binary file not shown.
Binary file not shown.
BIN
.yarn/cache/@jest-transform-npm-29.1.2-b6e3948a60-af1c4c0d13.zip
vendored
Normal file
BIN
.yarn/cache/@jest-transform-npm-29.1.2-b6e3948a60-af1c4c0d13.zip
vendored
Normal file
Binary file not shown.
Binary file not shown.
BIN
.yarn/cache/@jest-types-npm-29.1.2-0dbe55dc45-697fc72c37.zip
vendored
Normal file
BIN
.yarn/cache/@jest-types-npm-29.1.2-0dbe55dc45-697fc72c37.zip
vendored
Normal file
Binary file not shown.
BIN
.yarn/cache/@jridgewell-trace-mapping-npm-0.3.15-7357dbf648-38917e9c2b.zip
vendored
Normal file
BIN
.yarn/cache/@jridgewell-trace-mapping-npm-0.3.15-7357dbf648-38917e9c2b.zip
vendored
Normal file
Binary file not shown.
Binary file not shown.
BIN
.yarn/cache/@sinclair-typebox-npm-0.24.44-38506ddef6-773d9efc85.zip
vendored
Normal file
BIN
.yarn/cache/@sinclair-typebox-npm-0.24.44-38506ddef6-773d9efc85.zip
vendored
Normal file
Binary file not shown.
Binary file not shown.
BIN
.yarn/cache/@types-jest-npm-29.1.1-72eb10f82d-d9e6f7d6ab.zip
vendored
Normal file
BIN
.yarn/cache/@types-jest-npm-29.1.1-72eb10f82d-d9e6f7d6ab.zip
vendored
Normal file
Binary file not shown.
Binary file not shown.
BIN
.yarn/cache/babel-jest-npm-29.1.2-3410a1f3f5-7180628db0.zip
vendored
Normal file
BIN
.yarn/cache/babel-jest-npm-29.1.2-3410a1f3f5-7180628db0.zip
vendored
Normal file
Binary file not shown.
Binary file not shown.
BIN
.yarn/cache/babel-plugin-jest-hoist-npm-29.0.2-3febe9d556-e02ab2c56b.zip
vendored
Normal file
BIN
.yarn/cache/babel-plugin-jest-hoist-npm-29.0.2-3febe9d556-e02ab2c56b.zip
vendored
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
.yarn/cache/expect-npm-29.1.2-34e14175c0-578c61459e.zip
vendored
Normal file
BIN
.yarn/cache/expect-npm-29.1.2-34e14175c0-578c61459e.zip
vendored
Normal file
Binary file not shown.
Binary file not shown.
BIN
.yarn/cache/helmet-npm-6.0.0-2285459f57-0dd89d5b77.zip
vendored
Normal file
BIN
.yarn/cache/helmet-npm-6.0.0-2285459f57-0dd89d5b77.zip
vendored
Normal file
Binary file not shown.
Binary file not shown.
BIN
.yarn/cache/jest-changed-files-npm-29.0.0-86775e11cc-5642ace8cd.zip
vendored
Normal file
BIN
.yarn/cache/jest-changed-files-npm-29.0.0-86775e11cc-5642ace8cd.zip
vendored
Normal file
Binary file not shown.
Binary file not shown.
BIN
.yarn/cache/jest-circus-npm-29.1.2-34037f1c9c-27893239ba.zip
vendored
Normal file
BIN
.yarn/cache/jest-circus-npm-29.1.2-34037f1c9c-27893239ba.zip
vendored
Normal file
Binary file not shown.
Binary file not shown.
BIN
.yarn/cache/jest-cli-npm-29.1.2-80d7962004-2962060e3e.zip
vendored
Normal file
BIN
.yarn/cache/jest-cli-npm-29.1.2-80d7962004-2962060e3e.zip
vendored
Normal file
Binary file not shown.
Binary file not shown.
BIN
.yarn/cache/jest-config-npm-29.1.2-aade2f247f-095fdae03b.zip
vendored
Normal file
BIN
.yarn/cache/jest-config-npm-29.1.2-aade2f247f-095fdae03b.zip
vendored
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
.yarn/cache/jest-environment-node-npm-29.1.2-fc465c6ad1-9af99f8ede.zip
vendored
Normal file
BIN
.yarn/cache/jest-environment-node-npm-29.1.2-fc465c6ad1-9af99f8ede.zip
vendored
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
.yarn/cache/jest-leak-detector-npm-29.1.2-d76014ed8b-5a2de24ba8.zip
vendored
Normal file
BIN
.yarn/cache/jest-leak-detector-npm-29.1.2-d76014ed8b-5a2de24ba8.zip
vendored
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
.yarn/cache/jest-mock-npm-29.1.2-3b2739c55c-145817b10c.zip
vendored
Normal file
BIN
.yarn/cache/jest-mock-npm-29.1.2-3b2739c55c-145817b10c.zip
vendored
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
.yarn/cache/jest-resolve-npm-29.1.2-6c9d2562fb-3b91f61971.zip
vendored
Normal file
BIN
.yarn/cache/jest-resolve-npm-29.1.2-6c9d2562fb-3b91f61971.zip
vendored
Normal file
Binary file not shown.
Binary file not shown.
BIN
.yarn/cache/jest-runner-npm-29.1.2-f21e431614-717633249b.zip
vendored
Normal file
BIN
.yarn/cache/jest-runner-npm-29.1.2-f21e431614-717633249b.zip
vendored
Normal file
Binary file not shown.
Binary file not shown.
BIN
.yarn/cache/jest-runtime-npm-29.1.2-567b60ffd5-88011109a8.zip
vendored
Normal file
BIN
.yarn/cache/jest-runtime-npm-29.1.2-567b60ffd5-88011109a8.zip
vendored
Normal file
Binary file not shown.
Binary file not shown.
BIN
.yarn/cache/jest-snapshot-npm-29.1.2-8f38c86a98-fe2d57767c.zip
vendored
Normal file
BIN
.yarn/cache/jest-snapshot-npm-29.1.2-8f38c86a98-fe2d57767c.zip
vendored
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
.yarn/cache/jest-worker-npm-29.1.2-570b728071-788d14b2a0.zip
vendored
Normal file
BIN
.yarn/cache/jest-worker-npm-29.1.2-570b728071-788d14b2a0.zip
vendored
Normal file
Binary file not shown.
Binary file not shown.
BIN
.yarn/cache/pretty-format-npm-29.1.2-37c8a710ba-b2c6e77666.zip
vendored
Normal file
BIN
.yarn/cache/pretty-format-npm-29.1.2-37c8a710ba-b2c6e77666.zip
vendored
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
.yarn/cache/ts-jest-npm-29.0.3-c1e6bc8a8a-541e51776d.zip
vendored
Normal file
BIN
.yarn/cache/ts-jest-npm-29.0.3-c1e6bc8a8a-541e51776d.zip
vendored
Normal file
Binary file not shown.
@@ -2,11 +2,6 @@ module.exports = {
|
||||
preset: 'ts-jest',
|
||||
testEnvironment: 'node',
|
||||
testRegex: '(/__tests__/.*|(\\.|/)(test|spec))\\.ts$',
|
||||
globals: {
|
||||
'ts-jest': {
|
||||
tsconfig: './linter.tsconfig.json',
|
||||
},
|
||||
},
|
||||
testTimeout: 20000,
|
||||
coverageThreshold: {
|
||||
global: {
|
||||
|
||||
@@ -18,12 +18,14 @@
|
||||
"lint:files": "yarn workspace @standardnotes/files-server lint",
|
||||
"lint:api-gateway": "yarn workspace @standardnotes/api-gateway lint",
|
||||
"lint:event-store": "yarn workspace @standardnotes/event-store lint",
|
||||
"lint:workspace": "yarn workspace @standardnotes/workspace-server 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",
|
||||
"test:workspace": "yarn workspace @standardnotes/workspace-server 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",
|
||||
@@ -32,6 +34,7 @@
|
||||
"build:syncing-server": "yarn workspace @standardnotes/syncing-server build",
|
||||
"build:files": "yarn workspace @standardnotes/files-server build",
|
||||
"build:api-gateway": "yarn workspace @standardnotes/api-gateway build",
|
||||
"build:workspace": "yarn workspace @standardnotes/workspace-server build",
|
||||
"start:auth": "yarn workspace @standardnotes/auth-server start",
|
||||
"start:auth-worker": "yarn workspace @standardnotes/auth-server worker",
|
||||
"start:scheduler": "yarn workspace @standardnotes/scheduler-server worker",
|
||||
@@ -40,6 +43,7 @@
|
||||
"start:files": "yarn workspace @standardnotes/files-server start",
|
||||
"start:files-worker": "yarn workspace @standardnotes/files-server worker",
|
||||
"start:api-gateway": "yarn workspace @standardnotes/api-gateway start",
|
||||
"start:workspace": "yarn workspace @standardnotes/workspace-server start",
|
||||
"release": "lerna version --conventional-graduate --conventional-commits --yes -m \"chore(release): publish new version\"",
|
||||
"publish": "lerna publish from-git --yes --no-verify-access --loglevel verbose",
|
||||
"postversion": "./scripts/push-tags-one-by-one.sh",
|
||||
@@ -51,7 +55,7 @@
|
||||
"@lerna-lite/cli": "^1.5.1",
|
||||
"@lerna-lite/list": "^1.5.1",
|
||||
"@lerna-lite/run": "^1.5.1",
|
||||
"@types/jest": "^28.1.4",
|
||||
"@types/jest": "^29.1.1",
|
||||
"@types/newrelic": "^7.0.3",
|
||||
"@types/node": "^18.0.0",
|
||||
"@typescript-eslint/parser": "^5.29.0",
|
||||
|
||||
@@ -3,6 +3,28 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.35.1](https://github.com/standardnotes/server/compare/@standardnotes/analytics@1.35.0...@standardnotes/analytics@1.35.1) (2022-10-06)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/analytics
|
||||
|
||||
# [1.35.0](https://github.com/standardnotes/server/compare/@standardnotes/analytics@1.34.0...@standardnotes/analytics@1.35.0) (2022-10-05)
|
||||
|
||||
### Features
|
||||
|
||||
* **api-gateway:** include increments count in statistics measures report ([84e8a5c](https://github.com/standardnotes/server/commit/84e8a5cc6e6ba216f1c0737a7a93aba581eced0f))
|
||||
|
||||
# [1.34.0](https://github.com/standardnotes/server/compare/@standardnotes/analytics@1.33.0...@standardnotes/analytics@1.34.0) (2022-10-04)
|
||||
|
||||
### Features
|
||||
|
||||
* **analytics:** add new statistics measures for income ([19455ba](https://github.com/standardnotes/server/commit/19455ba6a7d84a389830c728c3dfea550b156985))
|
||||
|
||||
# [1.33.0](https://github.com/standardnotes/server/compare/@standardnotes/analytics@1.32.0...@standardnotes/analytics@1.33.0) (2022-10-03)
|
||||
|
||||
### Features
|
||||
|
||||
* add calculating monthly churn rate ([f075cd8](https://github.com/standardnotes/server/commit/f075cd8c4dfc411ba513dfec21bb84c03b238254))
|
||||
|
||||
# [1.32.0](https://github.com/standardnotes/server/compare/@standardnotes/analytics@1.31.1...@standardnotes/analytics@1.32.0) (2022-09-30)
|
||||
|
||||
### Features
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
const base = require('../../jest.config');
|
||||
const base = require('../../jest.config')
|
||||
const { defaults: tsjPreset } = require('ts-jest/presets')
|
||||
|
||||
module.exports = {
|
||||
...base,
|
||||
globals: {
|
||||
'ts-jest': {
|
||||
tsconfig: 'tsconfig.json',
|
||||
},
|
||||
transform: {
|
||||
...tsjPreset.transform,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/analytics",
|
||||
"version": "1.32.0",
|
||||
"version": "1.35.1",
|
||||
"engines": {
|
||||
"node": ">=14.0.0 <17.0.0"
|
||||
},
|
||||
@@ -27,12 +27,12 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/ioredis": "^4.28.10",
|
||||
"@types/jest": "^28.1.4",
|
||||
"@types/jest": "^29.1.1",
|
||||
"@typescript-eslint/eslint-plugin": "^5.30.0",
|
||||
"eslint-plugin-prettier": "^4.2.1",
|
||||
"ioredis": "^5.2.0",
|
||||
"jest": "^28.1.2",
|
||||
"ts-jest": "^28.0.5"
|
||||
"jest": "^29.1.2",
|
||||
"ts-jest": "^29.0.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"reflect-metadata": "^0.1.13"
|
||||
|
||||
@@ -12,7 +12,7 @@ export interface AnalyticsStoreInterface {
|
||||
secondActivity: AnalyticsActivity
|
||||
secondActivityPeriodKey: string
|
||||
}): Promise<number>
|
||||
calculateActivityTotalCount(activity: AnalyticsActivity, period: Period): Promise<number>
|
||||
calculateActivityTotalCount(activity: AnalyticsActivity, periodOrPeriodKey: Period | string): Promise<number>
|
||||
calculateActivityChangesTotalCount(
|
||||
activity: AnalyticsActivity,
|
||||
period: Period,
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
export enum StatisticsMeasure {
|
||||
Income = 'income',
|
||||
PlusSubscriptionInitialMonthlyPaymentsIncome = 'plus-subscription-initial-monthly-payments-income',
|
||||
ProSubscriptionInitialMonthlyPaymentsIncome = 'pro-subscription-initial-monthly-payments-income',
|
||||
PlusSubscriptionInitialAnnualPaymentsIncome = 'plus-subscription-initial-annual-payments-income',
|
||||
ProSubscriptionInitialAnnualPaymentsIncome = 'pro-subscription-initial-annual-payments-income',
|
||||
PlusSubscriptionRenewingMonthlyPaymentsIncome = 'plus-subscription-renewing-monthly-payments-income',
|
||||
ProSubscriptionRenewingMonthlyPaymentsIncome = 'pro-subscription-renewing-monthly-payments-income',
|
||||
PlusSubscriptionRenewingAnnualPaymentsIncome = 'plus-subscription-renewing-annual-payments-income',
|
||||
ProSubscriptionRenewingAnnualPaymentsIncome = 'pro-subscription-renewing-annual-payments-income',
|
||||
SubscriptionLength = 'subscription-length',
|
||||
RegistrationLength = 'registration-length',
|
||||
RegistrationToSubscriptionTime = 'registration-to-subscription-time',
|
||||
|
||||
@@ -11,5 +11,6 @@ export interface StatisticsStoreInterface {
|
||||
incrementMeasure(measure: StatisticsMeasure, value: number, periods: Period[]): Promise<void>
|
||||
setMeasure(measure: StatisticsMeasure, value: number, periods: Period[]): Promise<void>
|
||||
getMeasureAverage(measure: StatisticsMeasure, period: Period): Promise<number>
|
||||
getMeasureTotal(measure: StatisticsMeasure, period: Period): Promise<number>
|
||||
getMeasureTotal(measure: StatisticsMeasure, periodOrPeriodKey: Period | string): Promise<number>
|
||||
getMeasureIncrementCounts(measure: StatisticsMeasure, period: Period): Promise<number>
|
||||
}
|
||||
|
||||
@@ -14,4 +14,16 @@ export enum Period {
|
||||
Q2ThisYear,
|
||||
Q3ThisYear,
|
||||
Q4ThisYear,
|
||||
JanuaryThisYear,
|
||||
FebruaryThisYear,
|
||||
MarchThisYear,
|
||||
AprilThisYear,
|
||||
MayThisYear,
|
||||
JuneThisYear,
|
||||
JulyThisYear,
|
||||
AugustThisYear,
|
||||
SeptemberThisYear,
|
||||
OctoberThisYear,
|
||||
NovemberThisYear,
|
||||
DecemberThisYear,
|
||||
}
|
||||
|
||||
@@ -3,6 +3,20 @@ import { PeriodKeyGenerator } from './PeriodKeyGenerator'
|
||||
|
||||
describe('PeriodKeyGenerator', () => {
|
||||
const createGenerator = () => new PeriodKeyGenerator()
|
||||
const months = [
|
||||
Period.JanuaryThisYear,
|
||||
Period.FebruaryThisYear,
|
||||
Period.MarchThisYear,
|
||||
Period.AprilThisYear,
|
||||
Period.MayThisYear,
|
||||
Period.JuneThisYear,
|
||||
Period.JulyThisYear,
|
||||
Period.AugustThisYear,
|
||||
Period.SeptemberThisYear,
|
||||
Period.OctoberThisYear,
|
||||
Period.NovemberThisYear,
|
||||
Period.DecemberThisYear,
|
||||
]
|
||||
|
||||
beforeEach(() => {
|
||||
jest.useFakeTimers()
|
||||
@@ -48,6 +62,23 @@ describe('PeriodKeyGenerator', () => {
|
||||
])
|
||||
})
|
||||
|
||||
it('should generate period keys for this year', () => {
|
||||
expect(createGenerator().getDiscretePeriodKeys(Period.ThisYear)).toEqual([
|
||||
'2022-1',
|
||||
'2022-2',
|
||||
'2022-3',
|
||||
'2022-4',
|
||||
'2022-5',
|
||||
'2022-6',
|
||||
'2022-7',
|
||||
'2022-8',
|
||||
'2022-9',
|
||||
'2022-10',
|
||||
'2022-11',
|
||||
'2022-12',
|
||||
])
|
||||
})
|
||||
|
||||
it('should generate period keys for last 7 days', () => {
|
||||
expect(createGenerator().getDiscretePeriodKeys(Period.Last7Days)).toEqual([
|
||||
'2022-5-17',
|
||||
@@ -60,6 +91,81 @@ describe('PeriodKeyGenerator', () => {
|
||||
])
|
||||
})
|
||||
|
||||
it('should generate period keys for this month', () => {
|
||||
expect(createGenerator().getDiscretePeriodKeys(Period.ThisMonth)).toEqual([
|
||||
'2022-5-1',
|
||||
'2022-5-2',
|
||||
'2022-5-3',
|
||||
'2022-5-4',
|
||||
'2022-5-5',
|
||||
'2022-5-6',
|
||||
'2022-5-7',
|
||||
'2022-5-8',
|
||||
'2022-5-9',
|
||||
'2022-5-10',
|
||||
'2022-5-11',
|
||||
'2022-5-12',
|
||||
'2022-5-13',
|
||||
'2022-5-14',
|
||||
'2022-5-15',
|
||||
'2022-5-16',
|
||||
'2022-5-17',
|
||||
'2022-5-18',
|
||||
'2022-5-19',
|
||||
'2022-5-20',
|
||||
'2022-5-21',
|
||||
'2022-5-22',
|
||||
'2022-5-23',
|
||||
'2022-5-24',
|
||||
'2022-5-25',
|
||||
'2022-5-26',
|
||||
'2022-5-27',
|
||||
'2022-5-28',
|
||||
'2022-5-29',
|
||||
'2022-5-30',
|
||||
'2022-5-31',
|
||||
])
|
||||
})
|
||||
|
||||
it('should generate period keys for specific month', () => {
|
||||
expect(createGenerator().getDiscretePeriodKeys(Period.FebruaryThisYear)).toEqual([
|
||||
'2022-2-1',
|
||||
'2022-2-2',
|
||||
'2022-2-3',
|
||||
'2022-2-4',
|
||||
'2022-2-5',
|
||||
'2022-2-6',
|
||||
'2022-2-7',
|
||||
'2022-2-8',
|
||||
'2022-2-9',
|
||||
'2022-2-10',
|
||||
'2022-2-11',
|
||||
'2022-2-12',
|
||||
'2022-2-13',
|
||||
'2022-2-14',
|
||||
'2022-2-15',
|
||||
'2022-2-16',
|
||||
'2022-2-17',
|
||||
'2022-2-18',
|
||||
'2022-2-19',
|
||||
'2022-2-20',
|
||||
'2022-2-21',
|
||||
'2022-2-22',
|
||||
'2022-2-23',
|
||||
'2022-2-24',
|
||||
'2022-2-25',
|
||||
'2022-2-26',
|
||||
'2022-2-27',
|
||||
'2022-2-28',
|
||||
])
|
||||
})
|
||||
|
||||
it('should generate period keys for specific months', () => {
|
||||
for (const month of months) {
|
||||
expect(createGenerator().getDiscretePeriodKeys(month).length >= 28).toBeTruthy()
|
||||
}
|
||||
})
|
||||
|
||||
it('should generate period keys for Q1', () => {
|
||||
expect(createGenerator().getDiscretePeriodKeys(Period.Q1ThisYear)).toEqual(['2022-1', '2022-2', '2022-3'])
|
||||
})
|
||||
@@ -76,6 +182,10 @@ describe('PeriodKeyGenerator', () => {
|
||||
expect(createGenerator().getDiscretePeriodKeys(Period.Q4ThisYear)).toEqual(['2022-10', '2022-11', '2022-12'])
|
||||
})
|
||||
|
||||
it('should generate a period key for this year', () => {
|
||||
expect(createGenerator().getPeriodKey(Period.ThisYear)).toEqual('2022')
|
||||
})
|
||||
|
||||
it('should generate a period key for today', () => {
|
||||
expect(createGenerator().getPeriodKey(Period.Today)).toEqual('2022-5-24')
|
||||
})
|
||||
@@ -104,6 +214,12 @@ describe('PeriodKeyGenerator', () => {
|
||||
expect(createGenerator().getPeriodKey(Period.ThisMonth)).toEqual('2022-5')
|
||||
})
|
||||
|
||||
it('should generate a period key for each month', () => {
|
||||
for (let i = 0; i < months.length; i++) {
|
||||
expect(createGenerator().getPeriodKey(months[i])).toEqual(`2022-${i + 1}`)
|
||||
}
|
||||
})
|
||||
|
||||
it('should generate a period key for last month', () => {
|
||||
expect(createGenerator().getPeriodKey(Period.LastMonth)).toEqual('2022-4')
|
||||
})
|
||||
@@ -129,4 +245,19 @@ describe('PeriodKeyGenerator', () => {
|
||||
|
||||
expect(error).not.toBeNull()
|
||||
})
|
||||
|
||||
it('should convert period key to period', () => {
|
||||
expect(createGenerator().convertPeriodKeyToPeriod('2022-1')).toEqual(Period.JanuaryThisYear)
|
||||
expect(createGenerator().convertPeriodKeyToPeriod('2022-2')).toEqual(Period.FebruaryThisYear)
|
||||
expect(createGenerator().convertPeriodKeyToPeriod('2022-3')).toEqual(Period.MarchThisYear)
|
||||
expect(createGenerator().convertPeriodKeyToPeriod('2022-4')).toEqual(Period.AprilThisYear)
|
||||
expect(createGenerator().convertPeriodKeyToPeriod('2022-5')).toEqual(Period.MayThisYear)
|
||||
expect(createGenerator().convertPeriodKeyToPeriod('2022-6')).toEqual(Period.JuneThisYear)
|
||||
expect(createGenerator().convertPeriodKeyToPeriod('2022-7')).toEqual(Period.JulyThisYear)
|
||||
expect(createGenerator().convertPeriodKeyToPeriod('2022-8')).toEqual(Period.AugustThisYear)
|
||||
expect(createGenerator().convertPeriodKeyToPeriod('2022-9')).toEqual(Period.SeptemberThisYear)
|
||||
expect(createGenerator().convertPeriodKeyToPeriod('2022-10')).toEqual(Period.OctoberThisYear)
|
||||
expect(createGenerator().convertPeriodKeyToPeriod('2022-11')).toEqual(Period.NovemberThisYear)
|
||||
expect(createGenerator().convertPeriodKeyToPeriod('2022-12')).toEqual(Period.DecemberThisYear)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -2,6 +2,28 @@ import { Period } from './Period'
|
||||
import { PeriodKeyGeneratorInterface } from './PeriodKeyGeneratorInterface'
|
||||
|
||||
export class PeriodKeyGenerator implements PeriodKeyGeneratorInterface {
|
||||
private readonly MONTHS = [
|
||||
Period.JanuaryThisYear,
|
||||
Period.FebruaryThisYear,
|
||||
Period.MarchThisYear,
|
||||
Period.AprilThisYear,
|
||||
Period.MayThisYear,
|
||||
Period.JuneThisYear,
|
||||
Period.JulyThisYear,
|
||||
Period.AugustThisYear,
|
||||
Period.SeptemberThisYear,
|
||||
Period.OctoberThisYear,
|
||||
Period.NovemberThisYear,
|
||||
Period.DecemberThisYear,
|
||||
]
|
||||
|
||||
convertPeriodKeyToPeriod(periodKey: string): Period {
|
||||
const date = new Date(periodKey)
|
||||
const month = this.getMonth(date)
|
||||
|
||||
return this.MONTHS[+month - 1]
|
||||
}
|
||||
|
||||
getDiscretePeriodKeys(period: Period): string[] {
|
||||
const periodKeys = []
|
||||
|
||||
@@ -26,6 +48,23 @@ export class PeriodKeyGenerator implements PeriodKeyGeneratorInterface {
|
||||
return this.generateMonthlyKeysRange(6, 9)
|
||||
case Period.Q4ThisYear:
|
||||
return this.generateMonthlyKeysRange(9, 12)
|
||||
case Period.ThisYear:
|
||||
return this.generateMonthlyKeysRange(0, 12)
|
||||
case Period.ThisMonth:
|
||||
return this.generateDailyKeysRange()
|
||||
case Period.JanuaryThisYear:
|
||||
case Period.FebruaryThisYear:
|
||||
case Period.MarchThisYear:
|
||||
case Period.AprilThisYear:
|
||||
case Period.MayThisYear:
|
||||
case Period.JuneThisYear:
|
||||
case Period.JulyThisYear:
|
||||
case Period.AugustThisYear:
|
||||
case Period.SeptemberThisYear:
|
||||
case Period.OctoberThisYear:
|
||||
case Period.NovemberThisYear:
|
||||
case Period.DecemberThisYear:
|
||||
return this.generateDailyKeysRange(period - 15)
|
||||
default:
|
||||
throw new Error(`Unsuporrted period: ${period}`)
|
||||
}
|
||||
@@ -51,6 +90,30 @@ export class PeriodKeyGenerator implements PeriodKeyGeneratorInterface {
|
||||
return this.getMonthlyKey(this.getLastMonthDate())
|
||||
case Period.ThisYear:
|
||||
return this.getYearlyKey()
|
||||
case Period.JanuaryThisYear:
|
||||
return this.generateMonthlyKeysRange(0, 1)[0]
|
||||
case Period.FebruaryThisYear:
|
||||
return this.generateMonthlyKeysRange(1, 2)[0]
|
||||
case Period.MarchThisYear:
|
||||
return this.generateMonthlyKeysRange(2, 3)[0]
|
||||
case Period.AprilThisYear:
|
||||
return this.generateMonthlyKeysRange(3, 4)[0]
|
||||
case Period.MayThisYear:
|
||||
return this.generateMonthlyKeysRange(4, 5)[0]
|
||||
case Period.JuneThisYear:
|
||||
return this.generateMonthlyKeysRange(5, 6)[0]
|
||||
case Period.JulyThisYear:
|
||||
return this.generateMonthlyKeysRange(6, 7)[0]
|
||||
case Period.AugustThisYear:
|
||||
return this.generateMonthlyKeysRange(7, 8)[0]
|
||||
case Period.SeptemberThisYear:
|
||||
return this.generateMonthlyKeysRange(8, 9)[0]
|
||||
case Period.OctoberThisYear:
|
||||
return this.generateMonthlyKeysRange(9, 10)[0]
|
||||
case Period.NovemberThisYear:
|
||||
return this.generateMonthlyKeysRange(10, 11)[0]
|
||||
case Period.DecemberThisYear:
|
||||
return this.generateMonthlyKeysRange(11, 12)[0]
|
||||
default:
|
||||
throw new Error(`Unsuporrted period: ${period}`)
|
||||
}
|
||||
@@ -149,4 +212,22 @@ export class PeriodKeyGenerator implements PeriodKeyGeneratorInterface {
|
||||
|
||||
return keys
|
||||
}
|
||||
|
||||
private generateDailyKeysRange(month?: number): string[] {
|
||||
const today = new Date()
|
||||
if (month) {
|
||||
today.setMonth(month)
|
||||
}
|
||||
const numberOfDays = new Date(today.getFullYear(), today.getMonth() + 1, 0).getDate()
|
||||
|
||||
const keys = []
|
||||
for (let i = 1; i <= numberOfDays; i++) {
|
||||
const date = new Date()
|
||||
date.setMonth(today.getMonth())
|
||||
date.setDate(i)
|
||||
keys.push(this.getDailyKey(date))
|
||||
}
|
||||
|
||||
return keys
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,5 +2,6 @@ import { Period } from './Period'
|
||||
|
||||
export interface PeriodKeyGeneratorInterface {
|
||||
getPeriodKey(period: Period): string
|
||||
convertPeriodKeyToPeriod(periodKey: string): Period
|
||||
getDiscretePeriodKeys(period: Period): string[]
|
||||
}
|
||||
|
||||
@@ -102,7 +102,7 @@ describe('RedisAnalyticsStore', () => {
|
||||
expect(caughtError).not.toBeNull()
|
||||
})
|
||||
|
||||
it('should calculate total count of activities', async () => {
|
||||
it('should calculate total count of activities by period', async () => {
|
||||
redisClient.bitcount = jest.fn().mockReturnValue(70)
|
||||
|
||||
expect(await createStore().calculateActivityTotalCount(AnalyticsActivity.EditingItems, Period.Yesterday)).toEqual(
|
||||
@@ -112,6 +112,14 @@ describe('RedisAnalyticsStore', () => {
|
||||
expect(redisClient.bitcount).toHaveBeenCalledWith('bitmap:action:editing-items:timespan:period-key')
|
||||
})
|
||||
|
||||
it('should calculate total count of activities by period key', async () => {
|
||||
redisClient.bitcount = jest.fn().mockReturnValue(70)
|
||||
|
||||
expect(await createStore().calculateActivityTotalCount(AnalyticsActivity.EditingItems, '2022-10-03')).toEqual(70)
|
||||
|
||||
expect(redisClient.bitcount).toHaveBeenCalledWith('bitmap:action:editing-items:timespan:2022-10-03')
|
||||
})
|
||||
|
||||
it('should calculate activity retention', async () => {
|
||||
redisClient.bitcount = jest.fn().mockReturnValueOnce(7).mockReturnValueOnce(10)
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user