Compare commits

..

99 Commits

Author SHA1 Message Date
standardci 280fdc89c1 chore(release): publish new version
- @standardnotes/analytics@2.10.0
 - @standardnotes/api-gateway@1.38.5
 - @standardnotes/auth-server@1.59.11
 - @standardnotes/common@1.45.0
 - @standardnotes/domain-core@1.1.0
 - @standardnotes/domain-events-infra@1.9.27
 - @standardnotes/domain-events@2.87.0
 - @standardnotes/event-store@1.6.22
 - @standardnotes/files-server@1.8.22
 - @standardnotes/predicates@1.6.0
 - @standardnotes/scheduler-server@1.13.23
 - @standardnotes/security@1.7.0
 - @standardnotes/sncrypto-node@1.13.0
 - @standardnotes/syncing-server@1.13.8
 - @standardnotes/time@1.14.0
 - @standardnotes/websockets-server@1.4.24
 - @standardnotes/workspace-server@1.17.22
2022-11-14 10:35:04 +00:00
Karol Sójko 0f94e2ad0c feat(analytics): extract domain core into a separate package 2022-11-14 11:32:31 +01:00
standardci d0036600e9 chore(release): publish new version
- @standardnotes/syncing-server@1.13.7
2022-11-14 10:08:04 +00:00
Karol Sójko f766fefbf0 fix(syncing-server): content recalculation missing await 2022-11-14 11:06:15 +01:00
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
standardci 4189f11fd7 chore(release): publish new version
- @standardnotes/analytics@2.3.0
 - @standardnotes/api-gateway@1.37.1
 - @standardnotes/auth-server@1.55.0
 - @standardnotes/domain-events-infra@1.9.14
 - @standardnotes/domain-events@2.79.0
 - @standardnotes/event-store@1.6.9
 - @standardnotes/files-server@1.8.9
 - @standardnotes/scheduler-server@1.13.10
 - @standardnotes/syncing-server@1.11.1
 - @standardnotes/websockets-server@1.4.9
 - @standardnotes/workspace-server@1.17.9
2022-11-09 07:16:01 +00:00
Karol Sójko 5ea9941519 feat(analytics): add saving revenue modifications upon subscription purchased 2022-11-09 08:14:02 +01:00
standardci 7a64494d07 chore(release): publish new version
- @standardnotes/analytics@2.2.0
2022-11-08 14:16:38 +00:00
Karol Sójko 4928685198 feat(analytics): add persistence for revenue modifications 2022-11-08 15:14:39 +01:00
Karol Sójko 0103233d4a feat(analytics): create new ddd architecture for persisting revenue modifications 2022-11-08 15:14:38 +01:00
standardci ee7075fe60 chore(release): publish new version
- @standardnotes/auth-server@1.54.0
2022-11-07 10:59:27 +00:00
Karol Sójko 49feadd32a feat(auth): remove analytics table in favor of analytics service 2022-11-07 11:57:39 +01:00
standardci 45758bf554 chore(release): publish new version
- @standardnotes/analytics@2.1.0
 - @standardnotes/api-gateway@1.37.0
 - @standardnotes/auth-server@1.53.0
 - @standardnotes/domain-events-infra@1.9.13
 - @standardnotes/domain-events@2.78.1
 - @standardnotes/event-store@1.6.8
 - @standardnotes/files-server@1.8.8
 - @standardnotes/scheduler-server@1.13.9
 - @standardnotes/security@1.6.0
 - @standardnotes/syncing-server@1.11.0
 - @standardnotes/websockets-server@1.4.8
 - @standardnotes/workspace-server@1.17.8
2022-11-07 10:54:09 +00:00
Karol Sójko 535d566a94 fix: yarn.lock 2022-11-07 11:52:16 +01:00
Karol Sójko ff1d5db12c feat: remove analytics scope from other services in favor of a separate service 2022-11-07 11:51:38 +01:00
standardci 77a06b2fe7 chore(release): publish new version
- @standardnotes/analytics@1.52.0
 - @standardnotes/api-gateway@1.36.14
 - @standardnotes/auth-server@1.52.1
 - @standardnotes/syncing-server@1.10.25
2022-11-07 09:20:01 +00:00
Karol Sójko 6359030030 feat(analytics): add handling subscription reactivated events 2022-11-07 10:17:49 +01:00
standardci 006f1fccec chore(release): publish new version
- @standardnotes/analytics@1.51.0
 - @standardnotes/api-gateway@1.36.13
 - @standardnotes/auth-server@1.52.0
 - @standardnotes/domain-events-infra@1.9.12
 - @standardnotes/domain-events@2.78.0
 - @standardnotes/event-store@1.6.7
 - @standardnotes/files-server@1.8.7
 - @standardnotes/scheduler-server@1.13.8
 - @standardnotes/syncing-server@1.10.24
 - @standardnotes/websockets-server@1.4.7
 - @standardnotes/workspace-server@1.17.7
2022-11-07 09:16:03 +00:00
Karol Sójko c0f5817d47 feat(analytics): add handling subscription expired events 2022-11-07 10:14:12 +01:00
standardci 3da952fa52 chore(release): publish new version
- @standardnotes/analytics@1.50.0
 - @standardnotes/api-gateway@1.36.12
 - @standardnotes/auth-server@1.51.0
 - @standardnotes/domain-events-infra@1.9.11
 - @standardnotes/domain-events@2.77.0
 - @standardnotes/event-store@1.6.6
 - @standardnotes/files-server@1.8.6
 - @standardnotes/scheduler-server@1.13.7
 - @standardnotes/syncing-server@1.10.23
 - @standardnotes/websockets-server@1.4.6
 - @standardnotes/workspace-server@1.17.6
2022-11-07 09:03:54 +00:00
Karol Sójko f1834d58d2 feat(analytics): add handling subscription purchased events 2022-11-07 10:02:07 +01:00
standardci b0cde4ab75 chore(release): publish new version
- @standardnotes/analytics@1.49.0
 - @standardnotes/api-gateway@1.36.11
 - @standardnotes/auth-server@1.50.0
 - @standardnotes/domain-events-infra@1.9.10
 - @standardnotes/domain-events@2.76.0
 - @standardnotes/event-store@1.6.5
 - @standardnotes/files-server@1.8.5
 - @standardnotes/scheduler-server@1.13.6
 - @standardnotes/syncing-server@1.10.22
 - @standardnotes/websockets-server@1.4.5
 - @standardnotes/workspace-server@1.17.5
2022-11-07 06:45:26 +00:00
Karol Sójko 197c9914ca feat(analytics): add handling subscription refunded event 2022-11-07 07:43:36 +01:00
standardci d7ef6898be chore(release): publish new version
- @standardnotes/analytics@1.48.0
 - @standardnotes/api-gateway@1.36.10
 - @standardnotes/auth-server@1.49.13
 - @standardnotes/syncing-server@1.10.21
2022-11-07 06:13:47 +00:00
Karol Sójko 2aa57f1f0d feat(analytics): add subscription renewed event handler 2022-11-07 07:11:10 +01:00
standardci dcc0e38707 chore(release): publish new version
- @standardnotes/analytics@1.47.0
 - @standardnotes/api-gateway@1.36.9
 - @standardnotes/auth-server@1.49.12
 - @standardnotes/domain-events-infra@1.9.9
 - @standardnotes/domain-events@2.75.0
 - @standardnotes/event-store@1.6.4
 - @standardnotes/files-server@1.8.4
 - @standardnotes/scheduler-server@1.13.5
 - @standardnotes/syncing-server@1.10.20
 - @standardnotes/websockets-server@1.4.4
 - @standardnotes/workspace-server@1.17.4
2022-11-04 14:01:17 +00:00
Karol Sójko 037fb2398a feat(analytics): add subscription cancelled event handler 2022-11-04 14:59:30 +01:00
Karol Sójko 182512d07c fix(syncing-server): event specs 2022-11-04 14:59:30 +01:00
Karol Sójko a3be4b063d fix(auth): event specs 2022-11-04 14:59:30 +01:00
standardci a97be4c342 chore(release): publish new version
- @standardnotes/analytics@1.46.0
 - @standardnotes/api-gateway@1.36.8
 - @standardnotes/auth-server@1.49.11
 - @standardnotes/syncing-server@1.10.19
2022-11-04 13:28:39 +00:00
Karol Sójko 5902cbb621 feat(analytics): add payment success event handler 2022-11-04 14:26:47 +01:00
standardci afc26d42ca chore(release): publish new version
- @standardnotes/analytics@1.45.0
 - @standardnotes/api-gateway@1.36.7
 - @standardnotes/auth-server@1.49.10
 - @standardnotes/syncing-server@1.10.18
2022-11-04 13:23:51 +00:00
Karol Sójko 51b12d05d4 feat: add payment failed handler and email to analytics entity 2022-11-04 14:21:34 +01:00
standardci 3fe7b4ae24 chore(release): publish new version
- @standardnotes/analytics@1.44.0
 - @standardnotes/api-gateway@1.36.6
 - @standardnotes/auth-server@1.49.9
 - @standardnotes/syncing-server@1.10.17
