Compare commits

..

12 Commits

Author SHA1 Message Date
standardci
4952b48db6 chore(release): publish new version
- @standardnotes/analytics@2.7.0
 - @standardnotes/api-gateway@1.37.5
 - @standardnotes/auth-server@1.59.0
 - @standardnotes/domain-events-infra@1.9.18
 - @standardnotes/domain-events@2.83.0
 - @standardnotes/event-store@1.6.13
 - @standardnotes/files-server@1.8.13
 - @standardnotes/scheduler-server@1.13.14
 - @standardnotes/syncing-server@1.11.5
 - @standardnotes/websockets-server@1.4.13
 - @standardnotes/workspace-server@1.17.13
2022-11-09 10:27:37 +00:00
Karol Sójko
52a257abb1 feat(analytics): add saving revenue modifications upon subscription canceled 2022-11-09 11:25:26 +01:00
standardci
7480fb089b chore(release): publish new version
- @standardnotes/analytics@2.6.0
 - @standardnotes/api-gateway@1.37.4
 - @standardnotes/auth-server@1.58.0
 - @standardnotes/domain-events-infra@1.9.17
 - @standardnotes/domain-events@2.82.0
 - @standardnotes/event-store@1.6.12
 - @standardnotes/files-server@1.8.12
 - @standardnotes/scheduler-server@1.13.13
 - @standardnotes/syncing-server@1.11.4
 - @standardnotes/websockets-server@1.4.12
 - @standardnotes/workspace-server@1.17.12
2022-11-09 10:20:29 +00:00
Karol Sójko
0f65c051ab feat(analytics): add saving revenue modifications upon subscription refunded 2022-11-09 11:17:27 +01:00
standardci
7b62c7a967 chore(release): publish new version
- @standardnotes/analytics@2.5.0
 - @standardnotes/api-gateway@1.37.3
 - @standardnotes/auth-server@1.57.0
 - @standardnotes/domain-events-infra@1.9.16
 - @standardnotes/domain-events@2.81.0
 - @standardnotes/event-store@1.6.11
 - @standardnotes/files-server@1.8.11
 - @standardnotes/scheduler-server@1.13.12
 - @standardnotes/syncing-server@1.11.3
 - @standardnotes/websockets-server@1.4.11
 - @standardnotes/workspace-server@1.17.11
2022-11-09 10:12:01 +00:00
Karol Sójko
5c3db2cb29 feat(analytics): add saving revenue modifications upon subscription expired 2022-11-09 11:09:49 +01:00
standardci
7008cbd363 chore(release): publish new version
- @standardnotes/analytics@2.4.0
 - @standardnotes/api-gateway@1.37.2
 - @standardnotes/auth-server@1.56.0
 - @standardnotes/domain-events-infra@1.9.15
 - @standardnotes/domain-events@2.80.0
 - @standardnotes/event-store@1.6.10
 - @standardnotes/files-server@1.8.10
 - @standardnotes/scheduler-server@1.13.11
 - @standardnotes/syncing-server@1.11.2
 - @standardnotes/websockets-server@1.4.10
 - @standardnotes/workspace-server@1.17.10
2022-11-09 09:59:41 +00:00
Karol Sójko
cdb7fcf831 feat(analytics): add saving revenue modifications upon subscription renewed 2022-11-09 10:57:43 +01:00
standardci
628aafdd42 chore(release): publish new version
- @standardnotes/analytics@2.3.1
2022-11-09 09:49:22 +00:00
Karol Sójko
9d3ef24ba9 fix(analytics): missing injectable annotation 2022-11-09 10:47:27 +01:00
standardci
4189f11fd7 chore(release): publish new version
- @standardnotes/analytics@2.3.0
 - @standardnotes/api-gateway@1.37.1
 - @standardnotes/auth-server@1.55.0
 - @standardnotes/domain-events-infra@1.9.14
 - @standardnotes/domain-events@2.79.0
 - @standardnotes/event-store@1.6.9
 - @standardnotes/files-server@1.8.9
 - @standardnotes/scheduler-server@1.13.10
 - @standardnotes/syncing-server@1.11.1
 - @standardnotes/websockets-server@1.4.9
 - @standardnotes/workspace-server@1.17.9
2022-11-09 07:16:01 +00:00
Karol Sójko
5ea9941519 feat(analytics): add saving revenue modifications upon subscription purchased 2022-11-09 08:14:02 +01:00
48 changed files with 467 additions and 24 deletions

View File

