Compare commits

...

109 Commits

Author SHA1 Message Date
standardci
3b5bd6a47f chore(release): publish new version
- @standardnotes/analytics@2.12.0
 - @standardnotes/domain-core@1.7.0
 - @standardnotes/revisions-server@1.9.3
 - @standardnotes/syncing-server@1.20.3
2022-12-05 09:25:02 +00:00
Karol Sójko
06fd404d44 feat(domain-core): distinguish between username and email 2022-12-05 10:22:59 +01:00
standardci
d931c52508 chore(release): publish new version
- @standardnotes/analytics@2.11.17
 - @standardnotes/domain-core@1.6.0
 - @standardnotes/revisions-server@1.9.2
 - @standardnotes/syncing-server@1.20.2
2022-12-02 08:33:51 +00:00
Karol Sójko
800fe9e4c8 feat(domain-core): add subscription plan name value object 2022-12-02 09:32:05 +01:00
standardci
8b3d78678f chore(release): publish new version
- @standardnotes/analytics@2.11.16
 - @standardnotes/domain-core@1.5.2
 - @standardnotes/revisions-server@1.9.1
 - @standardnotes/syncing-server@1.20.1
2022-12-02 08:30:40 +00:00
Karol Sójko
2351cd3ad6 fix(revisions): change timestamps to dates value object 2022-12-01 11:31:11 +01:00
Karol Sójko
dd86c5bcdf fix(domain-core): rename timestamps to dates 2022-12-01 11:25:38 +01:00
standardci
d0c00e306e chore(release): publish new version
- @standardnotes/syncing-server@1.20.0
2022-11-30 17:15:44 +00:00
Karol Sójko
6cd68ddd6a feat(syncing-server): add revisions ownership fix procedure 2022-11-30 18:13:43 +01:00
standardci
02639cddb2 chore(release): publish new version
- @standardnotes/analytics@2.11.15
 - @standardnotes/api-gateway@1.39.6
 - @standardnotes/auth-server@1.60.15
 - @standardnotes/domain-events-infra@1.9.36
 - @standardnotes/domain-events@2.92.0
 - @standardnotes/event-store@1.6.32
 - @standardnotes/files-server@1.8.32
 - @standardnotes/revisions-server@1.9.0
 - @standardnotes/scheduler-server@1.13.33
 - @standardnotes/syncing-server@1.19.1
 - @standardnotes/websockets-server@1.4.33
 - @standardnotes/workspace-server@1.17.32
2022-11-30 12:46:26 +00:00
Karol Sójko
0f67aa4058 feat(revisions): add updating user uuid on revisions in async processing 2022-11-30 13:44:01 +01:00
standardci
78c3403d5f chore(release): publish new version
- @standardnotes/revisions-server@1.8.2
2022-11-29 15:30:07 +00:00
Karol Sójko
fc8f8c574d fix(revisions): make user uuid nullable 2022-11-29 16:27:39 +01:00
standardci
3972ee580d chore(release): publish new version
- @standardnotes/revisions-server@1.8.1
2022-11-29 09:11:04 +00:00
Karol Sójko
b0a994d5be fix(revisions): mysql queries 2022-11-29 10:08:35 +01:00
standardci
80df28a0c4 chore(release): publish new version
- @standardnotes/analytics@2.11.14
 - @standardnotes/api-gateway@1.39.5
 - @standardnotes/auth-server@1.60.14
 - @standardnotes/domain-events-infra@1.9.35
 - @standardnotes/domain-events@2.91.0
 - @standardnotes/event-store@1.6.31
 - @standardnotes/files-server@1.8.31
 - @standardnotes/revisions-server@1.8.0
 - @standardnotes/scheduler-server@1.13.32
 - @standardnotes/syncing-server@1.19.0
 - @standardnotes/websockets-server@1.4.32
 - @standardnotes/workspace-server@1.17.31
2022-11-28 14:08:28 +00:00
Karol Sójko
1c6c6a9296 fix(revisions): binding for revisions copy request handler 2022-11-28 15:06:26 +01:00
Karol Sójko
7bb698e442 feat(revisions): add copying revisions on duplicated items 2022-11-28 15:04:33 +01:00
standardci
784728cd54 chore(release): publish new version
- @standardnotes/revisions-server@1.7.1
2022-11-28 11:58:29 +00:00
Karol Sójko
4b883b68de fix(revisions): remove unnecessary indexes 2022-11-28 12:56:00 +01:00
standardci
dec2cc2aaf chore(release): publish new version
- @standardnotes/revisions-server@1.7.0
2022-11-28 11:44:16 +00:00
Karol Sójko
b4e8971ad2 feat(revisions): add handling account deletion requests 2022-11-28 12:42:25 +01:00
standardci
84e436265e chore(release): publish new version
- @standardnotes/revisions-server@1.6.0
2022-11-28 11:31:09 +00:00
Karol Sójko
ac8a69f8d4 feat(revisions): add deleting revisions 2022-11-28 12:28:38 +01:00
standardci
b912e050ea chore(release): publish new version
- @standardnotes/revisions-server@1.5.0
2022-11-28 11:06:13 +00:00
Karol Sójko
284561d093 feat(revisions): add fetching single revision 2022-11-28 12:04:00 +01:00
standardci
efc355982c chore(release): publish new version
- @standardnotes/api-gateway@1.39.4
2022-11-25 10:30:06 +00:00
Karol Sójko
8907879a19 fix(api-gateway): make revisions and workspace server urls optional 2022-11-25 11:28:02 +01:00
Karol Sójko
86f6057207 Revert "chore: tmp disable e2e to publish auth worker for email campaign"
This reverts commit ed8f82617d.
2022-11-25 07:56:07 +01:00
standardci
4c92698c73 chore(release): publish new version
- @standardnotes/auth-server@1.60.13
2022-11-25 06:45:52 +00:00
Karol Sójko
8407c3b649 fix(auth): bring back streaming all users in an email campaign send out 2022-11-25 07:43:55 +01:00
Karol Sójko
ed8f82617d chore: tmp disable e2e to publish auth worker for email campaign 2022-11-25 07:18:26 +01:00
standardci
31d040d1b6 chore(release): publish new version
- @standardnotes/auth-server@1.60.12
2022-11-25 06:16:08 +00:00
Karol Sójko
25a6796e63 fix(auth): tmp test email campaign black friday 2022 reminder on team only 2022-11-25 07:14:02 +01:00
standardci
ff091918aa chore(release): publish new version
- @standardnotes/analytics@2.11.13
 - @standardnotes/api-gateway@1.39.3
 - @standardnotes/auth-server@1.60.11
 - @standardnotes/common@1.46.1
 - @standardnotes/domain-core@1.5.1
 - @standardnotes/domain-events-infra@1.9.34
 - @standardnotes/domain-events@2.90.2
 - @standardnotes/event-store@1.6.30
 - @standardnotes/files-server@1.8.30
 - @standardnotes/predicates@1.6.2
 - @standardnotes/revisions-server@1.4.8
 - @standardnotes/scheduler-server@1.13.31
 - @standardnotes/security@1.7.2
 - @standardnotes/syncing-server@1.18.12
 - @standardnotes/websockets-server@1.4.31
 - @standardnotes/workspace-server@1.17.30
2022-11-25 05:54:46 +00:00
Karol Sójko
91b76edce1 fix(common): add black friday 2022 reminder message identifier 2022-11-25 06:52:08 +01:00
standardci
5ae5c83bf5 chore(release): publish new version
- @standardnotes/analytics@2.11.12
 - @standardnotes/domain-core@1.5.0
 - @standardnotes/revisions-server@1.4.7
 - @standardnotes/syncing-server@1.18.11
2022-11-24 20:13:47 +00:00
Karol Sójko
9d90f276de feat(domain-core): add methods to check role power 2022-11-24 21:11:08 +01:00
standardci
245f091e22 chore(release): publish new version
- @standardnotes/analytics@2.11.11
 - @standardnotes/domain-core@1.4.0
 - @standardnotes/revisions-server@1.4.6
 - @standardnotes/syncing-server@1.18.10
2022-11-24 10:36:50 +00:00
Karol Sójko
ae2f8f086b feat(domain-core): add role name collection value object 2022-11-24 11:34:43 +01:00
standardci
5e5eb7f937 chore(release): publish new version
- @standardnotes/analytics@2.11.10
 - @standardnotes/domain-core@1.3.0
 - @standardnotes/revisions-server@1.4.5
 - @standardnotes/syncing-server@1.18.9
2022-11-24 09:49:56 +00:00
Karol Sójko
748630e1f1 feat(domain-core): add role name value object 2022-11-24 10:48:00 +01:00
standardci
43064c8c55 chore(release): publish new version
- @standardnotes/analytics@2.11.9
 - @standardnotes/api-gateway@1.39.2
 - @standardnotes/auth-server@1.60.10
 - @standardnotes/domain-events-infra@1.9.33
 - @standardnotes/event-store@1.6.29
 - @standardnotes/files-server@1.8.29
 - @standardnotes/revisions-server@1.4.4
 - @standardnotes/scheduler-server@1.13.30
 - @standardnotes/settings@1.18.4
 - @standardnotes/syncing-server@1.18.8
 - @standardnotes/websockets-server@1.4.30
 - @standardnotes/workspace-server@1.17.29
2022-11-24 08:59:04 +00:00
Karol Sójko
4559a3047c chore(deps): remove newrelic native metrics 2022-11-24 09:56:53 +01:00
standardci
de8064ee5c chore(release): publish new version
- @standardnotes/analytics@2.11.8
 - @standardnotes/api-gateway@1.39.1
 - @standardnotes/auth-server@1.60.9
 - @standardnotes/domain-events-infra@1.9.32
 - @standardnotes/event-store@1.6.28
 - @standardnotes/files-server@1.8.28
 - @standardnotes/revisions-server@1.4.3
 - @standardnotes/scheduler-server@1.13.29
 - @standardnotes/syncing-server@1.18.7
 - @standardnotes/websockets-server@1.4.29
 - @standardnotes/workspace-server@1.17.28
2022-11-23 12:12:10 +00:00
Karol Sójko
48c8dba342 chore(deps): upgrade aws sdk 2022-11-23 13:10:05 +01:00
Karol Sójko
31a515b2f1 Revert "chore: tmp disable e2e to publish images with fixed sns and sqs binding"
This reverts commit 70596a0aac.
2022-11-23 09:29:12 +01:00
standardci
294f56e189 chore(release): publish new version
- @standardnotes/analytics@2.11.7
 - @standardnotes/auth-server@1.60.8
 - @standardnotes/event-store@1.6.27
 - @standardnotes/files-server@1.8.27
 - @standardnotes/scheduler-server@1.13.28
 - @standardnotes/syncing-server@1.18.6
 - @standardnotes/workspace-server@1.17.27
2022-11-23 08:19:47 +00:00
Karol Sójko
70596a0aac chore: tmp disable e2e to publish images with fixed sns and sqs binding 2022-11-23 09:17:43 +01:00
Karol Sójko
74bc79116b fix: binding of sns and sqs with additional config 2022-11-23 09:17:26 +01:00
standardci
e6bd50ae77 chore(release): publish new version
- @standardnotes/syncing-server@1.18.5
2022-11-22 14:52:13 +00:00
Karol Sójko
308662550f fix(syncing-server): publish revision creation request only for notes and files 2022-11-22 15:50:00 +01:00
Karol Sójko
d94a7e7157 Revert "Revert "chore: bring back e2e testing""
This reverts commit f68ece68af.
2022-11-22 15:50:00 +01:00
standardci
630b264754 chore(release): publish new version
- @standardnotes/auth-server@1.60.7
2022-11-22 14:33:44 +00:00
Karol Sójko
5f2be44b85 fix(auth): remove temporary email campaign check for team member 2022-11-22 15:31:44 +01:00
Karol Sójko
f68ece68af Revert "chore: bring back e2e testing"
This reverts commit 70c829a2c9.
2022-11-22 15:27:29 +01:00
Karol Sójko
70c829a2c9 chore: bring back e2e testing 2022-11-22 15:17:04 +01:00
Karol Sójko
e3b6ac4874 chore: temporary disable e2e to publish latest versions 2022-11-22 14:37:46 +01:00
standardci
a762d5a22c chore(release): publish new version
- @standardnotes/auth-server@1.60.6
 - @standardnotes/syncing-server@1.18.4
2022-11-22 13:31:16 +00:00
Karol Sójko
3686a26019 fix: sns binding 2022-11-22 14:29:07 +01:00
standardci
80daec748d chore(release): publish new version
- @standardnotes/auth-server@1.60.5
2022-11-22 13:22:58 +00:00
Karol Sójko
94359f1299 fix(auth): tmp send email campaign only to team 2022-11-22 14:08:48 +01:00
standardci
59dda1bb99 chore(release): publish new version
- @standardnotes/revisions-server@1.4.2
 - @standardnotes/syncing-server@1.18.3
2022-11-22 13:02:45 +00:00
Karol Sójko
806a732cbc fix: sqs binding 2022-11-22 14:00:54 +01:00
standardci
7816be7ba7 chore(release): publish new version
- @standardnotes/syncing-server@1.18.2
2022-11-22 12:31:22 +00:00
Karol Sójko
5f3bd5137f fix(syncing-server): bring back creating revisions in syncing server for a transition period 2022-11-22 13:23:56 +01:00
standardci
6c9fc5fb86 chore(release): publish new version
- @standardnotes/syncing-server@1.18.1
2022-11-22 11:38:45 +00:00
Karol Sójko
f7e0b68643 fix(syncing-server): specs 2022-11-22 12:36:32 +01:00
standardci
b283bbaca9 chore(release): publish new version
- @standardnotes/api-gateway@1.39.0
2022-11-22 11:30:16 +00:00
Karol Sójko
92ba759b1c feat(api-gateway): add v2 revisions controller 2022-11-22 12:28:03 +01:00
standardci
0acc9d8d68 chore(release): publish new version
- @standardnotes/revisions-server@1.4.1
 - @standardnotes/syncing-server@1.18.0
2022-11-22 11:20:59 +00:00
Karol Sójko
daa7a9ff61 fix(revisions): add more verbose error messages 2022-11-22 12:18:26 +01:00
Karol Sójko
455f35e0c1 feat(syncing-server): add dump projection for revisions 2022-11-22 12:18:26 +01:00
standardci
1fa655b56e chore(release): publish new version
- @standardnotes/revisions-server@1.4.0
2022-11-22 10:42:49 +00:00
Karol Sójko
e553222b4b feat(revisions): add database 2022-11-22 11:40:30 +01:00
standardci
f1b6f48926 chore(release): publish new version
- @standardnotes/revisions-server@1.3.0
2022-11-22 09:21:44 +00:00
Karol Sójko
14ab1cae69 feat(revisions): add filesystem dump repository 2022-11-22 10:19:46 +01:00
standardci
5f9cf90b16 chore(release): publish new version
- @standardnotes/syncing-server@1.17.0
2022-11-22 09:13:25 +00:00
Karol Sójko
97b367d4ee feat(syncing-server): add dumping backup items to filesystem 2022-11-22 10:11:09 +01:00
standardci
47119fb346 chore(release): publish new version
- @standardnotes/analytics@2.11.6
 - @standardnotes/api-gateway@1.38.9
 - @standardnotes/auth-server@1.60.4
 - @standardnotes/common@1.46.0
 - @standardnotes/domain-core@1.2.2
 - @standardnotes/domain-events-infra@1.9.31
 - @standardnotes/domain-events@2.90.1
 - @standardnotes/event-store@1.6.26
 - @standardnotes/files-server@1.8.26
 - @standardnotes/predicates@1.6.1
 - @standardnotes/revisions-server@1.2.2
 - @standardnotes/scheduler-server@1.13.27
 - @standardnotes/security@1.7.1
 - @standardnotes/syncing-server@1.16.1
 - @standardnotes/websockets-server@1.4.28
 - @standardnotes/workspace-server@1.17.26
2022-11-22 07:25:59 +00:00
Karol Sójko
d77eb7f5f1 feat(common): add marketing campaign for black friday 2022 email message identifier 2022-11-22 08:23:32 +01:00
standardci
1b0a2bb34c chore(release): publish new version
- @standardnotes/revisions-server@1.2.1
2022-11-21 13:20:13 +00:00
Karol Sójko
a363039fa1 fix(revisions): add missing worker process 2022-11-21 14:18:16 +01:00
standardci
32c740b58e chore(release): publish new version
- @standardnotes/revisions-server@1.2.0
 - @standardnotes/syncing-server@1.16.0