2022-11-04 13:02:55 +00:00
Karol Sójko 2720a7c827 feat(analytics): removing analytics entity upon account deletion 2022-11-04 14:01:10 +01:00
274 changed files with 4832 additions and 3083 deletions
+1 -1
View File
@@ -1 +1 @@
16.15.1
18.12.1
Generated
+210 -160
View File
@@ -29,6 +29,10 @@ const RAW_RUNTIME_STATE =
"name": "@standardnotes/common",\
"reference": "workspace:packages/common"\
},\
{\
"name": "@standardnotes/domain-core",\
"reference": "workspace:packages/domain-core"\
},\
{\
"name": "@standardnotes/domain-events",\
"reference": "workspace:packages/domain-events"\
@@ -89,6 +93,7 @@ const RAW_RUNTIME_STATE =
["@standardnotes/api-gateway", ["workspace:packages/api-gateway"]],\
["@standardnotes/auth-server", ["workspace:packages/auth"]],\
["@standardnotes/common", ["workspace:packages/common"]],\
["@standardnotes/domain-core", ["workspace:packages/domain-core"]],\
["@standardnotes/domain-events", ["workspace:packages/domain-events"]],\
["@standardnotes/domain-events-infra", ["workspace:packages/domain-events-infra"]],\
["@standardnotes/event-store", ["workspace:packages/event-store"]],\
@@ -116,15 +121,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 +1871,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 +1893,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 +1928,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 +1954,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 +2434,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 +2462,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,27 +2533,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-core", "workspace:packages/domain-core"],\
["@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"],\
["@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"],\
["ts-jest", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:29.0.3"],\
["typeorm", "virtual:c66bf20e88479ada0172094776519a9f51acc4731d22079b60a295bcec7ea42d5545cbce58a77a50d932bf953298799135e99707486e343da6d99ba1d167bdbd#npm:0.3.10"],\
@@ -2592,9 +2586,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"],\
["@standardnotes/analytics", "workspace:packages/analytics"],\
["@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"],\
@@ -2602,14 +2596,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"],\
@@ -2618,10 +2612,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"],\
@@ -2649,9 +2643,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"],\
["@standardnotes/analytics", "workspace:packages/analytics"],\
["@sentry/node", "npm:7.19.0"],\
["@standardnotes/api", "npm:1.19.0"],\
["@standardnotes/common", "workspace:packages/common"],\
["@standardnotes/domain-events", "workspace:packages/domain-events"],\
@@ -2667,16 +2661,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"],\
@@ -2686,10 +2680,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"],\
@@ -2698,7 +2692,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,7 +2705,7 @@ const RAW_RUNTIME_STATE =
"packageDependencies": [\
["@standardnotes/common", "workspace:packages/common"],\
["@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"],\
@@ -2736,6 +2730,29 @@ const RAW_RUNTIME_STATE =
"linkType": "HARD"\
}]\
]],\
["@standardnotes/domain-core", [\
["workspace:packages/domain-core", {\
"packageLocation": "./packages/domain-core/",\
"packageDependencies": [\
["@standardnotes/domain-core", "workspace:packages/domain-core"],\
["@standardnotes/common", "workspace:packages/common"],\
["@standardnotes/features", "npm:1.53.1"],\
["@standardnotes/predicates", "workspace:packages/predicates"],\
["@standardnotes/security", "workspace:packages/security"],\
["@types/jest", "npm:29.1.1"],\
["@types/uuid", "npm:8.3.4"],\
["@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"],\
["reflect-metadata", "npm:0.1.13"],\
["shallow-equal-object", "npm:1.1.1"],\
["ts-jest", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:29.0.3"],\
["typescript", "patch:typescript@npm%3A4.8.4#optional!builtin<compat/typescript>::version=4.8.4&hash=701156"],\
["uuid", "npm:9.0.0"]\
],\
"linkType": "SOFT"\
}]\
]],\
["@standardnotes/domain-events", [\
["workspace:packages/domain-events", {\
"packageLocation": "./packages/domain-events/",\
@@ -2761,16 +2778,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"],\
@@ -2800,23 +2818,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"],\
@@ -2855,7 +2874,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"],\
@@ -2867,14 +2887,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"],\
@@ -2886,10 +2906,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"],\
@@ -2989,28 +3009,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"],\
@@ -3050,15 +3071,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"],\
@@ -3072,6 +3094,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"],\
@@ -3097,7 +3120,7 @@ const RAW_RUNTIME_STATE =
["@standardnotes/sncrypto-node", "workspace:packages/sncrypto-node"],\
["@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"],\
@@ -3115,9 +3138,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"],\
["@standardnotes/analytics", "workspace:packages/analytics"],\
["@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 +3153,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 +3171,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 +3183,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"]\
],\
@@ -3215,8 +3238,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 +3248,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 +3261,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 +3279,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 +3291,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 +3303,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 +3555,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 +3688,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 +3703,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 +4762,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 +4781,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 +7332,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 +8283,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 +10408,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 +11511,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/",\
@@ -12216,6 +12257,15 @@ const RAW_RUNTIME_STATE =
"linkType": "HARD"\
}]\
]],\
["shallow-equal-object", [\
["npm:1.1.1", {\
"packageLocation": "./.yarn/cache/shallow-equal-object-npm-1.1.1-a41b289b2e-9e5e0cd10b.zip/node_modules/shallow-equal-object/",\
"packageDependencies": [\
["shallow-equal-object", "npm:1.1.1"]\
],\
"linkType": "HARD"\
}]\
]],\
["shebang-command", [\
["npm:2.0.0", {\
"packageLocation": "./.yarn/cache/shebang-command-npm-2.0.0-eb2b01921d-5907a8d5fa.zip/node_modules/shebang-command/",\
@@ -12482,7 +12532,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": [\
@@ -13097,7 +13147,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],\
@@ -13373,7 +13423,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],\
@@ -13397,7 +13447,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],\
@@ -13475,10 +13525,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.
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.
@@ -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
@@ -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
@@ -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:
@@ -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:
@@ -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:
@@ -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"
}
}
@@ -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++
+6 -5
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"
}
}
+193
View File
@@ -3,6 +3,199 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
# [2.10.0](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.9.9...@standardnotes/analytics@2.10.0) (2022-11-14)
### Features
* **analytics:** extract domain core into a separate package ([0f94e2a](https://github.com/standardnotes/server/commit/0f94e2ad0c8927733eac31f130cbe649dce765f9))
## [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
* **analytics:** add saving revenue modifications upon subscription purchased ([5ea9941](https://github.com/standardnotes/server/commit/5ea9941519ffb3027527130ec869da14abc5e994))
# [2.2.0](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.1.0...@standardnotes/analytics@2.2.0) (2022-11-08)
### Features
* **analytics:** add persistence for revenue modifications ([4928685](https://github.com/standardnotes/server/commit/49286851989f557d3b391b6b535a9aa307fbef50))
* **analytics:** create new ddd architecture for persisting revenue modifications ([0103233](https://github.com/standardnotes/server/commit/0103233d4a1e222e7c9b059475c1cdc3b2617455))
# [2.1.0](https://github.com/standardnotes/server/compare/@standardnotes/analytics@1.52.0...@standardnotes/analytics@2.1.0) (2022-11-07)
### Features
* remove analytics scope from other services in favor of a separate service ([ff1d5db](https://github.com/standardnotes/server/commit/ff1d5db12c93f8e51c07c3aecb9fed4be48ea96a))
# [1.52.0](https://github.com/standardnotes/server/compare/@standardnotes/analytics@1.51.0...@standardnotes/analytics@1.52.0) (2022-11-07)
### Features
* **analytics:** add handling subscription reactivated events ([6359030](https://github.com/standardnotes/server/commit/63590300308975097f4d092a4f140f479093a1ae))
# [1.51.0](https://github.com/standardnotes/server/compare/@standardnotes/analytics@1.50.0...@standardnotes/analytics@1.51.0) (2022-11-07)
### Features
* **analytics:** add handling subscription expired events ([c0f5817](https://github.com/standardnotes/server/commit/c0f5817d4753410ee5d997c1b94e340b400cb5d9))
# [1.50.0](https://github.com/standardnotes/server/compare/@standardnotes/analytics@1.49.0...@standardnotes/analytics@1.50.0) (2022-11-07)
### Features
* **analytics:** add handling subscription purchased events ([f1834d5](https://github.com/standardnotes/server/commit/f1834d58d2215c81322e82a0ec279617103b3260))
# [1.49.0](https://github.com/standardnotes/server/compare/@standardnotes/analytics@1.48.0...@standardnotes/analytics@1.49.0) (2022-11-07)
### Features
* **analytics:** add handling subscription refunded event ([197c991](https://github.com/standardnotes/server/commit/197c9914caf8fb31ce3ee69d05381d2a6416b366))
# [1.48.0](https://github.com/standardnotes/server/compare/@standardnotes/analytics@1.47.0...@standardnotes/analytics@1.48.0) (2022-11-07)
### Features
* **analytics:** add subscription renewed event handler ([2aa57f1](https://github.com/standardnotes/server/commit/2aa57f1f0ddace741b79e9375b87464eaaba6320))
# [1.47.0](https://github.com/standardnotes/server/compare/@standardnotes/analytics@1.46.0...@standardnotes/analytics@1.47.0) (2022-11-04)
### Features
* **analytics:** add subscription cancelled event handler ([037fb23](https://github.com/standardnotes/server/commit/037fb2398ae9aaa11682e1a8576bab28c69e0f9b))
# [1.46.0](https://github.com/standardnotes/server/compare/@standardnotes/analytics@1.45.0...@standardnotes/analytics@1.46.0) (2022-11-04)
### Features
* **analytics:** add payment success event handler ([5902cbb](https://github.com/standardnotes/server/commit/5902cbb6218a5b3982b4c56f8d6644f4f5bc6d32))
# [1.45.0](https://github.com/standardnotes/server/compare/@standardnotes/analytics@1.44.0...@standardnotes/analytics@1.45.0) (2022-11-04)
### Features
* add payment failed handler and email to analytics entity ([51b12d0](https://github.com/standardnotes/server/commit/51b12d05d49868db1d61313c4d8b3829994e7eb3))
# [1.44.0](https://github.com/standardnotes/server/compare/@standardnotes/analytics@1.43.0...@standardnotes/analytics@1.44.0) (2022-11-04)
### Features
* **analytics:** removing analytics entity upon account deletion ([2720a7c](https://github.com/standardnotes/server/commit/2720a7c827a6352cb5254e88d42d45c385921448))
# [1.43.0](https://github.com/standardnotes/server/compare/@standardnotes/analytics@1.42.0...@standardnotes/analytics@1.43.0) (2022-11-04)
### Features
+1 -1
View File
@@ -1,4 +1,4 @@
FROM node:16.15.1-alpine
FROM node:18.12.1-alpine
RUN apk add --update \
curl \
+50 -45
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
@@ -34,8 +38,6 @@ const requestReport = async (
}> = []
const thirtyDaysAnalyticsNames = [
AnalyticsActivity.GeneralActivity,
AnalyticsActivity.EditingItems,
AnalyticsActivity.SubscriptionPurchased,
AnalyticsActivity.Register,
AnalyticsActivity.SubscriptionRenewed,
@@ -80,9 +82,6 @@ const requestReport = async (
}> = []
const yesterdayActivityNames = [
AnalyticsActivity.LimitedDiscountOfferPurchased,
AnalyticsActivity.GeneralActivity,
AnalyticsActivity.GeneralActivityFreeUsers,
AnalyticsActivity.GeneralActivityPaidUsers,
AnalyticsActivity.PaymentFailed,
AnalyticsActivity.PaymentSuccess,
AnalyticsActivity.NewCustomersChurn,
@@ -101,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,
@@ -116,9 +149,6 @@ const requestReport = async (
StatisticsMeasure.SubscriptionLength,
StatisticsMeasure.RegistrationToSubscriptionTime,
StatisticsMeasure.RemainingSubscriptionTimePercentage,
StatisticsMeasure.NotesCountFreeUsers,
StatisticsMeasure.NotesCountPaidUsers,
StatisticsMeasure.FilesCount,
StatisticsMeasure.NewCustomers,
StatisticsMeasure.TotalCustomers,
]
@@ -141,29 +171,6 @@ const requestReport = async (
}
}
const periodKeys = periodKeyGenerator.getDiscretePeriodKeys(Period.Last7Days)
const retentionOverDays: Array<{
firstPeriodKey: string
secondPeriodKey: string
value: number
}> = []
for (let i = 0; i < periodKeys.length; i++) {
for (let j = 0; j < periodKeys.length - i; j++) {
const dailyRetention = await analyticsStore.calculateActivitiesRetention({
firstActivity: AnalyticsActivity.Register,
firstActivityPeriodKey: periodKeys[i],
secondActivity: AnalyticsActivity.GeneralActivity,
secondActivityPeriodKey: periodKeys[i + j],
})
retentionOverDays.push({
firstPeriodKey: periodKeys[i],
secondPeriodKey: periodKeys[i + j],
value: dailyRetention,
})
}
}
const monthlyPeriodKeys = periodKeyGenerator.getDiscretePeriodKeys(Period.ThisYear)
const churnRates: Array<{
rate: number
@@ -201,22 +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: [
{
firstActivity: AnalyticsActivity.Register,
secondActivity: AnalyticsActivity.GeneralActivity,
retention: {
periodKeys,
values: retentionOverDays,
},
},
],
churn: {
periodKeys: monthlyPeriodKeys,
values: churnRates,
@@ -240,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')
+1
View File
@@ -7,4 +7,5 @@ module.exports = {
transform: {
...tsjPreset.transform,
},
coveragePathIgnorePatterns: ['/Infra/'],
}
@@ -0,0 +1,15 @@
import { MigrationInterface, QueryRunner } from 'typeorm'
export class addEmailToAnalyticsEntity1667568051894 implements MigrationInterface {
name = 'addEmailToAnalyticsEntity1667568051894'
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query('ALTER TABLE `analytics_entities` ADD `user_email` varchar(255) NULL')
await queryRunner.query('CREATE INDEX `email` ON `analytics_entities` (`user_email`)')
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query('DROP INDEX `email` ON `analytics_entities`')
await queryRunner.query('ALTER TABLE `analytics_entities` DROP COLUMN `user_email`')
}
}
@@ -0,0 +1,17 @@
import { MigrationInterface, QueryRunner } from 'typeorm'
export class addRevenueModifications1667912580964 implements MigrationInterface {
name = 'addRevenueModifications1667912580964'
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
'CREATE TABLE `revenue_modifications` (`uuid` varchar(36) NOT NULL, `subscription_id` int NOT NULL, `user_email` varchar(255) NOT NULL, `user_uuid` varchar(36) NOT NULL, `event_type` varchar(255) NOT NULL, `subscription_plan` varchar(255) NOT NULL, `billing_frequency` int NOT NULL, `new_customer` tinyint NOT NULL, `previous_mrr` int NOT NULL, `new_mrr` int NOT NULL, INDEX `email` (`user_email`), INDEX `user_uuid` (`user_uuid`), PRIMARY KEY (`uuid`)) ENGINE=InnoDB',
)
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query('DROP INDEX `user_uuid` ON `revenue_modifications`')
await queryRunner.query('DROP INDEX `email` ON `revenue_modifications`')
await queryRunner.query('DROP TABLE `revenue_modifications`')
}
}
@@ -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`')
}
}
@@ -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')
}
}
+13 -14
View File
@@ -1,17 +1,14 @@
{
"name": "@standardnotes/analytics",
"version": "1.43.0",
"version": "2.10.0",
"engines": {
"node": ">=14.0.0 <17.0.0"
"node": ">=18.0.0 <19.0.0"
},
"private": true,
"description": "Analytics tools for Standard Notes projects",
"main": "dist/src/index.js",
"author": "Standard Notes",
"types": "dist/src/index.d.ts",
"files": [
"dist/src/**/*.js",
"dist/src/**/*.d.ts"
],
"publishConfig": {
"access": "public"
},
@@ -28,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",
"@typescript-eslint/eslint-plugin": "^5.30.0",
"eslint": "^8.14.0",
"eslint-plugin-prettier": "^4.2.1",
@@ -40,21 +37,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-core": "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",
"typeorm": "^0.3.6",
"typeorm": "^0.3.10",
"winston": "^3.8.1"
}
}
@@ -35,6 +35,23 @@ import { AnalyticsEntity } from '../Domain/Entity/AnalyticsEntity'
import { GetUserAnalyticsId } from '../Domain/UseCase/GetUserAnalyticsId/GetUserAnalyticsId'
import { UserRegisteredEventHandler } from '../Domain/Handler/UserRegisteredEventHandler'
import { AccountDeletionRequestedEventHandler } from '../Domain/Handler/AccountDeletionRequestedEventHandler'
import { PaymentFailedEventHandler } from '../Domain/Handler/PaymentFailedEventHandler'
import { PaymentSuccessEventHandler } from '../Domain/Handler/PaymentSuccessEventHandler'
import { SubscriptionCancelledEventHandler } from '../Domain/Handler/SubscriptionCancelledEventHandler'
import { SubscriptionRenewedEventHandler } from '../Domain/Handler/SubscriptionRenewedEventHandler'
import { SubscriptionRefundedEventHandler } from '../Domain/Handler/SubscriptionRefundedEventHandler'
import { SubscriptionPurchasedEventHandler } from '../Domain/Handler/SubscriptionPurchasedEventHandler'
import { SubscriptionExpiredEventHandler } from '../Domain/Handler/SubscriptionExpiredEventHandler'
import { SubscriptionReactivatedEventHandler } from '../Domain/Handler/SubscriptionReactivatedEventHandler'
import { RefundProcessedEventHandler } from '../Domain/Handler/RefundProcessedEventHandler'
import { RevenueModificationRepositoryInterface } from '../Domain/Revenue/RevenueModificationRepositoryInterface'
import { MySQLRevenueModificationRepository } from '../Infra/MySQL/MySQLRevenueModificationRepository'
import { TypeORMRevenueModification } from '../Infra/TypeORM/TypeORMRevenueModification'
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')
@@ -107,20 +124,56 @@ export class ContainerConfigLoader {
container
.bind<AnalyticsEntityRepositoryInterface>(TYPES.AnalyticsEntityRepository)
.to(MySQLAnalyticsEntityRepository)
container
.bind<RevenueModificationRepositoryInterface>(TYPES.RevenueModificationRepository)
.to(MySQLRevenueModificationRepository)
// ORM
container
.bind<Repository<AnalyticsEntity>>(TYPES.ORMAnalyticsEntityRepository)
.toConstantValue(AppDataSource.getRepository(AnalyticsEntity))
container
.bind<Repository<TypeORMRevenueModification>>(TYPES.ORMRevenueModificationRepository)
.toConstantValue(AppDataSource.getRepository(TypeORMRevenueModification))
// 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)
container
.bind<AccountDeletionRequestedEventHandler>(TYPES.AccountDeletionRequestedEventHandler)
.to(AccountDeletionRequestedEventHandler)
container.bind<PaymentFailedEventHandler>(TYPES.PaymentFailedEventHandler).to(PaymentFailedEventHandler)
container.bind<PaymentSuccessEventHandler>(TYPES.PaymentSuccessEventHandler).to(PaymentSuccessEventHandler)
container
.bind<SubscriptionCancelledEventHandler>(TYPES.SubscriptionCancelledEventHandler)
.to(SubscriptionCancelledEventHandler)
container
.bind<SubscriptionRenewedEventHandler>(TYPES.SubscriptionRenewedEventHandler)
.to(SubscriptionRenewedEventHandler)
container
.bind<SubscriptionRefundedEventHandler>(TYPES.SubscriptionRefundedEventHandler)
.to(SubscriptionRefundedEventHandler)
container
.bind<SubscriptionPurchasedEventHandler>(TYPES.SubscriptionPurchasedEventHandler)
.to(SubscriptionPurchasedEventHandler)
container
.bind<SubscriptionExpiredEventHandler>(TYPES.SubscriptionExpiredEventHandler)
.to(SubscriptionExpiredEventHandler)
container
.bind<SubscriptionReactivatedEventHandler>(TYPES.SubscriptionReactivatedEventHandler)
.to(SubscriptionReactivatedEventHandler)
container.bind<RefundProcessedEventHandler>(TYPES.RefundProcessedEventHandler).to(RefundProcessedEventHandler)
// Maps
container
.bind<MapInterface<RevenueModification, TypeORMRevenueModification>>(TYPES.RevenueModificationMap)
.to(RevenueModificationMap)
// Services
container.bind<DomainEventFactory>(TYPES.DomainEventFactory).to(DomainEventFactory)
@@ -147,6 +200,16 @@ export class ContainerConfigLoader {
const eventHandlers: Map<string, DomainEventHandlerInterface> = new Map([
['USER_REGISTERED', container.get(TYPES.UserRegisteredEventHandler)],
['ACCOUNT_DELETION_REQUESTED', container.get(TYPES.AccountDeletionRequestedEventHandler)],
['PAYMENT_FAILED', container.get(TYPES.PaymentFailedEventHandler)],
['PAYMENT_SUCCESS', container.get(TYPES.PaymentSuccessEventHandler)],
['SUBSCRIPTION_CANCELLED', container.get(TYPES.SubscriptionCancelledEventHandler)],
['SUBSCRIPTION_RENEWED', container.get(TYPES.SubscriptionRenewedEventHandler)],
['SUBSCRIPTION_REFUNDED', container.get(TYPES.SubscriptionRefundedEventHandler)],
['SUBSCRIPTION_PURCHASED', container.get(TYPES.SubscriptionPurchasedEventHandler)],
['SUBSCRIPTION_EXPIRED', container.get(TYPES.SubscriptionExpiredEventHandler)],
['SUBSCRIPTION_REACTIVATED', container.get(TYPES.SubscriptionReactivatedEventHandler)],
['REFUND_PROCESSED', container.get(TYPES.RefundProcessedEventHandler)],
])
if (env.get('SQS_QUEUE_URL', true)) {
@@ -1,6 +1,7 @@
import { DataSource, LoggerOptions } from 'typeorm'
import { AnalyticsEntity } from '../Domain/Entity/AnalyticsEntity'
import { TypeORMRevenueModification } from '../Infra/TypeORM/TypeORMRevenueModification'
import { Env } from './Env'
@@ -36,7 +37,7 @@ export const AppDataSource = new DataSource({
],
removeNodeErrorCount: 10,
},
entities: [AnalyticsEntity],
entities: [AnalyticsEntity, TypeORMRevenueModification],
migrations: [env.get('DB_MIGRATIONS_PATH', true) ?? 'dist/migrations/*.js'],
migrationsRun: true,
logging: <LoggerOptions>env.get('DB_DEBUG_LEVEL'),
+15
View File
@@ -13,13 +13,28 @@ const TYPES = {
NEW_RELIC_ENABLED: Symbol.for('NEW_RELIC_ENABLED'),
// Repositories
AnalyticsEntityRepository: Symbol.for('AnalyticsEntityRepository'),
RevenueModificationRepository: Symbol.for('RevenueModificationRepository'),
// ORM
ORMAnalyticsEntityRepository: Symbol.for('ORMAnalyticsEntityRepository'),
ORMRevenueModificationRepository: Symbol.for('ORMRevenueModificationRepository'),
// Use Case
GetUserAnalyticsId: Symbol.for('GetUserAnalyticsId'),
SaveRevenueModification: Symbol.for('SaveRevenueModification'),
CalculateMonthlyRecurringRevenue: Symbol.for('CalculateMonthlyRecurringRevenue'),
// Handlers
UserRegisteredEventHandler: Symbol.for('UserRegisteredEventHandler'),
AccountDeletionRequestedEventHandler: Symbol.for('AccountDeletionRequestedEventHandler'),
PaymentFailedEventHandler: Symbol.for('PaymentFailedEventHandler'),
PaymentSuccessEventHandler: Symbol.for('PaymentSuccessEventHandler'),
SubscriptionCancelledEventHandler: Symbol.for('SubscriptionCancelledEventHandler'),
SubscriptionRenewedEventHandler: Symbol.for('SubscriptionRenewedEventHandler'),
SubscriptionRefundedEventHandler: Symbol.for('SubscriptionRefundedEventHandler'),
SubscriptionPurchasedEventHandler: Symbol.for('SubscriptionPurchasedEventHandler'),
SubscriptionExpiredEventHandler: Symbol.for('SubscriptionExpiredEventHandler'),
SubscriptionReactivatedEventHandler: Symbol.for('SubscriptionReactivatedEventHandler'),
RefundProcessedEventHandler: Symbol.for('RefundProcessedEventHandler'),
// Maps
RevenueModificationMap: Symbol.for('RevenueModificationMap'),
// Services
DomainEventPublisher: Symbol.for('DomainEventPublisher'),
DomainEventSubscriberFactory: Symbol.for('DomainEventSubscriberFactory'),
@@ -1,10 +1,4 @@
export enum AnalyticsActivity {
GeneralActivity = 'general-activity',
GeneralActivityFreeUsers = 'general-activity-free-users',
GeneralActivityPaidUsers = 'general-activity-paid-users',
EditingItems = 'editing-items',
CheckingIntegrity = 'checking-integrity',
Login = 'login',
Register = 'register',
DeleteAccount = 'DeleteAccount',
SubscriptionPurchased = 'subscription-purchased',
@@ -13,8 +7,6 @@ export enum AnalyticsActivity {
SubscriptionCancelled = 'subscription-cancelled',
SubscriptionExpired = 'subscription-expired',
SubscriptionReactivated = 'subscription-reactivated',
EmailUnbackedUpData = 'email-unbacked-up-data',
EmailBackup = 'email-backup',
LimitedDiscountOfferPurchased = 'limited-discount-offer-purchased',
PaymentFailed = 'payment-failed',
PaymentSuccess = 'payment-success',
@@ -11,4 +11,12 @@ export class AnalyticsEntity {
})
@Index('user_uuid')
declare userUuid: string
@Column({
name: 'user_email',
length: 255,
nullable: true,
})
@Index('email')
declare userEmail: string
}
@@ -3,5 +3,7 @@ import { AnalyticsEntity } from './AnalyticsEntity'
export interface AnalyticsEntityRepositoryInterface {
save(analyticsEntity: AnalyticsEntity): Promise<AnalyticsEntity>
remove(analyticsEntity: AnalyticsEntity): Promise<void>
findOneByUserUuid(userUuid: Uuid): Promise<AnalyticsEntity | null>
findOneByUserEmail(email: string): Promise<AnalyticsEntity | null>
}
@@ -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,21 +51,16 @@ describe('DomainEventFactory', () => {
totalCount: 123,
},
],
outOfSyncIncidents: 324,
retentionStatistics: [
statisticsOverTime: [
{
firstActivity: AnalyticsActivity.Register,
secondActivity: AnalyticsActivity.Login,
retention: {
periodKeys: ['2022-10-9'],
values: [
{
firstPeriodKey: AnalyticsActivity.Register,
secondPeriodKey: AnalyticsActivity.Login,
value: 12,
},
],
},
name: StatisticsMeasure.MRR,
period: Period.Last30Days,
counts: [
{
periodKey: '2022-10-9',
totalCount: 3,
},
],
},
],
churn: {
@@ -120,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: {
@@ -135,29 +124,6 @@ describe('DomainEventFactory', () => {
},
],
},
outOfSyncIncidents: 324,
retentionStatistics: [
{
firstActivity: 'register',
retention: {
periodKeys: ['2022-10-9'],
values: [
{
firstPeriodKey: 'register',
secondPeriodKey: 'login',
value: 12,
},
],
},
secondActivity: 'login',
},
],
snjsStatistics: [
{
count: 2,
version: '1-2-3',
},
],
statisticMeasures: [
{
average: 23,
@@ -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>
@@ -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>
@@ -2,21 +2,21 @@ import 'reflect-metadata'
import { AccountDeletionRequestedEvent } from '@standardnotes/domain-events'
import { AccountDeletionRequestedEventHandler } from './AccountDeletionRequestedEventHandler'
import { GetUserAnalyticsId } from '../UseCase/GetUserAnalyticsId/GetUserAnalyticsId'
import { TimerInterface } from '@standardnotes/time'
import { AnalyticsStoreInterface } from '../Analytics/AnalyticsStoreInterface'
import { StatisticsStoreInterface } from '../Statistics/StatisticsStoreInterface'
import { Period } from '../Time/Period'
import { AnalyticsEntityRepositoryInterface } from '../Entity/AnalyticsEntityRepositoryInterface'
describe('AccountDeletionRequestedEventHandler', () => {
let event: AccountDeletionRequestedEvent
let getUserAnalyticsId: GetUserAnalyticsId
let analyticsEntityRepository: AnalyticsEntityRepositoryInterface
let analyticsStore: AnalyticsStoreInterface
let statisticsStore: StatisticsStoreInterface
let timer: TimerInterface
const createHandler = () =>
new AccountDeletionRequestedEventHandler(getUserAnalyticsId, analyticsStore, statisticsStore, timer)
new AccountDeletionRequestedEventHandler(analyticsEntityRepository, analyticsStore, statisticsStore, timer)
beforeEach(() => {
event = {} as jest.Mocked<AccountDeletionRequestedEvent>
@@ -27,8 +27,9 @@ describe('AccountDeletionRequestedEventHandler', () => {
regularSubscriptionUuid: '2-3-4',
}
getUserAnalyticsId = {} as jest.Mocked<GetUserAnalyticsId>
getUserAnalyticsId.execute = jest.fn().mockReturnValue({ analyticsId: 3 })
analyticsEntityRepository = {} as jest.Mocked<AnalyticsEntityRepositoryInterface>
analyticsEntityRepository.findOneByUserUuid = jest.fn().mockReturnValue({ id: 3 })
analyticsEntityRepository.remove = jest.fn()
analyticsStore = {} as jest.Mocked<AnalyticsStoreInterface>
analyticsStore.markActivity = jest.fn()
@@ -53,5 +54,16 @@ describe('AccountDeletionRequestedEventHandler', () => {
Period.ThisWeek,
Period.ThisMonth,
])
expect(analyticsEntityRepository.remove).toHaveBeenCalled()
})
it('should not mark anything if entity is not found', async () => {
analyticsEntityRepository.findOneByUserUuid = jest.fn().mockReturnValue(null)
await createHandler().handle(event)
expect(analyticsStore.markActivity).not.toHaveBeenCalled()
expect(statisticsStore.incrementMeasure).not.toHaveBeenCalled()
expect(analyticsEntityRepository.remove).not.toHaveBeenCalled()
})
})
@@ -5,23 +5,28 @@ import { inject, injectable } from 'inversify'
import TYPES from '../../Bootstrap/Types'
import { AnalyticsActivity } from '../Analytics/AnalyticsActivity'
import { AnalyticsStoreInterface } from '../Analytics/AnalyticsStoreInterface'
import { AnalyticsEntityRepositoryInterface } from '../Entity/AnalyticsEntityRepositoryInterface'
import { StatisticsMeasure } from '../Statistics/StatisticsMeasure'
import { StatisticsStoreInterface } from '../Statistics/StatisticsStoreInterface'
import { Period } from '../Time/Period'
import { GetUserAnalyticsId } from '../UseCase/GetUserAnalyticsId/GetUserAnalyticsId'
@injectable()
export class AccountDeletionRequestedEventHandler implements DomainEventHandlerInterface {
constructor(
@inject(TYPES.GetUserAnalyticsId) private getUserAnalyticsId: GetUserAnalyticsId,
@inject(TYPES.AnalyticsEntityRepository) private analyticsEntityRepository: AnalyticsEntityRepositoryInterface,
@inject(TYPES.AnalyticsStore) private analyticsStore: AnalyticsStoreInterface,
@inject(TYPES.StatisticsStore) private statisticsStore: StatisticsStoreInterface,
@inject(TYPES.Timer) private timer: TimerInterface,
) {}
async handle(event: AccountDeletionRequestedEvent): Promise<void> {
const { analyticsId } = await this.getUserAnalyticsId.execute({ userUuid: event.payload.userUuid })
await this.analyticsStore.markActivity([AnalyticsActivity.DeleteAccount], analyticsId, [
const analyticsEntity = await this.analyticsEntityRepository.findOneByUserUuid(event.payload.userUuid)
if (analyticsEntity === null) {
return
}
await this.analyticsStore.markActivity([AnalyticsActivity.DeleteAccount], analyticsEntity.id, [
Period.Today,
Period.ThisWeek,
Period.ThisMonth,
@@ -33,5 +38,7 @@ export class AccountDeletionRequestedEventHandler implements DomainEventHandlerI
Period.ThisWeek,
Period.ThisMonth,
])
await this.analyticsEntityRepository.remove(analyticsEntity)
}
}
@@ -1,28 +1,19 @@
import 'reflect-metadata'
import { PaymentFailedEvent } from '@standardnotes/domain-events'
import { AnalyticsStoreInterface } from '@standardnotes/analytics'
import { PaymentFailedEventHandler } from './PaymentFailedEventHandler'
import { UserRepositoryInterface } from '../User/UserRepositoryInterface'
import { User } from '../User/User'
import { GetUserAnalyticsId } from '../UseCase/GetUserAnalyticsId/GetUserAnalyticsId'
import { AnalyticsStoreInterface } from '../Analytics/AnalyticsStoreInterface'
describe('PaymentFailedEventHandler', () => {
let userRepository: UserRepositoryInterface
let event: PaymentFailedEvent
let user: User
let getUserAnalyticsId: GetUserAnalyticsId
let analyticsStore: AnalyticsStoreInterface
const createHandler = () => new PaymentFailedEventHandler(userRepository, getUserAnalyticsId, analyticsStore)
const createHandler = () => new PaymentFailedEventHandler(getUserAnalyticsId, analyticsStore)
beforeEach(() => {
user = {} as jest.Mocked<User>
userRepository = {} as jest.Mocked<UserRepositoryInterface>
userRepository.findOneByEmail = jest.fn().mockReturnValue(user)
getUserAnalyticsId = {} as jest.Mocked<GetUserAnalyticsId>
getUserAnalyticsId.execute = jest.fn().mockReturnValue({ analyticsId: 3 })
@@ -40,12 +31,4 @@ describe('PaymentFailedEventHandler', () => {
expect(analyticsStore.markActivity).toHaveBeenCalled()
})
it('should not mark payment failed for analytics if user is not found', async () => {
userRepository.findOneByEmail = jest.fn().mockReturnValue(null)
await createHandler().handle(event)
expect(analyticsStore.markActivity).not.toHaveBeenCalled()
})
})
@@ -1,26 +1,21 @@
import { AnalyticsActivity, AnalyticsStoreInterface, Period } from '@standardnotes/analytics'
import { DomainEventHandlerInterface, PaymentFailedEvent } from '@standardnotes/domain-events'
import { inject, injectable } from 'inversify'
import TYPES from '../../Bootstrap/Types'
import { AnalyticsActivity } from '../Analytics/AnalyticsActivity'
import { AnalyticsStoreInterface } from '../Analytics/AnalyticsStoreInterface'
import { Period } from '../Time/Period'
import { GetUserAnalyticsId } from '../UseCase/GetUserAnalyticsId/GetUserAnalyticsId'
import { UserRepositoryInterface } from '../User/UserRepositoryInterface'
@injectable()
export class PaymentFailedEventHandler implements DomainEventHandlerInterface {
constructor(
@inject(TYPES.UserRepository) private userRepository: UserRepositoryInterface,
@inject(TYPES.GetUserAnalyticsId) private getUserAnalyticsId: GetUserAnalyticsId,
@inject(TYPES.AnalyticsStore) private analyticsStore: AnalyticsStoreInterface,
) {}
async handle(event: PaymentFailedEvent): Promise<void> {
const user = await this.userRepository.findOneByEmail(event.payload.userEmail)
if (user === null) {
return
}
const { analyticsId } = await this.getUserAnalyticsId.execute({ userUuid: user.uuid })
const { analyticsId } = await this.getUserAnalyticsId.execute({ userEmail: event.payload.userEmail })
await this.analyticsStore.markActivity([AnalyticsActivity.PaymentFailed], analyticsId, [
Period.Today,
Period.ThisWeek,
@@ -1,32 +1,25 @@
import 'reflect-metadata'
import { PaymentSuccessEvent } from '@standardnotes/domain-events'
import { AnalyticsStoreInterface, Period, StatisticsStoreInterface } from '@standardnotes/analytics'
import { PaymentSuccessEventHandler } from './PaymentSuccessEventHandler'
import { UserRepositoryInterface } from '../User/UserRepositoryInterface'
import { User } from '../User/User'
import { GetUserAnalyticsId } from '../UseCase/GetUserAnalyticsId/GetUserAnalyticsId'
import { Logger } from 'winston'
import { StatisticsStoreInterface } from '../Statistics/StatisticsStoreInterface'
import { AnalyticsStoreInterface } from '../Analytics/AnalyticsStoreInterface'
import { Period } from '../Time/Period'
describe('PaymentSuccessEventHandler', () => {
let userRepository: UserRepositoryInterface
let event: PaymentSuccessEvent
let user: User
let getUserAnalyticsId: GetUserAnalyticsId
let analyticsStore: AnalyticsStoreInterface
let statisticsStore: StatisticsStoreInterface
let logger: Logger
const createHandler = () =>
new PaymentSuccessEventHandler(userRepository, getUserAnalyticsId, analyticsStore, statisticsStore, logger)
new PaymentSuccessEventHandler(getUserAnalyticsId, analyticsStore, statisticsStore, logger)
beforeEach(() => {
user = {} as jest.Mocked<User>
userRepository = {} as jest.Mocked<UserRepositoryInterface>
userRepository.findOneByEmail = jest.fn().mockReturnValue(user)
getUserAnalyticsId = {} as jest.Mocked<GetUserAnalyticsId>
getUserAnalyticsId.execute = jest.fn().mockReturnValue({ analyticsId: 3 })
@@ -79,12 +72,4 @@ describe('PaymentSuccessEventHandler', () => {
Period.ThisMonth,
])
})
it('should not mark payment failed for analytics if user is not found', async () => {
userRepository.findOneByEmail = jest.fn().mockReturnValue(null)
await createHandler().handle(event)
expect(analyticsStore.markActivity).not.toHaveBeenCalled()
})
})
@@ -1,18 +1,15 @@
import {
AnalyticsActivity,
AnalyticsStoreInterface,
Period,
StatisticsMeasure,
StatisticsStoreInterface,
} from '@standardnotes/analytics'
import { PaymentType, SubscriptionBillingFrequency, SubscriptionName } from '@standardnotes/common'
import { DomainEventHandlerInterface, PaymentSuccessEvent } 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 { StatisticsMeasure } from '../Statistics/StatisticsMeasure'
import { StatisticsStoreInterface } from '../Statistics/StatisticsStoreInterface'
import { Period } from '../Time/Period'
import { GetUserAnalyticsId } from '../UseCase/GetUserAnalyticsId/GetUserAnalyticsId'
import { UserRepositoryInterface } from '../User/UserRepositoryInterface'
@injectable()
export class PaymentSuccessEventHandler implements DomainEventHandlerInterface {
@@ -58,7 +55,6 @@ export class PaymentSuccessEventHandler implements DomainEventHandlerInterface {
])
constructor(
@inject(TYPES.UserRepository) private userRepository: UserRepositoryInterface,
@inject(TYPES.GetUserAnalyticsId) private getUserAnalyticsId: GetUserAnalyticsId,
@inject(TYPES.AnalyticsStore) private analyticsStore: AnalyticsStoreInterface,
@inject(TYPES.StatisticsStore) private statisticsStore: StatisticsStoreInterface,
@@ -66,12 +62,7 @@ export class PaymentSuccessEventHandler implements DomainEventHandlerInterface {
) {}
async handle(event: PaymentSuccessEvent): Promise<void> {
const user = await this.userRepository.findOneByEmail(event.payload.userEmail)
if (user === null) {
return
}
const { analyticsId } = await this.getUserAnalyticsId.execute({ userUuid: user.uuid })
const { analyticsId } = await this.getUserAnalyticsId.execute({ userEmail: event.payload.userEmail })
await this.analyticsStore.markActivity([AnalyticsActivity.PaymentSuccess], analyticsId, [
Period.Today,
Period.ThisWeek,
@@ -1,9 +1,11 @@
import 'reflect-metadata'
import { RefundProcessedEvent } from '@standardnotes/domain-events'
import { Period, StatisticsMeasure, StatisticsStoreInterface } from '@standardnotes/analytics'
import { RefundProcessedEventHandler } from './RefundProcessedEventHandler'
import { StatisticsMeasure } from '../Statistics/StatisticsMeasure'
import { StatisticsStoreInterface } from '../Statistics/StatisticsStoreInterface'
import { Period } from '../Time/Period'
describe('RefundProcessedEventHandler', () => {
let event: RefundProcessedEvent
@@ -1,8 +1,10 @@
import { Period, StatisticsMeasure, StatisticsStoreInterface } from '@standardnotes/analytics'
import { DomainEventHandlerInterface, RefundProcessedEvent } from '@standardnotes/domain-events'
import { inject, injectable } from 'inversify'
import TYPES from '../../Bootstrap/Types'
import { StatisticsMeasure } from '../Statistics/StatisticsMeasure'
import { StatisticsStoreInterface } from '../Statistics/StatisticsStoreInterface'
import { Period } from '../Time/Period'
@injectable()
export class RefundProcessedEventHandler implements DomainEventHandlerInterface {
@@ -0,0 +1,104 @@
import 'reflect-metadata'
import { SubscriptionName } from '@standardnotes/common'
import { SubscriptionCancelledEvent } from '@standardnotes/domain-events'
import { SubscriptionCancelledEventHandler } from './SubscriptionCancelledEventHandler'
import { GetUserAnalyticsId } from '../UseCase/GetUserAnalyticsId/GetUserAnalyticsId'
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,
saveRevenueModification,
logger,
)
beforeEach(() => {
logger = {} as jest.Mocked<Logger>
logger.error = jest.fn()
getUserAnalyticsId = {} as jest.Mocked<GetUserAnalyticsId>
getUserAnalyticsId.execute = jest.fn().mockReturnValue({ analyticsId: 3 })
analyticsStore = {} as jest.Mocked<AnalyticsStoreInterface>
analyticsStore.markActivity = jest.fn()
statisticsStore = {} as jest.Mocked<StatisticsStoreInterface>
statisticsStore.incrementMeasure = jest.fn()
event = {} as jest.Mocked<SubscriptionCancelledEvent>
event.createdAt = new Date(1)
event.type = 'SUBSCRIPTION_CANCELLED'
event.payload = {
subscriptionId: 1,
userEmail: 'test@test.com',
subscriptionName: SubscriptionName.ProPlan,
subscriptionCreatedAt: 1642395451515000,
subscriptionUpdatedAt: 1642395451515001,
lastPayedAt: 1642395451515001,
subscriptionEndsAt: 1642395451515000 + 10,
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 () => {
event.payload.timestamp = 1642395451516000
await createHandler().handle(event)
expect(analyticsStore.markActivity).toHaveBeenCalled()
expect(statisticsStore.incrementMeasure).toHaveBeenCalledWith(StatisticsMeasure.SubscriptionLength, 1000, [
Period.Today,
Period.ThisWeek,
Period.ThisMonth,
])
expect(saveRevenueModification.execute).toHaveBeenCalled()
})
it('should not track statistics for subscriptions that are in a legacy 5 year plan', async () => {
event.payload.timestamp = 1642395451516000
event.payload.subscriptionEndsAt = 1642395451515000 + 126_230_400_000_001
event.payload.subscriptionCreatedAt = 1642395451515000
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()
})
})
@@ -0,0 +1,84 @@
import { DomainEventHandlerInterface, SubscriptionCancelledEvent } from '@standardnotes/domain-events'
import { inject, injectable } from 'inversify'
import { Logger } from 'winston'
import { Email } from '@standardnotes/domain-core'
import TYPES from '../../Bootstrap/Types'
import { AnalyticsActivity } from '../Analytics/AnalyticsActivity'
import { AnalyticsStoreInterface } from '../Analytics/AnalyticsStoreInterface'
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 {
constructor(
@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, userUuid } = await this.getUserAnalyticsId.execute({ userEmail: event.payload.userEmail })
await this.analyticsStore.markActivity([AnalyticsActivity.SubscriptionCancelled], analyticsId, [
Period.Today,
Period.ThisWeek,
Period.ThisMonth,
])
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) {
if (this.isLegacy5yearSubscriptionPlan(event.payload.subscriptionEndsAt, event.payload.subscriptionCreatedAt)) {
return
}
const subscriptionLength = event.payload.timestamp - event.payload.subscriptionCreatedAt
await this.statisticsStore.incrementMeasure(StatisticsMeasure.SubscriptionLength, subscriptionLength, [
Period.Today,
Period.ThisWeek,
Period.ThisMonth,
])
const remainingSubscriptionTime = event.payload.subscriptionEndsAt - event.payload.timestamp
const totalSubscriptionTime = event.payload.subscriptionEndsAt - event.payload.lastPayedAt
const remainingSubscriptionPercentage = Math.floor((remainingSubscriptionTime / totalSubscriptionTime) * 100)
await this.statisticsStore.incrementMeasure(
StatisticsMeasure.RemainingSubscriptionTimePercentage,
remainingSubscriptionPercentage,
[Period.Today, Period.ThisWeek, Period.ThisMonth],
)
}
private isLegacy5yearSubscriptionPlan(subscriptionEndsAt: number, subscriptionCreatedAt: number) {
const fourYearsInMicroseconds = 126_230_400_000_000
return subscriptionEndsAt - subscriptionCreatedAt > fourYearsInMicroseconds
}
}
@@ -0,0 +1,79 @@
import 'reflect-metadata'
import { SubscriptionName } from '@standardnotes/common'
import { SubscriptionExpiredEvent } from '@standardnotes/domain-events'
import { SubscriptionExpiredEventHandler } from './SubscriptionExpiredEventHandler'
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,
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',
subscriptionName: SubscriptionName.PlusPlan,
timestamp: 1,
offline: false,
totalActiveSubscriptionsCount: 123,
userExistingSubscriptionsCount: 2,
billingFrequency: 1,
payAmount: 12.99,
}
getUserAnalyticsId = {} as jest.Mocked<GetUserAnalyticsId>
getUserAnalyticsId.execute = jest.fn().mockReturnValue({ analyticsId: 3 })
analyticsStore = {} as jest.Mocked<AnalyticsStoreInterface>
analyticsStore.markActivity = jest.fn()
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 () => {
await createHandler().handle(event)
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()
})
})
@@ -0,0 +1,58 @@
import { DomainEventHandlerInterface, SubscriptionExpiredEvent } from '@standardnotes/domain-events'
import { inject, injectable } from 'inversify'
import { Logger } from 'winston'
import { Email } from '@standardnotes/domain-core'
import TYPES from '../../Bootstrap/Types'
import { AnalyticsActivity } from '../Analytics/AnalyticsActivity'
import { AnalyticsStoreInterface } from '../Analytics/AnalyticsStoreInterface'
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 {
constructor(
@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, userUuid } = await this.getUserAnalyticsId.execute({ userEmail: event.payload.userEmail })
await this.analyticsStore.markActivity(
[AnalyticsActivity.SubscriptionExpired, AnalyticsActivity.ExistingCustomersChurn],
analyticsId,
[Period.Today, Period.ThisWeek, Period.ThisMonth],
)
await this.statisticsStore.setMeasure(
StatisticsMeasure.TotalCustomers,
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()}`,
)
}
}
}
@@ -0,0 +1,102 @@
import 'reflect-metadata'
import { SubscriptionName } from '@standardnotes/common'
import { SubscriptionPurchasedEvent } from '@standardnotes/domain-events'
import { SubscriptionPurchasedEventHandler } from './SubscriptionPurchasedEventHandler'
import { GetUserAnalyticsId } from '../UseCase/GetUserAnalyticsId/GetUserAnalyticsId'
import { AnalyticsStoreInterface } from '../Analytics/AnalyticsStoreInterface'
import { StatisticsStoreInterface } from '../Statistics/StatisticsStoreInterface'
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
let subscriptionExpiresAt: number
let getUserAnalyticsId: GetUserAnalyticsId
let analyticsStore: AnalyticsStoreInterface
let statisticsStore: StatisticsStoreInterface
let saveRevenueModification: SaveRevenueModification
let logger: Logger
const createHandler = () =>
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()
event = {} as jest.Mocked<SubscriptionPurchasedEvent>
event.createdAt = new Date(1)
event.type = 'SUBSCRIPTION_PURCHASED'
event.payload = {
subscriptionId: 1,
userEmail: 'test@test.com',
subscriptionName: SubscriptionName.ProPlan,
subscriptionExpiresAt,
timestamp: 60,
offline: false,
discountCode: null,
limitedDiscountPurchased: false,
newSubscriber: true,
totalActiveSubscriptionsCount: 123,
userRegisteredAt: 23,
billingFrequency: 12,
payAmount: 29.99,
}
getUserAnalyticsId = {} as jest.Mocked<GetUserAnalyticsId>
getUserAnalyticsId.execute = jest.fn().mockReturnValue({ analyticsId: 3 })
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 mark subscription creation statistics', async () => {
await createHandler().handle(event)
expect(statisticsStore.incrementMeasure).toHaveBeenCalled()
expect(saveRevenueModification.execute).toHaveBeenCalled()
})
it("should not measure registration to subscription time if this is not user's first subscription", async () => {
event.payload.newSubscriber = false
await createHandler().handle(event)
expect(statisticsStore.incrementMeasure).not.toHaveBeenCalled()
})
it('should update analytics on limited discount offer purchasing', async () => {
event.payload.limitedDiscountPurchased = true
await createHandler().handle(event)
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()
})
})
@@ -0,0 +1,82 @@
import { DomainEventHandlerInterface, SubscriptionPurchasedEvent } from '@standardnotes/domain-events'
import { inject, injectable } from 'inversify'
import { Logger } from 'winston'
import { Email } from '@standardnotes/domain-core'
import TYPES from '../../Bootstrap/Types'
import { AnalyticsActivity } from '../Analytics/AnalyticsActivity'
import { AnalyticsStoreInterface } from '../Analytics/AnalyticsStoreInterface'
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 SubscriptionPurchasedEventHandler implements DomainEventHandlerInterface {
constructor(
@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: SubscriptionPurchasedEvent): Promise<void> {
const { analyticsId, userUuid } = await this.getUserAnalyticsId.execute({ userEmail: event.payload.userEmail })
await this.analyticsStore.markActivity([AnalyticsActivity.SubscriptionPurchased], analyticsId, [
Period.Today,
Period.ThisWeek,
Period.ThisMonth,
])
await this.analyticsStore.unmarkActivity(
[AnalyticsActivity.ExistingCustomersChurn, AnalyticsActivity.NewCustomersChurn],
analyticsId,
[Period.Today, Period.ThisWeek, Period.ThisMonth],
)
if (event.payload.limitedDiscountPurchased) {
await this.analyticsStore.markActivity([AnalyticsActivity.LimitedDiscountOfferPurchased], analyticsId, [
Period.Today,
])
}
if (event.payload.newSubscriber) {
await this.statisticsStore.incrementMeasure(
StatisticsMeasure.RegistrationToSubscriptionTime,
event.payload.timestamp - event.payload.userRegisteredAt,
[Period.Today, Period.ThisWeek, Period.ThisMonth],
)
await this.statisticsStore.incrementMeasure(StatisticsMeasure.NewCustomers, 1, [
Period.Today,
Period.ThisWeek,
Period.ThisMonth,
Period.ThisYear,
])
await this.statisticsStore.setMeasure(
StatisticsMeasure.TotalCustomers,
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.newSubscriber,
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()}`,
)
}
}
}
@@ -1,41 +1,21 @@
import 'reflect-metadata'
import { RoleName, SubscriptionName } from '@standardnotes/common'
import { SubscriptionName } from '@standardnotes/common'
import { SubscriptionReactivatedEvent } from '@standardnotes/domain-events'
import { Logger } from 'winston'
import { User } from '../User/User'
import { UserRepositoryInterface } from '../User/UserRepositoryInterface'
import { SubscriptionReactivatedEventHandler } from './SubscriptionReactivatedEventHandler'
import { AnalyticsStoreInterface, Period } from '@standardnotes/analytics'
import { GetUserAnalyticsId } from '../UseCase/GetUserAnalyticsId/GetUserAnalyticsId'
import { AnalyticsStoreInterface } from '../Analytics/AnalyticsStoreInterface'
import { Period } from '../Time/Period'
describe('SubscriptionReactivatedEventHandler', () => {
let userRepository: UserRepositoryInterface
let logger: Logger
let user: User
let event: SubscriptionReactivatedEvent
let getUserAnalyticsId: GetUserAnalyticsId
let analyticsStore: AnalyticsStoreInterface
const createHandler = () =>
new SubscriptionReactivatedEventHandler(userRepository, analyticsStore, getUserAnalyticsId, logger)
const createHandler = () => new SubscriptionReactivatedEventHandler(analyticsStore, getUserAnalyticsId)
beforeEach(() => {
user = {
uuid: '123',
email: 'test@test.com',
roles: Promise.resolve([
{
name: RoleName.ProUser,
},
]),
} as jest.Mocked<User>
userRepository = {} as jest.Mocked<UserRepositoryInterface>
userRepository.findOneByEmail = jest.fn().mockReturnValue(user)
userRepository.save = jest.fn().mockReturnValue(user)
event = {} as jest.Mocked<SubscriptionReactivatedEvent>
event.createdAt = new Date(1)
event.payload = {
@@ -52,10 +32,6 @@ describe('SubscriptionReactivatedEventHandler', () => {
analyticsStore = {} as jest.Mocked<AnalyticsStoreInterface>
analyticsStore.markActivity = jest.fn()
logger = {} as jest.Mocked<Logger>
logger.info = jest.fn()
logger.warn = jest.fn()
})
it('should mark subscription reactivated activity for analytics', async () => {
@@ -67,12 +43,4 @@ describe('SubscriptionReactivatedEventHandler', () => {
Period.ThisMonth,
])
})
it('should not do anything if no user is found for specified email', async () => {
userRepository.findOneByEmail = jest.fn().mockReturnValue(null)
await createHandler().handle(event)
expect(analyticsStore.markActivity).not.toHaveBeenCalled()
})
})
@@ -1,30 +1,21 @@
import { AnalyticsActivity, AnalyticsStoreInterface, Period } from '@standardnotes/analytics'
import { DomainEventHandlerInterface, SubscriptionReactivatedEvent } 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 { Period } from '../Time/Period'
import { GetUserAnalyticsId } from '../UseCase/GetUserAnalyticsId/GetUserAnalyticsId'
import { UserRepositoryInterface } from '../User/UserRepositoryInterface'
@injectable()
export class SubscriptionReactivatedEventHandler implements DomainEventHandlerInterface {
constructor(
@inject(TYPES.UserRepository) private userRepository: UserRepositoryInterface,
@inject(TYPES.AnalyticsStore) private analyticsStore: AnalyticsStoreInterface,
@inject(TYPES.GetUserAnalyticsId) private getUserAnalyticsId: GetUserAnalyticsId,
@inject(TYPES.Logger) private logger: Logger,
) {}
async handle(event: SubscriptionReactivatedEvent): Promise<void> {
const user = await this.userRepository.findOneByEmail(event.payload.userEmail)
if (user === null) {
this.logger.warn(`Could not find user with email: ${event.payload.userEmail}`)
return
}
const { analyticsId } = await this.getUserAnalyticsId.execute({ userUuid: user.uuid })
const { analyticsId } = await this.getUserAnalyticsId.execute({ userEmail: event.payload.userEmail })
await this.analyticsStore.markActivity([AnalyticsActivity.SubscriptionReactivated], analyticsId, [
Period.Today,
Period.ThisWeek,
@@ -0,0 +1,110 @@
import 'reflect-metadata'
import { SubscriptionName } from '@standardnotes/common'
import { SubscriptionRefundedEvent } from '@standardnotes/domain-events'
import { GetUserAnalyticsId } from '../UseCase/GetUserAnalyticsId/GetUserAnalyticsId'
import { AnalyticsStoreInterface } from '../Analytics/AnalyticsStoreInterface'
import { SubscriptionRefundedEventHandler } from './SubscriptionRefundedEventHandler'
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,
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',
subscriptionName: SubscriptionName.PlusPlan,
timestamp: 1,
offline: false,
userExistingSubscriptionsCount: 3,
totalActiveSubscriptionsCount: 1,
billingFrequency: 1,
payAmount: 12.99,
}
getUserAnalyticsId = {} as jest.Mocked<GetUserAnalyticsId>
getUserAnalyticsId.execute = jest.fn().mockReturnValue({ analyticsId: 3 })
analyticsStore = {} as jest.Mocked<AnalyticsStoreInterface>
analyticsStore.markActivity = jest.fn()
analyticsStore.wasActivityDone = jest.fn().mockReturnValue(true)
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 () => {
event.payload.userExistingSubscriptionsCount = 1
await createHandler().handle(event)
expect(analyticsStore.markActivity).toHaveBeenCalledWith([AnalyticsActivity.SubscriptionRefunded], 3, [
Period.Today,
Period.ThisWeek,
Period.ThisMonth,
])
expect(analyticsStore.markActivity).toHaveBeenCalledWith([AnalyticsActivity.NewCustomersChurn], 3, [
Period.ThisMonth,
])
expect(saveRevenueModification.execute).toHaveBeenCalled()
})
it('should mark churn for existing customer', async () => {
await createHandler().handle(event)
expect(analyticsStore.markActivity).toHaveBeenCalledWith([AnalyticsActivity.ExistingCustomersChurn], 3, [
Period.ThisMonth,
])
})
it('should not mark churn if customer did not purchase subscription in defined analytic periods', async () => {
analyticsStore.wasActivityDone = jest.fn().mockReturnValue(false)
await createHandler().handle(event)
expect(analyticsStore.markActivity).not.toHaveBeenCalledWith([AnalyticsActivity.ExistingCustomersChurn], 3, [
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()
})
})
@@ -0,0 +1,78 @@
import { DomainEventHandlerInterface, SubscriptionRefundedEvent } from '@standardnotes/domain-events'
import { inject, injectable } from 'inversify'
import { Logger } from 'winston'
import { Email } from '@standardnotes/domain-core'
import TYPES from '../../Bootstrap/Types'
import { AnalyticsActivity } from '../Analytics/AnalyticsActivity'
import { AnalyticsStoreInterface } from '../Analytics/AnalyticsStoreInterface'
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 {
constructor(
@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, userUuid } = await this.getUserAnalyticsId.execute({ userEmail: event.payload.userEmail })
await this.analyticsStore.markActivity([AnalyticsActivity.SubscriptionRefunded], analyticsId, [
Period.Today,
Period.ThisWeek,
Period.ThisMonth,
])
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> {
const churnActivity =
event.payload.userExistingSubscriptionsCount > 1
? AnalyticsActivity.ExistingCustomersChurn
: AnalyticsActivity.NewCustomersChurn
for (const period of [Period.ThisMonth, Period.ThisWeek, Period.Today]) {
const customerPurchasedInPeriod = await this.analyticsStore.wasActivityDone(
AnalyticsActivity.SubscriptionPurchased,
analyticsId,
period,
)
if (customerPurchasedInPeriod) {
await this.analyticsStore.markActivity([churnActivity], analyticsId, [period])
}
}
await this.statisticsStore.setMeasure(
StatisticsMeasure.TotalCustomers,
event.payload.totalActiveSubscriptionsCount,
[Period.Today, Period.ThisWeek, Period.ThisMonth, Period.ThisYear],
)
}
}
@@ -0,0 +1,68 @@
import 'reflect-metadata'
import { SubscriptionName } from '@standardnotes/common'
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, 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',
subscriptionName: SubscriptionName.ProPlan,
subscriptionExpiresAt: 2,
timestamp: 1,
offline: false,
billingFrequency: 1,
payAmount: 12.99,
}
getUserAnalyticsId = {} as jest.Mocked<GetUserAnalyticsId>
getUserAnalyticsId.execute = jest.fn().mockReturnValue({ analyticsId: 3 })
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 () => {
await createHandler().handle(event)
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()
})
})
@@ -0,0 +1,54 @@
import { DomainEventHandlerInterface, SubscriptionRenewedEvent } from '@standardnotes/domain-events'
import { inject, injectable } from 'inversify'
import { Email } from '@standardnotes/domain-core'
import TYPES from '../../Bootstrap/Types'
import { GetUserAnalyticsId } from '../UseCase/GetUserAnalyticsId/GetUserAnalyticsId'
import { AnalyticsActivity } from '../Analytics/AnalyticsActivity'
import { AnalyticsStoreInterface } from '../Analytics/AnalyticsStoreInterface'
import { Period } from '../Time/Period'
import { SaveRevenueModification } from '../UseCase/SaveRevenueModification/SaveRevenueModification'
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, userUuid } = await this.getUserAnalyticsId.execute({ userEmail: event.payload.userEmail })
await this.analyticsStore.markActivity([AnalyticsActivity.SubscriptionRenewed], analyticsId, [
Period.Today,
Period.ThisWeek,
Period.ThisMonth,
])
await this.analyticsStore.unmarkActivity(
[AnalyticsActivity.ExistingCustomersChurn, AnalyticsActivity.NewCustomersChurn],
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()}`,
)
}
}
}
@@ -18,6 +18,7 @@ export class UserRegisteredEventHandler implements DomainEventHandlerInterface {
async handle(event: UserRegisteredEvent): Promise<void> {
let analyticsEntity = new AnalyticsEntity()
analyticsEntity.userUuid = event.payload.userUuid
analyticsEntity.userEmail = event.payload.email
analyticsEntity = await this.analyticsEntityRepository.save(analyticsEntity)
await this.analyticsStore.markActivity([AnalyticsActivity.Register], analyticsEntity.id, [
@@ -0,0 +1,4 @@
export interface MapInterface<T, U> {
toDomain(persistence: U): T
toPersistence(domain: T): U
}
@@ -0,0 +1,80 @@
import { injectable } from 'inversify'
import { Email, UniqueEntityId } from '@standardnotes/domain-core'
import { TypeORMRevenueModification } from '../../Infra/TypeORM/TypeORMRevenueModification'
import { MonthlyRevenue } from '../Revenue/MonthlyRevenue'
import { RevenueModification } from '../Revenue/RevenueModification'
import { Subscription } from '../Subscription/Subscription'
import { User } from '../User/User'
import { MapInterface } from './MapInterface'
import { SubscriptionPlanName } from '../Subscription/SubscriptionPlanName'
import { SubscriptionEventType } from '../Subscription/SubscriptionEventType'
@injectable()
export class RevenueModificationMap implements MapInterface<RevenueModification, TypeORMRevenueModification> {
toDomain(persistence: TypeORMRevenueModification): RevenueModification {
const userOrError = User.create(
{
email: Email.create(persistence.userEmail).getValue(),
},
new UniqueEntityId(persistence.userUuid),
)
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,
payedAmount: persistence.billingFrequency * persistence.newMonthlyRevenue,
planName: SubscriptionPlanName.create(persistence.subscriptionPlan).getValue(),
},
new UniqueEntityId(persistence.subscriptionId),
)
if (subscriptionOrError.isFailed()) {
throw new Error(`Could not create subscription: ${subscriptionOrError.getError()}`)
}
const subscription = subscriptionOrError.getValue()
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 {
const { subscription, user } = domain.props
const persistence = new TypeORMRevenueModification()
persistence.uuid = domain.id.toString()
persistence.billingFrequency = subscription.props.billingFrequency
persistence.eventType = domain.props.eventType.value
persistence.isNewCustomer = subscription.props.isFirstSubscriptionForUser
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
}
}
@@ -0,0 +1,16 @@
import { MonthlyRevenue } from './MonthlyRevenue'
describe('MonthlyRevenue', () => {
it('should create a value object', () => {
const valueOrError = MonthlyRevenue.create(123)
expect(valueOrError.isFailed()).toBeFalsy()
expect(valueOrError.getValue().value).toEqual(123)
})
it('should not create an invalid value object', () => {
const valueOrError = MonthlyRevenue.create(-3)
expect(valueOrError.isFailed()).toBeTruthy()
})
})
@@ -0,0 +1,21 @@
import { Result, ValueObject } from '@standardnotes/domain-core'
import { MonthlyRevenueProps } from './MonthlyRevenueProps'
export class MonthlyRevenue extends ValueObject<MonthlyRevenueProps> {
get value(): number {
return this.props.value
}
private constructor(props: MonthlyRevenueProps) {
super(props)
}
static create(revenue: number): Result<MonthlyRevenue> {
if (isNaN(revenue) || revenue < 0) {
return Result.fail<MonthlyRevenue>(`Monthly revenue must be a non-negative number. Supplied: ${revenue}`)
} else {
return Result.ok<MonthlyRevenue>(new MonthlyRevenue({ value: revenue }))
}
}
}
@@ -0,0 +1,3 @@
export interface MonthlyRevenueProps {
value: number
}
@@ -0,0 +1,38 @@
import { Email } from '../Common/Email'
import { Subscription } from '../Subscription/Subscription'
import { SubscriptionEventType } from '../Subscription/SubscriptionEventType'
import { SubscriptionPlanName } from '../Subscription/SubscriptionPlanName'
import { User } from '../User/User'
import { MonthlyRevenue } from './MonthlyRevenue'
import { RevenueModification } from './RevenueModification'
describe('RevenueModification', () => {
let user: User
let subscription: Subscription
beforeEach(() => {
subscription = Subscription.create({
billingFrequency: 12,
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.props.newMonthlyRevenue.value).toEqual(45)
})
})
@@ -0,0 +1,13 @@
import { Aggregate, UniqueEntityId, Result } from '@standardnotes/domain-core'
import { RevenueModificationProps } from './RevenueModificationProps'
export class RevenueModification extends Aggregate<RevenueModificationProps> {
private constructor(props: RevenueModificationProps, id?: UniqueEntityId) {
super(props, id)
}
static create(props: RevenueModificationProps, id?: UniqueEntityId): Result<RevenueModification> {
return Result.ok<RevenueModification>(new RevenueModification(props, id))
}
}
@@ -0,0 +1,13 @@
import { MonthlyRevenue } from './MonthlyRevenue'
import { Subscription } from '../Subscription/Subscription'
import { User } from '../User/User'
import { SubscriptionEventType } from '../Subscription/SubscriptionEventType'
export interface RevenueModificationProps {
user: User
subscription: Subscription
eventType: SubscriptionEventType
previousMonthlyRevenue: MonthlyRevenue
newMonthlyRevenue: MonthlyRevenue
createdAt: number
}
@@ -0,0 +1,9 @@
import { Uuid } from '@standardnotes/domain-core'
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>
}
@@ -13,9 +13,12 @@ export enum StatisticsMeasure {
RegistrationToSubscriptionTime = 'registration-to-subscription-time',
RemainingSubscriptionTimePercentage = 'remaining-subscription-time-percentage',
Refunds = 'refunds',
NotesCountFreeUsers = 'notes-count-free-users',
NotesCountPaidUsers = 'notes-count-paid-users',
FilesCount = 'files-count',
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',
}
@@ -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 }>>
}
@@ -0,0 +1,15 @@
import { Subscription } from './Subscription'
import { SubscriptionPlanName } from './SubscriptionPlanName'
describe('Subscription', () => {
it('should create an entity', () => {
const subscription = Subscription.create({
billingFrequency: 1,
isFirstSubscriptionForUser: true,
payedAmount: 12.99,
planName: SubscriptionPlanName.create('PRO_PLAN').getValue(),
}).getValue()
expect(subscription.id.toString()).toHaveLength(36)
})
})
@@ -0,0 +1,17 @@
import { Entity, Result, UniqueEntityId } from '@standardnotes/domain-core'
import { SubscriptionProps } from './SubscriptionProps'
export class Subscription extends Entity<SubscriptionProps> {
get id(): UniqueEntityId {
return this._id
}
private constructor(props: SubscriptionProps, id?: UniqueEntityId) {
super(props, id)
}
static create(props: SubscriptionProps, id?: UniqueEntityId): Result<Subscription> {
return Result.ok<Subscription>(new Subscription(props, id))
}
}
@@ -0,0 +1,16 @@
import { SubscriptionEventType } from './SubscriptionEventType'
describe('SubscriptionEventType', () => {
it('should create a value object', () => {
const valueOrError = SubscriptionEventType.create('SUBSCRIPTION_PURCHASED')
expect(valueOrError.isFailed()).toBeFalsy()
expect(valueOrError.getValue().value).toEqual('SUBSCRIPTION_PURCHASED')
})
it('should not create an invalid value object', () => {
const valueOrError = SubscriptionEventType.create('SUBSCRIPTION_REACTIVATED')
expect(valueOrError.isFailed()).toBeTruthy()
})
})
@@ -0,0 +1,30 @@
import { ValueObject, Result } from '@standardnotes/domain-core'
import { SubscriptionEventTypeProps } from './SubscriptionEventTypeProps'
export class SubscriptionEventType extends ValueObject<SubscriptionEventTypeProps> {
get value(): string {
return this.props.value
}
private constructor(props: SubscriptionEventTypeProps) {
super(props)
}
static create(subscriptionEventType: string): Result<SubscriptionEventType> {
if (
![
'SUBSCRIPTION_PURCHASED',
'SUBSCRIPTION_RENEWED',
'SUBSCRIPTION_EXPIRED',
'SUBSCRIPTION_REFUNDED',
'SUBSCRIPTION_CANCELLED',
'SUBSCRIPTION_DATA_MIGRATED',
].includes(subscriptionEventType)
) {
return Result.fail<SubscriptionEventType>(`Invalid subscription event type ${subscriptionEventType}`)
} else {
return Result.ok<SubscriptionEventType>(new SubscriptionEventType({ value: subscriptionEventType }))
}
}
}
@@ -0,0 +1,3 @@
export interface SubscriptionEventTypeProps {
value: string
}
@@ -0,0 +1,16 @@
import { SubscriptionPlanName } from './SubscriptionPlanName'
describe('SubscriptionPlanName', () => {
it('should create a value object', () => {
const valueOrError = SubscriptionPlanName.create('PRO_PLAN')
expect(valueOrError.isFailed()).toBeFalsy()
expect(valueOrError.getValue().value).toEqual('PRO_PLAN')
})
it('should not create an invalid value object', () => {
const valueOrError = SubscriptionPlanName.create('TEST')
expect(valueOrError.isFailed()).toBeTruthy()
})
})
@@ -0,0 +1,21 @@
import { Result, ValueObject } from '@standardnotes/domain-core'
import { SubscriptionPlanNameProps } from './SubscriptionPlanNameProps'
export class SubscriptionPlanName extends ValueObject<SubscriptionPlanNameProps> {
get value(): string {
return this.props.value
}
private constructor(props: SubscriptionPlanNameProps) {
super(props)
}
static create(subscriptionPlanName: string): Result<SubscriptionPlanName> {
if (!['PRO_PLAN', 'PLUS_PLAN'].includes(subscriptionPlanName)) {
return Result.fail<SubscriptionPlanName>(`Invalid subscription plan name ${subscriptionPlanName}`)
} else {
return Result.ok<SubscriptionPlanName>(new SubscriptionPlanName({ value: subscriptionPlanName }))
}
}
}
@@ -0,0 +1,3 @@
export interface SubscriptionPlanNameProps {
value: string
}
@@ -0,0 +1,8 @@
import { SubscriptionPlanName } from '../Subscription/SubscriptionPlanName'
export interface SubscriptionProps {
planName: SubscriptionPlanName
isFirstSubscriptionForUser: boolean
payedAmount: number
billingFrequency: number
}
@@ -26,4 +26,5 @@ export enum Period {
OctoberThisYear,
NovemberThisYear,
DecemberThisYear,
Last30DaysIncludingToday,
}
@@ -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',
@@ -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++) {

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