@@ -3,6 +3,42 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
# [2.7.0](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.6.0...@standardnotes/analytics@2.7.0) (2022-11-09)
### Features
* **analytics:** add saving revenue modifications upon subscription canceled ([52a257a](https://github.com/standardnotes/server/commit/52a257abb16034134a50474fbbb2493a00c58b99))
# [2.6.0](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.5.0...@standardnotes/analytics@2.6.0) (2022-11-09)
### Features
* **analytics:** add saving revenue modifications upon subscription refunded ([0f65c05](https://github.com/standardnotes/server/commit/0f65c051abcff805e920f91d338e5fadda7905a9))
# [2.5.0](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.4.0...@standardnotes/analytics@2.5.0) (2022-11-09)
### Features
* **analytics:** add saving revenue modifications upon subscription expired ([5c3db2c](https://github.com/standardnotes/server/commit/5c3db2cb29a929e44b63eb8226ce4ad1d14f8a99))
# [2.4.0](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.3.1...@standardnotes/analytics@2.4.0) (2022-11-09)
### Features
* **analytics:** add saving revenue modifications upon subscription renewed ([cdb7fcf](https://github.com/standardnotes/server/commit/cdb7fcf8311fecfabe3ef9eb656cd6ec57b87de0))
## [2.3.1](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.3.0...@standardnotes/analytics@2.3.1) (2022-11-09)
### Bug Fixes
* **analytics:** missing injectable annotation ([9d3ef24](https://github.com/standardnotes/server/commit/9d3ef24ba94ad28976a211d40f94f1bce8d0d305))
# [2.3.0](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.2.0...@standardnotes/analytics@2.3.0) (2022-11-09)
### Features
* **analytics:** add saving revenue modifications upon subscription purchased ([5ea9941](https://github.com/standardnotes/server/commit/5ea9941519ffb3027527130ec869da14abc5e994))
# [2.2.0](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.1.0...@standardnotes/analytics@2.2.0) (2022-11-08)
### Features

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/analytics",
"version": "2.2.0",
"version": "2.7.0",
"engines": {
"node": ">=14.0.0 <17.0.0"
},

View File

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

View File

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

View File

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

View File

@@ -4,10 +4,14 @@ import { inject, injectable } from 'inversify'
import TYPES from '../../Bootstrap/Types'
import { AnalyticsActivity } from '../Analytics/AnalyticsActivity'
import { AnalyticsStoreInterface } from '../Analytics/AnalyticsStoreInterface'
import { Email } from '../Common/Email'
import { StatisticsMeasure } from '../Statistics/StatisticsMeasure'
import { StatisticsStoreInterface } from '../Statistics/StatisticsStoreInterface'
import { SubscriptionEventType } from '../Subscription/SubscriptionEventType'
import { SubscriptionPlanName } from '../Subscription/SubscriptionPlanName'
import { Period } from '../Time/Period'
import { GetUserAnalyticsId } from '../UseCase/GetUserAnalyticsId/GetUserAnalyticsId'
import { SaveRevenueModification } from '../UseCase/SaveRevenueModification/SaveRevenueModification'
@injectable()
export class SubscriptionCancelledEventHandler implements DomainEventHandlerInterface {
@@ -15,10 +19,11 @@ export class SubscriptionCancelledEventHandler implements DomainEventHandlerInte
@inject(TYPES.GetUserAnalyticsId) private getUserAnalyticsId: GetUserAnalyticsId,
@inject(TYPES.AnalyticsStore) private analyticsStore: AnalyticsStoreInterface,
@inject(TYPES.StatisticsStore) private statisticsStore: StatisticsStoreInterface,
@inject(TYPES.SaveRevenueModification) private saveRevenueModification: SaveRevenueModification,
) {}
async handle(event: SubscriptionCancelledEvent): Promise<void> {
const { analyticsId } = await this.getUserAnalyticsId.execute({ userEmail: event.payload.userEmail })
const { analyticsId, userUuid } = await this.getUserAnalyticsId.execute({ userEmail: event.payload.userEmail })
await this.analyticsStore.markActivity([AnalyticsActivity.SubscriptionCancelled], analyticsId, [
Period.Today,
Period.ThisWeek,
@@ -26,6 +31,17 @@ export class SubscriptionCancelledEventHandler implements DomainEventHandlerInte
])
await this.trackSubscriptionStatistics(event)
await this.saveRevenueModification.execute({
billingFrequency: event.payload.billingFrequency,
eventType: SubscriptionEventType.create(event.type).getValue(),
newSubscriber: event.payload.userExistingSubscriptionsCount === 1,
payedAmount: event.payload.payAmount,
planName: SubscriptionPlanName.create(event.payload.subscriptionName).getValue(),
subscriptionId: event.payload.subscriptionId,
userEmail: Email.create(event.payload.userEmail).getValue(),
userUuid,
})
}
private async trackSubscriptionStatistics(event: SubscriptionCancelledEvent) {

View File

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

View File

@@ -4,10 +4,14 @@ import { inject, injectable } from 'inversify'
import TYPES from '../../Bootstrap/Types'
import { AnalyticsActivity } from '../Analytics/AnalyticsActivity'
import { AnalyticsStoreInterface } from '../Analytics/AnalyticsStoreInterface'
import { Email } from '../Common/Email'
import { StatisticsMeasure } from '../Statistics/StatisticsMeasure'
import { StatisticsStoreInterface } from '../Statistics/StatisticsStoreInterface'
import { SubscriptionEventType } from '../Subscription/SubscriptionEventType'
import { SubscriptionPlanName } from '../Subscription/SubscriptionPlanName'
import { Period } from '../Time/Period'
import { GetUserAnalyticsId } from '../UseCase/GetUserAnalyticsId/GetUserAnalyticsId'
import { SaveRevenueModification } from '../UseCase/SaveRevenueModification/SaveRevenueModification'
@injectable()
export class SubscriptionExpiredEventHandler implements DomainEventHandlerInterface {
@@ -15,10 +19,11 @@ export class SubscriptionExpiredEventHandler implements DomainEventHandlerInterf
@inject(TYPES.GetUserAnalyticsId) private getUserAnalyticsId: GetUserAnalyticsId,
@inject(TYPES.AnalyticsStore) private analyticsStore: AnalyticsStoreInterface,
@inject(TYPES.StatisticsStore) private statisticsStore: StatisticsStoreInterface,
@inject(TYPES.SaveRevenueModification) private saveRevenueModification: SaveRevenueModification,
) {}
async handle(event: SubscriptionExpiredEvent): Promise<void> {
const { analyticsId } = await this.getUserAnalyticsId.execute({ userEmail: event.payload.userEmail })
const { analyticsId, userUuid } = await this.getUserAnalyticsId.execute({ userEmail: event.payload.userEmail })
await this.analyticsStore.markActivity(
[AnalyticsActivity.SubscriptionExpired, AnalyticsActivity.ExistingCustomersChurn],
analyticsId,
@@ -30,5 +35,16 @@ export class SubscriptionExpiredEventHandler implements DomainEventHandlerInterf
event.payload.totalActiveSubscriptionsCount,
[Period.Today, Period.ThisWeek, Period.ThisMonth, Period.ThisYear],
)
await this.saveRevenueModification.execute({
billingFrequency: event.payload.billingFrequency,
eventType: SubscriptionEventType.create(event.type).getValue(),
newSubscriber: event.payload.userExistingSubscriptionsCount === 1,
payedAmount: event.payload.payAmount,
planName: SubscriptionPlanName.create(event.payload.subscriptionName).getValue(),
subscriptionId: event.payload.subscriptionId,
userEmail: Email.create(event.payload.userEmail).getValue(),
userUuid,
})
}
}

View File

@@ -8,6 +8,9 @@ import { GetUserAnalyticsId } from '../UseCase/GetUserAnalyticsId/GetUserAnalyti
import { AnalyticsStoreInterface } from '../Analytics/AnalyticsStoreInterface'
import { StatisticsStoreInterface } from '../Statistics/StatisticsStoreInterface'
import { Period } from '../Time/Period'
import { SaveRevenueModification } from '../UseCase/SaveRevenueModification/SaveRevenueModification'
import { Result } from '../Core/Result'
import { RevenueModification } from '../Revenue/RevenueModification'
describe('SubscriptionPurchasedEventHandler', () => {
let event: SubscriptionPurchasedEvent
@@ -15,8 +18,10 @@ describe('SubscriptionPurchasedEventHandler', () => {
let getUserAnalyticsId: GetUserAnalyticsId
let analyticsStore: AnalyticsStoreInterface
let statisticsStore: StatisticsStoreInterface
let saveRevenueModification: SaveRevenueModification
const createHandler = () => new SubscriptionPurchasedEventHandler(getUserAnalyticsId, analyticsStore, statisticsStore)
const createHandler = () =>
new SubscriptionPurchasedEventHandler(getUserAnalyticsId, analyticsStore, statisticsStore, saveRevenueModification)
beforeEach(() => {
statisticsStore = {} as jest.Mocked<StatisticsStoreInterface>
@@ -25,6 +30,7 @@ describe('SubscriptionPurchasedEventHandler', () => {
event = {} as jest.Mocked<SubscriptionPurchasedEvent>
event.createdAt = new Date(1)
event.type = 'SUBSCRIPTION_PURCHASED'
event.payload = {
subscriptionId: 1,
userEmail: 'test@test.com',
@@ -37,6 +43,8 @@ describe('SubscriptionPurchasedEventHandler', () => {
newSubscriber: true,
totalActiveSubscriptionsCount: 123,
userRegisteredAt: 23,
billingFrequency: 12,
payAmount: 29.99,
}
getUserAnalyticsId = {} as jest.Mocked<GetUserAnalyticsId>
@@ -45,12 +53,16 @@ describe('SubscriptionPurchasedEventHandler', () => {
analyticsStore = {} as jest.Mocked<AnalyticsStoreInterface>
analyticsStore.markActivity = jest.fn()
analyticsStore.unmarkActivity = jest.fn()
saveRevenueModification = {} as jest.Mocked<SaveRevenueModification>
saveRevenueModification.execute = jest.fn().mockReturnValue(Result.ok<RevenueModification>())
})
it('should mark subscription creation statistics', async () => {
await createHandler().handle(event)
expect(statisticsStore.incrementMeasure).toHaveBeenCalled()
expect(saveRevenueModification.execute).toHaveBeenCalled()
})
it("should not measure registration to subscription time if this is not user's first subscription", async () => {

View File

@@ -4,10 +4,14 @@ import { inject, injectable } from 'inversify'
import TYPES from '../../Bootstrap/Types'
import { AnalyticsActivity } from '../Analytics/AnalyticsActivity'
import { AnalyticsStoreInterface } from '../Analytics/AnalyticsStoreInterface'
import { Email } from '../Common/Email'
import { StatisticsMeasure } from '../Statistics/StatisticsMeasure'
import { StatisticsStoreInterface } from '../Statistics/StatisticsStoreInterface'
import { SubscriptionEventType } from '../Subscription/SubscriptionEventType'
import { SubscriptionPlanName } from '../Subscription/SubscriptionPlanName'
import { Period } from '../Time/Period'
import { GetUserAnalyticsId } from '../UseCase/GetUserAnalyticsId/GetUserAnalyticsId'
import { SaveRevenueModification } from '../UseCase/SaveRevenueModification/SaveRevenueModification'
@injectable()
export class SubscriptionPurchasedEventHandler implements DomainEventHandlerInterface {
@@ -15,10 +19,11 @@ export class SubscriptionPurchasedEventHandler implements DomainEventHandlerInte
@inject(TYPES.GetUserAnalyticsId) private getUserAnalyticsId: GetUserAnalyticsId,
@inject(TYPES.AnalyticsStore) private analyticsStore: AnalyticsStoreInterface,
@inject(TYPES.StatisticsStore) private statisticsStore: StatisticsStoreInterface,
@inject(TYPES.SaveRevenueModification) private saveRevenueModification: SaveRevenueModification,
) {}
async handle(event: SubscriptionPurchasedEvent): Promise<void> {
const { analyticsId } = await this.getUserAnalyticsId.execute({ userEmail: event.payload.userEmail })
const { analyticsId, userUuid } = await this.getUserAnalyticsId.execute({ userEmail: event.payload.userEmail })
await this.analyticsStore.markActivity([AnalyticsActivity.SubscriptionPurchased], analyticsId, [
Period.Today,
Period.ThisWeek,
@@ -54,5 +59,16 @@ export class SubscriptionPurchasedEventHandler implements DomainEventHandlerInte
[Period.Today, Period.ThisWeek, Period.ThisMonth, Period.ThisYear],
)
}
await this.saveRevenueModification.execute({
billingFrequency: event.payload.billingFrequency,
eventType: SubscriptionEventType.create(event.type).getValue(),
newSubscriber: event.payload.newSubscriber,
payedAmount: event.payload.payAmount,
planName: SubscriptionPlanName.create(event.payload.subscriptionName).getValue(),
subscriptionId: event.payload.subscriptionId,
userEmail: Email.create(event.payload.userEmail).getValue(),
userUuid,
})
}
}

View File

@@ -10,18 +10,24 @@ import { SubscriptionRefundedEventHandler } from './SubscriptionRefundedEventHan
import { StatisticsStoreInterface } from '../Statistics/StatisticsStoreInterface'
import { AnalyticsActivity } from '../Analytics/AnalyticsActivity'
import { Period } from '../Time/Period'
import { Result } from '../Core/Result'
import { RevenueModification } from '../Revenue/RevenueModification'
import { SaveRevenueModification } from '../UseCase/SaveRevenueModification/SaveRevenueModification'
describe('SubscriptionRefundedEventHandler', () => {
let event: SubscriptionRefundedEvent
let getUserAnalyticsId: GetUserAnalyticsId
let analyticsStore: AnalyticsStoreInterface
let statisticsStore: StatisticsStoreInterface
let saveRevenueModification: SaveRevenueModification
const createHandler = () => new SubscriptionRefundedEventHandler(getUserAnalyticsId, analyticsStore, statisticsStore)
const createHandler = () =>
new SubscriptionRefundedEventHandler(getUserAnalyticsId, analyticsStore, statisticsStore, saveRevenueModification)
beforeEach(() => {
event = {} as jest.Mocked<SubscriptionRefundedEvent>
event.createdAt = new Date(1)
event.type = 'SUBSCRIPTION_REFUNDED'
event.payload = {
subscriptionId: 1,
userEmail: 'test@test.com',
@@ -30,6 +36,8 @@ describe('SubscriptionRefundedEventHandler', () => {
offline: false,
userExistingSubscriptionsCount: 3,
totalActiveSubscriptionsCount: 1,
billingFrequency: 1,
payAmount: 12.99,
}
getUserAnalyticsId = {} as jest.Mocked<GetUserAnalyticsId>
@@ -41,6 +49,9 @@ describe('SubscriptionRefundedEventHandler', () => {
statisticsStore = {} as jest.Mocked<StatisticsStoreInterface>
statisticsStore.setMeasure = jest.fn()
saveRevenueModification = {} as jest.Mocked<SaveRevenueModification>
saveRevenueModification.execute = jest.fn().mockReturnValue(Result.ok<RevenueModification>())
})
it('should mark churn for new customer', async () => {
@@ -56,6 +67,8 @@ describe('SubscriptionRefundedEventHandler', () => {
expect(analyticsStore.markActivity).toHaveBeenCalledWith([AnalyticsActivity.NewCustomersChurn], 3, [
Period.ThisMonth,
])
expect(saveRevenueModification.execute).toHaveBeenCalled()
})
it('should mark churn for existing customer', async () => {

View File

@@ -4,10 +4,14 @@ import { inject, injectable } from 'inversify'
import TYPES from '../../Bootstrap/Types'
import { AnalyticsActivity } from '../Analytics/AnalyticsActivity'
import { AnalyticsStoreInterface } from '../Analytics/AnalyticsStoreInterface'
import { Email } from '../Common/Email'
import { StatisticsMeasure } from '../Statistics/StatisticsMeasure'
import { StatisticsStoreInterface } from '../Statistics/StatisticsStoreInterface'
import { SubscriptionEventType } from '../Subscription/SubscriptionEventType'
import { SubscriptionPlanName } from '../Subscription/SubscriptionPlanName'
import { Period } from '../Time/Period'
import { GetUserAnalyticsId } from '../UseCase/GetUserAnalyticsId/GetUserAnalyticsId'
import { SaveRevenueModification } from '../UseCase/SaveRevenueModification/SaveRevenueModification'
@injectable()
export class SubscriptionRefundedEventHandler implements DomainEventHandlerInterface {
@@ -15,10 +19,11 @@ export class SubscriptionRefundedEventHandler implements DomainEventHandlerInter
@inject(TYPES.GetUserAnalyticsId) private getUserAnalyticsId: GetUserAnalyticsId,
@inject(TYPES.AnalyticsStore) private analyticsStore: AnalyticsStoreInterface,
@inject(TYPES.StatisticsStore) private statisticsStore: StatisticsStoreInterface,
@inject(TYPES.SaveRevenueModification) private saveRevenueModification: SaveRevenueModification,
) {}
async handle(event: SubscriptionRefundedEvent): Promise<void> {
const { analyticsId } = await this.getUserAnalyticsId.execute({ userEmail: event.payload.userEmail })
const { analyticsId, userUuid } = await this.getUserAnalyticsId.execute({ userEmail: event.payload.userEmail })
await this.analyticsStore.markActivity([AnalyticsActivity.SubscriptionRefunded], analyticsId, [
Period.Today,
Period.ThisWeek,
@@ -26,6 +31,17 @@ export class SubscriptionRefundedEventHandler implements DomainEventHandlerInter
])
await this.markChurnActivity(analyticsId, event)
await this.saveRevenueModification.execute({
billingFrequency: event.payload.billingFrequency,
eventType: SubscriptionEventType.create(event.type).getValue(),
newSubscriber: event.payload.userExistingSubscriptionsCount === 1,
payedAmount: event.payload.payAmount,
planName: SubscriptionPlanName.create(event.payload.subscriptionName).getValue(),
subscriptionId: event.payload.subscriptionId,
userEmail: Email.create(event.payload.userEmail).getValue(),
userUuid,
})
}
private async markChurnActivity(analyticsId: number, event: SubscriptionRefundedEvent): Promise<void> {

View File

@@ -6,17 +6,23 @@ import { SubscriptionRenewedEvent } from '@standardnotes/domain-events'
import { SubscriptionRenewedEventHandler } from './SubscriptionRenewedEventHandler'
import { GetUserAnalyticsId } from '../UseCase/GetUserAnalyticsId/GetUserAnalyticsId'
import { AnalyticsStoreInterface } from '../Analytics/AnalyticsStoreInterface'
import { SaveRevenueModification } from '../UseCase/SaveRevenueModification/SaveRevenueModification'
import { RevenueModification } from '../Revenue/RevenueModification'
import { Result } from '../Core/Result'
describe('SubscriptionRenewedEventHandler', () => {
let event: SubscriptionRenewedEvent
let getUserAnalyticsId: GetUserAnalyticsId
let analyticsStore: AnalyticsStoreInterface
let saveRevenueModification: SaveRevenueModification
const createHandler = () => new SubscriptionRenewedEventHandler(getUserAnalyticsId, analyticsStore)
const createHandler = () =>
new SubscriptionRenewedEventHandler(getUserAnalyticsId, analyticsStore, saveRevenueModification)
beforeEach(() => {
event = {} as jest.Mocked<SubscriptionRenewedEvent>
event.createdAt = new Date(1)
event.type = 'SUBSCRIPTION_RENEWED'
event.payload = {
subscriptionId: 1,
userEmail: 'test@test.com',
@@ -24,6 +30,8 @@ describe('SubscriptionRenewedEventHandler', () => {
subscriptionExpiresAt: 2,
timestamp: 1,
offline: false,
billingFrequency: 1,
payAmount: 12.99,
}
getUserAnalyticsId = {} as jest.Mocked<GetUserAnalyticsId>
@@ -32,6 +40,9 @@ describe('SubscriptionRenewedEventHandler', () => {
analyticsStore = {} as jest.Mocked<AnalyticsStoreInterface>
analyticsStore.markActivity = jest.fn()
analyticsStore.unmarkActivity = jest.fn()
saveRevenueModification = {} as jest.Mocked<SaveRevenueModification>
saveRevenueModification.execute = jest.fn().mockReturnValue(Result.ok<RevenueModification>())
})
it('should track subscription renewed statistics', async () => {
@@ -39,5 +50,6 @@ describe('SubscriptionRenewedEventHandler', () => {
expect(analyticsStore.markActivity).toHaveBeenCalled()
expect(analyticsStore.unmarkActivity).toHaveBeenCalled()
expect(saveRevenueModification.execute).toHaveBeenCalled()
})
})

View File

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

View File

@@ -1,3 +1,5 @@
import { injectable } from 'inversify'
import { TypeORMRevenueModification } from '../../Infra/TypeORM/TypeORMRevenueModification'
import { UniqueEntityId } from '../Core/UniqueEntityId'
import { MonthlyRevenue } from '../Revenue/MonthlyRevenue'
@@ -9,6 +11,7 @@ import { Email } from '../Common/Email'
import { SubscriptionPlanName } from '../Subscription/SubscriptionPlanName'
import { SubscriptionEventType } from '../Subscription/SubscriptionEventType'
@injectable()
export class RevenueModificationMap implements MapInterface<RevenueModification, TypeORMRevenueModification> {
toDomain(persistence: TypeORMRevenueModification): RevenueModification {
const user = User.create(

View File

@@ -12,7 +12,11 @@ describe('GetUserAnalyticsId', () => {
const createUseCase = () => new GetUserAnalyticsId(analyticsEntityRepository)
beforeEach(() => {
analyticsEntity = { id: 123 } as jest.Mocked<AnalyticsEntity>
analyticsEntity = {
id: 123,
userUuid: '1-2-3',
userEmail: 'test@test.te',
} as jest.Mocked<AnalyticsEntity>
analyticsEntityRepository = {} as jest.Mocked<AnalyticsEntityRepositoryInterface>
analyticsEntityRepository.findOneByUserUuid = jest.fn().mockReturnValue(analyticsEntity)
@@ -20,11 +24,11 @@ describe('GetUserAnalyticsId', () => {
})
it('should return analytics id for a user by uuid', async () => {
expect(await createUseCase().execute({ userUuid: '1-2-3' })).toEqual({ analyticsId: 123 })
expect(await (await createUseCase().execute({ userUuid: '1-2-3' })).analyticsId).toEqual(123)
})
it('should return analytics id for a user by email', async () => {
expect(await createUseCase().execute({ userEmail: 'test@test.te' })).toEqual({ analyticsId: 123 })
expect(await (await createUseCase().execute({ userEmail: 'test@test.te' })).analyticsId).toEqual(123)
})
it('should throw error if user is missing analytics entity', async () => {

View File

@@ -1,5 +1,7 @@
import { inject, injectable } from 'inversify'
import TYPES from '../../../Bootstrap/Types'
import { Email } from '../../Common/Email'
import { Uuid } from '../../Common/Uuid'
import { AnalyticsEntityRepositoryInterface } from '../../Entity/AnalyticsEntityRepositoryInterface'
import { UseCaseInterface } from '../UseCaseInterface'
import { GetUserAnalyticsIdDTO } from './GetUserAnalyticsIdDTO'
@@ -25,6 +27,8 @@ export class GetUserAnalyticsId implements UseCaseInterface {
return {
analyticsId: analyticsEntity.id,
userUuid: Uuid.create(analyticsEntity.userUuid).getValue(),
userEmail: Email.create(analyticsEntity.userEmail).getValue(),
}
}
}

View File

@@ -1,3 +1,8 @@
import { Email } from '../../Common/Email'
import { Uuid } from '../../Common/Uuid'
export type GetUserAnalyticsIdResponse = {
analyticsId: number
userEmail: Email
userUuid: Uuid
}

View File

@@ -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.
## [1.37.5](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.37.4...@standardnotes/api-gateway@1.37.5) (2022-11-09)
**Note:** Version bump only for package @standardnotes/api-gateway
## [1.37.4](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.37.3...@standardnotes/api-gateway@1.37.4) (2022-11-09)
**Note:** Version bump only for package @standardnotes/api-gateway
## [1.37.3](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.37.2...@standardnotes/api-gateway@1.37.3) (2022-11-09)
**Note:** Version bump only for package @standardnotes/api-gateway
## [1.37.2](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.37.1...@standardnotes/api-gateway@1.37.2) (2022-11-09)
**Note:** Version bump only for package @standardnotes/api-gateway
## [1.37.1](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.37.0...@standardnotes/api-gateway@1.37.1) (2022-11-09)
**Note:** Version bump only for package @standardnotes/api-gateway
# [1.37.0](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.36.14...@standardnotes/api-gateway@1.37.0) (2022-11-07)
### Features

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/api-gateway",
"version": "1.37.0",
"version": "1.37.5",
"engines": {
"node": ">=16.0.0 <17.0.0"
},

View File

@@ -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.59.0](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.58.0...@standardnotes/auth-server@1.59.0) (2022-11-09)
### Features
* **analytics:** add saving revenue modifications upon subscription canceled ([52a257a](https://github.com/standardnotes/server/commit/52a257abb16034134a50474fbbb2493a00c58b99))
# [1.58.0](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.57.0...@standardnotes/auth-server@1.58.0) (2022-11-09)
### Features
* **analytics:** add saving revenue modifications upon subscription refunded ([0f65c05](https://github.com/standardnotes/server/commit/0f65c051abcff805e920f91d338e5fadda7905a9))
# [1.57.0](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.56.0...@standardnotes/auth-server@1.57.0) (2022-11-09)
### Features
* **analytics:** add saving revenue modifications upon subscription expired ([5c3db2c](https://github.com/standardnotes/server/commit/5c3db2cb29a929e44b63eb8226ce4ad1d14f8a99))
# [1.56.0](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.55.0...@standardnotes/auth-server@1.56.0) (2022-11-09)
### Features
* **analytics:** add saving revenue modifications upon subscription renewed ([cdb7fcf](https://github.com/standardnotes/server/commit/cdb7fcf8311fecfabe3ef9eb656cd6ec57b87de0))
# [1.55.0](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.54.0...@standardnotes/auth-server@1.55.0) (2022-11-09)
### Features
* **analytics:** add saving revenue modifications upon subscription purchased ([5ea9941](https://github.com/standardnotes/server/commit/5ea9941519ffb3027527130ec869da14abc5e994))
# [1.54.0](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.53.0...@standardnotes/auth-server@1.54.0) (2022-11-07)
### Features

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/auth-server",
"version": "1.54.0",
"version": "1.59.0",
"engines": {
"node": ">=16.0.0 <17.0.0"
},

View File

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

View File

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

View File

@@ -90,6 +90,8 @@ describe('SubscriptionPurchasedEventHandler', () => {
newSubscriber: true,
totalActiveSubscriptionsCount: 123,
userRegisteredAt: dayjs.utc().valueOf() - 23,
billingFrequency: 12,
payAmount: 29.99,
}
subscriptionSettingService = {} as jest.Mocked<SubscriptionSettingServiceInterface>

View File

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

View File

@@ -81,6 +81,8 @@ describe('SubscriptionRenewedEventHandler', () => {
subscriptionExpiresAt,
timestamp,
offline: false,
billingFrequency: 1,
payAmount: 12.99,
}
logger = {} as jest.Mocked<Logger>

View File

@@ -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.
## [1.9.18](https://github.com/standardnotes/server/compare/@standardnotes/domain-events-infra@1.9.17...@standardnotes/domain-events-infra@1.9.18) (2022-11-09)
**Note:** Version bump only for package @standardnotes/domain-events-infra
## [1.9.17](https://github.com/standardnotes/server/compare/@standardnotes/domain-events-infra@1.9.16...@standardnotes/domain-events-infra@1.9.17) (2022-11-09)
**Note:** Version bump only for package @standardnotes/domain-events-infra
## [1.9.16](https://github.com/standardnotes/server/compare/@standardnotes/domain-events-infra@1.9.15...@standardnotes/domain-events-infra@1.9.16) (2022-11-09)
**Note:** Version bump only for package @standardnotes/domain-events-infra
## [1.9.15](https://github.com/standardnotes/server/compare/@standardnotes/domain-events-infra@1.9.14...@standardnotes/domain-events-infra@1.9.15) (2022-11-09)
**Note:** Version bump only for package @standardnotes/domain-events-infra
## [1.9.14](https://github.com/standardnotes/server/compare/@standardnotes/domain-events-infra@1.9.13...@standardnotes/domain-events-infra@1.9.14) (2022-11-09)
**Note:** Version bump only for package @standardnotes/domain-events-infra
## [1.9.13](https://github.com/standardnotes/server/compare/@standardnotes/domain-events-infra@1.9.12...@standardnotes/domain-events-infra@1.9.13) (2022-11-07)
**Note:** Version bump only for package @standardnotes/domain-events-infra

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/domain-events-infra",
"version": "1.9.13",
"version": "1.9.18",
"engines": {
"node": ">=16.0.0 <17.0.0"
},

View File

@@ -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.
# [2.83.0](https://github.com/standardnotes/server/compare/@standardnotes/domain-events@2.82.0...@standardnotes/domain-events@2.83.0) (2022-11-09)
### Features
* **analytics:** add saving revenue modifications upon subscription canceled ([52a257a](https://github.com/standardnotes/server/commit/52a257abb16034134a50474fbbb2493a00c58b99))
# [2.82.0](https://github.com/standardnotes/server/compare/@standardnotes/domain-events@2.81.0...@standardnotes/domain-events@2.82.0) (2022-11-09)
### Features
* **analytics:** add saving revenue modifications upon subscription refunded ([0f65c05](https://github.com/standardnotes/server/commit/0f65c051abcff805e920f91d338e5fadda7905a9))
# [2.81.0](https://github.com/standardnotes/server/compare/@standardnotes/domain-events@2.80.0...@standardnotes/domain-events@2.81.0) (2022-11-09)
### Features
* **analytics:** add saving revenue modifications upon subscription expired ([5c3db2c](https://github.com/standardnotes/server/commit/5c3db2cb29a929e44b63eb8226ce4ad1d14f8a99))
# [2.80.0](https://github.com/standardnotes/server/compare/@standardnotes/domain-events@2.79.0...@standardnotes/domain-events@2.80.0) (2022-11-09)
### Features
* **analytics:** add saving revenue modifications upon subscription renewed ([cdb7fcf](https://github.com/standardnotes/server/commit/cdb7fcf8311fecfabe3ef9eb656cd6ec57b87de0))
# [2.79.0](https://github.com/standardnotes/server/compare/@standardnotes/domain-events@2.78.1...@standardnotes/domain-events@2.79.0) (2022-11-09)
### Features
* **analytics:** add saving revenue modifications upon subscription purchased ([5ea9941](https://github.com/standardnotes/server/commit/5ea9941519ffb3027527130ec869da14abc5e994))
## [2.78.1](https://github.com/standardnotes/server/compare/@standardnotes/domain-events@2.78.0...@standardnotes/domain-events@2.78.1) (2022-11-07)
**Note:** Version bump only for package @standardnotes/domain-events

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/domain-events",
"version": "2.78.1",
"version": "2.83.0",
"engines": {
"node": ">=16.0.0 <17.0.0"
},

View File

@@ -11,4 +11,7 @@ export interface SubscriptionCancelledEventPayload {
timestamp: number
offline: boolean
replaced: boolean
userExistingSubscriptionsCount: number
billingFrequency: number
payAmount: number
}

View File

@@ -7,4 +7,7 @@ export interface SubscriptionExpiredEventPayload {
timestamp: number
offline: boolean
totalActiveSubscriptionsCount: number
userExistingSubscriptionsCount: number
billingFrequency: number
payAmount: number
}

View File

@@ -12,4 +12,6 @@ export interface SubscriptionPurchasedEventPayload {
newSubscriber: boolean
totalActiveSubscriptionsCount: number
userRegisteredAt: number
billingFrequency: number
payAmount: number
}

View File

@@ -8,4 +8,6 @@ export interface SubscriptionRefundedEventPayload {
totalActiveSubscriptionsCount: number
timestamp: number
offline: boolean
billingFrequency: number
payAmount: number
}

View File

@@ -7,4 +7,6 @@ export interface SubscriptionRenewedEventPayload {
subscriptionExpiresAt: number
timestamp: number
offline: boolean
billingFrequency: number
payAmount: number
}

View File

@@ -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.
## [1.6.13](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.6.12...@standardnotes/event-store@1.6.13) (2022-11-09)
**Note:** Version bump only for package @standardnotes/event-store
## [1.6.12](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.6.11...@standardnotes/event-store@1.6.12) (2022-11-09)
**Note:** Version bump only for package @standardnotes/event-store
## [1.6.11](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.6.10...@standardnotes/event-store@1.6.11) (2022-11-09)
**Note:** Version bump only for package @standardnotes/event-store
## [1.6.10](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.6.9...@standardnotes/event-store@1.6.10) (2022-11-09)
**Note:** Version bump only for package @standardnotes/event-store
## [1.6.9](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.6.8...@standardnotes/event-store@1.6.9) (2022-11-09)
**Note:** Version bump only for package @standardnotes/event-store
## [1.6.8](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.6.7...@standardnotes/event-store@1.6.8) (2022-11-07)
**Note:** Version bump only for package @standardnotes/event-store

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/event-store",
"version": "1.6.8",
"version": "1.6.13",
"description": "Event Store Service",
"private": true,
"main": "dist/src/index.js",

View File

@@ -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.
## [1.8.13](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.8.12...@standardnotes/files-server@1.8.13) (2022-11-09)
**Note:** Version bump only for package @standardnotes/files-server
## [1.8.12](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.8.11...@standardnotes/files-server@1.8.12) (2022-11-09)
**Note:** Version bump only for package @standardnotes/files-server
## [1.8.11](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.8.10...@standardnotes/files-server@1.8.11) (2022-11-09)
**Note:** Version bump only for package @standardnotes/files-server
## [1.8.10](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.8.9...@standardnotes/files-server@1.8.10) (2022-11-09)
**Note:** Version bump only for package @standardnotes/files-server
## [1.8.9](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.8.8...@standardnotes/files-server@1.8.9) (2022-11-09)
**Note:** Version bump only for package @standardnotes/files-server
## [1.8.8](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.8.7...@standardnotes/files-server@1.8.8) (2022-11-07)
**Note:** Version bump only for package @standardnotes/files-server

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/files-server",
"version": "1.8.8",
"version": "1.8.13",
"engines": {
"node": ">=16.0.0 <17.0.0"
},

View File

@@ -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.
## [1.13.14](https://github.com/standardnotes/server/compare/@standardnotes/scheduler-server@1.13.13...@standardnotes/scheduler-server@1.13.14) (2022-11-09)
**Note:** Version bump only for package @standardnotes/scheduler-server
## [1.13.13](https://github.com/standardnotes/server/compare/@standardnotes/scheduler-server@1.13.12...@standardnotes/scheduler-server@1.13.13) (2022-11-09)
**Note:** Version bump only for package @standardnotes/scheduler-server
## [1.13.12](https://github.com/standardnotes/server/compare/@standardnotes/scheduler-server@1.13.11...@standardnotes/scheduler-server@1.13.12) (2022-11-09)
**Note:** Version bump only for package @standardnotes/scheduler-server
## [1.13.11](https://github.com/standardnotes/server/compare/@standardnotes/scheduler-server@1.13.10...@standardnotes/scheduler-server@1.13.11) (2022-11-09)
**Note:** Version bump only for package @standardnotes/scheduler-server
## [1.13.10](https://github.com/standardnotes/server/compare/@standardnotes/scheduler-server@1.13.9...@standardnotes/scheduler-server@1.13.10) (2022-11-09)
**Note:** Version bump only for package @standardnotes/scheduler-server
## [1.13.9](https://github.com/standardnotes/server/compare/@standardnotes/scheduler-server@1.13.8...@standardnotes/scheduler-server@1.13.9) (2022-11-07)
**Note:** Version bump only for package @standardnotes/scheduler-server

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/scheduler-server",
"version": "1.13.9",
"version": "1.13.14",
"engines": {
"node": ">=16.0.0 <17.0.0"
},

View File

@@ -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.
## [1.11.5](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.11.4...@standardnotes/syncing-server@1.11.5) (2022-11-09)
**Note:** Version bump only for package @standardnotes/syncing-server
## [1.11.4](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.11.3...@standardnotes/syncing-server@1.11.4) (2022-11-09)
**Note:** Version bump only for package @standardnotes/syncing-server
## [1.11.3](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.11.2...@standardnotes/syncing-server@1.11.3) (2022-11-09)
**Note:** Version bump only for package @standardnotes/syncing-server
## [1.11.2](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.11.1...@standardnotes/syncing-server@1.11.2) (2022-11-09)
**Note:** Version bump only for package @standardnotes/syncing-server
## [1.11.1](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.11.0...@standardnotes/syncing-server@1.11.1) (2022-11-09)
**Note:** Version bump only for package @standardnotes/syncing-server
# [1.11.0](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.10.25...@standardnotes/syncing-server@1.11.0) (2022-11-07)
### Features

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/syncing-server",
"version": "1.11.0",
"version": "1.11.5",
"engines": {
"node": ">=16.0.0 <17.0.0"
},

View File

@@ -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.
## [1.4.13](https://github.com/standardnotes/server/compare/@standardnotes/websockets-server@1.4.12...@standardnotes/websockets-server@1.4.13) (2022-11-09)
**Note:** Version bump only for package @standardnotes/websockets-server
## [1.4.12](https://github.com/standardnotes/server/compare/@standardnotes/websockets-server@1.4.11...@standardnotes/websockets-server@1.4.12) (2022-11-09)
**Note:** Version bump only for package @standardnotes/websockets-server
## [1.4.11](https://github.com/standardnotes/server/compare/@standardnotes/websockets-server@1.4.10...@standardnotes/websockets-server@1.4.11) (2022-11-09)
**Note:** Version bump only for package @standardnotes/websockets-server
## [1.4.10](https://github.com/standardnotes/server/compare/@standardnotes/websockets-server@1.4.9...@standardnotes/websockets-server@1.4.10) (2022-11-09)
**Note:** Version bump only for package @standardnotes/websockets-server
## [1.4.9](https://github.com/standardnotes/server/compare/@standardnotes/websockets-server@1.4.8...@standardnotes/websockets-server@1.4.9) (2022-11-09)
**Note:** Version bump only for package @standardnotes/websockets-server
## [1.4.8](https://github.com/standardnotes/server/compare/@standardnotes/websockets-server@1.4.7...@standardnotes/websockets-server@1.4.8) (2022-11-07)
**Note:** Version bump only for package @standardnotes/websockets-server

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/websockets-server",
"version": "1.4.8",
"version": "1.4.13",
"engines": {
"node": ">=16.0.0 <17.0.0"
},

View File

@@ -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.
## [1.17.13](https://github.com/standardnotes/server/compare/@standardnotes/workspace-server@1.17.12...@standardnotes/workspace-server@1.17.13) (2022-11-09)
**Note:** Version bump only for package @standardnotes/workspace-server
## [1.17.12](https://github.com/standardnotes/server/compare/@standardnotes/workspace-server@1.17.11...@standardnotes/workspace-server@1.17.12) (2022-11-09)
**Note:** Version bump only for package @standardnotes/workspace-server
## [1.17.11](https://github.com/standardnotes/server/compare/@standardnotes/workspace-server@1.17.10...@standardnotes/workspace-server@1.17.11) (2022-11-09)
**Note:** Version bump only for package @standardnotes/workspace-server
## [1.17.10](https://github.com/standardnotes/server/compare/@standardnotes/workspace-server@1.17.9...@standardnotes/workspace-server@1.17.10) (2022-11-09)
**Note:** Version bump only for package @standardnotes/workspace-server
## [1.17.9](https://github.com/standardnotes/server/compare/@standardnotes/workspace-server@1.17.8...@standardnotes/workspace-server@1.17.9) (2022-11-09)
**Note:** Version bump only for package @standardnotes/workspace-server
## [1.17.8](https://github.com/standardnotes/server/compare/@standardnotes/workspace-server@1.17.7...@standardnotes/workspace-server@1.17.8) (2022-11-07)
**Note:** Version bump only for package @standardnotes/workspace-server

View File

@@ -1,6 +1,6 @@
{
"name": "@standardnotes/workspace-server",
"version": "1.17.8",
"version": "1.17.13",
"engines": {
"node": ">=16.0.0 <17.0.0"
},