mirror of
https://github.com/standardnotes/server
synced 2026-01-17 14:04:28 -05:00
Compare commits
60 Commits
@standardn
...
@standardn
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ff091918aa | ||
|
|
91b76edce1 | ||
|
|
5ae5c83bf5 | ||
|
|
9d90f276de | ||
|
|
245f091e22 | ||
|
|
ae2f8f086b | ||
|
|
5e5eb7f937 | ||
|
|
748630e1f1 | ||
|
|
43064c8c55 | ||
|
|
4559a3047c | ||
|
|
de8064ee5c | ||
|
|
48c8dba342 | ||
|
|
31a515b2f1 | ||
|
|
294f56e189 | ||
|
|
70596a0aac | ||
|
|
74bc79116b | ||
|
|
e6bd50ae77 | ||
|
|
308662550f | ||
|
|
d94a7e7157 | ||
|
|
630b264754 | ||
|
|
5f2be44b85 | ||
|
|
f68ece68af | ||
|
|
70c829a2c9 | ||
|
|
e3b6ac4874 | ||
|
|
a762d5a22c | ||
|
|
3686a26019 | ||
|
|
80daec748d | ||
|
|
94359f1299 | ||
|
|
59dda1bb99 | ||
|
|
806a732cbc | ||
|
|
7816be7ba7 | ||
|
|
5f3bd5137f | ||
|
|
6c9fc5fb86 | ||
|
|
f7e0b68643 | ||
|
|
b283bbaca9 | ||
|
|
92ba759b1c | ||
|
|
0acc9d8d68 | ||
|
|
daa7a9ff61 | ||
|
|
455f35e0c1 | ||
|
|
1fa655b56e | ||
|
|
e553222b4b | ||
|
|
f1b6f48926 | ||
|
|
14ab1cae69 | ||
|
|
5f9cf90b16 | ||
|
|
97b367d4ee | ||
|
|
47119fb346 | ||
|
|
d77eb7f5f1 | ||
|
|
1b0a2bb34c | ||
|
|
a363039fa1 | ||
|
|
32c740b58e | ||
|
|
822ee890af | ||
|
|
b0406dd8aa | ||
|
|
8d152ddfcb | ||
|
|
1a16d2e4f4 | ||
|
|
1ca8531305 | ||
|
|
6190e7d092 | ||
|
|
a6542dd638 | ||
|
|
840777a851 | ||
|
|
5c9dff38c9 | ||
|
|
abfbacb8c2 |
4
.github/workflows/revisions.yml
vendored
4
.github/workflows/revisions.yml
vendored
@@ -1,7 +1,7 @@
|
||||
name: Revisions
|
||||
name: Revisions Server
|
||||
|
||||
concurrency:
|
||||
group: revisions
|
||||
group: revisions_server
|
||||
cancel-in-progress: true
|
||||
|
||||
on:
|
||||
|
||||
44
.pnp.cjs
generated
44
.pnp.cjs
generated
@@ -126,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"],\
|
||||
@@ -2538,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"],\
|
||||
@@ -2551,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"],\
|
||||
@@ -2591,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"],\
|
||||
@@ -2607,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"],\
|
||||
@@ -2648,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"],\
|
||||
@@ -2674,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"],\
|
||||
@@ -2783,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"],\
|
||||
@@ -2823,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"],\
|
||||
@@ -2832,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"],\
|
||||
@@ -2879,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"],\
|
||||
@@ -2899,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"],\
|
||||
@@ -3014,7 +3007,6 @@ const RAW_RUNTIME_STATE =
|
||||
"packageLocation": "./packages/revisions/",\
|
||||
"packageDependencies": [\
|
||||
["@standardnotes/revisions-server", "workspace:packages/revisions"],\
|
||||
["@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"],\
|
||||
@@ -3032,7 +3024,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"],\
|
||||
@@ -3060,7 +3052,6 @@ const RAW_RUNTIME_STATE =
|
||||
"packageLocation": "./packages/scheduler/",\
|
||||
"packageDependencies": [\
|
||||
["@standardnotes/scheduler-server", "workspace:packages/scheduler"],\
|
||||
["@newrelic/native-metrics", "npm:9.0.0"],\
|
||||
["@newrelic/winston-enricher", "virtual:c66bf20e88479ada0172094776519a9f51acc4731d22079b60a295bcec7ea42d5545cbce58a77a50d932bf953298799135e99707486e343da6d99ba1d167bdbd#npm:4.0.0"],\
|
||||
["@sentry/node", "npm:7.19.0"],\
|
||||
["@standardnotes/common", "workspace:packages/common"],\
|
||||
@@ -3073,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"],\
|
||||
@@ -3122,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"],\
|
||||
@@ -3145,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"],\
|
||||
@@ -3189,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"],\
|
||||
@@ -3213,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"],\
|
||||
@@ -3290,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"],\
|
||||
@@ -3304,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"],\
|
||||
@@ -3331,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"],\
|
||||
@@ -3347,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"],\
|
||||
@@ -4814,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"],\
|
||||
@@ -12584,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": [\
|
||||
|
||||
Binary file not shown.
@@ -61,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"
|
||||
}
|
||||
|
||||
@@ -3,6 +3,52 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [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
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/analytics",
|
||||
"version": "2.11.2",
|
||||
"version": "2.11.13",
|
||||
"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",
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -3,6 +3,36 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.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
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/api-gateway",
|
||||
"version": "1.38.6",
|
||||
"version": "1.39.3",
|
||||
"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",
|
||||
|
||||
@@ -54,6 +54,7 @@ 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'))
|
||||
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'))
|
||||
|
||||
@@ -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'),
|
||||
|
||||
@@ -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`)
|
||||
}
|
||||
}
|
||||
@@ -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,15 @@ 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> {
|
||||
await this.callServer(this.revisionsServerUrl, request, response, endpoint, payload)
|
||||
}
|
||||
|
||||
async callLegacySyncingServer(
|
||||
request: Request,
|
||||
response: Response,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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.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,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/auth-server",
|
||||
"version": "1.60.1",
|
||||
"version": "1.60.11",
|
||||
"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",
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/common",
|
||||
"version": "1.45.0",
|
||||
"version": "1.46.1",
|
||||
"engines": {
|
||||
"node": ">=18.0.0 <19.0.0"
|
||||
},
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -3,6 +3,38 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.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
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/domain-core",
|
||||
"version": "1.2.0",
|
||||
"version": "1.5.1",
|
||||
"engines": {
|
||||
"node": ">=18.0.0 <19.0.0"
|
||||
},
|
||||
|
||||
36
packages/domain-core/src/Domain/Common/RoleName.spec.ts
Normal file
36
packages/domain-core/src/Domain/Common/RoleName.spec.ts
Normal file
@@ -0,0 +1,36 @@
|
||||
import { RoleName } from './RoleName'
|
||||
|
||||
describe('RoleName', () => {
|
||||
it('should create a value object', () => {
|
||||
const valueOrError = RoleName.create('PRO_USER')
|
||||
|
||||
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('PRO_USER').getValue()
|
||||
const plusUserRole = RoleName.create('PLUS_USER').getValue()
|
||||
const coreUser = RoleName.create('CORE_USER').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()
|
||||
})
|
||||
})
|
||||
42
packages/domain-core/src/Domain/Common/RoleName.ts
Normal file
42
packages/domain-core/src/Domain/Common/RoleName.ts
Normal 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> {
|
||||
private 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 }))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
import { RoleName } from './RoleName'
|
||||
import { RoleNameCollection } from './RoleNameCollection'
|
||||
|
||||
describe('RoleNameCollection', () => {
|
||||
it('should create a value object', () => {
|
||||
const role1 = RoleName.create('PRO_USER').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('PRO_USER').getValue(), RoleName.create('PLUS_USER').getValue()]
|
||||
|
||||
const roles2 = RoleNameCollection.create([
|
||||
RoleName.create('PRO_USER').getValue(),
|
||||
RoleName.create('CORE_USER').getValue(),
|
||||
]).getValue()
|
||||
|
||||
const valueOrError = RoleNameCollection.create(roles1)
|
||||
expect(valueOrError.getValue().equals(roles2)).toBeFalsy()
|
||||
})
|
||||
|
||||
it('should tell if collections are equal', () => {
|
||||
const roles1 = [RoleName.create('PRO_USER').getValue(), RoleName.create('PLUS_USER').getValue()]
|
||||
|
||||
const roles2 = RoleNameCollection.create([
|
||||
RoleName.create('PRO_USER').getValue(),
|
||||
RoleName.create('PLUS_USER').getValue(),
|
||||
]).getValue()
|
||||
|
||||
const valueOrError = RoleNameCollection.create(roles1)
|
||||
expect(valueOrError.getValue().equals(roles2)).toBeTruthy()
|
||||
})
|
||||
|
||||
it('should tell if collection includes element', () => {
|
||||
const roles1 = [RoleName.create('PRO_USER').getValue(), RoleName.create('PLUS_USER').getValue()]
|
||||
|
||||
const valueOrError = RoleNameCollection.create(roles1)
|
||||
expect(valueOrError.getValue().includes(RoleName.create('PRO_USER').getValue())).toBeTruthy()
|
||||
})
|
||||
|
||||
it('should tell if collection does not includes element', () => {
|
||||
const roles1 = [RoleName.create('PRO_USER').getValue(), RoleName.create('PLUS_USER').getValue()]
|
||||
|
||||
const valueOrError = RoleNameCollection.create(roles1)
|
||||
expect(valueOrError.getValue().includes(RoleName.create('CORE_USER').getValue())).toBeFalsy()
|
||||
})
|
||||
|
||||
it('should tell if collection has a role with more or equal power to', () => {
|
||||
let roles = [RoleName.create('CORE_USER').getValue()]
|
||||
let valueOrError = RoleNameCollection.create(roles)
|
||||
let roleNames = valueOrError.getValue()
|
||||
|
||||
expect(roleNames.hasARoleNameWithMoreOrEqualPowerTo(RoleName.create('PLUS_USER').getValue())).toBeFalsy()
|
||||
expect(roleNames.hasARoleNameWithMoreOrEqualPowerTo(RoleName.create('PRO_USER').getValue())).toBeFalsy()
|
||||
expect(roleNames.hasARoleNameWithMoreOrEqualPowerTo(RoleName.create('CORE_USER').getValue())).toBeTruthy()
|
||||
|
||||
roles = [RoleName.create('CORE_USER').getValue(), RoleName.create('PLUS_USER').getValue()]
|
||||
valueOrError = RoleNameCollection.create(roles)
|
||||
roleNames = valueOrError.getValue()
|
||||
|
||||
expect(roleNames.hasARoleNameWithMoreOrEqualPowerTo(RoleName.create('PLUS_USER').getValue())).toBeTruthy()
|
||||
expect(roleNames.hasARoleNameWithMoreOrEqualPowerTo(RoleName.create('PRO_USER').getValue())).toBeFalsy()
|
||||
expect(roleNames.hasARoleNameWithMoreOrEqualPowerTo(RoleName.create('CORE_USER').getValue())).toBeTruthy()
|
||||
|
||||
roles = [RoleName.create('PRO_USER').getValue(), RoleName.create('PLUS_USER').getValue()]
|
||||
valueOrError = RoleNameCollection.create(roles)
|
||||
roleNames = valueOrError.getValue()
|
||||
|
||||
expect(roleNames.hasARoleNameWithMoreOrEqualPowerTo(RoleName.create('PLUS_USER').getValue())).toBeTruthy()
|
||||
expect(roleNames.hasARoleNameWithMoreOrEqualPowerTo(RoleName.create('PRO_USER').getValue())).toBeTruthy()
|
||||
expect(roleNames.hasARoleNameWithMoreOrEqualPowerTo(RoleName.create('CORE_USER').getValue())).toBeTruthy()
|
||||
})
|
||||
})
|
||||
52
packages/domain-core/src/Domain/Common/RoleNameCollection.ts
Normal file
52
packages/domain-core/src/Domain/Common/RoleNameCollection.ts
Normal 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 }))
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
import { RoleName } from './RoleName'
|
||||
|
||||
export interface RoleNameCollectionProps {
|
||||
value: RoleName[]
|
||||
}
|
||||
3
packages/domain-core/src/Domain/Common/RoleNameProps.ts
Normal file
3
packages/domain-core/src/Domain/Common/RoleNameProps.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export interface RoleNameProps {
|
||||
value: string
|
||||
}
|
||||
@@ -1,5 +1,9 @@
|
||||
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/Timestamps'
|
||||
export * from './Common/TimestampsProps'
|
||||
export * from './Common/Uuid'
|
||||
@@ -16,11 +20,4 @@ export * from './Core/ValueObjectProps'
|
||||
|
||||
export * from './Mapping/MapperInterface'
|
||||
|
||||
export * from './Revision/ContentType'
|
||||
export * from './Revision/ContentTypeProps'
|
||||
export * from './Revision/Revision'
|
||||
export * from './Revision/RevisionMetadata'
|
||||
export * from './Revision/RevisionMetadataProps'
|
||||
export * from './Revision/RevisionProps'
|
||||
|
||||
export * from './UseCase/UseCaseInterface'
|
||||
|
||||
@@ -3,6 +3,30 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.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,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/domain-events-infra",
|
||||
"version": "1.9.28",
|
||||
"version": "1.9.34",
|
||||
"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",
|
||||
|
||||
@@ -3,6 +3,26 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [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
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/domain-events",
|
||||
"version": "2.88.0",
|
||||
"version": "2.90.2",
|
||||
"engines": {
|
||||
"node": ">=18.0.0 <19.0.0"
|
||||
},
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
import { DomainEventInterface } from './DomainEventInterface'
|
||||
import { ItemDumpedEventPayload } from './ItemDumpedEventPayload'
|
||||
|
||||
export interface ItemDumpedEvent extends DomainEventInterface {
|
||||
type: 'ITEM_DUMPED'
|
||||
payload: ItemDumpedEventPayload
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
export interface ItemDumpedEventPayload {
|
||||
fileDumpPath: string
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
import { DomainEventInterface } from './DomainEventInterface'
|
||||
import { ItemRevisionCreationRequestedEventPayload } from './ItemRevisionCreationRequestedEventPayload'
|
||||
|
||||
export interface ItemRevisionCreationRequestedEvent extends DomainEventInterface {
|
||||
type: 'ITEM_REVISION_CREATION_REQUESTED'
|
||||
payload: ItemRevisionCreationRequestedEventPayload
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
export interface ItemRevisionCreationRequestedEventPayload {
|
||||
itemUuid: string
|
||||
}
|
||||
@@ -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'
|
||||
|
||||
@@ -3,6 +3,36 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.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 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/event-store",
|
||||
"version": "1.6.23",
|
||||
"version": "1.6.30",
|
||||
"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",
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -3,6 +3,36 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.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,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/files-server",
|
||||
"version": "1.8.23",
|
||||
"version": "1.8.30",
|
||||
"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",
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/predicates",
|
||||
"version": "1.6.0",
|
||||
"version": "1.6.2",
|
||||
"engines": {
|
||||
"node": ">=18.0.0 <19.0.0"
|
||||
},
|
||||
|
||||
@@ -6,12 +6,12 @@ AUTH_JWT_SECRET=auth_jwt_secret
|
||||
|
||||
PORT=3000
|
||||
|
||||
DB_HOST=db
|
||||
DB_REPLICA_HOST=db
|
||||
DB_HOST=127.0.0.1
|
||||
DB_REPLICA_HOST=127.0.0.1
|
||||
DB_PORT=3306
|
||||
DB_USERNAME=std_notes_user
|
||||
DB_PASSWORD=changeme123
|
||||
DB_DATABASE=standard_notes_db
|
||||
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
|
||||
|
||||
|
||||
@@ -3,6 +3,84 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.4.8](https://github.com/standardnotes/server/compare/@standardnotes/revisions-server@1.4.7...@standardnotes/revisions-server@1.4.8) (2022-11-25)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/revisions-server
|
||||
|
||||
## [1.4.7](https://github.com/standardnotes/server/compare/@standardnotes/revisions-server@1.4.6...@standardnotes/revisions-server@1.4.7) (2022-11-24)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/revisions-server
|
||||
|
||||
## [1.4.6](https://github.com/standardnotes/server/compare/@standardnotes/revisions-server@1.4.5...@standardnotes/revisions-server@1.4.6) (2022-11-24)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/revisions-server
|
||||
|
||||
## [1.4.5](https://github.com/standardnotes/server/compare/@standardnotes/revisions-server@1.4.4...@standardnotes/revisions-server@1.4.5) (2022-11-24)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/revisions-server
|
||||
|
||||
## [1.4.4](https://github.com/standardnotes/server/compare/@standardnotes/revisions-server@1.4.3...@standardnotes/revisions-server@1.4.4) (2022-11-24)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/revisions-server
|
||||
|
||||
## [1.4.3](https://github.com/standardnotes/server/compare/@standardnotes/revisions-server@1.4.2...@standardnotes/revisions-server@1.4.3) (2022-11-23)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/revisions-server
|
||||
|
||||
## [1.4.2](https://github.com/standardnotes/server/compare/@standardnotes/revisions-server@1.4.1...@standardnotes/revisions-server@1.4.2) (2022-11-22)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* sqs binding ([806a732](https://github.com/standardnotes/server/commit/806a732cbc92cd89deb9d9d2aa95565922ce6b72))
|
||||
|
||||
## [1.4.1](https://github.com/standardnotes/server/compare/@standardnotes/revisions-server@1.4.0...@standardnotes/revisions-server@1.4.1) (2022-11-22)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **revisions:** add more verbose error messages ([daa7a9f](https://github.com/standardnotes/server/commit/daa7a9ff61d389e573960b443faff77e0abe01dc))
|
||||
|
||||
# [1.4.0](https://github.com/standardnotes/server/compare/@standardnotes/revisions-server@1.3.0...@standardnotes/revisions-server@1.4.0) (2022-11-22)
|
||||
|
||||
### Features
|
||||
|
||||
* **revisions:** add database ([e553222](https://github.com/standardnotes/server/commit/e553222b4b0f185bea5146d440834483b140339d))
|
||||
|
||||
# [1.3.0](https://github.com/standardnotes/server/compare/@standardnotes/revisions-server@1.2.2...@standardnotes/revisions-server@1.3.0) (2022-11-22)
|
||||
|
||||
### Features
|
||||
|
||||
* **revisions:** add filesystem dump repository ([14ab1ca](https://github.com/standardnotes/server/commit/14ab1cae6981b7c12e797dd316da1b3bdb37c75f))
|
||||
|
||||
## [1.2.2](https://github.com/standardnotes/server/compare/@standardnotes/revisions-server@1.2.1...@standardnotes/revisions-server@1.2.2) (2022-11-22)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/revisions-server
|
||||
|
||||
## [1.2.1](https://github.com/standardnotes/server/compare/@standardnotes/revisions-server@1.2.0...@standardnotes/revisions-server@1.2.1) (2022-11-21)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **revisions:** add missing worker process ([a363039](https://github.com/standardnotes/server/commit/a363039fa1f1c75842d1eaba2a476257eba385f7))
|
||||
|
||||
# [1.2.0](https://github.com/standardnotes/server/compare/@standardnotes/revisions-server@1.1.3...@standardnotes/revisions-server@1.2.0) (2022-11-21)
|
||||
|
||||
### Features
|
||||
|
||||
* **revisions:** add persisting revisions from s3 dump ([822ee89](https://github.com/standardnotes/server/commit/822ee890aff80cd099fc67b778ee02b8e9ef40eb))
|
||||
|
||||
## [1.1.3](https://github.com/standardnotes/server/compare/@standardnotes/revisions-server@1.1.2...@standardnotes/revisions-server@1.1.3) (2022-11-21)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/revisions-server
|
||||
|
||||
## [1.1.2](https://github.com/standardnotes/server/compare/@standardnotes/revisions-server@1.1.1...@standardnotes/revisions-server@1.1.2) (2022-11-21)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **domain-core:** remove revisions related models to revisions microservice ([a6542dd](https://github.com/standardnotes/server/commit/a6542dd63870a8ada5fd8143d8e2133a570d9329))
|
||||
|
||||
## [1.1.1](https://github.com/standardnotes/server/compare/@standardnotes/revisions-server@1.1.0...@standardnotes/revisions-server@1.1.1) (2022-11-18)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/revisions-server
|
||||
|
||||
# 1.1.0 (2022-11-18)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
25
packages/revisions/bin/worker.ts
Normal file
25
packages/revisions/bin/worker.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import 'reflect-metadata'
|
||||
|
||||
import 'newrelic'
|
||||
|
||||
import { Logger } from 'winston'
|
||||
|
||||
import { ContainerConfigLoader } from '../src/Bootstrap/Container'
|
||||
import TYPES from '../src/Bootstrap/Types'
|
||||
import { Env } from '../src/Bootstrap/Env'
|
||||
import { DomainEventSubscriberFactoryInterface } from '@standardnotes/domain-events'
|
||||
|
||||
const container = new ContainerConfigLoader()
|
||||
void container.load().then((container) => {
|
||||
const env: Env = new Env()
|
||||
env.load()
|
||||
|
||||
const logger: Logger = container.get(TYPES.Logger)
|
||||
|
||||
logger.info('Starting worker...')
|
||||
|
||||
const subscriberFactory: DomainEventSubscriberFactoryInterface = container.get(TYPES.DomainEventSubscriberFactory)
|
||||
subscriberFactory.create().start()
|
||||
|
||||
setInterval(() => logger.info('Alive and kicking!'), 20 * 60 * 1000)
|
||||
})
|
||||
19
packages/revisions/migrations/1669113322388-init.ts
Normal file
19
packages/revisions/migrations/1669113322388-init.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import { MigrationInterface, QueryRunner } from 'typeorm'
|
||||
|
||||
export class init1669113322388 implements MigrationInterface {
|
||||
name = 'init1669113322388'
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
'CREATE TABLE `revisions` (`uuid` varchar(36) NOT NULL, `item_uuid` varchar(36) NOT NULL, `user_uuid` varchar(36) NOT NULL, `content` mediumtext NULL, `content_type` varchar(255) NULL, `items_key_id` varchar(255) NULL, `enc_item_key` text NULL, `auth_hash` varchar(255) NULL, `creation_date` date NULL, `created_at` datetime(6) NULL, `updated_at` datetime(6) NULL, INDEX `item_uuid` (`item_uuid`), INDEX `user_uuid` (`user_uuid`), INDEX `creation_date` (`creation_date`), INDEX `created_at` (`created_at`), PRIMARY KEY (`uuid`)) ENGINE=InnoDB',
|
||||
)
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query('DROP INDEX `created_at` ON `revisions`')
|
||||
await queryRunner.query('DROP INDEX `creation_date` ON `revisions`')
|
||||
await queryRunner.query('DROP INDEX `user_uuid` ON `revisions`')
|
||||
await queryRunner.query('DROP INDEX `item_uuid` ON `revisions`')
|
||||
await queryRunner.query('DROP TABLE `revisions`')
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/revisions-server",
|
||||
"version": "1.1.0",
|
||||
"version": "1.4.8",
|
||||
"engines": {
|
||||
"node": ">=18.0.0 <19.0.0"
|
||||
},
|
||||
@@ -23,7 +23,6 @@
|
||||
"worker": "yarn node dist/bin/worker.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@newrelic/native-metrics": "^9.0.0",
|
||||
"@newrelic/winston-enricher": "^4.0.0",
|
||||
"@sentry/node": "^7.19.0",
|
||||
"@standardnotes/api": "^1.19.0",
|
||||
@@ -33,7 +32,7 @@
|
||||
"@standardnotes/domain-events-infra": "workspace:*",
|
||||
"@standardnotes/security": "workspace:^",
|
||||
"@standardnotes/time": "workspace:^",
|
||||
"aws-sdk": "^2.1253.0",
|
||||
"aws-sdk": "^2.1260.0",
|
||||
"cors": "2.8.5",
|
||||
"dotenv": "^16.0.1",
|
||||
"express": "^4.18.2",
|
||||
|
||||
@@ -2,6 +2,7 @@ import * as winston from 'winston'
|
||||
import Redis from 'ioredis'
|
||||
import * as AWS from 'aws-sdk'
|
||||
import { Container } from 'inversify'
|
||||
import { Repository } from 'typeorm'
|
||||
import {
|
||||
DomainEventHandlerInterface,
|
||||
DomainEventMessageHandlerInterface,
|
||||
@@ -15,6 +16,7 @@ import {
|
||||
SQSEventMessageHandler,
|
||||
SQSNewRelicEventMessageHandler,
|
||||
} from '@standardnotes/domain-events-infra'
|
||||
import { MapperInterface } from '@standardnotes/domain-core'
|
||||
|
||||
import { Env } from './Env'
|
||||
import TYPES from './Types'
|
||||
@@ -25,9 +27,15 @@ import { GetRevisionsMetada } from '../Domain/UseCase/GetRevisionsMetada/GetRevi
|
||||
import { RevisionRepositoryInterface } from '../Domain/Revision/RevisionRepositoryInterface'
|
||||
import { MySQLRevisionRepository } from '../Infra/MySQL/MySQLRevisionRepository'
|
||||
import { RevisionMetadataPersistenceMapper } from '../Mapping/RevisionMetadataPersistenceMapper'
|
||||
import { MapperInterface, RevisionMetadata } from '@standardnotes/domain-core'
|
||||
import { TypeORMRevision } from '../Infra/TypeORM/TypeORMRevision'
|
||||
import { Repository } from 'typeorm'
|
||||
import { RevisionMetadata } from '../Domain/Revision/RevisionMetadata'
|
||||
import { Revision } from '../Domain/Revision/Revision'
|
||||
import { RevisionItemStringMapper } from '../Mapping/RevisionItemStringMapper'
|
||||
import { RevisionPersistenceMapper } from '../Mapping/RevisionPersistenceMapper'
|
||||
import { ItemDumpedEventHandler } from '../Domain/Handler/ItemDumpedEventHandler'
|
||||
import { DumpRepositoryInterface } from '../Domain/Dump/DumpRepositoryInterface'
|
||||
import { S3DumpRepository } from '../Infra/S3/S3ItemDumpRepository'
|
||||
import { FSDumpRepository } from '../Infra/FS/FSDumpRepository'
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
const newrelicFormatter = require('@newrelic/winston-enricher')
|
||||
@@ -65,13 +73,18 @@ export class ContainerConfigLoader {
|
||||
})
|
||||
container.bind<winston.Logger>(TYPES.Logger).toConstantValue(logger)
|
||||
|
||||
if (env.get('SQS_AWS_REGION', true)) {
|
||||
container.bind<AWS.SQS>(TYPES.SQS).toConstantValue(
|
||||
new AWS.SQS({
|
||||
apiVersion: 'latest',
|
||||
region: env.get('SQS_AWS_REGION', true),
|
||||
}),
|
||||
)
|
||||
if (env.get('SQS_QUEUE_URL', true)) {
|
||||
const sqsConfig: AWS.SQS.Types.ClientConfiguration = {
|
||||
apiVersion: 'latest',
|
||||
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))
|
||||
}
|
||||
|
||||
let s3Client = undefined
|
||||
@@ -87,22 +100,18 @@ export class ContainerConfigLoader {
|
||||
container
|
||||
.bind<MapperInterface<RevisionMetadata, TypeORMRevision>>(TYPES.RevisionMetadataPersistenceMapper)
|
||||
.toConstantValue(new RevisionMetadataPersistenceMapper())
|
||||
container
|
||||
.bind<MapperInterface<Revision, TypeORMRevision>>(TYPES.RevisionPersistenceMapper)
|
||||
.toConstantValue(new RevisionPersistenceMapper())
|
||||
container
|
||||
.bind<MapperInterface<Revision, string>>(TYPES.RevisionItemStringMapper)
|
||||
.toConstantValue(new RevisionItemStringMapper())
|
||||
|
||||
// ORM
|
||||
container
|
||||
.bind<Repository<TypeORMRevision>>(TYPES.ORMRevisionRepository)
|
||||
.toConstantValue(AppDataSource.getRepository(TypeORMRevision))
|
||||
|
||||
// Repositories
|
||||
container
|
||||
.bind<RevisionRepositoryInterface>(TYPES.RevisionRepository)
|
||||
.toConstantValue(
|
||||
new MySQLRevisionRepository(
|
||||
container.get(TYPES.ORMRevisionRepository),
|
||||
container.get(TYPES.RevisionMetadataPersistenceMapper),
|
||||
),
|
||||
)
|
||||
|
||||
// env vars
|
||||
container.bind(TYPES.REDIS_URL).toConstantValue(env.get('REDIS_URL'))
|
||||
container.bind(TYPES.SQS_QUEUE_URL).toConstantValue(env.get('SQS_QUEUE_URL', true))
|
||||
@@ -113,6 +122,32 @@ export class ContainerConfigLoader {
|
||||
container.bind(TYPES.NEW_RELIC_ENABLED).toConstantValue(env.get('NEW_RELIC_ENABLED', true))
|
||||
container.bind(TYPES.VERSION).toConstantValue(env.get('VERSION'))
|
||||
|
||||
// Repositories
|
||||
container
|
||||
.bind<RevisionRepositoryInterface>(TYPES.RevisionRepository)
|
||||
.toConstantValue(
|
||||
new MySQLRevisionRepository(
|
||||
container.get(TYPES.ORMRevisionRepository),
|
||||
container.get(TYPES.RevisionMetadataPersistenceMapper),
|
||||
container.get(TYPES.RevisionPersistenceMapper),
|
||||
),
|
||||
)
|
||||
if (env.get('S3_AWS_REGION', true)) {
|
||||
container
|
||||
.bind<DumpRepositoryInterface>(TYPES.DumpRepository)
|
||||
.toConstantValue(
|
||||
new S3DumpRepository(
|
||||
container.get(TYPES.S3_BACKUP_BUCKET_NAME),
|
||||
container.get(TYPES.S3),
|
||||
container.get(TYPES.RevisionItemStringMapper),
|
||||
),
|
||||
)
|
||||
} else {
|
||||
container
|
||||
.bind<DumpRepositoryInterface>(TYPES.DumpRepository)
|
||||
.toConstantValue(new FSDumpRepository(container.get(TYPES.RevisionItemStringMapper)))
|
||||
}
|
||||
|
||||
// use cases
|
||||
container
|
||||
.bind<GetRevisionsMetada>(TYPES.GetRevisionsMetada)
|
||||
@@ -124,6 +159,11 @@ export class ContainerConfigLoader {
|
||||
.toConstantValue(new RevisionsController(container.get(TYPES.GetRevisionsMetada), container.get(TYPES.Logger)))
|
||||
|
||||
// Handlers
|
||||
container
|
||||
.bind<ItemDumpedEventHandler>(TYPES.ItemDumpedEventHandler)
|
||||
.toConstantValue(
|
||||
new ItemDumpedEventHandler(container.get(TYPES.DumpRepository), container.get(TYPES.RevisionRepository)),
|
||||
)
|
||||
|
||||
// Services
|
||||
container
|
||||
@@ -135,7 +175,9 @@ export class ContainerConfigLoader {
|
||||
.bind<InversifyExpressApiGatewayAuthMiddleware>(TYPES.ApiGatewayAuthMiddleware)
|
||||
.to(InversifyExpressApiGatewayAuthMiddleware)
|
||||
|
||||
const eventHandlers: Map<string, DomainEventHandlerInterface> = new Map([])
|
||||
const eventHandlers: Map<string, DomainEventHandlerInterface> = new Map([
|
||||
['ITEM_DUMPED', container.get(TYPES.ItemDumpedEventHandler)],
|
||||
])
|
||||
|
||||
if (env.get('SQS_QUEUE_URL', true)) {
|
||||
container
|
||||
|
||||
@@ -6,10 +6,13 @@ const TYPES = {
|
||||
S3: Symbol.for('S3'),
|
||||
// Map
|
||||
RevisionMetadataPersistenceMapper: Symbol.for('RevisionMetadataPersistenceMapper'),
|
||||
RevisionPersistenceMapper: Symbol.for('RevisionPersistenceMapper'),
|
||||
RevisionItemStringMapper: Symbol.for('RevisionItemStringMapper'),
|
||||
// ORM
|
||||
ORMRevisionRepository: Symbol.for('ORMRevisionRepository'),
|
||||
// Repositories
|
||||
RevisionRepository: Symbol.for('RevisionRepository'),
|
||||
DumpRepository: Symbol.for('DumpRepository'),
|
||||
// env vars
|
||||
REDIS_URL: Symbol.for('REDIS_URL'),
|
||||
SQS_QUEUE_URL: Symbol.for('SQS_QUEUE_URL'),
|
||||
@@ -25,6 +28,7 @@ const TYPES = {
|
||||
// Controller
|
||||
RevisionsController: Symbol.for('RevisionsController'),
|
||||
// Handlers
|
||||
ItemDumpedEventHandler: Symbol.for('ItemDumpedEventHandler'),
|
||||
// Services
|
||||
CrossServiceTokenDecoder: Symbol.for('CrossServiceTokenDecoder'),
|
||||
DomainEventSubscriberFactory: Symbol.for('DomainEventSubscriberFactory'),
|
||||
|
||||
@@ -20,14 +20,14 @@ describe('RevisionsController', () => {
|
||||
})
|
||||
|
||||
it('should get revisions list', async () => {
|
||||
const response = await createController().getRevisions({ itemUuid: '1-2-3' })
|
||||
const response = await createController().getRevisions({ itemUuid: '1-2-3', userUuid: '1-2-3' })
|
||||
|
||||
expect(response.status).toEqual(200)
|
||||
})
|
||||
|
||||
it('should indicate failure to get revisions list', async () => {
|
||||
getRevisionsMetadata.execute = jest.fn().mockReturnValue(Result.fail('Oops'))
|
||||
const response = await createController().getRevisions({ itemUuid: '1-2-3' })
|
||||
const response = await createController().getRevisions({ itemUuid: '1-2-3', userUuid: '1-2-3' })
|
||||
|
||||
expect(response.status).toEqual(400)
|
||||
})
|
||||
|
||||
@@ -8,7 +8,10 @@ export class RevisionsController {
|
||||
constructor(private getRevisionsMetadata: GetRevisionsMetada, private logger: Logger) {}
|
||||
|
||||
async getRevisions(params: GetRevisionsMetadataRequestParams): Promise<HttpResponse> {
|
||||
const revisionMetadataOrError = await this.getRevisionsMetadata.execute({ itemUuid: params.itemUuid })
|
||||
const revisionMetadataOrError = await this.getRevisionsMetadata.execute({
|
||||
itemUuid: params.itemUuid,
|
||||
userUuid: params.userUuid,
|
||||
})
|
||||
|
||||
if (revisionMetadataOrError.isFailed()) {
|
||||
this.logger.warn(revisionMetadataOrError.getError())
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
import { Revision } from '../Revision/Revision'
|
||||
|
||||
export interface DumpRepositoryInterface {
|
||||
getRevisionFromDumpPath(path: string): Promise<Revision | null>
|
||||
removeDump(path: string): Promise<void>
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
import { ItemDumpedEvent } from '@standardnotes/domain-events'
|
||||
import { DumpRepositoryInterface } from '../Dump/DumpRepositoryInterface'
|
||||
import { Revision } from '../Revision/Revision'
|
||||
import { RevisionRepositoryInterface } from '../Revision/RevisionRepositoryInterface'
|
||||
import { ItemDumpedEventHandler } from './ItemDumpedEventHandler'
|
||||
|
||||
describe('ItemDumpedEventHandler', () => {
|
||||
let dumpRepository: DumpRepositoryInterface
|
||||
let revisionRepository: RevisionRepositoryInterface
|
||||
let revision: Revision
|
||||
let event: ItemDumpedEvent
|
||||
|
||||
const createHandler = () => new ItemDumpedEventHandler(dumpRepository, revisionRepository)
|
||||
|
||||
beforeEach(() => {
|
||||
revision = {} as jest.Mocked<Revision>
|
||||
|
||||
dumpRepository = {} as jest.Mocked<DumpRepositoryInterface>
|
||||
dumpRepository.getRevisionFromDumpPath = jest.fn().mockReturnValue(revision)
|
||||
dumpRepository.removeDump = jest.fn()
|
||||
|
||||
revisionRepository = {} as jest.Mocked<RevisionRepositoryInterface>
|
||||
revisionRepository.save = jest.fn()
|
||||
|
||||
event = {} as jest.Mocked<ItemDumpedEvent>
|
||||
event.payload = {
|
||||
fileDumpPath: 'foobar',
|
||||
}
|
||||
})
|
||||
|
||||
it('should save a revision from file dump', async () => {
|
||||
await createHandler().handle(event)
|
||||
|
||||
expect(revisionRepository.save).toHaveBeenCalled()
|
||||
expect(dumpRepository.removeDump).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('should not save a revision if it could not be created from dump', async () => {
|
||||
dumpRepository.getRevisionFromDumpPath = jest.fn().mockReturnValue(null)
|
||||
|
||||
await createHandler().handle(event)
|
||||
|
||||
expect(revisionRepository.save).not.toHaveBeenCalled()
|
||||
expect(dumpRepository.removeDump).toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,24 @@
|
||||
import { DomainEventHandlerInterface, ItemDumpedEvent } from '@standardnotes/domain-events'
|
||||
|
||||
import { DumpRepositoryInterface } from '../Dump/DumpRepositoryInterface'
|
||||
import { RevisionRepositoryInterface } from '../Revision/RevisionRepositoryInterface'
|
||||
|
||||
export class ItemDumpedEventHandler implements DomainEventHandlerInterface {
|
||||
constructor(
|
||||
private dumpRepository: DumpRepositoryInterface,
|
||||
private revisionRepository: RevisionRepositoryInterface,
|
||||
) {}
|
||||
|
||||
async handle(event: ItemDumpedEvent): Promise<void> {
|
||||
const revision = await this.dumpRepository.getRevisionFromDumpPath(event.payload.fileDumpPath)
|
||||
if (revision === null) {
|
||||
await this.dumpRepository.removeDump(event.payload.fileDumpPath)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
await this.revisionRepository.save(revision)
|
||||
|
||||
await this.dumpRepository.removeDump(event.payload.fileDumpPath)
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
import { ValueObject } from '../Core/ValueObject'
|
||||
import { Result } from '../Core/Result'
|
||||
import { ContentTypeProps } from './ContentTypeProps'
|
||||
import { ContentType as ContentTypeValues } from '@standardnotes/common'
|
||||
import { Result, ValueObject } from '@standardnotes/domain-core'
|
||||
|
||||
import { ContentTypeProps } from './ContentTypeProps'
|
||||
|
||||
export class ContentType extends ValueObject<ContentTypeProps> {
|
||||
get value(): string | null {
|
||||
@@ -1,6 +1,4 @@
|
||||
import { Entity } from '../Core/Entity'
|
||||
import { Result } from '../Core/Result'
|
||||
import { UniqueEntityId } from '../Core/UniqueEntityId'
|
||||
import { Entity, Result, UniqueEntityId } from '@standardnotes/domain-core'
|
||||
|
||||
import { RevisionProps } from './RevisionProps'
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
import { Entity } from '../Core/Entity'
|
||||
import { Result } from '../Core/Result'
|
||||
import { UniqueEntityId } from '../Core/UniqueEntityId'
|
||||
import { Entity, Result, UniqueEntityId } from '@standardnotes/domain-core'
|
||||
|
||||
import { RevisionMetadataProps } from './RevisionMetadataProps'
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Timestamps } from '../Common/Timestamps'
|
||||
import { Timestamps } from '@standardnotes/domain-core'
|
||||
|
||||
import { ContentType } from './ContentType'
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
import { Uuid } from '../Common/Uuid'
|
||||
import { Timestamps, Uuid } from '@standardnotes/domain-core'
|
||||
|
||||
import { ContentType } from './ContentType'
|
||||
|
||||
export interface RevisionProps {
|
||||
itemUuid: Uuid
|
||||
userUuid: Uuid
|
||||
content: string | null
|
||||
contentType: ContentType
|
||||
itemsKeyId: string | null
|
||||
encItemKey: string | null
|
||||
authHash: string | null
|
||||
creationDate: Date
|
||||
createdAt: Date
|
||||
updatedAt: Date
|
||||
timestamps: Timestamps
|
||||
}
|
||||
@@ -1,5 +1,9 @@
|
||||
import { Uuid, RevisionMetadata } from '@standardnotes/domain-core'
|
||||
import { Uuid } from '@standardnotes/domain-core'
|
||||
|
||||
import { Revision } from './Revision'
|
||||
import { RevisionMetadata } from './RevisionMetadata'
|
||||
|
||||
export interface RevisionRepositoryInterface {
|
||||
findMetadataByItemId(itemUuid: Uuid): Promise<Array<RevisionMetadata>>
|
||||
findMetadataByItemId(itemUuid: Uuid, userUuid: Uuid): Promise<Array<RevisionMetadata>>
|
||||
save(revision: Revision): Promise<Revision>
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { RevisionMetadata } from '@standardnotes/domain-core'
|
||||
|
||||
import { RevisionMetadata } from '../../Revision/RevisionMetadata'
|
||||
import { RevisionRepositoryInterface } from '../../Revision/RevisionRepositoryInterface'
|
||||
import { GetRevisionsMetada } from './GetRevisionsMetada'
|
||||
|
||||
@@ -14,14 +13,29 @@ describe('GetRevisionsMetada', () => {
|
||||
})
|
||||
|
||||
it('should return revisions metadata for a given item', async () => {
|
||||
const result = await createUseCase().execute({ itemUuid: '84c0f8e8-544a-4c7e-9adf-26209303bc1d' })
|
||||
const result = await createUseCase().execute({
|
||||
itemUuid: '84c0f8e8-544a-4c7e-9adf-26209303bc1d',
|
||||
userUuid: '84c0f8e8-544a-4c7e-9adf-26209303bc1d',
|
||||
})
|
||||
|
||||
expect(result.isFailed()).toBeFalsy()
|
||||
expect(result.getValue().length).toEqual(1)
|
||||
})
|
||||
|
||||
it('should not return revisions metadata for a an invalid item uuid', async () => {
|
||||
const result = await createUseCase().execute({ itemUuid: '1-2-3' })
|
||||
const result = await createUseCase().execute({
|
||||
itemUuid: '1-2-3',
|
||||
userUuid: '84c0f8e8-544a-4c7e-9adf-26209303bc1d',
|
||||
})
|
||||
|
||||
expect(result.isFailed()).toBeTruthy()
|
||||
})
|
||||
|
||||
it('should not return revisions metadata for a an invalid user uuid', async () => {
|
||||
const result = await createUseCase().execute({
|
||||
userUuid: '1-2-3',
|
||||
itemUuid: '84c0f8e8-544a-4c7e-9adf-26209303bc1d',
|
||||
})
|
||||
|
||||
expect(result.isFailed()).toBeTruthy()
|
||||
})
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { Result, RevisionMetadata, UseCaseInterface, Uuid } from '@standardnotes/domain-core'
|
||||
import { Result, UseCaseInterface, Uuid } from '@standardnotes/domain-core'
|
||||
|
||||
import { RevisionMetadata } from '../../Revision/RevisionMetadata'
|
||||
import { RevisionRepositoryInterface } from '../../Revision/RevisionRepositoryInterface'
|
||||
|
||||
import { GetRevisionsMetadaDTO } from './GetRevisionsMetadaDTO'
|
||||
@@ -13,7 +14,15 @@ export class GetRevisionsMetada implements UseCaseInterface<RevisionMetadata[]>
|
||||
return Result.fail<RevisionMetadata[]>(`Could not get revisions: ${itemUuidOrError.getError()}`)
|
||||
}
|
||||
|
||||
const revisionsMetdata = await this.revisionRepository.findMetadataByItemId(itemUuidOrError.getValue())
|
||||
const userUuidOrError = Uuid.create(dto.userUuid)
|
||||
if (userUuidOrError.isFailed()) {
|
||||
return Result.fail<RevisionMetadata[]>(`Could not get revisions: ${userUuidOrError.getError()}`)
|
||||
}
|
||||
|
||||
const revisionsMetdata = await this.revisionRepository.findMetadataByItemId(
|
||||
itemUuidOrError.getValue(),
|
||||
userUuidOrError.getValue(),
|
||||
)
|
||||
|
||||
return Result.ok<RevisionMetadata[]>(revisionsMetdata)
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
export interface GetRevisionsMetadaDTO {
|
||||
itemUuid: string
|
||||
userUuid: string
|
||||
}
|
||||
|
||||
21
packages/revisions/src/Infra/FS/FSDumpRepository.ts
Normal file
21
packages/revisions/src/Infra/FS/FSDumpRepository.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
import { MapperInterface } from '@standardnotes/domain-core'
|
||||
import { promises } from 'fs'
|
||||
|
||||
import { DumpRepositoryInterface } from '../../Domain/Dump/DumpRepositoryInterface'
|
||||
import { Revision } from '../../Domain/Revision/Revision'
|
||||
|
||||
export class FSDumpRepository implements DumpRepositoryInterface {
|
||||
constructor(private revisionStringItemMapper: MapperInterface<Revision, string>) {}
|
||||
|
||||
async getRevisionFromDumpPath(path: string): Promise<Revision | null> {
|
||||
const contents = (await promises.readFile(path)).toString()
|
||||
|
||||
const revision = this.revisionStringItemMapper.toDomain(contents)
|
||||
|
||||
return revision
|
||||
}
|
||||
|
||||
async removeDump(path: string): Promise<void> {
|
||||
await promises.rm(path)
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
export interface GetRevisionsMetadataRequestParams {
|
||||
itemUuid: string
|
||||
userUuid: string
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Request } from 'express'
|
||||
import { Request, Response } from 'express'
|
||||
import { BaseHttpController, controller, httpGet, results } from 'inversify-express-utils'
|
||||
import { inject } from 'inversify'
|
||||
|
||||
@@ -12,9 +12,10 @@ export class InversifyExpressRevisionsController extends BaseHttpController {
|
||||
}
|
||||
|
||||
@httpGet('/')
|
||||
public async getRevisions(req: Request): Promise<results.JsonResult> {
|
||||
public async getRevisions(req: Request, response: Response): Promise<results.JsonResult> {
|
||||
const result = await this.revisionsController.getRevisions({
|
||||
itemUuid: req.params.itemUuid,
|
||||
userUuid: response.locals.user.uuid,
|
||||
})
|
||||
|
||||
return this.json(result.data, result.status)
|
||||
|
||||
@@ -1,32 +1,42 @@
|
||||
import { MapperInterface, RevisionMetadata, Uuid } from '@standardnotes/domain-core'
|
||||
import { MapperInterface, Uuid } from '@standardnotes/domain-core'
|
||||
import { Repository } from 'typeorm'
|
||||
import { Revision } from '../../Domain/Revision/Revision'
|
||||
|
||||
import { RevisionMetadata } from '../../Domain/Revision/RevisionMetadata'
|
||||
import { RevisionRepositoryInterface } from '../../Domain/Revision/RevisionRepositoryInterface'
|
||||
import { TypeORMRevision } from '../TypeORM/TypeORMRevision'
|
||||
|
||||
export class MySQLRevisionRepository implements RevisionRepositoryInterface {
|
||||
constructor(
|
||||
private ormRepository: Repository<TypeORMRevision>,
|
||||
private revisionMapper: MapperInterface<RevisionMetadata, TypeORMRevision>,
|
||||
private revisionMetadataMapper: MapperInterface<RevisionMetadata, TypeORMRevision>,
|
||||
private revisionMapper: MapperInterface<Revision, TypeORMRevision>,
|
||||
) {}
|
||||
|
||||
async findMetadataByItemId(itemUuid: Uuid): Promise<Array<RevisionMetadata>> {
|
||||
async save(revision: Revision): Promise<Revision> {
|
||||
const typeormRevision = this.revisionMapper.toProjection(revision)
|
||||
|
||||
await this.ormRepository.save(typeormRevision)
|
||||
|
||||
return revision
|
||||
}
|
||||
|
||||
async findMetadataByItemId(itemUuid: Uuid, userUuid: Uuid): Promise<Array<RevisionMetadata>> {
|
||||
const queryBuilder = this.ormRepository
|
||||
.createQueryBuilder()
|
||||
.select('uuid', 'uuid')
|
||||
.addSelect('content_type', 'contentType')
|
||||
.addSelect('created_at', 'createdAt')
|
||||
.addSelect('updated_at', 'updatedAt')
|
||||
.where('item_uuid = :item_uuid', {
|
||||
item_uuid: itemUuid,
|
||||
})
|
||||
.where('item_uuid = :itemUuid', { itemUuid })
|
||||
.andWhere('user_uuid = :userUuid', { userUuid })
|
||||
.orderBy('created_at', 'DESC')
|
||||
|
||||
const simplifiedRevisions = await queryBuilder.getMany()
|
||||
|
||||
const metadata = []
|
||||
for (const simplifiedRevision of simplifiedRevisions) {
|
||||
metadata.push(this.revisionMapper.toDomain(simplifiedRevision))
|
||||
metadata.push(this.revisionMetadataMapper.toDomain(simplifiedRevision))
|
||||
}
|
||||
|
||||
return metadata
|
||||
|
||||
39
packages/revisions/src/Infra/S3/S3ItemDumpRepository.ts
Normal file
39
packages/revisions/src/Infra/S3/S3ItemDumpRepository.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
import { MapperInterface } from '@standardnotes/domain-core'
|
||||
import { S3 } from 'aws-sdk'
|
||||
|
||||
import { DumpRepositoryInterface } from '../../Domain/Dump/DumpRepositoryInterface'
|
||||
import { Revision } from '../../Domain/Revision/Revision'
|
||||
|
||||
export class S3DumpRepository implements DumpRepositoryInterface {
|
||||
constructor(
|
||||
private dumpBucketName: string,
|
||||
private s3Client: S3,
|
||||
private revisionStringItemMapper: MapperInterface<Revision, string>,
|
||||
) {}
|
||||
|
||||
async getRevisionFromDumpPath(path: string): Promise<Revision | null> {
|
||||
const s3Object = await this.s3Client
|
||||
.getObject({
|
||||
Bucket: this.dumpBucketName,
|
||||
Key: path,
|
||||
})
|
||||
.promise()
|
||||
|
||||
if (s3Object.Body === undefined) {
|
||||
return null
|
||||
}
|
||||
|
||||
const revision = this.revisionStringItemMapper.toDomain(s3Object.Body as string)
|
||||
|
||||
return revision
|
||||
}
|
||||
|
||||
async removeDump(path: string): Promise<void> {
|
||||
await this.s3Client
|
||||
.deleteObject({
|
||||
Bucket: this.dumpBucketName,
|
||||
Key: path,
|
||||
})
|
||||
.promise()
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,3 @@
|
||||
import { ContentType } from '@standardnotes/common'
|
||||
|
||||
import { Column, Entity, Index, PrimaryGeneratedColumn } from 'typeorm'
|
||||
|
||||
@Entity({ name: 'revisions' })
|
||||
@@ -11,8 +9,16 @@ export class TypeORMRevision {
|
||||
name: 'item_uuid',
|
||||
length: 36,
|
||||
})
|
||||
@Index('item_uuid')
|
||||
declare itemUuid: string
|
||||
|
||||
@Column({
|
||||
name: 'user_uuid',
|
||||
length: 36,
|
||||
})
|
||||
@Index('user_uuid')
|
||||
declare userUuid: string
|
||||
|
||||
@Column({
|
||||
type: 'mediumtext',
|
||||
nullable: true,
|
||||
@@ -25,7 +31,7 @@ export class TypeORMRevision {
|
||||
length: 255,
|
||||
nullable: true,
|
||||
})
|
||||
declare contentType: ContentType | null
|
||||
declare contentType: string | null
|
||||
|
||||
@Column({
|
||||
type: 'varchar',
|
||||
@@ -55,7 +61,7 @@ export class TypeORMRevision {
|
||||
type: 'date',
|
||||
nullable: true,
|
||||
})
|
||||
@Index('index_revisions_on_creation_date')
|
||||
@Index('creation_date')
|
||||
declare creationDate: Date
|
||||
|
||||
@Column({
|
||||
@@ -64,7 +70,7 @@ export class TypeORMRevision {
|
||||
precision: 6,
|
||||
nullable: true,
|
||||
})
|
||||
@Index('index_revisions_on_created_at')
|
||||
@Index('created_at')
|
||||
declare createdAt: Date
|
||||
|
||||
@Column({
|
||||
|
||||
50
packages/revisions/src/Mapping/RevisionItemStringMapper.ts
Normal file
50
packages/revisions/src/Mapping/RevisionItemStringMapper.ts
Normal file
@@ -0,0 +1,50 @@
|
||||
import { MapperInterface, Timestamps, Uuid } from '@standardnotes/domain-core'
|
||||
|
||||
import { ContentType } from '../Domain/Revision/ContentType'
|
||||
import { Revision } from '../Domain/Revision/Revision'
|
||||
|
||||
export class RevisionItemStringMapper implements MapperInterface<Revision, string> {
|
||||
toDomain(projection: string): Revision {
|
||||
const item = JSON.parse(projection).item
|
||||
|
||||
const contentTypeOrError = ContentType.create(item.content_type)
|
||||
if (contentTypeOrError.isFailed()) {
|
||||
throw new Error(`Could not map item string to revision [content type]: ${contentTypeOrError.getError()}`)
|
||||
}
|
||||
const contentType = contentTypeOrError.getValue()
|
||||
|
||||
const itemUuidOrError = Uuid.create(item.uuid)
|
||||
if (itemUuidOrError.isFailed()) {
|
||||
throw new Error(`Could not map item string to revision [item uuid]: ${itemUuidOrError.getError()}`)
|
||||
}
|
||||
const itemUuid = itemUuidOrError.getValue()
|
||||
|
||||
const userUuidOrError = Uuid.create(item.user_uuid)
|
||||
if (userUuidOrError.isFailed()) {
|
||||
throw new Error(`Could not map item string to revision [user uuid]: ${userUuidOrError.getError()}`)
|
||||
}
|
||||
const userUuid = userUuidOrError.getValue()
|
||||
|
||||
const revisionOrError = Revision.create({
|
||||
itemUuid,
|
||||
userUuid,
|
||||
authHash: item.auth_hash,
|
||||
content: item.content,
|
||||
contentType,
|
||||
itemsKeyId: item.items_key_id,
|
||||
encItemKey: item.enc_item_key,
|
||||
creationDate: new Date(),
|
||||
timestamps: Timestamps.create(new Date(), new Date()).getValue(),
|
||||
})
|
||||
|
||||
if (revisionOrError.isFailed()) {
|
||||
throw new Error(`Could not map item string to revision [revision]: ${revisionOrError.getError()}`)
|
||||
}
|
||||
|
||||
return revisionOrError.getValue()
|
||||
}
|
||||
|
||||
toProjection(domain: Revision): string {
|
||||
return JSON.stringify(domain)
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
import { RevisionMetadata, MapperInterface, UniqueEntityId, ContentType, Timestamps } from '@standardnotes/domain-core'
|
||||
import { MapperInterface, Timestamps, UniqueEntityId } from '@standardnotes/domain-core'
|
||||
|
||||
import { ContentType } from '../Domain/Revision/ContentType'
|
||||
import { RevisionMetadata } from '../Domain/Revision/RevisionMetadata'
|
||||
import { TypeORMRevision } from '../Infra/TypeORM/TypeORMRevision'
|
||||
|
||||
export class RevisionMetadataPersistenceMapper implements MapperInterface<RevisionMetadata, TypeORMRevision> {
|
||||
|
||||
70
packages/revisions/src/Mapping/RevisionPersistenceMapper.ts
Normal file
70
packages/revisions/src/Mapping/RevisionPersistenceMapper.ts
Normal file
@@ -0,0 +1,70 @@
|
||||
import { MapperInterface, Timestamps, UniqueEntityId, Uuid } from '@standardnotes/domain-core'
|
||||
import { ContentType } from '../Domain/Revision/ContentType'
|
||||
import { Revision } from '../Domain/Revision/Revision'
|
||||
import { TypeORMRevision } from '../Infra/TypeORM/TypeORMRevision'
|
||||
|
||||
export class RevisionPersistenceMapper implements MapperInterface<Revision, TypeORMRevision> {
|
||||
toDomain(projection: TypeORMRevision): Revision {
|
||||
const contentTypeOrError = ContentType.create(projection.contentType)
|
||||
if (contentTypeOrError.isFailed()) {
|
||||
throw new Error(`Could not map typeorm revision to domain revision: ${contentTypeOrError.getError()}`)
|
||||
}
|
||||
const contentType = contentTypeOrError.getValue()
|
||||
|
||||
const timestampsOrError = Timestamps.create(projection.createdAt, projection.updatedAt)
|
||||
if (timestampsOrError.isFailed()) {
|
||||
throw new Error(`Could not map typeorm revision to domain revision: ${timestampsOrError.getError()}`)
|
||||
}
|
||||
const timestamps = timestampsOrError.getValue()
|
||||
|
||||
const itemUuidOrError = Uuid.create(projection.itemUuid)
|
||||
if (itemUuidOrError.isFailed()) {
|
||||
throw new Error(`Could not map typeorm revision to domain revision: ${itemUuidOrError.getError()}`)
|
||||
}
|
||||
const itemUuid = itemUuidOrError.getValue()
|
||||
|
||||
const userUuidOrError = Uuid.create(projection.userUuid)
|
||||
if (userUuidOrError.isFailed()) {
|
||||
throw new Error(`Could not map typeorm revision to domain revision: ${userUuidOrError.getError()}`)
|
||||
}
|
||||
const userUuid = userUuidOrError.getValue()
|
||||
|
||||
const revisionOrError = Revision.create(
|
||||
{
|
||||
authHash: projection.authHash,
|
||||
content: projection.content,
|
||||
contentType,
|
||||
creationDate: projection.creationDate,
|
||||
encItemKey: projection.encItemKey,
|
||||
itemsKeyId: projection.itemsKeyId,
|
||||
itemUuid,
|
||||
userUuid,
|
||||
timestamps,
|
||||
},
|
||||
new UniqueEntityId(projection.uuid),
|
||||
)
|
||||
if (revisionOrError.isFailed()) {
|
||||
throw new Error(`Could not map typeorm revision to domain revision: ${revisionOrError.getError()}`)
|
||||
}
|
||||
|
||||
return revisionOrError.getValue()
|
||||
}
|
||||
|
||||
toProjection(domain: Revision): TypeORMRevision {
|
||||
const typeormRevision = new TypeORMRevision()
|
||||
|
||||
typeormRevision.authHash = domain.props.authHash
|
||||
typeormRevision.content = domain.props.content
|
||||
typeormRevision.contentType = domain.props.contentType.value
|
||||
typeormRevision.createdAt = domain.props.timestamps.createdAt
|
||||
typeormRevision.updatedAt = domain.props.timestamps.updatedAt
|
||||
typeormRevision.creationDate = domain.props.creationDate
|
||||
typeormRevision.encItemKey = domain.props.encItemKey
|
||||
typeormRevision.itemUuid = domain.props.itemUuid.value
|
||||
typeormRevision.itemsKeyId = domain.props.itemsKeyId
|
||||
typeormRevision.userUuid = domain.props.userUuid.value
|
||||
typeormRevision.uuid = domain.id.toString()
|
||||
|
||||
return typeormRevision
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,36 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.13.31](https://github.com/standardnotes/server/compare/@standardnotes/scheduler-server@1.13.30...@standardnotes/scheduler-server@1.13.31) (2022-11-25)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/scheduler-server
|
||||
|
||||
## [1.13.30](https://github.com/standardnotes/server/compare/@standardnotes/scheduler-server@1.13.29...@standardnotes/scheduler-server@1.13.30) (2022-11-24)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/scheduler-server
|
||||
|
||||
## [1.13.29](https://github.com/standardnotes/server/compare/@standardnotes/scheduler-server@1.13.28...@standardnotes/scheduler-server@1.13.29) (2022-11-23)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/scheduler-server
|
||||
|
||||
## [1.13.28](https://github.com/standardnotes/server/compare/@standardnotes/scheduler-server@1.13.27...@standardnotes/scheduler-server@1.13.28) (2022-11-23)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* binding of sns and sqs with additional config ([74bc791](https://github.com/standardnotes/server/commit/74bc79116bc50d9a5af1a558db1b7108dcda6d0e))
|
||||
|
||||
## [1.13.27](https://github.com/standardnotes/server/compare/@standardnotes/scheduler-server@1.13.26...@standardnotes/scheduler-server@1.13.27) (2022-11-22)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/scheduler-server
|
||||
|
||||
## [1.13.26](https://github.com/standardnotes/server/compare/@standardnotes/scheduler-server@1.13.25...@standardnotes/scheduler-server@1.13.26) (2022-11-21)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/scheduler-server
|
||||
|
||||
## [1.13.25](https://github.com/standardnotes/server/compare/@standardnotes/scheduler-server@1.13.24...@standardnotes/scheduler-server@1.13.25) (2022-11-18)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/scheduler-server
|
||||
|
||||
## [1.13.24](https://github.com/standardnotes/server/compare/@standardnotes/scheduler-server@1.13.23...@standardnotes/scheduler-server@1.13.24) (2022-11-16)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/scheduler-server
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/scheduler-server",
|
||||
"version": "1.13.24",
|
||||
"version": "1.13.31",
|
||||
"engines": {
|
||||
"node": ">=18.0.0 <19.0.0"
|
||||
},
|
||||
@@ -24,7 +24,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:*",
|
||||
@@ -32,7 +31,7 @@
|
||||
"@standardnotes/domain-events-infra": "workspace:*",
|
||||
"@standardnotes/predicates": "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",
|
||||
|
||||
@@ -74,13 +74,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)) {
|
||||
|
||||
@@ -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.7.2](https://github.com/standardnotes/server/compare/@standardnotes/security@1.7.1...@standardnotes/security@1.7.2) (2022-11-25)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/security
|
||||
|
||||
## [1.7.1](https://github.com/standardnotes/server/compare/@standardnotes/security@1.7.0...@standardnotes/security@1.7.1) (2022-11-22)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/security
|
||||
|
||||
# [1.7.0](https://github.com/standardnotes/server/compare/@standardnotes/security@1.6.4...@standardnotes/security@1.7.0) (2022-11-14)
|
||||
|
||||
### Features
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/security",
|
||||
"version": "1.7.0",
|
||||
"version": "1.7.2",
|
||||
"engines": {
|
||||
"node": ">=18.0.0 <19.0.0"
|
||||
},
|
||||
|
||||
@@ -3,6 +3,10 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.18.4](https://github.com/standardnotes/server/compare/@standardnotes/settings@1.18.3...@standardnotes/settings@1.18.4) (2022-11-24)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/settings
|
||||
|
||||
## [1.18.3](https://github.com/standardnotes/server/compare/@standardnotes/settings@1.18.0...@standardnotes/settings@1.18.3) (2022-11-14)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/settings",
|
||||
"version": "1.18.3",
|
||||
"version": "1.18.4",
|
||||
"engines": {
|
||||
"node": ">=18.0.0 <19.0.0"
|
||||
},
|
||||
@@ -29,7 +29,6 @@
|
||||
"typescript": "^4.8.4"
|
||||
},
|
||||
"dependencies": {
|
||||
"@newrelic/native-metrics": "^9.0.0",
|
||||
"reflect-metadata": "^0.1.13"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,3 +42,6 @@ NEW_RELIC_NO_CONFIG_FILE=true
|
||||
NEW_RELIC_DISTRIBUTED_TRACING_ENABLED=false
|
||||
NEW_RELIC_LOG_ENABLED=false
|
||||
NEW_RELIC_LOG_LEVEL=info
|
||||
|
||||
# (Optional) Revision Dumps
|
||||
FILE_UPLOAD_PATH=
|
||||
|
||||
@@ -3,6 +3,108 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.18.12](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.18.11...@standardnotes/syncing-server@1.18.12) (2022-11-25)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/syncing-server
|
||||
|
||||
## [1.18.11](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.18.10...@standardnotes/syncing-server@1.18.11) (2022-11-24)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/syncing-server
|
||||
|
||||
## [1.18.10](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.18.9...@standardnotes/syncing-server@1.18.10) (2022-11-24)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/syncing-server
|
||||
|
||||
## [1.18.9](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.18.8...@standardnotes/syncing-server@1.18.9) (2022-11-24)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/syncing-server
|
||||
|
||||
## [1.18.8](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.18.7...@standardnotes/syncing-server@1.18.8) (2022-11-24)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/syncing-server
|
||||
|
||||
## [1.18.7](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.18.6...@standardnotes/syncing-server@1.18.7) (2022-11-23)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/syncing-server
|
||||
|
||||
## [1.18.6](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.18.5...@standardnotes/syncing-server@1.18.6) (2022-11-23)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* binding of sns and sqs with additional config ([74bc791](https://github.com/standardnotes/syncing-server-js/commit/74bc79116bc50d9a5af1a558db1b7108dcda6d0e))
|
||||
|
||||
## [1.18.5](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.18.4...@standardnotes/syncing-server@1.18.5) (2022-11-22)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **syncing-server:** publish revision creation request only for notes and files ([3086625](https://github.com/standardnotes/syncing-server-js/commit/308662550f7da086a93cb47fd2d0f41cbec14159))
|
||||
|
||||
## [1.18.4](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.18.3...@standardnotes/syncing-server@1.18.4) (2022-11-22)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* sns binding ([3686a26](https://github.com/standardnotes/syncing-server-js/commit/3686a260192468c00b52087590dd2edf76ada939))
|
||||
|
||||
## [1.18.3](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.18.2...@standardnotes/syncing-server@1.18.3) (2022-11-22)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* sqs binding ([806a732](https://github.com/standardnotes/syncing-server-js/commit/806a732cbc92cd89deb9d9d2aa95565922ce6b72))
|
||||
|
||||
## [1.18.2](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.18.1...@standardnotes/syncing-server@1.18.2) (2022-11-22)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **syncing-server:** bring back creating revisions in syncing server for a transition period ([5f3bd51](https://github.com/standardnotes/syncing-server-js/commit/5f3bd5137f3a22330ea19fefff5f9310e9323044))
|
||||
|
||||
## [1.18.1](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.18.0...@standardnotes/syncing-server@1.18.1) (2022-11-22)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **syncing-server:** specs ([f7e0b68](https://github.com/standardnotes/syncing-server-js/commit/f7e0b68643df4027d274ed1e575cada62c6dbc25))
|
||||
|
||||
# [1.18.0](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.17.0...@standardnotes/syncing-server@1.18.0) (2022-11-22)
|
||||
|
||||
### Features
|
||||
|
||||
* **syncing-server:** add dump projection for revisions ([455f35e](https://github.com/standardnotes/syncing-server-js/commit/455f35e0c1ac811720b67592a9017a3470a7740c))
|
||||
|
||||
# [1.17.0](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.16.1...@standardnotes/syncing-server@1.17.0) (2022-11-22)
|
||||
|
||||
### Features
|
||||
|
||||
* **syncing-server:** add dumping backup items to filesystem ([97b367d](https://github.com/standardnotes/syncing-server-js/commit/97b367d4eee1e8bc2fcfd4a477e6fb1d19507c14))
|
||||
|
||||
## [1.16.1](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.16.0...@standardnotes/syncing-server@1.16.1) (2022-11-22)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/syncing-server
|
||||
|
||||
# [1.16.0](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.15.0...@standardnotes/syncing-server@1.16.0) (2022-11-21)
|
||||
|
||||
### Features
|
||||
|
||||
* **revisions:** add persisting revisions from s3 dump ([822ee89](https://github.com/standardnotes/syncing-server-js/commit/822ee890aff80cd099fc67b778ee02b8e9ef40eb))
|
||||
|
||||
# [1.15.0](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.14.0...@standardnotes/syncing-server@1.15.0) (2022-11-21)
|
||||
|
||||
### Features
|
||||
|
||||
* **syncing-server:** add creating item dumps for revision service ([8d152dd](https://github.com/standardnotes/syncing-server-js/commit/8d152ddfcb3c88cbbf9df04e3ed6e2c02571d821))
|
||||
|
||||
# [1.14.0](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.13.17...@standardnotes/syncing-server@1.14.0) (2022-11-21)
|
||||
|
||||
### Features
|
||||
|
||||
* **syncing-server:** add creating revisions in async way ([1ca8531](https://github.com/standardnotes/syncing-server-js/commit/1ca853130547ebfc26bdd9abce0dfb550e8217f6))
|
||||
|
||||
## [1.13.17](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.13.16...@standardnotes/syncing-server@1.13.17) (2022-11-21)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/syncing-server
|
||||
|
||||
## [1.13.16](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.13.15...@standardnotes/syncing-server@1.13.16) (2022-11-18)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/syncing-server
|
||||
|
||||
## [1.13.15](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.13.14...@standardnotes/syncing-server@1.13.15) (2022-11-18)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
@@ -7,6 +7,6 @@ module.exports = {
|
||||
transform: {
|
||||
...tsjPreset.transform,
|
||||
},
|
||||
coveragePathIgnorePatterns: ['/Bootstrap/', 'HealthCheckController'],
|
||||
coveragePathIgnorePatterns: ['/Bootstrap/', 'HealthCheckController', '/Infra/'],
|
||||
setupFilesAfterEnv: ['./test-setup.ts'],
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/syncing-server",
|
||||
"version": "1.13.15",
|
||||
"version": "1.18.12",
|
||||
"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",
|
||||
"@newrelic/winston-enricher": "^4.0.0",
|
||||
"@sentry/node": "^7.19.0",
|
||||
"@standardnotes/common": "workspace:*",
|
||||
@@ -37,7 +36,7 @@
|
||||
"@standardnotes/security": "workspace:*",
|
||||
"@standardnotes/settings": "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",
|
||||
|
||||
@@ -84,6 +84,8 @@ import { RevisionMetadataMap } from '../Domain/Map/RevisionMetadataMap'
|
||||
import { MapperInterface } from '@standardnotes/domain-core'
|
||||
import { RevisionMetadata } from '../Domain/Revision/RevisionMetadata'
|
||||
import { SimpleRevisionProjection } from '../Projection/SimpleRevisionProjection'
|
||||
import { ItemRevisionCreationRequestedEventHandler } from '../Domain/Handler/ItemRevisionCreationRequestedEventHandler'
|
||||
import { FSItemBackupService } from '../Infra/FS/FSItemBackupService'
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
const newrelicFormatter = require('@newrelic/winston-enricher')
|
||||
@@ -91,6 +93,7 @@ const newrelicFormatter = require('@newrelic/winston-enricher')
|
||||
export class ContainerConfigLoader {
|
||||
private readonly DEFAULT_CONTENT_SIZE_TRANSFER_LIMIT = 10_000_000
|
||||
private readonly DEFAULT_MAX_ITEMS_LIMIT = 300
|
||||
private readonly DEFAULT_FILE_UPLOAD_PATH = `${__dirname}/../../uploads`
|
||||
|
||||
async load(): Promise<Container> {
|
||||
const env: Env = new Env()
|
||||
@@ -124,22 +127,38 @@ 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_AWS_REGION', true)) {
|
||||
container.bind<AWS.SQS>(TYPES.SQS).toConstantValue(
|
||||
new AWS.SQS({
|
||||
apiVersion: 'latest',
|
||||
region: env.get('SQS_AWS_REGION', true),
|
||||
}),
|
||||
)
|
||||
if (env.get('SQS_QUEUE_URL', true)) {
|
||||
const sqsConfig: AWS.SQS.Types.ClientConfiguration = {
|
||||
apiVersion: 'latest',
|
||||
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))
|
||||
}
|
||||
|
||||
let s3Client = undefined
|
||||
@@ -202,6 +221,11 @@ export class ContainerConfigLoader {
|
||||
.toConstantValue(
|
||||
env.get('MAX_ITEMS_LIMIT', true) ? +env.get('MAX_ITEMS_LIMIT', true) : this.DEFAULT_MAX_ITEMS_LIMIT,
|
||||
)
|
||||
container
|
||||
.bind(TYPES.FILE_UPLOAD_PATH)
|
||||
.toConstantValue(
|
||||
env.get('FILE_UPLOAD_PATH', true) ? env.get('FILE_UPLOAD_PATH', true) : this.DEFAULT_FILE_UPLOAD_PATH,
|
||||
)
|
||||
|
||||
// use cases
|
||||
container.bind<SyncItems>(TYPES.SyncItems).to(SyncItems)
|
||||
@@ -228,6 +252,9 @@ export class ContainerConfigLoader {
|
||||
container
|
||||
.bind<UserContentSizeRecalculationRequestedEventHandler>(TYPES.UserContentSizeRecalculationRequestedEventHandler)
|
||||
.to(UserContentSizeRecalculationRequestedEventHandler)
|
||||
container
|
||||
.bind<ItemRevisionCreationRequestedEventHandler>(TYPES.ItemRevisionCreationRequestedEventHandler)
|
||||
.to(ItemRevisionCreationRequestedEventHandler)
|
||||
|
||||
// Map
|
||||
container
|
||||
@@ -248,7 +275,11 @@ export class ContainerConfigLoader {
|
||||
.to(SyncResponseFactoryResolver)
|
||||
container.bind<AuthHttpServiceInterface>(TYPES.AuthHttpService).to(AuthHttpService)
|
||||
container.bind<ExtensionsHttpServiceInterface>(TYPES.ExtensionsHttpService).to(ExtensionsHttpService)
|
||||
container.bind<ItemBackupServiceInterface>(TYPES.ItemBackupService).to(S3ItemBackupService)
|
||||
if (env.get('S3_AWS_REGION', true)) {
|
||||
container.bind<ItemBackupServiceInterface>(TYPES.ItemBackupService).to(S3ItemBackupService)
|
||||
} else {
|
||||
container.bind<ItemBackupServiceInterface>(TYPES.ItemBackupService).to(FSItemBackupService)
|
||||
}
|
||||
container.bind<RevisionServiceInterface>(TYPES.RevisionService).to(RevisionService)
|
||||
|
||||
if (env.get('SNS_TOPIC_ARN', true)) {
|
||||
@@ -274,6 +305,7 @@ export class ContainerConfigLoader {
|
||||
'USER_CONTENT_SIZE_RECALCULATION_REQUESTED',
|
||||
container.get(TYPES.UserContentSizeRecalculationRequestedEventHandler),
|
||||
],
|
||||
['ITEM_REVISION_CREATION_REQUESTED', container.get(TYPES.ItemRevisionCreationRequestedEventHandler)],
|
||||
])
|
||||
|
||||
if (env.get('SQS_QUEUE_URL', true)) {
|
||||
|
||||
@@ -37,6 +37,7 @@ const TYPES = {
|
||||
VERSION: Symbol.for('VERSION'),
|
||||
CONTENT_SIZE_TRANSFER_LIMIT: Symbol.for('CONTENT_SIZE_TRANSFER_LIMIT'),
|
||||
MAX_ITEMS_LIMIT: Symbol.for('MAX_ITEMS_LIMIT'),
|
||||
FILE_UPLOAD_PATH: Symbol.for('FILE_UPLOAD_PATH'),
|
||||
// use cases
|
||||
SyncItems: Symbol.for('SyncItems'),
|
||||
CheckIntegrity: Symbol.for('CheckIntegrity'),
|
||||
@@ -49,6 +50,7 @@ const TYPES = {
|
||||
EmailBackupRequestedEventHandler: Symbol.for('EmailBackupRequestedEventHandler'),
|
||||
CloudBackupRequestedEventHandler: Symbol.for('CloudBackupRequestedEventHandler'),
|
||||
UserContentSizeRecalculationRequestedEventHandler: Symbol.for('UserContentSizeRecalculationRequestedEventHandler'),
|
||||
ItemRevisionCreationRequestedEventHandler: Symbol.for('ItemRevisionCreationRequestedEventHandler'),
|
||||
// Map
|
||||
RevisionMetadataMap: Symbol.for('RevisionMetadataMap'),
|
||||
// Services
|
||||
|
||||
@@ -6,6 +6,8 @@ import {
|
||||
EmailArchiveExtensionSyncedEvent,
|
||||
EmailBackupAttachmentCreatedEvent,
|
||||
GoogleDriveBackupFailedEvent,
|
||||
ItemDumpedEvent,
|
||||
ItemRevisionCreationRequestedEvent,
|
||||
ItemsSyncedEvent,
|
||||
OneDriveBackupFailedEvent,
|
||||
UserContentSizeRecalculationRequestedEvent,
|
||||
@@ -19,6 +21,40 @@ import { DomainEventFactoryInterface } from './DomainEventFactoryInterface'
|
||||
export class DomainEventFactory implements DomainEventFactoryInterface {
|
||||
constructor(@inject(TYPES.Timer) private timer: TimerInterface) {}
|
||||
|
||||
createItemDumpedEvent(fileDumpPath: string, userUuid: string): ItemDumpedEvent {
|
||||
return {
|
||||
type: 'ITEM_DUMPED',
|
||||
createdAt: this.timer.getUTCDate(),
|
||||
meta: {
|
||||
correlation: {
|
||||
userIdentifier: userUuid,
|
||||
userIdentifierType: 'uuid',
|
||||
},
|
||||
origin: DomainEventService.SyncingServer,
|
||||
},
|
||||
payload: {
|
||||
fileDumpPath,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
createItemRevisionCreationRequested(itemUuid: string, userUuid: string): ItemRevisionCreationRequestedEvent {
|
||||
return {
|
||||
type: 'ITEM_REVISION_CREATION_REQUESTED',
|
||||
createdAt: this.timer.getUTCDate(),
|
||||
meta: {
|
||||
correlation: {
|
||||
userIdentifier: userUuid,
|
||||
userIdentifierType: 'uuid',
|
||||
},
|
||||
origin: DomainEventService.SyncingServer,
|
||||
},
|
||||
payload: {
|
||||
itemUuid,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
createUserContentSizeRecalculationRequestedEvent(userUuid: string): UserContentSizeRecalculationRequestedEvent {
|
||||
return {
|
||||
type: 'USER_CONTENT_SIZE_RECALCULATION_REQUESTED',
|
||||
|
||||
@@ -4,6 +4,8 @@ import {
|
||||
EmailArchiveExtensionSyncedEvent,
|
||||
EmailBackupAttachmentCreatedEvent,
|
||||
GoogleDriveBackupFailedEvent,
|
||||
ItemDumpedEvent,
|
||||
ItemRevisionCreationRequestedEvent,
|
||||
ItemsSyncedEvent,
|
||||
OneDriveBackupFailedEvent,
|
||||
UserContentSizeRecalculationRequestedEvent,
|
||||
@@ -31,4 +33,6 @@ export interface DomainEventFactoryInterface {
|
||||
email: string
|
||||
}): EmailBackupAttachmentCreatedEvent
|
||||
createDuplicateItemSyncedEvent(itemUuid: string, userUuid: string): DuplicateItemSyncedEvent
|
||||
createItemRevisionCreationRequested(itemUuid: string, userUuid: string): ItemRevisionCreationRequestedEvent
|
||||
createItemDumpedEvent(fileDumpPath: string, userUuid: string): ItemDumpedEvent
|
||||
}
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
import 'reflect-metadata'
|
||||
|
||||
import {
|
||||
DomainEventPublisherInterface,
|
||||
DomainEventService,
|
||||
ItemRevisionCreationRequestedEvent,
|
||||
} from '@standardnotes/domain-events'
|
||||
|
||||
import { Item } from '../Item/Item'
|
||||
import { ItemRepositoryInterface } from '../Item/ItemRepositoryInterface'
|
||||
import { ItemRevisionCreationRequestedEventHandler } from './ItemRevisionCreationRequestedEventHandler'
|
||||
import { ItemBackupServiceInterface } from '../Item/ItemBackupServiceInterface'
|
||||
import { DomainEventFactoryInterface } from '../Event/DomainEventFactoryInterface'
|
||||
|
||||
describe('ItemRevisionCreationRequestedEventHandler', () => {
|
||||
let itemRepository: ItemRepositoryInterface
|
||||
let event: ItemRevisionCreationRequestedEvent
|
||||
let item: Item
|
||||
let itemBackupService: ItemBackupServiceInterface
|
||||
let domainEventFactory: DomainEventFactoryInterface
|
||||
let domainEventPublisher: DomainEventPublisherInterface
|
||||
|
||||
const createHandler = () =>
|
||||
new ItemRevisionCreationRequestedEventHandler(
|
||||
itemRepository,
|
||||
itemBackupService,
|
||||
domainEventFactory,
|
||||
domainEventPublisher,
|
||||
)
|
||||
|
||||
beforeEach(() => {
|
||||
item = {
|
||||
uuid: '1-2-3',
|
||||
content: 'test',
|
||||
} as jest.Mocked<Item>
|
||||
|
||||
itemRepository = {} as jest.Mocked<ItemRepositoryInterface>
|
||||
itemRepository.findByUuid = jest.fn().mockReturnValue(item)
|
||||
|
||||
event = {} as jest.Mocked<ItemRevisionCreationRequestedEvent>
|
||||
event.createdAt = new Date(1)
|
||||
event.payload = {
|
||||
itemUuid: '2-3-4',
|
||||
}
|
||||
event.meta = {
|
||||
correlation: {
|
||||
userIdentifier: '1-2-3',
|
||||
userIdentifierType: 'uuid',
|
||||
},
|
||||
origin: DomainEventService.SyncingServer,
|
||||
}
|
||||
|
||||
itemBackupService = {} as jest.Mocked<ItemBackupServiceInterface>
|
||||
itemBackupService.dump = jest.fn().mockReturnValue('foo://bar')
|
||||
|
||||
domainEventFactory = {} as jest.Mocked<DomainEventFactoryInterface>
|
||||
domainEventFactory.createItemDumpedEvent = jest.fn()
|
||||
|
||||
domainEventPublisher = {} as jest.Mocked<DomainEventPublisherInterface>
|
||||
domainEventPublisher.publish = jest.fn()
|
||||
})
|
||||
|
||||
it('should create a revision for an item', async () => {
|
||||
await createHandler().handle(event)
|
||||
|
||||
expect(domainEventPublisher.publish).toHaveBeenCalled()
|
||||
expect(domainEventFactory.createItemDumpedEvent).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('should not create a revision for an item that does not exist', async () => {
|
||||
itemRepository.findByUuid = jest.fn().mockReturnValue(null)
|
||||
|
||||
await createHandler().handle(event)
|
||||
|
||||
expect(domainEventPublisher.publish).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('should not create a revision for an item if the dump was not created', async () => {
|
||||
itemBackupService.dump = jest.fn().mockReturnValue('')
|
||||
|
||||
await createHandler().handle(event)
|
||||
|
||||
expect(domainEventPublisher.publish).not.toHaveBeenCalled()
|
||||
expect(domainEventFactory.createItemDumpedEvent).not.toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,35 @@
|
||||
import {
|
||||
ItemRevisionCreationRequestedEvent,
|
||||
DomainEventHandlerInterface,
|
||||
DomainEventPublisherInterface,
|
||||
} from '@standardnotes/domain-events'
|
||||
import { inject, injectable } from 'inversify'
|
||||
|
||||
import TYPES from '../../Bootstrap/Types'
|
||||
import { DomainEventFactoryInterface } from '../Event/DomainEventFactoryInterface'
|
||||
import { ItemBackupServiceInterface } from '../Item/ItemBackupServiceInterface'
|
||||
import { ItemRepositoryInterface } from '../Item/ItemRepositoryInterface'
|
||||
|
||||
@injectable()
|
||||
export class ItemRevisionCreationRequestedEventHandler implements DomainEventHandlerInterface {
|
||||
constructor(
|
||||
@inject(TYPES.ItemRepository) private itemRepository: ItemRepositoryInterface,
|
||||
@inject(TYPES.ItemBackupService) private itemBackupService: ItemBackupServiceInterface,
|
||||
@inject(TYPES.DomainEventFactory) private domainEventFactory: DomainEventFactoryInterface,
|
||||
@inject(TYPES.DomainEventPublisher) private domainEventPublisher: DomainEventPublisherInterface,
|
||||
) {}
|
||||
|
||||
async handle(event: ItemRevisionCreationRequestedEvent): Promise<void> {
|
||||
const item = await this.itemRepository.findByUuid(event.payload.itemUuid)
|
||||
if (item === null) {
|
||||
return
|
||||
}
|
||||
|
||||
const fileDumpPath = await this.itemBackupService.dump(item)
|
||||
if (fileDumpPath) {
|
||||
await this.domainEventPublisher.publish(
|
||||
this.domainEventFactory.createItemDumpedEvent(fileDumpPath, event.meta.correlation.userIdentifier),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,4 +3,5 @@ import { Item } from './Item'
|
||||
|
||||
export interface ItemBackupServiceInterface {
|
||||
backup(items: Array<Item>, authParams: KeyParamsData): Promise<string>
|
||||
dump(item: Item): Promise<string>
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@ import { ItemHash } from './ItemHash'
|
||||
import { ItemRepositoryInterface } from './ItemRepositoryInterface'
|
||||
import { ItemService } from './ItemService'
|
||||
import { ApiVersion } from '../Api/ApiVersion'
|
||||
import { RevisionServiceInterface } from '../Revision/RevisionServiceInterface'
|
||||
import { DomainEventPublisherInterface } from '@standardnotes/domain-events'
|
||||
import { DomainEventFactoryInterface } from '../Event/DomainEventFactoryInterface'
|
||||
import { Logger } from 'winston'
|
||||
@@ -18,10 +17,10 @@ import { ItemConflict } from './ItemConflict'
|
||||
import { ItemTransferCalculatorInterface } from './ItemTransferCalculatorInterface'
|
||||
import { ProjectorInterface } from '../../Projection/ProjectorInterface'
|
||||
import { ItemProjection } from '../../Projection/ItemProjection'
|
||||
import { RevisionServiceInterface } from '../Revision/RevisionServiceInterface'
|
||||
|
||||
describe('ItemService', () => {
|
||||
let itemRepository: ItemRepositoryInterface
|
||||
let revisionService: RevisionServiceInterface
|
||||
let domainEventPublisher: DomainEventPublisherInterface
|
||||
let domainEventFactory: DomainEventFactoryInterface
|
||||
const revisionFrequency = 300
|
||||
@@ -40,6 +39,7 @@ describe('ItemService', () => {
|
||||
let timeHelper: Timer
|
||||
let itemTransferCalculator: ItemTransferCalculatorInterface
|
||||
let itemProjector: ProjectorInterface<Item, ItemProjection>
|
||||
let revisionService: RevisionServiceInterface
|
||||
const maxItemsSyncLimit = 300
|
||||
|
||||
const createService = () =>
|
||||
@@ -147,6 +147,7 @@ describe('ItemService', () => {
|
||||
|
||||
domainEventFactory = {} as jest.Mocked<DomainEventFactoryInterface>
|
||||
domainEventFactory.createDuplicateItemSyncedEvent = jest.fn()
|
||||
domainEventFactory.createItemRevisionCreationRequested = jest.fn()
|
||||
|
||||
logger = {} as jest.Mocked<Logger>
|
||||
logger.error = jest.fn()
|
||||
@@ -157,7 +158,9 @@ describe('ItemService', () => {
|
||||
itemSaveValidator = {} as jest.Mocked<ItemSaveValidatorInterface>
|
||||
itemSaveValidator.validate = jest.fn().mockReturnValue({ passed: true })
|
||||
|
||||
newItem = {} as jest.Mocked<Item>
|
||||
newItem = {
|
||||
contentType: ContentType.Note,
|
||||
} as jest.Mocked<Item>
|
||||
|
||||
itemFactory = {} as jest.Mocked<ItemFactoryInterface>
|
||||
itemFactory.create = jest.fn().mockReturnValue(newItem)
|
||||
@@ -491,7 +494,8 @@ describe('ItemService', () => {
|
||||
syncToken: 'MjpOYU4=',
|
||||
})
|
||||
|
||||
expect(revisionService.createRevision).toHaveBeenCalledTimes(1)
|
||||
expect(domainEventFactory.createItemRevisionCreationRequested).toHaveBeenCalledTimes(1)
|
||||
expect(domainEventPublisher.publish).toHaveBeenCalledTimes(1)
|
||||
})
|
||||
|
||||
it('should not save new items in read only access mode', async () => {
|
||||
@@ -515,13 +519,15 @@ describe('ItemService', () => {
|
||||
savedItems: [],
|
||||
syncToken: 'MjoxNjE2MTY0NjMzLjI0MTU2OQ==',
|
||||
})
|
||||
|
||||
expect(revisionService.createRevision).toHaveBeenCalledTimes(0)
|
||||
})
|
||||
|
||||
it('should save new items that are duplicates', async () => {
|
||||
itemRepository.findByUuid = jest.fn().mockReturnValue(null)
|
||||
const duplicateItem = { updatedAtTimestamp: 1616164633241570, duplicateOf: '1-2-3' } as jest.Mocked<Item>
|
||||
const duplicateItem = {
|
||||
updatedAtTimestamp: 1616164633241570,
|
||||
duplicateOf: '1-2-3',
|
||||
contentType: ContentType.Note,
|
||||
} as jest.Mocked<Item>
|
||||
itemFactory.create = jest.fn().mockReturnValueOnce(duplicateItem)
|
||||
|
||||
const result = await createService().saveItems({
|
||||
@@ -538,8 +544,8 @@ describe('ItemService', () => {
|
||||
syncToken: 'MjoxNjE2MTY0NjMzLjI0MTU3MQ==',
|
||||
})
|
||||
|
||||
expect(revisionService.createRevision).toHaveBeenCalledTimes(1)
|
||||
expect(domainEventPublisher.publish).toHaveBeenCalledTimes(1)
|
||||
expect(domainEventFactory.createItemRevisionCreationRequested).toHaveBeenCalledTimes(1)
|
||||
expect(domainEventPublisher.publish).toHaveBeenCalledTimes(2)
|
||||
expect(domainEventFactory.createDuplicateItemSyncedEvent).toHaveBeenCalledTimes(1)
|
||||
})
|
||||
|
||||
@@ -933,8 +939,9 @@ describe('ItemService', () => {
|
||||
],
|
||||
syncToken: 'MjoxNjE2MTY0NjMzLjI0MTU2OQ==',
|
||||
})
|
||||
expect(domainEventPublisher.publish).toHaveBeenCalledTimes(1)
|
||||
expect(domainEventPublisher.publish).toHaveBeenCalledTimes(2)
|
||||
expect(domainEventFactory.createDuplicateItemSyncedEvent).toHaveBeenCalledTimes(1)
|
||||
expect(domainEventFactory.createItemRevisionCreationRequested).toHaveBeenCalledTimes(1)
|
||||
})
|
||||
|
||||
it('should skip saving conflicting items and mark them as sync conflicts when saving to database fails', async () => {
|
||||
|
||||
@@ -6,7 +6,6 @@ import { Logger } from 'winston'
|
||||
|
||||
import TYPES from '../../Bootstrap/Types'
|
||||
import { DomainEventFactoryInterface } from '../Event/DomainEventFactoryInterface'
|
||||
import { RevisionServiceInterface } from '../Revision/RevisionServiceInterface'
|
||||
import { GetItemsDTO } from './GetItemsDTO'
|
||||
import { GetItemsResult } from './GetItemsResult'
|
||||
import { Item } from './Item'
|
||||
@@ -23,6 +22,7 @@ import { ConflictType } from '@standardnotes/responses'
|
||||
import { ItemTransferCalculatorInterface } from './ItemTransferCalculatorInterface'
|
||||
import { ProjectorInterface } from '../../Projection/ProjectorInterface'
|
||||
import { ItemProjection } from '../../Projection/ItemProjection'
|
||||
import { RevisionServiceInterface } from '../Revision/RevisionServiceInterface'
|
||||
|
||||
@injectable()
|
||||
export class ItemService implements ItemServiceInterface {
|
||||
@@ -254,6 +254,12 @@ export class ItemService implements ItemServiceInterface {
|
||||
|
||||
if (secondsFromLastUpdate >= this.revisionFrequency) {
|
||||
await this.revisionService.createRevision(savedItem)
|
||||
|
||||
if ([ContentType.Note, ContentType.File].includes(savedItem.contentType as ContentType)) {
|
||||
await this.domainEventPublisher.publish(
|
||||
this.domainEventFactory.createItemRevisionCreationRequested(savedItem.uuid, savedItem.userUuid),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
if (wasMarkedAsDuplicate) {
|
||||
@@ -272,6 +278,12 @@ export class ItemService implements ItemServiceInterface {
|
||||
|
||||
await this.revisionService.createRevision(savedItem)
|
||||
|
||||
if ([ContentType.Note, ContentType.File].includes(savedItem.contentType as ContentType)) {
|
||||
await this.domainEventPublisher.publish(
|
||||
this.domainEventFactory.createItemRevisionCreationRequested(savedItem.uuid, savedItem.userUuid),
|
||||
)
|
||||
}
|
||||
|
||||
if (savedItem.duplicateOf) {
|
||||
await this.domainEventPublisher.publish(
|
||||
this.domainEventFactory.createDuplicateItemSyncedEvent(savedItem.uuid, savedItem.userUuid),
|
||||
|
||||
34
packages/syncing-server/src/Infra/FS/FSItemBackupService.ts
Normal file
34
packages/syncing-server/src/Infra/FS/FSItemBackupService.ts
Normal file
@@ -0,0 +1,34 @@
|
||||
import { KeyParamsData } from '@standardnotes/responses'
|
||||
import { promises } from 'fs'
|
||||
import * as uuid from 'uuid'
|
||||
import { inject, injectable } from 'inversify'
|
||||
|
||||
import TYPES from '../../Bootstrap/Types'
|
||||
import { Item } from '../../Domain/Item/Item'
|
||||
import { ItemBackupServiceInterface } from '../../Domain/Item/ItemBackupServiceInterface'
|
||||
import { ItemProjection } from '../../Projection/ItemProjection'
|
||||
import { ProjectorInterface } from '../../Projection/ProjectorInterface'
|
||||
|
||||
@injectable()
|
||||
export class FSItemBackupService implements ItemBackupServiceInterface {
|
||||
constructor(
|
||||
@inject(TYPES.FILE_UPLOAD_PATH) private fileUploadPath: string,
|
||||
@inject(TYPES.ItemProjector) private itemProjector: ProjectorInterface<Item, ItemProjection>,
|
||||
) {}
|
||||
|
||||
async backup(_items: Item[], _authParams: KeyParamsData): Promise<string> {
|
||||
throw new Error('Method not implemented.')
|
||||
}
|
||||
|
||||
async dump(item: Item): Promise<string> {
|
||||
const contents = JSON.stringify({
|
||||
item: await this.itemProjector.projectCustom('dump', item),
|
||||
})
|
||||
|
||||
const path = `${this.fileUploadPath}/dumps/${uuid.v4()}`
|
||||
|
||||
await promises.writeFile(path, contents)
|
||||
|
||||
return path
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user