Compare commits

...

65 Commits

Author SHA1 Message Date
standardci
2178ed2a31 chore(release): publish new version
- @standardnotes/syncing-server@1.13.6
2022-11-14 09:42:58 +00:00
Karol Sójko
79511aea5f fix(syncing-server): add missing content size recalculation handler binding 2022-11-14 10:40:51 +01:00
standardci
19bb77273b chore(release): publish new version
- @standardnotes/analytics@2.9.9
 - @standardnotes/api-gateway@1.38.4
 - @standardnotes/auth-server@1.59.10
 - @standardnotes/common@1.44.4
 - @standardnotes/domain-events-infra@1.9.26
 - @standardnotes/domain-events@2.86.3
 - @standardnotes/event-store@1.6.21
 - @standardnotes/files-server@1.8.21
 - @standardnotes/predicates@1.5.7
 - @standardnotes/scheduler-server@1.13.22
 - @standardnotes/security@1.6.4
 - @standardnotes/settings@1.18.3
 - @standardnotes/sncrypto-node@1.12.3
 - @standardnotes/syncing-server@1.13.5
 - @standardnotes/time@1.13.3
 - @standardnotes/websockets-server@1.4.23
 - @standardnotes/workspace-server@1.17.21
2022-11-14 09:39:52 +00:00
Karol Sójko
7ca377f1b8 fix: versioning issue 2022-11-14 10:37:27 +01:00
Karol Sójko
6f5e9b7b5a fix(api-gateway): bump version 2022-11-14 10:32:54 +01:00
Karol Sójko
f03a58079d chore(deps): upgrade node types 2022-11-14 10:29:20 +01:00
Karol Sójko
8715fe1822 fix(analytics): bump version 2022-11-14 10:27:20 +01:00
Karol Sójko
e10cb9adaf chore(deps): upgrade to latest node LTS 2022-11-14 10:21:18 +01:00
Karol Sójko
3030832711 chore(deps): upgrade typeorm 2022-11-14 10:13:12 +01:00
Karol Sójko
7c638ef28a chore(deps): add missing sentry deps 2022-11-14 10:11:32 +01:00
Karol Sójko
447a4b5e04 chore(deps): upgrade sentry 2022-11-14 10:11:00 +01:00
Karol Sójko
dd1ba6e302 chore(deps): upgrade aws-sdk 2022-11-14 10:10:18 +01:00
Karol Sójko
08556b751f chore(deps): upgrade express 2022-11-14 10:09:42 +01:00
Karol Sójko
11d2190310 chore(deps): upgrade ioredis 2022-11-14 10:08:54 +01:00
Karol Sójko
46519bb710 chore(deps): add newrelic native metrics to measure oom issues 2022-11-14 10:06:49 +01:00
standardci
7b9290382d chore(release): publish new version
- @standardnotes/analytics@2.9.6
 - @standardnotes/api-gateway@1.38.1
 - @standardnotes/auth-server@1.59.7
 - @standardnotes/domain-events-infra@1.9.23
 - @standardnotes/event-store@1.6.18
 - @standardnotes/files-server@1.8.18
 - @standardnotes/scheduler-server@1.13.19
 - @standardnotes/syncing-server@1.13.2
 - @standardnotes/websockets-server@1.4.20
 - @standardnotes/workspace-server@1.17.18