2022-11-21 11:58:16 +00:00
Karol Sójko
822ee890af feat(revisions): add persisting revisions from s3 dump 2022-11-21 12:56:17 +01:00
standardci
b0406dd8aa chore(release): publish new version
- @standardnotes/analytics@2.11.5
 - @standardnotes/api-gateway@1.38.8
 - @standardnotes/auth-server@1.60.3
 - @standardnotes/domain-events-infra@1.9.30
 - @standardnotes/domain-events@2.90.0
 - @standardnotes/event-store@1.6.25
 - @standardnotes/files-server@1.8.25
 - @standardnotes/revisions-server@1.1.3
 - @standardnotes/scheduler-server@1.13.26
 - @standardnotes/syncing-server@1.15.0
 - @standardnotes/websockets-server@1.4.27
 - @standardnotes/workspace-server@1.17.25
2022-11-21 08:36:38 +00:00
Karol Sójko
8d152ddfcb feat(syncing-server): add creating item dumps for revision service 2022-11-21 09:34:19 +01:00
standardci
1a16d2e4f4 chore(release): publish new version
- @standardnotes/syncing-server@1.14.0
2022-11-21 08:12:48 +00:00
Karol Sójko
1ca8531305 feat(syncing-server): add creating revisions in async way 2022-11-21 09:10:37 +01:00
standardci
6190e7d092 chore(release): publish new version
- @standardnotes/analytics@2.11.4
 - @standardnotes/domain-core@1.2.1
 - @standardnotes/revisions-server@1.1.2
 - @standardnotes/syncing-server@1.13.17
2022-11-21 07:53:58 +00:00
Karol Sójko
a6542dd638 fix(domain-core): remove revisions related models to revisions microservice 2022-11-21 08:51:57 +01:00
standardci
840777a851 chore(release): publish new version
- @standardnotes/analytics@2.11.3
 - @standardnotes/api-gateway@1.38.7
 - @standardnotes/auth-server@1.60.2
 - @standardnotes/domain-events-infra@1.9.29
 - @standardnotes/domain-events@2.89.0
 - @standardnotes/event-store@1.6.24
 - @standardnotes/files-server@1.8.24
 - @standardnotes/revisions-server@1.1.1
 - @standardnotes/scheduler-server@1.13.25
 - @standardnotes/syncing-server@1.13.16
 - @standardnotes/websockets-server@1.4.26
 - @standardnotes/workspace-server@1.17.24
2022-11-18 13:32:16 +00:00
Karol Sójko
5c9dff38c9 feat: add item revision creation requested event 2022-11-18 14:30:11 +01:00
Karol Sójko
abfbacb8c2 chore: rename revisions workflow 2022-11-18 14:24:18 +01:00
standardci
03afdbf431 chore(release): publish new version
- @standardnotes/analytics@2.11.2
2022-11-18 13:22:27 +00:00
Karol Sójko
507d43b328 fix(analytics): specs 2022-11-18 14:19:58 +01:00
standardci
be214c0599 chore(release): publish new version
- @standardnotes/syncing-server@1.13.15
2022-11-18 13:13:45 +00:00
Karol Sójko
91f36c3a3f fix(syncing-server): mapper interface imports in specs 2022-11-18 14:11:52 +01:00
standardci
f60c15ed2e chore(release): publish new version
- @standardnotes/analytics@2.11.1
 - @standardnotes/domain-core@1.2.0
 - @standardnotes/revisions-server@1.1.0
 - @standardnotes/syncing-server@1.13.14
2022-11-18 13:06:03 +00:00
Karol Sójko
1ec072373d fix: mapper interface imports 2022-11-18 14:03:32 +01:00
Karol Sójko
a7d039082e fix(revisions): docker entrypoint 2022-11-18 11:56:38 +01:00
Karol Sójko
d5c06bfa58 feat(revisions): add revisions microservice 2022-11-18 11:54:42 +01:00
Karol Sójko
c8f3a0ce7b feat(domain-core): add revision definition to domain core 2022-11-18 11:54:42 +01:00
standardci
edbedc181b chore(release): publish new version
- @standardnotes/syncing-server@1.13.13
2022-11-17 09:41:19 +00:00
Karol Sójko
94afa34780 fix(syncing-server): paginating with upper bound limit 2022-11-17 10:38:34 +01:00
standardci
74dd0ab6cd chore(release): publish new version
- @standardnotes/analytics@2.11.0
 - @standardnotes/api-gateway@1.38.6
 - @standardnotes/auth-server@1.60.1
 - @standardnotes/domain-events-infra@1.9.28
 - @standardnotes/domain-events@2.88.0
 - @standardnotes/event-store@1.6.23
 - @standardnotes/files-server@1.8.23
 - @standardnotes/scheduler-server@1.13.24
 - @standardnotes/syncing-server@1.13.12
 - @standardnotes/websockets-server@1.4.25
 - @standardnotes/workspace-server@1.17.23
2022-11-16 11:48:01 +00:00
Karol Sójko
6c43a331d0 feat(analytics): add publishing churn calculation values in the report 2022-11-16 12:46:09 +01:00
standardci
67835ba0c0 chore(release): publish new version
- @standardnotes/analytics@2.10.3
2022-11-16 11:34:16 +00:00
Karol Sójko
fe1b2a0e07 fix(analytics): exclude five year plans from mrr stats 2022-11-16 12:32:22 +01:00
205 changed files with 4569 additions and 467 deletions

46
.github/workflows/revisions.yml vendored Normal file
View File

@@ -0,0 +1,46 @@
name: Revisions Server
concurrency:
group: revisions_server
cancel-in-progress: true
on:
push:
tags:
- '*standardnotes/revisions-server*'
workflow_dispatch:
jobs:
call_server_application_workflow:
name: Server Application
uses: standardnotes/server/.github/workflows/common-server-application.yml@main
with:
service_name: revisions
workspace_name: "@standardnotes/revisions-server"
e2e_tag_parameter_name: revisions_image_tag
package_path: packages/revisions
secrets: inherit
newrelic:
needs: call_server_application_workflow
runs-on: ubuntu-latest
steps:
- name: Create New Relic deployment marker for Web
uses: newrelic/deployment-marker-action@v1
with:
accountId: ${{ secrets.NEW_RELIC_ACCOUNT_ID }}
apiKey: ${{ secrets.NEW_RELIC_API_KEY }}
applicationId: ${{ secrets.NEW_RELIC_APPLICATION_ID_REVISIONS_WEB_PROD }}
revision: "${{ github.sha }}"
description: "Automated Deployment via Github Actions"
user: "${{ github.actor }}"
- name: Create New Relic deployment marker for Worker
uses: newrelic/deployment-marker-action@v1
with:
accountId: ${{ secrets.NEW_RELIC_ACCOUNT_ID }}
apiKey: ${{ secrets.NEW_RELIC_API_KEY }}
applicationId: ${{ secrets.NEW_RELIC_APPLICATION_ID_REVISIONS_WORKER_PROD }}
revision: "${{ github.sha }}"
description: "Automated Deployment via Github Actions"
user: "${{ github.actor }}"

91
.pnp.cjs generated
View File

