mirror of
https://github.com/standardnotes/server
synced 2026-01-31 02:01:12 -05:00
Compare commits
18 Commits
@standardn
...
@standardn
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d73c9833ab | ||
|
|
1841597405 | ||
|
|
8003e5ce43 | ||
|
|
d0023a6c92 | ||
|
|
a9293f6ce1 | ||
|
|
58c5b586a9 | ||
|
|
21d224da22 | ||
|
|
43d957c8d3 | ||
|
|
917fad510a | ||
|
|
269eef7ef3 | ||
|
|
b811f4527b | ||
|
|
67378e4535 | ||
|
|
dad9033482 | ||
|
|
32c8333564 | ||
|
|
4d074e7f9a | ||
|
|
c61b615da6 | ||
|
|
fba6cfd62c | ||
|
|
1ba5ba5ff6 |
@@ -327,7 +327,7 @@ endif
|
||||
|
||||
quiet_cmd_regen_makefile = ACTION Regenerating $@
|
||||
cmd_regen_makefile = cd $(srcdir); /Users/karolsojko/workspace/server/.yarn/unplugged/node-gyp-npm-9.0.0-0eccfca4d1/node_modules/node-gyp/gyp/gyp_main.py -fmake --ignore-environment "-Dlibrary=shared_library" "-Dvisibility=default" "-Dnode_root_dir=/Users/karolsojko/Library/Caches/node-gyp/16.15.1" "-Dnode_gyp_dir=/Users/karolsojko/workspace/server/.yarn/unplugged/node-gyp-npm-9.0.0-0eccfca4d1/node_modules/node-gyp" "-Dnode_lib_file=/Users/karolsojko/Library/Caches/node-gyp/16.15.1/<(target_arch)/node.lib" "-Dmodule_root_dir=/Users/karolsojko/workspace/server/.yarn/unplugged/@newrelic-native-metrics-npm-9.0.0-590d2e713a/node_modules/@newrelic/native-metrics" "-Dnode_engine=v8" "--depth=." "-Goutput_dir=." "--generator-output=build" -I/Users/karolsojko/workspace/server/.yarn/unplugged/@newrelic-native-metrics-npm-9.0.0-590d2e713a/node_modules/@newrelic/native-metrics/build/config.gypi -I/Users/karolsojko/workspace/server/.yarn/unplugged/node-gyp-npm-9.0.0-0eccfca4d1/node_modules/node-gyp/addon.gypi -I/Users/karolsojko/Library/Caches/node-gyp/16.15.1/include/node/common.gypi "--toplevel-dir=." binding.gyp
|
||||
Makefile: $(srcdir)/binding.gyp $(srcdir)/../../../../../../../../Library/Caches/node-gyp/16.15.1/include/node/common.gypi $(srcdir)/build/config.gypi $(srcdir)/../../../../node-gyp-npm-9.0.0-0eccfca4d1/node_modules/node-gyp/addon.gypi
|
||||
Makefile: $(srcdir)/binding.gyp $(srcdir)/../../../../node-gyp-npm-9.0.0-0eccfca4d1/node_modules/node-gyp/addon.gypi $(srcdir)/../../../../../../../../Library/Caches/node-gyp/16.15.1/include/node/common.gypi $(srcdir)/build/config.gypi
|
||||
$(call do_cmd,regen_makefile)
|
||||
|
||||
# "all" is a concatenation of the "all" targets from all the included
|
||||
|
||||
Binary file not shown.
BIN
.yarn/unplugged/node-gyp-npm-9.0.0-0eccfca4d1/node_modules/node-gyp/gyp/pylib/gyp/__pycache__/MSVSUtil.cpython-37.pyc
generated
vendored
Normal file
BIN
.yarn/unplugged/node-gyp-npm-9.0.0-0eccfca4d1/node_modules/node-gyp/gyp/pylib/gyp/__pycache__/MSVSUtil.cpython-37.pyc
generated
vendored
Normal file
Binary file not shown.
BIN
.yarn/unplugged/node-gyp-npm-9.0.0-0eccfca4d1/node_modules/node-gyp/gyp/pylib/gyp/__pycache__/MSVSVersion.cpython-37.pyc
generated
vendored
Normal file
BIN
.yarn/unplugged/node-gyp-npm-9.0.0-0eccfca4d1/node_modules/node-gyp/gyp/pylib/gyp/__pycache__/MSVSVersion.cpython-37.pyc
generated
vendored
Normal file
Binary file not shown.
BIN
.yarn/unplugged/node-gyp-npm-9.0.0-0eccfca4d1/node_modules/node-gyp/gyp/pylib/gyp/__pycache__/__init__.cpython-37.pyc
generated
vendored
Normal file
BIN
.yarn/unplugged/node-gyp-npm-9.0.0-0eccfca4d1/node_modules/node-gyp/gyp/pylib/gyp/__pycache__/__init__.cpython-37.pyc
generated
vendored
Normal file
Binary file not shown.
BIN
.yarn/unplugged/node-gyp-npm-9.0.0-0eccfca4d1/node_modules/node-gyp/gyp/pylib/gyp/__pycache__/common.cpython-37.pyc
generated
vendored
Normal file
BIN
.yarn/unplugged/node-gyp-npm-9.0.0-0eccfca4d1/node_modules/node-gyp/gyp/pylib/gyp/__pycache__/common.cpython-37.pyc
generated
vendored
Normal file
Binary file not shown.
BIN
.yarn/unplugged/node-gyp-npm-9.0.0-0eccfca4d1/node_modules/node-gyp/gyp/pylib/gyp/__pycache__/input.cpython-37.pyc
generated
vendored
Normal file
BIN
.yarn/unplugged/node-gyp-npm-9.0.0-0eccfca4d1/node_modules/node-gyp/gyp/pylib/gyp/__pycache__/input.cpython-37.pyc
generated
vendored
Normal file
Binary file not shown.
BIN
.yarn/unplugged/node-gyp-npm-9.0.0-0eccfca4d1/node_modules/node-gyp/gyp/pylib/gyp/__pycache__/msvs_emulation.cpython-37.pyc
generated
vendored
Normal file
BIN
.yarn/unplugged/node-gyp-npm-9.0.0-0eccfca4d1/node_modules/node-gyp/gyp/pylib/gyp/__pycache__/msvs_emulation.cpython-37.pyc
generated
vendored
Normal file
Binary file not shown.
BIN
.yarn/unplugged/node-gyp-npm-9.0.0-0eccfca4d1/node_modules/node-gyp/gyp/pylib/gyp/__pycache__/ninja_syntax.cpython-37.pyc
generated
vendored
Normal file
BIN
.yarn/unplugged/node-gyp-npm-9.0.0-0eccfca4d1/node_modules/node-gyp/gyp/pylib/gyp/__pycache__/ninja_syntax.cpython-37.pyc
generated
vendored
Normal file
Binary file not shown.
BIN
.yarn/unplugged/node-gyp-npm-9.0.0-0eccfca4d1/node_modules/node-gyp/gyp/pylib/gyp/__pycache__/simple_copy.cpython-37.pyc
generated
vendored
Normal file
BIN
.yarn/unplugged/node-gyp-npm-9.0.0-0eccfca4d1/node_modules/node-gyp/gyp/pylib/gyp/__pycache__/simple_copy.cpython-37.pyc
generated
vendored
Normal file
Binary file not shown.
BIN
.yarn/unplugged/node-gyp-npm-9.0.0-0eccfca4d1/node_modules/node-gyp/gyp/pylib/gyp/__pycache__/xcode_emulation.cpython-37.pyc
generated
vendored
Normal file
BIN
.yarn/unplugged/node-gyp-npm-9.0.0-0eccfca4d1/node_modules/node-gyp/gyp/pylib/gyp/__pycache__/xcode_emulation.cpython-37.pyc
generated
vendored
Normal file
Binary file not shown.
BIN
.yarn/unplugged/node-gyp-npm-9.0.0-0eccfca4d1/node_modules/node-gyp/gyp/pylib/gyp/__pycache__/xcode_ninja.cpython-37.pyc
generated
vendored
Normal file
BIN
.yarn/unplugged/node-gyp-npm-9.0.0-0eccfca4d1/node_modules/node-gyp/gyp/pylib/gyp/__pycache__/xcode_ninja.cpython-37.pyc
generated
vendored
Normal file
Binary file not shown.
BIN
.yarn/unplugged/node-gyp-npm-9.0.0-0eccfca4d1/node_modules/node-gyp/gyp/pylib/gyp/__pycache__/xcodeproj_file.cpython-37.pyc
generated
vendored
Normal file
BIN
.yarn/unplugged/node-gyp-npm-9.0.0-0eccfca4d1/node_modules/node-gyp/gyp/pylib/gyp/__pycache__/xcodeproj_file.cpython-37.pyc
generated
vendored
Normal file
Binary file not shown.
BIN
.yarn/unplugged/node-gyp-npm-9.0.0-0eccfca4d1/node_modules/node-gyp/gyp/pylib/gyp/generator/__pycache__/__init__.cpython-37.pyc
generated
vendored
Normal file
BIN
.yarn/unplugged/node-gyp-npm-9.0.0-0eccfca4d1/node_modules/node-gyp/gyp/pylib/gyp/generator/__pycache__/__init__.cpython-37.pyc
generated
vendored
Normal file
Binary file not shown.
BIN
.yarn/unplugged/node-gyp-npm-9.0.0-0eccfca4d1/node_modules/node-gyp/gyp/pylib/gyp/generator/__pycache__/make.cpython-37.pyc
generated
vendored
Normal file
BIN
.yarn/unplugged/node-gyp-npm-9.0.0-0eccfca4d1/node_modules/node-gyp/gyp/pylib/gyp/generator/__pycache__/make.cpython-37.pyc
generated
vendored
Normal file
Binary file not shown.
BIN
.yarn/unplugged/node-gyp-npm-9.0.0-0eccfca4d1/node_modules/node-gyp/gyp/pylib/gyp/generator/__pycache__/ninja.cpython-37.pyc
generated
vendored
Normal file
BIN
.yarn/unplugged/node-gyp-npm-9.0.0-0eccfca4d1/node_modules/node-gyp/gyp/pylib/gyp/generator/__pycache__/ninja.cpython-37.pyc
generated
vendored
Normal file
Binary file not shown.
BIN
.yarn/unplugged/node-gyp-npm-9.0.0-0eccfca4d1/node_modules/node-gyp/gyp/pylib/gyp/generator/__pycache__/xcode.cpython-37.pyc
generated
vendored
Normal file
BIN
.yarn/unplugged/node-gyp-npm-9.0.0-0eccfca4d1/node_modules/node-gyp/gyp/pylib/gyp/generator/__pycache__/xcode.cpython-37.pyc
generated
vendored
Normal file
Binary file not shown.
@@ -3,6 +3,36 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [1.18.0](https://github.com/standardnotes/server/compare/@standardnotes/analytics@1.17.2...@standardnotes/analytics@1.18.0) (2022-08-15)
|
||||
|
||||
### Features
|
||||
|
||||
* **auth:** add payment failed event handler ([58c5b58](https://github.com/standardnotes/server/commit/58c5b586a904cf1fd179cc28783a6ae7da688063))
|
||||
|
||||
## [1.17.2](https://github.com/standardnotes/server/compare/@standardnotes/analytics@1.17.1...@standardnotes/analytics@1.17.2) (2022-08-15)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **analytics:** quarterly calculations over time ([43d957c](https://github.com/standardnotes/server/commit/43d957c8d382b501e8101b51e30b33f18a4dd871))
|
||||
|
||||
## [1.17.1](https://github.com/standardnotes/server/compare/@standardnotes/analytics@1.17.0...@standardnotes/analytics@1.17.1) (2022-08-15)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **analytics:** expire bitop keys ([269eef7](https://github.com/standardnotes/server/commit/269eef7ef31343390c6909350bf1bfede94c24b3))
|
||||
|
||||
# [1.17.0](https://github.com/standardnotes/server/compare/@standardnotes/analytics@1.16.0...@standardnotes/analytics@1.17.0) (2022-08-15)
|
||||
|
||||
### Features
|
||||
|
||||
* **api-gateway:** add quarterly analytics ([67378e4](https://github.com/standardnotes/server/commit/67378e4535ef2760cfe3fe27256ffe117ee11a71))
|
||||
|
||||
# [1.16.0](https://github.com/standardnotes/server/compare/@standardnotes/analytics@1.15.0...@standardnotes/analytics@1.16.0) (2022-08-15)
|
||||
|
||||
### Features
|
||||
|
||||
* **analytics:** add calculating quarterly stats ([32c8333](https://github.com/standardnotes/server/commit/32c8333564dea742b28ccc6f09e5fa33dd1f7af2))
|
||||
|
||||
# [1.15.0](https://github.com/standardnotes/server/compare/@standardnotes/analytics@1.14.0...@standardnotes/analytics@1.15.0) (2022-08-11)
|
||||
|
||||
### Features
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/analytics",
|
||||
"version": "1.15.0",
|
||||
"version": "1.18.0",
|
||||
"engines": {
|
||||
"node": ">=14.0.0 <17.0.0"
|
||||
},
|
||||
|
||||
@@ -11,4 +11,5 @@ export enum AnalyticsActivity {
|
||||
EmailUnbackedUpData = 'email-unbacked-up-data',
|
||||
EmailBackup = 'email-backup',
|
||||
LimitedDiscountOfferPurchased = 'limited-discount-offer-purchased',
|
||||
PaymentFailed = 'payment-failed',
|
||||
}
|
||||
|
||||
@@ -8,4 +8,8 @@ export enum Period {
|
||||
ThisMonth,
|
||||
LastMonth,
|
||||
Last30Days,
|
||||
Q1ThisYear,
|
||||
Q2ThisYear,
|
||||
Q3ThisYear,
|
||||
Q4ThisYear,
|
||||
}
|
||||
|
||||
@@ -48,6 +48,22 @@ describe('PeriodKeyGenerator', () => {
|
||||
])
|
||||
})
|
||||
|
||||
it('should generate period keys for Q1', () => {
|
||||
expect(createGenerator().getDiscretePeriodKeys(Period.Q1ThisYear)).toEqual(['2022-1', '2022-2', '2022-3'])
|
||||
})
|
||||
|
||||
it('should generate period keys for Q2', () => {
|
||||
expect(createGenerator().getDiscretePeriodKeys(Period.Q2ThisYear)).toEqual(['2022-4', '2022-5', '2022-6'])
|
||||
})
|
||||
|
||||
it('should generate period keys for Q3', () => {
|
||||
expect(createGenerator().getDiscretePeriodKeys(Period.Q3ThisYear)).toEqual(['2022-7', '2022-8', '2022-9'])
|
||||
})
|
||||
|
||||
it('should generate period keys for Q4', () => {
|
||||
expect(createGenerator().getDiscretePeriodKeys(Period.Q4ThisYear)).toEqual(['2022-10', '2022-11', '2022-12'])
|
||||
})
|
||||
|
||||
it('should generate a period key for today', () => {
|
||||
expect(createGenerator().getPeriodKey(Period.Today)).toEqual('2022-5-24')
|
||||
})
|
||||
|
||||
@@ -12,6 +12,14 @@ export class PeriodKeyGenerator implements PeriodKeyGeneratorInterface {
|
||||
}
|
||||
|
||||
return periodKeys
|
||||
case Period.Q1ThisYear:
|
||||
return this.generateMonthlyKeysRange(0, 3)
|
||||
case Period.Q2ThisYear:
|
||||
return this.generateMonthlyKeysRange(3, 6)
|
||||
case Period.Q3ThisYear:
|
||||
return this.generateMonthlyKeysRange(6, 9)
|
||||
case Period.Q4ThisYear:
|
||||
return this.generateMonthlyKeysRange(9, 12)
|
||||
default:
|
||||
throw new Error(`Unsuporrted period: ${period}`)
|
||||
}
|
||||
@@ -115,4 +123,16 @@ export class PeriodKeyGenerator implements PeriodKeyGeneratorInterface {
|
||||
|
||||
return yesterday
|
||||
}
|
||||
|
||||
private generateMonthlyKeysRange(startingMonthIndex: number, endingMonthIndex: number): string[] {
|
||||
const today = new Date()
|
||||
const keys = []
|
||||
for (let i = startingMonthIndex; i < endingMonthIndex; i++) {
|
||||
today.setMonth(i)
|
||||
today.setDate(1)
|
||||
keys.push(this.getMonthlyKey(today))
|
||||
}
|
||||
|
||||
return keys
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ describe('RedisAnalyticsStore', () => {
|
||||
redisClient.setbit = jest.fn()
|
||||
redisClient.getbit = jest.fn().mockReturnValue(1)
|
||||
redisClient.bitop = jest.fn()
|
||||
redisClient.expire = jest.fn()
|
||||
|
||||
periodKeyGenerator = {} as jest.Mocked<PeriodKeyGeneratorInterface>
|
||||
periodKeyGenerator.getPeriodKey = jest.fn().mockReturnValue('period-key')
|
||||
@@ -48,6 +49,17 @@ describe('RedisAnalyticsStore', () => {
|
||||
expect(redisClient.bitcount).toHaveBeenCalledWith('bitmap:action:editing-items:timespan:2022-4-24-2022-4-26')
|
||||
})
|
||||
|
||||
it('should not calculate total count over time of activities if period is unsupported', async () => {
|
||||
let caughtError = null
|
||||
try {
|
||||
await createStore().calculateActivityTotalCountOverTime(AnalyticsActivity.EditingItems, Period.LastWeek)
|
||||
} catch (error) {
|
||||
caughtError = error
|
||||
}
|
||||
|
||||
expect(caughtError).not.toBeNull()
|
||||
})
|
||||
|
||||
it('should calculate total count changes of activities', async () => {
|
||||
periodKeyGenerator.getDiscretePeriodKeys = jest.fn().mockReturnValue(['2022-4-24', '2022-4-25', '2022-4-26'])
|
||||
|
||||
|
||||
@@ -9,17 +9,24 @@ export class RedisAnalyticsStore implements AnalyticsStoreInterface {
|
||||
constructor(private periodKeyGenerator: PeriodKeyGeneratorInterface, private redisClient: IORedis.Redis) {}
|
||||
|
||||
async calculateActivityTotalCountOverTime(activity: AnalyticsActivity, period: Period): Promise<number> {
|
||||
if (period !== Period.Last30Days) {
|
||||
if (
|
||||
![Period.Last30Days, Period.Q1ThisYear, Period.Q2ThisYear, Period.Q3ThisYear, Period.Q4ThisYear].includes(period)
|
||||
) {
|
||||
throw new Error(`Unsuporrted period: ${period}`)
|
||||
}
|
||||
|
||||
const periodKeys = this.periodKeyGenerator.getDiscretePeriodKeys(Period.Last30Days)
|
||||
const periodKeys = this.periodKeyGenerator.getDiscretePeriodKeys(period)
|
||||
await this.redisClient.bitop(
|
||||
'OR',
|
||||
`bitmap:action:${activity}:timespan:${periodKeys[0]}-${periodKeys[periodKeys.length - 1]}`,
|
||||
...periodKeys.map((p) => `bitmap:action:${activity}:timespan:${p}`),
|
||||
)
|
||||
|
||||
await this.redisClient.expire(
|
||||
`bitmap:action:${activity}:timespan:${periodKeys[0]}-${periodKeys[periodKeys.length - 1]}`,
|
||||
3600,
|
||||
)
|
||||
|
||||
return this.redisClient.bitcount(
|
||||
`bitmap:action:${activity}:timespan:${periodKeys[0]}-${periodKeys[periodKeys.length - 1]}`,
|
||||
)
|
||||
@@ -29,11 +36,13 @@ export class RedisAnalyticsStore implements AnalyticsStoreInterface {
|
||||
activity: AnalyticsActivity,
|
||||
period: Period,
|
||||
): Promise<Array<{ periodKey: string; totalCount: number }>> {
|
||||
if (period !== Period.Last30Days) {
|
||||
if (
|
||||
![Period.Last30Days, Period.Q1ThisYear, Period.Q2ThisYear, Period.Q3ThisYear, Period.Q4ThisYear].includes(period)
|
||||
) {
|
||||
throw new Error(`Unsuporrted period: ${period}`)
|
||||
}
|
||||
|
||||
const periodKeys = this.periodKeyGenerator.getDiscretePeriodKeys(Period.Last30Days)
|
||||
const periodKeys = this.periodKeyGenerator.getDiscretePeriodKeys(period)
|
||||
const counts = []
|
||||
for (const periodKey of periodKeys) {
|
||||
counts.push({
|
||||
@@ -103,6 +112,8 @@ export class RedisAnalyticsStore implements AnalyticsStoreInterface {
|
||||
`bitmap:action:${activity}:timespan:${subsequentPeriodKey}`,
|
||||
)
|
||||
|
||||
await this.redisClient.expire(diffKey, 3600)
|
||||
|
||||
const retainedTotalInActivity = await this.redisClient.bitcount(diffKey)
|
||||
|
||||
const initialTotalInActivity = await this.redisClient.bitcount(
|
||||
|
||||
@@ -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.15.1](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.15.0...@standardnotes/api-gateway@1.15.1) (2022-08-15)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/api-gateway
|
||||
|
||||
# [1.15.0](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.14.3...@standardnotes/api-gateway@1.15.0) (2022-08-15)
|
||||
|
||||
### Features
|
||||
|
||||
* **api-gateway:** add gathering analytics for failed payments ([d0023a6](https://github.com/standardnotes/api-gateway/commit/d0023a6c92756c81b8daa9089d38141b6cd4fe48))
|
||||
|
||||
## [1.14.3](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.14.2...@standardnotes/api-gateway@1.14.3) (2022-08-15)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/api-gateway
|
||||
|
||||
## [1.14.2](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.14.1...@standardnotes/api-gateway@1.14.2) (2022-08-15)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/api-gateway
|
||||
|
||||
## [1.14.1](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.14.0...@standardnotes/api-gateway@1.14.1) (2022-08-15)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/api-gateway
|
||||
|
||||
# [1.14.0](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.13.1...@standardnotes/api-gateway@1.14.0) (2022-08-15)
|
||||
|
||||
### Features
|
||||
|
||||
* **api-gateway:** add quarterly analytics ([67378e4](https://github.com/standardnotes/api-gateway/commit/67378e4535ef2760cfe3fe27256ffe117ee11a71))
|
||||
|
||||
## [1.13.1](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.13.0...@standardnotes/api-gateway@1.13.1) (2022-08-15)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/api-gateway
|
||||
|
||||
# [1.13.0](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.12.0...@standardnotes/api-gateway@1.13.0) (2022-08-11)
|
||||
|
||||
### Features
|
||||
|
||||
@@ -19,6 +19,65 @@ const requestReport = async (
|
||||
statisticsStore: StatisticsStoreInterface,
|
||||
domainEventPublisher: DomainEventPublisherInterface,
|
||||
): Promise<void> => {
|
||||
const analyticsOverTime = []
|
||||
|
||||
const thirtyDaysAnalyticsNames = [
|
||||
AnalyticsActivity.GeneralActivity,
|
||||
AnalyticsActivity.EditingItems,
|
||||
AnalyticsActivity.SubscriptionPurchased,
|
||||
AnalyticsActivity.Register,
|
||||
AnalyticsActivity.SubscriptionRenewed,
|
||||
AnalyticsActivity.DeleteAccount,
|
||||
AnalyticsActivity.SubscriptionCancelled,
|
||||
AnalyticsActivity.SubscriptionRefunded,
|
||||
]
|
||||
|
||||
for (const analyticsName of thirtyDaysAnalyticsNames) {
|
||||
analyticsOverTime.push({
|
||||
name: analyticsName,
|
||||
period: Period.Last30Days,
|
||||
counts: await analyticsStore.calculateActivityChangesTotalCount(analyticsName, Period.Last30Days),
|
||||
totalCount: await analyticsStore.calculateActivityTotalCountOverTime(analyticsName, Period.Last30Days),
|
||||
})
|
||||
}
|
||||
|
||||
const quarterlyAnalyticsNames = [
|
||||
AnalyticsActivity.Register,
|
||||
AnalyticsActivity.SubscriptionPurchased,
|
||||
AnalyticsActivity.SubscriptionRenewed,
|
||||
]
|
||||
|
||||
for (const analyticsName of quarterlyAnalyticsNames) {
|
||||
for (const period of [Period.Q1ThisYear, Period.Q2ThisYear, Period.Q3ThisYear, Period.Q4ThisYear]) {
|
||||
analyticsOverTime.push({
|
||||
name: analyticsName,
|
||||
period: period,
|
||||
counts: await analyticsStore.calculateActivityChangesTotalCount(analyticsName, period),
|
||||
totalCount: await analyticsStore.calculateActivityTotalCountOverTime(analyticsName, period),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const yesterdayActivityStatistics = []
|
||||
const yesterdayActivityNames = [
|
||||
AnalyticsActivity.EditingItems,
|
||||
AnalyticsActivity.LimitedDiscountOfferPurchased,
|
||||
AnalyticsActivity.GeneralActivity,
|
||||
AnalyticsActivity.PaymentFailed,
|
||||
]
|
||||
|
||||
for (const activityName of yesterdayActivityNames) {
|
||||
yesterdayActivityStatistics.push({
|
||||
name: activityName,
|
||||
retention: await analyticsStore.calculateActivityRetention(
|
||||
activityName,
|
||||
Period.DayBeforeYesterday,
|
||||
Period.Yesterday,
|
||||
),
|
||||
totalCount: await analyticsStore.calculateActivityTotalCount(activityName, Period.Yesterday),
|
||||
})
|
||||
}
|
||||
|
||||
const event: DailyAnalyticsReportGeneratedEvent = {
|
||||
type: 'DAILY_ANALYTICS_REPORT_GENERATED',
|
||||
createdAt: new Date(),
|
||||
@@ -33,138 +92,8 @@ const requestReport = async (
|
||||
applicationStatistics: await statisticsStore.getYesterdayApplicationUsage(),
|
||||
snjsStatistics: await statisticsStore.getYesterdaySNJSUsage(),
|
||||
outOfSyncIncidents: await statisticsStore.getYesterdayOutOfSyncIncidents(),
|
||||
activityStatistics: [
|
||||
{
|
||||
name: AnalyticsActivity.EditingItems,
|
||||
retention: await analyticsStore.calculateActivityRetention(
|
||||
AnalyticsActivity.EditingItems,
|
||||
Period.DayBeforeYesterday,
|
||||
Period.Yesterday,
|
||||
),
|
||||
totalCount: await analyticsStore.calculateActivityTotalCount(
|
||||
AnalyticsActivity.EditingItems,
|
||||
Period.Yesterday,
|
||||
),
|
||||
},
|
||||
{
|
||||
name: AnalyticsActivity.LimitedDiscountOfferPurchased,
|
||||
retention: 0,
|
||||
totalCount: await analyticsStore.calculateActivityTotalCount(
|
||||
AnalyticsActivity.LimitedDiscountOfferPurchased,
|
||||
Period.Yesterday,
|
||||
),
|
||||
},
|
||||
{
|
||||
name: AnalyticsActivity.GeneralActivity,
|
||||
retention: await analyticsStore.calculateActivityRetention(
|
||||
AnalyticsActivity.GeneralActivity,
|
||||
Period.DayBeforeYesterday,
|
||||
Period.Yesterday,
|
||||
),
|
||||
totalCount: await analyticsStore.calculateActivityTotalCount(
|
||||
AnalyticsActivity.GeneralActivity,
|
||||
Period.Yesterday,
|
||||
),
|
||||
},
|
||||
],
|
||||
activityStatisticsOverTime: [
|
||||
{
|
||||
name: AnalyticsActivity.GeneralActivity,
|
||||
period: Period.Last30Days,
|
||||
counts: await analyticsStore.calculateActivityChangesTotalCount(
|
||||
AnalyticsActivity.GeneralActivity,
|
||||
Period.Last30Days,
|
||||
),
|
||||
totalCount: await analyticsStore.calculateActivityTotalCountOverTime(
|
||||
AnalyticsActivity.GeneralActivity,
|
||||
Period.Last30Days,
|
||||
),
|
||||
},
|
||||
{
|
||||
name: AnalyticsActivity.EditingItems,
|
||||
period: Period.Last30Days,
|
||||
counts: await analyticsStore.calculateActivityChangesTotalCount(
|
||||
AnalyticsActivity.EditingItems,
|
||||
Period.Last30Days,
|
||||
),
|
||||
totalCount: await analyticsStore.calculateActivityTotalCountOverTime(
|
||||
AnalyticsActivity.EditingItems,
|
||||
Period.Last30Days,
|
||||
),
|
||||
},
|
||||
{
|
||||
name: AnalyticsActivity.SubscriptionPurchased,
|
||||
period: Period.Last30Days,
|
||||
counts: await analyticsStore.calculateActivityChangesTotalCount(
|
||||
AnalyticsActivity.SubscriptionPurchased,
|
||||
Period.Last30Days,
|
||||
),
|
||||
totalCount: await analyticsStore.calculateActivityTotalCountOverTime(
|
||||
AnalyticsActivity.SubscriptionPurchased,
|
||||
Period.Last30Days,
|
||||
),
|
||||
},
|
||||
{
|
||||
name: AnalyticsActivity.Register,
|
||||
period: Period.Last30Days,
|
||||
counts: await analyticsStore.calculateActivityChangesTotalCount(
|
||||
AnalyticsActivity.Register,
|
||||
Period.Last30Days,
|
||||
),
|
||||
totalCount: await analyticsStore.calculateActivityTotalCountOverTime(
|
||||
AnalyticsActivity.Register,
|
||||
Period.Last30Days,
|
||||
),
|
||||
},
|
||||
{
|
||||
name: AnalyticsActivity.SubscriptionRenewed,
|
||||
period: Period.Last30Days,
|
||||
counts: await analyticsStore.calculateActivityChangesTotalCount(
|
||||
AnalyticsActivity.SubscriptionRenewed,
|
||||
Period.Last30Days,
|
||||
),
|
||||
totalCount: await analyticsStore.calculateActivityTotalCountOverTime(
|
||||
AnalyticsActivity.SubscriptionRenewed,
|
||||
Period.Last30Days,
|
||||
),
|
||||
},
|
||||
{
|
||||
name: AnalyticsActivity.DeleteAccount,
|
||||
period: Period.Last30Days,
|
||||
counts: await analyticsStore.calculateActivityChangesTotalCount(
|
||||
AnalyticsActivity.DeleteAccount,
|
||||
Period.Last30Days,
|
||||
),
|
||||
totalCount: await analyticsStore.calculateActivityTotalCountOverTime(
|
||||
AnalyticsActivity.DeleteAccount,
|
||||
Period.Last30Days,
|
||||
),
|
||||
},
|
||||
{
|
||||
name: AnalyticsActivity.SubscriptionCancelled,
|
||||
period: Period.Last30Days,
|
||||
counts: await analyticsStore.calculateActivityChangesTotalCount(
|
||||
AnalyticsActivity.SubscriptionCancelled,
|
||||
Period.Last30Days,
|
||||
),
|
||||
totalCount: await analyticsStore.calculateActivityTotalCountOverTime(
|
||||
AnalyticsActivity.SubscriptionCancelled,
|
||||
Period.Last30Days,
|
||||
),
|
||||
},
|
||||
{
|
||||
name: AnalyticsActivity.SubscriptionRefunded,
|
||||
period: Period.Last30Days,
|
||||
counts: await analyticsStore.calculateActivityChangesTotalCount(
|
||||
AnalyticsActivity.SubscriptionRefunded,
|
||||
Period.Last30Days,
|
||||
),
|
||||
totalCount: await analyticsStore.calculateActivityTotalCountOverTime(
|
||||
AnalyticsActivity.SubscriptionRefunded,
|
||||
Period.Last30Days,
|
||||
),
|
||||
},
|
||||
],
|
||||
activityStatistics: yesterdayActivityStatistics,
|
||||
activityStatisticsOverTime: analyticsOverTime,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/api-gateway",
|
||||
"version": "1.13.0",
|
||||
"version": "1.15.1",
|
||||
"engines": {
|
||||
"node": ">=16.0.0 <17.0.0"
|
||||
},
|
||||
|
||||
@@ -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.19.1](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.19.0...@standardnotes/auth-server@1.19.1) (2022-08-15)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/auth-server
|
||||
|
||||
# [1.19.0](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.18.4...@standardnotes/auth-server@1.19.0) (2022-08-15)
|
||||
|
||||
### Features
|
||||
|
||||
* **auth:** add payment failed event handler ([58c5b58](https://github.com/standardnotes/server/commit/58c5b586a904cf1fd179cc28783a6ae7da688063))
|
||||
|
||||
## [1.18.4](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.18.3...@standardnotes/auth-server@1.18.4) (2022-08-15)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/auth-server
|
||||
|
||||
## [1.18.3](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.18.2...@standardnotes/auth-server@1.18.3) (2022-08-15)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/auth-server
|
||||
|
||||
## [1.18.2](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.18.1...@standardnotes/auth-server@1.18.2) (2022-08-15)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/auth-server
|
||||
|
||||
## [1.18.1](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.18.0...@standardnotes/auth-server@1.18.1) (2022-08-15)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/auth-server
|
||||
|
||||
# [1.18.0](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.17.0...@standardnotes/auth-server@1.18.0) (2022-08-12)
|
||||
|
||||
### Features
|
||||
|
||||
* **auth:** add endpoint for generating offline subscription tokens for admin panel ([c61b615](https://github.com/standardnotes/server/commit/c61b615da6e1d4556e60e73d7414a80e8b331fca))
|
||||
|
||||
# [1.17.0](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.16.2...@standardnotes/auth-server@1.17.0) (2022-08-11)
|
||||
|
||||
### Features
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/auth-server",
|
||||
"version": "1.17.0",
|
||||
"version": "1.19.1",
|
||||
"engines": {
|
||||
"node": ">=16.0.0 <17.0.0"
|
||||
},
|
||||
|
||||
@@ -191,6 +191,7 @@ import { AuthController } from '../Controller/AuthController'
|
||||
import { VerifyPredicate } from '../Domain/UseCase/VerifyPredicate/VerifyPredicate'
|
||||
import { PredicateVerificationRequestedEventHandler } from '../Domain/Handler/PredicateVerificationRequestedEventHandler'
|
||||
import { MuteMarketingEmails } from '../Domain/UseCase/MuteMarketingEmails/MuteMarketingEmails'
|
||||
import { PaymentFailedEventHandler } from '../Domain/Handler/PaymentFailedEventHandler'
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
const newrelicFormatter = require('@newrelic/winston-enricher')
|
||||
@@ -478,6 +479,7 @@ export class ContainerConfigLoader {
|
||||
container
|
||||
.bind<PredicateVerificationRequestedEventHandler>(TYPES.PredicateVerificationRequestedEventHandler)
|
||||
.to(PredicateVerificationRequestedEventHandler)
|
||||
container.bind<PaymentFailedEventHandler>(TYPES.PaymentFailedEventHandler).to(PaymentFailedEventHandler)
|
||||
|
||||
// Services
|
||||
container.bind<UAParser>(TYPES.DeviceDetector).toConstantValue(new UAParser())
|
||||
@@ -576,6 +578,7 @@ export class ContainerConfigLoader {
|
||||
],
|
||||
['SHARED_SUBSCRIPTION_INVITATION_CREATED', container.get(TYPES.SharedSubscriptionInvitationCreatedEventHandler)],
|
||||
['PREDICATE_VERIFICATION_REQUESTED', container.get(TYPES.PredicateVerificationRequestedEventHandler)],
|
||||
['PAYMENT_FAILED', container.get(TYPES.PaymentFailedEventHandler)],
|
||||
])
|
||||
|
||||
if (env.get('SQS_QUEUE_URL', true)) {
|
||||
|
||||
@@ -143,6 +143,7 @@ const TYPES = {
|
||||
UserDisabledSessionUserAgentLoggingEventHandler: Symbol.for('UserDisabledSessionUserAgentLoggingEventHandler'),
|
||||
SharedSubscriptionInvitationCreatedEventHandler: Symbol.for('SharedSubscriptionInvitationCreatedEventHandler'),
|
||||
PredicateVerificationRequestedEventHandler: Symbol.for('PredicateVerificationRequestedEventHandler'),
|
||||
PaymentFailedEventHandler: Symbol.for('PaymentFailedEventHandler'),
|
||||
// Services
|
||||
DeviceDetector: Symbol.for('DeviceDetector'),
|
||||
SessionService: Symbol.for('SessionService'),
|
||||
|
||||
@@ -7,15 +7,18 @@ import { UserRepositoryInterface } from '../Domain/User/UserRepositoryInterface'
|
||||
import * as express from 'express'
|
||||
import { DeleteSetting } from '../Domain/UseCase/DeleteSetting/DeleteSetting'
|
||||
import { CreateSubscriptionToken } from '../Domain/UseCase/CreateSubscriptionToken/CreateSubscriptionToken'
|
||||
import { CreateOfflineSubscriptionToken } from '../Domain/UseCase/CreateOfflineSubscriptionToken/CreateOfflineSubscriptionToken'
|
||||
|
||||
describe('AdminController', () => {
|
||||
let deleteSetting: DeleteSetting
|
||||
let userRepository: UserRepositoryInterface
|
||||
let createSubscriptionToken: CreateSubscriptionToken
|
||||
let createOfflineSubscriptionToken: CreateOfflineSubscriptionToken
|
||||
let request: express.Request
|
||||
let user: User
|
||||
|
||||
const createController = () => new AdminController(deleteSetting, userRepository, createSubscriptionToken)
|
||||
const createController = () =>
|
||||
new AdminController(deleteSetting, userRepository, createSubscriptionToken, createOfflineSubscriptionToken)
|
||||
|
||||
beforeEach(() => {
|
||||
user = {} as jest.Mocked<User>
|
||||
@@ -34,6 +37,14 @@ describe('AdminController', () => {
|
||||
},
|
||||
})
|
||||
|
||||
createOfflineSubscriptionToken = {} as jest.Mocked<CreateOfflineSubscriptionToken>
|
||||
createOfflineSubscriptionToken.execute = jest.fn().mockReturnValue({
|
||||
success: true,
|
||||
offlineSubscriptionToken: {
|
||||
token: '123-sub-token',
|
||||
},
|
||||
})
|
||||
|
||||
request = {
|
||||
headers: {},
|
||||
body: {},
|
||||
@@ -125,6 +136,31 @@ describe('AdminController', () => {
|
||||
expect(await result.content.readAsStringAsync()).toEqual('{"token":"123-sub-token"}')
|
||||
})
|
||||
|
||||
it("should return a new offline subscription token for the user's email", async () => {
|
||||
request.params.email = 'test@test.te'
|
||||
|
||||
const httpResponse = await createController().createOfflineToken(request)
|
||||
const result = await httpResponse.executeAsync()
|
||||
|
||||
expect(httpResponse).toBeInstanceOf(results.JsonResult)
|
||||
|
||||
expect(result.statusCode).toBe(200)
|
||||
expect(await result.content.readAsStringAsync()).toEqual('{"token":"123-sub-token"}')
|
||||
})
|
||||
|
||||
it('should not return a new offline subscription token if the workflow fails', async () => {
|
||||
request.params.email = 'test@test.te'
|
||||
|
||||
createOfflineSubscriptionToken.execute = jest.fn().mockReturnValue({ success: false })
|
||||
|
||||
const httpResponse = await createController().createOfflineToken(request)
|
||||
const result = await httpResponse.executeAsync()
|
||||
|
||||
expect(httpResponse).toBeInstanceOf(results.BadRequestResult)
|
||||
|
||||
expect(result.statusCode).toBe(400)
|
||||
})
|
||||
|
||||
it('should not delete email backup setting if value is null', async () => {
|
||||
request.body = {}
|
||||
request.params = {
|
||||
|
||||
@@ -11,6 +11,7 @@ import {
|
||||
results,
|
||||
} from 'inversify-express-utils'
|
||||
import TYPES from '../Bootstrap/Types'
|
||||
import { CreateOfflineSubscriptionToken } from '../Domain/UseCase/CreateOfflineSubscriptionToken/CreateOfflineSubscriptionToken'
|
||||
import { CreateSubscriptionToken } from '../Domain/UseCase/CreateSubscriptionToken/CreateSubscriptionToken'
|
||||
import { DeleteSetting } from '../Domain/UseCase/DeleteSetting/DeleteSetting'
|
||||
import { UserRepositoryInterface } from '../Domain/User/UserRepositoryInterface'
|
||||
@@ -21,6 +22,8 @@ export class AdminController extends BaseHttpController {
|
||||
@inject(TYPES.DeleteSetting) private doDeleteSetting: DeleteSetting,
|
||||
@inject(TYPES.UserRepository) private userRepository: UserRepositoryInterface,
|
||||
@inject(TYPES.CreateSubscriptionToken) private createSubscriptionToken: CreateSubscriptionToken,
|
||||
@inject(TYPES.CreateOfflineSubscriptionToken)
|
||||
private createOfflineSubscriptionToken: CreateOfflineSubscriptionToken,
|
||||
) {
|
||||
super()
|
||||
}
|
||||
@@ -90,6 +93,22 @@ export class AdminController extends BaseHttpController {
|
||||
})
|
||||
}
|
||||
|
||||
@httpPost('/users/:email/offline-subscription-token')
|
||||
async createOfflineToken(request: Request): Promise<results.JsonResult | results.BadRequestResult> {
|
||||
const { email } = request.params
|
||||
const result = await this.createOfflineSubscriptionToken.execute({
|
||||
userEmail: email,
|
||||
})
|
||||
|
||||
if (!result.success) {
|
||||
return this.badRequest()
|
||||
}
|
||||
|
||||
return this.json({
|
||||
token: result.offlineSubscriptionToken.token,
|
||||
})
|
||||
}
|
||||
|
||||
@httpPost('/users/:userUuid/email-backups')
|
||||
async disableEmailBackups(request: Request): Promise<results.BadRequestErrorMessageResult | results.OkResult> {
|
||||
const { userUuid } = request.params
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
import 'reflect-metadata'
|
||||
|
||||
import { PaymentFailedEvent } from '@standardnotes/domain-events'
|
||||
import { AnalyticsStoreInterface } from '@standardnotes/analytics'
|
||||
|
||||
import { PaymentFailedEventHandler } from './PaymentFailedEventHandler'
|
||||
import { UserRepositoryInterface } from '../User/UserRepositoryInterface'
|
||||
import { User } from '../User/User'
|
||||
import { GetUserAnalyticsId } from '../UseCase/GetUserAnalyticsId/GetUserAnalyticsId'
|
||||
|
||||
describe('PaymentFailedEventHandler', () => {
|
||||
let userRepository: UserRepositoryInterface
|
||||
let event: PaymentFailedEvent
|
||||
let user: User
|
||||
let getUserAnalyticsId: GetUserAnalyticsId
|
||||
let analyticsStore: AnalyticsStoreInterface
|
||||
|
||||
const createHandler = () => new PaymentFailedEventHandler(userRepository, getUserAnalyticsId, analyticsStore)
|
||||
|
||||
beforeEach(() => {
|
||||
user = {} as jest.Mocked<User>
|
||||
|
||||
userRepository = {} as jest.Mocked<UserRepositoryInterface>
|
||||
userRepository.findOneByEmail = jest.fn().mockReturnValue(user)
|
||||
|
||||
getUserAnalyticsId = {} as jest.Mocked<GetUserAnalyticsId>
|
||||
getUserAnalyticsId.execute = jest.fn().mockReturnValue({ analyticsId: 3 })
|
||||
|
||||
analyticsStore = {} as jest.Mocked<AnalyticsStoreInterface>
|
||||
analyticsStore.markActivity = jest.fn()
|
||||
|
||||
event = {} as jest.Mocked<PaymentFailedEvent>
|
||||
event.payload = {
|
||||
userEmail: 'test@test.com',
|
||||
}
|
||||
})
|
||||
|
||||
it('should mark payment failed for analytics', async () => {
|
||||
await createHandler().handle(event)
|
||||
|
||||
expect(analyticsStore.markActivity).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('should not mark payment failed for analytics if user is not found', async () => {
|
||||
userRepository.findOneByEmail = jest.fn().mockReturnValue(null)
|
||||
|
||||
await createHandler().handle(event)
|
||||
|
||||
expect(analyticsStore.markActivity).not.toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,30 @@
|
||||
import { AnalyticsActivity, AnalyticsStoreInterface, Period } from '@standardnotes/analytics'
|
||||
import { DomainEventHandlerInterface, PaymentFailedEvent } from '@standardnotes/domain-events'
|
||||
import { inject, injectable } from 'inversify'
|
||||
|
||||
import TYPES from '../../Bootstrap/Types'
|
||||
import { GetUserAnalyticsId } from '../UseCase/GetUserAnalyticsId/GetUserAnalyticsId'
|
||||
import { UserRepositoryInterface } from '../User/UserRepositoryInterface'
|
||||
|
||||
@injectable()
|
||||
export class PaymentFailedEventHandler implements DomainEventHandlerInterface {
|
||||
constructor(
|
||||
@inject(TYPES.UserRepository) private userRepository: UserRepositoryInterface,
|
||||
@inject(TYPES.GetUserAnalyticsId) private getUserAnalyticsId: GetUserAnalyticsId,
|
||||
@inject(TYPES.AnalyticsStore) private analyticsStore: AnalyticsStoreInterface,
|
||||
) {}
|
||||
|
||||
async handle(event: PaymentFailedEvent): Promise<void> {
|
||||
const user = await this.userRepository.findOneByEmail(event.payload.userEmail)
|
||||
if (user === null) {
|
||||
return
|
||||
}
|
||||
|
||||
const { analyticsId } = await this.getUserAnalyticsId.execute({ userUuid: user.uuid })
|
||||
await this.analyticsStore.markActivity([AnalyticsActivity.PaymentFailed], analyticsId, [
|
||||
Period.Today,
|
||||
Period.ThisWeek,
|
||||
Period.ThisMonth,
|
||||
])
|
||||
}
|
||||
}
|
||||
@@ -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.7.32](https://github.com/standardnotes/server/compare/@standardnotes/domain-events-infra@1.7.31...@standardnotes/domain-events-infra@1.7.32) (2022-08-15)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/domain-events-infra
|
||||
|
||||
## [1.7.31](https://github.com/standardnotes/server/compare/@standardnotes/domain-events-infra@1.7.30...@standardnotes/domain-events-infra@1.7.31) (2022-08-10)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/domain-events-infra
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/domain-events-infra",
|
||||
"version": "1.7.31",
|
||||
"version": "1.7.32",
|
||||
"engines": {
|
||||
"node": ">=16.0.0 <17.0.0"
|
||||
},
|
||||
|
||||
@@ -3,6 +3,12 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [2.54.0](https://github.com/standardnotes/server/compare/@standardnotes/domain-events@2.53.0...@standardnotes/domain-events@2.54.0) (2022-08-15)
|
||||
|
||||
### Features
|
||||
|
||||
* **domain-events:** add payment success event ([1841597](https://github.com/standardnotes/server/commit/1841597405461981c7b6eb4ee8ada079c77a8fc5))
|
||||
|
||||
# [2.53.0](https://github.com/standardnotes/server/compare/@standardnotes/domain-events@2.52.0...@standardnotes/domain-events@2.53.0) (2022-08-09)
|
||||
|
||||
### Features
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/domain-events",
|
||||
"version": "2.53.0",
|
||||
"version": "2.54.0",
|
||||
"engines": {
|
||||
"node": ">=16.0.0 <17.0.0"
|
||||
},
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
import { DomainEventInterface } from './DomainEventInterface'
|
||||
|
||||
import { PaymentSuccessEventPayload } from './PaymentSuccessEventPayload'
|
||||
|
||||
export interface PaymentSuccessEvent extends DomainEventInterface {
|
||||
type: 'PAYMENT_SUCCESS'
|
||||
payload: PaymentSuccessEventPayload
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
export interface PaymentSuccessEventPayload {
|
||||
userEmail: string
|
||||
}
|
||||
@@ -3,6 +3,16 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.1.32](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.1.31...@standardnotes/event-store@1.1.32) (2022-08-15)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/event-store
|
||||
|
||||
## [1.1.31](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.1.30...@standardnotes/event-store@1.1.31) (2022-08-12)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **event-store:** add listening to offline subscription token created events ([1ba5ba5](https://github.com/standardnotes/server/commit/1ba5ba5ff6f7afe5c8e2e929555042a01f2465ac))
|
||||
|
||||
## [1.1.30](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.1.29...@standardnotes/event-store@1.1.30) (2022-08-10)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/event-store
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/event-store",
|
||||
"version": "1.1.30",
|
||||
"version": "1.1.32",
|
||||
"description": "Event Store Service",
|
||||
"private": true,
|
||||
"main": "dist/src/index.js",
|
||||
|
||||
@@ -75,6 +75,7 @@ export class ContainerConfigLoader {
|
||||
['SHARED_SUBSCRIPTION_INVITATION_CREATED', container.get(TYPES.EventHandler)],
|
||||
['EMAIL_BACKUP_ATTACHMENT_CREATED', container.get(TYPES.EventHandler)],
|
||||
['EMAIL_BACKUP_REQUESTED', container.get(TYPES.EventHandler)],
|
||||
['OFFLINE_SUBSCRIPTION_TOKEN_CREATED', container.get(TYPES.EventHandler)],
|
||||
])
|
||||
|
||||
container
|
||||
|
||||
@@ -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.5.34](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.5.33...@standardnotes/files-server@1.5.34) (2022-08-15)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/files-server
|
||||
|
||||
## [1.5.33](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.5.32...@standardnotes/files-server@1.5.33) (2022-08-10)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/files-server
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/files-server",
|
||||
"version": "1.5.33",
|
||||
"version": "1.5.34",
|
||||
"engines": {
|
||||
"node": ">=16.0.0 <17.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.10.8](https://github.com/standardnotes/server/compare/@standardnotes/scheduler-server@1.10.7...@standardnotes/scheduler-server@1.10.8) (2022-08-15)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/scheduler-server
|
||||
|
||||
## [1.10.7](https://github.com/standardnotes/server/compare/@standardnotes/scheduler-server@1.10.6...@standardnotes/scheduler-server@1.10.7) (2022-08-10)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/scheduler-server
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/scheduler-server",
|
||||
"version": "1.10.7",
|
||||
"version": "1.10.8",
|
||||
"engines": {
|
||||
"node": ">=16.0.0 <17.0.0"
|
||||
},
|
||||
|
||||
@@ -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.6.49](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.6.48...@standardnotes/syncing-server@1.6.49) (2022-08-15)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/syncing-server
|
||||
|
||||
## [1.6.48](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.6.47...@standardnotes/syncing-server@1.6.48) (2022-08-15)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/syncing-server
|
||||
|
||||
## [1.6.47](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.6.46...@standardnotes/syncing-server@1.6.47) (2022-08-15)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/syncing-server
|
||||
|
||||
## [1.6.46](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.6.45...@standardnotes/syncing-server@1.6.46) (2022-08-15)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/syncing-server
|
||||
|
||||
## [1.6.45](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.6.44...@standardnotes/syncing-server@1.6.45) (2022-08-15)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/syncing-server
|
||||
|
||||
## [1.6.44](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.6.43...@standardnotes/syncing-server@1.6.44) (2022-08-15)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/syncing-server
|
||||
|
||||
## [1.6.43](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.6.42...@standardnotes/syncing-server@1.6.43) (2022-08-11)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/syncing-server
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/syncing-server",
|
||||
"version": "1.6.43",
|
||||
"version": "1.6.49",
|
||||
"engines": {
|
||||
"node": ">=16.0.0 <17.0.0"
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user