Compare commits

..

40 Commits

Author SHA1 Message Date
standardci
ffa0f51305 chore(release): publish new version
- @standardnotes/api-gateway@1.15.5
 - @standardnotes/auth-server@1.21.2
 - @standardnotes/domain-events-infra@1.7.35
 - @standardnotes/domain-events@2.55.0
 - @standardnotes/event-store@1.2.2
 - @standardnotes/files-server@1.5.38
 - @standardnotes/scheduler-server@1.10.15
 - @standardnotes/syncing-server@1.6.52
2022-09-01 09:02:44 +00:00
Karol Sójko
e0cec9e24a feat(domain-events): add subscription revert requested event 2022-09-01 11:00:45 +02:00
standardci
f6b359a772 chore(release): publish new version
- @standardnotes/scheduler-server@1.10.14
2022-08-30 12:53:27 +00:00
Karol Sójko
648eb89c7c fix(scheduler): linter issues 2022-08-30 14:51:54 +02:00
standardci
ba22e085b8 chore(release): publish new version
- @standardnotes/scheduler-server@1.10.13
2022-08-30 12:46:35 +00:00
Karol Sójko
35373db1d3 fix(scheduler): skip sending exit survery when a subscription is replaced 2022-08-30 14:44:54 +02:00
standardci
932cfa7200 chore(release): publish new version
- @standardnotes/api-gateway@1.15.4
 - @standardnotes/auth-server@1.21.1
 - @standardnotes/domain-events-infra@1.7.34
 - @standardnotes/domain-events@2.54.2
 - @standardnotes/event-store@1.2.1
 - @standardnotes/files-server@1.5.37
 - @standardnotes/scheduler-server@1.10.12
 - @standardnotes/syncing-server@1.6.51
2022-08-30 12:35:32 +00:00
Karol Sójko
932ef933fc fix(domain-events): add replaced boolean to subscription canceled event 2022-08-30 14:33:59 +02:00
standardci
4f1293525c chore(release): publish new version
- @standardnotes/event-store@1.2.0
2022-08-30 08:02:20 +00:00
Karol Sójko
dd6bec8a0c feat(event-store): add account claim events subscription 2022-08-30 10:00:48 +02:00
standardci
1abca64765 chore(release): publish new version
- @standardnotes/scheduler-server@1.10.11
2022-08-29 12:40:41 +00:00
Karol Sójko
dbe55d89ec fix(scheduler): change logs severity to reduce noise 2022-08-29 14:39:04 +02:00
Karol Sójko
dcb3ad661c chore(setup): node version setting up on workflows 2022-08-29 14:20:39 +02:00
standardci
1e1f6cb4a3 chore(release): publish new version
- @standardnotes/files-server@1.5.36
2022-08-29 11:59:12 +00:00
Karol Sójko
83d96fd71d chore(deps): upgrade ts-node 2022-08-29 13:57:43 +02:00
standardci
7dc4670028 chore(release): publish new version
- @standardnotes/auth-server@1.21.0
2022-08-29 11:20:16 +00:00
Karol Sójko
dc88e2413b feat(auth): retain user agent, api version and received at on revoked sessions 2022-08-29 13:18:05 +02:00
standardci
b7f7c3f164 chore(release): publish new version
- @standardnotes/api-gateway@1.15.3
2022-08-22 08:37:14 +00:00
Karol Sójko
f7def38e20 fix(api-gateway): add error logs on missing connection id for websockets 2022-08-22 10:35:38 +02:00
Karol Sójko
cf49e1ff74 chore(deps): remove reviewers assignment from dependabot to avoid noise 2022-08-17 10:06:22 +02:00
standardci
38de2d6b30 chore(release): publish new version
- @standardnotes/auth-server@1.20.1
 - @standardnotes/scheduler-server@1.10.10
2022-08-17 06:53:26 +00:00
Karol Sójko
4b3de264ef fix(scheduler): change discount from 10% to 20% on a limited time offer 2022-08-17 08:51:35 +02:00
standardci
4bb785c7f0 chore(release): publish new version
- @standardnotes/analytics@1.18.1
 - @standardnotes/api-gateway@1.15.2
 - @standardnotes/auth-server@1.20.0
 - @standardnotes/domain-events-infra@1.7.33
 - @standardnotes/domain-events@2.54.1
 - @standardnotes/event-store@1.1.33
 - @standardnotes/files-server@1.5.35
 - @standardnotes/scheduler-server@1.10.9
 - @standardnotes/syncing-server@1.6.50
2022-08-15 16:37:33 +00:00
Karol Sójko
2fb904d2cb fix(domain-events): missing exports 2022-08-15 18:35:52 +02:00
Karol Sójko
ee79347e27 fix(api-gateway): add payment success events to report 2022-08-15 18:27:44 +02:00
Karol Sójko
3477c81d37 fix(event-store): add payment events handling 2022-08-15 18:26:41 +02:00
Karol Sójko
930789316c fix(analytics): add payment success activity 2022-08-15 18:24:53 +02:00
Karol Sójko
01a08eae58 feat(auth): add payment success event handler 2022-08-15 18:24:13 +02:00
standardci
d73c9833ab chore(release): publish new version
- @standardnotes/api-gateway@1.15.1
 - @standardnotes/auth-server@1.19.1
 - @standardnotes/domain-events-infra@1.7.32
 - @standardnotes/domain-events@2.54.0
 - @standardnotes/event-store@1.1.32
 - @standardnotes/files-server@1.5.34
 - @standardnotes/scheduler-server@1.10.8
 - @standardnotes/syncing-server@1.6.49
2022-08-15 15:03:28 +00:00
Karol Sójko
1841597405 feat(domain-events): add payment success event 2022-08-15 17:01:32 +02:00
standardci
8003e5ce43 chore(release): publish new version
- @standardnotes/api-gateway@1.15.0
2022-08-15 12:39:40 +00:00
Karol Sójko
d0023a6c92 feat(api-gateway): add gathering analytics for failed payments 2022-08-15 14:38:04 +02:00
standardci
a9293f6ce1 chore(release): publish new version
- @standardnotes/analytics@1.18.0
 - @standardnotes/api-gateway@1.14.3
 - @standardnotes/auth-server@1.19.0
 - @standardnotes/syncing-server@1.6.48
2022-08-15 11:12:04 +00:00
Karol Sójko
58c5b586a9 feat(auth): add payment failed event handler 2022-08-15 13:10:36 +02:00
standardci
21d224da22 chore(release): publish new version
- @standardnotes/analytics@1.17.2
 - @standardnotes/api-gateway@1.14.2
 - @standardnotes/auth-server@1.18.4
 - @standardnotes/syncing-server@1.6.47
2022-08-15 10:59:57 +00:00
Karol Sójko
43d957c8d3 fix(analytics): quarterly calculations over time 2022-08-15 12:58:25 +02:00
standardci
917fad510a chore(release): publish new version
- @standardnotes/analytics@1.17.1
 - @standardnotes/api-gateway@1.14.1
 - @standardnotes/auth-server@1.18.3
 - @standardnotes/syncing-server@1.6.46
2022-08-15 10:43:54 +00:00
Karol Sójko
269eef7ef3 fix(analytics): expire bitop keys 2022-08-15 12:42:26 +02:00
standardci
b811f4527b chore(release): publish new version
- @standardnotes/analytics@1.17.0
 - @standardnotes/api-gateway@1.14.0
 - @standardnotes/auth-server@1.18.2
 - @standardnotes/syncing-server@1.6.45
2022-08-15 09:57:53 +00:00
Karol Sójko
67378e4535 feat(api-gateway): add quarterly analytics 2022-08-15 11:55:51 +02:00
65 changed files with 870 additions and 233 deletions

View File

@@ -9,134 +9,83 @@ updates:
directory: "/"
schedule:
interval: "daily"
reviewers:
- "moughxyz"
- "karolsojko"
- package-ecosystem: "npm"
directory: "/packages/analytics"
schedule:
interval: "daily"
reviewers:
- "moughxyz"
- "karolsojko"
- package-ecosystem: "npm"
directory: "/packages/api-gateway"
schedule:
interval: "daily"
reviewers:
- "moughxyz"
- "karolsojko"
- package-ecosystem: "npm"
directory: "/packages/auth"
schedule:
interval: "daily"
reviewers:
- "moughxyz"
- "karolsojko"
- package-ecosystem: "npm"
directory: "/packages/common"
schedule:
interval: "daily"
reviewers:
- "moughxyz"
- "karolsojko"
- package-ecosystem: "npm"
directory: "/packages/domain-events"
schedule:
interval: "daily"
reviewers:
- "moughxyz"
- "karolsojko"
- package-ecosystem: "npm"
directory: "/packages/domain-events-infra"
schedule:
interval: "daily"
reviewers:
- "moughxyz"
- "karolsojko"
- package-ecosystem: "npm"
directory: "/packages/event-store"
schedule:
interval: "daily"
reviewers:
- "moughxyz"
- "karolsojko"
- package-ecosystem: "npm"
directory: "/packages/files"
schedule:
interval: "daily"
reviewers:
- "moughxyz"
- "karolsojko"
- package-ecosystem: "npm"
directory: "/packages/predicates"
schedule:
interval: "daily"
reviewers:
- "moughxyz"
- "karolsojko"
- package-ecosystem: "npm"
directory: "/packages/scheduler"
schedule:
interval: "daily"
reviewers:
- "moughxyz"
- "karolsojko"
- package-ecosystem: "npm"
directory: "/packages/security"
schedule:
interval: "daily"
reviewers:
- "moughxyz"
- "karolsojko"
- package-ecosystem: "npm"
directory: "/packages/settings"
schedule:
interval: "daily"
reviewers:
- "moughxyz"
- "karolsojko"
- package-ecosystem: "npm"
directory: "/packages/sncrypto-node"
schedule:
interval: "daily"
reviewers:
- "moughxyz"
- "karolsojko"
- package-ecosystem: "npm"
directory: "/packages/syncing-server"
schedule:
interval: "daily"
reviewers:
- "moughxyz"
- "karolsojko"
- package-ecosystem: "npm"
directory: "/packages/time"
schedule:
interval: "daily"
reviewers:
- "moughxyz"
- "karolsojko"
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
reviewers:
- "moughxyz"
- "karolsojko"

View File

@@ -60,6 +60,11 @@ 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'
- name: Build locally
run: yarn build
- name: Configure AWS credentials
@@ -90,6 +95,11 @@ 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'
- name: Build locally
run: yarn build
- name: Login to Docker Hub