@@ -53,6 +53,10 @@ const RAW_RUNTIME_STATE =
"name": "@standardnotes/predicates",\
"reference": "workspace:packages/predicates"\
},\
{\
"name": "@standardnotes/revisions-server",\
"reference": "workspace:packages/revisions"\
},\
{\
"name": "@standardnotes/scheduler-server",\
"reference": "workspace:packages/scheduler"\
@@ -99,6 +103,7 @@ const RAW_RUNTIME_STATE =
["@standardnotes/event-store", ["workspace:packages/event-store"]],\
["@standardnotes/files-server", ["workspace:packages/files"]],\
["@standardnotes/predicates", ["workspace:packages/predicates"]],\
["@standardnotes/revisions-server", ["workspace:packages/revisions"]],\
["@standardnotes/scheduler-server", ["workspace:packages/scheduler"]],\
["@standardnotes/security", ["workspace:packages/security"]],\
["@standardnotes/server-monorepo", ["workspace:."]],\
@@ -121,7 +126,6 @@ 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"],\
["@newrelic/native-metrics", "npm:9.0.0"],\
["@sentry/node", "npm:7.19.0"],\
["@types/jest", "npm:29.1.1"],\
["@types/newrelic", "npm:7.0.4"],\
@@ -2533,7 +2537,6 @@ 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.19.0"],\
["@standardnotes/common", "workspace:packages/common"],\
@@ -2546,7 +2549,7 @@ const RAW_RUNTIME_STATE =
["@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.1253.0"],\
["aws-sdk", "npm:2.1260.0"],\
["dayjs", "npm:1.11.6"],\
["dotenv", "npm:16.0.1"],\
["eslint", "npm:8.25.0"],\
@@ -2586,7 +2589,6 @@ 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.19.0"],\
["@standardnotes/common", "workspace:packages/common"],\
@@ -2602,7 +2604,7 @@ const RAW_RUNTIME_STATE =
["@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.1253.0"],\
["aws-sdk", "npm:2.1260.0"],\
["axios", "npm:1.1.3"],\
["cors", "npm:2.8.5"],\
["dotenv", "npm:16.0.1"],\
@@ -2643,7 +2645,6 @@ 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.19.0"],\
["@standardnotes/api", "npm:1.19.0"],\
@@ -2669,7 +2670,7 @@ const RAW_RUNTIME_STATE =
["@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.1253.0"],\
["aws-sdk", "npm:2.1260.0"],\
["axios", "npm:1.1.3"],\
["bcryptjs", "npm:2.4.3"],\
["cors", "npm:2.8.5"],\
@@ -2778,13 +2779,12 @@ 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:5.0.0"],\
["@types/jest", "npm:29.1.1"],\
["@types/newrelic", "npm:7.0.4"],\
["@typescript-eslint/eslint-plugin", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:5.30.5"],\
["aws-sdk", "npm:2.1253.0"],\
["aws-sdk", "npm:2.1260.0"],\
["eslint-plugin-prettier", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:4.2.1"],\
["ioredis", "npm:5.2.4"],\
["jest", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:29.1.2"],\
@@ -2818,7 +2818,6 @@ 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"],\
@@ -2827,7 +2826,7 @@ const RAW_RUNTIME_STATE =
["@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.1253.0"],\
["aws-sdk", "npm:2.1260.0"],\
["dotenv", "npm:16.0.1"],\
["eslint", "npm:8.25.0"],\
["eslint-plugin-prettier", "virtual:c66bf20e88479ada0172094776519a9f51acc4731d22079b60a295bcec7ea42d5545cbce58a77a50d932bf953298799135e99707486e343da6d99ba1d167bdbd#npm:4.2.1"],\
@@ -2874,7 +2873,6 @@ const RAW_RUNTIME_STATE =
"packageLocation": "./packages/files/",\
"packageDependencies": [\
["@standardnotes/files-server", "workspace:packages/files"],\
["@newrelic/native-metrics", "npm:9.0.0"],\
["@sentry/node", "npm:7.19.0"],\
["@standardnotes/common", "workspace:packages/common"],\
["@standardnotes/config", "npm:2.4.3"],\
@@ -2894,7 +2892,7 @@ const RAW_RUNTIME_STATE =
["@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.1253.0"],\
["aws-sdk", "npm:2.1260.0"],\
["connect-busboy", "npm:1.0.0"],\
["cors", "npm:2.8.5"],\
["dayjs", "npm:1.11.6"],\
@@ -3004,12 +3002,56 @@ const RAW_RUNTIME_STATE =
"linkType": "HARD"\
}]\
]],\
["@standardnotes/revisions-server", [\
["workspace:packages/revisions", {\
"packageLocation": "./packages/revisions/",\
"packageDependencies": [\
["@standardnotes/revisions-server", "workspace:packages/revisions"],\
["@newrelic/winston-enricher", "virtual:c66bf20e88479ada0172094776519a9f51acc4731d22079b60a295bcec7ea42d5545cbce58a77a50d932bf953298799135e99707486e343da6d99ba1d167bdbd#npm:4.0.0"],\
["@sentry/node", "npm:7.19.0"],\
["@standardnotes/api", "npm:1.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/security", "workspace:packages/security"],\
["@standardnotes/time", "workspace:packages/time"],\
["@types/cors", "npm:2.8.12"],\
["@types/dotenv", "npm:8.2.0"],\
["@types/express", "npm:4.17.14"],\
["@types/inversify-express-utils", "npm:2.0.0"],\
["@types/ioredis", "npm:5.0.0"],\
["@types/jest", "npm:29.1.1"],\
["@types/newrelic", "npm:7.0.4"],\
["@typescript-eslint/eslint-plugin", "virtual:04783e12400851b8a3d76e71495851cc94959db6e62f04cb0a31190080629440b182d8c8eb4d7f2b04e281912f2783a5fd4d2c3c6ab68d38b7097246c93f4c19#npm:5.40.1"],\
["aws-sdk", "npm:2.1260.0"],\
["cors", "npm:2.8.5"],\
["dotenv", "npm:16.0.1"],\
["eslint", "npm:8.25.0"],\
["eslint-plugin-prettier", "virtual:c66bf20e88479ada0172094776519a9f51acc4731d22079b60a295bcec7ea42d5545cbce58a77a50d932bf953298799135e99707486e343da6d99ba1d167bdbd#npm:4.2.1"],\
["express", "npm:4.18.2"],\
["helmet", "npm:6.0.0"],\
["inversify", "npm:6.0.1"],\
["inversify-express-utils", "npm:6.4.3"],\
["ioredis", "npm:5.2.4"],\
["jest", "virtual:fd909b174d079e30b336c4ce72c38a88c1e447767b1a8dd7655e07719a1e31b97807f0931368724fc78897ff15e6a6d00b83316c0f76d11f85111f342e08bb79#npm:29.1.2"],\
["mysql2", "npm:2.3.3"],\
["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"],\
["typeorm", "virtual:c66bf20e88479ada0172094776519a9f51acc4731d22079b60a295bcec7ea42d5545cbce58a77a50d932bf953298799135e99707486e343da6d99ba1d167bdbd#npm:0.3.10"],\
["typescript", "patch:typescript@npm%3A4.8.4#optional!builtin<compat/typescript>::version=4.8.4&hash=701156"],\
["winston", "npm:3.8.2"]\
],\
"linkType": "SOFT"\
}]\
]],\
["@standardnotes/scheduler-server", [\
["workspace:packages/scheduler", {\
"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.19.0"],\
["@standardnotes/common", "workspace:packages/common"],\
@@ -3022,7 +3064,7 @@ const RAW_RUNTIME_STATE =
["@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.1253.0"],\
["aws-sdk", "npm:2.1260.0"],\
["dayjs", "npm:1.11.6"],\
["dotenv", "npm:16.0.1"],\
["eslint", "npm:8.25.0"],\
@@ -3071,7 +3113,6 @@ 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"],\
["@newrelic/native-metrics", "npm:9.0.0"],\
["@sentry/node", "npm:7.19.0"],\
["@types/jest", "npm:29.1.1"],\
["@types/newrelic", "npm:7.0.4"],\
@@ -3094,7 +3135,6 @@ 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"],\
@@ -3138,7 +3178,6 @@ 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.19.0"],\
["@standardnotes/common", "workspace:packages/common"],\
@@ -3162,7 +3201,7 @@ const RAW_RUNTIME_STATE =
["@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.1253.0"],\
["aws-sdk", "npm:2.1260.0"],\
["axios", "npm:1.1.3"],\
["cors", "npm:2.8.5"],\
["dotenv", "npm:16.0.1"],\
@@ -3239,7 +3278,6 @@ 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.19.0"],\
["@standardnotes/api", "npm:1.19.0"],\
@@ -3253,7 +3291,7 @@ const RAW_RUNTIME_STATE =
["@types/jest", "npm:29.1.1"],\
["@types/newrelic", "npm:7.0.4"],\
["@typescript-eslint/eslint-plugin", "virtual:04783e12400851b8a3d76e71495851cc94959db6e62f04cb0a31190080629440b182d8c8eb4d7f2b04e281912f2783a5fd4d2c3c6ab68d38b7097246c93f4c19#npm:5.40.1"],\
["aws-sdk", "npm:2.1253.0"],\
["aws-sdk", "npm:2.1260.0"],\
["axios", "npm:1.1.3"],\
["cors", "npm:2.8.5"],\
["dotenv", "npm:16.0.1"],\
@@ -3280,7 +3318,6 @@ 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.19.0"],\
["@standardnotes/api", "npm:1.19.0"],\
@@ -3296,7 +3333,7 @@ const RAW_RUNTIME_STATE =
["@types/jest", "npm:29.1.1"],\
["@types/newrelic", "npm:7.0.4"],\
["@typescript-eslint/eslint-plugin", "virtual:04783e12400851b8a3d76e71495851cc94959db6e62f04cb0a31190080629440b182d8c8eb4d7f2b04e281912f2783a5fd4d2c3c6ab68d38b7097246c93f4c19#npm:5.40.1"],\
["aws-sdk", "npm:2.1253.0"],\
["aws-sdk", "npm:2.1260.0"],\
["cors", "npm:2.8.5"],\
["dotenv", "npm:16.0.1"],\
["eslint", "npm:8.25.0"],\
@@ -4763,10 +4800,10 @@ const RAW_RUNTIME_STATE =
}]\
]],\
["aws-sdk", [\
["npm:2.1253.0", {\
"packageLocation": "./.yarn/cache/aws-sdk-npm-2.1253.0-2cf60975ab-faa4af2949.zip/node_modules/aws-sdk/",\
["npm:2.1260.0", {\
"packageLocation": "./.yarn/cache/aws-sdk-npm-2.1260.0-0145998ab1-9a1b2e4cb5.zip/node_modules/aws-sdk/",\
"packageDependencies": [\
["aws-sdk", "npm:2.1253.0"],\
["aws-sdk", "npm:2.1260.0"],\
["buffer", "npm:4.9.2"],\
["events", "npm:1.1.1"],\
["ieee754", "npm:1.1.13"],\
@@ -12533,7 +12570,7 @@ const RAW_RUNTIME_STATE =
"packageDependencies": [\
["sqs-consumer", "virtual:685a6222c3349423674bb7f0684ba34e2ab20912010f352e04dcf707a156e13183fc382e2417cb37a60f3e7b52fd0178c53181674890e1773eb83e190dc13378#npm:5.7.0"],\
["@types/aws-sdk", null],\
["aws-sdk", "npm:2.1253.0"],\
["aws-sdk", "npm:2.1260.0"],\
["debug", "virtual:b86a9fb34323a98c6519528ed55faa0d9b44ca8879307c0b29aa384bde47ff59a7d0c9051b31246f14521dfb71ba3c5d6d0b35c29fffc17bf875aa6ad977d9e8#npm:4.3.4"]\
],\
"packagePeers": [\

View File

@@ -21,6 +21,7 @@
"lint:websockets": "yarn workspace @standardnotes/websockets-server lint",
"lint:workspace": "yarn workspace @standardnotes/workspace-server lint",
"lint:analytics": "yarn workspace @standardnotes/analytics lint",
"lint:revisions": "yarn workspace @standardnotes/revisions-server lint",
"clean": "yarn workspaces foreach -p --verbose run clean",
"setup:env": "cp .env.sample .env && yarn workspaces foreach -p --verbose run setup:env",
"start:auth": "yarn workspace @standardnotes/auth-server start",
@@ -34,6 +35,7 @@
"start:websockets": "yarn workspace @standardnotes/websockets-server start",
"start:workspace": "yarn workspace @standardnotes/workspace-server start",
"start:analytics": "yarn workspace @standardnotes/analytics worker",
"start:revisions": "yarn workspace @standardnotes/revisions-server start",
"release": "lerna version --conventional-graduate --conventional-commits --yes -m \"chore(release): publish new version\"",
"publish": "lerna publish from-git --yes --no-verify-access --loglevel verbose",
"postversion": "./scripts/push-tags-one-by-one.sh",
@@ -59,7 +61,6 @@
},
"packageManager": "yarn@4.0.0-rc.25",
"dependencies": {
"@newrelic/native-metrics": "^9.0.0",
"@sentry/node": "^7.19.0",
"newrelic": "^9.6.0"
}

View File

@@ -3,6 +3,98 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
# [2.12.0](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.11.17...@standardnotes/analytics@2.12.0) (2022-12-05)
### Features
* **domain-core:** distinguish between username and email ([06fd404](https://github.com/standardnotes/server/commit/06fd404d44b44a53733f889aabd4da63f21e2f36))
## [2.11.17](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.11.16...@standardnotes/analytics@2.11.17) (2022-12-02)
**Note:** Version bump only for package @standardnotes/analytics
## [2.11.16](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.11.15...@standardnotes/analytics@2.11.16) (2022-12-02)
**Note:** Version bump only for package @standardnotes/analytics
## [2.11.15](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.11.14...@standardnotes/analytics@2.11.15) (2022-11-30)
**Note:** Version bump only for package @standardnotes/analytics
## [2.11.14](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.11.13...@standardnotes/analytics@2.11.14) (2022-11-28)
**Note:** Version bump only for package @standardnotes/analytics
## [2.11.13](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.11.12...@standardnotes/analytics@2.11.13) (2022-11-25)
**Note:** Version bump only for package @standardnotes/analytics
## [2.11.12](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.11.11...@standardnotes/analytics@2.11.12) (2022-11-24)
**Note:** Version bump only for package @standardnotes/analytics
## [2.11.11](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.11.10...@standardnotes/analytics@2.11.11) (2022-11-24)
**Note:** Version bump only for package @standardnotes/analytics
## [2.11.10](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.11.9...@standardnotes/analytics@2.11.10) (2022-11-24)
**Note:** Version bump only for package @standardnotes/analytics
## [2.11.9](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.11.8...@standardnotes/analytics@2.11.9) (2022-11-24)
**Note:** Version bump only for package @standardnotes/analytics
## [2.11.8](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.11.7...@standardnotes/analytics@2.11.8) (2022-11-23)
**Note:** Version bump only for package @standardnotes/analytics
## [2.11.7](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.11.6...@standardnotes/analytics@2.11.7) (2022-11-23)
### Bug Fixes
* binding of sns and sqs with additional config ([74bc791](https://github.com/standardnotes/server/commit/74bc79116bc50d9a5af1a558db1b7108dcda6d0e))
## [2.11.6](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.11.5...@standardnotes/analytics@2.11.6) (2022-11-22)
**Note:** Version bump only for package @standardnotes/analytics
## [2.11.5](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.11.4...@standardnotes/analytics@2.11.5) (2022-11-21)
**Note:** Version bump only for package @standardnotes/analytics
## [2.11.4](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.11.3...@standardnotes/analytics@2.11.4) (2022-11-21)
**Note:** Version bump only for package @standardnotes/analytics
## [2.11.3](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.11.2...@standardnotes/analytics@2.11.3) (2022-11-18)
**Note:** Version bump only for package @standardnotes/analytics
## [2.11.2](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.11.1...@standardnotes/analytics@2.11.2) (2022-11-18)
### Bug Fixes
* **analytics:** specs ([507d43b](https://github.com/standardnotes/server/commit/507d43b3289d1e178644df6d3e15d1d55e56c7bb))
## [2.11.1](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.11.0...@standardnotes/analytics@2.11.1) (2022-11-18)
### Bug Fixes
* mapper interface imports ([1ec0723](https://github.com/standardnotes/server/commit/1ec072373d640c4e2f24b9bb12fec0c678b48032))
# [2.11.0](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.10.3...@standardnotes/analytics@2.11.0) (2022-11-16)
### Features
* **analytics:** add publishing churn calculation values in the report ([6c43a33](https://github.com/standardnotes/server/commit/6c43a331d09c2dcf1300742509da6a1d8ef2f5b7))
## [2.10.3](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.10.2...@standardnotes/analytics@2.10.3) (2022-11-16)
### Bug Fixes
* **analytics:** exclude five year plans from mrr stats ([fe1b2a0](https://github.com/standardnotes/server/commit/fe1b2a0e0744417e592f3f61f42610765b416ce6))
## [2.10.2](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.10.1...@standardnotes/analytics@2.10.2) (2022-11-14)
### Bug Fixes

View File

@@ -175,6 +175,9 @@ const requestReport = async (
const churnRates: Array<{
rate: number
periodKey: string
averageCustomersCount: number
existingCustomersChurn: number
newCustomersChurn: number
}> = []
for (const monthPeriodKey of monthlyPeriodKeys) {
const monthPeriod = periodKeyGenerator.convertPeriodKeyToPeriod(monthPeriodKey)
@@ -204,6 +207,9 @@ const requestReport = async (
churnRates.push({
periodKey: monthPeriodKey,
rate: averageCustomersCount ? (totalChurn / averageCustomersCount) * 100 : 0,
averageCustomersCount,
existingCustomersChurn,
newCustomersChurn,
})
}

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/analytics",
"version": "2.10.2",
"version": "2.12.0",
"engines": {
"node": ">=18.0.0 <19.0.0"
},
@@ -37,7 +37,6 @@
"typescript": "^4.8.4"
},
"dependencies": {
"@newrelic/native-metrics": "^9.0.0",
"@newrelic/winston-enricher": "^4.0.0",
"@sentry/node": "^7.19.0",
"@standardnotes/common": "workspace:*",
@@ -45,7 +44,7 @@
"@standardnotes/domain-events": "workspace:*",
"@standardnotes/domain-events-infra": "workspace:*",
"@standardnotes/time": "workspace:*",
"aws-sdk": "^2.1253.0",
"aws-sdk": "^2.1260.0",
"dayjs": "^1.11.6",
"dotenv": "^16.0.1",
"inversify": "^6.0.1",

View File

@@ -7,7 +7,7 @@ import {
DomainEventMessageHandlerInterface,
DomainEventSubscriberFactoryInterface,
} from '@standardnotes/domain-events'
import { MapInterface } from '@standardnotes/domain-core'
import { MapperInterface } from '@standardnotes/domain-core'
import { Env } from './Env'
import TYPES from './Types'
@@ -89,13 +89,24 @@ export class ContainerConfigLoader {
})
container.bind<winston.Logger>(TYPES.Logger).toConstantValue(logger)
if (env.get('SNS_AWS_REGION', true)) {
container.bind<AWS.SNS>(TYPES.SNS).toConstantValue(
new AWS.SNS({
apiVersion: 'latest',
region: env.get('SNS_AWS_REGION', true),
}),
)
if (env.get('SNS_TOPIC_ARN', true)) {
const snsConfig: AWS.SNS.Types.ClientConfiguration = {
apiVersion: 'latest',
region: env.get('SNS_AWS_REGION', true),
}
if (env.get('SNS_ENDPOINT', true)) {
snsConfig.endpoint = env.get('SNS_ENDPOINT', true)
}
if (env.get('SNS_DISABLE_SSL', true) === 'true') {
snsConfig.sslEnabled = false
}
if (env.get('SNS_ACCESS_KEY_ID', true) && env.get('SNS_SECRET_ACCESS_KEY', true)) {
snsConfig.credentials = {
accessKeyId: env.get('SNS_ACCESS_KEY_ID', true),
secretAccessKey: env.get('SNS_SECRET_ACCESS_KEY', true),
}
}
container.bind<AWS.SNS>(TYPES.SNS).toConstantValue(new AWS.SNS(snsConfig))
}
if (env.get('SQS_QUEUE_URL', true)) {
@@ -172,7 +183,7 @@ export class ContainerConfigLoader {
// Maps
container
.bind<MapInterface<RevenueModification, TypeORMRevenueModification>>(TYPES.RevenueModificationMap)
.bind<MapperInterface<RevenueModification, TypeORMRevenueModification>>(TYPES.RevenueModificationMap)
.to(RevenueModificationMap)
// Services

View File

@@ -18,5 +18,5 @@ export class AnalyticsEntity {
nullable: true,
})
@Index('email')
declare userEmail: string
declare username: string
}

View File

@@ -1,140 +0,0 @@
import 'reflect-metadata'
import { TimerInterface } from '@standardnotes/time'
import { AnalyticsActivity } from '../Analytics/AnalyticsActivity'
import { StatisticsMeasure } from '../Statistics/StatisticsMeasure'
import { Period } from '../Time/Period'
import { DomainEventFactory } from './DomainEventFactory'
describe('DomainEventFactory', () => {
let timer: TimerInterface
const createFactory = () => new DomainEventFactory(timer)
beforeEach(() => {
timer = {} as jest.Mocked<TimerInterface>
timer.getTimestampInMicroseconds = jest.fn().mockReturnValue(1)
timer.getUTCDate = jest.fn().mockReturnValue(new Date(1))
})
it('should create a DAILY_ANALYTICS_REPORT_GENERATED event', () => {
expect(
createFactory().createDailyAnalyticsReportGeneratedEvent({
activityStatistics: [
{
name: AnalyticsActivity.Register,
retention: 24,
totalCount: 45,
},
],
statisticMeasures: [
{
name: StatisticsMeasure.Income,
totalValue: 43,
average: 23,
increments: 5,
period: Period.Today,
},
],
activityStatisticsOverTime: [
{
name: AnalyticsActivity.Register,
period: Period.Last30Days,
counts: [
{
periodKey: '2022-10-9',
totalCount: 3,
},
],
totalCount: 123,
},
],
statisticsOverTime: [
{
name: StatisticsMeasure.MRR,
period: Period.Last30Days,
counts: [
{
periodKey: '2022-10-9',
totalCount: 3,
},
],
},
],
churn: {
periodKeys: ['2022-10-9'],
values: [
{
rate: 12,
periodKey: '2022-10-9',
},
],
},
}),
).toEqual({
createdAt: expect.any(Date),
meta: {
correlation: {
userIdentifier: '',
userIdentifierType: 'uuid',
},
origin: 'analytics',
},
payload: {
activityStatistics: [
{
name: 'register',
retention: 24,
totalCount: 45,
},
],
activityStatisticsOverTime: [
{
counts: [
{
periodKey: '2022-10-9',
totalCount: 3,
},
],
name: 'register',
period: 9,
totalCount: 123,
},
],
statisticsOverTime: [
{
counts: [
{
periodKey: '2022-10-9',
totalCount: 3,
},
],
name: 'mrr',
period: 9,
},
],
churn: {
periodKeys: ['2022-10-9'],
values: [
{
periodKey: '2022-10-9',
rate: 12,
},
],
},
statisticMeasures: [
{
average: 23,
increments: 5,
name: 'income',
period: 0,
totalValue: 43,
},
],
},
type: 'DAILY_ANALYTICS_REPORT_GENERATED',
})
})
})

View File

@@ -1,3 +1,5 @@
/* istanbul ignore file */
import { DomainEventService, DailyAnalyticsReportGeneratedEvent } from '@standardnotes/domain-events'
import { TimerInterface } from '@standardnotes/time'
import { inject, injectable } from 'inversify'
@@ -43,6 +45,9 @@ export class DomainEventFactory implements DomainEventFactoryInterface {
values: Array<{
rate: number
periodKey: string
averageCustomersCount: number
existingCustomersChurn: number
newCustomersChurn: number
}>
}
}): DailyAnalyticsReportGeneratedEvent {

View File

@@ -36,6 +36,9 @@ export interface DomainEventFactoryInterface {
values: Array<{
rate: number
periodKey: string
averageCustomersCount: number
existingCustomersChurn: number
newCustomersChurn: number
}>
}
}): DailyAnalyticsReportGeneratedEvent

View File

@@ -1,7 +1,7 @@
import { DomainEventHandlerInterface, SubscriptionCancelledEvent } from '@standardnotes/domain-events'
import { inject, injectable } from 'inversify'
import { Logger } from 'winston'
import { Email } from '@standardnotes/domain-core'
import { Username } from '@standardnotes/domain-core'
import TYPES from '../../Bootstrap/Types'
import { AnalyticsActivity } from '../Analytics/AnalyticsActivity'
@@ -41,7 +41,7 @@ export class SubscriptionCancelledEventHandler implements DomainEventHandlerInte
payedAmount: event.payload.payAmount,
planName: SubscriptionPlanName.create(event.payload.subscriptionName).getValue(),
subscriptionId: event.payload.subscriptionId,
userEmail: Email.create(event.payload.userEmail).getValue(),
username: Username.create(event.payload.userEmail).getValue(),
userUuid,
})

View File

@@ -1,7 +1,7 @@
import { Username } from '@standardnotes/domain-core'
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'
@@ -45,7 +45,7 @@ export class SubscriptionExpiredEventHandler implements DomainEventHandlerInterf
payedAmount: event.payload.payAmount,
planName: SubscriptionPlanName.create(event.payload.subscriptionName).getValue(),
subscriptionId: event.payload.subscriptionId,
userEmail: Email.create(event.payload.userEmail).getValue(),
username: Username.create(event.payload.userEmail).getValue(),
userUuid,
})

View File

@@ -1,7 +1,7 @@
import { Username } from '@standardnotes/domain-core'
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'
@@ -69,7 +69,7 @@ export class SubscriptionPurchasedEventHandler implements DomainEventHandlerInte
payedAmount: event.payload.payAmount,
planName: SubscriptionPlanName.create(event.payload.subscriptionName).getValue(),
subscriptionId: event.payload.subscriptionId,
userEmail: Email.create(event.payload.userEmail).getValue(),
username: Username.create(event.payload.userEmail).getValue(),
userUuid,
})

View File

@@ -1,7 +1,7 @@
import { Username } from '@standardnotes/domain-core'
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'
@@ -41,7 +41,7 @@ export class SubscriptionRefundedEventHandler implements DomainEventHandlerInter
payedAmount: event.payload.payAmount,
planName: SubscriptionPlanName.create(event.payload.subscriptionName).getValue(),
subscriptionId: event.payload.subscriptionId,
userEmail: Email.create(event.payload.userEmail).getValue(),
username: Username.create(event.payload.userEmail).getValue(),
userUuid,
})

View File

@@ -1,6 +1,6 @@
import { DomainEventHandlerInterface, SubscriptionRenewedEvent } from '@standardnotes/domain-events'
import { inject, injectable } from 'inversify'
import { Email } from '@standardnotes/domain-core'
import { Username } from '@standardnotes/domain-core'
import TYPES from '../../Bootstrap/Types'
import { GetUserAnalyticsId } from '../UseCase/GetUserAnalyticsId/GetUserAnalyticsId'
@@ -41,7 +41,7 @@ export class SubscriptionRenewedEventHandler implements DomainEventHandlerInterf
payedAmount: event.payload.payAmount,
planName: SubscriptionPlanName.create(event.payload.subscriptionName).getValue(),
subscriptionId: event.payload.subscriptionId,
userEmail: Email.create(event.payload.userEmail).getValue(),
username: Username.create(event.payload.userEmail).getValue(),
userUuid,
})

View File

@@ -18,7 +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.username = event.payload.email
analyticsEntity = await this.analyticsEntityRepository.save(analyticsEntity)
await this.analyticsStore.markActivity([AnalyticsActivity.Register], analyticsEntity.id, [

View File

@@ -1,5 +1,5 @@
import { injectable } from 'inversify'
import { Email, MapInterface, UniqueEntityId } from '@standardnotes/domain-core'
import { MapperInterface, UniqueEntityId, Username } from '@standardnotes/domain-core'
import { TypeORMRevenueModification } from '../../Infra/TypeORM/TypeORMRevenueModification'
import { MonthlyRevenue } from '../Revenue/MonthlyRevenue'
@@ -10,11 +10,11 @@ import { SubscriptionPlanName } from '../Subscription/SubscriptionPlanName'
import { SubscriptionEventType } from '../Subscription/SubscriptionEventType'
@injectable()
export class RevenueModificationMap implements MapInterface<RevenueModification, TypeORMRevenueModification> {
export class RevenueModificationMap implements MapperInterface<RevenueModification, TypeORMRevenueModification> {
toDomain(persistence: TypeORMRevenueModification): RevenueModification {
const userOrError = User.create(
{
email: Email.create(persistence.userEmail).getValue(),
username: Username.create(persistence.username).getValue(),
},
new UniqueEntityId(persistence.userUuid),
)
@@ -70,7 +70,7 @@ export class RevenueModificationMap implements MapInterface<RevenueModification,
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.username = user.props.username.value
persistence.userUuid = user.id.toString()
persistence.createdAt = domain.props.createdAt

View File

@@ -1,4 +1,4 @@
import { Email } from '@standardnotes/domain-core'
import { Username } from '@standardnotes/domain-core'
import { Subscription } from '../Subscription/Subscription'
import { SubscriptionEventType } from '../Subscription/SubscriptionEventType'
@@ -19,7 +19,7 @@ describe('RevenueModification', () => {
planName: SubscriptionPlanName.create('PRO_PLAN').getValue(),
}).getValue()
user = User.create({
email: Email.create('test@test.te').getValue(),
username: Username.create('test@test.te').getValue(),
}).getValue()
})

View File

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

View File

@@ -20,7 +20,9 @@ export class CalculateMonthlyRecurringRevenue implements DomainUseCaseInterface<
) {}
async execute(_dto: CalculateMonthlyRecurringRevenueDTO): Promise<Result<MonthlyRevenue>> {
const mrrDiff = await this.revenueModificationRepository.sumMRRDiff({})
const mrrDiff = await this.revenueModificationRepository.sumMRRDiff({
billingFrequencies: [SubscriptionBillingFrequency.Annual, SubscriptionBillingFrequency.Monthly],
})
await this.statisticsStore.setMeasure(StatisticsMeasure.MRR, mrrDiff, [
Period.Today,
@@ -29,7 +31,7 @@ export class CalculateMonthlyRecurringRevenue implements DomainUseCaseInterface<
])
const monthlyPlansMrrDiff = await this.revenueModificationRepository.sumMRRDiff({
billingFrequency: SubscriptionBillingFrequency.Monthly,
billingFrequencies: [SubscriptionBillingFrequency.Monthly],
})
await this.statisticsStore.setMeasure(StatisticsMeasure.MonthlyPlansMRR, monthlyPlansMrrDiff, [
@@ -39,7 +41,7 @@ export class CalculateMonthlyRecurringRevenue implements DomainUseCaseInterface<
])
const annualPlansMrrDiff = await this.revenueModificationRepository.sumMRRDiff({
billingFrequency: SubscriptionBillingFrequency.Annual,
billingFrequencies: [SubscriptionBillingFrequency.Annual],
})
await this.statisticsStore.setMeasure(StatisticsMeasure.AnnualPlansMRR, annualPlansMrrDiff, [
@@ -49,7 +51,7 @@ export class CalculateMonthlyRecurringRevenue implements DomainUseCaseInterface<
])
const fiveYearPlansMrrDiff = await this.revenueModificationRepository.sumMRRDiff({
billingFrequency: SubscriptionBillingFrequency.FiveYear,
billingFrequencies: [SubscriptionBillingFrequency.FiveYear],
})
await this.statisticsStore.setMeasure(StatisticsMeasure.FiveYearPlansMRR, fiveYearPlansMrrDiff, [
@@ -59,7 +61,8 @@ export class CalculateMonthlyRecurringRevenue implements DomainUseCaseInterface<
])
const proPlansMrrDiff = await this.revenueModificationRepository.sumMRRDiff({
planName: SubscriptionName.ProPlan,
planNames: [SubscriptionName.ProPlan],
billingFrequencies: [SubscriptionBillingFrequency.Annual, SubscriptionBillingFrequency.Monthly],
})
await this.statisticsStore.setMeasure(StatisticsMeasure.ProPlansMRR, proPlansMrrDiff, [
@@ -69,7 +72,8 @@ export class CalculateMonthlyRecurringRevenue implements DomainUseCaseInterface<
])
const plusPlansMrrDiff = await this.revenueModificationRepository.sumMRRDiff({
planName: SubscriptionName.PlusPlan,
planNames: [SubscriptionName.PlusPlan],
billingFrequencies: [SubscriptionBillingFrequency.Annual, SubscriptionBillingFrequency.Monthly],
})
await this.statisticsStore.setMeasure(StatisticsMeasure.PlusPlansMRR, plusPlansMrrDiff, [

View File

@@ -14,8 +14,8 @@ describe('GetUserAnalyticsId', () => {
beforeEach(() => {
analyticsEntity = {
id: 123,
userUuid: '1-2-3',
userEmail: 'test@test.te',
userUuid: '84c0f8e8-544a-4c7e-9adf-26209303bc1d',
username: 'test@test.te',
} as jest.Mocked<AnalyticsEntity>
analyticsEntityRepository = {} as jest.Mocked<AnalyticsEntityRepositoryInterface>
@@ -24,11 +24,11 @@ describe('GetUserAnalyticsId', () => {
})
it('should return analytics id for a user by uuid', async () => {
expect(await (await createUseCase().execute({ userUuid: '1-2-3' })).analyticsId).toEqual(123)
expect((await createUseCase().execute({ userUuid: '1-2-3' })).analyticsId).toEqual(123)
})
it('should return analytics id for a user by email', async () => {
expect(await (await createUseCase().execute({ userEmail: 'test@test.te' })).analyticsId).toEqual(123)
expect((await createUseCase().execute({ userEmail: 'test@test.te' })).analyticsId).toEqual(123)
})
it('should throw error if user is missing analytics entity', async () => {

View File

@@ -1,5 +1,5 @@
import { inject, injectable } from 'inversify'
import { Email, Uuid } from '@standardnotes/domain-core'
import { Username, Uuid } from '@standardnotes/domain-core'
import TYPES from '../../../Bootstrap/Types'
import { AnalyticsEntityRepositoryInterface } from '../../Entity/AnalyticsEntityRepositoryInterface'
@@ -28,7 +28,7 @@ export class GetUserAnalyticsId implements UseCaseInterface {
return {
analyticsId: analyticsEntity.id,
userUuid: Uuid.create(analyticsEntity.userUuid).getValue(),
userEmail: Email.create(analyticsEntity.userEmail).getValue(),
username: Username.create(analyticsEntity.username).getValue(),
}
}
}

View File

@@ -1,7 +1,7 @@
import { Email, Uuid } from '@standardnotes/domain-core'
import { Username, Uuid } from '@standardnotes/domain-core'
export type GetUserAnalyticsIdResponse = {
analyticsId: number
userEmail: Email
username: Username
userUuid: Uuid
}

View File

@@ -1,7 +1,7 @@
import 'reflect-metadata'
import { TimerInterface } from '@standardnotes/time'
import { Email, Result, Uuid } from '@standardnotes/domain-core'
import { Result, Username, Uuid } from '@standardnotes/domain-core'
import { MonthlyRevenue } from '../../Revenue/MonthlyRevenue'
@@ -45,8 +45,8 @@ describe('SaveRevenueModification', () => {
payedAmount: 12.99,
planName: SubscriptionPlanName.create('PRO_PLAN').getValue(),
subscriptionId: 1234,
userEmail: Email.create('test@test.te').getValue(),
userUuid: Uuid.create('1-2-3').getValue(),
username: Username.create('test@test.te').getValue(),
userUuid: Uuid.create('84c0f8e8-544a-4c7e-9adf-26209303bc1d').getValue(),
})
expect(revenueOrError.isFailed()).toBeFalsy()
@@ -63,8 +63,8 @@ describe('SaveRevenueModification', () => {
payedAmount: 12.99,
planName: SubscriptionPlanName.create('PRO_PLAN').getValue(),
subscriptionId: 1234,
userEmail: Email.create('test@test.te').getValue(),
userUuid: Uuid.create('1-2-3').getValue(),
username: Username.create('test@test.te').getValue(),
userUuid: Uuid.create('84c0f8e8-544a-4c7e-9adf-26209303bc1d').getValue(),
})
expect(revenueOrError.isFailed()).toBeFalsy()
@@ -81,8 +81,8 @@ describe('SaveRevenueModification', () => {
payedAmount: 2,
planName: SubscriptionPlanName.create('PRO_PLAN').getValue(),
subscriptionId: 1234,
userEmail: Email.create('test@test.te').getValue(),
userUuid: Uuid.create('1-2-3').getValue(),
username: Username.create('test@test.te').getValue(),
userUuid: Uuid.create('84c0f8e8-544a-4c7e-9adf-26209303bc1d').getValue(),
})
expect(revenueOrError.isFailed()).toBeFalsy()
@@ -101,8 +101,8 @@ describe('SaveRevenueModification', () => {
payedAmount: 12.99,
planName: SubscriptionPlanName.create('PRO_PLAN').getValue(),
subscriptionId: 1234,
userEmail: Email.create('test@test.te').getValue(),
userUuid: Uuid.create('1-2-3').getValue(),
username: Username.create('test@test.te').getValue(),
userUuid: Uuid.create('84c0f8e8-544a-4c7e-9adf-26209303bc1d').getValue(),
})
expect(revenueOrError.isFailed()).toBeFalsy()
@@ -122,8 +122,8 @@ describe('SaveRevenueModification', () => {
payedAmount: 12.99,
planName: SubscriptionPlanName.create('PRO_PLAN').getValue(),
subscriptionId: 1234,
userEmail: Email.create('test@test.te').getValue(),
userUuid: Uuid.create('1-2-3').getValue(),
username: Username.create('test@test.te').getValue(),
userUuid: Uuid.create('84c0f8e8-544a-4c7e-9adf-26209303bc1d').getValue(),
})
expect(revenueOrError.isFailed()).toBeTruthy()
@@ -142,8 +142,8 @@ describe('SaveRevenueModification', () => {
payedAmount: 12.99,
planName: SubscriptionPlanName.create('PRO_PLAN').getValue(),
subscriptionId: 1234,
userEmail: Email.create('test@test.te').getValue(),
userUuid: Uuid.create('1-2-3').getValue(),
username: Username.create('test@test.te').getValue(),
userUuid: Uuid.create('84c0f8e8-544a-4c7e-9adf-26209303bc1d').getValue(),
})
expect(revenueOrError.isFailed()).toBeTruthy()
@@ -162,8 +162,8 @@ describe('SaveRevenueModification', () => {
payedAmount: 12.99,
planName: SubscriptionPlanName.create('PRO_PLAN').getValue(),
subscriptionId: 1234,
userEmail: Email.create('test@test.te').getValue(),
userUuid: Uuid.create('1-2-3').getValue(),
username: Username.create('test@test.te').getValue(),
userUuid: Uuid.create('84c0f8e8-544a-4c7e-9adf-26209303bc1d').getValue(),
})
expect(revenueOrError.isFailed()).toBeTruthy()
@@ -182,8 +182,8 @@ describe('SaveRevenueModification', () => {
payedAmount: 12.99,
planName: SubscriptionPlanName.create('PRO_PLAN').getValue(),
subscriptionId: 1234,
userEmail: Email.create('test@test.te').getValue(),
userUuid: Uuid.create('1-2-3').getValue(),
username: Username.create('test@test.te').getValue(),
userUuid: Uuid.create('84c0f8e8-544a-4c7e-9adf-26209303bc1d').getValue(),
})
expect(revenueOrError.isFailed()).toBeTruthy()
@@ -202,8 +202,8 @@ describe('SaveRevenueModification', () => {
payedAmount: 12.99,
planName: SubscriptionPlanName.create('PRO_PLAN').getValue(),
subscriptionId: 1234,
userEmail: Email.create('test@test.te').getValue(),
userUuid: Uuid.create('1-2-3').getValue(),
username: Username.create('test@test.te').getValue(),
userUuid: Uuid.create('84c0f8e8-544a-4c7e-9adf-26209303bc1d').getValue(),
})
expect(revenueOrError.isFailed()).toBeTruthy()

View File

@@ -23,7 +23,7 @@ export class SaveRevenueModification implements DomainUseCaseInterface<RevenueMo
async execute(dto: SaveRevenueModificationDTO): Promise<Result<RevenueModification>> {
const userOrError = User.create(
{
email: dto.userEmail,
username: dto.username,
},
new UniqueEntityId(dto.userUuid.value),
)

View File

@@ -1,4 +1,4 @@
import { Email, Uuid } from '@standardnotes/domain-core'
import { Username, Uuid } from '@standardnotes/domain-core'
import { SubscriptionEventType } from '../../Subscription/SubscriptionEventType'
import { SubscriptionPlanName } from '../../Subscription/SubscriptionPlanName'
@@ -9,7 +9,7 @@ export interface SaveRevenueModificationDTO {
planName: SubscriptionPlanName
newSubscriber: boolean
userUuid: Uuid
userEmail: Email
username: Username
subscriptionId: number
billingFrequency: number
}

View File

@@ -1,11 +1,11 @@
import { Email } from '@standardnotes/domain-core'
import { Username } from '@standardnotes/domain-core'
import { User } from './User'
describe('User', () => {
it('should create an entity', () => {
const user = User.create({
email: Email.create('test@test.te').getValue(),
username: Username.create('test@test.te').getValue(),
}).getValue()
expect(user.id.toString()).toHaveLength(36)

View File

@@ -1,5 +1,5 @@
import { Email } from '@standardnotes/domain-core'
import { Username } from '@standardnotes/domain-core'
export interface UserProps {
email: Email
username: Username
}

View File

@@ -1,6 +1,6 @@
import { inject, injectable } from 'inversify'
import { Repository } from 'typeorm'
import { MapInterface, Uuid } from '@standardnotes/domain-core'
import { MapperInterface, Uuid } from '@standardnotes/domain-core'
import TYPES from '../../Bootstrap/Types'
import { RevenueModification } from '../../Domain/Revenue/RevenueModification'
@@ -13,17 +13,17 @@ export class MySQLRevenueModificationRepository implements RevenueModificationRe
@inject(TYPES.ORMRevenueModificationRepository)
private ormRepository: Repository<TypeORMRevenueModification>,
@inject(TYPES.RevenueModificationMap)
private revenueModificationMap: MapInterface<RevenueModification, TypeORMRevenueModification>,
private revenueModificationMap: MapperInterface<RevenueModification, TypeORMRevenueModification>,
) {}
async sumMRRDiff(dto: { planName?: string; billingFrequency?: number }): Promise<number> {
async sumMRRDiff(dto: { billingFrequencies: number[]; planNames?: string[] }): Promise<number> {
const query = this.ormRepository.createQueryBuilder().select('sum(new_mrr - previous_mrr)', 'mrrDiff')
if (dto.planName !== undefined) {
query.where('subscription_plan = :planName', { planName: dto.planName })
if (dto.billingFrequencies.length > 0) {
query.where('billing_frequency IN (:...billingFrequencies)', { billingFrequencies: dto.billingFrequencies })
}
if (dto.billingFrequency !== undefined) {
query.where('billing_frequency = :billingFrequency', { billingFrequency: dto.billingFrequency })
if (dto.planNames && dto.planNames.length > 0) {
query.andWhere('subscription_plan IN (:...planNames)', { planNames: dto.planNames })
}
const result = await query.getRawOne()

View File

@@ -18,7 +18,7 @@ export class TypeORMRevenueModification {
length: 255,
})
@Index('email')
declare userEmail: string
declare username: string
@Column({
name: 'user_uuid',

View File

@@ -10,6 +10,7 @@ WORKSPACE_SERVER_URL=http://workspace:3000
WEB_SOCKET_SERVER_URL=http://websockets:3000
PAYMENTS_SERVER_URL=http://payments:3000
FILES_SERVER_URL=http://files:3000
REVISIONS_SERVER_URL=http://revisions:3000
HTTP_CALL_TIMEOUT=60000

View File

@@ -3,6 +3,54 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.39.6](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.39.5...@standardnotes/api-gateway@1.39.6) (2022-11-30)
**Note:** Version bump only for package @standardnotes/api-gateway
## [1.39.5](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.39.4...@standardnotes/api-gateway@1.39.5) (2022-11-28)
**Note:** Version bump only for package @standardnotes/api-gateway
## [1.39.4](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.39.3...@standardnotes/api-gateway@1.39.4) (2022-11-25)
### Bug Fixes
* **api-gateway:** make revisions and workspace server urls optional ([8907879](https://github.com/standardnotes/api-gateway/commit/8907879a194d2d8328fbd3ca8ec9d0b608c2da50))
## [1.39.3](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.39.2...@standardnotes/api-gateway@1.39.3) (2022-11-25)
**Note:** Version bump only for package @standardnotes/api-gateway
## [1.39.2](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.39.1...@standardnotes/api-gateway@1.39.2) (2022-11-24)
**Note:** Version bump only for package @standardnotes/api-gateway
## [1.39.1](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.39.0...@standardnotes/api-gateway@1.39.1) (2022-11-23)
**Note:** Version bump only for package @standardnotes/api-gateway
# [1.39.0](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.38.9...@standardnotes/api-gateway@1.39.0) (2022-11-22)
### Features
* **api-gateway:** add v2 revisions controller ([92ba759](https://github.com/standardnotes/api-gateway/commit/92ba759b1c3719e773f989707ddd6d7a9ec57d1c))
## [1.38.9](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.38.8...@standardnotes/api-gateway@1.38.9) (2022-11-22)
**Note:** Version bump only for package @standardnotes/api-gateway
## [1.38.8](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.38.7...@standardnotes/api-gateway@1.38.8) (2022-11-21)
**Note:** Version bump only for package @standardnotes/api-gateway
## [1.38.7](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.38.6...@standardnotes/api-gateway@1.38.7) (2022-11-18)
**Note:** Version bump only for package @standardnotes/api-gateway
## [1.38.6](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.38.5...@standardnotes/api-gateway@1.38.6) (2022-11-16)
**Note:** Version bump only for package @standardnotes/api-gateway
## [1.38.5](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.38.4...@standardnotes/api-gateway@1.38.5) (2022-11-14)
**Note:** Version bump only for package @standardnotes/api-gateway

View File

@@ -24,6 +24,7 @@ import '../src/Controller/v1/InvitesController'
import '../src/Controller/v2/PaymentsControllerV2'
import '../src/Controller/v2/ActionsControllerV2'
import '../src/Controller/v2/RevisionsControllerV2'
import helmet from 'helmet'
import * as cors from 'cors'

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/api-gateway",
"version": "1.38.5",
"version": "1.39.6",
"engines": {
"node": ">=18.0.0 <19.0.0"
},
@@ -20,7 +20,6 @@
"upgrade:snjs": "yarn ncu -u '@standardnotes/*'"
},
"dependencies": {
"@newrelic/native-metrics": "^9.0.0",
"@newrelic/winston-enricher": "^4.0.0",
"@sentry/node": "^7.19.0",
"@standardnotes/common": "workspace:^",
@@ -28,7 +27,7 @@
"@standardnotes/domain-events-infra": "workspace:*",
"@standardnotes/security": "workspace:*",
"@standardnotes/time": "workspace:*",
"aws-sdk": "^2.1253.0",
"aws-sdk": "^2.1260.0",
"axios": "^1.1.3",
"cors": "2.8.5",
"dotenv": "^16.0.1",

View File

@@ -54,10 +54,11 @@ export class ContainerConfigLoader {
// env vars
container.bind(TYPES.SYNCING_SERVER_JS_URL).toConstantValue(env.get('SYNCING_SERVER_JS_URL'))
container.bind(TYPES.AUTH_SERVER_URL).toConstantValue(env.get('AUTH_SERVER_URL'))
container.bind(TYPES.REVISIONS_SERVER_URL).toConstantValue(env.get('REVISIONS_SERVER_URL', true))
container.bind(TYPES.PAYMENTS_SERVER_URL).toConstantValue(env.get('PAYMENTS_SERVER_URL', true))
container.bind(TYPES.FILES_SERVER_URL).toConstantValue(env.get('FILES_SERVER_URL', true))
container.bind(TYPES.AUTH_JWT_SECRET).toConstantValue(env.get('AUTH_JWT_SECRET'))
container.bind(TYPES.WORKSPACE_SERVER_URL).toConstantValue(env.get('WORKSPACE_SERVER_URL'))
container.bind(TYPES.WORKSPACE_SERVER_URL).toConstantValue(env.get('WORKSPACE_SERVER_URL', true))
container.bind(TYPES.WEB_SOCKET_SERVER_URL).toConstantValue(env.get('WEB_SOCKET_SERVER_URL', true))
container
.bind(TYPES.HTTP_CALL_TIMEOUT)

View File

@@ -7,6 +7,7 @@ const TYPES = {
AUTH_SERVER_URL: Symbol.for('AUTH_SERVER_URL'),
PAYMENTS_SERVER_URL: Symbol.for('PAYMENTS_SERVER_URL'),
FILES_SERVER_URL: Symbol.for('FILES_SERVER_URL'),
REVISIONS_SERVER_URL: Symbol.for('REVISIONS_SERVER_URL'),
WORKSPACE_SERVER_URL: Symbol.for('WORKSPACE_SERVER_URL'),
WEB_SOCKET_SERVER_URL: Symbol.for('WEB_SOCKET_SERVER_URL'),
AUTH_JWT_SECRET: Symbol.for('AUTH_JWT_SECRET'),

View File

@@ -0,0 +1,17 @@
import { Request, Response } from 'express'
import { inject } from 'inversify'
import { BaseHttpController, controller, httpGet } from 'inversify-express-utils'
import TYPES from '../../Bootstrap/Types'
import { HttpServiceInterface } from '../../Service/Http/HttpServiceInterface'
@controller('/v2/items/:item_id/revisions', TYPES.AuthMiddleware)
export class RevisionsControllerV2 extends BaseHttpController {
constructor(@inject(TYPES.HTTPService) private httpService: HttpServiceInterface) {
super()
}
@httpGet('/')
async getRevisions(request: Request, response: Response): Promise<void> {
await this.httpService.callRevisionsServer(request, response, `items/${request.params.item_id}/revisions`)
}
}

View File

@@ -18,6 +18,7 @@ export class HttpService implements HttpServiceInterface {
@inject(TYPES.FILES_SERVER_URL) private filesServerUrl: string,
@inject(TYPES.WORKSPACE_SERVER_URL) private workspaceServerUrl: string,
@inject(TYPES.WEB_SOCKET_SERVER_URL) private webSocketServerUrl: string,
@inject(TYPES.REVISIONS_SERVER_URL) private revisionsServerUrl: string,
@inject(TYPES.HTTP_CALL_TIMEOUT) private httpCallTimeout: number,
@inject(TYPES.CrossServiceTokenCache) private crossServiceTokenCache: CrossServiceTokenCacheInterface,
@inject(TYPES.Logger) private logger: Logger,
@@ -32,6 +33,20 @@ export class HttpService implements HttpServiceInterface {
await this.callServer(this.syncingServerJsUrl, request, response, endpoint, payload)
}
async callRevisionsServer(
request: Request,
response: Response,
endpoint: string,
payload?: Record<string, unknown> | string,
): Promise<void> {
if (!this.revisionsServerUrl) {
response.status(400).send({ message: 'Revisions Server not configured' })
return
}
await this.callServer(this.revisionsServerUrl, request, response, endpoint, payload)
}
async callLegacySyncingServer(
request: Request,
response: Response,
@@ -56,6 +71,12 @@ export class HttpService implements HttpServiceInterface {
endpoint: string,
payload?: Record<string, unknown> | string,
): Promise<void> {
if (!this.workspaceServerUrl) {
response.status(400).send({ message: 'Workspace Server not configured' })
return
}
await this.callServer(this.workspaceServerUrl, request, response, endpoint, payload)
}

View File

@@ -13,6 +13,12 @@ export interface HttpServiceInterface {
endpoint: string,
payload?: Record<string, unknown> | string,
): Promise<void>
callRevisionsServer(
request: Request,
response: Response,
endpoint: string,
payload?: Record<string, unknown> | string,
): Promise<void>
callSyncingServer(
request: Request,
response: Response,

View File

@@ -3,6 +3,78 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.60.15](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.60.14...@standardnotes/auth-server@1.60.15) (2022-11-30)
**Note:** Version bump only for package @standardnotes/auth-server
## [1.60.14](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.60.13...@standardnotes/auth-server@1.60.14) (2022-11-28)
**Note:** Version bump only for package @standardnotes/auth-server
## [1.60.13](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.60.12...@standardnotes/auth-server@1.60.13) (2022-11-25)
### Bug Fixes
* **auth:** bring back streaming all users in an email campaign send out ([8407c3b](https://github.com/standardnotes/server/commit/8407c3b64910c87591a97b856f5b0c0aebc98e51))
## [1.60.12](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.60.11...@standardnotes/auth-server@1.60.12) (2022-11-25)
### Bug Fixes
* **auth:** tmp test email campaign black friday 2022 reminder on team only ([25a6796](https://github.com/standardnotes/server/commit/25a6796e636bc30de99001bd16a2a1084b608b6a))
## [1.60.11](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.60.10...@standardnotes/auth-server@1.60.11) (2022-11-25)
**Note:** Version bump only for package @standardnotes/auth-server
## [1.60.10](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.60.9...@standardnotes/auth-server@1.60.10) (2022-11-24)
**Note:** Version bump only for package @standardnotes/auth-server
## [1.60.9](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.60.8...@standardnotes/auth-server@1.60.9) (2022-11-23)
**Note:** Version bump only for package @standardnotes/auth-server
## [1.60.8](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.60.7...@standardnotes/auth-server@1.60.8) (2022-11-23)
### Bug Fixes
* binding of sns and sqs with additional config ([74bc791](https://github.com/standardnotes/server/commit/74bc79116bc50d9a5af1a558db1b7108dcda6d0e))
## [1.60.7](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.60.6...@standardnotes/auth-server@1.60.7) (2022-11-22)
### Bug Fixes
* **auth:** remove temporary email campaign check for team member ([5f2be44](https://github.com/standardnotes/server/commit/5f2be44b853e83abb6c4e758efd477e899381e07))
## [1.60.6](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.60.5...@standardnotes/auth-server@1.60.6) (2022-11-22)
### Bug Fixes
* sns binding ([3686a26](https://github.com/standardnotes/server/commit/3686a260192468c00b52087590dd2edf76ada939))
## [1.60.5](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.60.4...@standardnotes/auth-server@1.60.5) (2022-11-22)
### Bug Fixes
* **auth:** tmp send email campaign only to team ([94359f1](https://github.com/standardnotes/server/commit/94359f1299a2bb009099af163d3929c4adc7e274))
## [1.60.4](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.60.3...@standardnotes/auth-server@1.60.4) (2022-11-22)
**Note:** Version bump only for package @standardnotes/auth-server
## [1.60.3](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.60.2...@standardnotes/auth-server@1.60.3) (2022-11-21)
**Note:** Version bump only for package @standardnotes/auth-server
## [1.60.2](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.60.1...@standardnotes/auth-server@1.60.2) (2022-11-18)
**Note:** Version bump only for package @standardnotes/auth-server
## [1.60.1](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.60.0...@standardnotes/auth-server@1.60.1) (2022-11-16)
**Note:** Version bump only for package @standardnotes/auth-server
# [1.60.0](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.59.11...@standardnotes/auth-server@1.60.0) (2022-11-14)
### Features

View File

@@ -7,6 +7,6 @@ module.exports = {
transform: {
...tsjPreset.transform,
},
coveragePathIgnorePatterns: ['/Bootstrap/', '/InversifyExpressUtils/', 'HealthCheckController'],
coveragePathIgnorePatterns: ['/Bootstrap/', '/InversifyExpressUtils/', 'HealthCheckController', '/Infra/'],
setupFilesAfterEnv: ['./test-setup.ts'],
}

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/auth-server",
"version": "1.60.0",
"version": "1.60.15",
"engines": {
"node": ">=18.0.0 <19.0.0"
},
@@ -31,7 +31,6 @@
"upgrade:snjs": "yarn ncu -u '@standardnotes/*'"
},
"dependencies": {
"@newrelic/native-metrics": "^9.0.0",
"@newrelic/winston-enricher": "^4.0.0",
"@sentry/node": "^7.19.0",
"@standardnotes/api": "^1.19.0",
@@ -46,7 +45,7 @@
"@standardnotes/sncrypto-common": "^1.9.0",
"@standardnotes/sncrypto-node": "workspace:*",
"@standardnotes/time": "workspace:*",
"aws-sdk": "^2.1253.0",
"aws-sdk": "^2.1260.0",
"axios": "^1.1.3",
"bcryptjs": "2.4.3",
"cors": "2.8.5",

View File

@@ -230,13 +230,24 @@ export class ContainerConfigLoader {
})
container.bind<winston.Logger>(TYPES.Logger).toConstantValue(logger)
if (env.get('SNS_AWS_REGION', true)) {
container.bind<AWS.SNS>(TYPES.SNS).toConstantValue(
new AWS.SNS({
apiVersion: 'latest',
region: env.get('SNS_AWS_REGION', true),
}),
)
if (env.get('SNS_TOPIC_ARN', true)) {
const snsConfig: AWS.SNS.Types.ClientConfiguration = {
apiVersion: 'latest',
region: env.get('SNS_AWS_REGION', true),
}
if (env.get('SNS_ENDPOINT', true)) {
snsConfig.endpoint = env.get('SNS_ENDPOINT', true)
}
if (env.get('SNS_DISABLE_SSL', true) === 'true') {
snsConfig.sslEnabled = false
}
if (env.get('SNS_ACCESS_KEY_ID', true) && env.get('SNS_SECRET_ACCESS_KEY', true)) {
snsConfig.credentials = {
accessKeyId: env.get('SNS_ACCESS_KEY_ID', true),
secretAccessKey: env.get('SNS_SECRET_ACCESS_KEY', true),
}
}
container.bind<AWS.SNS>(TYPES.SNS).toConstantValue(new AWS.SNS(snsConfig))
}
if (env.get('SQS_QUEUE_URL', true)) {

View File

@@ -3,6 +3,7 @@ import { User } from './User'
export interface UserRepositoryInterface {
streamAll(): Promise<ReadStream>
streamTeam(memberEmail?: string): Promise<ReadStream>
findOneByUuid(uuid: string): Promise<User | null>
findOneByEmail(email: string): Promise<User | null>
save(user: User): Promise<User>

View File

@@ -25,6 +25,17 @@ export class MySQLUserRepository implements UserRepositoryInterface {
return this.ormRepository.createQueryBuilder('user').stream()
}
async streamTeam(memberEmail?: string): Promise<ReadStream> {
const queryBuilder = this.ormRepository.createQueryBuilder()
if (memberEmail !== undefined) {
queryBuilder.where('email = :email', { email: memberEmail })
} else {
queryBuilder.where('email LIKE :email', { email: '%@standardnotes.com' })
}
return queryBuilder.stream()
}
async findOneByUuid(uuid: string): Promise<User | null> {
return this.ormRepository
.createQueryBuilder('user')

View File

@@ -3,6 +3,18 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.46.1](https://github.com/standardnotes/server/compare/@standardnotes/common@1.46.0...@standardnotes/common@1.46.1) (2022-11-25)
### Bug Fixes
* **common:** add black friday 2022 reminder message identifier ([91b76ed](https://github.com/standardnotes/server/commit/91b76edce1c1abfa4e860932d98ce8cd369017c0))
# [1.46.0](https://github.com/standardnotes/server/compare/@standardnotes/common@1.45.0...@standardnotes/common@1.46.0) (2022-11-22)
### Features
* **common:** add marketing campaign for black friday 2022 email message identifier ([d77eb7f](https://github.com/standardnotes/server/commit/d77eb7f5f11bcc7cd5c6fa6d20e891b466af7b45))
# [1.45.0](https://github.com/standardnotes/server/compare/@standardnotes/common@1.44.4...@standardnotes/common@1.45.0) (2022-11-14)
### Features

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/common",
"version": "1.45.0",
"version": "1.46.1",
"engines": {
"node": ">=18.0.0 <19.0.0"
},

View File

@@ -18,6 +18,8 @@ export enum EmailMessageIdentifier {
STUDENT_DISCOUNT_REQUESTED = 'STUDENT_DISCOUNT_REQUESTED',
STUDENT_DISCOUNT_APPROVED = 'STUDENT_DISCOUNT_APPROVED',
MARKETING_CAMPAIGN_FILES = 'MARKETING_CAMPAIGN_FILES',
MARKETING_BLACK_FRIDAY_2022 = 'MARKETING_BLACK_FRIDAY_2022',
MARKETING_BLACK_FRIDAY_2022_REMINDER = 'MARKETING_BLACK_FRIDAY_2022_REMINDER',
PAYMENT_FAILED = 'PAYMENT_FAILED',
SEND_INVOICE = 'SEND_INVOICE',
DISCOUNT_NOTICE = 'DISCOUNT_NOTICE',

View File

@@ -3,6 +3,63 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
# [1.7.0](https://github.com/standardnotes/server/compare/@standardnotes/domain-core@1.6.0...@standardnotes/domain-core@1.7.0) (2022-12-05)
### Features
* **domain-core:** distinguish between username and email ([06fd404](https://github.com/standardnotes/server/commit/06fd404d44b44a53733f889aabd4da63f21e2f36))
# [1.6.0](https://github.com/standardnotes/server/compare/@standardnotes/domain-core@1.5.2...@standardnotes/domain-core@1.6.0) (2022-12-02)
### Features
* **domain-core:** add subscription plan name value object ([800fe9e](https://github.com/standardnotes/server/commit/800fe9e4c80c33f2da8097b5a153f470a23b7984))
## [1.5.2](https://github.com/standardnotes/server/compare/@standardnotes/domain-core@1.5.1...@standardnotes/domain-core@1.5.2) (2022-12-02)
### Bug Fixes
* **domain-core:** rename timestamps to dates ([dd86c5b](https://github.com/standardnotes/server/commit/dd86c5bcdf3a1a37d684f6416d4cc6f24497fe5e))
## [1.5.1](https://github.com/standardnotes/server/compare/@standardnotes/domain-core@1.5.0...@standardnotes/domain-core@1.5.1) (2022-11-25)
**Note:** Version bump only for package @standardnotes/domain-core
# [1.5.0](https://github.com/standardnotes/server/compare/@standardnotes/domain-core@1.4.0...@standardnotes/domain-core@1.5.0) (2022-11-24)
### Features
* **domain-core:** add methods to check role power ([9d90f27](https://github.com/standardnotes/server/commit/9d90f276de8915d91d009909154036ba128687e0))
# [1.4.0](https://github.com/standardnotes/server/compare/@standardnotes/domain-core@1.3.0...@standardnotes/domain-core@1.4.0) (2022-11-24)
### Features
* **domain-core:** add role name collection value object ([ae2f8f0](https://github.com/standardnotes/server/commit/ae2f8f086b9f647bb98c59f32375b45243cb0af9))
# [1.3.0](https://github.com/standardnotes/server/compare/@standardnotes/domain-core@1.2.2...@standardnotes/domain-core@1.3.0) (2022-11-24)
### Features
* **domain-core:** add role name value object ([748630e](https://github.com/standardnotes/server/commit/748630e1f1ed1dfae2e743cd2b3d3fd91967088c))
## [1.2.2](https://github.com/standardnotes/server/compare/@standardnotes/domain-core@1.2.1...@standardnotes/domain-core@1.2.2) (2022-11-22)
**Note:** Version bump only for package @standardnotes/domain-core
## [1.2.1](https://github.com/standardnotes/server/compare/@standardnotes/domain-core@1.2.0...@standardnotes/domain-core@1.2.1) (2022-11-21)
### Bug Fixes
* **domain-core:** remove revisions related models to revisions microservice ([a6542dd](https://github.com/standardnotes/server/commit/a6542dd63870a8ada5fd8143d8e2133a570d9329))
# [1.2.0](https://github.com/standardnotes/server/compare/@standardnotes/domain-core@1.1.1...@standardnotes/domain-core@1.2.0) (2022-11-18)
### Features
* **domain-core:** add revision definition to domain core ([c8f3a0c](https://github.com/standardnotes/server/commit/c8f3a0ce7b589a6fbc47941fc5d1a44b6cf04fe3))
* **revisions:** add revisions microservice ([d5c06bf](https://github.com/standardnotes/server/commit/d5c06bfa58a987685fbd8fbab0d22df3fcff3377))
## [1.1.1](https://github.com/standardnotes/server/compare/@standardnotes/domain-core@1.1.0...@standardnotes/domain-core@1.1.1) (2022-11-14)
### Bug Fixes

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/domain-core",
"version": "1.1.1",
"version": "1.7.0",
"engines": {
"node": ">=18.0.0 <19.0.0"
},

View File

@@ -0,0 +1,21 @@
import { Dates } from './Dates'
describe('Dates', () => {
it('should create a value object', () => {
const valueOrError = Dates.create(new Date(1), new Date(2))
expect(valueOrError.isFailed()).toBeFalsy()
expect(valueOrError.getValue().createdAt).toEqual(new Date(1))
expect(valueOrError.getValue().updatedAt).toEqual(new Date(2))
})
it('should not create an invalid value object', () => {
let valueOrError = Dates.create(null as unknown as Date, '2' as unknown as Date)
expect(valueOrError.isFailed()).toBeTruthy()
valueOrError = Dates.create(new Date(2), '2' as unknown as Date)
expect(valueOrError.isFailed()).toBeTruthy()
})
})

View File

@@ -0,0 +1,28 @@
import { Result } from '../Core/Result'
import { ValueObject } from '../Core/ValueObject'
import { DatesProps } from './DatesProps'
export class Dates extends ValueObject<DatesProps> {
get createdAt(): Date {
return this.props.createdAt
}
get updatedAt(): Date {
return this.props.updatedAt
}
private constructor(props: DatesProps) {
super(props)
}
static create(createdAt: Date, updatedAt: Date): Result<Dates> {
if (!(createdAt instanceof Date)) {
return Result.fail<Dates>(`Could not create Dates. Creation date should be a date object, given: ${createdAt}`)
}
if (!(updatedAt instanceof Date)) {
return Result.fail<Dates>(`Could not create Dates. Update date should be a date object, given: ${createdAt}`)
}
return Result.ok<Dates>(new Dates({ createdAt, updatedAt }))
}
}

View File

@@ -0,0 +1,4 @@
export interface DatesProps {
createdAt: Date
updatedAt: Date
}

View File

@@ -9,7 +9,7 @@ describe('Email', () => {
})
it('should not create an invalid value object', () => {
const valueOrError = Email.create('')
const valueOrError = Email.create('foobar')
expect(valueOrError.isFailed()).toBeTruthy()
})

View File

@@ -1,6 +1,7 @@
import { ValueObject } from '../Core/ValueObject'
import { Result } from '../Core/Result'
import { EmailProps } from './EmailProps'
import { Validator } from '../Core/Validator'
export class Email extends ValueObject<EmailProps> {
get value(): string {
@@ -12,10 +13,11 @@ export class Email extends ValueObject<EmailProps> {
}
static create(email: string): Result<Email> {
if (!!email === false || email.length === 0) {
return Result.fail<Email>('Email cannot be empty')
} else {
return Result.ok<Email>(new Email({ value: email }))
const emailValidation = Validator.isValidEmail(email)
if (emailValidation.isFailed()) {
return Result.fail<Email>(emailValidation.getError())
}
return Result.ok<Email>(new Email({ value: email }))
}
}

View File

@@ -0,0 +1,38 @@
import { RoleName } from './RoleName'
describe('RoleName', () => {
it('should create a value object', () => {
const valueOrError = RoleName.create(RoleName.NAMES.ProUser)
expect(valueOrError.isFailed()).toBeFalsy()
expect(valueOrError.getValue().value).toEqual('PRO_USER')
})
it('should not create an invalid value object', () => {
for (const value of ['', undefined, null, 0, 'SOME_USER']) {
const valueOrError = RoleName.create(value as string)
expect(valueOrError.isFailed()).toBeTruthy()
}
})
it('should say if a role has more power or equal power to another role', () => {
const proUserRole = RoleName.create(RoleName.NAMES.ProUser).getValue()
const plusUserRole = RoleName.create(RoleName.NAMES.PlusUser).getValue()
const coreUser = RoleName.create(RoleName.NAMES.CoreUser).getValue()
expect(proUserRole.hasMoreOrEqualPowerTo(proUserRole)).toBeTruthy()
expect(proUserRole.hasMoreOrEqualPowerTo(plusUserRole)).toBeTruthy()
expect(proUserRole.hasMoreOrEqualPowerTo(coreUser)).toBeTruthy()
expect(plusUserRole.hasMoreOrEqualPowerTo(proUserRole)).toBeFalsy()
expect(plusUserRole.hasMoreOrEqualPowerTo(plusUserRole)).toBeTruthy()
expect(plusUserRole.hasMoreOrEqualPowerTo(coreUser)).toBeTruthy()
expect(coreUser.hasMoreOrEqualPowerTo(proUserRole)).toBeFalsy()
expect(coreUser.hasMoreOrEqualPowerTo(plusUserRole)).toBeFalsy()
expect(coreUser.hasMoreOrEqualPowerTo(coreUser)).toBeTruthy()
expect(RoleName.create(RoleName.NAMES.FilesBetaUser).getValue().hasMoreOrEqualPowerTo(coreUser)).toBeFalsy()
})
})

View File

@@ -0,0 +1,42 @@
import { ValueObject } from '../Core/ValueObject'
import { Result } from '../Core/Result'
import { RoleNameProps } from './RoleNameProps'
export class RoleName extends ValueObject<RoleNameProps> {
static readonly NAMES = {
CoreUser: 'CORE_USER',
PlusUser: 'PLUS_USER',
ProUser: 'PRO_USER',
FilesBetaUser: 'FILES_BETA_USER',
}
get value(): string {
return this.props.value
}
hasMoreOrEqualPowerTo(roleName: RoleName): boolean {
switch (this.value) {
case RoleName.NAMES.ProUser:
return true
case RoleName.NAMES.PlusUser:
return [RoleName.NAMES.CoreUser, RoleName.NAMES.PlusUser].includes(roleName.value)
case RoleName.NAMES.CoreUser:
return [RoleName.NAMES.CoreUser].includes(roleName.value)
default:
return false
}
}
private constructor(props: RoleNameProps) {
super(props)
}
static create(name: string): Result<RoleName> {
const isValidName = Object.values(this.NAMES).includes(name)
if (!isValidName) {
return Result.fail<RoleName>(`Invalid role name: ${name}`)
} else {
return Result.ok<RoleName>(new RoleName({ value: name }))
}
}
}

View File

@@ -0,0 +1,112 @@
import { RoleName } from './RoleName'
import { RoleNameCollection } from './RoleNameCollection'
describe('RoleNameCollection', () => {
it('should create a value object', () => {
const role1 = RoleName.create(RoleName.NAMES.ProUser).getValue()
const valueOrError = RoleNameCollection.create([role1])
expect(valueOrError.isFailed()).toBeFalsy()
expect(valueOrError.getValue().value).toEqual([role1])
})
it('should tell if collections are not equal', () => {
const roles1 = [
RoleName.create(RoleName.NAMES.ProUser).getValue(),
RoleName.create(RoleName.NAMES.PlusUser).getValue(),
]
let roles2 = RoleNameCollection.create([
RoleName.create(RoleName.NAMES.ProUser).getValue(),
RoleName.create(RoleName.NAMES.CoreUser).getValue(),
]).getValue()
let valueOrError = RoleNameCollection.create(roles1)
expect(valueOrError.getValue().equals(roles2)).toBeFalsy()
roles2 = RoleNameCollection.create([
RoleName.create(RoleName.NAMES.ProUser).getValue(),
RoleName.create(RoleName.NAMES.PlusUser).getValue(),
RoleName.create(RoleName.NAMES.CoreUser).getValue(),
]).getValue()
valueOrError = RoleNameCollection.create(roles1)
expect(valueOrError.getValue().equals(roles2)).toBeFalsy()
})
it('should tell if collections are equal', () => {
const roles1 = [
RoleName.create(RoleName.NAMES.ProUser).getValue(),
RoleName.create(RoleName.NAMES.PlusUser).getValue(),
]
const roles2 = RoleNameCollection.create([
RoleName.create(RoleName.NAMES.ProUser).getValue(),
RoleName.create(RoleName.NAMES.PlusUser).getValue(),
]).getValue()
const valueOrError = RoleNameCollection.create(roles1)
expect(valueOrError.getValue().equals(roles2)).toBeTruthy()
})
it('should tell if collection includes element', () => {
const roles1 = [
RoleName.create(RoleName.NAMES.ProUser).getValue(),
RoleName.create(RoleName.NAMES.PlusUser).getValue(),
]
const valueOrError = RoleNameCollection.create(roles1)
expect(valueOrError.getValue().includes(RoleName.create(RoleName.NAMES.ProUser).getValue())).toBeTruthy()
})
it('should tell if collection does not includes element', () => {
const roles1 = [
RoleName.create(RoleName.NAMES.ProUser).getValue(),
RoleName.create(RoleName.NAMES.PlusUser).getValue(),
]
const valueOrError = RoleNameCollection.create(roles1)
expect(valueOrError.getValue().includes(RoleName.create(RoleName.NAMES.CoreUser).getValue())).toBeFalsy()
})
it('should tell if collection has a role with more or equal power to', () => {
let roles = [RoleName.create(RoleName.NAMES.CoreUser).getValue()]
let valueOrError = RoleNameCollection.create(roles)
let roleNames = valueOrError.getValue()
expect(
roleNames.hasARoleNameWithMoreOrEqualPowerTo(RoleName.create(RoleName.NAMES.PlusUser).getValue()),
).toBeFalsy()
expect(roleNames.hasARoleNameWithMoreOrEqualPowerTo(RoleName.create(RoleName.NAMES.ProUser).getValue())).toBeFalsy()
expect(
roleNames.hasARoleNameWithMoreOrEqualPowerTo(RoleName.create(RoleName.NAMES.CoreUser).getValue()),
).toBeTruthy()
roles = [RoleName.create(RoleName.NAMES.CoreUser).getValue(), RoleName.create(RoleName.NAMES.PlusUser).getValue()]
valueOrError = RoleNameCollection.create(roles)
roleNames = valueOrError.getValue()
expect(
roleNames.hasARoleNameWithMoreOrEqualPowerTo(RoleName.create(RoleName.NAMES.PlusUser).getValue()),
).toBeTruthy()
expect(roleNames.hasARoleNameWithMoreOrEqualPowerTo(RoleName.create(RoleName.NAMES.ProUser).getValue())).toBeFalsy()
expect(
roleNames.hasARoleNameWithMoreOrEqualPowerTo(RoleName.create(RoleName.NAMES.CoreUser).getValue()),
).toBeTruthy()
roles = [RoleName.create(RoleName.NAMES.ProUser).getValue(), RoleName.create(RoleName.NAMES.PlusUser).getValue()]
valueOrError = RoleNameCollection.create(roles)
roleNames = valueOrError.getValue()
expect(
roleNames.hasARoleNameWithMoreOrEqualPowerTo(RoleName.create(RoleName.NAMES.PlusUser).getValue()),
).toBeTruthy()
expect(
roleNames.hasARoleNameWithMoreOrEqualPowerTo(RoleName.create(RoleName.NAMES.ProUser).getValue()),
).toBeTruthy()
expect(
roleNames.hasARoleNameWithMoreOrEqualPowerTo(RoleName.create(RoleName.NAMES.CoreUser).getValue()),
).toBeTruthy()
})
})

View File

@@ -0,0 +1,52 @@
import { ValueObject } from '../Core/ValueObject'
import { Result } from '../Core/Result'
import { RoleNameCollectionProps } from './RoleNameCollectionProps'
import { RoleName } from './RoleName'
export class RoleNameCollection extends ValueObject<RoleNameCollectionProps> {
get value(): RoleName[] {
return this.props.value
}
includes(roleName: RoleName): boolean {
for (const existingRoleName of this.props.value) {
if (existingRoleName.equals(roleName)) {
return true
}
}
return false
}
hasARoleNameWithMoreOrEqualPowerTo(roleName: RoleName): boolean {
for (const existingRoleName of this.props.value) {
if (existingRoleName.hasMoreOrEqualPowerTo(roleName)) {
return true
}
}
return false
}
override equals(roleNameCollection: RoleNameCollection): boolean {
if (this.props.value.length !== roleNameCollection.value.length) {
return false
}
for (const roleName of roleNameCollection.value) {
if (!this.includes(roleName)) {
return false
}
}
return true
}
private constructor(props: RoleNameCollectionProps) {
super(props)
}
static create(roleName: RoleName[]): Result<RoleNameCollection> {
return Result.ok<RoleNameCollection>(new RoleNameCollection({ value: roleName }))
}
}

View File

@@ -0,0 +1,5 @@
import { RoleName } from './RoleName'
export interface RoleNameCollectionProps {
value: RoleName[]
}

View File

@@ -0,0 +1,3 @@
export interface RoleNameProps {
value: string
}

View File

@@ -0,0 +1,16 @@
import { Username } from './Username'
describe('Username', () => {
it('should create a value object', () => {
const valueOrError = Username.create('test@test.te')
expect(valueOrError.isFailed()).toBeFalsy()
expect(valueOrError.getValue().value).toEqual('test@test.te')
})
it('should not create an invalid value object', () => {
const valueOrError = Username.create('')
expect(valueOrError.isFailed()).toBeTruthy()
})
})

View File

@@ -0,0 +1,22 @@
import { ValueObject } from '../Core/ValueObject'
import { Result } from '../Core/Result'
import { UsernameProps } from './UsernameProps'
import { Validator } from '../Core/Validator'
export class Username extends ValueObject<UsernameProps> {
get value(): string {
return this.props.value
}
private constructor(props: UsernameProps) {
super(props)
}
static create(username: string): Result<Username> {
if (Validator.isNotEmpty(username).isFailed()) {
return Result.fail<Username>('Username cannot be empty')
}
return Result.ok<Username>(new Username({ value: username }))
}
}

View File

@@ -0,0 +1,3 @@
export interface UsernameProps {
value: string
}

View File

@@ -2,14 +2,14 @@ import { Uuid } from './Uuid'
describe('Uuid', () => {
it('should create a value object', () => {
const valueOrError = Uuid.create('1-2-3')
const valueOrError = Uuid.create('84c0f8e8-544a-4c7e-9adf-26209303bc1d')
expect(valueOrError.isFailed()).toBeFalsy()
expect(valueOrError.getValue().value).toEqual('1-2-3')
expect(valueOrError.getValue().value).toEqual('84c0f8e8-544a-4c7e-9adf-26209303bc1d')
})
it('should not create an invalid value object', () => {
const valueOrError = Uuid.create('')
const valueOrError = Uuid.create('1-2-3')
expect(valueOrError.isFailed()).toBeTruthy()
})

View File

@@ -1,6 +1,7 @@
import { ValueObject } from '../Core/ValueObject'
import { Result } from '../Core/Result'
import { UuidProps } from './UuidProps'
import { Validator } from '../Core/Validator'
export class Uuid extends ValueObject<UuidProps> {
get value(): string {
@@ -12,8 +13,9 @@ export class Uuid extends ValueObject<UuidProps> {
}
static create(uuid: string): Result<Uuid> {
if (!!uuid === false || uuid.length === 0) {
return Result.fail<Uuid>('Uuid cannot be empty')
const validUuidOrError = Validator.isValidUuid(uuid)
if (validUuidOrError.isFailed()) {
return Result.fail<Uuid>(validUuidOrError.getError())
} else {
return Result.ok<Uuid>(new Uuid({ value: uuid }))
}

View File

@@ -0,0 +1,81 @@
import { Validator } from './Validator'
describe('Validator', () => {
const validUuids = [
'2221101c-1da9-4d2b-9b32-b8be2a8d1c82',
'c08f2f29-a74b-42b4-aefd-98af9832391c',
'b453fa64-1493-443b-b5bb-bca7b9c696c7',
]
const invalidUuids = [
123,
'someone@127.0.0.1',
'',
null,
'b453fa64-1493-443b-b5bb-ca7b9c696c7',
'c08f*f29-a74b-42b4-aefd-98af9832391c',
'c08f*f29-a74b-42b4-aefd-98af9832391c',
'../../escaped.sh',
]
const validEmails = [
'something@something.com',
'someone@localhost.localdomain',
'a/b@domain.com',
'{}@domain.com',
'karol+test@standardnotes.com',
"m*'!%@something.sa",
'tu!!7n7.ad##0!!!@company.ca',
'%@com.com',
"!#$%&'*+/=?^_`{|}~.-@com.com",
'someone@do-ma-in.com',
'""testlah""@example.com',
]
const invalidEmails = [
'someone@127.0.0.1',
'a@b.b',
'',
null,
'.wooly@example.com',
'wo..oly@example.com',
'somebody@example',
'a @p.com',
]
it('should validate proper uuids', () => {
for (const validUuid of validUuids) {
expect(Validator.isValidUuid(validUuid).isFailed()).toBeFalsy()
}
})
it('should not validate invalid uuids', () => {
for (const invalidUuid of invalidUuids) {
expect(Validator.isValidUuid(invalidUuid as string).isFailed()).toBeTruthy()
}
})
it('should validate proper emails', () => {
for (const validEmail of validEmails) {
expect(Validator.isValidEmail(validEmail).isFailed()).toBeFalsy()
}
})
it('should not validate invalid emails', () => {
for (const invalidEmail of invalidEmails) {
expect(Validator.isValidEmail(invalidEmail as string).isFailed()).toBeTruthy()
}
})
it('should validate value if not empty', () => {
for (const value of [1, 'foobar', {}, 0]) {
expect(Validator.isNotEmpty(value).isFailed()).toBeFalsy()
}
})
it('should not validate value if empty', () => {
for (const value of [null, undefined, '', []]) {
expect(Validator.isNotEmpty(value).isFailed()).toBeTruthy()
}
})
})

View File

@@ -0,0 +1,37 @@
import { Result } from './Result'
export class Validator {
private static readonly UUID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-5][0-9a-f]{3}-[089ab][0-9a-f]{3}-[0-9a-f]{12}$/i
private static readonly EMAIL_REGEX =
/^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
static isValidUuid(value: string): Result<string> {
const matchesUuidRegex = String(value).toLowerCase().match(Validator.UUID_REGEX) !== null
if (matchesUuidRegex) {
return Result.ok()
}
return Result.fail(`Given value is not a valid uuid: ${value}`)
}
static isValidEmail(value: string): Result<string> {
const matchesUuidRegex = String(value).toLowerCase().match(Validator.EMAIL_REGEX) !== null
if (matchesUuidRegex) {
return Result.ok()
}
return Result.fail(`Given value is not a valid email address: ${value}`)
}
static isNotEmpty(value: unknown): Result<string> {
if (value instanceof Array && value.length === 0) {
return Result.fail(`Given value is empty: ${value}`)
}
if (value === null || value === undefined || value === '') {
return Result.fail(`Given value is empty: ${value}`)
}
return Result.ok()
}
}

View File

@@ -1,4 +0,0 @@
export interface MapInterface<T, U> {
toDomain(persistence: U): T
toProjection(domain: T): U
}

View File

@@ -0,0 +1,4 @@
export interface MapperInterface<T, U> {
toDomain(projection: U): T
toProjection(domain: T): U
}

View File

@@ -0,0 +1,18 @@
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', () => {
for (const value of ['', undefined, null, 0, 'SOME_PLAN']) {
const valueOrError = SubscriptionPlanName.create(value as string)
expect(valueOrError.isFailed()).toBeTruthy()
}
})
})

View File

@@ -0,0 +1,27 @@
import { ValueObject } from '../Core/ValueObject'
import { Result } from '../Core/Result'
import { SubscriptionPlanNameProps } from './SubscriptionPlanNameProps'
export class SubscriptionPlanName extends ValueObject<SubscriptionPlanNameProps> {
static readonly NAMES = {
PlusPlan: 'PLUS_PLAN',
ProPlan: 'PRO_PLAN',
}
get value(): string {
return this.props.value
}
private constructor(props: SubscriptionPlanNameProps) {
super(props)
}
static create(name: string): Result<SubscriptionPlanName> {
const isValidName = Object.values(this.NAMES).includes(name)
if (!isValidName) {
return Result.fail<SubscriptionPlanName>(`Invalid subscription plan name: ${name}`)
} else {
return Result.ok<SubscriptionPlanName>(new SubscriptionPlanName({ value: name }))
}
}
}

View File

@@ -0,0 +1,3 @@
export interface SubscriptionPlanNameProps {
value: string
}

View File

@@ -0,0 +1,5 @@
import { Result } from '../Core/Result'
export interface UseCaseInterface<T> {
execute(...args: any[]): Promise<Result<T>>
}

View File

@@ -1,5 +1,13 @@
export * from './Common/Dates'
export * from './Common/DatesProps'
export * from './Common/Email'
export * from './Common/EmailProps'
export * from './Common/RoleName'
export * from './Common/RoleNameProps'
export * from './Common/RoleNameCollection'
export * from './Common/RoleNameCollectionProps'
export * from './Common/Username'
export * from './Common/UsernameProps'
export * from './Common/Uuid'
export * from './Common/UuidProps'
@@ -8,7 +16,13 @@ export * from './Core/Entity'
export * from './Core/Id'
export * from './Core/Result'
export * from './Core/UniqueEntityId'
export * from './Core/Validator'
export * from './Core/ValueObject'
export * from './Core/ValueObjectProps'
export * from './Map/MapInterface'
export * from './Mapping/MapperInterface'
export * from './Subscription/SubscriptionPlanName'
export * from './Subscription/SubscriptionPlanNameProps'
export * from './UseCase/UseCaseInterface'

View File

@@ -3,6 +3,42 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.9.36](https://github.com/standardnotes/server/compare/@standardnotes/domain-events-infra@1.9.35...@standardnotes/domain-events-infra@1.9.36) (2022-11-30)
**Note:** Version bump only for package @standardnotes/domain-events-infra
## [1.9.35](https://github.com/standardnotes/server/compare/@standardnotes/domain-events-infra@1.9.34...@standardnotes/domain-events-infra@1.9.35) (2022-11-28)
**Note:** Version bump only for package @standardnotes/domain-events-infra
## [1.9.34](https://github.com/standardnotes/server/compare/@standardnotes/domain-events-infra@1.9.33...@standardnotes/domain-events-infra@1.9.34) (2022-11-25)
**Note:** Version bump only for package @standardnotes/domain-events-infra
## [1.9.33](https://github.com/standardnotes/server/compare/@standardnotes/domain-events-infra@1.9.32...@standardnotes/domain-events-infra@1.9.33) (2022-11-24)
**Note:** Version bump only for package @standardnotes/domain-events-infra
## [1.9.32](https://github.com/standardnotes/server/compare/@standardnotes/domain-events-infra@1.9.31...@standardnotes/domain-events-infra@1.9.32) (2022-11-23)
**Note:** Version bump only for package @standardnotes/domain-events-infra
## [1.9.31](https://github.com/standardnotes/server/compare/@standardnotes/domain-events-infra@1.9.30...@standardnotes/domain-events-infra@1.9.31) (2022-11-22)
**Note:** Version bump only for package @standardnotes/domain-events-infra
## [1.9.30](https://github.com/standardnotes/server/compare/@standardnotes/domain-events-infra@1.9.29...@standardnotes/domain-events-infra@1.9.30) (2022-11-21)
**Note:** Version bump only for package @standardnotes/domain-events-infra
## [1.9.29](https://github.com/standardnotes/server/compare/@standardnotes/domain-events-infra@1.9.28...@standardnotes/domain-events-infra@1.9.29) (2022-11-18)
**Note:** Version bump only for package @standardnotes/domain-events-infra
## [1.9.28](https://github.com/standardnotes/server/compare/@standardnotes/domain-events-infra@1.9.27...@standardnotes/domain-events-infra@1.9.28) (2022-11-16)
**Note:** Version bump only for package @standardnotes/domain-events-infra
## [1.9.27](https://github.com/standardnotes/server/compare/@standardnotes/domain-events-infra@1.9.26...@standardnotes/domain-events-infra@1.9.27) (2022-11-14)
**Note:** Version bump only for package @standardnotes/domain-events-infra

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/domain-events-infra",
"version": "1.9.27",
"version": "1.9.36",
"engines": {
"node": ">=18.0.0 <19.0.0"
},
@@ -23,9 +23,8 @@
"test": "jest spec --coverage"
},
"dependencies": {
"@newrelic/native-metrics": "^9.0.0",
"@standardnotes/domain-events": "workspace:*",
"aws-sdk": "^2.1253.0",
"aws-sdk": "^2.1260.0",
"ioredis": "^5.2.4",
"newrelic": "^9.6.0",
"reflect-metadata": "^0.1.13",

View File

@@ -3,6 +3,44 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
# [2.92.0](https://github.com/standardnotes/server/compare/@standardnotes/domain-events@2.91.0...@standardnotes/domain-events@2.92.0) (2022-11-30)
### Features
* **revisions:** add updating user uuid on revisions in async processing ([0f67aa4](https://github.com/standardnotes/server/commit/0f67aa4058301dfa92794b90a842966173f71b95))
# [2.91.0](https://github.com/standardnotes/server/compare/@standardnotes/domain-events@2.90.2...@standardnotes/domain-events@2.91.0) (2022-11-28)
### Features
* **revisions:** add copying revisions on duplicated items ([7bb698e](https://github.com/standardnotes/server/commit/7bb698e44222ef128d9642d625e96b7d26ee4dbf))
## [2.90.2](https://github.com/standardnotes/server/compare/@standardnotes/domain-events@2.90.1...@standardnotes/domain-events@2.90.2) (2022-11-25)
**Note:** Version bump only for package @standardnotes/domain-events
## [2.90.1](https://github.com/standardnotes/server/compare/@standardnotes/domain-events@2.90.0...@standardnotes/domain-events@2.90.1) (2022-11-22)
**Note:** Version bump only for package @standardnotes/domain-events
# [2.90.0](https://github.com/standardnotes/server/compare/@standardnotes/domain-events@2.89.0...@standardnotes/domain-events@2.90.0) (2022-11-21)
### Features
* **syncing-server:** add creating item dumps for revision service ([8d152dd](https://github.com/standardnotes/server/commit/8d152ddfcb3c88cbbf9df04e3ed6e2c02571d821))
# [2.89.0](https://github.com/standardnotes/server/compare/@standardnotes/domain-events@2.88.0...@standardnotes/domain-events@2.89.0) (2022-11-18)
### Features
* add item revision creation requested event ([5c9dff3](https://github.com/standardnotes/server/commit/5c9dff38c9006d39150ea95b2ca17c4ab7175ec2))
# [2.88.0](https://github.com/standardnotes/server/compare/@standardnotes/domain-events@2.87.0...@standardnotes/domain-events@2.88.0) (2022-11-16)
### Features
* **analytics:** add publishing churn calculation values in the report ([6c43a33](https://github.com/standardnotes/server/commit/6c43a331d09c2dcf1300742509da6a1d8ef2f5b7))
# [2.87.0](https://github.com/standardnotes/server/compare/@standardnotes/domain-events@2.86.3...@standardnotes/domain-events@2.87.0) (2022-11-14)
### Features

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/domain-events",
"version": "2.87.0",
"version": "2.92.0",
"engines": {
"node": ">=18.0.0 <19.0.0"
},

View File

@@ -32,6 +32,9 @@ export interface DailyAnalyticsReportGeneratedEventPayload {
periodKeys: Array<string>
values: Array<{
rate: number
averageCustomersCount: number
existingCustomersChurn: number
newCustomersChurn: number
periodKey: string
}>
}

View File

@@ -0,0 +1,7 @@
import { DomainEventInterface } from './DomainEventInterface'
import { ItemDumpedEventPayload } from './ItemDumpedEventPayload'
export interface ItemDumpedEvent extends DomainEventInterface {
type: 'ITEM_DUMPED'
payload: ItemDumpedEventPayload
}

View File

@@ -0,0 +1,3 @@
export interface ItemDumpedEventPayload {
fileDumpPath: string
}

View File

@@ -0,0 +1,7 @@
import { DomainEventInterface } from './DomainEventInterface'
import { ItemRevisionCreationRequestedEventPayload } from './ItemRevisionCreationRequestedEventPayload'
export interface ItemRevisionCreationRequestedEvent extends DomainEventInterface {
type: 'ITEM_REVISION_CREATION_REQUESTED'
payload: ItemRevisionCreationRequestedEventPayload
}

View File

@@ -0,0 +1,3 @@
export interface ItemRevisionCreationRequestedEventPayload {
itemUuid: string
}

View File

@@ -0,0 +1,7 @@
import { DomainEventInterface } from './DomainEventInterface'
import { RevisionsCopyRequestedEventPayload } from './RevisionsCopyRequestedEventPayload'
export interface RevisionsCopyRequestedEvent extends DomainEventInterface {
type: 'REVISIONS_COPY_REQUESTED'
payload: RevisionsCopyRequestedEventPayload
}

View File

@@ -0,0 +1,4 @@
export interface RevisionsCopyRequestedEventPayload {
newItemUuid: string
originalItemUuid: string
}

View File

@@ -0,0 +1,7 @@
import { DomainEventInterface } from './DomainEventInterface'
import { RevisionsOwnershipUpdateRequestedEventPayload } from './RevisionsOwnershipUpdateRequestedEventPayload'
export interface RevisionsOwnershipUpdateRequestedEvent extends DomainEventInterface {
type: 'REVISIONS_OWNERSHIP_UPDATE_REQUESTED'
payload: RevisionsOwnershipUpdateRequestedEventPayload
}

View File

@@ -0,0 +1,4 @@
export interface RevisionsOwnershipUpdateRequestedEventPayload {
itemUuid: string
userUuid: string
}

View File

@@ -46,6 +46,10 @@ export * from './Event/GoogleDriveBackupFailedEvent'
export * from './Event/GoogleDriveBackupFailedEventPayload'
export * from './Event/InvoiceGeneratedEvent'
export * from './Event/InvoiceGeneratedEventPayload'
export * from './Event/ItemDumpedEvent'
export * from './Event/ItemDumpedEventPayload'
export * from './Event/ItemRevisionCreationRequestedEvent'
export * from './Event/ItemRevisionCreationRequestedEventPayload'
export * from './Event/ItemsSyncedEvent'
export * from './Event/ItemsSyncedEventPayload'
export * from './Event/ListedAccountCreatedEvent'
@@ -70,6 +74,10 @@ export * from './Event/RefundRequestedEvent'
export * from './Event/RefundRequestedEventPayload'
export * from './Event/RefundProcessedEvent'
export * from './Event/RefundProcessedEventPayload'
export * from './Event/RevisionsCopyRequestedEvent'
export * from './Event/RevisionsCopyRequestedEventPayload'
export * from './Event/RevisionsOwnershipUpdateRequestedEvent'
export * from './Event/RevisionsOwnershipUpdateRequestedEventPayload'
export * from './Event/SharedSubscriptionInvitationCanceledEvent'
export * from './Event/SharedSubscriptionInvitationCanceledEventPayload'
export * from './Event/SharedSubscriptionInvitationCreatedEvent'

View File

@@ -3,6 +3,48 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.6.32](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.6.31...@standardnotes/event-store@1.6.32) (2022-11-30)
**Note:** Version bump only for package @standardnotes/event-store
## [1.6.31](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.6.30...@standardnotes/event-store@1.6.31) (2022-11-28)
**Note:** Version bump only for package @standardnotes/event-store
## [1.6.30](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.6.29...@standardnotes/event-store@1.6.30) (2022-11-25)
**Note:** Version bump only for package @standardnotes/event-store
## [1.6.29](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.6.28...@standardnotes/event-store@1.6.29) (2022-11-24)
**Note:** Version bump only for package @standardnotes/event-store
## [1.6.28](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.6.27...@standardnotes/event-store@1.6.28) (2022-11-23)
**Note:** Version bump only for package @standardnotes/event-store
## [1.6.27](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.6.26...@standardnotes/event-store@1.6.27) (2022-11-23)
### Bug Fixes
* binding of sns and sqs with additional config ([74bc791](https://github.com/standardnotes/server/commit/74bc79116bc50d9a5af1a558db1b7108dcda6d0e))
## [1.6.26](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.6.25...@standardnotes/event-store@1.6.26) (2022-11-22)
**Note:** Version bump only for package @standardnotes/event-store
## [1.6.25](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.6.24...@standardnotes/event-store@1.6.25) (2022-11-21)
**Note:** Version bump only for package @standardnotes/event-store
## [1.6.24](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.6.23...@standardnotes/event-store@1.6.24) (2022-11-18)
**Note:** Version bump only for package @standardnotes/event-store
## [1.6.23](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.6.22...@standardnotes/event-store@1.6.23) (2022-11-16)
**Note:** Version bump only for package @standardnotes/event-store
## [1.6.22](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.6.21...@standardnotes/event-store@1.6.22) (2022-11-14)
**Note:** Version bump only for package @standardnotes/event-store

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/event-store",
"version": "1.6.22",
"version": "1.6.32",
"description": "Event Store Service",
"private": true,
"main": "dist/src/index.js",
@@ -31,11 +31,10 @@
"typescript": "^4.8.4"
},
"dependencies": {
"@newrelic/native-metrics": "^9.0.0",
"@standardnotes/domain-events": "workspace:*",
"@standardnotes/domain-events-infra": "workspace:*",
"@standardnotes/time": "workspace:*",
"aws-sdk": "^2.1253.0",
"aws-sdk": "^2.1260.0",
"dotenv": "^16.0.1",
"inversify": "^6.0.1",
"ioredis": "^5.2.4",

View File

@@ -28,12 +28,19 @@ export class ContainerConfigLoader {
await AppDataSource.initialize()
container.bind<AWS.SQS>(TYPES.SQS).toConstantValue(
new AWS.SQS({
if (env.get('SQS_QUEUE_URL', true)) {
const sqsConfig: AWS.SQS.Types.ClientConfiguration = {
apiVersion: 'latest',
region: env.get('SQS_AWS_REGION'),
}),
)
region: env.get('SQS_AWS_REGION', true),
}
if (env.get('SQS_ACCESS_KEY_ID', true) && env.get('SQS_SECRET_ACCESS_KEY', true)) {
sqsConfig.credentials = {
accessKeyId: env.get('SQS_ACCESS_KEY_ID', true),
secretAccessKey: env.get('SQS_SECRET_ACCESS_KEY', true),
}
}
container.bind<AWS.SQS>(TYPES.SQS).toConstantValue(new AWS.SQS(sqsConfig))
}
const logger = winston.createLogger({
level: env.get('LOG_LEVEL') || 'info',

View File

@@ -3,6 +3,48 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.8.32](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.8.31...@standardnotes/files-server@1.8.32) (2022-11-30)
**Note:** Version bump only for package @standardnotes/files-server
## [1.8.31](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.8.30...@standardnotes/files-server@1.8.31) (2022-11-28)
**Note:** Version bump only for package @standardnotes/files-server
## [1.8.30](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.8.29...@standardnotes/files-server@1.8.30) (2022-11-25)
**Note:** Version bump only for package @standardnotes/files-server
## [1.8.29](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.8.28...@standardnotes/files-server@1.8.29) (2022-11-24)
**Note:** Version bump only for package @standardnotes/files-server
## [1.8.28](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.8.27...@standardnotes/files-server@1.8.28) (2022-11-23)
**Note:** Version bump only for package @standardnotes/files-server
## [1.8.27](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.8.26...@standardnotes/files-server@1.8.27) (2022-11-23)
### Bug Fixes
* binding of sns and sqs with additional config ([74bc791](https://github.com/standardnotes/files/commit/74bc79116bc50d9a5af1a558db1b7108dcda6d0e))
## [1.8.26](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.8.25...@standardnotes/files-server@1.8.26) (2022-11-22)
**Note:** Version bump only for package @standardnotes/files-server
## [1.8.25](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.8.24...@standardnotes/files-server@1.8.25) (2022-11-21)
**Note:** Version bump only for package @standardnotes/files-server
## [1.8.24](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.8.23...@standardnotes/files-server@1.8.24) (2022-11-18)
**Note:** Version bump only for package @standardnotes/files-server
## [1.8.23](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.8.22...@standardnotes/files-server@1.8.23) (2022-11-16)
**Note:** Version bump only for package @standardnotes/files-server
## [1.8.22](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.8.21...@standardnotes/files-server@1.8.22) (2022-11-14)
**Note:** Version bump only for package @standardnotes/files-server

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/files-server",
"version": "1.8.22",
"version": "1.8.32",
"engines": {
"node": ">=18.0.0 <19.0.0"
},
@@ -25,7 +25,6 @@
"upgrade:snjs": "yarn ncu -u '@standardnotes/*'"
},
"dependencies": {
"@newrelic/native-metrics": "^9.0.0",
"@sentry/node": "^7.19.0",
"@standardnotes/common": "workspace:*",
"@standardnotes/domain-events": "workspace:*",
@@ -34,7 +33,7 @@
"@standardnotes/sncrypto-common": "^1.9.0",
"@standardnotes/sncrypto-node": "workspace:*",
"@standardnotes/time": "workspace:*",
"aws-sdk": "^2.1253.0",
"aws-sdk": "^2.1260.0",
"connect-busboy": "^1.0.0",
"cors": "^2.8.5",
"dayjs": "^1.11.6",

View File

@@ -110,13 +110,24 @@ export class ContainerConfigLoader {
}
container.bind<ValidatorInterface<Uuid>>(TYPES.UuidValidator).toConstantValue(new UuidValidator())
if (env.get('SNS_AWS_REGION', true)) {
container.bind<AWS.SNS>(TYPES.SNS).toConstantValue(
new AWS.SNS({
apiVersion: 'latest',
region: env.get('SNS_AWS_REGION', true),
}),
)
if (env.get('SNS_TOPIC_ARN', true)) {
const snsConfig: AWS.SNS.Types.ClientConfiguration = {
apiVersion: 'latest',
region: env.get('SNS_AWS_REGION', true),
}
if (env.get('SNS_ENDPOINT', true)) {
snsConfig.endpoint = env.get('SNS_ENDPOINT', true)
}
if (env.get('SNS_DISABLE_SSL', true) === 'true') {
snsConfig.sslEnabled = false
}
if (env.get('SNS_ACCESS_KEY_ID', true) && env.get('SNS_SECRET_ACCESS_KEY', true)) {
snsConfig.credentials = {
accessKeyId: env.get('SNS_ACCESS_KEY_ID', true),
secretAccessKey: env.get('SNS_SECRET_ACCESS_KEY', true),
}
}
container.bind<AWS.SNS>(TYPES.SNS).toConstantValue(new AWS.SNS(snsConfig))
}
if (env.get('SQS_QUEUE_URL', true)) {

View File

@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.6.2](https://github.com/standardnotes/server/compare/@standardnotes/predicates@1.6.1...@standardnotes/predicates@1.6.2) (2022-11-25)
**Note:** Version bump only for package @standardnotes/predicates
## [1.6.1](https://github.com/standardnotes/server/compare/@standardnotes/predicates@1.6.0...@standardnotes/predicates@1.6.1) (2022-11-22)
**Note:** Version bump only for package @standardnotes/predicates
# [1.6.0](https://github.com/standardnotes/server/compare/@standardnotes/predicates@1.5.7...@standardnotes/predicates@1.6.0) (2022-11-14)
### Features

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/predicates",
"version": "1.6.0",
"version": "1.6.2",
"engines": {
"node": ">=18.0.0 <19.0.0"
},

View File

@@ -0,0 +1,34 @@
LOG_LEVEL=info
NODE_ENV=development
VERSION=development
AUTH_JWT_SECRET=auth_jwt_secret
PORT=3000
DB_HOST=127.0.0.1
DB_REPLICA_HOST=127.0.0.1
DB_PORT=3306
DB_USERNAME=revisions
DB_PASSWORD=revisionspassword
DB_DATABASE=revisions
DB_DEBUG_LEVEL=all # "all" | "query" | "schema" | "error" | "warn" | "info" | "log" | "migration"
DB_MIGRATIONS_PATH=dist/migrations/*.js
REDIS_URL=redis://cache
SQS_QUEUE_URL=
SQS_AWS_REGION=
S3_AWS_REGION=
S3_BACKUP_BUCKET_NAME=
REDIS_EVENTS_CHANNEL=revisions
# (Optional) New Relic Setup
NEW_RELIC_ENABLED=false
NEW_RELIC_APP_NAME="Revisions Server"
NEW_RELIC_LICENSE_KEY=
NEW_RELIC_NO_CONFIG_FILE=true
NEW_RELIC_DISTRIBUTED_TRACING_ENABLED=false
NEW_RELIC_LOG_ENABLED=false
NEW_RELIC_LOG_LEVEL=info

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