2022-11-14 09:03:07 +00:00
Karol Sójko
85e55cf0e4 chore(deps): upgrade newrelic 2022-11-14 10:01:08 +01:00
standardci
7016854b7f chore(release): publish new version
- @standardnotes/syncing-server@1.13.1
2022-11-14 08:14:00 +00:00
Karol Sójko
01a4151763 fix(syncing-server): add debugs logs for content size recalculation handler 2022-11-14 09:11:33 +01:00
standardci
311f758cd8 chore(release): publish new version
- @standardnotes/api-gateway@1.38.0
2022-11-13 15:06:19 +00:00
Mo
3bba36742a feat: iap confirm endpoint (#338) 2022-11-13 09:04:27 -06:00
standardci
ea52ba51ca chore(release): publish new version
- @standardnotes/syncing-server@1.13.0
2022-11-11 12:57:03 +00:00
Karol Sójko
7e404ae71a feat(syncing-server): add content size recalculation job 2022-11-11 13:54:45 +01:00
standardci
3ad95afa84 chore(release): publish new version
- @standardnotes/analytics@2.9.5
 - @standardnotes/api-gateway@1.37.11
 - @standardnotes/auth-server@1.59.6
 - @standardnotes/domain-events-infra@1.9.22
 - @standardnotes/domain-events@2.86.0
 - @standardnotes/event-store@1.6.17
 - @standardnotes/files-server@1.8.17
 - @standardnotes/scheduler-server@1.13.18
 - @standardnotes/syncing-server@1.12.0
 - @standardnotes/websockets-server@1.4.19
 - @standardnotes/workspace-server@1.17.17
2022-11-11 12:45:17 +00:00
Karol Sójko
1a13861647 feat(syncing-server): add item content size recalculation 2022-11-11 13:43:22 +01:00
standardci
6d84c819c0 chore(release): publish new version
- @standardnotes/analytics@2.9.4
 - @standardnotes/api-gateway@1.37.10
 - @standardnotes/auth-server@1.59.5
 - @standardnotes/domain-events-infra@1.9.21
 - @standardnotes/domain-events@2.85.0
 - @standardnotes/event-store@1.6.16
 - @standardnotes/files-server@1.8.16
 - @standardnotes/scheduler-server@1.13.17
 - @standardnotes/syncing-server@1.11.10
 - @standardnotes/websockets-server@1.4.18
 - @standardnotes/workspace-server@1.17.16
2022-11-11 12:11:40 +00:00
Karol Sójko
36ec39d2fb feat(domain-events): add user content size recalculation requested event 2022-11-11 13:09:33 +01:00
standardci
eaafc12c8a chore(release): publish new version
- @standardnotes/analytics@2.9.3
 - @standardnotes/api-gateway@1.37.9
 - @standardnotes/auth-server@1.59.4
 - @standardnotes/common@1.44.1
 - @standardnotes/domain-events-infra@1.9.20
 - @standardnotes/domain-events@2.84.1
 - @standardnotes/event-store@1.6.15
 - @standardnotes/files-server@1.8.15
 - @standardnotes/predicates@1.5.4
 - @standardnotes/scheduler-server@1.13.16
 - @standardnotes/security@1.6.1
 - @standardnotes/syncing-server@1.11.9
 - @standardnotes/websockets-server@1.4.17
 - @standardnotes/workspace-server@1.17.15
2022-11-10 18:20:16 +00:00
Karol Sójko
a03c5bceea fix(analytics): add five year plans mrr calculation 2022-11-10 19:18:25 +01:00
standardci
53c51fd204 chore(release): publish new version
- @standardnotes/analytics@2.9.2
2022-11-10 15:21:59 +00:00
Karol Sójko
9b593f2a6b fix(analytics): add missing period for stats report 2022-11-10 16:19:45 +01:00
standardci
363609cb1b chore(release): publish new version
- @standardnotes/api-gateway@1.37.8
 - @standardnotes/auth-server@1.59.3
 - @standardnotes/syncing-server@1.11.8
 - @standardnotes/websockets-server@1.4.16
2022-11-10 15:19:21 +00:00
Karol Sójko
68e6d30093 chore(deps): fix axios imports 2022-11-10 16:17:11 +01:00
standardci
c53a40ef8d chore(release): publish new version
- @standardnotes/api-gateway@1.37.7
 - @standardnotes/auth-server@1.59.2
 - @standardnotes/syncing-server@1.11.7
 - @standardnotes/websockets-server@1.4.15
2022-11-10 14:42:52 +00:00
Karol Sójko
3c2ac05c60 fix(api-gateway): setting headers 2022-11-10 15:39:57 +01:00
Karol Sójko
bffab433f6 chore(deps): upgrade ua-parser-js 2022-11-10 15:37:31 +01:00
Karol Sójko
200b6ce01f chore(deps): upgrade axios 2022-11-10 15:35:39 +01:00
standardci
0d29dc1012 chore(release): publish new version
- @standardnotes/analytics@2.9.1
2022-11-10 14:24:45 +00:00
Karol Sójko
b92c4ae650 fix(analytics): generate mrr stats for last 30 days including Today 2022-11-10 15:22:52 +01:00
standardci
e15d1e52bd chore(release): publish new version
- @standardnotes/analytics@2.9.0
2022-11-10 14:19:41 +00:00
Karol Sójko
ce3e259bde feat(analytics): add mrr for annual, monthly, pro and plus subscription plans 2022-11-10 15:17:35 +01:00
standardci
87361f90b1 chore(release): publish new version
- @standardnotes/analytics@2.8.3
2022-11-10 11:27:40 +00:00
Karol Sójko
81be06598c fix(analytics): add subscription id to error logs 2022-11-10 12:25:46 +01:00
standardci
9492da6789 chore(release): publish new version
- @standardnotes/analytics@2.8.2
2022-11-10 10:54:18 +00:00
Karol Sójko
fce47a0a37 fix(analytics): add monthly mrr to the report 2022-11-10 11:52:24 +01:00
standardci
92ba682198 chore(release): publish new version
- @standardnotes/analytics@2.8.1
2022-11-10 10:43:40 +00:00
Karol Sójko
8df0482eb4 fix(analytics): add persisting mrr for this month and this year as well 2022-11-10 11:41:24 +01:00
standardci
37a5cb347d chore(release): publish new version
- @standardnotes/analytics@2.8.0
 - @standardnotes/api-gateway@1.37.6
 - @standardnotes/auth-server@1.59.1
 - @standardnotes/domain-events-infra@1.9.19
 - @standardnotes/domain-events@2.84.0
 - @standardnotes/event-store@1.6.14
 - @standardnotes/files-server@1.8.14
 - @standardnotes/scheduler-server@1.13.15
 - @standardnotes/syncing-server@1.11.6
 - @standardnotes/websockets-server@1.4.14
 - @standardnotes/workspace-server@1.17.14
2022-11-10 10:35:38 +00:00
Karol Sójko
77e50655f6 feat(analytics): add calculating monthly recurring revenue 2022-11-10 11:33:46 +01:00
standardci
eacd2abc00 chore(release): publish new version
- @standardnotes/analytics@2.7.3
2022-11-10 06:55:58 +00:00
Karol Sójko
7393954ff6 fix(analytics): arhcitecture arrangements for use case execution 2022-11-10 07:54:06 +01:00
standardci
68744379a6 chore(release): publish new version
- @standardnotes/analytics@2.7.2
2022-11-09 12:11:11 +00:00
Karol Sójko
90aef905af fix(analytics): mrr column types 2022-11-09 13:09:14 +01:00
standardci
c7cbc8966e chore(release): publish new version
- @standardnotes/analytics@2.7.1
2022-11-09 11:43:39 +00:00
Karol Sójko
89502bed63 fix(analytics): add missing created at column 2022-11-09 12:41:45 +01:00
standardci
4952b48db6 chore(release): publish new version
- @standardnotes/analytics@2.7.0
 - @standardnotes/api-gateway@1.37.5
 - @standardnotes/auth-server@1.59.0
 - @standardnotes/domain-events-infra@1.9.18
 - @standardnotes/domain-events@2.83.0
 - @standardnotes/event-store@1.6.13
 - @standardnotes/files-server@1.8.13
 - @standardnotes/scheduler-server@1.13.14
 - @standardnotes/syncing-server@1.11.5
 - @standardnotes/websockets-server@1.4.13
 - @standardnotes/workspace-server@1.17.13
2022-11-09 10:27:37 +00:00
Karol Sójko
52a257abb1 feat(analytics): add saving revenue modifications upon subscription canceled 2022-11-09 11:25:26 +01:00
standardci
7480fb089b chore(release): publish new version
- @standardnotes/analytics@2.6.0
 - @standardnotes/api-gateway@1.37.4
 - @standardnotes/auth-server@1.58.0
 - @standardnotes/domain-events-infra@1.9.17
 - @standardnotes/domain-events@2.82.0
 - @standardnotes/event-store@1.6.12
 - @standardnotes/files-server@1.8.12
 - @standardnotes/scheduler-server@1.13.13
 - @standardnotes/syncing-server@1.11.4
 - @standardnotes/websockets-server@1.4.12
 - @standardnotes/workspace-server@1.17.12
2022-11-09 10:20:29 +00:00
Karol Sójko
0f65c051ab feat(analytics): add saving revenue modifications upon subscription refunded 2022-11-09 11:17:27 +01:00
standardci
7b62c7a967 chore(release): publish new version
- @standardnotes/analytics@2.5.0
 - @standardnotes/api-gateway@1.37.3
 - @standardnotes/auth-server@1.57.0
 - @standardnotes/domain-events-infra@1.9.16
 - @standardnotes/domain-events@2.81.0
 - @standardnotes/event-store@1.6.11
 - @standardnotes/files-server@1.8.11
 - @standardnotes/scheduler-server@1.13.12
 - @standardnotes/syncing-server@1.11.3
 - @standardnotes/websockets-server@1.4.11
 - @standardnotes/workspace-server@1.17.11
2022-11-09 10:12:01 +00:00
Karol Sójko
5c3db2cb29 feat(analytics): add saving revenue modifications upon subscription expired 2022-11-09 11:09:49 +01:00
standardci
7008cbd363 chore(release): publish new version
- @standardnotes/analytics@2.4.0
 - @standardnotes/api-gateway@1.37.2
 - @standardnotes/auth-server@1.56.0
 - @standardnotes/domain-events-infra@1.9.15
 - @standardnotes/domain-events@2.80.0
 - @standardnotes/event-store@1.6.10
 - @standardnotes/files-server@1.8.10
 - @standardnotes/scheduler-server@1.13.11
 - @standardnotes/syncing-server@1.11.2
 - @standardnotes/websockets-server@1.4.10
 - @standardnotes/workspace-server@1.17.10
2022-11-09 09:59:41 +00:00
Karol Sójko
cdb7fcf831 feat(analytics): add saving revenue modifications upon subscription renewed 2022-11-09 10:57:43 +01:00
standardci
628aafdd42 chore(release): publish new version
- @standardnotes/analytics@2.3.1
2022-11-09 09:49:22 +00:00
Karol Sójko
9d3ef24ba9 fix(analytics): missing injectable annotation 2022-11-09 10:47:27 +01:00
154 changed files with 2597 additions and 1653 deletions

2
.nvmrc
View File

@@ -1 +1 @@
16.15.1
18.12.1

335
.pnp.cjs generated
View File

@@ -116,15 +116,16 @@ const RAW_RUNTIME_STATE =
["@lerna-lite/cli", "npm:1.6.0"],\
["@lerna-lite/list", "npm:1.6.0"],\
["@lerna-lite/run", "npm:1.6.0"],\
["@sentry/node", "npm:7.5.0"],\
["@newrelic/native-metrics", "npm:9.0.0"],\
["@sentry/node", "npm:7.19.0"],\
["@types/jest", "npm:29.1.1"],\
["@types/newrelic", "npm:7.0.3"],\
["@types/node", "npm:18.0.3"],\
["@types/newrelic", "npm:7.0.4"],\
["@types/node", "npm:18.11.9"],\
["@typescript-eslint/parser", "virtual:8859b278716fedf3e7458b5628625f7e35678c418626878559a0b816445001b7e24c55546f4677ba4c20b521aa0cf52cc33ac07deff171e383ada6eeab69933f#npm:5.40.1"],\
["eslint", "npm:8.19.0"],\
["eslint-config-prettier", "virtual:8859b278716fedf3e7458b5628625f7e35678c418626878559a0b816445001b7e24c55546f4677ba4c20b521aa0cf52cc33ac07deff171e383ada6eeab69933f#npm:8.5.0"],\
["ini", "npm:3.0.0"],\
["newrelic", "npm:9.0.0"],\
["newrelic", "npm:9.6.0"],\
["npm-check-updates", "npm:16.0.1"],\
["prettier", "npm:2.7.1"],\
["ts-node", "virtual:8859b278716fedf3e7458b5628625f7e35678c418626878559a0b816445001b7e24c55546f4677ba4c20b521aa0cf52cc33ac07deff171e383ada6eeab69933f#npm:10.9.1"],\
@@ -1865,12 +1866,12 @@ const RAW_RUNTIME_STATE =
],\
"linkType": "SOFT"\
}],\
["virtual:65e8703d5df08d5ff3f7296fcb759f276254ee430ae6f3cc1f03da392ff63066a3c6c59591c38f36f19d3e877285287a834b5c55e22d764dc2cb0938f7128707#npm:5.0.0", {\
"packageLocation": "./.yarn/__virtual__/@newrelic-aws-sdk-virtual-e9040e4121/0/cache/@newrelic-aws-sdk-npm-5.0.0-7d9d10d58f-ed1dc3fa16.zip/node_modules/@newrelic/aws-sdk/",\
["virtual:f10080c2deb75096716a913b06010dcd94891c77539a757ab32210a1efc3ff91527b36d6c7c46e890db826160e0724553ca23acd0a8a734b5554c9600c71eb52#npm:5.0.0", {\
"packageLocation": "./.yarn/__virtual__/@newrelic-aws-sdk-virtual-ccf1e948b3/0/cache/@newrelic-aws-sdk-npm-5.0.0-7d9d10d58f-ed1dc3fa16.zip/node_modules/@newrelic/aws-sdk/",\
"packageDependencies": [\
["@newrelic/aws-sdk", "virtual:65e8703d5df08d5ff3f7296fcb759f276254ee430ae6f3cc1f03da392ff63066a3c6c59591c38f36f19d3e877285287a834b5c55e22d764dc2cb0938f7128707#npm:5.0.0"],\
["@newrelic/aws-sdk", "virtual:f10080c2deb75096716a913b06010dcd94891c77539a757ab32210a1efc3ff91527b36d6c7c46e890db826160e0724553ca23acd0a8a734b5554c9600c71eb52#npm:5.0.0"],\
["@types/newrelic", null],\
["newrelic", "npm:9.0.0"]\
["newrelic", "npm:9.6.0"]\
],\
"packagePeers": [\
"@types/newrelic",\
@@ -1887,12 +1888,12 @@ const RAW_RUNTIME_STATE =
],\
"linkType": "SOFT"\
}],\
["virtual:65e8703d5df08d5ff3f7296fcb759f276254ee430ae6f3cc1f03da392ff63066a3c6c59591c38f36f19d3e877285287a834b5c55e22d764dc2cb0938f7128707#npm:7.0.0", {\
"packageLocation": "./.yarn/__virtual__/@newrelic-koa-virtual-d6376894e6/0/cache/@newrelic-koa-npm-7.0.0-903c251b9f-0fc2298c8b.zip/node_modules/@newrelic/koa/",\
["virtual:f10080c2deb75096716a913b06010dcd94891c77539a757ab32210a1efc3ff91527b36d6c7c46e890db826160e0724553ca23acd0a8a734b5554c9600c71eb52#npm:7.0.0", {\
"packageLocation": "./.yarn/__virtual__/@newrelic-koa-virtual-613d84b4f1/0/cache/@newrelic-koa-npm-7.0.0-903c251b9f-0fc2298c8b.zip/node_modules/@newrelic/koa/",\
"packageDependencies": [\
["@newrelic/koa", "virtual:65e8703d5df08d5ff3f7296fcb759f276254ee430ae6f3cc1f03da392ff63066a3c6c59591c38f36f19d3e877285287a834b5c55e22d764dc2cb0938f7128707#npm:7.0.0"],\
["@newrelic/koa", "virtual:f10080c2deb75096716a913b06010dcd94891c77539a757ab32210a1efc3ff91527b36d6c7c46e890db826160e0724553ca23acd0a8a734b5554c9600c71eb52#npm:7.0.0"],\
["@types/newrelic", null],\
["newrelic", "npm:9.0.0"]\
["newrelic", "npm:9.6.0"]\
],\
"packagePeers": [\
"@types/newrelic",\
@@ -1922,12 +1923,12 @@ const RAW_RUNTIME_STATE =
],\
"linkType": "SOFT"\
}],\
["virtual:65e8703d5df08d5ff3f7296fcb759f276254ee430ae6f3cc1f03da392ff63066a3c6c59591c38f36f19d3e877285287a834b5c55e22d764dc2cb0938f7128707#npm:6.0.0", {\
"packageLocation": "./.yarn/__virtual__/@newrelic-superagent-virtual-c2a5d7b8a8/0/cache/@newrelic-superagent-npm-6.0.0-db8b77d0f3-b77997b792.zip/node_modules/@newrelic/superagent/",\
["virtual:f10080c2deb75096716a913b06010dcd94891c77539a757ab32210a1efc3ff91527b36d6c7c46e890db826160e0724553ca23acd0a8a734b5554c9600c71eb52#npm:6.0.0", {\
"packageLocation": "./.yarn/__virtual__/@newrelic-superagent-virtual-37eb7b41a0/0/cache/@newrelic-superagent-npm-6.0.0-db8b77d0f3-b77997b792.zip/node_modules/@newrelic/superagent/",\
"packageDependencies": [\
["@newrelic/superagent", "virtual:65e8703d5df08d5ff3f7296fcb759f276254ee430ae6f3cc1f03da392ff63066a3c6c59591c38f36f19d3e877285287a834b5c55e22d764dc2cb0938f7128707#npm:6.0.0"],\
["@newrelic/superagent", "virtual:f10080c2deb75096716a913b06010dcd94891c77539a757ab32210a1efc3ff91527b36d6c7c46e890db826160e0724553ca23acd0a8a734b5554c9600c71eb52#npm:6.0.0"],\
["@types/newrelic", null],\
["newrelic", "npm:9.0.0"]\
["newrelic", "npm:9.6.0"]\
],\
"packagePeers": [\
"@types/newrelic",\
@@ -1948,8 +1949,8 @@ const RAW_RUNTIME_STATE =
"packageLocation": "./.yarn/__virtual__/@newrelic-winston-enricher-virtual-6b8c53ab3d/0/cache/@newrelic-winston-enricher-npm-4.0.0-ebaf2d0d28-3fc901cded.zip/node_modules/@newrelic/winston-enricher/",\
"packageDependencies": [\
["@newrelic/winston-enricher", "virtual:c66bf20e88479ada0172094776519a9f51acc4731d22079b60a295bcec7ea42d5545cbce58a77a50d932bf953298799135e99707486e343da6d99ba1d167bdbd#npm:4.0.0"],\
["@types/newrelic", "npm:7.0.3"],\
["newrelic", "npm:9.0.0"]\
["@types/newrelic", "npm:7.0.4"],\
["newrelic", "npm:9.6.0"]\
],\
"packagePeers": [\
"@types/newrelic",\
@@ -2428,39 +2429,25 @@ const RAW_RUNTIME_STATE =
}]\
]],\
["@sentry/core", [\
["npm:7.5.0", {\
"packageLocation": "./.yarn/cache/@sentry-core-npm-7.5.0-984c871a50-99c8e93a6f.zip/node_modules/@sentry/core/",\
["npm:7.19.0", {\
"packageLocation": "./.yarn/cache/@sentry-core-npm-7.19.0-151e6173ac-cabd7852ff.zip/node_modules/@sentry/core/",\
"packageDependencies": [\
["@sentry/core", "npm:7.5.0"],\
["@sentry/hub", "npm:7.5.0"],\
["@sentry/types", "npm:7.5.0"],\
["@sentry/utils", "npm:7.5.0"],\
["tslib", "npm:1.14.1"]\
],\
"linkType": "HARD"\
}]\
]],\
["@sentry/hub", [\
["npm:7.5.0", {\
"packageLocation": "./.yarn/cache/@sentry-hub-npm-7.5.0-993573a68c-27e240423e.zip/node_modules/@sentry/hub/",\
"packageDependencies": [\
["@sentry/hub", "npm:7.5.0"],\
["@sentry/types", "npm:7.5.0"],\
["@sentry/utils", "npm:7.5.0"],\
["@sentry/core", "npm:7.19.0"],\
["@sentry/types", "npm:7.19.0"],\
["@sentry/utils", "npm:7.19.0"],\
["tslib", "npm:1.14.1"]\
],\
"linkType": "HARD"\
}]\
]],\
["@sentry/node", [\
["npm:7.5.0", {\
"packageLocation": "./.yarn/cache/@sentry-node-npm-7.5.0-a14989f161-9b65bc44d2.zip/node_modules/@sentry/node/",\
["npm:7.19.0", {\
"packageLocation": "./.yarn/cache/@sentry-node-npm-7.19.0-fd3d8dbde1-3a69647d2e.zip/node_modules/@sentry/node/",\
"packageDependencies": [\
["@sentry/node", "npm:7.5.0"],\
["@sentry/core", "npm:7.5.0"],\
["@sentry/hub", "npm:7.5.0"],\
["@sentry/types", "npm:7.5.0"],\
["@sentry/utils", "npm:7.5.0"],\
["@sentry/node", "npm:7.19.0"],\
["@sentry/core", "npm:7.19.0"],\
["@sentry/types", "npm:7.19.0"],\
["@sentry/utils", "npm:7.19.0"],\
["cookie", "npm:0.4.2"],\
["https-proxy-agent", "npm:5.0.1"],\
["lru_map", "npm:0.3.3"],\
@@ -2470,20 +2457,20 @@ const RAW_RUNTIME_STATE =
}]\
]],\
["@sentry/types", [\
["npm:7.5.0", {\
"packageLocation": "./.yarn/cache/@sentry-types-npm-7.5.0-eea3d326fa-8029b56bae.zip/node_modules/@sentry/types/",\
["npm:7.19.0", {\
"packageLocation": "./.yarn/cache/@sentry-types-npm-7.19.0-d6ed1960f2-541e1ef49a.zip/node_modules/@sentry/types/",\
"packageDependencies": [\
["@sentry/types", "npm:7.5.0"]\
["@sentry/types", "npm:7.19.0"]\
],\
"linkType": "HARD"\
}]\
]],\
["@sentry/utils", [\
["npm:7.5.0", {\
"packageLocation": "./.yarn/cache/@sentry-utils-npm-7.5.0-e8c66594bc-f5045667ea.zip/node_modules/@sentry/utils/",\
["npm:7.19.0", {\
"packageLocation": "./.yarn/cache/@sentry-utils-npm-7.19.0-79844d4d90-50e4f391fe.zip/node_modules/@sentry/utils/",\
"packageDependencies": [\
["@sentry/utils", "npm:7.5.0"],\
["@sentry/types", "npm:7.5.0"],\
["@sentry/utils", "npm:7.19.0"],\
["@sentry/types", "npm:7.19.0"],\
["tslib", "npm:1.14.1"]\
],\
"linkType": "HARD"\
@@ -2541,28 +2528,29 @@ const RAW_RUNTIME_STATE =
"packageLocation": "./packages/analytics/",\
"packageDependencies": [\
["@standardnotes/analytics", "workspace:packages/analytics"],\
["@newrelic/native-metrics", "npm:9.0.0"],\
["@newrelic/winston-enricher", "virtual:c66bf20e88479ada0172094776519a9f51acc4731d22079b60a295bcec7ea42d5545cbce58a77a50d932bf953298799135e99707486e343da6d99ba1d167bdbd#npm:4.0.0"],\
["@sentry/node", "npm:7.5.0"],\
["@sentry/node", "npm:7.19.0"],\
["@standardnotes/common", "workspace:packages/common"],\
["@standardnotes/domain-events", "workspace:packages/domain-events"],\
["@standardnotes/domain-events-infra", "workspace:packages/domain-events-infra"],\
["@standardnotes/time", "workspace:packages/time"],\
["@types/ioredis", "npm:4.28.10"],\
["@types/ioredis", "npm:5.0.0"],\
["@types/jest", "npm:29.1.1"],\
["@types/newrelic", "npm:7.0.3"],\
["@types/node", "npm:18.0.3"],\
["@types/newrelic", "npm:7.0.4"],\
["@types/node", "npm:18.11.9"],\
["@types/uuid", "npm:8.3.4"],\
["@typescript-eslint/eslint-plugin", "virtual:c66bf20e88479ada0172094776519a9f51acc4731d22079b60a295bcec7ea42d5545cbce58a77a50d932bf953298799135e99707486e343da6d99ba1d167bdbd#npm:5.30.5"],\
["aws-sdk", "npm:2.1234.0"],\
["aws-sdk", "npm:2.1253.0"],\
["dayjs", "npm:1.11.6"],\
["dotenv", "npm:16.0.1"],\
["eslint", "npm:8.25.0"],\
["eslint-plugin-prettier", "virtual:c66bf20e88479ada0172094776519a9f51acc4731d22079b60a295bcec7ea42d5545cbce58a77a50d932bf953298799135e99707486e343da6d99ba1d167bdbd#npm:4.2.1"],\
["inversify", "npm:6.0.1"],\
["ioredis", "npm:5.2.3"],\
["ioredis", "npm:5.2.4"],\
["jest", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:29.1.2"],\
["mysql2", "npm:2.3.3"],\
["newrelic", "npm:9.0.0"],\
["newrelic", "npm:9.6.0"],\
["reflect-metadata", "npm:0.1.13"],\
["shallow-equal-object", "npm:1.1.1"],\
["ts-jest", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:29.0.3"],\
@@ -2595,8 +2583,9 @@ const RAW_RUNTIME_STATE =
"packageLocation": "./packages/api-gateway/",\
"packageDependencies": [\
["@standardnotes/api-gateway", "workspace:packages/api-gateway"],\
["@newrelic/native-metrics", "npm:9.0.0"],\
["@newrelic/winston-enricher", "virtual:c66bf20e88479ada0172094776519a9f51acc4731d22079b60a295bcec7ea42d5545cbce58a77a50d932bf953298799135e99707486e343da6d99ba1d167bdbd#npm:4.0.0"],\
["@sentry/node", "npm:7.5.0"],\
["@sentry/node", "npm:7.19.0"],\
["@standardnotes/common", "workspace:packages/common"],\
["@standardnotes/domain-events", "workspace:packages/domain-events"],\
["@standardnotes/domain-events-infra", "workspace:packages/domain-events-infra"],\
@@ -2604,14 +2593,14 @@ const RAW_RUNTIME_STATE =
["@standardnotes/time", "workspace:packages/time"],\
["@types/cors", "npm:2.8.12"],\
["@types/express", "npm:4.17.14"],\
["@types/ioredis", "npm:4.28.10"],\
["@types/ioredis", "npm:5.0.0"],\
["@types/jest", "npm:29.1.1"],\
["@types/jsonwebtoken", "npm:8.5.9"],\
["@types/newrelic", "npm:7.0.3"],\
["@types/newrelic", "npm:7.0.4"],\
["@types/prettyjson", "npm:0.0.30"],\
["@typescript-eslint/eslint-plugin", "virtual:04783e12400851b8a3d76e71495851cc94959db6e62f04cb0a31190080629440b182d8c8eb4d7f2b04e281912f2783a5fd4d2c3c6ab68d38b7097246c93f4c19#npm:5.40.1"],\
["aws-sdk", "npm:2.1234.0"],\
["axios", "npm:0.27.2"],\
["aws-sdk", "npm:2.1253.0"],\
["axios", "npm:1.1.3"],\
["cors", "npm:2.8.5"],\
["dotenv", "npm:16.0.1"],\
["eslint", "npm:8.25.0"],\
@@ -2620,10 +2609,10 @@ const RAW_RUNTIME_STATE =
["helmet", "npm:6.0.0"],\
["inversify", "npm:6.0.1"],\
["inversify-express-utils", "npm:6.4.3"],\
["ioredis", "npm:5.2.3"],\
["ioredis", "npm:5.2.4"],\
["jest", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:29.1.2"],\
["jsonwebtoken", "npm:8.5.1"],\
["newrelic", "npm:9.0.0"],\
["newrelic", "npm:9.6.0"],\
["nodemon", "npm:2.0.20"],\
["npm-check-updates", "npm:16.0.1"],\
["prettyjson", "npm:1.2.5"],\
@@ -2651,8 +2640,9 @@ const RAW_RUNTIME_STATE =
"packageLocation": "./packages/auth/",\
"packageDependencies": [\
["@standardnotes/auth-server", "workspace:packages/auth"],\
["@newrelic/native-metrics", "npm:9.0.0"],\
["@newrelic/winston-enricher", "virtual:c66bf20e88479ada0172094776519a9f51acc4731d22079b60a295bcec7ea42d5545cbce58a77a50d932bf953298799135e99707486e343da6d99ba1d167bdbd#npm:4.0.0"],\
["@sentry/node", "npm:7.5.0"],\
["@sentry/node", "npm:7.19.0"],\
["@standardnotes/api", "npm:1.19.0"],\
["@standardnotes/common", "workspace:packages/common"],\
["@standardnotes/domain-events", "workspace:packages/domain-events"],\
@@ -2668,16 +2658,16 @@ const RAW_RUNTIME_STATE =
["@types/bcryptjs", "npm:2.4.2"],\
["@types/cors", "npm:2.8.12"],\
["@types/express", "npm:4.17.14"],\
["@types/ioredis", "npm:4.28.10"],\
["@types/ioredis", "npm:5.0.0"],\
["@types/jest", "npm:29.1.1"],\
["@types/newrelic", "npm:7.0.3"],\
["@types/newrelic", "npm:7.0.4"],\
["@types/otplib", "npm:10.0.0"],\
["@types/prettyjson", "npm:0.0.30"],\
["@types/ua-parser-js", "npm:0.7.36"],\
["@types/uuid", "npm:8.3.4"],\
["@typescript-eslint/eslint-plugin", "virtual:04783e12400851b8a3d76e71495851cc94959db6e62f04cb0a31190080629440b182d8c8eb4d7f2b04e281912f2783a5fd4d2c3c6ab68d38b7097246c93f4c19#npm:5.40.1"],\
["aws-sdk", "npm:2.1234.0"],\
["axios", "npm:0.27.2"],\
["aws-sdk", "npm:2.1253.0"],\
["axios", "npm:1.1.3"],\
["bcryptjs", "npm:2.4.3"],\
["cors", "npm:2.8.5"],\
["dayjs", "npm:1.11.6"],\
@@ -2687,10 +2677,10 @@ const RAW_RUNTIME_STATE =
["express", "npm:4.18.2"],\
["inversify", "npm:6.0.1"],\
["inversify-express-utils", "npm:6.4.3"],\
["ioredis", "npm:5.2.3"],\
["ioredis", "npm:5.2.4"],\
["jest", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:29.1.2"],\
["mysql2", "npm:2.3.3"],\
["newrelic", "npm:9.0.0"],\
["newrelic", "npm:9.6.0"],\
["nodemon", "npm:2.0.20"],\
["npm-check-updates", "npm:16.0.1"],\
["otplib", "npm:12.0.1"],\
@@ -2699,7 +2689,7 @@ const RAW_RUNTIME_STATE =
["ts-jest", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:29.0.3"],\
["typeorm", "virtual:c66bf20e88479ada0172094776519a9f51acc4731d22079b60a295bcec7ea42d5545cbce58a77a50d932bf953298799135e99707486e343da6d99ba1d167bdbd#npm:0.3.10"],\
["typescript", "patch:typescript@npm%3A4.8.4#optional!builtin<compat/typescript>::version=4.8.4&hash=701156"],\
["ua-parser-js", "npm:1.0.2"],\
["ua-parser-js", "npm:1.0.32"],\
["uuid", "npm:9.0.0"],\
["winston", "npm:3.8.2"]\
],\
@@ -2711,8 +2701,9 @@ const RAW_RUNTIME_STATE =
"packageLocation": "./packages/common/",\
"packageDependencies": [\
["@standardnotes/common", "workspace:packages/common"],\
["@newrelic/native-metrics", "npm:9.0.0"],\
["@types/jest", "npm:29.1.1"],\
["@types/node", "npm:18.0.3"],\
["@types/node", "npm:18.11.9"],\
["@typescript-eslint/eslint-plugin", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:5.30.5"],\
["eslint-plugin-prettier", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:4.2.1"],\
["jest", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:29.1.2"],\
@@ -2742,6 +2733,7 @@ const RAW_RUNTIME_STATE =
"packageLocation": "./packages/domain-events/",\
"packageDependencies": [\
["@standardnotes/domain-events", "workspace:packages/domain-events"],\
["@newrelic/native-metrics", "npm:9.0.0"],\
["@standardnotes/common", "workspace:packages/common"],\
["@standardnotes/features", "npm:1.53.1"],\
["@standardnotes/predicates", "workspace:packages/predicates"],\
@@ -2762,16 +2754,17 @@ const RAW_RUNTIME_STATE =
"packageLocation": "./packages/domain-events-infra/",\
"packageDependencies": [\
["@standardnotes/domain-events-infra", "workspace:packages/domain-events-infra"],\
["@newrelic/native-metrics", "npm:9.0.0"],\
["@standardnotes/domain-events", "workspace:packages/domain-events"],\
["@types/ioredis", "npm:4.28.10"],\
["@types/ioredis", "npm:5.0.0"],\
["@types/jest", "npm:29.1.1"],\
["@types/newrelic", "npm:7.0.3"],\
["@types/newrelic", "npm:7.0.4"],\
["@typescript-eslint/eslint-plugin", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:5.30.5"],\
["aws-sdk", "npm:2.1234.0"],\
["aws-sdk", "npm:2.1253.0"],\
["eslint-plugin-prettier", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:4.2.1"],\
["ioredis", "npm:5.2.3"],\
["ioredis", "npm:5.2.4"],\
["jest", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:29.1.2"],\
["newrelic", "npm:9.0.0"],\
["newrelic", "npm:9.6.0"],\
["reflect-metadata", "npm:0.1.13"],\
["sqs-consumer", "virtual:685a6222c3349423674bb7f0684ba34e2ab20912010f352e04dcf707a156e13183fc382e2417cb37a60f3e7b52fd0178c53181674890e1773eb83e190dc13378#npm:5.7.0"],\
["ts-jest", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:29.0.3"],\
@@ -2801,23 +2794,24 @@ const RAW_RUNTIME_STATE =
"packageLocation": "./packages/event-store/",\
"packageDependencies": [\
["@standardnotes/event-store", "workspace:packages/event-store"],\
["@newrelic/native-metrics", "npm:9.0.0"],\
["@standardnotes/domain-events", "workspace:packages/domain-events"],\
["@standardnotes/domain-events-infra", "workspace:packages/domain-events-infra"],\
["@standardnotes/time", "workspace:packages/time"],\
["@types/ioredis", "npm:4.28.10"],\
["@types/ioredis", "npm:5.0.0"],\
["@types/jest", "npm:29.1.1"],\
["@types/newrelic", "npm:7.0.3"],\
["@types/newrelic", "npm:7.0.4"],\
["@types/nodemailer", "npm:6.4.6"],\
["@typescript-eslint/eslint-plugin", "virtual:04783e12400851b8a3d76e71495851cc94959db6e62f04cb0a31190080629440b182d8c8eb4d7f2b04e281912f2783a5fd4d2c3c6ab68d38b7097246c93f4c19#npm:5.40.1"],\
["aws-sdk", "npm:2.1234.0"],\
["aws-sdk", "npm:2.1253.0"],\
["dotenv", "npm:16.0.1"],\
["eslint", "npm:8.25.0"],\
["eslint-plugin-prettier", "virtual:c66bf20e88479ada0172094776519a9f51acc4731d22079b60a295bcec7ea42d5545cbce58a77a50d932bf953298799135e99707486e343da6d99ba1d167bdbd#npm:4.2.1"],\
["inversify", "npm:6.0.1"],\
["ioredis", "npm:5.2.3"],\
["ioredis", "npm:5.2.4"],\
["jest", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:29.1.2"],\
["mysql2", "npm:2.3.3"],\
["newrelic", "npm:9.0.0"],\
["newrelic", "npm:9.6.0"],\
["reflect-metadata", "npm:0.1.13"],\
["ts-jest", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:29.0.3"],\
["typeorm", "virtual:c66bf20e88479ada0172094776519a9f51acc4731d22079b60a295bcec7ea42d5545cbce58a77a50d932bf953298799135e99707486e343da6d99ba1d167bdbd#npm:0.3.10"],\
@@ -2856,7 +2850,8 @@ const RAW_RUNTIME_STATE =
"packageLocation": "./packages/files/",\
"packageDependencies": [\
["@standardnotes/files-server", "workspace:packages/files"],\
["@sentry/node", "npm:7.5.0"],\
["@newrelic/native-metrics", "npm:9.0.0"],\
["@sentry/node", "npm:7.19.0"],\
["@standardnotes/common", "workspace:packages/common"],\
["@standardnotes/config", "npm:2.4.3"],\
["@standardnotes/domain-events", "workspace:packages/domain-events"],\
@@ -2868,14 +2863,14 @@ const RAW_RUNTIME_STATE =
["@types/connect-busboy", "npm:1.0.0"],\
["@types/cors", "npm:2.8.12"],\
["@types/express", "npm:4.17.14"],\
["@types/ioredis", "npm:4.28.10"],\
["@types/ioredis", "npm:5.0.0"],\
["@types/jest", "npm:29.1.1"],\
["@types/jsonwebtoken", "npm:8.5.9"],\
["@types/newrelic", "npm:7.0.3"],\
["@types/newrelic", "npm:7.0.4"],\
["@types/prettyjson", "npm:0.0.30"],\
["@types/uuid", "npm:8.3.4"],\
["@typescript-eslint/eslint-plugin", "virtual:04783e12400851b8a3d76e71495851cc94959db6e62f04cb0a31190080629440b182d8c8eb4d7f2b04e281912f2783a5fd4d2c3c6ab68d38b7097246c93f4c19#npm:5.40.1"],\
["aws-sdk", "npm:2.1234.0"],\
["aws-sdk", "npm:2.1253.0"],\
["connect-busboy", "npm:1.0.0"],\
["cors", "npm:2.8.5"],\
["dayjs", "npm:1.11.6"],\
@@ -2887,10 +2882,10 @@ const RAW_RUNTIME_STATE =
["helmet", "npm:6.0.0"],\
["inversify", "npm:6.0.1"],\
["inversify-express-utils", "npm:6.4.3"],\
["ioredis", "npm:5.2.3"],\
["ioredis", "npm:5.2.4"],\
["jest", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:29.1.2"],\
["jsonwebtoken", "npm:8.5.1"],\
["newrelic", "npm:9.0.0"],\
["newrelic", "npm:9.6.0"],\
["nodemon", "npm:2.0.20"],\
["npm-check-updates", "npm:16.0.1"],\
["prettyjson", "npm:1.2.5"],\
@@ -2949,6 +2944,7 @@ const RAW_RUNTIME_STATE =
"packageLocation": "./packages/predicates/",\
"packageDependencies": [\
["@standardnotes/predicates", "workspace:packages/predicates"],\
["@newrelic/native-metrics", "npm:9.0.0"],\
["@standardnotes/common", "workspace:packages/common"],\
["@types/jest", "npm:29.1.1"],\
["@typescript-eslint/eslint-plugin", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:5.30.5"],\
@@ -2990,28 +2986,29 @@ const RAW_RUNTIME_STATE =
"packageLocation": "./packages/scheduler/",\
"packageDependencies": [\
["@standardnotes/scheduler-server", "workspace:packages/scheduler"],\
["@newrelic/native-metrics", "npm:9.0.0"],\
["@newrelic/winston-enricher", "virtual:c66bf20e88479ada0172094776519a9f51acc4731d22079b60a295bcec7ea42d5545cbce58a77a50d932bf953298799135e99707486e343da6d99ba1d167bdbd#npm:4.0.0"],\
["@sentry/node", "npm:7.5.0"],\
["@sentry/node", "npm:7.19.0"],\
["@standardnotes/common", "workspace:packages/common"],\
["@standardnotes/domain-events", "workspace:packages/domain-events"],\
["@standardnotes/domain-events-infra", "workspace:packages/domain-events-infra"],\
["@standardnotes/predicates", "workspace:packages/predicates"],\
["@standardnotes/time", "workspace:packages/time"],\
["@types/ioredis", "npm:4.28.10"],\
["@types/ioredis", "npm:5.0.0"],\
["@types/jest", "npm:29.1.1"],\
["@types/newrelic", "npm:7.0.3"],\
["@types/node", "npm:18.0.3"],\
["@types/newrelic", "npm:7.0.4"],\
["@types/node", "npm:18.11.9"],\
["@typescript-eslint/eslint-plugin", "virtual:04783e12400851b8a3d76e71495851cc94959db6e62f04cb0a31190080629440b182d8c8eb4d7f2b04e281912f2783a5fd4d2c3c6ab68d38b7097246c93f4c19#npm:5.40.1"],\
["aws-sdk", "npm:2.1234.0"],\
["aws-sdk", "npm:2.1253.0"],\
["dayjs", "npm:1.11.6"],\
["dotenv", "npm:16.0.1"],\
["eslint", "npm:8.25.0"],\
["eslint-plugin-prettier", "virtual:c66bf20e88479ada0172094776519a9f51acc4731d22079b60a295bcec7ea42d5545cbce58a77a50d932bf953298799135e99707486e343da6d99ba1d167bdbd#npm:4.2.1"],\
["inversify", "npm:6.0.1"],\
["ioredis", "npm:5.2.3"],\
["ioredis", "npm:5.2.4"],\
["jest", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:29.1.2"],\
["mysql2", "npm:2.3.3"],\
["newrelic", "npm:9.0.0"],\
["newrelic", "npm:9.6.0"],\
["npm-check-updates", "npm:16.0.1"],\
["reflect-metadata", "npm:0.1.13"],\
["ts-jest", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:29.0.3"],\
@@ -3027,6 +3024,7 @@ const RAW_RUNTIME_STATE =
"packageLocation": "./packages/security/",\
"packageDependencies": [\
["@standardnotes/security", "workspace:packages/security"],\
["@newrelic/native-metrics", "npm:9.0.0"],\
["@standardnotes/common", "workspace:packages/common"],\
["@types/jest", "npm:29.1.1"],\
["@types/jsonwebtoken", "npm:8.5.9"],\
@@ -3051,15 +3049,16 @@ const RAW_RUNTIME_STATE =
["@lerna-lite/cli", "npm:1.6.0"],\
["@lerna-lite/list", "npm:1.6.0"],\
["@lerna-lite/run", "npm:1.6.0"],\
["@sentry/node", "npm:7.5.0"],\
["@newrelic/native-metrics", "npm:9.0.0"],\
["@sentry/node", "npm:7.19.0"],\
["@types/jest", "npm:29.1.1"],\
["@types/newrelic", "npm:7.0.3"],\
["@types/node", "npm:18.0.3"],\
["@types/newrelic", "npm:7.0.4"],\
["@types/node", "npm:18.11.9"],\
["@typescript-eslint/parser", "virtual:8859b278716fedf3e7458b5628625f7e35678c418626878559a0b816445001b7e24c55546f4677ba4c20b521aa0cf52cc33ac07deff171e383ada6eeab69933f#npm:5.40.1"],\
["eslint", "npm:8.19.0"],\
["eslint-config-prettier", "virtual:8859b278716fedf3e7458b5628625f7e35678c418626878559a0b816445001b7e24c55546f4677ba4c20b521aa0cf52cc33ac07deff171e383ada6eeab69933f#npm:8.5.0"],\
["ini", "npm:3.0.0"],\
["newrelic", "npm:9.0.0"],\
["newrelic", "npm:9.6.0"],\
["npm-check-updates", "npm:16.0.1"],\
["prettier", "npm:2.7.1"],\
["ts-node", "virtual:8859b278716fedf3e7458b5628625f7e35678c418626878559a0b816445001b7e24c55546f4677ba4c20b521aa0cf52cc33ac07deff171e383ada6eeab69933f#npm:10.9.1"],\
@@ -3073,6 +3072,7 @@ const RAW_RUNTIME_STATE =
"packageLocation": "./packages/settings/",\
"packageDependencies": [\
["@standardnotes/settings", "workspace:packages/settings"],\
["@newrelic/native-metrics", "npm:9.0.0"],\
["@typescript-eslint/eslint-plugin", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:5.30.5"],\
["eslint-plugin-prettier", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:4.2.1"],\
["reflect-metadata", "npm:0.1.13"],\
@@ -3096,9 +3096,10 @@ const RAW_RUNTIME_STATE =
"packageLocation": "./packages/sncrypto-node/",\
"packageDependencies": [\
["@standardnotes/sncrypto-node", "workspace:packages/sncrypto-node"],\
["@newrelic/native-metrics", "npm:9.0.0"],\
["@standardnotes/sncrypto-common", "npm:1.13.0"],\
["@types/jest", "npm:29.1.1"],\
["@types/node", "npm:18.0.3"],\
["@types/node", "npm:18.11.9"],\
["@typescript-eslint/eslint-plugin", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:5.30.5"],\
["eslint-plugin-prettier", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:4.2.1"],\
["jest", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:29.1.2"],\
@@ -3116,8 +3117,9 @@ const RAW_RUNTIME_STATE =
"packageLocation": "./packages/syncing-server/",\
"packageDependencies": [\
["@standardnotes/syncing-server", "workspace:packages/syncing-server"],\
["@newrelic/native-metrics", "npm:9.0.0"],\
["@newrelic/winston-enricher", "virtual:c66bf20e88479ada0172094776519a9f51acc4731d22079b60a295bcec7ea42d5545cbce58a77a50d932bf953298799135e99707486e343da6d99ba1d167bdbd#npm:4.0.0"],\
["@sentry/node", "npm:7.5.0"],\
["@sentry/node", "npm:7.19.0"],\
["@standardnotes/common", "workspace:packages/common"],\
["@standardnotes/domain-events", "workspace:packages/domain-events"],\
["@standardnotes/domain-events-infra", "workspace:packages/domain-events-infra"],\
@@ -3130,16 +3132,16 @@ const RAW_RUNTIME_STATE =
["@types/dotenv", "npm:8.2.0"],\
["@types/express", "npm:4.17.14"],\
["@types/inversify-express-utils", "npm:2.0.0"],\
["@types/ioredis", "npm:4.28.10"],\
["@types/ioredis", "npm:5.0.0"],\
["@types/jest", "npm:29.1.1"],\
["@types/jsonwebtoken", "npm:8.5.9"],\
["@types/newrelic", "npm:7.0.3"],\
["@types/newrelic", "npm:7.0.4"],\
["@types/prettyjson", "npm:0.0.30"],\
["@types/ua-parser-js", "npm:0.7.36"],\
["@types/uuid", "npm:8.3.4"],\
["@typescript-eslint/eslint-plugin", "virtual:04783e12400851b8a3d76e71495851cc94959db6e62f04cb0a31190080629440b182d8c8eb4d7f2b04e281912f2783a5fd4d2c3c6ab68d38b7097246c93f4c19#npm:5.40.1"],\
["aws-sdk", "npm:2.1234.0"],\
["axios", "npm:0.27.2"],\
["aws-sdk", "npm:2.1253.0"],\
["axios", "npm:1.1.3"],\
["cors", "npm:2.8.5"],\
["dotenv", "npm:16.0.1"],\
["eslint", "npm:8.25.0"],\
@@ -3148,11 +3150,11 @@ const RAW_RUNTIME_STATE =
["helmet", "npm:6.0.0"],\
["inversify", "npm:6.0.1"],\
["inversify-express-utils", "npm:6.4.3"],\
["ioredis", "npm:5.2.3"],\
["ioredis", "npm:5.2.4"],\
["jest", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:29.1.2"],\
["jsonwebtoken", "npm:8.5.1"],\
["mysql2", "npm:2.3.3"],\
["newrelic", "npm:9.0.0"],\
["newrelic", "npm:9.6.0"],\
["nodemon", "npm:2.0.20"],\
["npm-check-updates", "npm:16.0.1"],\
["prettyjson", "npm:1.2.5"],\
@@ -3160,7 +3162,7 @@ const RAW_RUNTIME_STATE =
["ts-jest", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:29.0.3"],\
["typeorm", "virtual:c66bf20e88479ada0172094776519a9f51acc4731d22079b60a295bcec7ea42d5545cbce58a77a50d932bf953298799135e99707486e343da6d99ba1d167bdbd#npm:0.3.10"],\
["typescript", "patch:typescript@npm%3A4.8.4#optional!builtin<compat/typescript>::version=4.8.4&hash=701156"],\
["ua-parser-js", "npm:1.0.2"],\
["ua-parser-js", "npm:1.0.32"],\
["uuid", "npm:9.0.0"],\
["winston", "npm:3.8.2"]\
],\
@@ -3172,6 +3174,7 @@ const RAW_RUNTIME_STATE =
"packageLocation": "./packages/time/",\
"packageDependencies": [\
["@standardnotes/time", "workspace:packages/time"],\
["@newrelic/native-metrics", "npm:9.0.0"],\
["@types/jest", "npm:29.1.1"],\
["@types/microtime", "npm:2.1.0"],\
["@typescript-eslint/eslint-plugin", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:5.30.5"],\
@@ -3215,8 +3218,9 @@ const RAW_RUNTIME_STATE =
"packageLocation": "./packages/websockets/",\
"packageDependencies": [\
["@standardnotes/websockets-server", "workspace:packages/websockets"],\
["@newrelic/native-metrics", "npm:9.0.0"],\
["@newrelic/winston-enricher", "virtual:c66bf20e88479ada0172094776519a9f51acc4731d22079b60a295bcec7ea42d5545cbce58a77a50d932bf953298799135e99707486e343da6d99ba1d167bdbd#npm:4.0.0"],\
["@sentry/node", "npm:7.5.0"],\
["@sentry/node", "npm:7.19.0"],\
["@standardnotes/api", "npm:1.19.0"],\
["@standardnotes/common", "workspace:packages/common"],\
["@standardnotes/domain-events", "workspace:packages/domain-events"],\
@@ -3224,12 +3228,12 @@ const RAW_RUNTIME_STATE =
["@standardnotes/security", "workspace:packages/security"],\
["@types/cors", "npm:2.8.12"],\
["@types/express", "npm:4.17.14"],\
["@types/ioredis", "npm:4.28.10"],\
["@types/ioredis", "npm:5.0.0"],\
["@types/jest", "npm:29.1.1"],\
["@types/newrelic", "npm:7.0.3"],\
["@types/newrelic", "npm:7.0.4"],\
["@typescript-eslint/eslint-plugin", "virtual:04783e12400851b8a3d76e71495851cc94959db6e62f04cb0a31190080629440b182d8c8eb4d7f2b04e281912f2783a5fd4d2c3c6ab68d38b7097246c93f4c19#npm:5.40.1"],\
["aws-sdk", "npm:2.1234.0"],\
["axios", "npm:0.27.2"],\
["aws-sdk", "npm:2.1253.0"],\
["axios", "npm:1.1.3"],\
["cors", "npm:2.8.5"],\
["dotenv", "npm:16.0.1"],\
["eslint", "npm:8.25.0"],\
@@ -3237,10 +3241,10 @@ const RAW_RUNTIME_STATE =
["express", "npm:4.18.2"],\
["inversify", "npm:6.0.1"],\
["inversify-express-utils", "npm:6.4.3"],\
["ioredis", "npm:5.2.3"],\
["ioredis", "npm:5.2.4"],\
["jest", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:29.1.2"],\
["mysql2", "npm:2.3.3"],\
["newrelic", "npm:9.0.0"],\
["newrelic", "npm:9.6.0"],\
["reflect-metadata", "npm:0.1.13"],\
["ts-jest", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:29.0.3"],\
["typeorm", "virtual:c66bf20e88479ada0172094776519a9f51acc4731d22079b60a295bcec7ea42d5545cbce58a77a50d932bf953298799135e99707486e343da6d99ba1d167bdbd#npm:0.3.10"],\
@@ -3255,8 +3259,9 @@ const RAW_RUNTIME_STATE =
"packageLocation": "./packages/workspace/",\
"packageDependencies": [\
["@standardnotes/workspace-server", "workspace:packages/workspace"],\
["@newrelic/native-metrics", "npm:9.0.0"],\
["@newrelic/winston-enricher", "virtual:c66bf20e88479ada0172094776519a9f51acc4731d22079b60a295bcec7ea42d5545cbce58a77a50d932bf953298799135e99707486e343da6d99ba1d167bdbd#npm:4.0.0"],\
["@sentry/node", "npm:7.5.0"],\
["@sentry/node", "npm:7.19.0"],\
["@standardnotes/api", "npm:1.19.0"],\
["@standardnotes/common", "workspace:packages/common"],\
["@standardnotes/domain-events", "workspace:packages/domain-events"],\
@@ -3266,11 +3271,11 @@ const RAW_RUNTIME_STATE =
["@standardnotes/time", "workspace:packages/time"],\
["@types/cors", "npm:2.8.12"],\
["@types/express", "npm:4.17.14"],\
["@types/ioredis", "npm:4.28.10"],\
["@types/ioredis", "npm:5.0.0"],\
["@types/jest", "npm:29.1.1"],\
["@types/newrelic", "npm:7.0.3"],\
["@types/newrelic", "npm:7.0.4"],\
["@typescript-eslint/eslint-plugin", "virtual:04783e12400851b8a3d76e71495851cc94959db6e62f04cb0a31190080629440b182d8c8eb4d7f2b04e281912f2783a5fd4d2c3c6ab68d38b7097246c93f4c19#npm:5.40.1"],\
["aws-sdk", "npm:2.1234.0"],\
["aws-sdk", "npm:2.1253.0"],\
["cors", "npm:2.8.5"],\
["dotenv", "npm:16.0.1"],\
["eslint", "npm:8.25.0"],\
@@ -3278,10 +3283,10 @@ const RAW_RUNTIME_STATE =
["express", "npm:4.18.2"],\
["inversify", "npm:6.0.1"],\
["inversify-express-utils", "npm:6.4.3"],\
["ioredis", "npm:5.2.3"],\
["ioredis", "npm:5.2.4"],\
["jest", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:29.1.2"],\
["mysql2", "npm:2.3.3"],\
["newrelic", "npm:9.0.0"],\
["newrelic", "npm:9.6.0"],\
["reflect-metadata", "npm:0.1.13"],\
["ts-jest", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:29.0.3"],\
["typeorm", "virtual:c66bf20e88479ada0172094776519a9f51acc4731d22079b60a295bcec7ea42d5545cbce58a77a50d932bf953298799135e99707486e343da6d99ba1d167bdbd#npm:0.3.10"],\
@@ -3530,11 +3535,11 @@ const RAW_RUNTIME_STATE =
}]\
]],\
["@types/ioredis", [\
["npm:4.28.10", {\
"packageLocation": "./.yarn/cache/@types-ioredis-npm-4.28.10-4bdbe26a79-a7f24a8a13.zip/node_modules/@types/ioredis/",\
["npm:5.0.0", {\
"packageLocation": "./.yarn/cache/@types-ioredis-npm-5.0.0-6efa70abfa-439770c9da.zip/node_modules/@types/ioredis/",\
"packageDependencies": [\
["@types/ioredis", "npm:4.28.10"],\
["@types/node", "npm:18.0.3"]\
["@types/ioredis", "npm:5.0.0"],\
["ioredis", "npm:5.2.4"]\
],\
"linkType": "HARD"\
}]\
@@ -3663,10 +3668,10 @@ const RAW_RUNTIME_STATE =
}]\
]],\
["@types/newrelic", [\
["npm:7.0.3", {\
"packageLocation": "./.yarn/cache/@types-newrelic-npm-7.0.3-c49600c8f5-f56ebaa21c.zip/node_modules/@types/newrelic/",\
["npm:7.0.4", {\
"packageLocation": "./.yarn/cache/@types-newrelic-npm-7.0.4-4f0b179b51-b44215b3ab.zip/node_modules/@types/newrelic/",\
"packageDependencies": [\
["@types/newrelic", "npm:7.0.3"]\
["@types/newrelic", "npm:7.0.4"]\
],\
"linkType": "HARD"\
}]\
@@ -3678,6 +3683,13 @@ const RAW_RUNTIME_STATE =
["@types/node", "npm:18.0.3"]\
],\
"linkType": "HARD"\
}],\
["npm:18.11.9", {\
"packageLocation": "./.yarn/cache/@types-node-npm-18.11.9-d21dd6ec05-7b7d90894d.zip/node_modules/@types/node/",\
"packageDependencies": [\
["@types/node", "npm:18.11.9"]\
],\
"linkType": "HARD"\
}]\
]],\
["@types/nodemailer", [\
@@ -4730,10 +4742,10 @@ const RAW_RUNTIME_STATE =
}]\
]],\
["aws-sdk", [\
["npm:2.1234.0", {\
"packageLocation": "./.yarn/cache/aws-sdk-npm-2.1234.0-7ee3cd4390-cd4b3e8baf.zip/node_modules/aws-sdk/",\
["npm:2.1253.0", {\
"packageLocation": "./.yarn/cache/aws-sdk-npm-2.1253.0-2cf60975ab-faa4af2949.zip/node_modules/aws-sdk/",\
"packageDependencies": [\
["aws-sdk", "npm:2.1234.0"],\
["aws-sdk", "npm:2.1253.0"],\
["buffer", "npm:4.9.2"],\
["events", "npm:1.1.1"],\
["ieee754", "npm:1.1.13"],\
@@ -4749,12 +4761,13 @@ const RAW_RUNTIME_STATE =
}]\
]],\
["axios", [\
["npm:0.27.2", {\
"packageLocation": "./.yarn/cache/axios-npm-0.27.2-dbe3a48aea-4cd898afe9.zip/node_modules/axios/",\
["npm:1.1.3", {\
"packageLocation": "./.yarn/cache/axios-npm-1.1.3-4b63965ac1-2e28acd01c.zip/node_modules/axios/",\
"packageDependencies": [\
["axios", "npm:0.27.2"],\
["follow-redirects", "virtual:dbe3a48aea1dd5649e16abaf23d4ae05582d2149e16141955113766a0f84f681baf358c77ddccfc82eb23e4ccc66c6c912df62a9c01f2a83f1842bf86cc297b1#npm:1.15.2"],\
["form-data", "npm:4.0.0"]\
["axios", "npm:1.1.3"],\
["follow-redirects", "virtual:4b63965ac1b2157b91a1875529bea3b0bbc3068d3676d1bef28bff5cf6689705374a86cc3832f95ba8d934037a93cc0e09c3662c13ca0e747800d7ca279a53c0#npm:1.15.2"],\
["form-data", "npm:4.0.0"],\
["proxy-from-env", "npm:1.1.0"]\
],\
"linkType": "HARD"\
}]\
@@ -7299,10 +7312,10 @@ const RAW_RUNTIME_STATE =
],\
"linkType": "SOFT"\
}],\
["virtual:dbe3a48aea1dd5649e16abaf23d4ae05582d2149e16141955113766a0f84f681baf358c77ddccfc82eb23e4ccc66c6c912df62a9c01f2a83f1842bf86cc297b1#npm:1.15.2", {\
"packageLocation": "./.yarn/__virtual__/follow-redirects-virtual-42073a9d6a/0/cache/follow-redirects-npm-1.15.2-1ec1dd82be-930171f8b8.zip/node_modules/follow-redirects/",\
["virtual:4b63965ac1b2157b91a1875529bea3b0bbc3068d3676d1bef28bff5cf6689705374a86cc3832f95ba8d934037a93cc0e09c3662c13ca0e747800d7ca279a53c0#npm:1.15.2", {\
"packageLocation": "./.yarn/__virtual__/follow-redirects-virtual-b0bb08d690/0/cache/follow-redirects-npm-1.15.2-1ec1dd82be-930171f8b8.zip/node_modules/follow-redirects/",\
"packageDependencies": [\
["follow-redirects", "virtual:dbe3a48aea1dd5649e16abaf23d4ae05582d2149e16141955113766a0f84f681baf358c77ddccfc82eb23e4ccc66c6c912df62a9c01f2a83f1842bf86cc297b1#npm:1.15.2"],\
["follow-redirects", "virtual:4b63965ac1b2157b91a1875529bea3b0bbc3068d3676d1bef28bff5cf6689705374a86cc3832f95ba8d934037a93cc0e09c3662c13ca0e747800d7ca279a53c0#npm:1.15.2"],\
["@types/debug", null],\
["debug", null]\
],\
@@ -8250,10 +8263,10 @@ const RAW_RUNTIME_STATE =
}]\
]],\
["ioredis", [\
["npm:5.2.3", {\
"packageLocation": "./.yarn/cache/ioredis-npm-5.2.3-54d9576179-3849fbe54a.zip/node_modules/ioredis/",\
["npm:5.2.4", {\
"packageLocation": "./.yarn/cache/ioredis-npm-5.2.4-875ff55d9a-f6572bf619.zip/node_modules/ioredis/",\
"packageDependencies": [\
["ioredis", "npm:5.2.3"],\
["ioredis", "npm:5.2.4"],\
["@ioredis/commands", "npm:1.2.0"],\
["cluster-key-slot", "npm:1.1.1"],\
["debug", "virtual:b86a9fb34323a98c6519528ed55faa0d9b44ca8879307c0b29aa384bde47ff59a7d0c9051b31246f14521dfb71ba3c5d6d0b35c29fffc17bf875aa6ad977d9e8#npm:4.3.4"],\
@@ -10375,18 +10388,17 @@ const RAW_RUNTIME_STATE =
}]\
]],\
["newrelic", [\
["npm:9.0.0", {\
"packageLocation": "./.yarn/cache/newrelic-npm-9.0.0-65e8703d5d-397f7d2626.zip/node_modules/newrelic/",\
["npm:9.6.0", {\
"packageLocation": "./.yarn/cache/newrelic-npm-9.6.0-f10080c2de-eb378acde1.zip/node_modules/newrelic/",\
"packageDependencies": [\
["newrelic", "npm:9.0.0"],\
["newrelic", "npm:9.6.0"],\
["@grpc/grpc-js", "npm:1.6.7"],\
["@grpc/proto-loader", "npm:0.6.13"],\
["@newrelic/aws-sdk", "virtual:65e8703d5df08d5ff3f7296fcb759f276254ee430ae6f3cc1f03da392ff63066a3c6c59591c38f36f19d3e877285287a834b5c55e22d764dc2cb0938f7128707#npm:5.0.0"],\
["@newrelic/koa", "virtual:65e8703d5df08d5ff3f7296fcb759f276254ee430ae6f3cc1f03da392ff63066a3c6c59591c38f36f19d3e877285287a834b5c55e22d764dc2cb0938f7128707#npm:7.0.0"],\
["@newrelic/aws-sdk", "virtual:f10080c2deb75096716a913b06010dcd94891c77539a757ab32210a1efc3ff91527b36d6c7c46e890db826160e0724553ca23acd0a8a734b5554c9600c71eb52#npm:5.0.0"],\
["@newrelic/koa", "virtual:f10080c2deb75096716a913b06010dcd94891c77539a757ab32210a1efc3ff91527b36d6c7c46e890db826160e0724553ca23acd0a8a734b5554c9600c71eb52#npm:7.0.0"],\
["@newrelic/native-metrics", "npm:9.0.0"],\
["@newrelic/superagent", "virtual:65e8703d5df08d5ff3f7296fcb759f276254ee430ae6f3cc1f03da392ff63066a3c6c59591c38f36f19d3e877285287a834b5c55e22d764dc2cb0938f7128707#npm:6.0.0"],\
["@newrelic/superagent", "virtual:f10080c2deb75096716a913b06010dcd94891c77539a757ab32210a1efc3ff91527b36d6c7c46e890db826160e0724553ca23acd0a8a734b5554c9600c71eb52#npm:6.0.0"],\
["@tyriar/fibonacci-heap", "npm:2.0.9"],\
["async", "npm:3.2.4"],\
["concat-stream", "npm:2.0.0"],\
["https-proxy-agent", "npm:5.0.1"],\
["json-stringify-safe", "npm:5.0.1"],\
@@ -11479,6 +11491,15 @@ const RAW_RUNTIME_STATE =
"linkType": "HARD"\
}]\
]],\
["proxy-from-env", [\
["npm:1.1.0", {\
"packageLocation": "./.yarn/cache/proxy-from-env-npm-1.1.0-c13d07f26b-0bba2ef7c8.zip/node_modules/proxy-from-env/",\
"packageDependencies": [\
["proxy-from-env", "npm:1.1.0"]\
],\
"linkType": "HARD"\
}]\
]],\
["pseudomap", [\
["npm:1.0.2", {\
"packageLocation": "./.yarn/cache/pseudomap-npm-1.0.2-0d0e40fee0-33cfbb99ac.zip/node_modules/pseudomap/",\
@@ -12491,7 +12512,7 @@ const RAW_RUNTIME_STATE =
"packageDependencies": [\
["sqs-consumer", "virtual:685a6222c3349423674bb7f0684ba34e2ab20912010f352e04dcf707a156e13183fc382e2417cb37a60f3e7b52fd0178c53181674890e1773eb83e190dc13378#npm:5.7.0"],\
["@types/aws-sdk", null],\
["aws-sdk", "npm:2.1234.0"],\
["aws-sdk", "npm:2.1253.0"],\
["debug", "virtual:b86a9fb34323a98c6519528ed55faa0d9b44ca8879307c0b29aa384bde47ff59a7d0c9051b31246f14521dfb71ba3c5d6d0b35c29fffc17bf875aa6ad977d9e8#npm:4.3.4"]\
],\
"packagePeers": [\
@@ -13106,7 +13127,7 @@ const RAW_RUNTIME_STATE =
["@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/node", "npm:18.11.9"],\
["@types/swc__core", null],\
["@types/swc__wasm", null],\
["@types/typescript", null],\
@@ -13382,7 +13403,7 @@ const RAW_RUNTIME_STATE =
["@types/better-sqlite3", null],\
["@types/google-cloud__spanner", null],\
["@types/hdb-pool", null],\
["@types/ioredis", "npm:4.28.10"],\
["@types/ioredis", "npm:5.0.0"],\
["@types/mongodb", null],\
["@types/mssql", null],\
["@types/mysql2", null],\
@@ -13406,7 +13427,7 @@ const RAW_RUNTIME_STATE =
["dotenv", "npm:16.0.3"],\
["glob", "npm:7.2.3"],\
["hdb-pool", null],\
["ioredis", "npm:5.2.3"],\
["ioredis", "npm:5.2.4"],\
["js-yaml", "npm:4.1.0"],\
["mkdirp", "npm:1.0.4"],\
["mongodb", null],\
@@ -13484,10 +13505,10 @@ const RAW_RUNTIME_STATE =
}]\
]],\
["ua-parser-js", [\
["npm:1.0.2", {\
"packageLocation": "./.yarn/cache/ua-parser-js-npm-1.0.2-c3376785e2-5ee14b105c.zip/node_modules/ua-parser-js/",\
["npm:1.0.32", {\
"packageLocation": "./.yarn/cache/ua-parser-js-npm-1.0.32-95b0b6a78d-9d320c6742.zip/node_modules/ua-parser-js/",\
"packageDependencies": [\
["ua-parser-js", "npm:1.0.2"]\
["ua-parser-js", "npm:1.0.32"]\
],\
"linkType": "HARD"\
}]\

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -326,8 +326,8 @@ ifeq ($(strip $(foreach prefix,$(NO_LOAD),\
endif
quiet_cmd_regen_makefile = ACTION Regenerating $@
cmd_regen_makefile = cd $(srcdir); /Users/karolsojko/workspace/server/.yarn/unplugged/node-gyp-npm-9.0.0-0eccfca4d1/node_modules/node-gyp/gyp/gyp_main.py -fmake --ignore-environment "-Dlibrary=shared_library" "-Dvisibility=default" "-Dnode_root_dir=/Users/karolsojko/Library/Caches/node-gyp/16.15.1" "-Dnode_gyp_dir=/Users/karolsojko/workspace/server/.yarn/unplugged/node-gyp-npm-9.0.0-0eccfca4d1/node_modules/node-gyp" "-Dnode_lib_file=/Users/karolsojko/Library/Caches/node-gyp/16.15.1/<(target_arch)/node.lib" "-Dmodule_root_dir=/Users/karolsojko/workspace/server/.yarn/unplugged/@newrelic-native-metrics-npm-9.0.0-590d2e713a/node_modules/@newrelic/native-metrics" "-Dnode_engine=v8" "--depth=." "-Goutput_dir=." "--generator-output=build" -I/Users/karolsojko/workspace/server/.yarn/unplugged/@newrelic-native-metrics-npm-9.0.0-590d2e713a/node_modules/@newrelic/native-metrics/build/config.gypi -I/Users/karolsojko/workspace/server/.yarn/unplugged/node-gyp-npm-9.0.0-0eccfca4d1/node_modules/node-gyp/addon.gypi -I/Users/karolsojko/Library/Caches/node-gyp/16.15.1/include/node/common.gypi "--toplevel-dir=." binding.gyp
Makefile: $(srcdir)/binding.gyp $(srcdir)/../../../../node-gyp-npm-9.0.0-0eccfca4d1/node_modules/node-gyp/addon.gypi $(srcdir)/../../../../../../../../Library/Caches/node-gyp/16.15.1/include/node/common.gypi $(srcdir)/build/config.gypi
cmd_regen_makefile = cd $(srcdir); /Users/karolsojko/workspace/server/.yarn/unplugged/node-gyp-npm-9.0.0-0eccfca4d1/node_modules/node-gyp/gyp/gyp_main.py -fmake --ignore-environment "-Dlibrary=shared_library" "-Dvisibility=default" "-Dnode_root_dir=/Users/karolsojko/Library/Caches/node-gyp/18.12.1" "-Dnode_gyp_dir=/Users/karolsojko/workspace/server/.yarn/unplugged/node-gyp-npm-9.0.0-0eccfca4d1/node_modules/node-gyp" "-Dnode_lib_file=/Users/karolsojko/Library/Caches/node-gyp/18.12.1/<(target_arch)/node.lib" "-Dmodule_root_dir=/Users/karolsojko/workspace/server/.yarn/unplugged/@newrelic-native-metrics-npm-9.0.0-590d2e713a/node_modules/@newrelic/native-metrics" "-Dnode_engine=v8" "--depth=." "-Goutput_dir=." "--generator-output=build" -I/Users/karolsojko/workspace/server/.yarn/unplugged/@newrelic-native-metrics-npm-9.0.0-590d2e713a/node_modules/@newrelic/native-metrics/build/config.gypi -I/Users/karolsojko/workspace/server/.yarn/unplugged/node-gyp-npm-9.0.0-0eccfca4d1/node_modules/node-gyp/addon.gypi -I/Users/karolsojko/Library/Caches/node-gyp/18.12.1/include/node/common.gypi "--toplevel-dir=." binding.gyp
Makefile: $(srcdir)/build/config.gypi $(srcdir)/../../../../node-gyp-npm-9.0.0-0eccfca4d1/node_modules/node-gyp/addon.gypi $(srcdir)/../../../../../../../../Library/Caches/node-gyp/18.12.1/include/node/common.gypi $(srcdir)/binding.gyp
$(call do_cmd,regen_makefile)
# "all" is a concatenation of the "all" targets from all the included

View File

@@ -1 +0,0 @@
cmd_Release/native_metrics.node := c++ -bundle -undefined dynamic_lookup -Wl,-search_paths_first -mmacosx-version-min=10.13 -arch x86_64 -L./Release -stdlib=libc++ -o Release/native_metrics.node Release/obj.target/native_metrics/src/native_metrics.o Release/obj.target/native_metrics/src/GCBinder.o Release/obj.target/native_metrics/src/LoopChecker.o

View File

@@ -1,69 +0,0 @@
cmd_Release/obj.target/native_metrics/src/GCBinder.o := c++ -o Release/obj.target/native_metrics/src/GCBinder.o ../src/GCBinder.cpp '-DNODE_GYP_MODULE_NAME=native_metrics' '-DUSING_UV_SHARED=1' '-DUSING_V8_SHARED=1' '-DV8_DEPRECATION_WARNINGS=1' '-DV8_DEPRECATION_WARNINGS' '-DV8_IMMINENT_DEPRECATION_WARNINGS' '-D_GLIBCXX_USE_CXX11_ABI=1' '-D_DARWIN_USE_64_BIT_INODE=1' '-D_LARGEFILE_SOURCE' '-D_FILE_OFFSET_BITS=64' '-DOPENSSL_NO_PINSHARED' '-DOPENSSL_THREADS' '-DNOMINMAX' '-DBUILDING_NODE_EXTENSION' -I/Users/karolsojko/Library/Caches/node-gyp/16.15.1/include/node -I/Users/karolsojko/Library/Caches/node-gyp/16.15.1/src -I/Users/karolsojko/Library/Caches/node-gyp/16.15.1/deps/openssl/config -I/Users/karolsojko/Library/Caches/node-gyp/16.15.1/deps/openssl/openssl/include -I/Users/karolsojko/Library/Caches/node-gyp/16.15.1/deps/uv/include -I/Users/karolsojko/Library/Caches/node-gyp/16.15.1/deps/zlib -I/Users/karolsojko/Library/Caches/node-gyp/16.15.1/deps/v8/include -I../src -I../../../../../nan-npm-2.16.0-cac314a230/node_modules/nan -O3 -gdwarf-2 -mmacosx-version-min=10.13 -arch x86_64 -Wall -Wendif-labels -W -Wno-unused-parameter -std=gnu++14 -stdlib=libc++ -fno-rtti -fno-exceptions -fno-strict-aliasing -MMD -MF ./Release/.deps/Release/obj.target/native_metrics/src/GCBinder.o.d.raw -c
Release/obj.target/native_metrics/src/GCBinder.o: ../src/GCBinder.cpp \
../src/GCBinder.hpp \
../../../../../nan-npm-2.16.0-cac314a230/node_modules/nan/nan.h \
/Users/karolsojko/Library/Caches/node-gyp/16.15.1/include/node/node_version.h \
/Users/karolsojko/Library/Caches/node-gyp/16.15.1/include/node/uv.h \
/Users/karolsojko/Library/Caches/node-gyp/16.15.1/include/node/uv/errno.h \
/Users/karolsojko/Library/Caches/node-gyp/16.15.1/include/node/uv/version.h \
/Users/karolsojko/Library/Caches/node-gyp/16.15.1/include/node/uv/unix.h \
/Users/karolsojko/Library/Caches/node-gyp/16.15.1/include/node/uv/threadpool.h \
/Users/karolsojko/Library/Caches/node-gyp/16.15.1/include/node/uv/darwin.h \
/Users/karolsojko/Library/Caches/node-gyp/16.15.1/include/node/node.h \
/Users/karolsojko/Library/Caches/node-gyp/16.15.1/include/node/v8.h \
/Users/karolsojko/Library/Caches/node-gyp/16.15.1/include/node/cppgc/common.h \
/Users/karolsojko/Library/Caches/node-gyp/16.15.1/include/node/v8config.h \
/Users/karolsojko/Library/Caches/node-gyp/16.15.1/include/node/v8-internal.h \
/Users/karolsojko/Library/Caches/node-gyp/16.15.1/include/node/v8-version.h \
/Users/karolsojko/Library/Caches/node-gyp/16.15.1/include/node/v8-platform.h \
/Users/karolsojko/Library/Caches/node-gyp/16.15.1/include/node/node_buffer.h \
/Users/karolsojko/Library/Caches/node-gyp/16.15.1/include/node/node_object_wrap.h \
../../../../../nan-npm-2.16.0-cac314a230/node_modules/nan/nan_callbacks.h \
../../../../../nan-npm-2.16.0-cac314a230/node_modules/nan/nan_callbacks_12_inl.h \
../../../../../nan-npm-2.16.0-cac314a230/node_modules/nan/nan_maybe_43_inl.h \
../../../../../nan-npm-2.16.0-cac314a230/node_modules/nan/nan_converters.h \
../../../../../nan-npm-2.16.0-cac314a230/node_modules/nan/nan_converters_43_inl.h \
../../../../../nan-npm-2.16.0-cac314a230/node_modules/nan/nan_new.h \
../../../../../nan-npm-2.16.0-cac314a230/node_modules/nan/nan_implementation_12_inl.h \
../../../../../nan-npm-2.16.0-cac314a230/node_modules/nan/nan_persistent_12_inl.h \
../../../../../nan-npm-2.16.0-cac314a230/node_modules/nan/nan_weak.h \
../../../../../nan-npm-2.16.0-cac314a230/node_modules/nan/nan_object_wrap.h \
../../../../../nan-npm-2.16.0-cac314a230/node_modules/nan/nan_private.h \
../../../../../nan-npm-2.16.0-cac314a230/node_modules/nan/nan_typedarray_contents.h \
../../../../../nan-npm-2.16.0-cac314a230/node_modules/nan/nan_json.h \
../../../../../nan-npm-2.16.0-cac314a230/node_modules/nan/nan_scriptorigin.h \
../src/Metric.hpp
../src/GCBinder.cpp:
../src/GCBinder.hpp:
../../../../../nan-npm-2.16.0-cac314a230/node_modules/nan/nan.h:
/Users/karolsojko/Library/Caches/node-gyp/16.15.1/include/node/node_version.h:
/Users/karolsojko/Library/Caches/node-gyp/16.15.1/include/node/uv.h:
/Users/karolsojko/Library/Caches/node-gyp/16.15.1/include/node/uv/errno.h:
/Users/karolsojko/Library/Caches/node-gyp/16.15.1/include/node/uv/version.h:
/Users/karolsojko/Library/Caches/node-gyp/16.15.1/include/node/uv/unix.h:
/Users/karolsojko/Library/Caches/node-gyp/16.15.1/include/node/uv/threadpool.h:
/Users/karolsojko/Library/Caches/node-gyp/16.15.1/include/node/uv/darwin.h:
/Users/karolsojko/Library/Caches/node-gyp/16.15.1/include/node/node.h:
/Users/karolsojko/Library/Caches/node-gyp/16.15.1/include/node/v8.h:
/Users/karolsojko/Library/Caches/node-gyp/16.15.1/include/node/cppgc/common.h:
/Users/karolsojko/Library/Caches/node-gyp/16.15.1/include/node/v8config.h:
/Users/karolsojko/Library/Caches/node-gyp/16.15.1/include/node/v8-internal.h:
/Users/karolsojko/Library/Caches/node-gyp/16.15.1/include/node/v8-version.h:
/Users/karolsojko/Library/Caches/node-gyp/16.15.1/include/node/v8-platform.h:
/Users/karolsojko/Library/Caches/node-gyp/16.15.1/include/node/node_buffer.h:
/Users/karolsojko/Library/Caches/node-gyp/16.15.1/include/node/node_object_wrap.h:
../../../../../nan-npm-2.16.0-cac314a230/node_modules/nan/nan_callbacks.h:
../../../../../nan-npm-2.16.0-cac314a230/node_modules/nan/nan_callbacks_12_inl.h:
../../../../../nan-npm-2.16.0-cac314a230/node_modules/nan/nan_maybe_43_inl.h:
../../../../../nan-npm-2.16.0-cac314a230/node_modules/nan/nan_converters.h:
../../../../../nan-npm-2.16.0-cac314a230/node_modules/nan/nan_converters_43_inl.h:
../../../../../nan-npm-2.16.0-cac314a230/node_modules/nan/nan_new.h:
../../../../../nan-npm-2.16.0-cac314a230/node_modules/nan/nan_implementation_12_inl.h:
../../../../../nan-npm-2.16.0-cac314a230/node_modules/nan/nan_persistent_12_inl.h:
../../../../../nan-npm-2.16.0-cac314a230/node_modules/nan/nan_weak.h:
../../../../../nan-npm-2.16.0-cac314a230/node_modules/nan/nan_object_wrap.h:
../../../../../nan-npm-2.16.0-cac314a230/node_modules/nan/nan_private.h:
../../../../../nan-npm-2.16.0-cac314a230/node_modules/nan/nan_typedarray_contents.h:
../../../../../nan-npm-2.16.0-cac314a230/node_modules/nan/nan_json.h:
../../../../../nan-npm-2.16.0-cac314a230/node_modules/nan/nan_scriptorigin.h:
../src/Metric.hpp:

View File

@@ -1,70 +0,0 @@
cmd_Release/obj.target/native_metrics/src/LoopChecker.o := c++ -o Release/obj.target/native_metrics/src/LoopChecker.o ../src/LoopChecker.cpp '-DNODE_GYP_MODULE_NAME=native_metrics' '-DUSING_UV_SHARED=1' '-DUSING_V8_SHARED=1' '-DV8_DEPRECATION_WARNINGS=1' '-DV8_DEPRECATION_WARNINGS' '-DV8_IMMINENT_DEPRECATION_WARNINGS' '-D_GLIBCXX_USE_CXX11_ABI=1' '-D_DARWIN_USE_64_BIT_INODE=1' '-D_LARGEFILE_SOURCE' '-D_FILE_OFFSET_BITS=64' '-DOPENSSL_NO_PINSHARED' '-DOPENSSL_THREADS' '-DNOMINMAX' '-DBUILDING_NODE_EXTENSION' -I/Users/karolsojko/Library/Caches/node-gyp/16.15.1/include/node -I/Users/karolsojko/Library/Caches/node-gyp/16.15.1/src -I/Users/karolsojko/Library/Caches/node-gyp/16.15.1/deps/openssl/config -I/Users/karolsojko/Library/Caches/node-gyp/16.15.1/deps/openssl/openssl/include -I/Users/karolsojko/Library/Caches/node-gyp/16.15.1/deps/uv/include -I/Users/karolsojko/Library/Caches/node-gyp/16.15.1/deps/zlib -I/Users/karolsojko/Library/Caches/node-gyp/16.15.1/deps/v8/include -I../src -I../../../../../nan-npm-2.16.0-cac314a230/node_modules/nan -O3 -gdwarf-2 -mmacosx-version-min=10.13 -arch x86_64 -Wall -Wendif-labels -W -Wno-unused-parameter -std=gnu++14 -stdlib=libc++ -fno-rtti -fno-exceptions -fno-strict-aliasing -MMD -MF ./Release/.deps/Release/obj.target/native_metrics/src/LoopChecker.o.d.raw -c
Release/obj.target/native_metrics/src/LoopChecker.o: \
../src/LoopChecker.cpp \
/Users/karolsojko/Library/Caches/node-gyp/16.15.1/include/node/uv.h \
/Users/karolsojko/Library/Caches/node-gyp/16.15.1/include/node/uv/errno.h \
/Users/karolsojko/Library/Caches/node-gyp/16.15.1/include/node/uv/version.h \
/Users/karolsojko/Library/Caches/node-gyp/16.15.1/include/node/uv/unix.h \
/Users/karolsojko/Library/Caches/node-gyp/16.15.1/include/node/uv/threadpool.h \
/Users/karolsojko/Library/Caches/node-gyp/16.15.1/include/node/uv/darwin.h \
../src/LoopChecker.hpp \
../../../../../nan-npm-2.16.0-cac314a230/node_modules/nan/nan.h \
/Users/karolsojko/Library/Caches/node-gyp/16.15.1/include/node/node_version.h \
/Users/karolsojko/Library/Caches/node-gyp/16.15.1/include/node/node.h \
/Users/karolsojko/Library/Caches/node-gyp/16.15.1/include/node/v8.h \
/Users/karolsojko/Library/Caches/node-gyp/16.15.1/include/node/cppgc/common.h \
/Users/karolsojko/Library/Caches/node-gyp/16.15.1/include/node/v8config.h \
/Users/karolsojko/Library/Caches/node-gyp/16.15.1/include/node/v8-internal.h \
/Users/karolsojko/Library/Caches/node-gyp/16.15.1/include/node/v8-version.h \
/Users/karolsojko/Library/Caches/node-gyp/16.15.1/include/node/v8-platform.h \
/Users/karolsojko/Library/Caches/node-gyp/16.15.1/include/node/node_buffer.h \
/Users/karolsojko/Library/Caches/node-gyp/16.15.1/include/node/node_object_wrap.h \
../../../../../nan-npm-2.16.0-cac314a230/node_modules/nan/nan_callbacks.h \
../../../../../nan-npm-2.16.0-cac314a230/node_modules/nan/nan_callbacks_12_inl.h \
../../../../../nan-npm-2.16.0-cac314a230/node_modules/nan/nan_maybe_43_inl.h \
../../../../../nan-npm-2.16.0-cac314a230/node_modules/nan/nan_converters.h \
../../../../../nan-npm-2.16.0-cac314a230/node_modules/nan/nan_converters_43_inl.h \
../../../../../nan-npm-2.16.0-cac314a230/node_modules/nan/nan_new.h \
../../../../../nan-npm-2.16.0-cac314a230/node_modules/nan/nan_implementation_12_inl.h \
../../../../../nan-npm-2.16.0-cac314a230/node_modules/nan/nan_persistent_12_inl.h \
../../../../../nan-npm-2.16.0-cac314a230/node_modules/nan/nan_weak.h \
../../../../../nan-npm-2.16.0-cac314a230/node_modules/nan/nan_object_wrap.h \
../../../../../nan-npm-2.16.0-cac314a230/node_modules/nan/nan_private.h \
../../../../../nan-npm-2.16.0-cac314a230/node_modules/nan/nan_typedarray_contents.h \
../../../../../nan-npm-2.16.0-cac314a230/node_modules/nan/nan_json.h \
../../../../../nan-npm-2.16.0-cac314a230/node_modules/nan/nan_scriptorigin.h \
../src/Metric.hpp
../src/LoopChecker.cpp:
/Users/karolsojko/Library/Caches/node-gyp/16.15.1/include/node/uv.h:
/Users/karolsojko/Library/Caches/node-gyp/16.15.1/include/node/uv/errno.h:
/Users/karolsojko/Library/Caches/node-gyp/16.15.1/include/node/uv/version.h:
/Users/karolsojko/Library/Caches/node-gyp/16.15.1/include/node/uv/unix.h:
/Users/karolsojko/Library/Caches/node-gyp/16.15.1/include/node/uv/threadpool.h:
/Users/karolsojko/Library/Caches/node-gyp/16.15.1/include/node/uv/darwin.h:
../src/LoopChecker.hpp:
../../../../../nan-npm-2.16.0-cac314a230/node_modules/nan/nan.h:
/Users/karolsojko/Library/Caches/node-gyp/16.15.1/include/node/node_version.h:
/Users/karolsojko/Library/Caches/node-gyp/16.15.1/include/node/node.h:
/Users/karolsojko/Library/Caches/node-gyp/16.15.1/include/node/v8.h:
/Users/karolsojko/Library/Caches/node-gyp/16.15.1/include/node/cppgc/common.h:
/Users/karolsojko/Library/Caches/node-gyp/16.15.1/include/node/v8config.h:
/Users/karolsojko/Library/Caches/node-gyp/16.15.1/include/node/v8-internal.h:
/Users/karolsojko/Library/Caches/node-gyp/16.15.1/include/node/v8-version.h:
/Users/karolsojko/Library/Caches/node-gyp/16.15.1/include/node/v8-platform.h:
/Users/karolsojko/Library/Caches/node-gyp/16.15.1/include/node/node_buffer.h:
/Users/karolsojko/Library/Caches/node-gyp/16.15.1/include/node/node_object_wrap.h:
../../../../../nan-npm-2.16.0-cac314a230/node_modules/nan/nan_callbacks.h:
../../../../../nan-npm-2.16.0-cac314a230/node_modules/nan/nan_callbacks_12_inl.h:
../../../../../nan-npm-2.16.0-cac314a230/node_modules/nan/nan_maybe_43_inl.h:
../../../../../nan-npm-2.16.0-cac314a230/node_modules/nan/nan_converters.h:
../../../../../nan-npm-2.16.0-cac314a230/node_modules/nan/nan_converters_43_inl.h:
../../../../../nan-npm-2.16.0-cac314a230/node_modules/nan/nan_new.h:
../../../../../nan-npm-2.16.0-cac314a230/node_modules/nan/nan_implementation_12_inl.h:
../../../../../nan-npm-2.16.0-cac314a230/node_modules/nan/nan_persistent_12_inl.h:
../../../../../nan-npm-2.16.0-cac314a230/node_modules/nan/nan_weak.h:
../../../../../nan-npm-2.16.0-cac314a230/node_modules/nan/nan_object_wrap.h:
../../../../../nan-npm-2.16.0-cac314a230/node_modules/nan/nan_private.h:
../../../../../nan-npm-2.16.0-cac314a230/node_modules/nan/nan_typedarray_contents.h:
../../../../../nan-npm-2.16.0-cac314a230/node_modules/nan/nan_json.h:
../../../../../nan-npm-2.16.0-cac314a230/node_modules/nan/nan_scriptorigin.h:
../src/Metric.hpp:

View File

@@ -1,70 +0,0 @@
cmd_Release/obj.target/native_metrics/src/native_metrics.o := c++ -o Release/obj.target/native_metrics/src/native_metrics.o ../src/native_metrics.cpp '-DNODE_GYP_MODULE_NAME=native_metrics' '-DUSING_UV_SHARED=1' '-DUSING_V8_SHARED=1' '-DV8_DEPRECATION_WARNINGS=1' '-DV8_DEPRECATION_WARNINGS' '-DV8_IMMINENT_DEPRECATION_WARNINGS' '-D_GLIBCXX_USE_CXX11_ABI=1' '-D_DARWIN_USE_64_BIT_INODE=1' '-D_LARGEFILE_SOURCE' '-D_FILE_OFFSET_BITS=64' '-DOPENSSL_NO_PINSHARED' '-DOPENSSL_THREADS' '-DNOMINMAX' '-DBUILDING_NODE_EXTENSION' -I/Users/karolsojko/Library/Caches/node-gyp/16.15.1/include/node -I/Users/karolsojko/Library/Caches/node-gyp/16.15.1/src -I/Users/karolsojko/Library/Caches/node-gyp/16.15.1/deps/openssl/config -I/Users/karolsojko/Library/Caches/node-gyp/16.15.1/deps/openssl/openssl/include -I/Users/karolsojko/Library/Caches/node-gyp/16.15.1/deps/uv/include -I/Users/karolsojko/Library/Caches/node-gyp/16.15.1/deps/zlib -I/Users/karolsojko/Library/Caches/node-gyp/16.15.1/deps/v8/include -I../src -I../../../../../nan-npm-2.16.0-cac314a230/node_modules/nan -O3 -gdwarf-2 -mmacosx-version-min=10.13 -arch x86_64 -Wall -Wendif-labels -W -Wno-unused-parameter -std=gnu++14 -stdlib=libc++ -fno-rtti -fno-exceptions -fno-strict-aliasing -MMD -MF ./Release/.deps/Release/obj.target/native_metrics/src/native_metrics.o.d.raw -c
Release/obj.target/native_metrics/src/native_metrics.o: \
../src/native_metrics.cpp \
../../../../../nan-npm-2.16.0-cac314a230/node_modules/nan/nan.h \
/Users/karolsojko/Library/Caches/node-gyp/16.15.1/include/node/node_version.h \
/Users/karolsojko/Library/Caches/node-gyp/16.15.1/include/node/uv.h \
/Users/karolsojko/Library/Caches/node-gyp/16.15.1/include/node/uv/errno.h \
/Users/karolsojko/Library/Caches/node-gyp/16.15.1/include/node/uv/version.h \
/Users/karolsojko/Library/Caches/node-gyp/16.15.1/include/node/uv/unix.h \
/Users/karolsojko/Library/Caches/node-gyp/16.15.1/include/node/uv/threadpool.h \
/Users/karolsojko/Library/Caches/node-gyp/16.15.1/include/node/uv/darwin.h \
/Users/karolsojko/Library/Caches/node-gyp/16.15.1/include/node/node.h \
/Users/karolsojko/Library/Caches/node-gyp/16.15.1/include/node/v8.h \
/Users/karolsojko/Library/Caches/node-gyp/16.15.1/include/node/cppgc/common.h \
/Users/karolsojko/Library/Caches/node-gyp/16.15.1/include/node/v8config.h \
/Users/karolsojko/Library/Caches/node-gyp/16.15.1/include/node/v8-internal.h \
/Users/karolsojko/Library/Caches/node-gyp/16.15.1/include/node/v8-version.h \
/Users/karolsojko/Library/Caches/node-gyp/16.15.1/include/node/v8-platform.h \
/Users/karolsojko/Library/Caches/node-gyp/16.15.1/include/node/node_buffer.h \
/Users/karolsojko/Library/Caches/node-gyp/16.15.1/include/node/node_object_wrap.h \
../../../../../nan-npm-2.16.0-cac314a230/node_modules/nan/nan_callbacks.h \
../../../../../nan-npm-2.16.0-cac314a230/node_modules/nan/nan_callbacks_12_inl.h \
../../../../../nan-npm-2.16.0-cac314a230/node_modules/nan/nan_maybe_43_inl.h \
../../../../../nan-npm-2.16.0-cac314a230/node_modules/nan/nan_converters.h \
../../../../../nan-npm-2.16.0-cac314a230/node_modules/nan/nan_converters_43_inl.h \
../../../../../nan-npm-2.16.0-cac314a230/node_modules/nan/nan_new.h \
../../../../../nan-npm-2.16.0-cac314a230/node_modules/nan/nan_implementation_12_inl.h \
../../../../../nan-npm-2.16.0-cac314a230/node_modules/nan/nan_persistent_12_inl.h \
../../../../../nan-npm-2.16.0-cac314a230/node_modules/nan/nan_weak.h \
../../../../../nan-npm-2.16.0-cac314a230/node_modules/nan/nan_object_wrap.h \
../../../../../nan-npm-2.16.0-cac314a230/node_modules/nan/nan_private.h \
../../../../../nan-npm-2.16.0-cac314a230/node_modules/nan/nan_typedarray_contents.h \
../../../../../nan-npm-2.16.0-cac314a230/node_modules/nan/nan_json.h \
../../../../../nan-npm-2.16.0-cac314a230/node_modules/nan/nan_scriptorigin.h \
../src/GCBinder.hpp ../src/Metric.hpp ../src/LoopChecker.hpp
../src/native_metrics.cpp:
../../../../../nan-npm-2.16.0-cac314a230/node_modules/nan/nan.h:
/Users/karolsojko/Library/Caches/node-gyp/16.15.1/include/node/node_version.h:
/Users/karolsojko/Library/Caches/node-gyp/16.15.1/include/node/uv.h:
/Users/karolsojko/Library/Caches/node-gyp/16.15.1/include/node/uv/errno.h:
/Users/karolsojko/Library/Caches/node-gyp/16.15.1/include/node/uv/version.h:
/Users/karolsojko/Library/Caches/node-gyp/16.15.1/include/node/uv/unix.h:
/Users/karolsojko/Library/Caches/node-gyp/16.15.1/include/node/uv/threadpool.h:
/Users/karolsojko/Library/Caches/node-gyp/16.15.1/include/node/uv/darwin.h:
/Users/karolsojko/Library/Caches/node-gyp/16.15.1/include/node/node.h:
/Users/karolsojko/Library/Caches/node-gyp/16.15.1/include/node/v8.h:
/Users/karolsojko/Library/Caches/node-gyp/16.15.1/include/node/cppgc/common.h:
/Users/karolsojko/Library/Caches/node-gyp/16.15.1/include/node/v8config.h:
/Users/karolsojko/Library/Caches/node-gyp/16.15.1/include/node/v8-internal.h:
/Users/karolsojko/Library/Caches/node-gyp/16.15.1/include/node/v8-version.h:
/Users/karolsojko/Library/Caches/node-gyp/16.15.1/include/node/v8-platform.h:
/Users/karolsojko/Library/Caches/node-gyp/16.15.1/include/node/node_buffer.h:
/Users/karolsojko/Library/Caches/node-gyp/16.15.1/include/node/node_object_wrap.h:
../../../../../nan-npm-2.16.0-cac314a230/node_modules/nan/nan_callbacks.h:
../../../../../nan-npm-2.16.0-cac314a230/node_modules/nan/nan_callbacks_12_inl.h:
../../../../../nan-npm-2.16.0-cac314a230/node_modules/nan/nan_maybe_43_inl.h:
../../../../../nan-npm-2.16.0-cac314a230/node_modules/nan/nan_converters.h:
../../../../../nan-npm-2.16.0-cac314a230/node_modules/nan/nan_converters_43_inl.h:
../../../../../nan-npm-2.16.0-cac314a230/node_modules/nan/nan_new.h:
../../../../../nan-npm-2.16.0-cac314a230/node_modules/nan/nan_implementation_12_inl.h:
../../../../../nan-npm-2.16.0-cac314a230/node_modules/nan/nan_persistent_12_inl.h:
../../../../../nan-npm-2.16.0-cac314a230/node_modules/nan/nan_weak.h:
../../../../../nan-npm-2.16.0-cac314a230/node_modules/nan/nan_object_wrap.h:
../../../../../nan-npm-2.16.0-cac314a230/node_modules/nan/nan_private.h:
../../../../../nan-npm-2.16.0-cac314a230/node_modules/nan/nan_typedarray_contents.h:
../../../../../nan-npm-2.16.0-cac314a230/node_modules/nan/nan_json.h:
../../../../../nan-npm-2.16.0-cac314a230/node_modules/nan/nan_scriptorigin.h:
../src/GCBinder.hpp:
../src/Metric.hpp:
../src/LoopChecker.hpp:

View File

@@ -19,293 +19,316 @@
"error_on_warn": "false",
"force_dynamic_crt": 0,
"host_arch": "x64",
"icu_data_in": "../../deps/icu-tmp/icudt70l.dat",
"icu_data_in": "../../deps/icu-tmp/icudt71l.dat",
"icu_endianness": "l",
"icu_gyp_path": "tools/icu/icu-generic.gyp",
"icu_path": "deps/icu-small",
"icu_small": "false",
"icu_ver_major": "70",
"icu_ver_major": "71",
"is_debug": 0,
"libdir": "lib",
"llvm_version": "11.0",
"napi_build_version": "8",
"node_byteorder": "little",
"node_debug_lib": "false",
"node_enable_d8": "false",
"node_fipsinstall": "false",
"node_install_corepack": "true",
"node_install_npm": "true",
"node_library_files": [
"lib/constants.js",
"lib/net.js",
"lib/trace_events.js",
"lib/events.js",
"lib/repl.js",
"lib/util.js",
"lib/dgram.js",
"lib/vm.js",
"lib/stream.js",
"lib/child_process.js",
"lib/assert.js",
"lib/_tls_wrap.js",
"lib/http2.js",
"lib/inspector.js",
"lib/os.js",
"lib/_http_server.js",
"lib/console.js",
"lib/perf_hooks.js",
"lib/readline.js",
"lib/punycode.js",
"lib/_http_incoming.js",
"lib/https.js",
"lib/_stream_wrap.js",
"lib/domain.js",
"lib/dns.js",
"lib/_http_client.js",
"lib/diagnostics_channel.js",
"lib/tty.js",
"lib/_http_agent.js",
"lib/timers.js",
"lib/_http_outgoing.js",
"lib/querystring.js",
"lib/_tls_common.js",
"lib/module.js",
"lib/_stream_passthrough.js",
"lib/_stream_transform.js",
"lib/worker_threads.js",
"lib/sys.js",
"lib/_stream_duplex.js",
"lib/path.js",
"lib/_http_client.js",
"lib/_http_common.js",
"lib/string_decoder.js",
"lib/cluster.js",
"lib/v8.js",
"lib/crypto.js",
"lib/wasi.js",
"lib/_http_incoming.js",
"lib/_http_outgoing.js",
"lib/_http_server.js",
"lib/_stream_duplex.js",
"lib/_stream_passthrough.js",
"lib/_stream_readable.js",
"lib/zlib.js",
"lib/url.js",
"lib/tls.js",
"lib/_stream_transform.js",
"lib/_stream_wrap.js",
"lib/_stream_writable.js",
"lib/_tls_common.js",
"lib/_tls_wrap.js",
"lib/assert.js",
"lib/assert/strict.js",
"lib/async_hooks.js",
"lib/process.js",
"lib/http.js",
"lib/buffer.js",
"lib/child_process.js",
"lib/cluster.js",
"lib/console.js",
"lib/constants.js",
"lib/crypto.js",
"lib/dgram.js",
"lib/diagnostics_channel.js",
"lib/dns.js",
"lib/dns/promises.js",
"lib/domain.js",
"lib/events.js",
"lib/fs.js",
"lib/util/types.js",
"lib/timers/promises.js",
"lib/path/win32.js",
"lib/path/posix.js",
"lib/stream/consumers.js",
"lib/stream/promises.js",
"lib/stream/web.js",
"lib/internal/constants.js",
"lib/fs/promises.js",
"lib/http.js",
"lib/http2.js",
"lib/https.js",
"lib/inspector.js",
"lib/internal/abort_controller.js",
"lib/internal/net.js",
"lib/internal/v8_prof_processor.js",
"lib/internal/event_target.js",
"lib/internal/inspector_async_hook.js",
"lib/internal/validators.js",
"lib/internal/linkedlist.js",
"lib/internal/cli_table.js",
"lib/internal/repl.js",
"lib/internal/util.js",
"lib/internal/histogram.js",
"lib/internal/error_serdes.js",
"lib/internal/dgram.js",
"lib/internal/child_process.js",
"lib/internal/assert.js",
"lib/internal/fixed_queue.js",
"lib/internal/blocklist.js",
"lib/internal/v8_prof_polyfill.js",
"lib/internal/options.js",
"lib/internal/worker.js",
"lib/internal/dtrace.js",
"lib/internal/idna.js",
"lib/internal/watchdog.js",
"lib/internal/encoding.js",
"lib/internal/tty.js",
"lib/internal/freeze_intrinsics.js",
"lib/internal/timers.js",
"lib/internal/heap_utils.js",
"lib/internal/querystring.js",
"lib/internal/js_stream_socket.js",
"lib/internal/errors.js",
"lib/internal/priority_queue.js",
"lib/internal/freelist.js",
"lib/internal/blob.js",
"lib/internal/socket_list.js",
"lib/internal/socketaddress.js",
"lib/internal/promise_hooks.js",
"lib/internal/stream_base_commons.js",
"lib/internal/url.js",
"lib/internal/assert/assertion_error.js",
"lib/internal/assert/calltracker.js",
"lib/internal/assert/snapshot.js",
"lib/internal/async_hooks.js",
"lib/internal/http.js",
"lib/internal/buffer.js",
"lib/internal/trace_events_async_hooks.js",
"lib/internal/crypto/sig.js",
"lib/internal/crypto/rsa.js",
"lib/internal/crypto/aes.js",
"lib/internal/crypto/util.js",
"lib/internal/crypto/scrypt.js",
"lib/internal/crypto/random.js",
"lib/internal/crypto/keys.js",
"lib/internal/crypto/x509.js",
"lib/internal/crypto/certificate.js",
"lib/internal/crypto/ec.js",
"lib/internal/crypto/keygen.js",
"lib/internal/crypto/mac.js",
"lib/internal/crypto/diffiehellman.js",
"lib/internal/crypto/hkdf.js",
"lib/internal/crypto/cipher.js",
"lib/internal/crypto/hash.js",
"lib/internal/crypto/pbkdf2.js",
"lib/internal/crypto/webcrypto.js",
"lib/internal/crypto/dsa.js",
"lib/internal/crypto/hashnames.js",
"lib/internal/cluster/shared_handle.js",
"lib/internal/cluster/round_robin_handle.js",
"lib/internal/cluster/worker.js",
"lib/internal/cluster/primary.js",
"lib/internal/cluster/utils.js",
"lib/internal/cluster/child.js",
"lib/internal/webstreams/compression.js",
"lib/internal/webstreams/util.js",
"lib/internal/webstreams/writablestream.js",
"lib/internal/webstreams/readablestream.js",
"lib/internal/webstreams/queuingstrategies.js",
"lib/internal/webstreams/encoding.js",
"lib/internal/webstreams/transformstream.js",
"lib/internal/webstreams/adapters.js",
"lib/internal/webstreams/transfer.js",
"lib/internal/blob.js",
"lib/internal/blocklist.js",
"lib/internal/bootstrap/browser.js",
"lib/internal/bootstrap/loaders.js",
"lib/internal/bootstrap/pre_execution.js",
"lib/internal/bootstrap/node.js",
"lib/internal/bootstrap/environment.js",
"lib/internal/bootstrap/switches/does_not_own_process_state.js",
"lib/internal/bootstrap/switches/is_not_main_thread.js",
"lib/internal/bootstrap/switches/does_own_process_state.js",
"lib/internal/bootstrap/switches/is_main_thread.js",
"lib/internal/test/binding.js",
"lib/internal/test/transfer.js",
"lib/internal/util/types.js",
"lib/internal/util/inspector.js",
"lib/internal/util/comparisons.js",
"lib/internal/util/debuglog.js",
"lib/internal/util/inspect.js",
"lib/internal/util/iterable_weak_map.js",
"lib/internal/streams/add-abort-signal.js",
"lib/internal/streams/compose.js",
"lib/internal/streams/duplexify.js",
"lib/internal/streams/destroy.js",
"lib/internal/streams/legacy.js",
"lib/internal/streams/passthrough.js",
"lib/internal/streams/operators.js",
"lib/internal/streams/readable.js",
"lib/internal/streams/from.js",
"lib/internal/streams/writable.js",
"lib/internal/streams/state.js",
"lib/internal/streams/buffer_list.js",
"lib/internal/streams/end-of-stream.js",
"lib/internal/streams/utils.js",
"lib/internal/streams/transform.js",
"lib/internal/streams/lazy_transform.js",
"lib/internal/streams/duplex.js",
"lib/internal/streams/pipeline.js",
"lib/internal/readline/interface.js",
"lib/internal/readline/utils.js",
"lib/internal/readline/emitKeypressEvents.js",
"lib/internal/readline/callbacks.js",
"lib/internal/repl/history.js",
"lib/internal/repl/utils.js",
"lib/internal/repl/await.js",
"lib/internal/legacy/processbinding.js",
"lib/internal/assert/calltracker.js",
"lib/internal/assert/assertion_error.js",
"lib/internal/http2/util.js",
"lib/internal/http2/core.js",
"lib/internal/http2/compat.js",
"lib/internal/per_context/messageport.js",
"lib/internal/per_context/primordials.js",
"lib/internal/per_context/domexception.js",
"lib/internal/vm/module.js",
"lib/internal/tls/secure-pair.js",
"lib/internal/tls/parse-cert-string.js",
"lib/internal/tls/secure-context.js",
"lib/internal/bootstrap/switches/is_not_main_thread.js",
"lib/internal/buffer.js",
"lib/internal/child_process.js",
"lib/internal/child_process/serialization.js",
"lib/internal/debugger/inspect_repl.js",
"lib/internal/debugger/inspect_client.js",
"lib/internal/cli_table.js",
"lib/internal/cluster/child.js",
"lib/internal/cluster/primary.js",
"lib/internal/cluster/round_robin_handle.js",
"lib/internal/cluster/shared_handle.js",
"lib/internal/cluster/utils.js",
"lib/internal/cluster/worker.js",
"lib/internal/console/constructor.js",
"lib/internal/console/global.js",
"lib/internal/constants.js",
"lib/internal/crypto/aes.js",
"lib/internal/crypto/certificate.js",
"lib/internal/crypto/cfrg.js",
"lib/internal/crypto/cipher.js",
"lib/internal/crypto/diffiehellman.js",
"lib/internal/crypto/ec.js",
"lib/internal/crypto/hash.js",
"lib/internal/crypto/hashnames.js",
"lib/internal/crypto/hkdf.js",
"lib/internal/crypto/keygen.js",
"lib/internal/crypto/keys.js",
"lib/internal/crypto/mac.js",
"lib/internal/crypto/pbkdf2.js",
"lib/internal/crypto/random.js",
"lib/internal/crypto/rsa.js",
"lib/internal/crypto/scrypt.js",
"lib/internal/crypto/sig.js",
"lib/internal/crypto/util.js",
"lib/internal/crypto/webcrypto.js",
"lib/internal/crypto/x509.js",
"lib/internal/debugger/inspect.js",
"lib/internal/worker/io.js",
"lib/internal/worker/js_transferable.js",
"lib/internal/main/repl.js",
"lib/internal/main/print_help.js",
"lib/internal/main/eval_string.js",
"lib/internal/main/check_syntax.js",
"lib/internal/main/prof_process.js",
"lib/internal/main/worker_thread.js",
"lib/internal/main/inspect.js",
"lib/internal/main/eval_stdin.js",
"lib/internal/main/run_main_module.js",
"lib/internal/modules/run_main.js",
"lib/internal/modules/package_json_reader.js",
"lib/internal/modules/esm/module_job.js",
"lib/internal/modules/esm/assert.js",
"lib/internal/modules/esm/fetch_module.js",
"lib/internal/modules/esm/get_source.js",
"lib/internal/modules/esm/translators.js",
"lib/internal/modules/esm/resolve.js",
"lib/internal/modules/esm/create_dynamic_module.js",
"lib/internal/modules/esm/load.js",
"lib/internal/modules/esm/handle_process_exit.js",
"lib/internal/modules/esm/initialize_import_meta.js",
"lib/internal/modules/esm/module_map.js",
"lib/internal/modules/esm/get_format.js",
"lib/internal/modules/esm/formats.js",
"lib/internal/modules/esm/loader.js",
"lib/internal/modules/cjs/helpers.js",
"lib/internal/modules/cjs/loader.js",
"lib/internal/source_map/source_map.js",
"lib/internal/source_map/prepare_stack_trace.js",
"lib/internal/source_map/source_map_cache.js",
"lib/internal/debugger/inspect_client.js",
"lib/internal/debugger/inspect_repl.js",
"lib/internal/dgram.js",
"lib/internal/dns/callback_resolver.js",
"lib/internal/dns/promises.js",
"lib/internal/dns/utils.js",
"lib/internal/fs/watchers.js",
"lib/internal/dtrace.js",
"lib/internal/encoding.js",
"lib/internal/error_serdes.js",
"lib/internal/errors.js",
"lib/internal/event_target.js",
"lib/internal/fixed_queue.js",
"lib/internal/freelist.js",
"lib/internal/freeze_intrinsics.js",
"lib/internal/fs/cp/cp-sync.js",
"lib/internal/fs/cp/cp.js",
"lib/internal/fs/dir.js",
"lib/internal/fs/promises.js",
"lib/internal/fs/read_file_context.js",
"lib/internal/fs/rimraf.js",
"lib/internal/fs/sync_write_stream.js",
"lib/internal/fs/dir.js",
"lib/internal/fs/streams.js",
"lib/internal/fs/sync_write_stream.js",
"lib/internal/fs/utils.js",
"lib/internal/fs/cp/cp.js",
"lib/internal/fs/cp/cp-sync.js",
"lib/internal/perf/nodetiming.js",
"lib/internal/perf/usertiming.js",
"lib/internal/perf/performance_entry.js",
"lib/internal/perf/performance.js",
"lib/internal/perf/timerify.js",
"lib/internal/perf/utils.js",
"lib/internal/perf/observe.js",
"lib/internal/fs/watchers.js",
"lib/internal/heap_utils.js",
"lib/internal/histogram.js",
"lib/internal/http.js",
"lib/internal/http2/compat.js",
"lib/internal/http2/core.js",
"lib/internal/http2/util.js",
"lib/internal/idna.js",
"lib/internal/inspector_async_hook.js",
"lib/internal/js_stream_socket.js",
"lib/internal/legacy/processbinding.js",
"lib/internal/linkedlist.js",
"lib/internal/main/check_syntax.js",
"lib/internal/main/environment.js",
"lib/internal/main/eval_stdin.js",
"lib/internal/main/eval_string.js",
"lib/internal/main/inspect.js",
"lib/internal/main/mksnapshot.js",
"lib/internal/main/print_help.js",
"lib/internal/main/prof_process.js",
"lib/internal/main/repl.js",
"lib/internal/main/run_main_module.js",
"lib/internal/main/test_runner.js",
"lib/internal/main/watch_mode.js",
"lib/internal/main/worker_thread.js",
"lib/internal/modules/cjs/helpers.js",
"lib/internal/modules/cjs/loader.js",
"lib/internal/modules/esm/assert.js",
"lib/internal/modules/esm/create_dynamic_module.js",
"lib/internal/modules/esm/fetch_module.js",
"lib/internal/modules/esm/formats.js",
"lib/internal/modules/esm/get_format.js",
"lib/internal/modules/esm/handle_process_exit.js",
"lib/internal/modules/esm/initialize_import_meta.js",
"lib/internal/modules/esm/load.js",
"lib/internal/modules/esm/loader.js",
"lib/internal/modules/esm/module_job.js",
"lib/internal/modules/esm/module_map.js",
"lib/internal/modules/esm/package_config.js",
"lib/internal/modules/esm/resolve.js",
"lib/internal/modules/esm/translators.js",
"lib/internal/modules/package_json_reader.js",
"lib/internal/modules/run_main.js",
"lib/internal/net.js",
"lib/internal/options.js",
"lib/internal/per_context/domexception.js",
"lib/internal/per_context/messageport.js",
"lib/internal/per_context/primordials.js",
"lib/internal/perf/event_loop_delay.js",
"lib/internal/perf/event_loop_utilization.js",
"lib/internal/perf/nodetiming.js",
"lib/internal/perf/observe.js",
"lib/internal/perf/performance.js",
"lib/internal/perf/performance_entry.js",
"lib/internal/perf/resource_timing.js",
"lib/internal/perf/timerify.js",
"lib/internal/perf/usertiming.js",
"lib/internal/perf/utils.js",
"lib/internal/policy/manifest.js",
"lib/internal/policy/sri.js",
"lib/internal/process/task_queues.js",
"lib/internal/process/per_thread.js",
"lib/internal/process/warning.js",
"lib/internal/process/policy.js",
"lib/internal/process/promises.js",
"lib/internal/process/signal.js",
"lib/internal/process/execution.js",
"lib/internal/priority_queue.js",
"lib/internal/process/esm_loader.js",
"lib/internal/process/execution.js",
"lib/internal/process/per_thread.js",
"lib/internal/process/policy.js",
"lib/internal/process/pre_execution.js",
"lib/internal/process/promises.js",
"lib/internal/process/report.js",
"lib/internal/process/signal.js",
"lib/internal/process/task_queues.js",
"lib/internal/process/warning.js",
"lib/internal/process/worker_thread_only.js",
"lib/internal/console/constructor.js",
"lib/internal/console/global.js",
"lib/assert/strict.js",
"lib/dns/promises.js",
"lib/fs/promises.js"
"lib/internal/promise_hooks.js",
"lib/internal/querystring.js",
"lib/internal/readline/callbacks.js",
"lib/internal/readline/emitKeypressEvents.js",
"lib/internal/readline/interface.js",
"lib/internal/readline/promises.js",
"lib/internal/readline/utils.js",
"lib/internal/repl.js",
"lib/internal/repl/await.js",
"lib/internal/repl/history.js",
"lib/internal/repl/utils.js",
"lib/internal/socket_list.js",
"lib/internal/socketaddress.js",
"lib/internal/source_map/prepare_stack_trace.js",
"lib/internal/source_map/source_map.js",
"lib/internal/source_map/source_map_cache.js",
"lib/internal/stream_base_commons.js",
"lib/internal/streams/add-abort-signal.js",
"lib/internal/streams/buffer_list.js",
"lib/internal/streams/compose.js",
"lib/internal/streams/destroy.js",
"lib/internal/streams/duplex.js",
"lib/internal/streams/duplexify.js",
"lib/internal/streams/end-of-stream.js",
"lib/internal/streams/from.js",
"lib/internal/streams/lazy_transform.js",
"lib/internal/streams/legacy.js",
"lib/internal/streams/operators.js",
"lib/internal/streams/passthrough.js",
"lib/internal/streams/pipeline.js",
"lib/internal/streams/readable.js",
"lib/internal/streams/state.js",
"lib/internal/streams/transform.js",
"lib/internal/streams/utils.js",
"lib/internal/streams/writable.js",
"lib/internal/structured_clone.js",
"lib/internal/test/binding.js",
"lib/internal/test/transfer.js",
"lib/internal/test_runner/harness.js",
"lib/internal/test_runner/runner.js",
"lib/internal/test_runner/tap_stream.js",
"lib/internal/test_runner/test.js",
"lib/internal/test_runner/utils.js",
"lib/internal/timers.js",
"lib/internal/tls/secure-context.js",
"lib/internal/tls/secure-pair.js",
"lib/internal/trace_events_async_hooks.js",
"lib/internal/tty.js",
"lib/internal/url.js",
"lib/internal/util.js",
"lib/internal/util/colors.js",
"lib/internal/util/comparisons.js",
"lib/internal/util/debuglog.js",
"lib/internal/util/inspect.js",
"lib/internal/util/inspector.js",
"lib/internal/util/iterable_weak_map.js",
"lib/internal/util/parse_args/parse_args.js",
"lib/internal/util/parse_args/utils.js",
"lib/internal/util/types.js",
"lib/internal/v8/startup_snapshot.js",
"lib/internal/v8_prof_polyfill.js",
"lib/internal/v8_prof_processor.js",
"lib/internal/validators.js",
"lib/internal/vm/module.js",
"lib/internal/wasm_web_api.js",
"lib/internal/watch_mode/files_watcher.js",
"lib/internal/watchdog.js",
"lib/internal/webstreams/adapters.js",
"lib/internal/webstreams/compression.js",
"lib/internal/webstreams/encoding.js",
"lib/internal/webstreams/queuingstrategies.js",
"lib/internal/webstreams/readablestream.js",
"lib/internal/webstreams/transfer.js",
"lib/internal/webstreams/transformstream.js",
"lib/internal/webstreams/util.js",
"lib/internal/webstreams/writablestream.js",
"lib/internal/worker.js",
"lib/internal/worker/io.js",
"lib/internal/worker/js_transferable.js",
"lib/module.js",
"lib/net.js",
"lib/os.js",
"lib/path.js",
"lib/path/posix.js",
"lib/path/win32.js",
"lib/perf_hooks.js",
"lib/process.js",
"lib/punycode.js",
"lib/querystring.js",
"lib/readline.js",
"lib/readline/promises.js",
"lib/repl.js",
"lib/stream.js",
"lib/stream/consumers.js",
"lib/stream/promises.js",
"lib/stream/web.js",
"lib/string_decoder.js",
"lib/sys.js",
"lib/test.js",
"lib/timers.js",
"lib/timers/promises.js",
"lib/tls.js",
"lib/trace_events.js",
"lib/tty.js",
"lib/url.js",
"lib/util.js",
"lib/util/types.js",
"lib/v8.js",
"lib/vm.js",
"lib/wasi.js",
"lib/worker_threads.js",
"lib/zlib.js"
],
"node_module_version": 93,
"node_module_version": 108,
"node_no_browser_globals": "false",
"node_prefix": "/",
"node_release_urlbase": "https://nodejs.org/download/release/",
@@ -330,20 +353,22 @@
"node_use_v8_platform": "true",
"node_with_ltcg": "false",
"node_without_node_options": "false",
"openssl_fips": "",
"openssl_is_fips": "false",
"openssl_quic": "true",
"ossfuzz": "false",
"shlib_suffix": "93.dylib",
"shlib_suffix": "108.dylib",
"target_arch": "x64",
"v8_enable_31bit_smis_on_64bit_arch": 0,
"v8_enable_gdbjit": 0,
"v8_enable_hugepage": 0,
"v8_enable_i18n_support": 1,
"v8_enable_inspector": 1,
"v8_enable_javascript_promise_hooks": 1,
"v8_enable_lite_mode": 0,
"v8_enable_object_print": 1,
"v8_enable_pointer_compression": 0,
"v8_enable_shared_ro_heap": 1,
"v8_enable_short_builtin_calls": 1,
"v8_enable_webassembly": 1,
"v8_no_strict_aliasing": 1,
"v8_optimized_debug": 1,
@@ -353,8 +378,8 @@
"v8_use_siphash": 1,
"want_separate_host_toolset": 0,
"xcode_version": "11.0",
"nodedir": "/Users/karolsojko/Library/Caches/node-gyp/16.15.1",
"nodedir": "/Users/karolsojko/Library/Caches/node-gyp/18.12.1",
"standalone_static_library": 1,
"user_agent": "yarn/3.2.1 npm/? node/v16.15.1 darwin x64"
"user_agent": "yarn/4.0.0-rc.25 npm/? node/v18.12.1 darwin x64"
}
}

View File

@@ -25,7 +25,7 @@ DEFS_Debug := \
CFLAGS_Debug := \
-O0 \
-gdwarf-2 \
-mmacosx-version-min=10.13 \
-mmacosx-version-min=10.15 \
-arch x86_64 \
-Wall \
-Wendif-labels \
@@ -38,7 +38,7 @@ CFLAGS_C_Debug := \
# Flags passed to only C++ files.
CFLAGS_CC_Debug := \
-std=gnu++14 \
-std=gnu++17 \
-stdlib=libc++ \
-fno-rtti \
-fno-exceptions \
@@ -51,13 +51,13 @@ CFLAGS_OBJC_Debug :=
CFLAGS_OBJCC_Debug :=
INCS_Debug := \
-I/Users/karolsojko/Library/Caches/node-gyp/16.15.1/include/node \
-I/Users/karolsojko/Library/Caches/node-gyp/16.15.1/src \
-I/Users/karolsojko/Library/Caches/node-gyp/16.15.1/deps/openssl/config \
-I/Users/karolsojko/Library/Caches/node-gyp/16.15.1/deps/openssl/openssl/include \
-I/Users/karolsojko/Library/Caches/node-gyp/16.15.1/deps/uv/include \
-I/Users/karolsojko/Library/Caches/node-gyp/16.15.1/deps/zlib \
-I/Users/karolsojko/Library/Caches/node-gyp/16.15.1/deps/v8/include \
-I/Users/karolsojko/Library/Caches/node-gyp/18.12.1/include/node \
-I/Users/karolsojko/Library/Caches/node-gyp/18.12.1/src \
-I/Users/karolsojko/Library/Caches/node-gyp/18.12.1/deps/openssl/config \
-I/Users/karolsojko/Library/Caches/node-gyp/18.12.1/deps/openssl/openssl/include \
-I/Users/karolsojko/Library/Caches/node-gyp/18.12.1/deps/uv/include \
-I/Users/karolsojko/Library/Caches/node-gyp/18.12.1/deps/zlib \
-I/Users/karolsojko/Library/Caches/node-gyp/18.12.1/deps/v8/include \
-I$(srcdir)/src \
-I$(srcdir)/../../../../nan-npm-2.16.0-cac314a230/node_modules/nan
@@ -81,7 +81,7 @@ DEFS_Release := \
CFLAGS_Release := \
-O3 \
-gdwarf-2 \
-mmacosx-version-min=10.13 \
-mmacosx-version-min=10.15 \
-arch x86_64 \
-Wall \
-Wendif-labels \
@@ -94,7 +94,7 @@ CFLAGS_C_Release := \
# Flags passed to only C++ files.
CFLAGS_CC_Release := \
-std=gnu++14 \
-std=gnu++17 \
-stdlib=libc++ \
-fno-rtti \
-fno-exceptions \
@@ -107,13 +107,13 @@ CFLAGS_OBJC_Release :=
CFLAGS_OBJCC_Release :=
INCS_Release := \
-I/Users/karolsojko/Library/Caches/node-gyp/16.15.1/include/node \
-I/Users/karolsojko/Library/Caches/node-gyp/16.15.1/src \
-I/Users/karolsojko/Library/Caches/node-gyp/16.15.1/deps/openssl/config \
-I/Users/karolsojko/Library/Caches/node-gyp/16.15.1/deps/openssl/openssl/include \
-I/Users/karolsojko/Library/Caches/node-gyp/16.15.1/deps/uv/include \
-I/Users/karolsojko/Library/Caches/node-gyp/16.15.1/deps/zlib \
-I/Users/karolsojko/Library/Caches/node-gyp/16.15.1/deps/v8/include \
-I/Users/karolsojko/Library/Caches/node-gyp/18.12.1/include/node \
-I/Users/karolsojko/Library/Caches/node-gyp/18.12.1/src \
-I/Users/karolsojko/Library/Caches/node-gyp/18.12.1/deps/openssl/config \
-I/Users/karolsojko/Library/Caches/node-gyp/18.12.1/deps/openssl/openssl/include \
-I/Users/karolsojko/Library/Caches/node-gyp/18.12.1/deps/uv/include \
-I/Users/karolsojko/Library/Caches/node-gyp/18.12.1/deps/zlib \
-I/Users/karolsojko/Library/Caches/node-gyp/18.12.1/deps/v8/include \
-I$(srcdir)/src \
-I$(srcdir)/../../../../nan-npm-2.16.0-cac314a230/node_modules/nan
@@ -151,7 +151,7 @@ $(obj).$(TOOLSET)/$(TARGET)/%.o: $(obj)/%.cpp FORCE_DO_CMD
LDFLAGS_Debug := \
-undefined dynamic_lookup \
-Wl,-search_paths_first \
-mmacosx-version-min=10.13 \
-mmacosx-version-min=10.15 \
-arch x86_64 \
-L$(builddir) \
-stdlib=libc++
@@ -163,7 +163,7 @@ LIBTOOLFLAGS_Debug := \
LDFLAGS_Release := \
-undefined dynamic_lookup \
-Wl,-search_paths_first \
-mmacosx-version-min=10.13 \
-mmacosx-version-min=10.15 \
-arch x86_64 \
-L$(builddir) \
-stdlib=libc++

View File

@@ -8,7 +8,7 @@
]
},
"engines": {
"node": ">=16.0.0 <17.0.0"
"node": ">=18.0.0 <19.0.0"
},
"scripts": {
"lint": "yarn workspaces foreach -p -j 10 --verbose run lint",
@@ -46,8 +46,8 @@
"@lerna-lite/list": "^1.5.1",
"@lerna-lite/run": "^1.5.1",
"@types/jest": "^29.1.1",
"@types/newrelic": "^7.0.3",
"@types/node": "^18.0.0",
"@types/newrelic": "^7.0.4",
"@types/node": "^18.11.9",
"@typescript-eslint/parser": "^5.40.1",
"eslint": "^8.17.0",
"eslint-config-prettier": "^8.5.0",
@@ -59,7 +59,8 @@
},
"packageManager": "yarn@4.0.0-rc.25",
"dependencies": {
"@sentry/node": "^7.3.0",
"newrelic": "^9.0.0"
"@newrelic/native-metrics": "^9.0.0",
"@sentry/node": "^7.19.0",
"newrelic": "^9.6.0"
}
}

View File

@@ -3,6 +3,120 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [2.9.9](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.9.6...@standardnotes/analytics@2.9.9) (2022-11-14)
### Bug Fixes
* **analytics:** bump version ([8715fe1](https://github.com/standardnotes/server/commit/8715fe182221f67f02b5f49e566366db3db581f4))
## [2.9.6](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.9.5...@standardnotes/analytics@2.9.6) (2022-11-14)
**Note:** Version bump only for package @standardnotes/analytics
## [2.9.5](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.9.4...@standardnotes/analytics@2.9.5) (2022-11-11)
**Note:** Version bump only for package @standardnotes/analytics
## [2.9.4](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.9.3...@standardnotes/analytics@2.9.4) (2022-11-11)
**Note:** Version bump only for package @standardnotes/analytics
## [2.9.3](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.9.2...@standardnotes/analytics@2.9.3) (2022-11-10)
### Bug Fixes
* **analytics:** add five year plans mrr calculation ([a03c5bc](https://github.com/standardnotes/server/commit/a03c5bceea2a9b166b1d5ad75181021462a86627))
## [2.9.2](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.9.1...@standardnotes/analytics@2.9.2) (2022-11-10)
### Bug Fixes
* **analytics:** add missing period for stats report ([9b593f2](https://github.com/standardnotes/server/commit/9b593f2a6b105ab8f9c7cef8bdda6892c42e20ef))
## [2.9.1](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.9.0...@standardnotes/analytics@2.9.1) (2022-11-10)
### Bug Fixes
* **analytics:** generate mrr stats for last 30 days including Today ([b92c4ae](https://github.com/standardnotes/server/commit/b92c4ae650b53db5c0bb2a9cf9afb01caeb8d822))
# [2.9.0](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.8.3...@standardnotes/analytics@2.9.0) (2022-11-10)
### Features
* **analytics:** add mrr for annual, monthly, pro and plus subscription plans ([ce3e259](https://github.com/standardnotes/server/commit/ce3e259bdedd10796fb4469f0eabd64bc326a115))
## [2.8.3](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.8.2...@standardnotes/analytics@2.8.3) (2022-11-10)
### Bug Fixes
* **analytics:** add subscription id to error logs ([81be065](https://github.com/standardnotes/server/commit/81be06598c918279f98a8ba6b59ea1b3803c949c))
## [2.8.2](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.8.1...@standardnotes/analytics@2.8.2) (2022-11-10)
### Bug Fixes
* **analytics:** add monthly mrr to the report ([fce47a0](https://github.com/standardnotes/server/commit/fce47a0a37a67b3edf3ea0b6ccda43c54dbd9870))
## [2.8.1](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.8.0...@standardnotes/analytics@2.8.1) (2022-11-10)
### Bug Fixes
* **analytics:** add persisting mrr for this month and this year as well ([8df0482](https://github.com/standardnotes/server/commit/8df0482eb4bfd63b9639fd786c9b6952ad7f801d))
# [2.8.0](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.7.3...@standardnotes/analytics@2.8.0) (2022-11-10)
### Features
* **analytics:** add calculating monthly recurring revenue ([77e5065](https://github.com/standardnotes/server/commit/77e50655f6fa7f9c28e13f8b8bc6de246c0454f0))
## [2.7.3](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.7.2...@standardnotes/analytics@2.7.3) (2022-11-10)
### Bug Fixes
* **analytics:** arhcitecture arrangements for use case execution ([7393954](https://github.com/standardnotes/server/commit/7393954ff6ece6143f7661104299172548db90ee))
## [2.7.2](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.7.1...@standardnotes/analytics@2.7.2) (2022-11-09)
### Bug Fixes
* **analytics:** mrr column types ([90aef90](https://github.com/standardnotes/server/commit/90aef905af05b8c1c86c7bd383df6b2b502f7c91))
## [2.7.1](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.7.0...@standardnotes/analytics@2.7.1) (2022-11-09)
### Bug Fixes
* **analytics:** add missing created at column ([89502be](https://github.com/standardnotes/server/commit/89502bed638b17301e42e0d5916635b0a59f585d))
# [2.7.0](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.6.0...@standardnotes/analytics@2.7.0) (2022-11-09)
### Features
* **analytics:** add saving revenue modifications upon subscription canceled ([52a257a](https://github.com/standardnotes/server/commit/52a257abb16034134a50474fbbb2493a00c58b99))
# [2.6.0](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.5.0...@standardnotes/analytics@2.6.0) (2022-11-09)
### Features
* **analytics:** add saving revenue modifications upon subscription refunded ([0f65c05](https://github.com/standardnotes/server/commit/0f65c051abcff805e920f91d338e5fadda7905a9))
# [2.5.0](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.4.0...@standardnotes/analytics@2.5.0) (2022-11-09)
### Features
* **analytics:** add saving revenue modifications upon subscription expired ([5c3db2c](https://github.com/standardnotes/server/commit/5c3db2cb29a929e44b63eb8226ce4ad1d14f8a99))
# [2.4.0](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.3.1...@standardnotes/analytics@2.4.0) (2022-11-09)
### Features
* **analytics:** add saving revenue modifications upon subscription renewed ([cdb7fcf](https://github.com/standardnotes/server/commit/cdb7fcf8311fecfabe3ef9eb656cd6ec57b87de0))
## [2.3.1](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.3.0...@standardnotes/analytics@2.3.1) (2022-11-09)
### Bug Fixes
* **analytics:** missing injectable annotation ([9d3ef24](https://github.com/standardnotes/server/commit/9d3ef24ba94ad28976a211d40f94f1bce8d0d305))
# [2.3.0](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.2.0...@standardnotes/analytics@2.3.0) (2022-11-09)
### Features

View File

@@ -1,4 +1,4 @@
FROM node:16.15.1-alpine
FROM node:18.12.1-alpine
RUN apk add --update \
curl \

View File

@@ -15,6 +15,7 @@ import { ContainerConfigLoader } from '../src/Bootstrap/Container'
import TYPES from '../src/Bootstrap/Types'
import { Env } from '../src/Bootstrap/Env'
import { DomainEventFactoryInterface } from '../src/Domain/Event/DomainEventFactoryInterface'
import { CalculateMonthlyRecurringRevenue } from '../src/Domain/UseCase/CalculateMonthlyRecurringRevenue/CalculateMonthlyRecurringRevenue'
const requestReport = async (
analyticsStore: AnalyticsStoreInterface,
@@ -22,7 +23,10 @@ const requestReport = async (
domainEventFactory: DomainEventFactoryInterface,
domainEventPublisher: DomainEventPublisherInterface,
periodKeyGenerator: PeriodKeyGeneratorInterface,
calculateMonthlyRecurringRevenue: CalculateMonthlyRecurringRevenue,
): Promise<void> => {
await calculateMonthlyRecurringRevenue.execute({})
const analyticsOverTime: Array<{
name: string
period: number
@@ -96,6 +100,40 @@ const requestReport = async (
})
}
const statisticsOverTime: Array<{
name: string
period: number
counts: Array<{
periodKey: string
totalCount: number
}>
}> = []
const thirtyDaysStatisticsNames = [
StatisticsMeasure.MRR,
StatisticsMeasure.AnnualPlansMRR,
StatisticsMeasure.MonthlyPlansMRR,
StatisticsMeasure.FiveYearPlansMRR,
StatisticsMeasure.PlusPlansMRR,
StatisticsMeasure.ProPlansMRR,
]
for (const statisticName of thirtyDaysStatisticsNames) {
statisticsOverTime.push({
name: statisticName,
period: Period.Last30DaysIncludingToday,
counts: await statisticsStore.calculateTotalCountOverPeriod(statisticName, Period.Last30DaysIncludingToday),
})
}
const monthlyStatisticsNames = [StatisticsMeasure.MRR]
for (const statisticName of monthlyStatisticsNames) {
statisticsOverTime.push({
name: statisticName,
period: Period.ThisYear,
counts: await statisticsStore.calculateTotalCountOverPeriod(statisticName, Period.ThisYear),
})
}
const statisticMeasureNames = [
StatisticsMeasure.Income,
StatisticsMeasure.PlusSubscriptionInitialAnnualPaymentsIncome,
@@ -170,13 +208,10 @@ const requestReport = async (
}
const event = domainEventFactory.createDailyAnalyticsReportGeneratedEvent({
applicationStatistics: await statisticsStore.getYesterdayApplicationUsage(),
snjsStatistics: await statisticsStore.getYesterdaySNJSUsage(),
outOfSyncIncidents: await statisticsStore.getYesterdayOutOfSyncIncidents(),
activityStatistics: yesterdayActivityStatistics,
activityStatisticsOverTime: analyticsOverTime,
statisticsOverTime,
statisticMeasures,
retentionStatistics: [],
churn: {
periodKeys: monthlyPeriodKeys,
values: churnRates,
@@ -200,9 +235,19 @@ void container.load().then((container) => {
const domainEventFactory: DomainEventFactoryInterface = container.get(TYPES.DomainEventFactory)
const domainEventPublisher: DomainEventPublisherInterface = container.get(TYPES.DomainEventPublisher)
const periodKeyGenerator: PeriodKeyGeneratorInterface = container.get(TYPES.PeriodKeyGenerator)
const calculateMonthlyRecurringRevenue: CalculateMonthlyRecurringRevenue = container.get(
TYPES.CalculateMonthlyRecurringRevenue,
)
Promise.resolve(
requestReport(analyticsStore, statisticsStore, domainEventFactory, domainEventPublisher, periodKeyGenerator),
requestReport(
analyticsStore,
statisticsStore,
domainEventFactory,
domainEventPublisher,
periodKeyGenerator,
calculateMonthlyRecurringRevenue,
),
)
.then(() => {
logger.info('Usage report generation complete')

View File

@@ -0,0 +1,13 @@
import { MigrationInterface, QueryRunner } from 'typeorm'
export class addMissingCreatedAt1667994036734 implements MigrationInterface {
name = 'addMissingCreatedAt1667994036734'
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query('ALTER TABLE `revenue_modifications` ADD `created_at` bigint NOT NULL')
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query('ALTER TABLE `revenue_modifications` DROP COLUMN `created_at`')
}
}

View File

@@ -0,0 +1,19 @@
import { MigrationInterface, QueryRunner } from 'typeorm'
export class fixMrrFloatingColumns1667995681714 implements MigrationInterface {
name = 'fixMrrFloatingColumns1667995681714'
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query('ALTER TABLE `revenue_modifications` DROP COLUMN `previous_mrr`')
await queryRunner.query('ALTER TABLE `revenue_modifications` ADD `previous_mrr` float NOT NULL')
await queryRunner.query('ALTER TABLE `revenue_modifications` DROP COLUMN `new_mrr`')
await queryRunner.query('ALTER TABLE `revenue_modifications` ADD `new_mrr` float NOT NULL')
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query('ALTER TABLE `revenue_modifications` DROP COLUMN `new_mrr`')
await queryRunner.query('ALTER TABLE `revenue_modifications` ADD `new_mrr` int NOT NULL')
await queryRunner.query('ALTER TABLE `revenue_modifications` DROP COLUMN `previous_mrr`')
await queryRunner.query('ALTER TABLE `revenue_modifications` ADD `previous_mrr` int NOT NULL')
}
}

View File

@@ -1,8 +1,8 @@
{
"name": "@standardnotes/analytics",
"version": "2.3.0",
"version": "2.9.9",
"engines": {
"node": ">=14.0.0 <17.0.0"
"node": ">=18.0.0 <19.0.0"
},
"private": true,
"description": "Analytics tools for Standard Notes projects",
@@ -25,10 +25,10 @@
"typeorm": "typeorm-ts-node-commonjs"
},
"devDependencies": {
"@types/ioredis": "^4.28.10",
"@types/ioredis": "^5.0.0",
"@types/jest": "^29.1.1",
"@types/newrelic": "^7.0.3",
"@types/node": "^18.0.0",
"@types/newrelic": "^7.0.4",
"@types/node": "^18.11.9",
"@types/uuid": "^8.3.0",
"@typescript-eslint/eslint-plugin": "^5.30.0",
"eslint": "^8.14.0",
@@ -38,22 +38,23 @@
"typescript": "^4.8.4"
},
"dependencies": {
"@newrelic/native-metrics": "^9.0.0",
"@newrelic/winston-enricher": "^4.0.0",
"@sentry/node": "^7.3.0",
"@sentry/node": "^7.19.0",
"@standardnotes/common": "workspace:*",
"@standardnotes/domain-events": "workspace:*",
"@standardnotes/domain-events-infra": "workspace:*",
"@standardnotes/time": "workspace:*",
"aws-sdk": "^2.1158.0",
"aws-sdk": "^2.1253.0",
"dayjs": "^1.11.6",
"dotenv": "^16.0.1",
"inversify": "^6.0.1",
"ioredis": "^5.2.3",
"ioredis": "^5.2.4",
"mysql2": "^2.3.3",
"newrelic": "^9.0.0",
"newrelic": "^9.6.0",
"reflect-metadata": "^0.1.13",
"shallow-equal-object": "^1.1.1",
"typeorm": "^0.3.6",
"typeorm": "^0.3.10",
"uuid": "^9.0.0",
"winston": "^3.8.1"
}

View File

@@ -51,6 +51,7 @@ import { MapInterface } from '../Domain/Map/MapInterface'
import { RevenueModification } from '../Domain/Revenue/RevenueModification'
import { RevenueModificationMap } from '../Domain/Map/RevenueModificationMap'
import { SaveRevenueModification } from '../Domain/UseCase/SaveRevenueModification/SaveRevenueModification'
import { CalculateMonthlyRecurringRevenue } from '../Domain/UseCase/CalculateMonthlyRecurringRevenue/CalculateMonthlyRecurringRevenue'
// eslint-disable-next-line @typescript-eslint/no-var-requires
const newrelicFormatter = require('@newrelic/winston-enricher')
@@ -138,6 +139,9 @@ export class ContainerConfigLoader {
// Use Case
container.bind<GetUserAnalyticsId>(TYPES.GetUserAnalyticsId).to(GetUserAnalyticsId)
container.bind<SaveRevenueModification>(TYPES.SaveRevenueModification).to(SaveRevenueModification)
container
.bind<CalculateMonthlyRecurringRevenue>(TYPES.CalculateMonthlyRecurringRevenue)
.to(CalculateMonthlyRecurringRevenue)
// Hanlders
container.bind<UserRegisteredEventHandler>(TYPES.UserRegisteredEventHandler).to(UserRegisteredEventHandler)

View File

@@ -20,6 +20,7 @@ const TYPES = {
// Use Case
GetUserAnalyticsId: Symbol.for('GetUserAnalyticsId'),
SaveRevenueModification: Symbol.for('SaveRevenueModification'),
CalculateMonthlyRecurringRevenue: Symbol.for('CalculateMonthlyRecurringRevenue'),
// Handlers
UserRegisteredEventHandler: Symbol.for('UserRegisteredEventHandler'),
AccountDeletionRequestedEventHandler: Symbol.for('AccountDeletionRequestedEventHandler'),

View File

@@ -1,7 +1,7 @@
/* istanbul ignore file */
export class Result<T> {
constructor(private isSuccess: boolean, private error?: T | string, private value?: T) {
constructor(private isSuccess: boolean, private error?: string, private value?: T) {
Object.freeze(this)
}
@@ -11,13 +11,13 @@ export class Result<T> {
getValue(): T {
if (!this.isSuccess) {
throw new Error('Cannot get value of an unsuccessfull result')
throw new Error(`Cannot get value of an unsuccessfull result: ${this.error}`)
}
return this.value as T
}
getError(): T | string {
getError(): string {
if (this.isSuccess || this.error === undefined) {
throw new Error('Cannot get an error of a successfull result')
}
@@ -29,7 +29,7 @@ export class Result<T> {
return new Result<U>(true, undefined, value)
}
static fail<U>(error: U | string): Result<U> {
static fail<U>(error: string): Result<U> {
return new Result<U>(false, error)
}
}

View File

@@ -22,18 +22,6 @@ describe('DomainEventFactory', () => {
it('should create a DAILY_ANALYTICS_REPORT_GENERATED event', () => {
expect(
createFactory().createDailyAnalyticsReportGeneratedEvent({
snjsStatistics: [
{
version: '1-2-3',
count: 2,
},
],
applicationStatistics: [
{
version: '2-3-4',
count: 45,
},
],
activityStatistics: [
{
name: AnalyticsActivity.Register,
@@ -63,8 +51,18 @@ describe('DomainEventFactory', () => {
totalCount: 123,
},
],
outOfSyncIncidents: 324,
retentionStatistics: [],
statisticsOverTime: [
{
name: StatisticsMeasure.MRR,
period: Period.Last30Days,
counts: [
{
periodKey: '2022-10-9',
totalCount: 3,
},
],
},
],
churn: {
periodKeys: ['2022-10-9'],
values: [
@@ -105,10 +103,16 @@ describe('DomainEventFactory', () => {
totalCount: 123,
},
],
applicationStatistics: [
statisticsOverTime: [
{
count: 45,
version: '2-3-4',
counts: [
{
periodKey: '2022-10-9',
totalCount: 3,
},
],
name: 'mrr',
period: 9,
},
],
churn: {
@@ -120,14 +124,6 @@ describe('DomainEventFactory', () => {
},
],
},
outOfSyncIncidents: 324,
retentionStatistics: [],
snjsStatistics: [
{
count: 2,
version: '1-2-3',
},
],
statisticMeasures: [
{
average: 23,

View File

@@ -9,14 +9,6 @@ export class DomainEventFactory implements DomainEventFactoryInterface {
constructor(@inject(TYPES.Timer) private timer: TimerInterface) {}
createDailyAnalyticsReportGeneratedEvent(dto: {
snjsStatistics: Array<{
version: string
count: number
}>
applicationStatistics: Array<{
version: string
count: number
}>
activityStatistics: Array<{
name: string
retention: number
@@ -38,18 +30,13 @@ export class DomainEventFactory implements DomainEventFactoryInterface {
}>
totalCount: number
}>
outOfSyncIncidents: number
retentionStatistics: Array<{
firstActivity: string
secondActivity: string
retention: {
periodKeys: Array<string>
values: Array<{
firstPeriodKey: string
secondPeriodKey: string
value: number
}>
}
statisticsOverTime: Array<{
name: string
period: number
counts: Array<{
periodKey: string
totalCount: number
}>
}>
churn: {
periodKeys: Array<string>

View File

@@ -2,14 +2,6 @@ import { DailyAnalyticsReportGeneratedEvent } from '@standardnotes/domain-events
export interface DomainEventFactoryInterface {
createDailyAnalyticsReportGeneratedEvent(dto: {
snjsStatistics: Array<{
version: string
count: number
}>
applicationStatistics: Array<{
version: string
count: number
}>
activityStatistics: Array<{
name: string
retention: number
@@ -31,18 +23,13 @@ export interface DomainEventFactoryInterface {
}>
totalCount: number
}>
outOfSyncIncidents: number
retentionStatistics: Array<{
firstActivity: string
secondActivity: string
retention: {
periodKeys: Array<string>
values: Array<{
firstPeriodKey: string
secondPeriodKey: string
value: number
}>
}
statisticsOverTime: Array<{
name: string
period: number
counts: Array<{
periodKey: string
totalCount: number
}>
}>
churn: {
periodKeys: Array<string>

View File

@@ -9,16 +9,32 @@ import { AnalyticsStoreInterface } from '../Analytics/AnalyticsStoreInterface'
import { StatisticsMeasure } from '../Statistics/StatisticsMeasure'
import { StatisticsStoreInterface } from '../Statistics/StatisticsStoreInterface'
import { Period } from '../Time/Period'
import { Result } from '../Core/Result'
import { RevenueModification } from '../Revenue/RevenueModification'
import { SaveRevenueModification } from '../UseCase/SaveRevenueModification/SaveRevenueModification'
import { Logger } from 'winston'
describe('SubscriptionCancelledEventHandler', () => {
let event: SubscriptionCancelledEvent
let getUserAnalyticsId: GetUserAnalyticsId
let analyticsStore: AnalyticsStoreInterface
let statisticsStore: StatisticsStoreInterface
let saveRevenueModification: SaveRevenueModification
let logger: Logger
const createHandler = () => new SubscriptionCancelledEventHandler(getUserAnalyticsId, analyticsStore, statisticsStore)
const createHandler = () =>
new SubscriptionCancelledEventHandler(
getUserAnalyticsId,
analyticsStore,
statisticsStore,
saveRevenueModification,
logger,
)
beforeEach(() => {
logger = {} as jest.Mocked<Logger>
logger.error = jest.fn()
getUserAnalyticsId = {} as jest.Mocked<GetUserAnalyticsId>
getUserAnalyticsId.execute = jest.fn().mockReturnValue({ analyticsId: 3 })
@@ -30,6 +46,7 @@ describe('SubscriptionCancelledEventHandler', () => {
event = {} as jest.Mocked<SubscriptionCancelledEvent>
event.createdAt = new Date(1)
event.type = 'SUBSCRIPTION_CANCELLED'
event.payload = {
subscriptionId: 1,
userEmail: 'test@test.com',
@@ -41,7 +58,13 @@ describe('SubscriptionCancelledEventHandler', () => {
timestamp: 1,
offline: false,
replaced: false,
userExistingSubscriptionsCount: 1,
billingFrequency: 1,
payAmount: 12.99,
}
saveRevenueModification = {} as jest.Mocked<SaveRevenueModification>
saveRevenueModification.execute = jest.fn().mockReturnValue(Result.ok<RevenueModification>())
})
it('should track subscription cancelled statistics', async () => {
@@ -55,6 +78,7 @@ describe('SubscriptionCancelledEventHandler', () => {
Period.ThisWeek,
Period.ThisMonth,
])
expect(saveRevenueModification.execute).toHaveBeenCalled()
})
it('should not track statistics for subscriptions that are in a legacy 5 year plan', async () => {
@@ -65,5 +89,16 @@ describe('SubscriptionCancelledEventHandler', () => {
await createHandler().handle(event)
expect(statisticsStore.incrementMeasure).not.toHaveBeenCalled()
expect(saveRevenueModification.execute).toHaveBeenCalled()
})
it('should log failure to save revenue modification', async () => {
saveRevenueModification.execute = jest.fn().mockReturnValue(Result.fail('Oops'))
event.payload.timestamp = 1642395451516000
await createHandler().handle(event)
expect(logger.error).toHaveBeenCalled()
})
})

View File

@@ -1,13 +1,18 @@
import { DomainEventHandlerInterface, SubscriptionCancelledEvent } from '@standardnotes/domain-events'
import { inject, injectable } from 'inversify'
import { Logger } from 'winston'
import TYPES from '../../Bootstrap/Types'
import { AnalyticsActivity } from '../Analytics/AnalyticsActivity'
import { AnalyticsStoreInterface } from '../Analytics/AnalyticsStoreInterface'
import { Email } from '../Common/Email'
import { StatisticsMeasure } from '../Statistics/StatisticsMeasure'
import { StatisticsStoreInterface } from '../Statistics/StatisticsStoreInterface'
import { SubscriptionEventType } from '../Subscription/SubscriptionEventType'
import { SubscriptionPlanName } from '../Subscription/SubscriptionPlanName'
import { Period } from '../Time/Period'
import { GetUserAnalyticsId } from '../UseCase/GetUserAnalyticsId/GetUserAnalyticsId'
import { SaveRevenueModification } from '../UseCase/SaveRevenueModification/SaveRevenueModification'
@injectable()
export class SubscriptionCancelledEventHandler implements DomainEventHandlerInterface {
@@ -15,10 +20,12 @@ export class SubscriptionCancelledEventHandler implements DomainEventHandlerInte
@inject(TYPES.GetUserAnalyticsId) private getUserAnalyticsId: GetUserAnalyticsId,
@inject(TYPES.AnalyticsStore) private analyticsStore: AnalyticsStoreInterface,
@inject(TYPES.StatisticsStore) private statisticsStore: StatisticsStoreInterface,
@inject(TYPES.SaveRevenueModification) private saveRevenueModification: SaveRevenueModification,
@inject(TYPES.Logger) private logger: Logger,
) {}
async handle(event: SubscriptionCancelledEvent): Promise<void> {
const { analyticsId } = await this.getUserAnalyticsId.execute({ userEmail: event.payload.userEmail })
const { analyticsId, userUuid } = await this.getUserAnalyticsId.execute({ userEmail: event.payload.userEmail })
await this.analyticsStore.markActivity([AnalyticsActivity.SubscriptionCancelled], analyticsId, [
Period.Today,
Period.ThisWeek,
@@ -26,6 +33,23 @@ export class SubscriptionCancelledEventHandler implements DomainEventHandlerInte
])
await this.trackSubscriptionStatistics(event)
const result = await this.saveRevenueModification.execute({
billingFrequency: event.payload.billingFrequency,
eventType: SubscriptionEventType.create(event.type).getValue(),
newSubscriber: event.payload.userExistingSubscriptionsCount === 1,
payedAmount: event.payload.payAmount,
planName: SubscriptionPlanName.create(event.payload.subscriptionName).getValue(),
subscriptionId: event.payload.subscriptionId,
userEmail: Email.create(event.payload.userEmail).getValue(),
userUuid,
})
if (result.isFailed()) {
this.logger.error(
`[${event.type}][${event.payload.subscriptionId}] Could not save revenue modification: ${result.getError()}`,
)
}
}
private async trackSubscriptionStatistics(event: SubscriptionCancelledEvent) {

View File

@@ -7,18 +7,35 @@ import { SubscriptionExpiredEventHandler } from './SubscriptionExpiredEventHandl
import { GetUserAnalyticsId } from '../UseCase/GetUserAnalyticsId/GetUserAnalyticsId'
import { StatisticsStoreInterface } from '../Statistics/StatisticsStoreInterface'
import { AnalyticsStoreInterface } from '../Analytics/AnalyticsStoreInterface'
import { SaveRevenueModification } from '../UseCase/SaveRevenueModification/SaveRevenueModification'
import { Result } from '../Core/Result'
import { RevenueModification } from '../Revenue/RevenueModification'
import { Logger } from 'winston'
describe('SubscriptionExpiredEventHandler', () => {
let event: SubscriptionExpiredEvent
let getUserAnalyticsId: GetUserAnalyticsId
let analyticsStore: AnalyticsStoreInterface
let statisticsStore: StatisticsStoreInterface
let saveRevenueModification: SaveRevenueModification
let logger: Logger
const createHandler = () => new SubscriptionExpiredEventHandler(getUserAnalyticsId, analyticsStore, statisticsStore)
const createHandler = () =>
new SubscriptionExpiredEventHandler(
getUserAnalyticsId,
analyticsStore,
statisticsStore,
saveRevenueModification,
logger,
)
beforeEach(() => {
logger = {} as jest.Mocked<Logger>
logger.error = jest.fn()
event = {} as jest.Mocked<SubscriptionExpiredEvent>
event.createdAt = new Date(1)
event.type = 'SUBSCRIPTION_EXPIRED'
event.payload = {
subscriptionId: 1,
userEmail: 'test@test.com',
@@ -26,6 +43,9 @@ describe('SubscriptionExpiredEventHandler', () => {
timestamp: 1,
offline: false,
totalActiveSubscriptionsCount: 123,
userExistingSubscriptionsCount: 2,
billingFrequency: 1,
payAmount: 12.99,
}
getUserAnalyticsId = {} as jest.Mocked<GetUserAnalyticsId>
@@ -36,6 +56,9 @@ describe('SubscriptionExpiredEventHandler', () => {
statisticsStore = {} as jest.Mocked<StatisticsStoreInterface>
statisticsStore.setMeasure = jest.fn()
saveRevenueModification = {} as jest.Mocked<SaveRevenueModification>
saveRevenueModification.execute = jest.fn().mockReturnValue(Result.ok<RevenueModification>())
})
it('should update analytics and statistics', async () => {
@@ -43,5 +66,14 @@ describe('SubscriptionExpiredEventHandler', () => {
expect(analyticsStore.markActivity).toHaveBeenCalled()
expect(statisticsStore.setMeasure).toHaveBeenCalled()
expect(saveRevenueModification.execute).toHaveBeenCalled()
})
it('should log failure to save revenue modification', async () => {
saveRevenueModification.execute = jest.fn().mockReturnValue(Result.fail('Oops'))
await createHandler().handle(event)
expect(logger.error).toHaveBeenCalled()
})
})

View File

@@ -1,13 +1,18 @@
import { DomainEventHandlerInterface, SubscriptionExpiredEvent } from '@standardnotes/domain-events'
import { inject, injectable } from 'inversify'
import { Logger } from 'winston'
import TYPES from '../../Bootstrap/Types'
import { AnalyticsActivity } from '../Analytics/AnalyticsActivity'
import { AnalyticsStoreInterface } from '../Analytics/AnalyticsStoreInterface'
import { Email } from '../Common/Email'
import { StatisticsMeasure } from '../Statistics/StatisticsMeasure'
import { StatisticsStoreInterface } from '../Statistics/StatisticsStoreInterface'
import { SubscriptionEventType } from '../Subscription/SubscriptionEventType'
import { SubscriptionPlanName } from '../Subscription/SubscriptionPlanName'
import { Period } from '../Time/Period'
import { GetUserAnalyticsId } from '../UseCase/GetUserAnalyticsId/GetUserAnalyticsId'
import { SaveRevenueModification } from '../UseCase/SaveRevenueModification/SaveRevenueModification'
@injectable()
export class SubscriptionExpiredEventHandler implements DomainEventHandlerInterface {
@@ -15,10 +20,12 @@ export class SubscriptionExpiredEventHandler implements DomainEventHandlerInterf
@inject(TYPES.GetUserAnalyticsId) private getUserAnalyticsId: GetUserAnalyticsId,
@inject(TYPES.AnalyticsStore) private analyticsStore: AnalyticsStoreInterface,
@inject(TYPES.StatisticsStore) private statisticsStore: StatisticsStoreInterface,
@inject(TYPES.SaveRevenueModification) private saveRevenueModification: SaveRevenueModification,
@inject(TYPES.Logger) private logger: Logger,
) {}
async handle(event: SubscriptionExpiredEvent): Promise<void> {
const { analyticsId } = await this.getUserAnalyticsId.execute({ userEmail: event.payload.userEmail })
const { analyticsId, userUuid } = await this.getUserAnalyticsId.execute({ userEmail: event.payload.userEmail })
await this.analyticsStore.markActivity(
[AnalyticsActivity.SubscriptionExpired, AnalyticsActivity.ExistingCustomersChurn],
analyticsId,
@@ -30,5 +37,22 @@ export class SubscriptionExpiredEventHandler implements DomainEventHandlerInterf
event.payload.totalActiveSubscriptionsCount,
[Period.Today, Period.ThisWeek, Period.ThisMonth, Period.ThisYear],
)
const result = await this.saveRevenueModification.execute({
billingFrequency: event.payload.billingFrequency,
eventType: SubscriptionEventType.create(event.type).getValue(),
newSubscriber: event.payload.userExistingSubscriptionsCount === 1,
payedAmount: event.payload.payAmount,
planName: SubscriptionPlanName.create(event.payload.subscriptionName).getValue(),
subscriptionId: event.payload.subscriptionId,
userEmail: Email.create(event.payload.userEmail).getValue(),
userUuid,
})
if (result.isFailed()) {
this.logger.error(
`[${event.type}][${event.payload.subscriptionId}] Could not save revenue modification: ${result.getError()}`,
)
}
}
}

View File

@@ -11,6 +11,7 @@ import { Period } from '../Time/Period'
import { SaveRevenueModification } from '../UseCase/SaveRevenueModification/SaveRevenueModification'
import { Result } from '../Core/Result'
import { RevenueModification } from '../Revenue/RevenueModification'
import { Logger } from 'winston'
describe('SubscriptionPurchasedEventHandler', () => {
let event: SubscriptionPurchasedEvent
@@ -19,11 +20,21 @@ describe('SubscriptionPurchasedEventHandler', () => {
let analyticsStore: AnalyticsStoreInterface
let statisticsStore: StatisticsStoreInterface
let saveRevenueModification: SaveRevenueModification
let logger: Logger
const createHandler = () =>
new SubscriptionPurchasedEventHandler(getUserAnalyticsId, analyticsStore, statisticsStore, saveRevenueModification)
new SubscriptionPurchasedEventHandler(
getUserAnalyticsId,
analyticsStore,
statisticsStore,
saveRevenueModification,
logger,
)
beforeEach(() => {
logger = {} as jest.Mocked<Logger>
logger.error = jest.fn()
statisticsStore = {} as jest.Mocked<StatisticsStoreInterface>
statisticsStore.incrementMeasure = jest.fn()
statisticsStore.setMeasure = jest.fn()
@@ -80,4 +91,12 @@ describe('SubscriptionPurchasedEventHandler', () => {
expect(analyticsStore.markActivity).toHaveBeenCalledWith(['limited-discount-offer-purchased'], 3, [Period.Today])
})
it('should log failure to save revenue modification', async () => {
saveRevenueModification.execute = jest.fn().mockReturnValue(Result.fail('Oops'))
await createHandler().handle(event)
expect(logger.error).toHaveBeenCalled()
})
})

View File

@@ -1,5 +1,6 @@
import { DomainEventHandlerInterface, SubscriptionPurchasedEvent } from '@standardnotes/domain-events'
import { inject, injectable } from 'inversify'
import { Logger } from 'winston'
import TYPES from '../../Bootstrap/Types'
import { AnalyticsActivity } from '../Analytics/AnalyticsActivity'
@@ -20,6 +21,7 @@ export class SubscriptionPurchasedEventHandler implements DomainEventHandlerInte
@inject(TYPES.AnalyticsStore) private analyticsStore: AnalyticsStoreInterface,
@inject(TYPES.StatisticsStore) private statisticsStore: StatisticsStoreInterface,
@inject(TYPES.SaveRevenueModification) private saveRevenueModification: SaveRevenueModification,
@inject(TYPES.Logger) private logger: Logger,
) {}
async handle(event: SubscriptionPurchasedEvent): Promise<void> {
@@ -60,7 +62,7 @@ export class SubscriptionPurchasedEventHandler implements DomainEventHandlerInte
)
}
await this.saveRevenueModification.execute({
const result = await this.saveRevenueModification.execute({
billingFrequency: event.payload.billingFrequency,
eventType: SubscriptionEventType.create(event.type).getValue(),
newSubscriber: event.payload.newSubscriber,
@@ -70,5 +72,11 @@ export class SubscriptionPurchasedEventHandler implements DomainEventHandlerInte
userEmail: Email.create(event.payload.userEmail).getValue(),
userUuid,
})
if (result.isFailed()) {
this.logger.error(
`[${event.type}][${event.payload.subscriptionId}] Could not save revenue modification: ${result.getError()}`,
)
}
}
}

View File

@@ -10,18 +10,35 @@ import { SubscriptionRefundedEventHandler } from './SubscriptionRefundedEventHan
import { StatisticsStoreInterface } from '../Statistics/StatisticsStoreInterface'
import { AnalyticsActivity } from '../Analytics/AnalyticsActivity'
import { Period } from '../Time/Period'
import { Result } from '../Core/Result'
import { RevenueModification } from '../Revenue/RevenueModification'
import { SaveRevenueModification } from '../UseCase/SaveRevenueModification/SaveRevenueModification'
import { Logger } from 'winston'
describe('SubscriptionRefundedEventHandler', () => {
let event: SubscriptionRefundedEvent
let getUserAnalyticsId: GetUserAnalyticsId
let analyticsStore: AnalyticsStoreInterface
let statisticsStore: StatisticsStoreInterface
let saveRevenueModification: SaveRevenueModification
let logger: Logger
const createHandler = () => new SubscriptionRefundedEventHandler(getUserAnalyticsId, analyticsStore, statisticsStore)
const createHandler = () =>
new SubscriptionRefundedEventHandler(
getUserAnalyticsId,
analyticsStore,
statisticsStore,
saveRevenueModification,
logger,
)
beforeEach(() => {
logger = {} as jest.Mocked<Logger>
logger.error = jest.fn()
event = {} as jest.Mocked<SubscriptionRefundedEvent>
event.createdAt = new Date(1)
event.type = 'SUBSCRIPTION_REFUNDED'
event.payload = {
subscriptionId: 1,
userEmail: 'test@test.com',
@@ -30,6 +47,8 @@ describe('SubscriptionRefundedEventHandler', () => {
offline: false,
userExistingSubscriptionsCount: 3,
totalActiveSubscriptionsCount: 1,
billingFrequency: 1,
payAmount: 12.99,
}
getUserAnalyticsId = {} as jest.Mocked<GetUserAnalyticsId>
@@ -41,6 +60,9 @@ describe('SubscriptionRefundedEventHandler', () => {
statisticsStore = {} as jest.Mocked<StatisticsStoreInterface>
statisticsStore.setMeasure = jest.fn()
saveRevenueModification = {} as jest.Mocked<SaveRevenueModification>
saveRevenueModification.execute = jest.fn().mockReturnValue(Result.ok<RevenueModification>())
})
it('should mark churn for new customer', async () => {
@@ -56,6 +78,8 @@ describe('SubscriptionRefundedEventHandler', () => {
expect(analyticsStore.markActivity).toHaveBeenCalledWith([AnalyticsActivity.NewCustomersChurn], 3, [
Period.ThisMonth,
])
expect(saveRevenueModification.execute).toHaveBeenCalled()
})
it('should mark churn for existing customer', async () => {
@@ -75,4 +99,12 @@ describe('SubscriptionRefundedEventHandler', () => {
Period.ThisMonth,
])
})
it('should log failure to save revenue modification', async () => {
saveRevenueModification.execute = jest.fn().mockReturnValue(Result.fail('Oops'))
await createHandler().handle(event)
expect(logger.error).toHaveBeenCalled()
})
})

View File

@@ -1,13 +1,18 @@
import { DomainEventHandlerInterface, SubscriptionRefundedEvent } from '@standardnotes/domain-events'
import { inject, injectable } from 'inversify'
import { Logger } from 'winston'
import TYPES from '../../Bootstrap/Types'
import { AnalyticsActivity } from '../Analytics/AnalyticsActivity'
import { AnalyticsStoreInterface } from '../Analytics/AnalyticsStoreInterface'
import { Email } from '../Common/Email'
import { StatisticsMeasure } from '../Statistics/StatisticsMeasure'
import { StatisticsStoreInterface } from '../Statistics/StatisticsStoreInterface'
import { SubscriptionEventType } from '../Subscription/SubscriptionEventType'
import { SubscriptionPlanName } from '../Subscription/SubscriptionPlanName'
import { Period } from '../Time/Period'
import { GetUserAnalyticsId } from '../UseCase/GetUserAnalyticsId/GetUserAnalyticsId'
import { SaveRevenueModification } from '../UseCase/SaveRevenueModification/SaveRevenueModification'
@injectable()
export class SubscriptionRefundedEventHandler implements DomainEventHandlerInterface {
@@ -15,10 +20,12 @@ export class SubscriptionRefundedEventHandler implements DomainEventHandlerInter
@inject(TYPES.GetUserAnalyticsId) private getUserAnalyticsId: GetUserAnalyticsId,
@inject(TYPES.AnalyticsStore) private analyticsStore: AnalyticsStoreInterface,
@inject(TYPES.StatisticsStore) private statisticsStore: StatisticsStoreInterface,
@inject(TYPES.SaveRevenueModification) private saveRevenueModification: SaveRevenueModification,
@inject(TYPES.Logger) private logger: Logger,
) {}
async handle(event: SubscriptionRefundedEvent): Promise<void> {
const { analyticsId } = await this.getUserAnalyticsId.execute({ userEmail: event.payload.userEmail })
const { analyticsId, userUuid } = await this.getUserAnalyticsId.execute({ userEmail: event.payload.userEmail })
await this.analyticsStore.markActivity([AnalyticsActivity.SubscriptionRefunded], analyticsId, [
Period.Today,
Period.ThisWeek,
@@ -26,6 +33,23 @@ export class SubscriptionRefundedEventHandler implements DomainEventHandlerInter
])
await this.markChurnActivity(analyticsId, event)
const result = await this.saveRevenueModification.execute({
billingFrequency: event.payload.billingFrequency,
eventType: SubscriptionEventType.create(event.type).getValue(),
newSubscriber: event.payload.userExistingSubscriptionsCount === 1,
payedAmount: event.payload.payAmount,
planName: SubscriptionPlanName.create(event.payload.subscriptionName).getValue(),
subscriptionId: event.payload.subscriptionId,
userEmail: Email.create(event.payload.userEmail).getValue(),
userUuid,
})
if (result.isFailed()) {
this.logger.error(
`[${event.type}][${event.payload.subscriptionId}] Could not save revenue modification: ${result.getError()}`,
)
}
}
private async markChurnActivity(analyticsId: number, event: SubscriptionRefundedEvent): Promise<void> {

View File

@@ -6,17 +6,28 @@ import { SubscriptionRenewedEvent } from '@standardnotes/domain-events'
import { SubscriptionRenewedEventHandler } from './SubscriptionRenewedEventHandler'
import { GetUserAnalyticsId } from '../UseCase/GetUserAnalyticsId/GetUserAnalyticsId'
import { AnalyticsStoreInterface } from '../Analytics/AnalyticsStoreInterface'
import { SaveRevenueModification } from '../UseCase/SaveRevenueModification/SaveRevenueModification'
import { RevenueModification } from '../Revenue/RevenueModification'
import { Result } from '../Core/Result'
import { Logger } from 'winston'
describe('SubscriptionRenewedEventHandler', () => {
let event: SubscriptionRenewedEvent
let getUserAnalyticsId: GetUserAnalyticsId
let analyticsStore: AnalyticsStoreInterface
let saveRevenueModification: SaveRevenueModification
let logger: Logger
const createHandler = () => new SubscriptionRenewedEventHandler(getUserAnalyticsId, analyticsStore)
const createHandler = () =>
new SubscriptionRenewedEventHandler(getUserAnalyticsId, analyticsStore, saveRevenueModification, logger)
beforeEach(() => {
logger = {} as jest.Mocked<Logger>
logger.error = jest.fn()
event = {} as jest.Mocked<SubscriptionRenewedEvent>
event.createdAt = new Date(1)
event.type = 'SUBSCRIPTION_RENEWED'
event.payload = {
subscriptionId: 1,
userEmail: 'test@test.com',
@@ -24,6 +35,8 @@ describe('SubscriptionRenewedEventHandler', () => {
subscriptionExpiresAt: 2,
timestamp: 1,
offline: false,
billingFrequency: 1,
payAmount: 12.99,
}
getUserAnalyticsId = {} as jest.Mocked<GetUserAnalyticsId>
@@ -32,6 +45,9 @@ describe('SubscriptionRenewedEventHandler', () => {
analyticsStore = {} as jest.Mocked<AnalyticsStoreInterface>
analyticsStore.markActivity = jest.fn()
analyticsStore.unmarkActivity = jest.fn()
saveRevenueModification = {} as jest.Mocked<SaveRevenueModification>
saveRevenueModification.execute = jest.fn().mockReturnValue(Result.ok<RevenueModification>())
})
it('should track subscription renewed statistics', async () => {
@@ -39,5 +55,14 @@ describe('SubscriptionRenewedEventHandler', () => {
expect(analyticsStore.markActivity).toHaveBeenCalled()
expect(analyticsStore.unmarkActivity).toHaveBeenCalled()
expect(saveRevenueModification.execute).toHaveBeenCalled()
})
it('should log failure to save revenue modification', async () => {
saveRevenueModification.execute = jest.fn().mockReturnValue(Result.fail('Oops'))
await createHandler().handle(event)
expect(logger.error).toHaveBeenCalled()
})
})

View File

@@ -6,16 +6,23 @@ import { GetUserAnalyticsId } from '../UseCase/GetUserAnalyticsId/GetUserAnalyti
import { AnalyticsActivity } from '../Analytics/AnalyticsActivity'
import { AnalyticsStoreInterface } from '../Analytics/AnalyticsStoreInterface'
import { Period } from '../Time/Period'
import { SaveRevenueModification } from '../UseCase/SaveRevenueModification/SaveRevenueModification'
import { Email } from '../Common/Email'
import { SubscriptionEventType } from '../Subscription/SubscriptionEventType'
import { SubscriptionPlanName } from '../Subscription/SubscriptionPlanName'
import { Logger } from 'winston'
@injectable()
export class SubscriptionRenewedEventHandler implements DomainEventHandlerInterface {
constructor(
@inject(TYPES.GetUserAnalyticsId) private getUserAnalyticsId: GetUserAnalyticsId,
@inject(TYPES.AnalyticsStore) private analyticsStore: AnalyticsStoreInterface,
@inject(TYPES.SaveRevenueModification) private saveRevenueModification: SaveRevenueModification,
@inject(TYPES.Logger) private logger: Logger,
) {}
async handle(event: SubscriptionRenewedEvent): Promise<void> {
const { analyticsId } = await this.getUserAnalyticsId.execute({ userEmail: event.payload.userEmail })
const { analyticsId, userUuid } = await this.getUserAnalyticsId.execute({ userEmail: event.payload.userEmail })
await this.analyticsStore.markActivity([AnalyticsActivity.SubscriptionRenewed], analyticsId, [
Period.Today,
Period.ThisWeek,
@@ -26,5 +33,22 @@ export class SubscriptionRenewedEventHandler implements DomainEventHandlerInterf
analyticsId,
[Period.Today, Period.ThisWeek, Period.ThisMonth],
)
const result = await this.saveRevenueModification.execute({
billingFrequency: event.payload.billingFrequency,
eventType: SubscriptionEventType.create(event.type).getValue(),
newSubscriber: false,
payedAmount: event.payload.payAmount,
planName: SubscriptionPlanName.create(event.payload.subscriptionName).getValue(),
subscriptionId: event.payload.subscriptionId,
userEmail: Email.create(event.payload.userEmail).getValue(),
userUuid,
})
if (result.isFailed()) {
this.logger.error(
`[${event.type}][${event.payload.subscriptionId}] Could not save revenue modification: ${result.getError()}`,
)
}
}
}

View File

@@ -1,3 +1,5 @@
import { injectable } from 'inversify'
import { TypeORMRevenueModification } from '../../Infra/TypeORM/TypeORMRevenueModification'
import { UniqueEntityId } from '../Core/UniqueEntityId'
import { MonthlyRevenue } from '../Revenue/MonthlyRevenue'
@@ -9,15 +11,21 @@ import { Email } from '../Common/Email'
import { SubscriptionPlanName } from '../Subscription/SubscriptionPlanName'
import { SubscriptionEventType } from '../Subscription/SubscriptionEventType'
@injectable()
export class RevenueModificationMap implements MapInterface<RevenueModification, TypeORMRevenueModification> {
toDomain(persistence: TypeORMRevenueModification): RevenueModification {
const user = User.create(
const userOrError = User.create(
{
email: Email.create(persistence.userEmail).getValue(),
},
new UniqueEntityId(persistence.userUuid),
)
const subscription = Subscription.create(
if (userOrError.isFailed()) {
throw new Error(`Could not create user: ${userOrError.getError()}`)
}
const user = userOrError.getValue()
const subscriptionOrError = Subscription.create(
{
billingFrequency: persistence.billingFrequency,
isFirstSubscriptionForUser: persistence.isNewCustomer,
@@ -26,17 +34,31 @@ export class RevenueModificationMap implements MapInterface<RevenueModification,
},
new UniqueEntityId(persistence.subscriptionId),
)
const previousMonthlyRevenueOrError = MonthlyRevenue.create(persistence.previousMonthlyRevenue)
if (subscriptionOrError.isFailed()) {
throw new Error(`Could not create subscription: ${subscriptionOrError.getError()}`)
}
const subscription = subscriptionOrError.getValue()
return RevenueModification.create(
const previousMonthlyRevenueOrError = MonthlyRevenue.create(persistence.previousMonthlyRevenue)
const newMonthlyRevenueOrError = MonthlyRevenue.create(persistence.newMonthlyRevenue)
const revenuModificationOrError = RevenueModification.create(
{
user,
subscription,
eventType: SubscriptionEventType.create(persistence.eventType).getValue(),
previousMonthlyRevenue: previousMonthlyRevenueOrError.getValue(),
newMonthlyRevenue: newMonthlyRevenueOrError.getValue(),
createdAt: persistence.createdAt,
},
new UniqueEntityId(persistence.uuid),
)
if (revenuModificationOrError.isFailed()) {
throw new Error(`Could not map revenue modification to domain: ${revenuModificationOrError.getError()}`)
}
return revenuModificationOrError.getValue()
}
toPersistence(domain: RevenueModification): TypeORMRevenueModification {
@@ -46,12 +68,13 @@ export class RevenueModificationMap implements MapInterface<RevenueModification,
persistence.billingFrequency = subscription.props.billingFrequency
persistence.eventType = domain.props.eventType.value
persistence.isNewCustomer = subscription.props.isFirstSubscriptionForUser
persistence.newMonthlyRevenue = domain.newMonthlyRevenue.value
persistence.newMonthlyRevenue = domain.props.newMonthlyRevenue.value
persistence.previousMonthlyRevenue = domain.props.previousMonthlyRevenue.value
persistence.subscriptionId = subscription.id.toValue() as number
persistence.subscriptionPlan = subscription.props.planName.value
persistence.userEmail = user.props.email.value
persistence.userUuid = user.id.toString()
persistence.createdAt = domain.props.createdAt
return persistence
}

View File

@@ -13,7 +13,7 @@ export class MonthlyRevenue extends ValueObject<MonthlyRevenueProps> {
static create(revenue: number): Result<MonthlyRevenue> {
if (isNaN(revenue) || revenue < 0) {
return Result.fail<MonthlyRevenue>('Monthly revenue must be a non-negative number')
return Result.fail<MonthlyRevenue>(`Monthly revenue must be a non-negative number. Supplied: ${revenue}`)
} else {
return Result.ok<MonthlyRevenue>(new MonthlyRevenue({ value: revenue }))
}

View File

@@ -16,46 +16,23 @@ describe('RevenueModification', () => {
isFirstSubscriptionForUser: true,
payedAmount: 123,
planName: SubscriptionPlanName.create('PRO_PLAN').getValue(),
})
}).getValue()
user = User.create({
email: Email.create('test@test.te').getValue(),
})
}).getValue()
})
it('should create an aggregate for purchased subscription', () => {
const revenueModification = RevenueModification.create({
createdAt: 2,
eventType: SubscriptionEventType.create('SUBSCRIPTION_PURCHASED').getValue(),
previousMonthlyRevenue: MonthlyRevenue.create(123).getValue(),
newMonthlyRevenue: MonthlyRevenue.create(45).getValue(),
subscription,
user,
})
}).getValue()
expect(revenueModification.id.toString()).toHaveLength(36)
expect(revenueModification.newMonthlyRevenue.value).toEqual(123 / 12)
})
it('should create an aggregate for subscription expired', () => {
const revenueModification = RevenueModification.create({
createdAt: new Date(1),
eventType: SubscriptionEventType.create('SUBSCRIPTION_EXPIRED').getValue(),
previousMonthlyRevenue: MonthlyRevenue.create(123).getValue(),
subscription,
user,
})
expect(revenueModification.id.toString()).toHaveLength(36)
expect(revenueModification.newMonthlyRevenue.value).toEqual(0)
})
it('should create an aggregate for subscription cancelled', () => {
const revenueModification = RevenueModification.create({
eventType: SubscriptionEventType.create('SUBSCRIPTION_CANCELLED').getValue(),
previousMonthlyRevenue: MonthlyRevenue.create(123).getValue(),
subscription,
user,
})
expect(revenueModification.id.toString()).toHaveLength(36)
expect(revenueModification.newMonthlyRevenue.value).toEqual(123)
expect(revenueModification.props.newMonthlyRevenue.value).toEqual(45)
})
})

View File

@@ -1,6 +1,6 @@
import { Aggregate } from '../Core/Aggregate'
import { Result } from '../Core/Result'
import { UniqueEntityId } from '../Core/UniqueEntityId'
import { MonthlyRevenue } from './MonthlyRevenue'
import { RevenueModificationProps } from './RevenueModificationProps'
export class RevenueModification extends Aggregate<RevenueModificationProps> {
@@ -8,38 +8,7 @@ export class RevenueModification extends Aggregate<RevenueModificationProps> {
super(props, id)
}
static create(props: RevenueModificationProps, id?: UniqueEntityId): RevenueModification {
const revenueModification = new RevenueModification(
{
...props,
createdAt: props.createdAt ? props.createdAt : new Date(),
},
id,
)
return revenueModification
}
get newMonthlyRevenue(): MonthlyRevenue {
const { subscription } = this.props
let revenue = 0
switch (this.props.eventType.value) {
case 'SUBSCRIPTION_PURCHASED':
case 'SUBSCRIPTION_RENEWED':
revenue = subscription.props.payedAmount / subscription.props.billingFrequency
break
case 'SUBSCRIPTION_EXPIRED':
case 'SUBSCRIPTION_REFUNDED':
revenue = 0
break
case 'SUBSCRIPTION_CANCELLED':
revenue = this.props.previousMonthlyRevenue.value
break
}
const monthlyRevenueOrError = MonthlyRevenue.create(revenue)
return monthlyRevenueOrError.getValue()
static create(props: RevenueModificationProps, id?: UniqueEntityId): Result<RevenueModification> {
return Result.ok<RevenueModification>(new RevenueModification(props, id))
}
}

View File

@@ -8,5 +8,6 @@ export interface RevenueModificationProps {
subscription: Subscription
eventType: SubscriptionEventType
previousMonthlyRevenue: MonthlyRevenue
createdAt?: Date
newMonthlyRevenue: MonthlyRevenue
createdAt: number
}

View File

@@ -3,5 +3,6 @@ import { RevenueModification } from './RevenueModification'
export interface RevenueModificationRepositoryInterface {
findLastByUserUuid(userUuid: Uuid): Promise<RevenueModification | null>
sumMRRDiff(dto: { planName?: string; billingFrequency?: number }): Promise<number>
save(revenueModification: RevenueModification): Promise<RevenueModification>
}

View File

@@ -15,4 +15,10 @@ export enum StatisticsMeasure {
Refunds = 'refunds',
NewCustomers = 'new-customers',
TotalCustomers = 'total-customers',
MRR = 'mrr',
MonthlyPlansMRR = 'monthly-plans-mrr',
AnnualPlansMRR = 'annual-plans-mrr',
FiveYearPlansMRR = 'five-year-plans-mrr',
ProPlansMRR = 'pro-plans-mrr',
PlusPlansMRR = 'plus-plans-mrr',
}

View File

@@ -13,4 +13,8 @@ export interface StatisticsStoreInterface {
getMeasureAverage(measure: StatisticsMeasure, period: Period): Promise<number>
getMeasureTotal(measure: StatisticsMeasure, periodOrPeriodKey: Period | string): Promise<number>
getMeasureIncrementCounts(measure: StatisticsMeasure, period: Period): Promise<number>
calculateTotalCountOverPeriod(
measure: StatisticsMeasure,
period: Period,
): Promise<Array<{ periodKey: string; totalCount: number }>>
}

View File

@@ -8,7 +8,7 @@ describe('Subscription', () => {
isFirstSubscriptionForUser: true,
payedAmount: 12.99,
planName: SubscriptionPlanName.create('PRO_PLAN').getValue(),
})
}).getValue()
expect(subscription.id.toString()).toHaveLength(36)
})

View File

@@ -1,4 +1,5 @@
import { Entity } from '../Core/Entity'
import { Result } from '../Core/Result'
import { UniqueEntityId } from '../Core/UniqueEntityId'
import { SubscriptionProps } from './SubscriptionProps'
@@ -11,7 +12,7 @@ export class Subscription extends Entity<SubscriptionProps> {
super(props, id)
}
static create(props: SubscriptionProps, id?: UniqueEntityId): Subscription {
return new Subscription(props, id)
static create(props: SubscriptionProps, id?: UniqueEntityId): Result<Subscription> {
return Result.ok<Subscription>(new Subscription(props, id))
}
}

View File

@@ -19,6 +19,7 @@ export class SubscriptionEventType extends ValueObject<SubscriptionEventTypeProp
'SUBSCRIPTION_EXPIRED',
'SUBSCRIPTION_REFUNDED',
'SUBSCRIPTION_CANCELLED',
'SUBSCRIPTION_DATA_MIGRATED',
].includes(subscriptionEventType)
) {
return Result.fail<SubscriptionEventType>(`Invalid subscription event type ${subscriptionEventType}`)

View File

@@ -26,4 +26,5 @@ export enum Period {
OctoberThisYear,
NovemberThisYear,
DecemberThisYear,
Last30DaysIncludingToday,
}

View File

@@ -62,6 +62,41 @@ describe('PeriodKeyGenerator', () => {
])
})
it('should generate period keys for last 30 days including Today', () => {
expect(createGenerator().getDiscretePeriodKeys(Period.Last30DaysIncludingToday)).toEqual([
'2022-4-25',
'2022-4-26',
'2022-4-27',
'2022-4-28',
'2022-4-29',
'2022-4-30',
'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',
])
})
it('should generate period keys for this year', () => {
expect(createGenerator().getDiscretePeriodKeys(Period.ThisYear)).toEqual([
'2022-1',

View File

@@ -33,6 +33,12 @@ export class PeriodKeyGenerator implements PeriodKeyGeneratorInterface {
periodKeys.unshift(this.getDailyKey(this.getDateNDaysBefore(i)))
}
return periodKeys
case Period.Last30DaysIncludingToday:
for (let i = 0; i <= 29; i++) {
periodKeys.unshift(this.getDailyKey(this.getDateNDaysBefore(i)))
}
return periodKeys
case Period.Last7Days:
for (let i = 1; i <= 7; i++) {

View File

@@ -0,0 +1,33 @@
import 'reflect-metadata'
import { RevenueModificationRepositoryInterface } from '../../Revenue/RevenueModificationRepositoryInterface'
import { StatisticsMeasure } from '../../Statistics/StatisticsMeasure'
import { StatisticsStoreInterface } from '../../Statistics/StatisticsStoreInterface'
import { Period } from '../../Time/Period'
import { CalculateMonthlyRecurringRevenue } from './CalculateMonthlyRecurringRevenue'
describe('CalculateMonthlyRecurringRevenue', () => {
let revenueModificationRepository: RevenueModificationRepositoryInterface
let statisticsStore: StatisticsStoreInterface
const createUseCase = () => new CalculateMonthlyRecurringRevenue(revenueModificationRepository, statisticsStore)
beforeEach(() => {
revenueModificationRepository = {} as jest.Mocked<RevenueModificationRepositoryInterface>
revenueModificationRepository.sumMRRDiff = jest.fn().mockReturnValue(123.45)
statisticsStore = {} as jest.Mocked<StatisticsStoreInterface>
statisticsStore.setMeasure = jest.fn()
})
it('should calculate the MRR diff and persist it as a statistic', async () => {
await createUseCase().execute({})
expect(statisticsStore.setMeasure).toHaveBeenCalledWith(StatisticsMeasure.MRR, 123.45, [
Period.Today,
Period.ThisMonth,
Period.ThisYear,
])
})
})

View File

@@ -0,0 +1,82 @@
import { SubscriptionBillingFrequency, SubscriptionName } from '@standardnotes/common'
import { inject, injectable } from 'inversify'
import TYPES from '../../../Bootstrap/Types'
import { Result } from '../../Core/Result'
import { MonthlyRevenue } from '../../Revenue/MonthlyRevenue'
import { RevenueModificationRepositoryInterface } from '../../Revenue/RevenueModificationRepositoryInterface'
import { StatisticsMeasure } from '../../Statistics/StatisticsMeasure'
import { StatisticsStoreInterface } from '../../Statistics/StatisticsStoreInterface'
import { Period } from '../../Time/Period'
import { DomainUseCaseInterface } from '../DomainUseCaseInterface'
import { CalculateMonthlyRecurringRevenueDTO } from './CalculateMonthlyRecurringRevenueDTO'
@injectable()
export class CalculateMonthlyRecurringRevenue implements DomainUseCaseInterface<MonthlyRevenue> {
constructor(
@inject(TYPES.RevenueModificationRepository)
private revenueModificationRepository: RevenueModificationRepositoryInterface,
@inject(TYPES.StatisticsStore) private statisticsStore: StatisticsStoreInterface,
) {}
async execute(_dto: CalculateMonthlyRecurringRevenueDTO): Promise<Result<MonthlyRevenue>> {
const mrrDiff = await this.revenueModificationRepository.sumMRRDiff({})
await this.statisticsStore.setMeasure(StatisticsMeasure.MRR, mrrDiff, [
Period.Today,
Period.ThisMonth,
Period.ThisYear,
])
const monthlyPlansMrrDiff = await this.revenueModificationRepository.sumMRRDiff({
billingFrequency: SubscriptionBillingFrequency.Monthly,
})
await this.statisticsStore.setMeasure(StatisticsMeasure.MonthlyPlansMRR, monthlyPlansMrrDiff, [
Period.Today,
Period.ThisMonth,
Period.ThisYear,
])
const annualPlansMrrDiff = await this.revenueModificationRepository.sumMRRDiff({
billingFrequency: SubscriptionBillingFrequency.Annual,
})
await this.statisticsStore.setMeasure(StatisticsMeasure.AnnualPlansMRR, annualPlansMrrDiff, [
Period.Today,
Period.ThisMonth,
Period.ThisYear,
])
const fiveYearPlansMrrDiff = await this.revenueModificationRepository.sumMRRDiff({
billingFrequency: SubscriptionBillingFrequency.FiveYear,
})
await this.statisticsStore.setMeasure(StatisticsMeasure.FiveYearPlansMRR, fiveYearPlansMrrDiff, [
Period.Today,
Period.ThisMonth,
Period.ThisYear,
])
const proPlansMrrDiff = await this.revenueModificationRepository.sumMRRDiff({
planName: SubscriptionName.ProPlan,
})
await this.statisticsStore.setMeasure(StatisticsMeasure.ProPlansMRR, proPlansMrrDiff, [
Period.Today,
Period.ThisMonth,
Period.ThisYear,
])
const plusPlansMrrDiff = await this.revenueModificationRepository.sumMRRDiff({
planName: SubscriptionName.PlusPlan,
})
await this.statisticsStore.setMeasure(StatisticsMeasure.PlusPlansMRR, plusPlansMrrDiff, [
Period.Today,
Period.ThisMonth,
Period.ThisYear,
])
return MonthlyRevenue.create(mrrDiff)
}
}

View File

@@ -0,0 +1,2 @@
/* eslint-disable @typescript-eslint/no-empty-interface */
export interface CalculateMonthlyRecurringRevenueDTO {}

View File

@@ -1,5 +1,7 @@
import 'reflect-metadata'
import { TimerInterface } from '@standardnotes/time'
import { Email } from '../../Common/Email'
import { Uuid } from '../../Common/Uuid'
import { MonthlyRevenue } from '../../Revenue/MonthlyRevenue'
@@ -9,24 +11,35 @@ import { RevenueModificationRepositoryInterface } from '../../Revenue/RevenueMod
import { SubscriptionEventType } from '../../Subscription/SubscriptionEventType'
import { SubscriptionPlanName } from '../../Subscription/SubscriptionPlanName'
import { SaveRevenueModification } from './SaveRevenueModification'
import { User } from '../../User/User'
import { Result } from '../../Core/Result'
import { Subscription } from '../../Subscription/Subscription'
describe('SaveRevenueModification', () => {
let revenueModificationRepository: RevenueModificationRepositoryInterface
let previousMonthlyRevenue: RevenueModification
let previousMonthlyRevenueModification: RevenueModification
let timer: TimerInterface
const createUseCase = () => new SaveRevenueModification(revenueModificationRepository)
const createUseCase = () => new SaveRevenueModification(revenueModificationRepository, timer)
beforeEach(() => {
previousMonthlyRevenue = {
newMonthlyRevenue: MonthlyRevenue.create(2).getValue(),
const previousMonthlyRevenue = {
value: 2,
} as jest.Mocked<MonthlyRevenue>
previousMonthlyRevenueModification = {
props: {},
} as jest.Mocked<RevenueModification>
previousMonthlyRevenueModification.props.newMonthlyRevenue = previousMonthlyRevenue
revenueModificationRepository = {} as jest.Mocked<RevenueModificationRepositoryInterface>
revenueModificationRepository.findLastByUserUuid = jest.fn().mockReturnValue(previousMonthlyRevenue)
revenueModificationRepository.findLastByUserUuid = jest.fn().mockReturnValue(previousMonthlyRevenueModification)
revenueModificationRepository.save = jest.fn()
timer = {} as jest.Mocked<TimerInterface>
timer.getTimestampInMicroseconds = jest.fn().mockReturnValue(1)
})
it('should persist a revenue modification', async () => {
it('should persist a revenue modification for subscription purchased event', async () => {
const revenueOrError = await createUseCase().execute({
billingFrequency: 1,
eventType: SubscriptionEventType.create('SUBSCRIPTION_PURCHASED').getValue(),
@@ -37,8 +50,166 @@ describe('SaveRevenueModification', () => {
userEmail: Email.create('test@test.te').getValue(),
userUuid: Uuid.create('1-2-3').getValue(),
})
expect(revenueOrError.isFailed()).toBeFalsy()
const revenue = revenueOrError.getValue()
expect(revenue.newMonthlyRevenue.value).toEqual(12.99)
expect(revenue.props.newMonthlyRevenue.value).toEqual(12.99)
})
it('should persist a revenue modification for subscription expired event', async () => {
const revenueOrError = await createUseCase().execute({
billingFrequency: 1,
eventType: SubscriptionEventType.create('SUBSCRIPTION_EXPIRED').getValue(),
newSubscriber: true,
payedAmount: 12.99,
planName: SubscriptionPlanName.create('PRO_PLAN').getValue(),
subscriptionId: 1234,
userEmail: Email.create('test@test.te').getValue(),
userUuid: Uuid.create('1-2-3').getValue(),
})
expect(revenueOrError.isFailed()).toBeFalsy()
const revenue = revenueOrError.getValue()
expect(revenue.props.newMonthlyRevenue.value).toEqual(0)
})
it('should persist a revenue modification for subscription cancelled event', async () => {
const revenueOrError = await createUseCase().execute({
billingFrequency: 1,
eventType: SubscriptionEventType.create('SUBSCRIPTION_CANCELLED').getValue(),
newSubscriber: true,
payedAmount: 2,
planName: SubscriptionPlanName.create('PRO_PLAN').getValue(),
subscriptionId: 1234,
userEmail: Email.create('test@test.te').getValue(),
userUuid: Uuid.create('1-2-3').getValue(),
})
expect(revenueOrError.isFailed()).toBeFalsy()
const revenue = revenueOrError.getValue()
expect(revenue.props.newMonthlyRevenue.value).toEqual(2)
})
it('should persist a revenue modification for subscription purchased event if previous revenue modification did not exist', async () => {
revenueModificationRepository.findLastByUserUuid = jest.fn().mockReturnValue(null)
const revenueOrError = await createUseCase().execute({
billingFrequency: 1,
eventType: SubscriptionEventType.create('SUBSCRIPTION_PURCHASED').getValue(),
newSubscriber: true,
payedAmount: 12.99,
planName: SubscriptionPlanName.create('PRO_PLAN').getValue(),
subscriptionId: 1234,
userEmail: Email.create('test@test.te').getValue(),
userUuid: Uuid.create('1-2-3').getValue(),
})
expect(revenueOrError.isFailed()).toBeFalsy()
const revenue = revenueOrError.getValue()
expect(revenue.props.newMonthlyRevenue.value).toEqual(12.99)
})
it('should not persist a revenue modification if failed to create user', async () => {
const mock = jest.spyOn(User, 'create')
mock.mockReturnValue(Result.fail('Oops'))
const revenueOrError = await createUseCase().execute({
billingFrequency: 1,
eventType: SubscriptionEventType.create('SUBSCRIPTION_PURCHASED').getValue(),
newSubscriber: true,
payedAmount: 12.99,
planName: SubscriptionPlanName.create('PRO_PLAN').getValue(),
subscriptionId: 1234,
userEmail: Email.create('test@test.te').getValue(),
userUuid: Uuid.create('1-2-3').getValue(),
})
expect(revenueOrError.isFailed()).toBeTruthy()
mock.mockRestore()
})
it('should not persist a revenue modification if failed to create a subscription', async () => {
const mock = jest.spyOn(Subscription, 'create')
mock.mockReturnValue(Result.fail('Oops'))
const revenueOrError = await createUseCase().execute({
billingFrequency: 1,
eventType: SubscriptionEventType.create('SUBSCRIPTION_PURCHASED').getValue(),
newSubscriber: true,
payedAmount: 12.99,
planName: SubscriptionPlanName.create('PRO_PLAN').getValue(),
subscriptionId: 1234,
userEmail: Email.create('test@test.te').getValue(),
userUuid: Uuid.create('1-2-3').getValue(),
})
expect(revenueOrError.isFailed()).toBeTruthy()
mock.mockRestore()
})
it('should not persist a revenue modification if failed to create a previous monthly revenue', async () => {
const mock = jest.spyOn(MonthlyRevenue, 'create')
mock.mockReturnValue(Result.fail('Oops'))
const revenueOrError = await createUseCase().execute({
billingFrequency: 1,
eventType: SubscriptionEventType.create('SUBSCRIPTION_PURCHASED').getValue(),
newSubscriber: true,
payedAmount: 12.99,
planName: SubscriptionPlanName.create('PRO_PLAN').getValue(),
subscriptionId: 1234,
userEmail: Email.create('test@test.te').getValue(),
userUuid: Uuid.create('1-2-3').getValue(),
})
expect(revenueOrError.isFailed()).toBeTruthy()
mock.mockRestore()
})
it('should not persist a revenue modification if failed to create a next monthly revenue', async () => {
const mock = jest.spyOn(MonthlyRevenue, 'create')
mock.mockReturnValueOnce(Result.ok()).mockReturnValueOnce(Result.fail('Oops'))
const revenueOrError = await createUseCase().execute({
billingFrequency: 1,
eventType: SubscriptionEventType.create('SUBSCRIPTION_PURCHASED').getValue(),
newSubscriber: true,
payedAmount: 12.99,
planName: SubscriptionPlanName.create('PRO_PLAN').getValue(),
subscriptionId: 1234,
userEmail: Email.create('test@test.te').getValue(),
userUuid: Uuid.create('1-2-3').getValue(),
})
expect(revenueOrError.isFailed()).toBeTruthy()
mock.mockRestore()
})
it('should not persist a revenue modification if failed to create it', async () => {
const mock = jest.spyOn(RevenueModification, 'create')
mock.mockReturnValue(Result.fail('Oops'))
const revenueOrError = await createUseCase().execute({
billingFrequency: 1,
eventType: SubscriptionEventType.create('SUBSCRIPTION_PURCHASED').getValue(),
newSubscriber: true,
payedAmount: 12.99,
planName: SubscriptionPlanName.create('PRO_PLAN').getValue(),
subscriptionId: 1234,
userEmail: Email.create('test@test.te').getValue(),
userUuid: Uuid.create('1-2-3').getValue(),
})
expect(revenueOrError.isFailed()).toBeTruthy()
mock.mockRestore()
})
})

View File

@@ -1,4 +1,5 @@
import { inject, injectable } from 'inversify'
import TYPES from '../../../Bootstrap/Types'
import { UniqueEntityId } from '../../Core/UniqueEntityId'
import { MonthlyRevenue } from '../../Revenue/MonthlyRevenue'
@@ -9,22 +10,30 @@ import { User } from '../../User/User'
import { Result } from '../../Core/Result'
import { DomainUseCaseInterface } from '../DomainUseCaseInterface'
import { SaveRevenueModificationDTO } from './SaveRevenueModificationDTO'
import { TimerInterface } from '@standardnotes/time'
import { SubscriptionEventType } from '../../Subscription/SubscriptionEventType'
@injectable()
export class SaveRevenueModification implements DomainUseCaseInterface<RevenueModification> {
constructor(
@inject(TYPES.RevenueModificationRepository)
private revenueModificationRepository: RevenueModificationRepositoryInterface,
@inject(TYPES.Timer) private timer: TimerInterface,
) {}
async execute(dto: SaveRevenueModificationDTO): Promise<Result<RevenueModification>> {
const user = User.create(
const userOrError = User.create(
{
email: dto.userEmail,
},
new UniqueEntityId(dto.userUuid.value),
)
const subscription = Subscription.create(
if (userOrError.isFailed()) {
return Result.fail<RevenueModification>(userOrError.getError())
}
const user = userOrError.getValue()
const subscriptionOrError = Subscription.create(
{
isFirstSubscriptionForUser: dto.newSubscriber,
payedAmount: dto.payedAmount,
@@ -33,22 +42,77 @@ export class SaveRevenueModification implements DomainUseCaseInterface<RevenueMo
},
new UniqueEntityId(dto.subscriptionId),
)
if (subscriptionOrError.isFailed()) {
return Result.fail<RevenueModification>(subscriptionOrError.getError())
}
const subscription = subscriptionOrError.getValue()
const previousMonthlyRevenueOrError = MonthlyRevenue.create(0)
if (previousMonthlyRevenueOrError.isFailed()) {
return Result.fail<RevenueModification>(previousMonthlyRevenueOrError.getError())
}
let previousMonthlyRevenue = previousMonthlyRevenueOrError.getValue()
let previousMonthlyRevenue = MonthlyRevenue.create(0).getValue()
const previousRevenueModification = await this.revenueModificationRepository.findLastByUserUuid(dto.userUuid)
if (previousRevenueModification !== null) {
previousMonthlyRevenue = previousRevenueModification.newMonthlyRevenue
previousMonthlyRevenue = previousRevenueModification.props.newMonthlyRevenue
}
const newMonthlyRevenueOrError = this.calculateNewMonthlyRevenue(
subscription,
previousMonthlyRevenue,
dto.eventType,
)
if (newMonthlyRevenueOrError.isFailed()) {
return Result.fail<RevenueModification>(newMonthlyRevenueOrError.getError())
}
const newMonthlyRevenue = newMonthlyRevenueOrError.getValue()
const revenueModification = RevenueModification.create({
const revenueModificationOrError = RevenueModification.create({
eventType: dto.eventType,
subscription,
user,
previousMonthlyRevenue,
newMonthlyRevenue,
createdAt: this.timer.getTimestampInMicroseconds(),
})
if (revenueModificationOrError.isFailed()) {
return Result.fail<RevenueModification>(revenueModificationOrError.getError())
}
const revenueModification = revenueModificationOrError.getValue()
await this.revenueModificationRepository.save(revenueModification)
return Result.ok<RevenueModification>(revenueModification)
}
private calculateNewMonthlyRevenue(
subscription: Subscription,
previousMonthlyRevenue: MonthlyRevenue,
eventType: SubscriptionEventType,
): Result<MonthlyRevenue> {
let revenue = 0
switch (eventType.value) {
case 'SUBSCRIPTION_PURCHASED':
case 'SUBSCRIPTION_RENEWED':
case 'SUBSCRIPTION_DATA_MIGRATED':
revenue = subscription.props.payedAmount / subscription.props.billingFrequency
break
case 'SUBSCRIPTION_EXPIRED':
case 'SUBSCRIPTION_REFUNDED':
revenue = 0
break
case 'SUBSCRIPTION_CANCELLED':
revenue = previousMonthlyRevenue.value
break
}
const monthlyRevenueOrError = MonthlyRevenue.create(revenue)
if (monthlyRevenueOrError.isFailed()) {
return Result.fail<MonthlyRevenue>(monthlyRevenueOrError.getError())
}
return Result.ok<MonthlyRevenue>(monthlyRevenueOrError.getValue())
}
}

View File

@@ -5,7 +5,7 @@ describe('User', () => {
it('should create an entity', () => {
const user = User.create({
email: Email.create('test@test.te').getValue(),
})
}).getValue()
expect(user.id.toString()).toHaveLength(36)
})

View File

@@ -1,4 +1,5 @@
import { Entity } from '../Core/Entity'
import { Result } from '../Core/Result'
import { UniqueEntityId } from '../Core/UniqueEntityId'
import { UserProps } from './UserProps'
@@ -11,7 +12,7 @@ export class User extends Entity<UserProps> {
super(props, id)
}
public static create(props: UserProps, id?: UniqueEntityId): User {
return new User(props, id)
public static create(props: UserProps, id?: UniqueEntityId): Result<User> {
return Result.ok<User>(new User(props, id))
}
}

View File

@@ -17,6 +17,25 @@ export class MySQLRevenueModificationRepository implements RevenueModificationRe
private revenueModificationMap: MapInterface<RevenueModification, TypeORMRevenueModification>,
) {}
async sumMRRDiff(dto: { planName?: string; billingFrequency?: number }): Promise<number> {
const query = this.ormRepository.createQueryBuilder().select('sum(new_mrr - previous_mrr)', 'mrrDiff')
if (dto.planName !== undefined) {
query.where('subscription_plan = :planName', { planName: dto.planName })
}
if (dto.billingFrequency !== undefined) {
query.where('billing_frequency = :billingFrequency', { billingFrequency: dto.billingFrequency })
}
const result = await query.getRawOne()
if (result === undefined) {
return 0
}
return +(+result.mrrDiff).toFixed(2)
}
async findLastByUserUuid(userUuid: Uuid): Promise<RevenueModification | null> {
const persistence = await this.ormRepository
.createQueryBuilder()

View File

@@ -1,209 +0,0 @@
import * as IORedis from 'ioredis'
import { AnalyticsActivity } from '../../Domain/Analytics/AnalyticsActivity'
import { Period } from '../../Domain/Time/Period'
import { PeriodKeyGeneratorInterface } from '../../Domain/Time/PeriodKeyGeneratorInterface'
import { RedisAnalyticsStore } from './RedisAnalyticsStore'
describe('RedisAnalyticsStore', () => {
let redisClient: IORedis.Redis
let pipeline: IORedis.Pipeline
let periodKeyGenerator: PeriodKeyGeneratorInterface
const createStore = () => new RedisAnalyticsStore(periodKeyGenerator, redisClient)
beforeEach(() => {
pipeline = {} as jest.Mocked<IORedis.Pipeline>
pipeline.incr = jest.fn()
pipeline.setbit = jest.fn()
pipeline.exec = jest.fn()
redisClient = {} as jest.Mocked<IORedis.Redis>
redisClient.pipeline = jest.fn().mockReturnValue(pipeline)
redisClient.incr = jest.fn()
redisClient.setbit = jest.fn()
redisClient.getbit = jest.fn().mockReturnValue(1)
redisClient.bitop = jest.fn()
redisClient.expire = jest.fn()
periodKeyGenerator = {} as jest.Mocked<PeriodKeyGeneratorInterface>
periodKeyGenerator.getPeriodKey = jest.fn().mockReturnValue('period-key')
})
it('should calculate total count over time of activities', async () => {
redisClient.bitcount = jest.fn().mockReturnValue(70)
periodKeyGenerator.getDiscretePeriodKeys = jest.fn().mockReturnValue(['2022-4-24', '2022-4-25', '2022-4-26'])
await createStore().calculateActivityTotalCountOverTime(AnalyticsActivity.Register, Period.Last30Days)
expect(redisClient.bitop).toHaveBeenCalledTimes(1)
expect(redisClient.bitop).toHaveBeenNthCalledWith(
1,
'OR',
'bitmap:action:register:timespan:2022-4-24-2022-4-26',
'bitmap:action:register:timespan:2022-4-24',
'bitmap:action:register:timespan:2022-4-25',
'bitmap:action:register:timespan:2022-4-26',
)
expect(redisClient.bitcount).toHaveBeenCalledWith('bitmap:action:register:timespan:2022-4-24-2022-4-26')
})
it('should not calculate total count over time of activities if period is unsupported', async () => {
let caughtError = null
try {
await createStore().calculateActivityTotalCountOverTime(AnalyticsActivity.Register, Period.LastWeek)
} catch (error) {
caughtError = error
}
expect(caughtError).not.toBeNull()
})
it('should calculate total count changes of activities', async () => {
periodKeyGenerator.getDiscretePeriodKeys = jest.fn().mockReturnValue(['2022-4-24', '2022-4-25', '2022-4-26'])
redisClient.bitcount = jest.fn().mockReturnValueOnce(70).mockReturnValueOnce(71).mockReturnValueOnce(72)
expect(
await createStore().calculateActivityChangesTotalCount(AnalyticsActivity.Register, Period.Last30Days),
).toEqual([
{
periodKey: '2022-4-24',
totalCount: 70,
},
{
periodKey: '2022-4-25',
totalCount: 71,
},
{
periodKey: '2022-4-26',
totalCount: 72,
},
])
expect(redisClient.bitcount).toHaveBeenNthCalledWith(1, 'bitmap:action:register:timespan:2022-4-24')
expect(redisClient.bitcount).toHaveBeenNthCalledWith(2, 'bitmap:action:register:timespan:2022-4-25')
expect(redisClient.bitcount).toHaveBeenNthCalledWith(3, 'bitmap:action:register:timespan:2022-4-26')
})
it('should throw error on calculating total count changes of activities on unsupported period', async () => {
periodKeyGenerator.getDiscretePeriodKeys = jest.fn().mockReturnValue(['2022-4-24', '2022-4-25', '2022-4-26'])
redisClient.bitcount = jest.fn().mockReturnValueOnce(70).mockReturnValueOnce(71).mockReturnValueOnce(72)
let caughtError = null
try {
await createStore().calculateActivityChangesTotalCount(AnalyticsActivity.Register, Period.LastWeek)
} catch (error) {
caughtError = error
}
expect(caughtError).not.toBeNull()
})
it('should calculate total count of activities by period', async () => {
redisClient.bitcount = jest.fn().mockReturnValue(70)
expect(await createStore().calculateActivityTotalCount(AnalyticsActivity.Register, Period.Yesterday)).toEqual(70)
expect(redisClient.bitcount).toHaveBeenCalledWith('bitmap:action:register: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.Register, '2022-10-03')).toEqual(70)
expect(redisClient.bitcount).toHaveBeenCalledWith('bitmap:action:register:timespan:2022-10-03')
})
it('should calculate activity retention', async () => {
redisClient.bitcount = jest.fn().mockReturnValueOnce(7).mockReturnValueOnce(10)
expect(
await createStore().calculateActivityRetention(
AnalyticsActivity.Register,
Period.DayBeforeYesterday,
Period.Yesterday,
),
).toEqual(70)
expect(redisClient.bitop).toHaveBeenCalledWith(
'AND',
'bitmap:action:register-register:timespan:period-key',
'bitmap:action:register:timespan:period-key',
'bitmap:action:register:timespan:period-key',
)
})
it('shoud tell if activity was done', async () => {
await createStore().wasActivityDone(AnalyticsActivity.Register, 123, Period.Yesterday)
expect(redisClient.getbit).toHaveBeenCalledWith('bitmap:action:register:timespan:period-key', 123)
})
it('should mark activity as done', async () => {
await createStore().markActivity([AnalyticsActivity.Register], 123, [Period.Today])
expect(pipeline.setbit).toBeCalledTimes(1)
expect(pipeline.setbit).toHaveBeenNthCalledWith(1, 'bitmap:action:register:timespan:period-key', 123, 1)
expect(pipeline.exec).toHaveBeenCalled()
})
it('should mark activities as done', async () => {
await createStore().markActivity([AnalyticsActivity.Register, AnalyticsActivity.SubscriptionPurchased], 123, [
Period.Today,
Period.ThisWeek,
])
expect(pipeline.setbit).toBeCalledTimes(4)
expect(pipeline.setbit).toHaveBeenNthCalledWith(1, 'bitmap:action:register:timespan:period-key', 123, 1)
expect(pipeline.setbit).toHaveBeenNthCalledWith(2, 'bitmap:action:register:timespan:period-key', 123, 1)
expect(pipeline.setbit).toHaveBeenNthCalledWith(
3,
'bitmap:action:subscription-purchased:timespan:period-key',
123,
1,
)
expect(pipeline.setbit).toHaveBeenNthCalledWith(
4,
'bitmap:action:subscription-purchased:timespan:period-key',
123,
1,
)
expect(pipeline.exec).toHaveBeenCalled()
})
it('should unmark activity as done', async () => {
await createStore().unmarkActivity([AnalyticsActivity.Register], 123, [Period.Today])
expect(pipeline.setbit).toBeCalledTimes(1)
expect(pipeline.setbit).toHaveBeenNthCalledWith(1, 'bitmap:action:register:timespan:period-key', 123, 0)
expect(pipeline.exec).toHaveBeenCalled()
})
it('should unmark activities as done', async () => {
await createStore().unmarkActivity([AnalyticsActivity.Register, AnalyticsActivity.SubscriptionPurchased], 123, [
Period.Today,
Period.ThisWeek,
])
expect(pipeline.setbit).toBeCalledTimes(4)
expect(pipeline.setbit).toHaveBeenNthCalledWith(1, 'bitmap:action:register:timespan:period-key', 123, 0)
expect(pipeline.setbit).toHaveBeenNthCalledWith(2, 'bitmap:action:register:timespan:period-key', 123, 0)
expect(pipeline.setbit).toHaveBeenNthCalledWith(
3,
'bitmap:action:subscription-purchased:timespan:period-key',
123,
0,
)
expect(pipeline.setbit).toHaveBeenNthCalledWith(
4,
'bitmap:action:subscription-purchased:timespan:period-key',
123,
0,
)
expect(pipeline.exec).toHaveBeenCalled()
})
})

View File

@@ -1,145 +0,0 @@
import * as IORedis from 'ioredis'
import { StatisticsMeasure } from '../../Domain/Statistics/StatisticsMeasure'
import { Period } from '../../Domain/Time/Period'
import { PeriodKeyGeneratorInterface } from '../../Domain/Time/PeriodKeyGeneratorInterface'
import { RedisStatisticsStore } from './RedisStatisticsStore'
describe('RedisStatisticsStore', () => {
let redisClient: IORedis.Redis
let periodKeyGenerator: PeriodKeyGeneratorInterface
let pipeline: IORedis.Pipeline
const createStore = () => new RedisStatisticsStore(periodKeyGenerator, redisClient)
beforeEach(() => {
pipeline = {} as jest.Mocked<IORedis.Pipeline>
pipeline.incr = jest.fn()
pipeline.incrbyfloat = jest.fn()
pipeline.set = jest.fn()
pipeline.setbit = jest.fn()
pipeline.exec = jest.fn()
redisClient = {} as jest.Mocked<IORedis.Redis>
redisClient.pipeline = jest.fn().mockReturnValue(pipeline)
redisClient.incr = jest.fn()
redisClient.setbit = jest.fn()
redisClient.getbit = jest.fn().mockReturnValue(1)
periodKeyGenerator = {} as jest.Mocked<PeriodKeyGeneratorInterface>
periodKeyGenerator.getPeriodKey = jest.fn().mockReturnValue('period-key')
})
it('should get yesterday out of sync incidents', async () => {
redisClient.get = jest.fn().mockReturnValue(1)
expect(await createStore().getYesterdayOutOfSyncIncidents()).toEqual(1)
})
it('should default to 0 yesterday out of sync incidents', async () => {
redisClient.get = jest.fn().mockReturnValue(null)
expect(await createStore().getYesterdayOutOfSyncIncidents()).toEqual(0)
})
it('should get yesterday application version usage', async () => {
redisClient.keys = jest
.fn()
.mockReturnValue([
'count:action:application-request:1.2.3:timespan:2022-3-10',
'count:action:application-request:2.3.4:timespan:2022-3-10',
])
redisClient.get = jest.fn().mockReturnValueOnce(3).mockReturnValueOnce(4)
expect(await createStore().getYesterdayApplicationUsage()).toEqual([
{ count: 3, version: '1.2.3' },
{ count: 4, version: '2.3.4' },
])
})
it('should get yesterday snjs version usage', async () => {
redisClient.keys = jest
.fn()
.mockReturnValue([
'count:action:snjs-request:1.2.3:timespan:2022-3-10',
'count:action:snjs-request:2.3.4:timespan:2022-3-10',
])
redisClient.get = jest.fn().mockReturnValueOnce(3).mockReturnValueOnce(4)
expect(await createStore().getYesterdaySNJSUsage()).toEqual([
{ count: 3, version: '1.2.3' },
{ count: 4, version: '2.3.4' },
])
})
it('should increment application version usage', async () => {
await createStore().incrementApplicationVersionUsage('1.2.3')
expect(pipeline.incr).toHaveBeenCalled()
expect(pipeline.exec).toHaveBeenCalled()
})
it('should increment snjs version usage', async () => {
await createStore().incrementSNJSVersionUsage('1.2.3')
expect(pipeline.incr).toHaveBeenCalled()
expect(pipeline.exec).toHaveBeenCalled()
})
it('should increment out of sync incedent count', async () => {
await createStore().incrementOutOfSyncIncidents()
expect(pipeline.incr).toHaveBeenCalled()
expect(pipeline.exec).toHaveBeenCalled()
})
it('should set a value to a measure', async () => {
await createStore().setMeasure(StatisticsMeasure.Income, 2, [Period.Today, Period.ThisMonth])
expect(pipeline.set).toHaveBeenCalledTimes(2)
expect(pipeline.exec).toHaveBeenCalled()
})
it('should increment measure by a value', async () => {
await createStore().incrementMeasure(StatisticsMeasure.Income, 2, [Period.Today, Period.ThisMonth])
expect(pipeline.incr).toHaveBeenCalledTimes(2)
expect(pipeline.incrbyfloat).toHaveBeenCalledTimes(2)
expect(pipeline.exec).toHaveBeenCalled()
})
it('should count a measurement average', async () => {
redisClient.get = jest.fn().mockReturnValueOnce('5').mockReturnValueOnce('2')
expect(await createStore().getMeasureAverage(StatisticsMeasure.Income, Period.Today)).toEqual(2 / 5)
})
it('should count a measurement average - 0 increments', async () => {
redisClient.get = jest.fn().mockReturnValueOnce(null).mockReturnValueOnce(null)
expect(await createStore().getMeasureAverage(StatisticsMeasure.Income, Period.Today)).toEqual(0)
})
it('should count a measurement average - 0 total value', async () => {
redisClient.get = jest.fn().mockReturnValueOnce(5).mockReturnValueOnce(null)
expect(await createStore().getMeasureAverage(StatisticsMeasure.Income, Period.Today)).toEqual(0)
})
it('should retrieve a measurement total for period', async () => {
redisClient.get = jest.fn().mockReturnValueOnce(5)
expect(await createStore().getMeasureTotal(StatisticsMeasure.Income, Period.Today)).toEqual(5)
expect(redisClient.get).toHaveBeenCalledWith('count:measure:income:timespan:period-key')
})
it('should retrieve a measurement total for period key', async () => {
redisClient.get = jest.fn().mockReturnValueOnce(5)
expect(await createStore().getMeasureTotal(StatisticsMeasure.Income, '2022-10-03')).toEqual(5)
expect(redisClient.get).toHaveBeenCalledWith('count:measure:income:timespan:2022-10-03')
})
})

View File

@@ -9,6 +9,35 @@ import { PeriodKeyGeneratorInterface } from '../../Domain/Time/PeriodKeyGenerato
export class RedisStatisticsStore implements StatisticsStoreInterface {
constructor(private periodKeyGenerator: PeriodKeyGeneratorInterface, private redisClient: IORedis.Redis) {}
async calculateTotalCountOverPeriod(
measure: StatisticsMeasure,
period: Period,
): Promise<{ periodKey: string; totalCount: number }[]> {
if (
![
Period.Last30Days,
Period.Last30DaysIncludingToday,
Period.ThisYear,
Period.Q1ThisYear,
Period.Q2ThisYear,
Period.Q3ThisYear,
Period.Q4ThisYear,
].includes(period)
) {
throw new Error(`Unsuporrted period: ${period}`)
}
const periodKeys = this.periodKeyGenerator.getDiscretePeriodKeys(period)
const counts = []
for (const periodKey of periodKeys) {
counts.push({
periodKey,
totalCount: await this.getMeasureTotal(measure, periodKey),
})
}
return counts
}
async getMeasureIncrementCounts(measure: StatisticsMeasure, period: Period): Promise<number> {
const increments = await this.redisClient.get(
`count:increments:${measure}:timespan:${this.periodKeyGenerator.getPeriodKey(period)}`,

View File

@@ -49,11 +49,19 @@ export class TypeORMRevenueModification {
@Column({
name: 'previous_mrr',
type: 'float',
})
declare previousMonthlyRevenue: number
@Column({
name: 'new_mrr',
type: 'float',
})
declare newMonthlyRevenue: number
@Column({
name: 'created_at',
type: 'bigint',
})
declare createdAt: number
}

View File

@@ -3,6 +3,64 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.38.4](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.38.1...@standardnotes/api-gateway@1.38.4) (2022-11-14)
### Bug Fixes
* **api-gateway:** bump version ([6f5e9b7](https://github.com/standardnotes/api-gateway/commit/6f5e9b7b5a83a9e8894f1dff5cfc91228d90b7b4))
## [1.38.1](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.38.0...@standardnotes/api-gateway@1.38.1) (2022-11-14)
**Note:** Version bump only for package @standardnotes/api-gateway
# [1.38.0](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.37.11...@standardnotes/api-gateway@1.38.0) (2022-11-13)
### Features
* iap confirm endpoint ([#338](https://github.com/standardnotes/api-gateway/issues/338)) ([3bba367](https://github.com/standardnotes/api-gateway/commit/3bba36742ac00c8756dd69f3a81ea124538d5cbe))
## [1.37.11](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.37.10...@standardnotes/api-gateway@1.37.11) (2022-11-11)
**Note:** Version bump only for package @standardnotes/api-gateway
## [1.37.10](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.37.9...@standardnotes/api-gateway@1.37.10) (2022-11-11)
**Note:** Version bump only for package @standardnotes/api-gateway
## [1.37.9](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.37.8...@standardnotes/api-gateway@1.37.9) (2022-11-10)
**Note:** Version bump only for package @standardnotes/api-gateway
## [1.37.8](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.37.7...@standardnotes/api-gateway@1.37.8) (2022-11-10)
**Note:** Version bump only for package @standardnotes/api-gateway
## [1.37.7](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.37.6...@standardnotes/api-gateway@1.37.7) (2022-11-10)
### Bug Fixes
* **api-gateway:** setting headers ([3c2ac05](https://github.com/standardnotes/api-gateway/commit/3c2ac05c606371305b76dd368d5fe9287045f380))
## [1.37.6](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.37.5...@standardnotes/api-gateway@1.37.6) (2022-11-10)
**Note:** Version bump only for package @standardnotes/api-gateway
## [1.37.5](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.37.4...@standardnotes/api-gateway@1.37.5) (2022-11-09)
**Note:** Version bump only for package @standardnotes/api-gateway
## [1.37.4](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.37.3...@standardnotes/api-gateway@1.37.4) (2022-11-09)
**Note:** Version bump only for package @standardnotes/api-gateway
## [1.37.3](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.37.2...@standardnotes/api-gateway@1.37.3) (2022-11-09)
**Note:** Version bump only for package @standardnotes/api-gateway
## [1.37.2](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.37.1...@standardnotes/api-gateway@1.37.2) (2022-11-09)
**Note:** Version bump only for package @standardnotes/api-gateway
## [1.37.1](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.37.0...@standardnotes/api-gateway@1.37.1) (2022-11-09)
**Note:** Version bump only for package @standardnotes/api-gateway

View File

@@ -1,4 +1,4 @@
FROM node:16.15.1-alpine
FROM node:18.12.1-alpine
RUN apk add --update \
curl \

View File

@@ -1,8 +1,8 @@
{
"name": "@standardnotes/api-gateway",
"version": "1.37.1",
"version": "1.38.4",
"engines": {
"node": ">=16.0.0 <17.0.0"
"node": ">=18.0.0 <19.0.0"
},
"private": true,
"description": "API Gateway For Standard Notes Services",
@@ -20,35 +20,36 @@
"upgrade:snjs": "yarn ncu -u '@standardnotes/*'"
},
"dependencies": {
"@newrelic/native-metrics": "^9.0.0",
"@newrelic/winston-enricher": "^4.0.0",
"@sentry/node": "^7.3.0",
"@sentry/node": "^7.19.0",
"@standardnotes/common": "workspace:^",
"@standardnotes/domain-events": "workspace:*",
"@standardnotes/domain-events-infra": "workspace:*",
"@standardnotes/security": "workspace:*",
"@standardnotes/time": "workspace:*",
"aws-sdk": "^2.1160.0",
"axios": "^0.27.2",
"aws-sdk": "^2.1253.0",
"axios": "^1.1.3",
"cors": "2.8.5",
"dotenv": "^16.0.1",
"express": "^4.18.1",
"express": "^4.18.2",
"helmet": "^6.0.0",
"inversify": "^6.0.1",
"inversify-express-utils": "^6.4.3",
"ioredis": "^5.2.0",
"ioredis": "^5.2.4",
"jsonwebtoken": "8.5.1",
"newrelic": "^9.0.0",
"newrelic": "^9.6.0",
"prettyjson": "^1.2.5",
"reflect-metadata": "0.1.13",
"winston": "^3.8.1"
},
"devDependencies": {
"@types/cors": "^2.8.9",
"@types/express": "^4.17.11",
"@types/ioredis": "^4.28.10",
"@types/express": "^4.17.14",
"@types/ioredis": "^5.0.0",
"@types/jest": "^29.1.1",
"@types/jsonwebtoken": "^8.5.0",
"@types/newrelic": "^7.0.3",
"@types/newrelic": "^7.0.4",
"@types/prettyjson": "^0.0.30",
"@typescript-eslint/eslint-plugin": "^5.29.0",
"eslint": "^8.14.0",

View File

@@ -1,5 +1,7 @@
import * as winston from 'winston'
import axios, { AxiosInstance } from 'axios'
// eslint-disable-next-line @typescript-eslint/no-var-requires
const axios = require('axios')
import { AxiosInstance } from 'axios'
import Redis from 'ioredis'
import { Container } from 'inversify'
import { Timer, TimerInterface } from '@standardnotes/time'

View File

@@ -60,7 +60,7 @@ export class AuthMiddleware extends BaseMiddleware {
})
if (authResponse.status > 200) {
response.setHeader('content-type', authResponse.headers['content-type'])
response.setHeader('content-type', authResponse.headers['content-type'] as string)
response.status(authResponse.status).send(authResponse.data)
return

View File

@@ -20,7 +20,8 @@ export class SubscriptionTokenAuthMiddleware extends BaseMiddleware {
}
async handler(request: Request, response: Response, next: NextFunction): Promise<void> {
const subscriptionToken = request.query.subscription_token
const subscriptionToken = request.query.subscription_token || request.body.subscription_token
const email = request.headers['x-offline-email']
if (!subscriptionToken) {
response.status(401).send({
@@ -58,7 +59,7 @@ export class SubscriptionTokenAuthMiddleware extends BaseMiddleware {
})
if (authResponse.status > 200) {
response.setHeader('content-type', authResponse.headers['content-type'])
response.setHeader('content-type', authResponse.headers['content-type'] as string)
response.status(authResponse.status).send(authResponse.data)
return

View File

@@ -48,7 +48,7 @@ export class WebSocketAuthMiddleware extends BaseMiddleware {
})
if (authResponse.status > 200) {
response.setHeader('content-type', authResponse.headers['content-type'])
response.setHeader('content-type', authResponse.headers['content-type'] as string)
response.status(authResponse.status).send(authResponse.data)
return

View File

@@ -45,6 +45,11 @@ export class PaymentsController extends BaseHttpController {
await this.httpService.callPaymentsServer(request, response, 'api/subscriptions/tiered', request.body)
}
@httpPost('/subscriptions/apple_iap_confirm', TYPES.SubscriptionTokenAuthMiddleware)
async appleIAPConfirm(request: Request, response: Response): Promise<void> {
await this.httpService.callPaymentsServer(request, response, 'api/subscriptions/apple_iap_confirm', request.body)
}
@all('/subscriptions(/*)?')
async subscriptions(request: Request, response: Response): Promise<void> {
await this.httpService.callPaymentsServer(request, response, request.path.replace('v1', 'api'), request.body)

View File

@@ -3,6 +3,64 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.59.10](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.59.7...@standardnotes/auth-server@1.59.10) (2022-11-14)
### Bug Fixes
* versioning issue ([7ca377f](https://github.com/standardnotes/server/commit/7ca377f1b889379e6a43a66c0134bf266763516d))
## [1.59.7](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.59.6...@standardnotes/auth-server@1.59.7) (2022-11-14)
**Note:** Version bump only for package @standardnotes/auth-server
## [1.59.6](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.59.5...@standardnotes/auth-server@1.59.6) (2022-11-11)
**Note:** Version bump only for package @standardnotes/auth-server
## [1.59.5](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.59.4...@standardnotes/auth-server@1.59.5) (2022-11-11)
**Note:** Version bump only for package @standardnotes/auth-server
## [1.59.4](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.59.3...@standardnotes/auth-server@1.59.4) (2022-11-10)
**Note:** Version bump only for package @standardnotes/auth-server
## [1.59.3](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.59.2...@standardnotes/auth-server@1.59.3) (2022-11-10)
**Note:** Version bump only for package @standardnotes/auth-server
## [1.59.2](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.59.1...@standardnotes/auth-server@1.59.2) (2022-11-10)
**Note:** Version bump only for package @standardnotes/auth-server
## [1.59.1](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.59.0...@standardnotes/auth-server@1.59.1) (2022-11-10)
**Note:** Version bump only for package @standardnotes/auth-server
# [1.59.0](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.58.0...@standardnotes/auth-server@1.59.0) (2022-11-09)
### Features
* **analytics:** add saving revenue modifications upon subscription canceled ([52a257a](https://github.com/standardnotes/server/commit/52a257abb16034134a50474fbbb2493a00c58b99))
# [1.58.0](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.57.0...@standardnotes/auth-server@1.58.0) (2022-11-09)
### Features
* **analytics:** add saving revenue modifications upon subscription refunded ([0f65c05](https://github.com/standardnotes/server/commit/0f65c051abcff805e920f91d338e5fadda7905a9))
# [1.57.0](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.56.0...@standardnotes/auth-server@1.57.0) (2022-11-09)
### Features
* **analytics:** add saving revenue modifications upon subscription expired ([5c3db2c](https://github.com/standardnotes/server/commit/5c3db2cb29a929e44b63eb8226ce4ad1d14f8a99))
# [1.56.0](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.55.0...@standardnotes/auth-server@1.56.0) (2022-11-09)
### Features
* **analytics:** add saving revenue modifications upon subscription renewed ([cdb7fcf](https://github.com/standardnotes/server/commit/cdb7fcf8311fecfabe3ef9eb656cd6ec57b87de0))
# [1.55.0](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.54.0...@standardnotes/auth-server@1.55.0) (2022-11-09)
### Features

View File

@@ -1,4 +1,4 @@
FROM node:16.15.1-alpine
FROM node:18.12.1-alpine
RUN apk add --update \
curl \

View File

@@ -1,8 +1,8 @@
{
"name": "@standardnotes/auth-server",
"version": "1.55.0",
"version": "1.59.10",
"engines": {
"node": ">=16.0.0 <17.0.0"
"node": ">=18.0.0 <19.0.0"
},
"private": true,
"description": "Auth Server",
@@ -30,8 +30,9 @@
"upgrade:snjs": "yarn ncu -u '@standardnotes/*'"
},
"dependencies": {
"@newrelic/native-metrics": "^9.0.0",
"@newrelic/winston-enricher": "^4.0.0",
"@sentry/node": "^7.3.0",
"@sentry/node": "^7.19.0",
"@standardnotes/api": "^1.19.0",
"@standardnotes/common": "workspace:*",
"@standardnotes/domain-events": "workspace:*",
@@ -44,33 +45,33 @@
"@standardnotes/sncrypto-common": "^1.9.0",
"@standardnotes/sncrypto-node": "workspace:*",
"@standardnotes/time": "workspace:*",
"aws-sdk": "^2.1159.0",
"axios": "^0.27.2",
"aws-sdk": "^2.1253.0",
"axios": "^1.1.3",
"bcryptjs": "2.4.3",
"cors": "2.8.5",
"dayjs": "^1.11.6",
"dotenv": "^16.0.1",
"express": "^4.18.1",
"express": "^4.18.2",
"inversify": "^6.0.1",
"inversify-express-utils": "^6.4.3",
"ioredis": "^5.2.0",
"ioredis": "^5.2.4",
"mysql2": "^2.3.3",
"newrelic": "^9.0.0",
"newrelic": "^9.6.0",
"otplib": "12.0.1",
"prettyjson": "^1.2.5",
"reflect-metadata": "0.1.13",
"typeorm": "^0.3.6",
"ua-parser-js": "1.0.2",
"typeorm": "^0.3.10",
"ua-parser-js": "^1.0.32",
"uuid": "^9.0.0",
"winston": "^3.8.1"
},
"devDependencies": {
"@types/bcryptjs": "^2.4.2",
"@types/cors": "^2.8.9",
"@types/express": "^4.17.11",
"@types/ioredis": "^4.28.10",
"@types/express": "^4.17.14",
"@types/ioredis": "^5.0.0",
"@types/jest": "^29.1.1",
"@types/newrelic": "^7.0.3",
"@types/newrelic": "^7.0.4",
"@types/otplib": "^10.0.0",
"@types/prettyjson": "^0.0.30",
"@types/ua-parser-js": "^0.7.36",

View File

@@ -72,7 +72,9 @@ import { DeleteAccount } from '../Domain/UseCase/DeleteAccount/DeleteAccount'
import { DeleteSetting } from '../Domain/UseCase/DeleteSetting/DeleteSetting'
import { SettingFactory } from '../Domain/Setting/SettingFactory'
import { SettingService } from '../Domain/Setting/SettingService'
import axios, { AxiosInstance } from 'axios'
// eslint-disable-next-line @typescript-eslint/no-var-requires
const axios = require('axios')
import { AxiosInstance } from 'axios'
import { UserSubscription } from '../Domain/Subscription/UserSubscription'
import { MySQLUserSubscriptionRepository } from '../Infra/MySQL/MySQLUserSubscriptionRepository'
import { WebSocketsClientService } from '../Infra/WebSockets/WebSocketsClientService'

View File

@@ -40,6 +40,9 @@ describe('SubscriptionCancelledEventHandler', () => {
subscriptionEndsAt: 2,
subscriptionUpdatedAt: 2,
lastPayedAt: 1,
userExistingSubscriptionsCount: 1,
billingFrequency: 1,
payAmount: 12.99,
}
})

View File

@@ -72,6 +72,9 @@ describe('SubscriptionExpiredEventHandler', () => {
timestamp,
offline: false,
totalActiveSubscriptionsCount: 123,
userExistingSubscriptionsCount: 2,
billingFrequency: 1,
payAmount: 12.99,
}
logger = {} as jest.Mocked<Logger>

View File

@@ -74,6 +74,8 @@ describe('SubscriptionRefundedEventHandler', () => {
offline: false,
userExistingSubscriptionsCount: 3,
totalActiveSubscriptionsCount: 1,
billingFrequency: 1,
payAmount: 12.99,
}
logger = {} as jest.Mocked<Logger>

Some files were not shown because too many files have changed in this diff Show More