View File

@@ -63,6 +63,11 @@ 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'
- name: Build locally
run: yarn build
- name: Configure AWS credentials
@@ -93,6 +98,11 @@ 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'
- name: Build locally
run: yarn build
- name: Login to Docker Hub

View File

@@ -32,6 +32,11 @@ 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'
- name: Build locally
run: yarn build
- name: Configure AWS credentials
@@ -62,6 +67,11 @@ 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'
- name: Build locally
run: yarn build
- name: Login to Docker Hub

View File

@@ -63,6 +63,11 @@ 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'
- name: Build locally
run: yarn build
- name: Configure AWS credentials
@@ -93,6 +98,11 @@ 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'
- name: Build locally
run: yarn build
- name: Login to Docker Hub

View File

@@ -11,6 +11,11 @@ jobs:
steps:
- name: Checkout code
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: ESLint
run: yarn lint
- name: Build

View File

@@ -32,6 +32,11 @@ 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'
- name: Build locally
run: yarn build
- name: Configure AWS credentials
@@ -62,6 +67,11 @@ 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'
- name: Build locally
run: yarn build
- name: Login to Docker Hub

View File

@@ -14,9 +14,11 @@ jobs:
with:
ref: main
token: ${{ secrets.CI_PAT_TOKEN }}
- uses: actions/setup-node@v3
- name: Set up Node
uses: actions/setup-node@v3
with:
registry-url: 'https://registry.npmjs.org'
node-version-file: '.nvmrc'
- name: Setup git config
run: |
git config --global user.name "standardci"
@@ -43,4 +45,4 @@ jobs:
commit-message: "${{ 'chore(deps): upgrade snjs' }}"
delete-branch: true
committer: standardci <ci@standardnotes.com>
author: standardci <ci@standardnotes.com>
author: standardci <ci@standardnotes.com>

View File

@@ -63,6 +63,11 @@ 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'
- name: Build locally
run: yarn build
- name: Configure AWS credentials
@@ -93,6 +98,11 @@ 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'
- name: Build locally
run: yarn build
- name: Login to Docker Hub

60
.pnp.cjs generated
View File

@@ -124,7 +124,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
["newrelic", "npm:9.0.0"],\
["npm-check-updates", "npm:16.0.1"],\
["prettier", "npm:2.7.1"],\
["ts-node", "virtual:c0eab07e71af57f5501e97e7ca7a2a4f4965035bd2455ad124a8b09fa55780657c55fe3df41019fa6c2c44487c897668c842a0939e380b3c1f13b3756d128543#npm:10.8.2"],\
["ts-node", "virtual:8859b278716fedf3e7458b5628625f7e35678c418626878559a0b816445001b7e24c55546f4677ba4c20b521aa0cf52cc33ac07deff171e383ada6eeab69933f#npm:10.9.1"],\
["typescript", "patch:typescript@npm%3A4.7.4#~builtin<compat/typescript>::version=4.7.4&hash=7ad353"]\
],\
"linkType": "SOFT"\
@@ -2788,7 +2788,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
["prettyjson", "npm:1.2.5"],\
["reflect-metadata", "npm:0.1.13"],\
["ts-jest", "virtual:c66bf20e88479ada0172094776519a9f51acc4731d22079b60a295bcec7ea42d5545cbce58a77a50d932bf953298799135e99707486e343da6d99ba1d167bdbd#npm:28.0.5"],\
["ts-node", "virtual:b442cf0427cc365d1c137f7340f9b81f9b204561afe791a8564ae9590c3a7fc4b5f793aaf8817b946f75a3cb64d03ef8790eb847f8b576b41e700da7b00c240c#npm:10.8.2"],\
["ts-node", "virtual:b442cf0427cc365d1c137f7340f9b81f9b204561afe791a8564ae9590c3a7fc4b5f793aaf8817b946f75a3cb64d03ef8790eb847f8b576b41e700da7b00c240c#npm:10.9.1"],\
["uuid", "npm:8.3.2"],\
["winston", "npm:3.8.1"]\
],\
@@ -2866,11 +2866,12 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
["@types/jest", "npm:28.1.4"],\
["@types/newrelic", "npm:7.0.3"],\
["@types/node", "npm:18.0.3"],\
["@typescript-eslint/eslint-plugin", "virtual:c66bf20e88479ada0172094776519a9f51acc4731d22079b60a295bcec7ea42d5545cbce58a77a50d932bf953298799135e99707486e343da6d99ba1d167bdbd#npm:5.30.5"],\
["@typescript-eslint/eslint-plugin", "virtual:04783e12400851b8a3d76e71495851cc94959db6e62f04cb0a31190080629440b182d8c8eb4d7f2b04e281912f2783a5fd4d2c3c6ab68d38b7097246c93f4c19#npm:5.30.5"],\
["aws-sdk", "npm:2.1168.0"],\
["dayjs", "npm:1.11.3"],\
["dotenv", "npm:16.0.1"],\
["eslint-plugin-prettier", "virtual:c66bf20e88479ada0172094776519a9f51acc4731d22079b60a295bcec7ea42d5545cbce58a77a50d932bf953298799135e99707486e343da6d99ba1d167bdbd#npm:4.2.1"],\
["eslint", "npm:8.19.0"],\
["eslint-plugin-prettier", "virtual:04783e12400851b8a3d76e71495851cc94959db6e62f04cb0a31190080629440b182d8c8eb4d7f2b04e281912f2783a5fd4d2c3c6ab68d38b7097246c93f4c19#npm:4.2.1"],\
["inversify", "npm:6.0.1"],\
["ioredis", "npm:5.2.0"],\
["jest", "virtual:c66bf20e88479ada0172094776519a9f51acc4731d22079b60a295bcec7ea42d5545cbce58a77a50d932bf953298799135e99707486e343da6d99ba1d167bdbd#npm:28.1.2"],\
@@ -2924,7 +2925,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
["newrelic", "npm:9.0.0"],\
["npm-check-updates", "npm:16.0.1"],\
["prettier", "npm:2.7.1"],\
["ts-node", "virtual:c0eab07e71af57f5501e97e7ca7a2a4f4965035bd2455ad124a8b09fa55780657c55fe3df41019fa6c2c44487c897668c842a0939e380b3c1f13b3756d128543#npm:10.8.2"],\
["ts-node", "virtual:8859b278716fedf3e7458b5628625f7e35678c418626878559a0b816445001b7e24c55546f4677ba4c20b521aa0cf52cc33ac07deff171e383ada6eeab69933f#npm:10.9.1"],\
["typescript", "patch:typescript@npm%3A4.7.4#~builtin<compat/typescript>::version=4.7.4&hash=7ad353"]\
],\
"linkType": "SOFT"\
@@ -12187,10 +12188,53 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) {
],\
"linkType": "SOFT"\
}],\
["virtual:b442cf0427cc365d1c137f7340f9b81f9b204561afe791a8564ae9590c3a7fc4b5f793aaf8817b946f75a3cb64d03ef8790eb847f8b576b41e700da7b00c240c#npm:10.8.2", {\
"packageLocation": "./.yarn/__virtual__/ts-node-virtual-8a01a45377/0/cache/ts-node-npm-10.8.2-f3c0c9eaee-1eede939be.zip/node_modules/ts-node/",\
["npm:10.9.1", {\
"packageLocation": "./.yarn/cache/ts-node-npm-10.9.1-6c268be7f4-090adff130.zip/node_modules/ts-node/",\
"packageDependencies": [\
["ts-node", "virtual:b442cf0427cc365d1c137f7340f9b81f9b204561afe791a8564ae9590c3a7fc4b5f793aaf8817b946f75a3cb64d03ef8790eb847f8b576b41e700da7b00c240c#npm:10.8.2"],\
["ts-node", "npm:10.9.1"]\
],\
"linkType": "SOFT"\
}],\
["virtual:8859b278716fedf3e7458b5628625f7e35678c418626878559a0b816445001b7e24c55546f4677ba4c20b521aa0cf52cc33ac07deff171e383ada6eeab69933f#npm:10.9.1", {\
"packageLocation": "./.yarn/__virtual__/ts-node-virtual-ac01688ebc/0/cache/ts-node-npm-10.9.1-6c268be7f4-090adff130.zip/node_modules/ts-node/",\
"packageDependencies": [\
["ts-node", "virtual:8859b278716fedf3e7458b5628625f7e35678c418626878559a0b816445001b7e24c55546f4677ba4c20b521aa0cf52cc33ac07deff171e383ada6eeab69933f#npm:10.9.1"],\
["@cspotcode/source-map-support", "npm:0.8.1"],\
["@swc/core", null],\
["@swc/wasm", null],\
["@tsconfig/node10", "npm:1.0.9"],\
["@tsconfig/node12", "npm:1.0.11"],\
["@tsconfig/node14", "npm:1.0.3"],\
["@tsconfig/node16", "npm:1.0.3"],\
["@types/node", "npm:18.0.3"],\
["@types/swc__core", null],\
["@types/swc__wasm", null],\
["@types/typescript", null],\
["acorn", "npm:8.7.1"],\
["acorn-walk", "npm:8.2.0"],\
["arg", "npm:4.1.3"],\
["create-require", "npm:1.1.1"],\
["diff", "npm:4.0.2"],\
["make-error", "npm:1.3.6"],\
["typescript", "patch:typescript@npm%3A4.7.4#~builtin<compat/typescript>::version=4.7.4&hash=7ad353"],\
["v8-compile-cache-lib", "npm:3.0.1"],\
["yn", "npm:3.1.1"]\
],\
"packagePeers": [\
"@swc/core",\
"@swc/wasm",\
"@types/node",\
"@types/swc__core",\
"@types/swc__wasm",\
"@types/typescript",\
"typescript"\
],\
"linkType": "HARD"\
}],\
["virtual:b442cf0427cc365d1c137f7340f9b81f9b204561afe791a8564ae9590c3a7fc4b5f793aaf8817b946f75a3cb64d03ef8790eb847f8b576b41e700da7b00c240c#npm:10.9.1", {\
"packageLocation": "./.yarn/__virtual__/ts-node-virtual-c4e9951caa/0/cache/ts-node-npm-10.9.1-6c268be7f4-090adff130.zip/node_modules/ts-node/",\
"packageDependencies": [\
["ts-node", "virtual:b442cf0427cc365d1c137f7340f9b81f9b204561afe791a8564ae9590c3a7fc4b5f793aaf8817b946f75a3cb64d03ef8790eb847f8b576b41e700da7b00c240c#npm:10.9.1"],\
["@cspotcode/source-map-support", "npm:0.8.1"],\
["@swc/core", null],\
["@swc/wasm", null],\

Binary file not shown.

View File

@@ -60,7 +60,7 @@
"ini": "^3.0.0",
"npm-check-updates": "^16.0.1",
"prettier": "^2.7.1",
"ts-node": "^10.8.1",
"ts-node": "^10.9.1",
"typescript": "^4.7.4"
},
"packageManager": "yarn@3.2.1",

View File

@@ -3,6 +3,36 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.18.1](https://github.com/standardnotes/server/compare/@standardnotes/analytics@1.18.0...@standardnotes/analytics@1.18.1) (2022-08-15)
### Bug Fixes
* **analytics:** add payment success activity ([9307893](https://github.com/standardnotes/server/commit/930789316c2eec8227f26e75d4917796168f2d08))
# [1.18.0](https://github.com/standardnotes/server/compare/@standardnotes/analytics@1.17.2...@standardnotes/analytics@1.18.0) (2022-08-15)
### Features
* **auth:** add payment failed event handler ([58c5b58](https://github.com/standardnotes/server/commit/58c5b586a904cf1fd179cc28783a6ae7da688063))
## [1.17.2](https://github.com/standardnotes/server/compare/@standardnotes/analytics@1.17.1...@standardnotes/analytics@1.17.2) (2022-08-15)
### Bug Fixes
* **analytics:** quarterly calculations over time ([43d957c](https://github.com/standardnotes/server/commit/43d957c8d382b501e8101b51e30b33f18a4dd871))
## [1.17.1](https://github.com/standardnotes/server/compare/@standardnotes/analytics@1.17.0...@standardnotes/analytics@1.17.1) (2022-08-15)
### Bug Fixes
* **analytics:** expire bitop keys ([269eef7](https://github.com/standardnotes/server/commit/269eef7ef31343390c6909350bf1bfede94c24b3))
# [1.17.0](https://github.com/standardnotes/server/compare/@standardnotes/analytics@1.16.0...@standardnotes/analytics@1.17.0) (2022-08-15)
### Features
* **api-gateway:** add quarterly analytics ([67378e4](https://github.com/standardnotes/server/commit/67378e4535ef2760cfe3fe27256ffe117ee11a71))
# [1.16.0](https://github.com/standardnotes/server/compare/@standardnotes/analytics@1.15.0...@standardnotes/analytics@1.16.0) (2022-08-15)
### Features

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/analytics",
"version": "1.16.0",
"version": "1.18.1",
"engines": {
"node": ">=14.0.0 <17.0.0"
},

View File

@@ -11,4 +11,6 @@ export enum AnalyticsActivity {
EmailUnbackedUpData = 'email-unbacked-up-data',
EmailBackup = 'email-backup',
LimitedDiscountOfferPurchased = 'limited-discount-offer-purchased',
PaymentFailed = 'payment-failed',
PaymentSuccess = 'payment-success',
}

View File

@@ -24,6 +24,7 @@ describe('RedisAnalyticsStore', () => {
redisClient.setbit = jest.fn()
redisClient.getbit = jest.fn().mockReturnValue(1)
redisClient.bitop = jest.fn()
redisClient.expire = jest.fn()
periodKeyGenerator = {} as jest.Mocked<PeriodKeyGeneratorInterface>
periodKeyGenerator.getPeriodKey = jest.fn().mockReturnValue('period-key')

View File

@@ -15,13 +15,18 @@ export class RedisAnalyticsStore implements AnalyticsStoreInterface {
throw new Error(`Unsuporrted period: ${period}`)
}
const periodKeys = this.periodKeyGenerator.getDiscretePeriodKeys(Period.Last30Days)
const periodKeys = this.periodKeyGenerator.getDiscretePeriodKeys(period)
await this.redisClient.bitop(
'OR',
`bitmap:action:${activity}:timespan:${periodKeys[0]}-${periodKeys[periodKeys.length - 1]}`,
...periodKeys.map((p) => `bitmap:action:${activity}:timespan:${p}`),
)
await this.redisClient.expire(
`bitmap:action:${activity}:timespan:${periodKeys[0]}-${periodKeys[periodKeys.length - 1]}`,
3600,
)
return this.redisClient.bitcount(
`bitmap:action:${activity}:timespan:${periodKeys[0]}-${periodKeys[periodKeys.length - 1]}`,
)
@@ -31,11 +36,13 @@ export class RedisAnalyticsStore implements AnalyticsStoreInterface {
activity: AnalyticsActivity,
period: Period,
): Promise<Array<{ periodKey: string; totalCount: number }>> {
if (period !== Period.Last30Days) {
if (
![Period.Last30Days, Period.Q1ThisYear, Period.Q2ThisYear, Period.Q3ThisYear, Period.Q4ThisYear].includes(period)
) {
throw new Error(`Unsuporrted period: ${period}`)
}
const periodKeys = this.periodKeyGenerator.getDiscretePeriodKeys(Period.Last30Days)
const periodKeys = this.periodKeyGenerator.getDiscretePeriodKeys(period)
const counts = []
for (const periodKey of periodKeys) {
counts.push({
@@ -105,6 +112,8 @@ export class RedisAnalyticsStore implements AnalyticsStoreInterface {
`bitmap:action:${activity}:timespan:${subsequentPeriodKey}`,
)
await this.redisClient.expire(diffKey, 3600)
const retainedTotalInActivity = await this.redisClient.bitcount(diffKey)
const initialTotalInActivity = await this.redisClient.bitcount(

View File

@@ -3,6 +3,54 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.15.5](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.15.4...@standardnotes/api-gateway@1.15.5) (2022-09-01)
**Note:** Version bump only for package @standardnotes/api-gateway
## [1.15.4](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.15.3...@standardnotes/api-gateway@1.15.4) (2022-08-30)
**Note:** Version bump only for package @standardnotes/api-gateway
## [1.15.3](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.15.2...@standardnotes/api-gateway@1.15.3) (2022-08-22)
### Bug Fixes
* **api-gateway:** add error logs on missing connection id for websockets ([f7def38](https://github.com/standardnotes/api-gateway/commit/f7def38e20f87ae24ebc736a41bc7cac53b0c61f))
## [1.15.2](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.15.1...@standardnotes/api-gateway@1.15.2) (2022-08-15)
### Bug Fixes
* **api-gateway:** add payment success events to report ([ee79347](https://github.com/standardnotes/api-gateway/commit/ee79347e27f5887def2cda57091a7c0a40570d33))
## [1.15.1](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.15.0...@standardnotes/api-gateway@1.15.1) (2022-08-15)
**Note:** Version bump only for package @standardnotes/api-gateway
# [1.15.0](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.14.3...@standardnotes/api-gateway@1.15.0) (2022-08-15)
### Features
* **api-gateway:** add gathering analytics for failed payments ([d0023a6](https://github.com/standardnotes/api-gateway/commit/d0023a6c92756c81b8daa9089d38141b6cd4fe48))
## [1.14.3](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.14.2...@standardnotes/api-gateway@1.14.3) (2022-08-15)
**Note:** Version bump only for package @standardnotes/api-gateway
## [1.14.2](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.14.1...@standardnotes/api-gateway@1.14.2) (2022-08-15)
**Note:** Version bump only for package @standardnotes/api-gateway
## [1.14.1](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.14.0...@standardnotes/api-gateway@1.14.1) (2022-08-15)
**Note:** Version bump only for package @standardnotes/api-gateway
# [1.14.0](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.13.1...@standardnotes/api-gateway@1.14.0) (2022-08-15)
### Features
* **api-gateway:** add quarterly analytics ([67378e4](https://github.com/standardnotes/api-gateway/commit/67378e4535ef2760cfe3fe27256ffe117ee11a71))
## [1.13.1](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.13.0...@standardnotes/api-gateway@1.13.1) (2022-08-15)
**Note:** Version bump only for package @standardnotes/api-gateway

View File

@@ -19,6 +19,66 @@ const requestReport = async (
statisticsStore: StatisticsStoreInterface,
domainEventPublisher: DomainEventPublisherInterface,
): Promise<void> => {
const analyticsOverTime = []
const thirtyDaysAnalyticsNames = [
AnalyticsActivity.GeneralActivity,
AnalyticsActivity.EditingItems,
AnalyticsActivity.SubscriptionPurchased,
AnalyticsActivity.Register,
AnalyticsActivity.SubscriptionRenewed,
AnalyticsActivity.DeleteAccount,
AnalyticsActivity.SubscriptionCancelled,
AnalyticsActivity.SubscriptionRefunded,
]
for (const analyticsName of thirtyDaysAnalyticsNames) {
analyticsOverTime.push({
name: analyticsName,
period: Period.Last30Days,
counts: await analyticsStore.calculateActivityChangesTotalCount(analyticsName, Period.Last30Days),
totalCount: await analyticsStore.calculateActivityTotalCountOverTime(analyticsName, Period.Last30Days),
})
}
const quarterlyAnalyticsNames = [
AnalyticsActivity.Register,
AnalyticsActivity.SubscriptionPurchased,
AnalyticsActivity.SubscriptionRenewed,
]
for (const analyticsName of quarterlyAnalyticsNames) {
for (const period of [Period.Q1ThisYear, Period.Q2ThisYear, Period.Q3ThisYear, Period.Q4ThisYear]) {
analyticsOverTime.push({
name: analyticsName,
period: period,
counts: await analyticsStore.calculateActivityChangesTotalCount(analyticsName, period),
totalCount: await analyticsStore.calculateActivityTotalCountOverTime(analyticsName, period),
})
}
}
const yesterdayActivityStatistics = []
const yesterdayActivityNames = [
AnalyticsActivity.EditingItems,
AnalyticsActivity.LimitedDiscountOfferPurchased,
AnalyticsActivity.GeneralActivity,
AnalyticsActivity.PaymentFailed,
AnalyticsActivity.PaymentSuccess,
]
for (const activityName of yesterdayActivityNames) {
yesterdayActivityStatistics.push({
name: activityName,
retention: await analyticsStore.calculateActivityRetention(
activityName,
Period.DayBeforeYesterday,
Period.Yesterday,
),
totalCount: await analyticsStore.calculateActivityTotalCount(activityName, Period.Yesterday),
})
}
const event: DailyAnalyticsReportGeneratedEvent = {
type: 'DAILY_ANALYTICS_REPORT_GENERATED',
createdAt: new Date(),
@@ -33,138 +93,8 @@ const requestReport = async (
applicationStatistics: await statisticsStore.getYesterdayApplicationUsage(),
snjsStatistics: await statisticsStore.getYesterdaySNJSUsage(),
outOfSyncIncidents: await statisticsStore.getYesterdayOutOfSyncIncidents(),
activityStatistics: [
{
name: AnalyticsActivity.EditingItems,
retention: await analyticsStore.calculateActivityRetention(
AnalyticsActivity.EditingItems,
Period.DayBeforeYesterday,
Period.Yesterday,
),
totalCount: await analyticsStore.calculateActivityTotalCount(
AnalyticsActivity.EditingItems,
Period.Yesterday,
),
},
{
name: AnalyticsActivity.LimitedDiscountOfferPurchased,
retention: 0,
totalCount: await analyticsStore.calculateActivityTotalCount(
AnalyticsActivity.LimitedDiscountOfferPurchased,
Period.Yesterday,
),
},
{
name: AnalyticsActivity.GeneralActivity,
retention: await analyticsStore.calculateActivityRetention(
AnalyticsActivity.GeneralActivity,
Period.DayBeforeYesterday,
Period.Yesterday,
),
totalCount: await analyticsStore.calculateActivityTotalCount(
AnalyticsActivity.GeneralActivity,
Period.Yesterday,
),
},
],
activityStatisticsOverTime: [
{
name: AnalyticsActivity.GeneralActivity,
period: Period.Last30Days,
counts: await analyticsStore.calculateActivityChangesTotalCount(
AnalyticsActivity.GeneralActivity,
Period.Last30Days,
),
totalCount: await analyticsStore.calculateActivityTotalCountOverTime(
AnalyticsActivity.GeneralActivity,
Period.Last30Days,
),
},
{
name: AnalyticsActivity.EditingItems,
period: Period.Last30Days,
counts: await analyticsStore.calculateActivityChangesTotalCount(
AnalyticsActivity.EditingItems,
Period.Last30Days,
),
totalCount: await analyticsStore.calculateActivityTotalCountOverTime(
AnalyticsActivity.EditingItems,
Period.Last30Days,
),
},
{
name: AnalyticsActivity.SubscriptionPurchased,
period: Period.Last30Days,
counts: await analyticsStore.calculateActivityChangesTotalCount(
AnalyticsActivity.SubscriptionPurchased,
Period.Last30Days,
),
totalCount: await analyticsStore.calculateActivityTotalCountOverTime(
AnalyticsActivity.SubscriptionPurchased,
Period.Last30Days,
),
},
{
name: AnalyticsActivity.Register,
period: Period.Last30Days,
counts: await analyticsStore.calculateActivityChangesTotalCount(
AnalyticsActivity.Register,
Period.Last30Days,
),
totalCount: await analyticsStore.calculateActivityTotalCountOverTime(
AnalyticsActivity.Register,
Period.Last30Days,
),
},
{
name: AnalyticsActivity.SubscriptionRenewed,
period: Period.Last30Days,
counts: await analyticsStore.calculateActivityChangesTotalCount(
AnalyticsActivity.SubscriptionRenewed,
Period.Last30Days,
),
totalCount: await analyticsStore.calculateActivityTotalCountOverTime(
AnalyticsActivity.SubscriptionRenewed,
Period.Last30Days,
),
},
{
name: AnalyticsActivity.DeleteAccount,
period: Period.Last30Days,
counts: await analyticsStore.calculateActivityChangesTotalCount(
AnalyticsActivity.DeleteAccount,
Period.Last30Days,
),
totalCount: await analyticsStore.calculateActivityTotalCountOverTime(
AnalyticsActivity.DeleteAccount,
Period.Last30Days,
),
},
{
name: AnalyticsActivity.SubscriptionCancelled,
period: Period.Last30Days,
counts: await analyticsStore.calculateActivityChangesTotalCount(
AnalyticsActivity.SubscriptionCancelled,
Period.Last30Days,
),
totalCount: await analyticsStore.calculateActivityTotalCountOverTime(
AnalyticsActivity.SubscriptionCancelled,
Period.Last30Days,
),
},
{
name: AnalyticsActivity.SubscriptionRefunded,
period: Period.Last30Days,
counts: await analyticsStore.calculateActivityChangesTotalCount(
AnalyticsActivity.SubscriptionRefunded,
Period.Last30Days,
),
totalCount: await analyticsStore.calculateActivityTotalCountOverTime(
AnalyticsActivity.SubscriptionRefunded,
Period.Last30Days,
),
},
],
activityStatistics: yesterdayActivityStatistics,
activityStatisticsOverTime: analyticsOverTime,
},
}

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/api-gateway",
"version": "1.13.1",
"version": "1.15.5",
"engines": {
"node": ">=16.0.0 <17.0.0"
},

View File

@@ -1,18 +1,25 @@
import { Request, Response } from 'express'
import { inject } from 'inversify'
import { BaseHttpController, controller, httpDelete, httpPost } from 'inversify-express-utils'
import { Logger } from 'winston'
import TYPES from '../../Bootstrap/Types'
import { HttpServiceInterface } from '../../Service/Http/HttpServiceInterface'
@controller('/v1/sockets')
export class WebSocketsController extends BaseHttpController {
constructor(@inject(TYPES.HTTPService) private httpService: HttpServiceInterface) {
constructor(
@inject(TYPES.HTTPService) private httpService: HttpServiceInterface,
@inject(TYPES.Logger) private logger: Logger,
) {
super()
}
@httpPost('/', TYPES.AuthMiddleware)
async createWebSocketConnection(request: Request, response: Response): Promise<void> {
if (!request.headers.connectionid) {
this.logger.error('Could not create a websocket connection. Missing connection id header.')
response.status(400).send('Missing connection id in the request')
return
@@ -24,6 +31,8 @@ export class WebSocketsController extends BaseHttpController {
@httpDelete('/')
async deleteWebSocketConnection(request: Request, response: Response): Promise<void> {
if (!request.headers.connectionid) {
this.logger.error('Could not delete a websocket connection. Missing connection id header.')
response.status(400).send('Missing connection id in the request')
return

View File

@@ -3,6 +3,54 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.21.2](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.21.1...@standardnotes/auth-server@1.21.2) (2022-09-01)
**Note:** Version bump only for package @standardnotes/auth-server
## [1.21.1](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.21.0...@standardnotes/auth-server@1.21.1) (2022-08-30)
**Note:** Version bump only for package @standardnotes/auth-server
# [1.21.0](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.20.1...@standardnotes/auth-server@1.21.0) (2022-08-29)
### Features
* **auth:** retain user agent, api version and received at on revoked sessions ([dc88e24](https://github.com/standardnotes/server/commit/dc88e2413b3be254b265d2874174eaac39d628ee))
## [1.20.1](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.20.0...@standardnotes/auth-server@1.20.1) (2022-08-17)
### Bug Fixes
* **scheduler:** change discount from 10% to 20% on a limited time offer ([4b3de26](https://github.com/standardnotes/server/commit/4b3de264efc4fffb2603181c158cddb25c4ed4a9))
# [1.20.0](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.19.1...@standardnotes/auth-server@1.20.0) (2022-08-15)
### Features
* **auth:** add payment success event handler ([01a08ea](https://github.com/standardnotes/server/commit/01a08eae582e070ec844f5e05f34260447b7d4c6))
## [1.19.1](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.19.0...@standardnotes/auth-server@1.19.1) (2022-08-15)
**Note:** Version bump only for package @standardnotes/auth-server
# [1.19.0](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.18.4...@standardnotes/auth-server@1.19.0) (2022-08-15)
### Features
* **auth:** add payment failed event handler ([58c5b58](https://github.com/standardnotes/server/commit/58c5b586a904cf1fd179cc28783a6ae7da688063))
## [1.18.4](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.18.3...@standardnotes/auth-server@1.18.4) (2022-08-15)
**Note:** Version bump only for package @standardnotes/auth-server
## [1.18.3](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.18.2...@standardnotes/auth-server@1.18.3) (2022-08-15)
**Note:** Version bump only for package @standardnotes/auth-server
## [1.18.2](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.18.1...@standardnotes/auth-server@1.18.2) (2022-08-15)
**Note:** Version bump only for package @standardnotes/auth-server
## [1.18.1](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.18.0...@standardnotes/auth-server@1.18.1) (2022-08-15)
**Note:** Version bump only for package @standardnotes/auth-server

View File

@@ -0,0 +1,15 @@
import { MigrationInterface, QueryRunner } from 'typeorm'
export class revokedSessionData1661771230400 implements MigrationInterface {
name = 'revokedSessionData1661771230400'
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query('ALTER TABLE `revoked_sessions` ADD `received_at` datetime NULL')
await queryRunner.query('ALTER TABLE `revoked_sessions` ADD `user_agent` text NULL')
await queryRunner.query('ALTER TABLE `revoked_sessions` ADD `api_version` varchar(255) NULL')
}
public async down(): Promise<void> {
return
}
}

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/auth-server",
"version": "1.18.1",
"version": "1.21.2",
"engines": {
"node": ">=16.0.0 <17.0.0"
},

View File

@@ -191,6 +191,8 @@ import { AuthController } from '../Controller/AuthController'
import { VerifyPredicate } from '../Domain/UseCase/VerifyPredicate/VerifyPredicate'
import { PredicateVerificationRequestedEventHandler } from '../Domain/Handler/PredicateVerificationRequestedEventHandler'
import { MuteMarketingEmails } from '../Domain/UseCase/MuteMarketingEmails/MuteMarketingEmails'
import { PaymentFailedEventHandler } from '../Domain/Handler/PaymentFailedEventHandler'
import { PaymentSuccessEventHandler } from '../Domain/Handler/PaymentSuccessEventHandler'
// eslint-disable-next-line @typescript-eslint/no-var-requires
const newrelicFormatter = require('@newrelic/winston-enricher')
@@ -478,6 +480,8 @@ export class ContainerConfigLoader {
container
.bind<PredicateVerificationRequestedEventHandler>(TYPES.PredicateVerificationRequestedEventHandler)
.to(PredicateVerificationRequestedEventHandler)
container.bind<PaymentFailedEventHandler>(TYPES.PaymentFailedEventHandler).to(PaymentFailedEventHandler)
container.bind<PaymentSuccessEventHandler>(TYPES.PaymentSuccessEventHandler).to(PaymentSuccessEventHandler)
// Services
container.bind<UAParser>(TYPES.DeviceDetector).toConstantValue(new UAParser())
@@ -576,6 +580,8 @@ export class ContainerConfigLoader {
],
['SHARED_SUBSCRIPTION_INVITATION_CREATED', container.get(TYPES.SharedSubscriptionInvitationCreatedEventHandler)],
['PREDICATE_VERIFICATION_REQUESTED', container.get(TYPES.PredicateVerificationRequestedEventHandler)],
['PAYMENT_FAILED', container.get(TYPES.PaymentFailedEventHandler)],
['PAYMENT_SUCCESS', container.get(TYPES.PaymentSuccessEventHandler)],
])
if (env.get('SQS_QUEUE_URL', true)) {

View File

@@ -143,6 +143,8 @@ const TYPES = {
UserDisabledSessionUserAgentLoggingEventHandler: Symbol.for('UserDisabledSessionUserAgentLoggingEventHandler'),
SharedSubscriptionInvitationCreatedEventHandler: Symbol.for('SharedSubscriptionInvitationCreatedEventHandler'),
PredicateVerificationRequestedEventHandler: Symbol.for('PredicateVerificationRequestedEventHandler'),
PaymentFailedEventHandler: Symbol.for('PaymentFailedEventHandler'),
PaymentSuccessEventHandler: Symbol.for('PaymentSuccessEventHandler'),
// Services
DeviceDetector: Symbol.for('DeviceDetector'),
SessionService: Symbol.for('SessionService'),

View File

@@ -0,0 +1,51 @@
import 'reflect-metadata'
import { PaymentFailedEvent } from '@standardnotes/domain-events'
import { AnalyticsStoreInterface } from '@standardnotes/analytics'
import { PaymentFailedEventHandler } from './PaymentFailedEventHandler'
import { UserRepositoryInterface } from '../User/UserRepositoryInterface'
import { User } from '../User/User'
import { GetUserAnalyticsId } from '../UseCase/GetUserAnalyticsId/GetUserAnalyticsId'
describe('PaymentFailedEventHandler', () => {
let userRepository: UserRepositoryInterface
let event: PaymentFailedEvent
let user: User
let getUserAnalyticsId: GetUserAnalyticsId
let analyticsStore: AnalyticsStoreInterface
const createHandler = () => new PaymentFailedEventHandler(userRepository, getUserAnalyticsId, analyticsStore)
beforeEach(() => {
user = {} as jest.Mocked<User>
userRepository = {} as jest.Mocked<UserRepositoryInterface>
userRepository.findOneByEmail = jest.fn().mockReturnValue(user)
getUserAnalyticsId = {} as jest.Mocked<GetUserAnalyticsId>
getUserAnalyticsId.execute = jest.fn().mockReturnValue({ analyticsId: 3 })
analyticsStore = {} as jest.Mocked<AnalyticsStoreInterface>
analyticsStore.markActivity = jest.fn()
event = {} as jest.Mocked<PaymentFailedEvent>
event.payload = {
userEmail: 'test@test.com',
}
})
it('should mark payment failed for analytics', async () => {
await createHandler().handle(event)
expect(analyticsStore.markActivity).toHaveBeenCalled()
})
it('should not mark payment failed for analytics if user is not found', async () => {
userRepository.findOneByEmail = jest.fn().mockReturnValue(null)
await createHandler().handle(event)
expect(analyticsStore.markActivity).not.toHaveBeenCalled()
})
})

View File

@@ -0,0 +1,30 @@
import { AnalyticsActivity, AnalyticsStoreInterface, Period } from '@standardnotes/analytics'
import { DomainEventHandlerInterface, PaymentFailedEvent } from '@standardnotes/domain-events'
import { inject, injectable } from 'inversify'
import TYPES from '../../Bootstrap/Types'
import { GetUserAnalyticsId } from '../UseCase/GetUserAnalyticsId/GetUserAnalyticsId'
import { UserRepositoryInterface } from '../User/UserRepositoryInterface'
@injectable()
export class PaymentFailedEventHandler implements DomainEventHandlerInterface {
constructor(
@inject(TYPES.UserRepository) private userRepository: UserRepositoryInterface,
@inject(TYPES.GetUserAnalyticsId) private getUserAnalyticsId: GetUserAnalyticsId,
@inject(TYPES.AnalyticsStore) private analyticsStore: AnalyticsStoreInterface,
) {}
async handle(event: PaymentFailedEvent): Promise<void> {
const user = await this.userRepository.findOneByEmail(event.payload.userEmail)
if (user === null) {
return
}
const { analyticsId } = await this.getUserAnalyticsId.execute({ userUuid: user.uuid })
await this.analyticsStore.markActivity([AnalyticsActivity.PaymentFailed], analyticsId, [
Period.Today,
Period.ThisWeek,
Period.ThisMonth,
])
}
}

View File

@@ -0,0 +1,51 @@
import 'reflect-metadata'
import { PaymentSuccessEvent } from '@standardnotes/domain-events'
import { AnalyticsStoreInterface } from '@standardnotes/analytics'
import { PaymentSuccessEventHandler } from './PaymentSuccessEventHandler'
import { UserRepositoryInterface } from '../User/UserRepositoryInterface'
import { User } from '../User/User'
import { GetUserAnalyticsId } from '../UseCase/GetUserAnalyticsId/GetUserAnalyticsId'
describe('PaymentSuccessEventHandler', () => {
let userRepository: UserRepositoryInterface
let event: PaymentSuccessEvent
let user: User
let getUserAnalyticsId: GetUserAnalyticsId
let analyticsStore: AnalyticsStoreInterface
const createHandler = () => new PaymentSuccessEventHandler(userRepository, getUserAnalyticsId, analyticsStore)
beforeEach(() => {
user = {} as jest.Mocked<User>
userRepository = {} as jest.Mocked<UserRepositoryInterface>
userRepository.findOneByEmail = jest.fn().mockReturnValue(user)
getUserAnalyticsId = {} as jest.Mocked<GetUserAnalyticsId>
getUserAnalyticsId.execute = jest.fn().mockReturnValue({ analyticsId: 3 })
analyticsStore = {} as jest.Mocked<AnalyticsStoreInterface>
analyticsStore.markActivity = jest.fn()
event = {} as jest.Mocked<PaymentSuccessEvent>
event.payload = {
userEmail: 'test@test.com',
}
})
it('should mark payment failed for analytics', async () => {
await createHandler().handle(event)
expect(analyticsStore.markActivity).toHaveBeenCalled()
})
it('should not mark payment failed for analytics if user is not found', async () => {
userRepository.findOneByEmail = jest.fn().mockReturnValue(null)
await createHandler().handle(event)
expect(analyticsStore.markActivity).not.toHaveBeenCalled()
})
})

View File

@@ -0,0 +1,30 @@
import { AnalyticsActivity, AnalyticsStoreInterface, Period } from '@standardnotes/analytics'
import { DomainEventHandlerInterface, PaymentSuccessEvent } from '@standardnotes/domain-events'
import { inject, injectable } from 'inversify'
import TYPES from '../../Bootstrap/Types'
import { GetUserAnalyticsId } from '../UseCase/GetUserAnalyticsId/GetUserAnalyticsId'
import { UserRepositoryInterface } from '../User/UserRepositoryInterface'
@injectable()
export class PaymentSuccessEventHandler implements DomainEventHandlerInterface {
constructor(
@inject(TYPES.UserRepository) private userRepository: UserRepositoryInterface,
@inject(TYPES.GetUserAnalyticsId) private getUserAnalyticsId: GetUserAnalyticsId,
@inject(TYPES.AnalyticsStore) private analyticsStore: AnalyticsStoreInterface,
) {}
async handle(event: PaymentSuccessEvent): Promise<void> {
const user = await this.userRepository.findOneByEmail(event.payload.userEmail)
if (user === null) {
return
}
const { analyticsId } = await this.getUserAnalyticsId.execute({ userUuid: user.uuid })
await this.analyticsStore.markActivity([AnalyticsActivity.PaymentSuccess], analyticsId, [
Period.Today,
Period.ThisWeek,
Period.ThisMonth,
])
}
}

View File

@@ -74,7 +74,7 @@ export class SubscriptionPurchasedEventHandler implements DomainEventHandlerInte
Period.ThisMonth,
])
const limitedDiscountPurchased = event.payload.discountCode === 'limited-10'
const limitedDiscountPurchased = ['limited-10', 'limited-20'].includes(event.payload.discountCode as string)
if (limitedDiscountPurchased) {
await this.analyticsStore.markActivity([AnalyticsActivity.LimitedDiscountOfferPurchased], analyticsId, [
Period.Today,

View File

@@ -4,17 +4,23 @@ import { UserDisabledSessionUserAgentLoggingEvent } from '@standardnotes/domain-
import { SessionRepositoryInterface } from '../Session/SessionRepositoryInterface'
import { UserDisabledSessionUserAgentLoggingEventHandler } from './UserDisabledSessionUserAgentLoggingEventHandler'
import { RevokedSessionRepositoryInterface } from '../Session/RevokedSessionRepositoryInterface'
describe('UserDisabledSessionUserAgentLoggingEventHandler', () => {
let sessionRepository: SessionRepositoryInterface
let revokedSessionRepository: RevokedSessionRepositoryInterface
let event: UserDisabledSessionUserAgentLoggingEvent
const createHandler = () => new UserDisabledSessionUserAgentLoggingEventHandler(sessionRepository)
const createHandler = () =>
new UserDisabledSessionUserAgentLoggingEventHandler(sessionRepository, revokedSessionRepository)
beforeEach(() => {
sessionRepository = {} as jest.Mocked<SessionRepositoryInterface>
sessionRepository.clearUserAgentByUserUuid = jest.fn()
revokedSessionRepository = {} as jest.Mocked<RevokedSessionRepositoryInterface>
revokedSessionRepository.clearUserAgentByUserUuid = jest.fn()
event = {} as jest.Mocked<UserDisabledSessionUserAgentLoggingEvent>
event.payload = {
userUuid: '1-2-3',
@@ -26,5 +32,6 @@ describe('UserDisabledSessionUserAgentLoggingEventHandler', () => {
await createHandler().handle(event)
expect(sessionRepository.clearUserAgentByUserUuid).toHaveBeenCalledWith('1-2-3')
expect(revokedSessionRepository.clearUserAgentByUserUuid).toHaveBeenCalledWith('1-2-3')
})
})

View File

@@ -2,13 +2,18 @@ import { DomainEventHandlerInterface, UserDisabledSessionUserAgentLoggingEvent }
import { inject, injectable } from 'inversify'
import TYPES from '../../Bootstrap/Types'
import { RevokedSessionRepositoryInterface } from '../Session/RevokedSessionRepositoryInterface'
import { SessionRepositoryInterface } from '../Session/SessionRepositoryInterface'
@injectable()
export class UserDisabledSessionUserAgentLoggingEventHandler implements DomainEventHandlerInterface {
constructor(@inject(TYPES.SessionRepository) private sessionRepository: SessionRepositoryInterface) {}
constructor(
@inject(TYPES.SessionRepository) private sessionRepository: SessionRepositoryInterface,
@inject(TYPES.SessionRepository) private revokedSessionRepository: RevokedSessionRepositoryInterface,
) {}
async handle(event: UserDisabledSessionUserAgentLoggingEvent): Promise<void> {
await this.sessionRepository.clearUserAgentByUserUuid(event.payload.userUuid)
await this.revokedSessionRepository.clearUserAgentByUserUuid(event.payload.userUuid)
}
}

View File

@@ -36,4 +36,25 @@ export class RevokedSession {
)
@JoinColumn({ name: 'user_uuid', referencedColumnName: 'uuid' })
declare user: Promise<User>
@Column({
name: 'received_at',
type: 'datetime',
nullable: true,
})
declare receivedAt: Date
@Column({
name: 'user_agent',
type: 'text',
nullable: true,
})
declare userAgent: string | null
@Column({
name: 'api_version',
length: 255,
nullable: true,
})
declare apiVersion: string
}

View File

@@ -1,3 +1,4 @@
import { Uuid } from '@standardnotes/common'
import { RevokedSession } from './RevokedSession'
export interface RevokedSessionRepositoryInterface {
@@ -5,4 +6,5 @@ export interface RevokedSessionRepositoryInterface {
findAllByUserUuid(userUuid: string): Promise<Array<RevokedSession>>
save(revokedSession: RevokedSession): Promise<RevokedSession>
remove(revokedSession: RevokedSession): Promise<RevokedSession>
clearUserAgentByUserUuid(userUuid: Uuid): Promise<void>
}

View File

@@ -2,6 +2,7 @@ import 'reflect-metadata'
import * as winston from 'winston'
import { TimerInterface } from '@standardnotes/time'
import { ApiVersion } from '../Api/ApiVersion'
import { Session } from './Session'
import { SessionRepositoryInterface } from './SessionRepositoryInterface'
import { SessionService } from './SessionService'
@@ -47,6 +48,7 @@ describe('SessionService', () => {
session.uuid = '2e1e43'
session.userUuid = '1-2-3'
session.userAgent = 'Chrome'
session.apiVersion = ApiVersion.v20200115
session.hashedAccessToken = '4e07408562bedb8b60ce05c1decfe3ad16b72230967de01f640b7e4729b49fce'
session.hashedRefreshToken = '4e07408562bedb8b60ce05c1decfe3ad16b72230967de01f640b7e4729b49fce'
@@ -80,6 +82,7 @@ describe('SessionService', () => {
timer = {} as jest.Mocked<TimerInterface>
timer.convertStringDateToMilliseconds = jest.fn().mockReturnValue(123)
timer.getUTCDate = jest.fn().mockReturnValue(new Date(1))
deviceDetector = {} as jest.Mocked<UAParser>
deviceDetector.setUA = jest.fn().mockReturnThis()
@@ -111,6 +114,7 @@ describe('SessionService', () => {
expect(revokedSessionRepository.save).toHaveBeenCalledWith({
uuid: '2e1e43',
received: true,
receivedAt: new Date(1),
})
})
@@ -476,6 +480,8 @@ describe('SessionService', () => {
expect(revokedSessionRepository.save).toHaveBeenCalledWith({
uuid: '2e1e43',
userUuid: '1-2-3',
userAgent: 'Chrome',
apiVersion: '20200115',
createdAt: expect.any(Date),
})
})

View File

@@ -203,6 +203,7 @@ export class SessionService implements SessionServiceInterface {
async markRevokedSessionAsReceived(revokedSession: RevokedSession): Promise<RevokedSession> {
revokedSession.received = true
revokedSession.receivedAt = this.timer.getUTCDate()
return this.revokedSessionRepository.save(revokedSession)
}
@@ -224,7 +225,9 @@ export class SessionService implements SessionServiceInterface {
const revokedSession = new RevokedSession()
revokedSession.uuid = session.uuid
revokedSession.userUuid = session.userUuid
revokedSession.createdAt = dayjs.utc().toDate()
revokedSession.createdAt = this.timer.getUTCDate()
revokedSession.apiVersion = session.apiVersion
revokedSession.userAgent = session.userAgent
return this.revokedSessionRepository.save(revokedSession)
}
@@ -246,8 +249,8 @@ export class SessionService implements SessionServiceInterface {
}
session.userUuid = dto.user.uuid
session.apiVersion = dto.apiVersion
session.createdAt = dayjs.utc().toDate()
session.updatedAt = dayjs.utc().toDate()
session.createdAt = this.timer.getUTCDate()
session.updatedAt = this.timer.getUTCDate()
session.readonlyAccess = dto.readonlyAccess
return session

View File

@@ -1,6 +1,6 @@
import 'reflect-metadata'
import { Repository, SelectQueryBuilder } from 'typeorm'
import { Repository, SelectQueryBuilder, UpdateQueryBuilder } from 'typeorm'
import { RevokedSession } from '../../Domain/Session/RevokedSession'
@@ -9,12 +9,14 @@ import { MySQLRevokedSessionRepository } from './MySQLRevokedSessionRepository'
describe('MySQLRevokedSessionRepository', () => {
let ormRepository: Repository<RevokedSession>
let queryBuilder: SelectQueryBuilder<RevokedSession>
let updateQueryBuilder: UpdateQueryBuilder<RevokedSession>
let session: RevokedSession
const createRepository = () => new MySQLRevokedSessionRepository(ormRepository)
beforeEach(() => {
queryBuilder = {} as jest.Mocked<SelectQueryBuilder<RevokedSession>>
updateQueryBuilder = {} as jest.Mocked<UpdateQueryBuilder<RevokedSession>>
session = {} as jest.Mocked<RevokedSession>
@@ -36,6 +38,24 @@ describe('MySQLRevokedSessionRepository', () => {
expect(ormRepository.remove).toHaveBeenCalledWith(session)
})
it('should clear user agent data on all user sessions', async () => {
ormRepository.createQueryBuilder = jest.fn().mockImplementation(() => updateQueryBuilder)
updateQueryBuilder.update = jest.fn().mockReturnThis()
updateQueryBuilder.set = jest.fn().mockReturnThis()
updateQueryBuilder.where = jest.fn().mockReturnThis()
updateQueryBuilder.execute = jest.fn()
await createRepository().clearUserAgentByUserUuid('1-2-3')
expect(updateQueryBuilder.update).toHaveBeenCalled()
expect(updateQueryBuilder.set).toHaveBeenCalledWith({
userAgent: null,
})
expect(updateQueryBuilder.where).toHaveBeenCalledWith('user_uuid = :userUuid', { userUuid: '1-2-3' })
expect(updateQueryBuilder.execute).toHaveBeenCalled()
})
it('should find one session by id', async () => {
queryBuilder.where = jest.fn().mockReturnThis()
queryBuilder.getOne = jest.fn().mockReturnValue(session)

View File

@@ -20,6 +20,17 @@ export class MySQLRevokedSessionRepository implements RevokedSessionRepositoryIn
return this.ormRepository.remove(revokedSession)
}
async clearUserAgentByUserUuid(userUuid: string): Promise<void> {
await this.ormRepository
.createQueryBuilder('revoked_session')
.update()
.set({
userAgent: null,
})
.where('user_uuid = :userUuid', { userUuid })
.execute()
}
async findAllByUserUuid(userUuid: string): Promise<RevokedSession[]> {
return this.ormRepository
.createQueryBuilder('revoked_session')

View File

@@ -3,6 +3,22 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.7.35](https://github.com/standardnotes/server/compare/@standardnotes/domain-events-infra@1.7.34...@standardnotes/domain-events-infra@1.7.35) (2022-09-01)
**Note:** Version bump only for package @standardnotes/domain-events-infra
## [1.7.34](https://github.com/standardnotes/server/compare/@standardnotes/domain-events-infra@1.7.33...@standardnotes/domain-events-infra@1.7.34) (2022-08-30)
**Note:** Version bump only for package @standardnotes/domain-events-infra
## [1.7.33](https://github.com/standardnotes/server/compare/@standardnotes/domain-events-infra@1.7.32...@standardnotes/domain-events-infra@1.7.33) (2022-08-15)
**Note:** Version bump only for package @standardnotes/domain-events-infra
## [1.7.32](https://github.com/standardnotes/server/compare/@standardnotes/domain-events-infra@1.7.31...@standardnotes/domain-events-infra@1.7.32) (2022-08-15)
**Note:** Version bump only for package @standardnotes/domain-events-infra
## [1.7.31](https://github.com/standardnotes/server/compare/@standardnotes/domain-events-infra@1.7.30...@standardnotes/domain-events-infra@1.7.31) (2022-08-10)
**Note:** Version bump only for package @standardnotes/domain-events-infra

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/domain-events-infra",
"version": "1.7.31",
"version": "1.7.35",
"engines": {
"node": ">=16.0.0 <17.0.0"
},

View File

@@ -3,6 +3,30 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
# [2.55.0](https://github.com/standardnotes/server/compare/@standardnotes/domain-events@2.54.2...@standardnotes/domain-events@2.55.0) (2022-09-01)
### Features
* **domain-events:** add subscription revert requested event ([e0cec9e](https://github.com/standardnotes/server/commit/e0cec9e24ab9954868fb428062c9a82d0f0f85d5))
## [2.54.2](https://github.com/standardnotes/server/compare/@standardnotes/domain-events@2.54.1...@standardnotes/domain-events@2.54.2) (2022-08-30)
### Bug Fixes
* **domain-events:** add replaced boolean to subscription canceled event ([932ef93](https://github.com/standardnotes/server/commit/932ef933fce71aabdddca33da4eec6ce8fe686ef))
## [2.54.1](https://github.com/standardnotes/server/compare/@standardnotes/domain-events@2.54.0...@standardnotes/domain-events@2.54.1) (2022-08-15)
### Bug Fixes
* **domain-events:** missing exports ([2fb904d](https://github.com/standardnotes/server/commit/2fb904d2cbff040ba9a6b2b323eab1591309b174))
# [2.54.0](https://github.com/standardnotes/server/compare/@standardnotes/domain-events@2.53.0...@standardnotes/domain-events@2.54.0) (2022-08-15)
### Features
* **domain-events:** add payment success event ([1841597](https://github.com/standardnotes/server/commit/1841597405461981c7b6eb4ee8ada079c77a8fc5))
# [2.53.0](https://github.com/standardnotes/server/compare/@standardnotes/domain-events@2.52.0...@standardnotes/domain-events@2.53.0) (2022-08-09)
### Features

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/domain-events",
"version": "2.53.0",
"version": "2.55.0",
"engines": {
"node": ">=16.0.0 <17.0.0"
},

View File

@@ -0,0 +1,8 @@
import { DomainEventInterface } from './DomainEventInterface'
import { PaymentSuccessEventPayload } from './PaymentSuccessEventPayload'
export interface PaymentSuccessEvent extends DomainEventInterface {
type: 'PAYMENT_SUCCESS'
payload: PaymentSuccessEventPayload
}

View File

@@ -0,0 +1,3 @@
export interface PaymentSuccessEventPayload {
userEmail: string
}

View File

@@ -6,4 +6,5 @@ export interface SubscriptionCancelledEventPayload {
subscriptionName: SubscriptionName
timestamp: number
offline: boolean
replaced: boolean
}

View File

@@ -0,0 +1,8 @@
import { DomainEventInterface } from './DomainEventInterface'
import { SubscriptionRevertRequestedEventPayload } from './SubscriptionRevertRequestedEventPayload'
export interface SubscriptionRevertRequestedEvent extends DomainEventInterface {
type: 'SUBSCRIPTION_REVERT_REQUESTED'
payload: SubscriptionRevertRequestedEventPayload
}

View File

@@ -0,0 +1,3 @@
export interface SubscriptionRevertRequestedEventPayload {
userEmail: string
}

View File

@@ -54,6 +54,8 @@ export * from './Event/OneDriveBackupFailedEvent'
export * from './Event/OneDriveBackupFailedEventPayload'
export * from './Event/PaymentFailedEvent'
export * from './Event/PaymentFailedEventPayload'
export * from './Event/PaymentSuccessEvent'
export * from './Event/PaymentSuccessEventPayload'
export * from './Event/PredicateVerificationRequestedEvent'
export * from './Event/PredicateVerificationRequestedEventPayload'
export * from './Event/PredicateVerifiedEvent'
@@ -84,6 +86,8 @@ export * from './Event/SubscriptionRenewedEvent'
export * from './Event/SubscriptionRenewedEventPayload'
export * from './Event/SubscriptionExpiredEvent'
export * from './Event/SubscriptionExpiredEventPayload'
export * from './Event/SubscriptionRevertRequestedEvent'
export * from './Event/SubscriptionRevertRequestedEventPayload'
export * from './Event/SubscriptionSyncRequestedEvent'
export * from './Event/SubscriptionSyncRequestedEventPayload'
export * from './Event/UserDisabledSessionUserAgentLoggingEvent'

View File

@@ -3,6 +3,30 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.2.2](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.2.1...@standardnotes/event-store@1.2.2) (2022-09-01)
**Note:** Version bump only for package @standardnotes/event-store
## [1.2.1](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.2.0...@standardnotes/event-store@1.2.1) (2022-08-30)
**Note:** Version bump only for package @standardnotes/event-store
# [1.2.0](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.1.33...@standardnotes/event-store@1.2.0) (2022-08-30)
### Features
* **event-store:** add account claim events subscription ([dd6bec8](https://github.com/standardnotes/server/commit/dd6bec8a0c957b87ccf4d1fb0636fa3f56a4525e))
## [1.1.33](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.1.32...@standardnotes/event-store@1.1.33) (2022-08-15)
### Bug Fixes
* **event-store:** add payment events handling ([3477c81](https://github.com/standardnotes/server/commit/3477c81d37e6cb92e76d59b1128daac702a4a7ae))
## [1.1.32](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.1.31...@standardnotes/event-store@1.1.32) (2022-08-15)
**Note:** Version bump only for package @standardnotes/event-store
## [1.1.31](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.1.30...@standardnotes/event-store@1.1.31) (2022-08-12)
### Bug Fixes

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/event-store",
"version": "1.1.31",
"version": "1.2.2",
"description": "Event Store Service",
"private": true,
"main": "dist/src/index.js",

View File

@@ -76,6 +76,9 @@ export class ContainerConfigLoader {
['EMAIL_BACKUP_ATTACHMENT_CREATED', container.get(TYPES.EventHandler)],
['EMAIL_BACKUP_REQUESTED', container.get(TYPES.EventHandler)],
['OFFLINE_SUBSCRIPTION_TOKEN_CREATED', container.get(TYPES.EventHandler)],
['PAYMENT_FAILED', container.get(TYPES.EventHandler)],
['PAYMENT_SUCCESS', container.get(TYPES.EventHandler)],
['ACCOUNT_CLAIM_REQUESTED', container.get(TYPES.EventHandler)],
])
container

View File

@@ -3,6 +3,26 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.5.38](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.5.37...@standardnotes/files-server@1.5.38) (2022-09-01)
**Note:** Version bump only for package @standardnotes/files-server
## [1.5.37](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.5.36...@standardnotes/files-server@1.5.37) (2022-08-30)
**Note:** Version bump only for package @standardnotes/files-server
## [1.5.36](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.5.35...@standardnotes/files-server@1.5.36) (2022-08-29)
**Note:** Version bump only for package @standardnotes/files-server
## [1.5.35](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.5.34...@standardnotes/files-server@1.5.35) (2022-08-15)
**Note:** Version bump only for package @standardnotes/files-server
## [1.5.34](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.5.33...@standardnotes/files-server@1.5.34) (2022-08-15)
**Note:** Version bump only for package @standardnotes/files-server
## [1.5.33](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.5.32...@standardnotes/files-server@1.5.33) (2022-08-10)
**Note:** Version bump only for package @standardnotes/files-server

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/files-server",
"version": "1.5.33",
"version": "1.5.38",
"engines": {
"node": ">=16.0.0 <17.0.0"
},
@@ -50,7 +50,7 @@
"nodemon": "^2.0.19",
"prettyjson": "^1.2.5",
"reflect-metadata": "^0.1.13",
"ts-node": "^10.4.0",
"ts-node": "^10.9.1",
"winston": "^3.8.1"
},
"devDependencies": {

View File

@@ -3,6 +3,46 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.10.15](https://github.com/standardnotes/server/compare/@standardnotes/scheduler-server@1.10.14...@standardnotes/scheduler-server@1.10.15) (2022-09-01)
**Note:** Version bump only for package @standardnotes/scheduler-server
## [1.10.14](https://github.com/standardnotes/server/compare/@standardnotes/scheduler-server@1.10.13...@standardnotes/scheduler-server@1.10.14) (2022-08-30)
### Bug Fixes
* **scheduler:** linter issues ([648eb89](https://github.com/standardnotes/server/commit/648eb89c7c7b95cfb6235e38180958c3d332825d))
## [1.10.13](https://github.com/standardnotes/server/compare/@standardnotes/scheduler-server@1.10.12...@standardnotes/scheduler-server@1.10.13) (2022-08-30)
### Bug Fixes
* **scheduler:** skip sending exit survery when a subscription is replaced ([35373db](https://github.com/standardnotes/server/commit/35373db1d3d25ae5878ef7f7cfc8594a6623da8a))
## [1.10.12](https://github.com/standardnotes/server/compare/@standardnotes/scheduler-server@1.10.11...@standardnotes/scheduler-server@1.10.12) (2022-08-30)
**Note:** Version bump only for package @standardnotes/scheduler-server
## [1.10.11](https://github.com/standardnotes/server/compare/@standardnotes/scheduler-server@1.10.10...@standardnotes/scheduler-server@1.10.11) (2022-08-29)
### Bug Fixes
* **scheduler:** change logs severity to reduce noise ([dbe55d8](https://github.com/standardnotes/server/commit/dbe55d89ec33a4c69cae350793bc4c5dd6589a2b))
## [1.10.10](https://github.com/standardnotes/server/compare/@standardnotes/scheduler-server@1.10.9...@standardnotes/scheduler-server@1.10.10) (2022-08-17)
### Bug Fixes
* **scheduler:** change discount from 10% to 20% on a limited time offer ([4b3de26](https://github.com/standardnotes/server/commit/4b3de264efc4fffb2603181c158cddb25c4ed4a9))
## [1.10.9](https://github.com/standardnotes/server/compare/@standardnotes/scheduler-server@1.10.8...@standardnotes/scheduler-server@1.10.9) (2022-08-15)
**Note:** Version bump only for package @standardnotes/scheduler-server
## [1.10.8](https://github.com/standardnotes/server/compare/@standardnotes/scheduler-server@1.10.7...@standardnotes/scheduler-server@1.10.8) (2022-08-15)
**Note:** Version bump only for package @standardnotes/scheduler-server
## [1.10.7](https://github.com/standardnotes/server/compare/@standardnotes/scheduler-server@1.10.6...@standardnotes/scheduler-server@1.10.7) (2022-08-10)
**Note:** Version bump only for package @standardnotes/scheduler-server

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/scheduler-server",
"version": "1.10.7",
"version": "1.10.15",
"engines": {
"node": ">=16.0.0 <17.0.0"
},
@@ -15,6 +15,7 @@
"prebuild": "yarn clean",
"build": "tsc --rootDir ./",
"lint": "eslint . --ext .ts",
"lint:fix": "eslint . --ext .ts --fix",
"pretest": "yarn lint && yarn build",
"test": "jest --coverage --config=./jest.config.js --maxWorkers=50%",
"worker": "yarn node dist/bin/worker.js",
@@ -48,6 +49,7 @@
"@types/newrelic": "^7.0.3",
"@types/node": "^18.0.0",
"@typescript-eslint/eslint-plugin": "^5.29.0",
"eslint": "^8.14.0",
"eslint-plugin-prettier": "^4.0.0",
"jest": "^28.1.2",
"npm-check-updates": "^16.0.1",

View File

@@ -18,7 +18,7 @@ describe('PredicateVerifiedEventHandler', () => {
updatePredicateStatus.execute = jest.fn()
logger = {} as jest.Mocked<Logger>
logger.info = jest.fn()
logger.debug = jest.fn()
event = {} as jest.Mocked<PredicateVerifiedEvent>
event.payload = {

View File

@@ -13,7 +13,7 @@ export class PredicateVerifiedEventHandler implements DomainEventHandlerInterfac
) {}
async handle(event: PredicateVerifiedEvent): Promise<void> {
this.logger.info(
this.logger.debug(
`Updating predicate ${event.payload.predicate.name} for job ${event.payload.predicate.jobUuid} with status ${event.payload.predicateVerificationResult}`,
)

View File

@@ -24,7 +24,9 @@ describe('SubscriptionCancelledEventHandler', () => {
})
it('should schedule a job to do an exit interview', async () => {
await createHandler().handle({ payload: { userEmail: 'test@test.te' } } as jest.Mocked<SubscriptionCancelledEvent>)
await createHandler().handle({
payload: { userEmail: 'test@test.te', replaced: false },
} as jest.Mocked<SubscriptionCancelledEvent>)
expect(jobRepository.save).toHaveBeenNthCalledWith(1, {
createdAt: 1,
@@ -35,4 +37,12 @@ describe('SubscriptionCancelledEventHandler', () => {
userIdentifierType: 'email',
})
})
it('should not schedule a job to do an exit interview if the subscription is replaced', async () => {
await createHandler().handle({
payload: { userEmail: 'test@test.te', replaced: true },
} as jest.Mocked<SubscriptionCancelledEvent>)
expect(jobRepository.save).not.toHaveBeenCalled()
})
})

View File

@@ -16,7 +16,9 @@ export class SubscriptionCancelledEventHandler implements DomainEventHandlerInte
) {}
async handle(event: SubscriptionCancelledEvent): Promise<void> {
await this.scheduleExitInterview(event)
if (!event.payload.replaced) {
await this.scheduleExitInterview(event)
}
}
private async scheduleExitInterview(event: SubscriptionCancelledEvent): Promise<void> {

View File

@@ -54,6 +54,7 @@ describe('JobDoneInterpreter', () => {
logger = {} as jest.Mocked<Logger>
logger.info = jest.fn()
logger.debug = jest.fn()
logger.warn = jest.fn()
})
@@ -205,7 +206,7 @@ describe('JobDoneInterpreter', () => {
expect(domainEventFactory.createDiscountApplyRequestedEvent).toHaveBeenCalledWith({
userEmail: 'test@standardnotes.com',
discountCode: 'limited-10',
discountCode: 'limited-20',
})
expect(domainEventPublisher.publish).toHaveBeenCalled()
})
@@ -234,7 +235,7 @@ describe('JobDoneInterpreter', () => {
expect(domainEventFactory.createDiscountWithdrawRequestedEvent).toHaveBeenCalledWith({
userEmail: 'test@standardnotes.com',
discountCode: 'limited-10',
discountCode: 'limited-20',
})
expect(domainEventPublisher.publish).toHaveBeenCalled()
})

View File

@@ -31,10 +31,10 @@ export class JobDoneInterpreter implements JobDoneInterpreterInterface {
return
}
this.logger.info(`[${jobUuid}]${job.name}: Interpreting job as done.`)
this.logger.debug(`[${jobUuid}]${job.name}: Interpreting job as done.`)
if (!(await this.predicatesAreFulfilled(job))) {
this.logger.info(`[${jobUuid}]${job.name}: predicates are not fulfilled.`)
this.logger.debug(`[${jobUuid}]${job.name}: predicates are not fulfilled.`)
return
}
@@ -73,7 +73,7 @@ export class JobDoneInterpreter implements JobDoneInterpreterInterface {
}
private async requestEmailBackupEncouragementEmail(job: Job): Promise<void> {
this.logger.info(`[${job.uuid}]${job.name}: requesting email backup encouragement email.`)
this.logger.debug(`[${job.uuid}]${job.name}: requesting email backup encouragement email.`)
await this.domainEventPublisher.publish(
this.domainEventFactory.createEmailMessageRequestedEvent({
@@ -85,7 +85,7 @@ export class JobDoneInterpreter implements JobDoneInterpreterInterface {
}
private async requestSubscriptionPurchaseEncouragementEmail(job: Job): Promise<void> {
this.logger.info(`[${job.uuid}]${job.name}: requesting subscription purchase encouragement email.`)
this.logger.debug(`[${job.uuid}]${job.name}: requesting subscription purchase encouragement email.`)
await this.domainEventPublisher.publish(
this.domainEventFactory.createEmailMessageRequestedEvent({
@@ -99,7 +99,7 @@ export class JobDoneInterpreter implements JobDoneInterpreterInterface {
}
private async requestExitInterviewEmail(job: Job): Promise<void> {
this.logger.info(`[${job.uuid}]${job.name}: requesting exit interview email.`)
this.logger.debug(`[${job.uuid}]${job.name}: requesting exit interview email.`)
await this.domainEventPublisher.publish(
this.domainEventFactory.createEmailMessageRequestedEvent({
@@ -111,23 +111,23 @@ export class JobDoneInterpreter implements JobDoneInterpreterInterface {
}
private async requestDiscountApply(job: Job): Promise<void> {
this.logger.info(`[${job.uuid}]${job.name}: requesting discount applying.`)
this.logger.debug(`[${job.uuid}]${job.name}: requesting discount applying.`)
await this.domainEventPublisher.publish(
this.domainEventFactory.createDiscountApplyRequestedEvent({
userEmail: job.userIdentifier,
discountCode: 'limited-10',
discountCode: 'limited-20',
}),
)
}
private async requestDiscountWithdraw(job: Job): Promise<void> {
this.logger.info(`[${job.uuid}]${job.name}: requesting discount withdraw.`)
this.logger.debug(`[${job.uuid}]${job.name}: requesting discount withdraw.`)
await this.domainEventPublisher.publish(
this.domainEventFactory.createDiscountWithdrawRequestedEvent({
userEmail: job.userIdentifier,
discountCode: 'limited-10',
discountCode: 'limited-20',
}),
)
}

View File

@@ -3,6 +3,38 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.6.52](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.6.51...@standardnotes/syncing-server@1.6.52) (2022-09-01)
**Note:** Version bump only for package @standardnotes/syncing-server
## [1.6.51](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.6.50...@standardnotes/syncing-server@1.6.51) (2022-08-30)
**Note:** Version bump only for package @standardnotes/syncing-server
## [1.6.50](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.6.49...@standardnotes/syncing-server@1.6.50) (2022-08-15)
**Note:** Version bump only for package @standardnotes/syncing-server
## [1.6.49](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.6.48...@standardnotes/syncing-server@1.6.49) (2022-08-15)
**Note:** Version bump only for package @standardnotes/syncing-server
## [1.6.48](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.6.47...@standardnotes/syncing-server@1.6.48) (2022-08-15)
**Note:** Version bump only for package @standardnotes/syncing-server
## [1.6.47](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.6.46...@standardnotes/syncing-server@1.6.47) (2022-08-15)
**Note:** Version bump only for package @standardnotes/syncing-server
## [1.6.46](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.6.45...@standardnotes/syncing-server@1.6.46) (2022-08-15)
**Note:** Version bump only for package @standardnotes/syncing-server
## [1.6.45](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.6.44...@standardnotes/syncing-server@1.6.45) (2022-08-15)
**Note:** Version bump only for package @standardnotes/syncing-server
## [1.6.44](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.6.43...@standardnotes/syncing-server@1.6.44) (2022-08-15)
**Note:** Version bump only for package @standardnotes/syncing-server

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/syncing-server",
"version": "1.6.44",
"version": "1.6.52",
"engines": {
"node": ">=16.0.0 <17.0.0"
},

View File

@@ -2047,7 +2047,7 @@ __metadata:
prettyjson: ^1.2.5
reflect-metadata: ^0.1.13
ts-jest: ^28.0.5
ts-node: ^10.4.0
ts-node: ^10.9.1
uuid: ^8.3.2
winston: ^3.8.1
languageName: unknown
@@ -2122,6 +2122,7 @@ __metadata:
aws-sdk: ^2.1158.0
dayjs: ^1.11.3
dotenv: ^16.0.1
eslint: ^8.14.0
eslint-plugin-prettier: ^4.0.0
inversify: ^6.0.1
ioredis: ^5.2.0
@@ -2172,7 +2173,7 @@ __metadata:
newrelic: ^9.0.0
npm-check-updates: ^16.0.1
prettier: ^2.7.1
ts-node: ^10.8.1
ts-node: ^10.9.1
typescript: ^4.7.4
languageName: unknown
linkType: soft
@@ -9962,7 +9963,7 @@ __metadata:
languageName: node
linkType: hard
"ts-node@npm:^10.4.0, ts-node@npm:^10.8.1":
"ts-node@npm:^10.8.1":
version: 10.8.2
resolution: "ts-node@npm:10.8.2"
dependencies:
@@ -10000,6 +10001,44 @@ __metadata:
languageName: node
linkType: hard
"ts-node@npm:^10.9.1":
version: 10.9.1
resolution: "ts-node@npm:10.9.1"
dependencies:
"@cspotcode/source-map-support": ^0.8.0
"@tsconfig/node10": ^1.0.7
"@tsconfig/node12": ^1.0.7
"@tsconfig/node14": ^1.0.0
"@tsconfig/node16": ^1.0.2
acorn: ^8.4.1
acorn-walk: ^8.1.1
arg: ^4.1.0
create-require: ^1.1.0
diff: ^4.0.1
make-error: ^1.1.1
v8-compile-cache-lib: ^3.0.1
yn: 3.1.1
peerDependencies:
"@swc/core": ">=1.2.50"
"@swc/wasm": ">=1.2.50"
"@types/node": "*"
typescript: ">=2.7"
peerDependenciesMeta:
"@swc/core":
optional: true
"@swc/wasm":
optional: true
bin:
ts-node: dist/bin.js
ts-node-cwd: dist/bin-cwd.js
ts-node-esm: dist/bin-esm.js
ts-node-script: dist/bin-script.js
ts-node-transpile-only: dist/bin-transpile.js
ts-script: dist/bin-script-deprecated.js
checksum: 090adff1302ab20bd3486e6b4799e90f97726ed39e02b39e566f8ab674fd5bd5f727f43615debbfc580d33c6d9d1c6b1b3ce7d8e3cca3e20530a145ffa232c35
languageName: node
linkType: hard
"tslib@npm:^1.8.1, tslib@npm:^1.9.3":
version: 1.14.1
resolution: "tslib@npm:1.14.1"