mirror of
https://github.com/standardnotes/server
synced 2026-02-06 20:02:09 -05:00
Compare commits
13 Commits
@standardn
...
@standardn
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5f67e45911 | ||
|
|
fddf9fccbd | ||
|
|
2bedbd7bd2 | ||
|
|
02f3c85796 | ||
|
|
3b5bd6a47f | ||
|
|
06fd404d44 | ||
|
|
d931c52508 | ||
|
|
800fe9e4c8 | ||
|
|
8b3d78678f | ||
|
|
2351cd3ad6 | ||
|
|
dd86c5bcdf | ||
|
|
d0c00e306e | ||
|
|
6cd68ddd6a |
@@ -3,6 +3,28 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [2.12.2](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.12.1...@standardnotes/analytics@2.12.2) (2022-12-05)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/analytics
|
||||
|
||||
## [2.12.1](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.12.0...@standardnotes/analytics@2.12.1) (2022-12-05)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/analytics
|
||||
|
||||
# [2.12.0](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.11.17...@standardnotes/analytics@2.12.0) (2022-12-05)
|
||||
|
||||
### Features
|
||||
|
||||
* **domain-core:** distinguish between username and email ([06fd404](https://github.com/standardnotes/server/commit/06fd404d44b44a53733f889aabd4da63f21e2f36))
|
||||
|
||||
## [2.11.17](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.11.16...@standardnotes/analytics@2.11.17) (2022-12-02)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/analytics
|
||||
|
||||
## [2.11.16](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.11.15...@standardnotes/analytics@2.11.16) (2022-12-02)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/analytics
|
||||
|
||||
## [2.11.15](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.11.14...@standardnotes/analytics@2.11.15) (2022-11-30)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/analytics
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/analytics",
|
||||
"version": "2.11.15",
|
||||
"version": "2.12.2",
|
||||
"engines": {
|
||||
"node": ">=18.0.0 <19.0.0"
|
||||
},
|
||||
|
||||
@@ -18,5 +18,5 @@ export class AnalyticsEntity {
|
||||
nullable: true,
|
||||
})
|
||||
@Index('email')
|
||||
declare userEmail: string
|
||||
declare username: string
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { DomainEventHandlerInterface, SubscriptionCancelledEvent } from '@standardnotes/domain-events'
|
||||
import { inject, injectable } from 'inversify'
|
||||
import { Logger } from 'winston'
|
||||
import { Email } from '@standardnotes/domain-core'
|
||||
import { Username } from '@standardnotes/domain-core'
|
||||
|
||||
import TYPES from '../../Bootstrap/Types'
|
||||
import { AnalyticsActivity } from '../Analytics/AnalyticsActivity'
|
||||
@@ -41,7 +41,7 @@ export class SubscriptionCancelledEventHandler implements DomainEventHandlerInte
|
||||
payedAmount: event.payload.payAmount,
|
||||
planName: SubscriptionPlanName.create(event.payload.subscriptionName).getValue(),
|
||||
subscriptionId: event.payload.subscriptionId,
|
||||
userEmail: Email.create(event.payload.userEmail).getValue(),
|
||||
username: Username.create(event.payload.userEmail).getValue(),
|
||||
userUuid,
|
||||
})
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Username } from '@standardnotes/domain-core'
|
||||
import { DomainEventHandlerInterface, SubscriptionExpiredEvent } from '@standardnotes/domain-events'
|
||||
import { inject, injectable } from 'inversify'
|
||||
import { Logger } from 'winston'
|
||||
import { Email } from '@standardnotes/domain-core'
|
||||
|
||||
import TYPES from '../../Bootstrap/Types'
|
||||
import { AnalyticsActivity } from '../Analytics/AnalyticsActivity'
|
||||
@@ -45,7 +45,7 @@ export class SubscriptionExpiredEventHandler implements DomainEventHandlerInterf
|
||||
payedAmount: event.payload.payAmount,
|
||||
planName: SubscriptionPlanName.create(event.payload.subscriptionName).getValue(),
|
||||
subscriptionId: event.payload.subscriptionId,
|
||||
userEmail: Email.create(event.payload.userEmail).getValue(),
|
||||
username: Username.create(event.payload.userEmail).getValue(),
|
||||
userUuid,
|
||||
})
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Username } from '@standardnotes/domain-core'
|
||||
import { DomainEventHandlerInterface, SubscriptionPurchasedEvent } from '@standardnotes/domain-events'
|
||||
import { inject, injectable } from 'inversify'
|
||||
import { Logger } from 'winston'
|
||||
import { Email } from '@standardnotes/domain-core'
|
||||
|
||||
import TYPES from '../../Bootstrap/Types'
|
||||
import { AnalyticsActivity } from '../Analytics/AnalyticsActivity'
|
||||
@@ -69,7 +69,7 @@ export class SubscriptionPurchasedEventHandler implements DomainEventHandlerInte
|
||||
payedAmount: event.payload.payAmount,
|
||||
planName: SubscriptionPlanName.create(event.payload.subscriptionName).getValue(),
|
||||
subscriptionId: event.payload.subscriptionId,
|
||||
userEmail: Email.create(event.payload.userEmail).getValue(),
|
||||
username: Username.create(event.payload.userEmail).getValue(),
|
||||
userUuid,
|
||||
})
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Username } from '@standardnotes/domain-core'
|
||||
import { DomainEventHandlerInterface, SubscriptionRefundedEvent } from '@standardnotes/domain-events'
|
||||
import { inject, injectable } from 'inversify'
|
||||
import { Logger } from 'winston'
|
||||
import { Email } from '@standardnotes/domain-core'
|
||||
|
||||
import TYPES from '../../Bootstrap/Types'
|
||||
import { AnalyticsActivity } from '../Analytics/AnalyticsActivity'
|
||||
@@ -41,7 +41,7 @@ export class SubscriptionRefundedEventHandler implements DomainEventHandlerInter
|
||||
payedAmount: event.payload.payAmount,
|
||||
planName: SubscriptionPlanName.create(event.payload.subscriptionName).getValue(),
|
||||
subscriptionId: event.payload.subscriptionId,
|
||||
userEmail: Email.create(event.payload.userEmail).getValue(),
|
||||
username: Username.create(event.payload.userEmail).getValue(),
|
||||
userUuid,
|
||||
})
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { DomainEventHandlerInterface, SubscriptionRenewedEvent } from '@standardnotes/domain-events'
|
||||
import { inject, injectable } from 'inversify'
|
||||
import { Email } from '@standardnotes/domain-core'
|
||||
import { Username } from '@standardnotes/domain-core'
|
||||
|
||||
import TYPES from '../../Bootstrap/Types'
|
||||
import { GetUserAnalyticsId } from '../UseCase/GetUserAnalyticsId/GetUserAnalyticsId'
|
||||
@@ -41,7 +41,7 @@ export class SubscriptionRenewedEventHandler implements DomainEventHandlerInterf
|
||||
payedAmount: event.payload.payAmount,
|
||||
planName: SubscriptionPlanName.create(event.payload.subscriptionName).getValue(),
|
||||
subscriptionId: event.payload.subscriptionId,
|
||||
userEmail: Email.create(event.payload.userEmail).getValue(),
|
||||
username: Username.create(event.payload.userEmail).getValue(),
|
||||
userUuid,
|
||||
})
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ export class UserRegisteredEventHandler implements DomainEventHandlerInterface {
|
||||
async handle(event: UserRegisteredEvent): Promise<void> {
|
||||
let analyticsEntity = new AnalyticsEntity()
|
||||
analyticsEntity.userUuid = event.payload.userUuid
|
||||
analyticsEntity.userEmail = event.payload.email
|
||||
analyticsEntity.username = event.payload.email
|
||||
analyticsEntity = await this.analyticsEntityRepository.save(analyticsEntity)
|
||||
|
||||
await this.analyticsStore.markActivity([AnalyticsActivity.Register], analyticsEntity.id, [
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { injectable } from 'inversify'
|
||||
import { Email, MapperInterface, UniqueEntityId } from '@standardnotes/domain-core'
|
||||
import { MapperInterface, UniqueEntityId, Username } from '@standardnotes/domain-core'
|
||||
|
||||
import { TypeORMRevenueModification } from '../../Infra/TypeORM/TypeORMRevenueModification'
|
||||
import { MonthlyRevenue } from '../Revenue/MonthlyRevenue'
|
||||
@@ -14,7 +14,7 @@ export class RevenueModificationMap implements MapperInterface<RevenueModificati
|
||||
toDomain(persistence: TypeORMRevenueModification): RevenueModification {
|
||||
const userOrError = User.create(
|
||||
{
|
||||
email: Email.create(persistence.userEmail).getValue(),
|
||||
username: Username.create(persistence.username).getValue(),
|
||||
},
|
||||
new UniqueEntityId(persistence.userUuid),
|
||||
)
|
||||
@@ -70,7 +70,7 @@ export class RevenueModificationMap implements MapperInterface<RevenueModificati
|
||||
persistence.previousMonthlyRevenue = domain.props.previousMonthlyRevenue.value
|
||||
persistence.subscriptionId = subscription.id.toValue() as number
|
||||
persistence.subscriptionPlan = subscription.props.planName.value
|
||||
persistence.userEmail = user.props.email.value
|
||||
persistence.username = user.props.username.value
|
||||
persistence.userUuid = user.id.toString()
|
||||
persistence.createdAt = domain.props.createdAt
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Email } from '@standardnotes/domain-core'
|
||||
import { Username } from '@standardnotes/domain-core'
|
||||
|
||||
import { Subscription } from '../Subscription/Subscription'
|
||||
import { SubscriptionEventType } from '../Subscription/SubscriptionEventType'
|
||||
@@ -19,7 +19,7 @@ describe('RevenueModification', () => {
|
||||
planName: SubscriptionPlanName.create('PRO_PLAN').getValue(),
|
||||
}).getValue()
|
||||
user = User.create({
|
||||
email: Email.create('test@test.te').getValue(),
|
||||
username: Username.create('test@test.te').getValue(),
|
||||
}).getValue()
|
||||
})
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ describe('GetUserAnalyticsId', () => {
|
||||
analyticsEntity = {
|
||||
id: 123,
|
||||
userUuid: '84c0f8e8-544a-4c7e-9adf-26209303bc1d',
|
||||
userEmail: 'test@test.te',
|
||||
username: 'test@test.te',
|
||||
} as jest.Mocked<AnalyticsEntity>
|
||||
|
||||
analyticsEntityRepository = {} as jest.Mocked<AnalyticsEntityRepositoryInterface>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { inject, injectable } from 'inversify'
|
||||
import { Email, Uuid } from '@standardnotes/domain-core'
|
||||
import { Username, Uuid } from '@standardnotes/domain-core'
|
||||
|
||||
import TYPES from '../../../Bootstrap/Types'
|
||||
import { AnalyticsEntityRepositoryInterface } from '../../Entity/AnalyticsEntityRepositoryInterface'
|
||||
@@ -28,7 +28,7 @@ export class GetUserAnalyticsId implements UseCaseInterface {
|
||||
return {
|
||||
analyticsId: analyticsEntity.id,
|
||||
userUuid: Uuid.create(analyticsEntity.userUuid).getValue(),
|
||||
userEmail: Email.create(analyticsEntity.userEmail).getValue(),
|
||||
username: Username.create(analyticsEntity.username).getValue(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Email, Uuid } from '@standardnotes/domain-core'
|
||||
import { Username, Uuid } from '@standardnotes/domain-core'
|
||||
|
||||
export type GetUserAnalyticsIdResponse = {
|
||||
analyticsId: number
|
||||
userEmail: Email
|
||||
username: Username
|
||||
userUuid: Uuid
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import 'reflect-metadata'
|
||||
|
||||
import { TimerInterface } from '@standardnotes/time'
|
||||
import { Email, Result, Uuid } from '@standardnotes/domain-core'
|
||||
import { Result, Username, Uuid } from '@standardnotes/domain-core'
|
||||
|
||||
import { MonthlyRevenue } from '../../Revenue/MonthlyRevenue'
|
||||
|
||||
@@ -45,7 +45,7 @@ describe('SaveRevenueModification', () => {
|
||||
payedAmount: 12.99,
|
||||
planName: SubscriptionPlanName.create('PRO_PLAN').getValue(),
|
||||
subscriptionId: 1234,
|
||||
userEmail: Email.create('test@test.te').getValue(),
|
||||
username: Username.create('test@test.te').getValue(),
|
||||
userUuid: Uuid.create('84c0f8e8-544a-4c7e-9adf-26209303bc1d').getValue(),
|
||||
})
|
||||
|
||||
@@ -63,7 +63,7 @@ describe('SaveRevenueModification', () => {
|
||||
payedAmount: 12.99,
|
||||
planName: SubscriptionPlanName.create('PRO_PLAN').getValue(),
|
||||
subscriptionId: 1234,
|
||||
userEmail: Email.create('test@test.te').getValue(),
|
||||
username: Username.create('test@test.te').getValue(),
|
||||
userUuid: Uuid.create('84c0f8e8-544a-4c7e-9adf-26209303bc1d').getValue(),
|
||||
})
|
||||
|
||||
@@ -81,7 +81,7 @@ describe('SaveRevenueModification', () => {
|
||||
payedAmount: 2,
|
||||
planName: SubscriptionPlanName.create('PRO_PLAN').getValue(),
|
||||
subscriptionId: 1234,
|
||||
userEmail: Email.create('test@test.te').getValue(),
|
||||
username: Username.create('test@test.te').getValue(),
|
||||
userUuid: Uuid.create('84c0f8e8-544a-4c7e-9adf-26209303bc1d').getValue(),
|
||||
})
|
||||
|
||||
@@ -101,7 +101,7 @@ describe('SaveRevenueModification', () => {
|
||||
payedAmount: 12.99,
|
||||
planName: SubscriptionPlanName.create('PRO_PLAN').getValue(),
|
||||
subscriptionId: 1234,
|
||||
userEmail: Email.create('test@test.te').getValue(),
|
||||
username: Username.create('test@test.te').getValue(),
|
||||
userUuid: Uuid.create('84c0f8e8-544a-4c7e-9adf-26209303bc1d').getValue(),
|
||||
})
|
||||
|
||||
@@ -122,7 +122,7 @@ describe('SaveRevenueModification', () => {
|
||||
payedAmount: 12.99,
|
||||
planName: SubscriptionPlanName.create('PRO_PLAN').getValue(),
|
||||
subscriptionId: 1234,
|
||||
userEmail: Email.create('test@test.te').getValue(),
|
||||
username: Username.create('test@test.te').getValue(),
|
||||
userUuid: Uuid.create('84c0f8e8-544a-4c7e-9adf-26209303bc1d').getValue(),
|
||||
})
|
||||
|
||||
@@ -142,7 +142,7 @@ describe('SaveRevenueModification', () => {
|
||||
payedAmount: 12.99,
|
||||
planName: SubscriptionPlanName.create('PRO_PLAN').getValue(),
|
||||
subscriptionId: 1234,
|
||||
userEmail: Email.create('test@test.te').getValue(),
|
||||
username: Username.create('test@test.te').getValue(),
|
||||
userUuid: Uuid.create('84c0f8e8-544a-4c7e-9adf-26209303bc1d').getValue(),
|
||||
})
|
||||
|
||||
@@ -162,7 +162,7 @@ describe('SaveRevenueModification', () => {
|
||||
payedAmount: 12.99,
|
||||
planName: SubscriptionPlanName.create('PRO_PLAN').getValue(),
|
||||
subscriptionId: 1234,
|
||||
userEmail: Email.create('test@test.te').getValue(),
|
||||
username: Username.create('test@test.te').getValue(),
|
||||
userUuid: Uuid.create('84c0f8e8-544a-4c7e-9adf-26209303bc1d').getValue(),
|
||||
})
|
||||
|
||||
@@ -182,7 +182,7 @@ describe('SaveRevenueModification', () => {
|
||||
payedAmount: 12.99,
|
||||
planName: SubscriptionPlanName.create('PRO_PLAN').getValue(),
|
||||
subscriptionId: 1234,
|
||||
userEmail: Email.create('test@test.te').getValue(),
|
||||
username: Username.create('test@test.te').getValue(),
|
||||
userUuid: Uuid.create('84c0f8e8-544a-4c7e-9adf-26209303bc1d').getValue(),
|
||||
})
|
||||
|
||||
@@ -202,7 +202,7 @@ describe('SaveRevenueModification', () => {
|
||||
payedAmount: 12.99,
|
||||
planName: SubscriptionPlanName.create('PRO_PLAN').getValue(),
|
||||
subscriptionId: 1234,
|
||||
userEmail: Email.create('test@test.te').getValue(),
|
||||
username: Username.create('test@test.te').getValue(),
|
||||
userUuid: Uuid.create('84c0f8e8-544a-4c7e-9adf-26209303bc1d').getValue(),
|
||||
})
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ export class SaveRevenueModification implements DomainUseCaseInterface<RevenueMo
|
||||
async execute(dto: SaveRevenueModificationDTO): Promise<Result<RevenueModification>> {
|
||||
const userOrError = User.create(
|
||||
{
|
||||
email: dto.userEmail,
|
||||
username: dto.username,
|
||||
},
|
||||
new UniqueEntityId(dto.userUuid.value),
|
||||
)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Email, Uuid } from '@standardnotes/domain-core'
|
||||
import { Username, Uuid } from '@standardnotes/domain-core'
|
||||
|
||||
import { SubscriptionEventType } from '../../Subscription/SubscriptionEventType'
|
||||
import { SubscriptionPlanName } from '../../Subscription/SubscriptionPlanName'
|
||||
@@ -9,7 +9,7 @@ export interface SaveRevenueModificationDTO {
|
||||
planName: SubscriptionPlanName
|
||||
newSubscriber: boolean
|
||||
userUuid: Uuid
|
||||
userEmail: Email
|
||||
username: Username
|
||||
subscriptionId: number
|
||||
billingFrequency: number
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { Email } from '@standardnotes/domain-core'
|
||||
import { Username } from '@standardnotes/domain-core'
|
||||
|
||||
import { User } from './User'
|
||||
|
||||
describe('User', () => {
|
||||
it('should create an entity', () => {
|
||||
const user = User.create({
|
||||
email: Email.create('test@test.te').getValue(),
|
||||
username: Username.create('test@test.te').getValue(),
|
||||
}).getValue()
|
||||
|
||||
expect(user.id.toString()).toHaveLength(36)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Email } from '@standardnotes/domain-core'
|
||||
import { Username } from '@standardnotes/domain-core'
|
||||
|
||||
export interface UserProps {
|
||||
email: Email
|
||||
username: Username
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ export class TypeORMRevenueModification {
|
||||
length: 255,
|
||||
})
|
||||
@Index('email')
|
||||
declare userEmail: string
|
||||
declare username: string
|
||||
|
||||
@Column({
|
||||
name: 'user_uuid',
|
||||
|
||||
@@ -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.39.7](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.39.6...@standardnotes/api-gateway@1.39.7) (2022-12-05)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/api-gateway
|
||||
|
||||
## [1.39.6](https://github.com/standardnotes/api-gateway/compare/@standardnotes/api-gateway@1.39.5...@standardnotes/api-gateway@1.39.6) (2022-11-30)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/api-gateway
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/api-gateway",
|
||||
"version": "1.39.6",
|
||||
"version": "1.39.7",
|
||||
"engines": {
|
||||
"node": ">=18.0.0 <19.0.0"
|
||||
},
|
||||
|
||||
@@ -3,6 +3,10 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.60.16](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.60.15...@standardnotes/auth-server@1.60.16) (2022-12-05)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/auth-server
|
||||
|
||||
## [1.60.15](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.60.14...@standardnotes/auth-server@1.60.15) (2022-11-30)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/auth-server
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/auth-server",
|
||||
"version": "1.60.15",
|
||||
"version": "1.60.16",
|
||||
"engines": {
|
||||
"node": ">=18.0.0 <19.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.8.0](https://github.com/standardnotes/server/compare/@standardnotes/domain-core@1.7.0...@standardnotes/domain-core@1.8.0) (2022-12-05)
|
||||
|
||||
### Features
|
||||
|
||||
* **domain-core:** add email subscription rejection levels ([02f3c85](https://github.com/standardnotes/server/commit/02f3c85796ade7cb69edbdda2367c0d91ac1bdf0))
|
||||
|
||||
# [1.7.0](https://github.com/standardnotes/server/compare/@standardnotes/domain-core@1.6.0...@standardnotes/domain-core@1.7.0) (2022-12-05)
|
||||
|
||||
### Features
|
||||
|
||||
* **domain-core:** distinguish between username and email ([06fd404](https://github.com/standardnotes/server/commit/06fd404d44b44a53733f889aabd4da63f21e2f36))
|
||||
|
||||
# [1.6.0](https://github.com/standardnotes/server/compare/@standardnotes/domain-core@1.5.2...@standardnotes/domain-core@1.6.0) (2022-12-02)
|
||||
|
||||
### Features
|
||||
|
||||
* **domain-core:** add subscription plan name value object ([800fe9e](https://github.com/standardnotes/server/commit/800fe9e4c80c33f2da8097b5a153f470a23b7984))
|
||||
|
||||
## [1.5.2](https://github.com/standardnotes/server/compare/@standardnotes/domain-core@1.5.1...@standardnotes/domain-core@1.5.2) (2022-12-02)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **domain-core:** rename timestamps to dates ([dd86c5b](https://github.com/standardnotes/server/commit/dd86c5bcdf3a1a37d684f6416d4cc6f24497fe5e))
|
||||
|
||||
## [1.5.1](https://github.com/standardnotes/server/compare/@standardnotes/domain-core@1.5.0...@standardnotes/domain-core@1.5.1) (2022-11-25)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/domain-core
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/domain-core",
|
||||
"version": "1.5.1",
|
||||
"version": "1.8.0",
|
||||
"engines": {
|
||||
"node": ">=18.0.0 <19.0.0"
|
||||
},
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { Timestamps } from './Timestamps'
|
||||
import { Dates } from './Dates'
|
||||
|
||||
describe('Timestamps', () => {
|
||||
describe('Dates', () => {
|
||||
it('should create a value object', () => {
|
||||
const valueOrError = Timestamps.create(new Date(1), new Date(2))
|
||||
const valueOrError = Dates.create(new Date(1), new Date(2))
|
||||
|
||||
expect(valueOrError.isFailed()).toBeFalsy()
|
||||
expect(valueOrError.getValue().createdAt).toEqual(new Date(1))
|
||||
@@ -10,11 +10,11 @@ describe('Timestamps', () => {
|
||||
})
|
||||
|
||||
it('should not create an invalid value object', () => {
|
||||
let valueOrError = Timestamps.create(null as unknown as Date, '2' as unknown as Date)
|
||||
let valueOrError = Dates.create(null as unknown as Date, '2' as unknown as Date)
|
||||
|
||||
expect(valueOrError.isFailed()).toBeTruthy()
|
||||
|
||||
valueOrError = Timestamps.create(new Date(2), '2' as unknown as Date)
|
||||
valueOrError = Dates.create(new Date(2), '2' as unknown as Date)
|
||||
|
||||
expect(valueOrError.isFailed()).toBeTruthy()
|
||||
})
|
||||
28
packages/domain-core/src/Domain/Common/Dates.ts
Normal file
28
packages/domain-core/src/Domain/Common/Dates.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
import { Result } from '../Core/Result'
|
||||
import { ValueObject } from '../Core/ValueObject'
|
||||
import { DatesProps } from './DatesProps'
|
||||
|
||||
export class Dates extends ValueObject<DatesProps> {
|
||||
get createdAt(): Date {
|
||||
return this.props.createdAt
|
||||
}
|
||||
|
||||
get updatedAt(): Date {
|
||||
return this.props.updatedAt
|
||||
}
|
||||
|
||||
private constructor(props: DatesProps) {
|
||||
super(props)
|
||||
}
|
||||
|
||||
static create(createdAt: Date, updatedAt: Date): Result<Dates> {
|
||||
if (!(createdAt instanceof Date)) {
|
||||
return Result.fail<Dates>(`Could not create Dates. Creation date should be a date object, given: ${createdAt}`)
|
||||
}
|
||||
if (!(updatedAt instanceof Date)) {
|
||||
return Result.fail<Dates>(`Could not create Dates. Update date should be a date object, given: ${createdAt}`)
|
||||
}
|
||||
|
||||
return Result.ok<Dates>(new Dates({ createdAt, updatedAt }))
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
export interface TimestampsProps {
|
||||
export interface DatesProps {
|
||||
createdAt: Date
|
||||
updatedAt: Date
|
||||
}
|
||||
@@ -9,7 +9,7 @@ describe('Email', () => {
|
||||
})
|
||||
|
||||
it('should not create an invalid value object', () => {
|
||||
const valueOrError = Email.create('')
|
||||
const valueOrError = Email.create('foobar')
|
||||
|
||||
expect(valueOrError.isFailed()).toBeTruthy()
|
||||
})
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { ValueObject } from '../Core/ValueObject'
|
||||
import { Result } from '../Core/Result'
|
||||
import { EmailProps } from './EmailProps'
|
||||
import { Validator } from '../Core/Validator'
|
||||
|
||||
export class Email extends ValueObject<EmailProps> {
|
||||
get value(): string {
|
||||
@@ -12,10 +13,11 @@ export class Email extends ValueObject<EmailProps> {
|
||||
}
|
||||
|
||||
static create(email: string): Result<Email> {
|
||||
if (!!email === false || email.length === 0) {
|
||||
return Result.fail<Email>('Email cannot be empty')
|
||||
} else {
|
||||
return Result.ok<Email>(new Email({ value: email }))
|
||||
const emailValidation = Validator.isValidEmail(email)
|
||||
if (emailValidation.isFailed()) {
|
||||
return Result.fail<Email>(emailValidation.getError())
|
||||
}
|
||||
|
||||
return Result.ok<Email>(new Email({ value: email }))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ import { RoleName } from './RoleName'
|
||||
|
||||
describe('RoleName', () => {
|
||||
it('should create a value object', () => {
|
||||
const valueOrError = RoleName.create('PRO_USER')
|
||||
const valueOrError = RoleName.create(RoleName.NAMES.ProUser)
|
||||
|
||||
expect(valueOrError.isFailed()).toBeFalsy()
|
||||
expect(valueOrError.getValue().value).toEqual('PRO_USER')
|
||||
@@ -17,9 +17,9 @@ describe('RoleName', () => {
|
||||
})
|
||||
|
||||
it('should say if a role has more power or equal power to another role', () => {
|
||||
const proUserRole = RoleName.create('PRO_USER').getValue()
|
||||
const plusUserRole = RoleName.create('PLUS_USER').getValue()
|
||||
const coreUser = RoleName.create('CORE_USER').getValue()
|
||||
const proUserRole = RoleName.create(RoleName.NAMES.ProUser).getValue()
|
||||
const plusUserRole = RoleName.create(RoleName.NAMES.PlusUser).getValue()
|
||||
const coreUser = RoleName.create(RoleName.NAMES.CoreUser).getValue()
|
||||
|
||||
expect(proUserRole.hasMoreOrEqualPowerTo(proUserRole)).toBeTruthy()
|
||||
expect(proUserRole.hasMoreOrEqualPowerTo(plusUserRole)).toBeTruthy()
|
||||
@@ -32,5 +32,7 @@ describe('RoleName', () => {
|
||||
expect(coreUser.hasMoreOrEqualPowerTo(proUserRole)).toBeFalsy()
|
||||
expect(coreUser.hasMoreOrEqualPowerTo(plusUserRole)).toBeFalsy()
|
||||
expect(coreUser.hasMoreOrEqualPowerTo(coreUser)).toBeTruthy()
|
||||
|
||||
expect(RoleName.create(RoleName.NAMES.FilesBetaUser).getValue().hasMoreOrEqualPowerTo(coreUser)).toBeFalsy()
|
||||
})
|
||||
})
|
||||
|
||||
@@ -3,7 +3,7 @@ import { Result } from '../Core/Result'
|
||||
import { RoleNameProps } from './RoleNameProps'
|
||||
|
||||
export class RoleName extends ValueObject<RoleNameProps> {
|
||||
private static readonly NAMES = {
|
||||
static readonly NAMES = {
|
||||
CoreUser: 'CORE_USER',
|
||||
PlusUser: 'PLUS_USER',
|
||||
ProUser: 'PRO_USER',
|
||||
|
||||
@@ -3,7 +3,7 @@ import { RoleNameCollection } from './RoleNameCollection'
|
||||
|
||||
describe('RoleNameCollection', () => {
|
||||
it('should create a value object', () => {
|
||||
const role1 = RoleName.create('PRO_USER').getValue()
|
||||
const role1 = RoleName.create(RoleName.NAMES.ProUser).getValue()
|
||||
|
||||
const valueOrError = RoleNameCollection.create([role1])
|
||||
|
||||
@@ -12,23 +12,38 @@ describe('RoleNameCollection', () => {
|
||||
})
|
||||
|
||||
it('should tell if collections are not equal', () => {
|
||||
const roles1 = [RoleName.create('PRO_USER').getValue(), RoleName.create('PLUS_USER').getValue()]
|
||||
const roles1 = [
|
||||
RoleName.create(RoleName.NAMES.ProUser).getValue(),
|
||||
RoleName.create(RoleName.NAMES.PlusUser).getValue(),
|
||||
]
|
||||
|
||||
const roles2 = RoleNameCollection.create([
|
||||
RoleName.create('PRO_USER').getValue(),
|
||||
RoleName.create('CORE_USER').getValue(),
|
||||
let roles2 = RoleNameCollection.create([
|
||||
RoleName.create(RoleName.NAMES.ProUser).getValue(),
|
||||
RoleName.create(RoleName.NAMES.CoreUser).getValue(),
|
||||
]).getValue()
|
||||
|
||||
const valueOrError = RoleNameCollection.create(roles1)
|
||||
let valueOrError = RoleNameCollection.create(roles1)
|
||||
expect(valueOrError.getValue().equals(roles2)).toBeFalsy()
|
||||
|
||||
roles2 = RoleNameCollection.create([
|
||||
RoleName.create(RoleName.NAMES.ProUser).getValue(),
|
||||
RoleName.create(RoleName.NAMES.PlusUser).getValue(),
|
||||
RoleName.create(RoleName.NAMES.CoreUser).getValue(),
|
||||
]).getValue()
|
||||
|
||||
valueOrError = RoleNameCollection.create(roles1)
|
||||
expect(valueOrError.getValue().equals(roles2)).toBeFalsy()
|
||||
})
|
||||
|
||||
it('should tell if collections are equal', () => {
|
||||
const roles1 = [RoleName.create('PRO_USER').getValue(), RoleName.create('PLUS_USER').getValue()]
|
||||
const roles1 = [
|
||||
RoleName.create(RoleName.NAMES.ProUser).getValue(),
|
||||
RoleName.create(RoleName.NAMES.PlusUser).getValue(),
|
||||
]
|
||||
|
||||
const roles2 = RoleNameCollection.create([
|
||||
RoleName.create('PRO_USER').getValue(),
|
||||
RoleName.create('PLUS_USER').getValue(),
|
||||
RoleName.create(RoleName.NAMES.ProUser).getValue(),
|
||||
RoleName.create(RoleName.NAMES.PlusUser).getValue(),
|
||||
]).getValue()
|
||||
|
||||
const valueOrError = RoleNameCollection.create(roles1)
|
||||
@@ -36,42 +51,62 @@ describe('RoleNameCollection', () => {
|
||||
})
|
||||
|
||||
it('should tell if collection includes element', () => {
|
||||
const roles1 = [RoleName.create('PRO_USER').getValue(), RoleName.create('PLUS_USER').getValue()]
|
||||
const roles1 = [
|
||||
RoleName.create(RoleName.NAMES.ProUser).getValue(),
|
||||
RoleName.create(RoleName.NAMES.PlusUser).getValue(),
|
||||
]
|
||||
|
||||
const valueOrError = RoleNameCollection.create(roles1)
|
||||
expect(valueOrError.getValue().includes(RoleName.create('PRO_USER').getValue())).toBeTruthy()
|
||||
expect(valueOrError.getValue().includes(RoleName.create(RoleName.NAMES.ProUser).getValue())).toBeTruthy()
|
||||
})
|
||||
|
||||
it('should tell if collection does not includes element', () => {
|
||||
const roles1 = [RoleName.create('PRO_USER').getValue(), RoleName.create('PLUS_USER').getValue()]
|
||||
const roles1 = [
|
||||
RoleName.create(RoleName.NAMES.ProUser).getValue(),
|
||||
RoleName.create(RoleName.NAMES.PlusUser).getValue(),
|
||||
]
|
||||
|
||||
const valueOrError = RoleNameCollection.create(roles1)
|
||||
expect(valueOrError.getValue().includes(RoleName.create('CORE_USER').getValue())).toBeFalsy()
|
||||
expect(valueOrError.getValue().includes(RoleName.create(RoleName.NAMES.CoreUser).getValue())).toBeFalsy()
|
||||
})
|
||||
|
||||
it('should tell if collection has a role with more or equal power to', () => {
|
||||
let roles = [RoleName.create('CORE_USER').getValue()]
|
||||
let roles = [RoleName.create(RoleName.NAMES.CoreUser).getValue()]
|
||||
let valueOrError = RoleNameCollection.create(roles)
|
||||
let roleNames = valueOrError.getValue()
|
||||
|
||||
expect(roleNames.hasARoleNameWithMoreOrEqualPowerTo(RoleName.create('PLUS_USER').getValue())).toBeFalsy()
|
||||
expect(roleNames.hasARoleNameWithMoreOrEqualPowerTo(RoleName.create('PRO_USER').getValue())).toBeFalsy()
|
||||
expect(roleNames.hasARoleNameWithMoreOrEqualPowerTo(RoleName.create('CORE_USER').getValue())).toBeTruthy()
|
||||
expect(
|
||||
roleNames.hasARoleNameWithMoreOrEqualPowerTo(RoleName.create(RoleName.NAMES.PlusUser).getValue()),
|
||||
).toBeFalsy()
|
||||
expect(roleNames.hasARoleNameWithMoreOrEqualPowerTo(RoleName.create(RoleName.NAMES.ProUser).getValue())).toBeFalsy()
|
||||
expect(
|
||||
roleNames.hasARoleNameWithMoreOrEqualPowerTo(RoleName.create(RoleName.NAMES.CoreUser).getValue()),
|
||||
).toBeTruthy()
|
||||
|
||||
roles = [RoleName.create('CORE_USER').getValue(), RoleName.create('PLUS_USER').getValue()]
|
||||
roles = [RoleName.create(RoleName.NAMES.CoreUser).getValue(), RoleName.create(RoleName.NAMES.PlusUser).getValue()]
|
||||
valueOrError = RoleNameCollection.create(roles)
|
||||
roleNames = valueOrError.getValue()
|
||||
|
||||
expect(roleNames.hasARoleNameWithMoreOrEqualPowerTo(RoleName.create('PLUS_USER').getValue())).toBeTruthy()
|
||||
expect(roleNames.hasARoleNameWithMoreOrEqualPowerTo(RoleName.create('PRO_USER').getValue())).toBeFalsy()
|
||||
expect(roleNames.hasARoleNameWithMoreOrEqualPowerTo(RoleName.create('CORE_USER').getValue())).toBeTruthy()
|
||||
expect(
|
||||
roleNames.hasARoleNameWithMoreOrEqualPowerTo(RoleName.create(RoleName.NAMES.PlusUser).getValue()),
|
||||
).toBeTruthy()
|
||||
expect(roleNames.hasARoleNameWithMoreOrEqualPowerTo(RoleName.create(RoleName.NAMES.ProUser).getValue())).toBeFalsy()
|
||||
expect(
|
||||
roleNames.hasARoleNameWithMoreOrEqualPowerTo(RoleName.create(RoleName.NAMES.CoreUser).getValue()),
|
||||
).toBeTruthy()
|
||||
|
||||
roles = [RoleName.create('PRO_USER').getValue(), RoleName.create('PLUS_USER').getValue()]
|
||||
roles = [RoleName.create(RoleName.NAMES.ProUser).getValue(), RoleName.create(RoleName.NAMES.PlusUser).getValue()]
|
||||
valueOrError = RoleNameCollection.create(roles)
|
||||
roleNames = valueOrError.getValue()
|
||||
|
||||
expect(roleNames.hasARoleNameWithMoreOrEqualPowerTo(RoleName.create('PLUS_USER').getValue())).toBeTruthy()
|
||||
expect(roleNames.hasARoleNameWithMoreOrEqualPowerTo(RoleName.create('PRO_USER').getValue())).toBeTruthy()
|
||||
expect(roleNames.hasARoleNameWithMoreOrEqualPowerTo(RoleName.create('CORE_USER').getValue())).toBeTruthy()
|
||||
expect(
|
||||
roleNames.hasARoleNameWithMoreOrEqualPowerTo(RoleName.create(RoleName.NAMES.PlusUser).getValue()),
|
||||
).toBeTruthy()
|
||||
expect(
|
||||
roleNames.hasARoleNameWithMoreOrEqualPowerTo(RoleName.create(RoleName.NAMES.ProUser).getValue()),
|
||||
).toBeTruthy()
|
||||
expect(
|
||||
roleNames.hasARoleNameWithMoreOrEqualPowerTo(RoleName.create(RoleName.NAMES.CoreUser).getValue()),
|
||||
).toBeTruthy()
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
import { Result } from '../Core/Result'
|
||||
import { ValueObject } from '../Core/ValueObject'
|
||||
import { TimestampsProps } from './TimestampsProps'
|
||||
|
||||
export class Timestamps extends ValueObject<TimestampsProps> {
|
||||
get createdAt(): Date {
|
||||
return this.props.createdAt
|
||||
}
|
||||
|
||||
get updatedAt(): Date {
|
||||
return this.props.updatedAt
|
||||
}
|
||||
|
||||
private constructor(props: TimestampsProps) {
|
||||
super(props)
|
||||
}
|
||||
|
||||
static create(createdAt: Date, updatedAt: Date): Result<Timestamps> {
|
||||
if (!(createdAt instanceof Date)) {
|
||||
return Result.fail<Timestamps>(
|
||||
`Could not create Timestamps. Creation date should be a date object, given: ${createdAt}`,
|
||||
)
|
||||
}
|
||||
if (!(updatedAt instanceof Date)) {
|
||||
return Result.fail<Timestamps>(
|
||||
`Could not create Timestamps. Update date should be a date object, given: ${createdAt}`,
|
||||
)
|
||||
}
|
||||
|
||||
return Result.ok<Timestamps>(new Timestamps({ createdAt, updatedAt }))
|
||||
}
|
||||
}
|
||||
16
packages/domain-core/src/Domain/Common/Username.spec.ts
Normal file
16
packages/domain-core/src/Domain/Common/Username.spec.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import { Username } from './Username'
|
||||
|
||||
describe('Username', () => {
|
||||
it('should create a value object', () => {
|
||||
const valueOrError = Username.create('test@test.te')
|
||||
|
||||
expect(valueOrError.isFailed()).toBeFalsy()
|
||||
expect(valueOrError.getValue().value).toEqual('test@test.te')
|
||||
})
|
||||
|
||||
it('should not create an invalid value object', () => {
|
||||
const valueOrError = Username.create('')
|
||||
|
||||
expect(valueOrError.isFailed()).toBeTruthy()
|
||||
})
|
||||
})
|
||||
22
packages/domain-core/src/Domain/Common/Username.ts
Normal file
22
packages/domain-core/src/Domain/Common/Username.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import { ValueObject } from '../Core/ValueObject'
|
||||
import { Result } from '../Core/Result'
|
||||
import { UsernameProps } from './UsernameProps'
|
||||
import { Validator } from '../Core/Validator'
|
||||
|
||||
export class Username extends ValueObject<UsernameProps> {
|
||||
get value(): string {
|
||||
return this.props.value
|
||||
}
|
||||
|
||||
private constructor(props: UsernameProps) {
|
||||
super(props)
|
||||
}
|
||||
|
||||
static create(username: string): Result<Username> {
|
||||
if (Validator.isNotEmpty(username).isFailed()) {
|
||||
return Result.fail<Username>('Username cannot be empty')
|
||||
}
|
||||
|
||||
return Result.ok<Username>(new Username({ value: username }))
|
||||
}
|
||||
}
|
||||
3
packages/domain-core/src/Domain/Common/UsernameProps.ts
Normal file
3
packages/domain-core/src/Domain/Common/UsernameProps.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export interface UsernameProps {
|
||||
value: string
|
||||
}
|
||||
@@ -18,6 +18,31 @@ describe('Validator', () => {
|
||||
'../../escaped.sh',
|
||||
]
|
||||
|
||||
const validEmails = [
|
||||
'something@something.com',
|
||||
'someone@localhost.localdomain',
|
||||
'a/b@domain.com',
|
||||
'{}@domain.com',
|
||||
'karol+test@standardnotes.com',
|
||||
"m*'!%@something.sa",
|
||||
'tu!!7n7.ad##0!!!@company.ca',
|
||||
'%@com.com',
|
||||
"!#$%&'*+/=?^_`{|}~.-@com.com",
|
||||
'someone@do-ma-in.com',
|
||||
'""testlah""@example.com',
|
||||
]
|
||||
|
||||
const invalidEmails = [
|
||||
'someone@127.0.0.1',
|
||||
'a@b.b',
|
||||
'',
|
||||
null,
|
||||
'.wooly@example.com',
|
||||
'wo..oly@example.com',
|
||||
'somebody@example',
|
||||
'a@p.com',
|
||||
]
|
||||
|
||||
it('should validate proper uuids', () => {
|
||||
for (const validUuid of validUuids) {
|
||||
expect(Validator.isValidUuid(validUuid).isFailed()).toBeFalsy()
|
||||
@@ -29,4 +54,28 @@ describe('Validator', () => {
|
||||
expect(Validator.isValidUuid(invalidUuid as string).isFailed()).toBeTruthy()
|
||||
}
|
||||
})
|
||||
|
||||
it('should validate proper emails', () => {
|
||||
for (const validEmail of validEmails) {
|
||||
expect(Validator.isValidEmail(validEmail).isFailed()).toBeFalsy()
|
||||
}
|
||||
})
|
||||
|
||||
it('should not validate invalid emails', () => {
|
||||
for (const invalidEmail of invalidEmails) {
|
||||
expect(Validator.isValidEmail(invalidEmail as string).isFailed()).toBeTruthy()
|
||||
}
|
||||
})
|
||||
|
||||
it('should validate value if not empty', () => {
|
||||
for (const value of [1, 'foobar', {}, 0]) {
|
||||
expect(Validator.isNotEmpty(value).isFailed()).toBeFalsy()
|
||||
}
|
||||
})
|
||||
|
||||
it('should not validate value if empty', () => {
|
||||
for (const value of [null, undefined, '', []]) {
|
||||
expect(Validator.isNotEmpty(value).isFailed()).toBeTruthy()
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
@@ -2,6 +2,8 @@ import { Result } from './Result'
|
||||
|
||||
export class Validator {
|
||||
private static readonly UUID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-5][0-9a-f]{3}-[089ab][0-9a-f]{3}-[0-9a-f]{12}$/i
|
||||
private static readonly EMAIL_REGEX =
|
||||
/^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
|
||||
|
||||
static isValidUuid(value: string): Result<string> {
|
||||
const matchesUuidRegex = String(value).toLowerCase().match(Validator.UUID_REGEX) !== null
|
||||
@@ -11,4 +13,25 @@ export class Validator {
|
||||
|
||||
return Result.fail(`Given value is not a valid uuid: ${value}`)
|
||||
}
|
||||
|
||||
static isValidEmail(value: string): Result<string> {
|
||||
const matchesUuidRegex = String(value).toLowerCase().match(Validator.EMAIL_REGEX) !== null
|
||||
if (matchesUuidRegex) {
|
||||
return Result.ok()
|
||||
}
|
||||
|
||||
return Result.fail(`Given value is not a valid email address: ${value}`)
|
||||
}
|
||||
|
||||
static isNotEmpty(value: unknown): Result<string> {
|
||||
if (value instanceof Array && value.length === 0) {
|
||||
return Result.fail(`Given value is empty: ${value}`)
|
||||
}
|
||||
|
||||
if (value === null || value === undefined || value === '') {
|
||||
return Result.fail(`Given value is empty: ${value}`)
|
||||
}
|
||||
|
||||
return Result.ok()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
import { EmailSubscriptionRejectionLevel } from './EmailSubscriptionRejectionLevel'
|
||||
|
||||
describe('EmailSubscriptionRejectionLevel', () => {
|
||||
it('should create a value object', () => {
|
||||
const valueOrError = EmailSubscriptionRejectionLevel.create(EmailSubscriptionRejectionLevel.LEVELS.SignIn)
|
||||
|
||||
expect(valueOrError.isFailed()).toBeFalsy()
|
||||
expect(valueOrError.getValue().value).toEqual('SIGN_IN')
|
||||
})
|
||||
|
||||
it('should not create an invalid value object', () => {
|
||||
for (const value of ['', undefined, null, 0, 'FOOBAR']) {
|
||||
const valueOrError = EmailSubscriptionRejectionLevel.create(value as string)
|
||||
|
||||
expect(valueOrError.isFailed()).toBeTruthy()
|
||||
}
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,30 @@
|
||||
import { Result } from '../Core/Result'
|
||||
import { ValueObject } from '../Core/ValueObject'
|
||||
|
||||
import { EmailSubscriptionRejectionLevelProps } from './EmailSubscriptionRejectionLevelProps'
|
||||
|
||||
export class EmailSubscriptionRejectionLevel extends ValueObject<EmailSubscriptionRejectionLevelProps> {
|
||||
static readonly LEVELS = {
|
||||
SignIn: 'SIGN_IN',
|
||||
Marketing: 'MARKETING',
|
||||
FailedCloudBackup: 'FAILED_CLOUD_BACKUP',
|
||||
FailedEmailBackup: 'FAILED_EMAIL_BACKUP',
|
||||
}
|
||||
|
||||
get value(): string {
|
||||
return this.props.value
|
||||
}
|
||||
|
||||
private constructor(props: EmailSubscriptionRejectionLevelProps) {
|
||||
super(props)
|
||||
}
|
||||
|
||||
static create(name: string): Result<EmailSubscriptionRejectionLevel> {
|
||||
const isValidName = Object.values(this.LEVELS).includes(name)
|
||||
if (!isValidName) {
|
||||
return Result.fail<EmailSubscriptionRejectionLevel>(`Invalid subscription rejection level: ${name}`)
|
||||
} else {
|
||||
return Result.ok<EmailSubscriptionRejectionLevel>(new EmailSubscriptionRejectionLevel({ value: name }))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
export interface EmailSubscriptionRejectionLevelProps {
|
||||
value: string
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
import { SubscriptionPlanName } from './SubscriptionPlanName'
|
||||
|
||||
describe('SubscriptionPlanName', () => {
|
||||
it('should create a value object', () => {
|
||||
const valueOrError = SubscriptionPlanName.create('PRO_PLAN')
|
||||
|
||||
expect(valueOrError.isFailed()).toBeFalsy()
|
||||
expect(valueOrError.getValue().value).toEqual('PRO_PLAN')
|
||||
})
|
||||
|
||||
it('should not create an invalid value object', () => {
|
||||
for (const value of ['', undefined, null, 0, 'SOME_PLAN']) {
|
||||
const valueOrError = SubscriptionPlanName.create(value as string)
|
||||
|
||||
expect(valueOrError.isFailed()).toBeTruthy()
|
||||
}
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,27 @@
|
||||
import { ValueObject } from '../Core/ValueObject'
|
||||
import { Result } from '../Core/Result'
|
||||
import { SubscriptionPlanNameProps } from './SubscriptionPlanNameProps'
|
||||
|
||||
export class SubscriptionPlanName extends ValueObject<SubscriptionPlanNameProps> {
|
||||
static readonly NAMES = {
|
||||
PlusPlan: 'PLUS_PLAN',
|
||||
ProPlan: 'PRO_PLAN',
|
||||
}
|
||||
|
||||
get value(): string {
|
||||
return this.props.value
|
||||
}
|
||||
|
||||
private constructor(props: SubscriptionPlanNameProps) {
|
||||
super(props)
|
||||
}
|
||||
|
||||
static create(name: string): Result<SubscriptionPlanName> {
|
||||
const isValidName = Object.values(this.NAMES).includes(name)
|
||||
if (!isValidName) {
|
||||
return Result.fail<SubscriptionPlanName>(`Invalid subscription plan name: ${name}`)
|
||||
} else {
|
||||
return Result.ok<SubscriptionPlanName>(new SubscriptionPlanName({ value: name }))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
export interface SubscriptionPlanNameProps {
|
||||
value: string
|
||||
}
|
||||
@@ -1,11 +1,13 @@
|
||||
export * from './Common/Dates'
|
||||
export * from './Common/DatesProps'
|
||||
export * from './Common/Email'
|
||||
export * from './Common/EmailProps'
|
||||
export * from './Common/RoleName'
|
||||
export * from './Common/RoleNameProps'
|
||||
export * from './Common/RoleNameCollection'
|
||||
export * from './Common/RoleNameCollectionProps'
|
||||
export * from './Common/Timestamps'
|
||||
export * from './Common/TimestampsProps'
|
||||
export * from './Common/Username'
|
||||
export * from './Common/UsernameProps'
|
||||
export * from './Common/Uuid'
|
||||
export * from './Common/UuidProps'
|
||||
|
||||
@@ -18,6 +20,12 @@ export * from './Core/Validator'
|
||||
export * from './Core/ValueObject'
|
||||
export * from './Core/ValueObjectProps'
|
||||
|
||||
export * from './Email/EmailSubscriptionRejectionLevel'
|
||||
export * from './Email/EmailSubscriptionRejectionLevelProps'
|
||||
|
||||
export * from './Mapping/MapperInterface'
|
||||
|
||||
export * from './Subscription/SubscriptionPlanName'
|
||||
export * from './Subscription/SubscriptionPlanNameProps'
|
||||
|
||||
export * from './UseCase/UseCaseInterface'
|
||||
|
||||
@@ -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.9.37](https://github.com/standardnotes/server/compare/@standardnotes/domain-events-infra@1.9.36...@standardnotes/domain-events-infra@1.9.37) (2022-12-05)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/domain-events-infra
|
||||
|
||||
## [1.9.36](https://github.com/standardnotes/server/compare/@standardnotes/domain-events-infra@1.9.35...@standardnotes/domain-events-infra@1.9.36) (2022-11-30)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/domain-events-infra
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/domain-events-infra",
|
||||
"version": "1.9.36",
|
||||
"version": "1.9.37",
|
||||
"engines": {
|
||||
"node": ">=18.0.0 <19.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.93.0](https://github.com/standardnotes/server/compare/@standardnotes/domain-events@2.92.0...@standardnotes/domain-events@2.93.0) (2022-12-05)
|
||||
|
||||
### Features
|
||||
|
||||
* **domain-events:** add email subscription sync requested event ([fddf9fc](https://github.com/standardnotes/server/commit/fddf9fccbd92fa4279e97bcd2420ec9e270fedbb))
|
||||
|
||||
# [2.92.0](https://github.com/standardnotes/server/compare/@standardnotes/domain-events@2.91.0...@standardnotes/domain-events@2.92.0) (2022-11-30)
|
||||
|
||||
### Features
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/domain-events",
|
||||
"version": "2.92.0",
|
||||
"version": "2.93.0",
|
||||
"engines": {
|
||||
"node": ">=18.0.0 <19.0.0"
|
||||
},
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
import { DomainEventInterface } from './DomainEventInterface'
|
||||
|
||||
import { EmailSubscriptionSyncRequestedEventPayload } from './EmailSubscriptionSyncRequestedEventPayload'
|
||||
|
||||
export interface EmailSubscriptionSyncRequestedEvent extends DomainEventInterface {
|
||||
type: 'EMAIL_SUBSCRIPTION_SYNC_REQUESTED'
|
||||
payload: EmailSubscriptionSyncRequestedEventPayload
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
export interface EmailSubscriptionSyncRequestedEventPayload {
|
||||
username: string
|
||||
userUuid: string
|
||||
subscriptionPlanName: string | null
|
||||
muteFailedBackupsEmails: boolean
|
||||
muteFailedCloudBackupsEmails: boolean
|
||||
muteMarketingEmails: boolean
|
||||
muteSignInEmails: boolean
|
||||
}
|
||||
@@ -30,6 +30,8 @@ export * from './Event/EmailBackupRequestedEvent'
|
||||
export * from './Event/EmailBackupRequestedEventPayload'
|
||||
export * from './Event/EmailMessageRequestedEvent'
|
||||
export * from './Event/EmailMessageRequestedEventPayload'
|
||||
export * from './Event/EmailSubscriptionSyncRequestedEvent'
|
||||
export * from './Event/EmailSubscriptionSyncRequestedEventPayload'
|
||||
export * from './Event/ExitDiscountAppliedEvent'
|
||||
export * from './Event/ExitDiscountAppliedEventPayload'
|
||||
export * from './Event/ExitDiscountApplyRequestedEvent'
|
||||
|
||||
@@ -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.6.33](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.6.32...@standardnotes/event-store@1.6.33) (2022-12-05)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/event-store
|
||||
|
||||
## [1.6.32](https://github.com/standardnotes/server/compare/@standardnotes/event-store@1.6.31...@standardnotes/event-store@1.6.32) (2022-11-30)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/event-store
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/event-store",
|
||||
"version": "1.6.32",
|
||||
"version": "1.6.33",
|
||||
"description": "Event Store Service",
|
||||
"private": true,
|
||||
"main": "dist/src/index.js",
|
||||
|
||||
@@ -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.8.33](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.8.32...@standardnotes/files-server@1.8.33) (2022-12-05)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/files-server
|
||||
|
||||
## [1.8.32](https://github.com/standardnotes/files/compare/@standardnotes/files-server@1.8.31...@standardnotes/files-server@1.8.32) (2022-11-30)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/files-server
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/files-server",
|
||||
"version": "1.8.32",
|
||||
"version": "1.8.33",
|
||||
"engines": {
|
||||
"node": ">=18.0.0 <19.0.0"
|
||||
},
|
||||
|
||||
@@ -3,6 +3,28 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.9.5](https://github.com/standardnotes/server/compare/@standardnotes/revisions-server@1.9.4...@standardnotes/revisions-server@1.9.5) (2022-12-05)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/revisions-server
|
||||
|
||||
## [1.9.4](https://github.com/standardnotes/server/compare/@standardnotes/revisions-server@1.9.3...@standardnotes/revisions-server@1.9.4) (2022-12-05)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/revisions-server
|
||||
|
||||
## [1.9.3](https://github.com/standardnotes/server/compare/@standardnotes/revisions-server@1.9.2...@standardnotes/revisions-server@1.9.3) (2022-12-05)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/revisions-server
|
||||
|
||||
## [1.9.2](https://github.com/standardnotes/server/compare/@standardnotes/revisions-server@1.9.1...@standardnotes/revisions-server@1.9.2) (2022-12-02)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/revisions-server
|
||||
|
||||
## [1.9.1](https://github.com/standardnotes/server/compare/@standardnotes/revisions-server@1.9.0...@standardnotes/revisions-server@1.9.1) (2022-12-02)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **revisions:** change timestamps to dates value object ([2351cd3](https://github.com/standardnotes/server/commit/2351cd3ad660c81b3b6bbc3759bc1c32a03406af))
|
||||
|
||||
# [1.9.0](https://github.com/standardnotes/server/compare/@standardnotes/revisions-server@1.8.2...@standardnotes/revisions-server@1.9.0) (2022-11-30)
|
||||
|
||||
### Features
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/revisions-server",
|
||||
"version": "1.9.0",
|
||||
"version": "1.9.5",
|
||||
"engines": {
|
||||
"node": ">=18.0.0 <19.0.0"
|
||||
},
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Timestamps, Uuid } from '@standardnotes/domain-core'
|
||||
import { Dates, Uuid } from '@standardnotes/domain-core'
|
||||
import { ContentType } from './ContentType'
|
||||
import { Revision } from './Revision'
|
||||
|
||||
@@ -13,7 +13,7 @@ describe('Revision', () => {
|
||||
encItemKey: 'test',
|
||||
authHash: 'test',
|
||||
creationDate: new Date(1),
|
||||
timestamps: Timestamps.create(new Date(1), new Date(2)).getValue(),
|
||||
dates: Dates.create(new Date(1), new Date(2)).getValue(),
|
||||
})
|
||||
|
||||
expect(entityOrError.isFailed()).toBeFalsy()
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { Timestamps } from '@standardnotes/domain-core'
|
||||
import { Dates } from '@standardnotes/domain-core'
|
||||
|
||||
import { ContentType } from './ContentType'
|
||||
|
||||
export interface RevisionMetadataProps {
|
||||
contentType: ContentType
|
||||
timestamps: Timestamps
|
||||
dates: Dates
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Timestamps, Uuid } from '@standardnotes/domain-core'
|
||||
import { Dates, Uuid } from '@standardnotes/domain-core'
|
||||
|
||||
import { ContentType } from './ContentType'
|
||||
|
||||
@@ -11,5 +11,5 @@ export interface RevisionProps {
|
||||
encItemKey: string | null
|
||||
authHash: string | null
|
||||
creationDate: Date
|
||||
timestamps: Timestamps
|
||||
dates: Dates
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { MapperInterface, Timestamps, Uuid } from '@standardnotes/domain-core'
|
||||
import { MapperInterface, Dates, Uuid } from '@standardnotes/domain-core'
|
||||
|
||||
import { ContentType } from '../Domain/Revision/ContentType'
|
||||
import { Revision } from '../Domain/Revision/Revision'
|
||||
@@ -34,7 +34,7 @@ export class RevisionItemStringMapper implements MapperInterface<Revision, strin
|
||||
itemsKeyId: item.items_key_id,
|
||||
encItemKey: item.enc_item_key,
|
||||
creationDate: new Date(),
|
||||
timestamps: Timestamps.create(new Date(), new Date()).getValue(),
|
||||
dates: Dates.create(new Date(), new Date()).getValue(),
|
||||
})
|
||||
|
||||
if (revisionOrError.isFailed()) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { MapperInterface, Timestamps, UniqueEntityId } from '@standardnotes/domain-core'
|
||||
import { MapperInterface, Dates, UniqueEntityId } from '@standardnotes/domain-core'
|
||||
|
||||
import { ContentType } from '../Domain/Revision/ContentType'
|
||||
import { RevisionMetadata } from '../Domain/Revision/RevisionMetadata'
|
||||
@@ -12,16 +12,16 @@ export class RevisionMetadataPersistenceMapper implements MapperInterface<Revisi
|
||||
}
|
||||
const contentType = contentTypeOrError.getValue()
|
||||
|
||||
const timestampsOrError = Timestamps.create(projection.createdAt, projection.updatedAt)
|
||||
if (timestampsOrError.isFailed()) {
|
||||
throw new Error(`Could not create timestamps: ${timestampsOrError.getError()}`)
|
||||
const datesOrError = Dates.create(projection.createdAt, projection.updatedAt)
|
||||
if (datesOrError.isFailed()) {
|
||||
throw new Error(`Could not create dates: ${datesOrError.getError()}`)
|
||||
}
|
||||
const timestamps = timestampsOrError.getValue()
|
||||
const dates = datesOrError.getValue()
|
||||
|
||||
const revisionMetadataOrError = RevisionMetadata.create(
|
||||
{
|
||||
contentType,
|
||||
timestamps,
|
||||
dates,
|
||||
},
|
||||
new UniqueEntityId(projection.uuid),
|
||||
)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { MapperInterface, Timestamps, UniqueEntityId, Uuid } from '@standardnotes/domain-core'
|
||||
import { MapperInterface, Dates, UniqueEntityId, Uuid } from '@standardnotes/domain-core'
|
||||
import { ContentType } from '../Domain/Revision/ContentType'
|
||||
import { Revision } from '../Domain/Revision/Revision'
|
||||
import { TypeORMRevision } from '../Infra/TypeORM/TypeORMRevision'
|
||||
@@ -11,11 +11,11 @@ export class RevisionPersistenceMapper implements MapperInterface<Revision, Type
|
||||
}
|
||||
const contentType = contentTypeOrError.getValue()
|
||||
|
||||
const timestampsOrError = Timestamps.create(projection.createdAt, projection.updatedAt)
|
||||
if (timestampsOrError.isFailed()) {
|
||||
throw new Error(`Could not map typeorm revision to domain revision: ${timestampsOrError.getError()}`)
|
||||
const datesOrError = Dates.create(projection.createdAt, projection.updatedAt)
|
||||
if (datesOrError.isFailed()) {
|
||||
throw new Error(`Could not map typeorm revision to domain revision: ${datesOrError.getError()}`)
|
||||
}
|
||||
const timestamps = timestampsOrError.getValue()
|
||||
const dates = datesOrError.getValue()
|
||||
|
||||
const itemUuidOrError = Uuid.create(projection.itemUuid)
|
||||
if (itemUuidOrError.isFailed()) {
|
||||
@@ -42,7 +42,7 @@ export class RevisionPersistenceMapper implements MapperInterface<Revision, Type
|
||||
itemsKeyId: projection.itemsKeyId,
|
||||
itemUuid,
|
||||
userUuid,
|
||||
timestamps,
|
||||
dates,
|
||||
},
|
||||
new UniqueEntityId(projection.uuid),
|
||||
)
|
||||
@@ -59,8 +59,8 @@ export class RevisionPersistenceMapper implements MapperInterface<Revision, Type
|
||||
typeormRevision.authHash = domain.props.authHash
|
||||
typeormRevision.content = domain.props.content
|
||||
typeormRevision.contentType = domain.props.contentType.value
|
||||
typeormRevision.createdAt = domain.props.timestamps.createdAt
|
||||
typeormRevision.updatedAt = domain.props.timestamps.updatedAt
|
||||
typeormRevision.createdAt = domain.props.dates.createdAt
|
||||
typeormRevision.updatedAt = domain.props.dates.updatedAt
|
||||
typeormRevision.creationDate = domain.props.creationDate
|
||||
typeormRevision.encItemKey = domain.props.encItemKey
|
||||
typeormRevision.itemUuid = domain.props.itemUuid.value
|
||||
|
||||
@@ -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.13.34](https://github.com/standardnotes/server/compare/@standardnotes/scheduler-server@1.13.33...@standardnotes/scheduler-server@1.13.34) (2022-12-05)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/scheduler-server
|
||||
|
||||
## [1.13.33](https://github.com/standardnotes/server/compare/@standardnotes/scheduler-server@1.13.32...@standardnotes/scheduler-server@1.13.33) (2022-11-30)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/scheduler-server
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/scheduler-server",
|
||||
"version": "1.13.33",
|
||||
"version": "1.13.34",
|
||||
"engines": {
|
||||
"node": ">=18.0.0 <19.0.0"
|
||||
},
|
||||
|
||||
@@ -3,6 +3,32 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.20.5](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.20.4...@standardnotes/syncing-server@1.20.5) (2022-12-05)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/syncing-server
|
||||
|
||||
## [1.20.4](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.20.3...@standardnotes/syncing-server@1.20.4) (2022-12-05)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/syncing-server
|
||||
|
||||
## [1.20.3](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.20.2...@standardnotes/syncing-server@1.20.3) (2022-12-05)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/syncing-server
|
||||
|
||||
## [1.20.2](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.20.1...@standardnotes/syncing-server@1.20.2) (2022-12-02)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/syncing-server
|
||||
|
||||
## [1.20.1](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.20.0...@standardnotes/syncing-server@1.20.1) (2022-12-02)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/syncing-server
|
||||
|
||||
# [1.20.0](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.19.1...@standardnotes/syncing-server@1.20.0) (2022-11-30)
|
||||
|
||||
### Features
|
||||
|
||||
* **syncing-server:** add revisions ownership fix procedure ([6cd68dd](https://github.com/standardnotes/syncing-server-js/commit/6cd68ddd6af0b1adde6c0d1cb3acef6e1aa9811b))
|
||||
|
||||
## [1.19.1](https://github.com/standardnotes/syncing-server-js/compare/@standardnotes/syncing-server@1.19.0...@standardnotes/syncing-server@1.19.1) (2022-11-30)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/syncing-server
|
||||
|
||||
78
packages/syncing-server/bin/revisions.ts
Normal file
78
packages/syncing-server/bin/revisions.ts
Normal file
@@ -0,0 +1,78 @@
|
||||
import 'reflect-metadata'
|
||||
|
||||
import 'newrelic'
|
||||
|
||||
import { Logger } from 'winston'
|
||||
|
||||
import { ContainerConfigLoader } from '../src/Bootstrap/Container'
|
||||
import TYPES from '../src/Bootstrap/Types'
|
||||
import { Env } from '../src/Bootstrap/Env'
|
||||
import { DomainEventFactoryInterface } from '../src/Domain/Event/DomainEventFactoryInterface'
|
||||
import { DomainEventPublisherInterface } from '@standardnotes/domain-events'
|
||||
import { ItemRepositoryInterface } from '../src/Domain/Item/ItemRepositoryInterface'
|
||||
import { Stream } from 'stream'
|
||||
|
||||
const fixRevisionsOwnership = async (
|
||||
itemRepository: ItemRepositoryInterface,
|
||||
domainEventFactory: DomainEventFactoryInterface,
|
||||
domainEventPublisher: DomainEventPublisherInterface,
|
||||
logger: Logger,
|
||||
): Promise<void> => {
|
||||
const stream = await itemRepository.streamAll({
|
||||
sortBy: 'updated_at_timestamp',
|
||||
sortOrder: 'ASC',
|
||||
createdBefore: new Date('2022-11-23'),
|
||||
selectFields: ['user_uuid', 'item_uuid'],
|
||||
})
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
stream
|
||||
.pipe(
|
||||
new Stream.Transform({
|
||||
objectMode: true,
|
||||
transform: async (rawItemData, _encoding, callback) => {
|
||||
try {
|
||||
await domainEventPublisher.publish(
|
||||
domainEventFactory.createRevisionsOwnershipUpdateRequestedEvent({
|
||||
userUuid: rawItemData.item_user_uuid,
|
||||
itemUuid: rawItemData.item_uuid,
|
||||
}),
|
||||
)
|
||||
} catch (error) {
|
||||
logger.error(`Could not process item ${rawItemData.item_uuid}: ${(error as Error).message}`)
|
||||
}
|
||||
|
||||
callback()
|
||||
},
|
||||
}),
|
||||
)
|
||||
.on('finish', resolve)
|
||||
.on('error', reject)
|
||||
})
|
||||
}
|
||||
|
||||
const container = new ContainerConfigLoader()
|
||||
void container.load().then((container) => {
|
||||
const env: Env = new Env()
|
||||
env.load()
|
||||
|
||||
const logger: Logger = container.get(TYPES.Logger)
|
||||
|
||||
logger.info('Starting revisions ownership fixing')
|
||||
|
||||
const itemRepository: ItemRepositoryInterface = container.get(TYPES.ItemRepository)
|
||||
const domainEventFactory: DomainEventFactoryInterface = container.get(TYPES.DomainEventFactory)
|
||||
const domainEventPublisher: DomainEventPublisherInterface = container.get(TYPES.DomainEventPublisher)
|
||||
|
||||
Promise.resolve(fixRevisionsOwnership(itemRepository, domainEventFactory, domainEventPublisher, logger))
|
||||
.then(() => {
|
||||
logger.info('revisions ownership fix complete.')
|
||||
|
||||
process.exit(0)
|
||||
})
|
||||
.catch((error) => {
|
||||
logger.error(`Could not finish revisions ownership fix: ${error.message}`)
|
||||
|
||||
process.exit(1)
|
||||
})
|
||||
})
|
||||
@@ -25,6 +25,11 @@ case "$COMMAND" in
|
||||
yarn workspace @standardnotes/syncing-server content-size $USER_UUID
|
||||
;;
|
||||
|
||||
'revisions-ownership-fix' )
|
||||
echo "Starting Revisions Ownership Fixing..."
|
||||
yarn workspace @standardnotes/syncing-server revisions-ownership
|
||||
;;
|
||||
|
||||
* )
|
||||
echo "Unknown command"
|
||||
;;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/syncing-server",
|
||||
"version": "1.19.1",
|
||||
"version": "1.20.5",
|
||||
"engines": {
|
||||
"node": ">=18.0.0 <19.0.0"
|
||||
},
|
||||
@@ -22,6 +22,7 @@
|
||||
"start": "yarn node dist/bin/server.js",
|
||||
"worker": "yarn node dist/bin/worker.js",
|
||||
"content-size": "yarn node dist/bin/content.js",
|
||||
"revisions-ownership": "yarn node dist/bin/revisions.js",
|
||||
"upgrade:snjs": "yarn ncu -u '@standardnotes/*'"
|
||||
},
|
||||
"dependencies": {
|
||||
|
||||
@@ -11,6 +11,7 @@ import {
|
||||
ItemsSyncedEvent,
|
||||
OneDriveBackupFailedEvent,
|
||||
RevisionsCopyRequestedEvent,
|
||||
RevisionsOwnershipUpdateRequestedEvent,
|
||||
UserContentSizeRecalculationRequestedEvent,
|
||||
} from '@standardnotes/domain-events'
|
||||
import { TimerInterface } from '@standardnotes/time'
|
||||
@@ -22,6 +23,24 @@ import { DomainEventFactoryInterface } from './DomainEventFactoryInterface'
|
||||
export class DomainEventFactory implements DomainEventFactoryInterface {
|
||||
constructor(@inject(TYPES.Timer) private timer: TimerInterface) {}
|
||||
|
||||
createRevisionsOwnershipUpdateRequestedEvent(dto: {
|
||||
userUuid: string
|
||||
itemUuid: string
|
||||
}): RevisionsOwnershipUpdateRequestedEvent {
|
||||
return {
|
||||
type: 'REVISIONS_OWNERSHIP_UPDATE_REQUESTED',
|
||||
createdAt: this.timer.getUTCDate(),
|
||||
meta: {
|
||||
correlation: {
|
||||
userIdentifier: dto.userUuid,
|
||||
userIdentifierType: 'uuid',
|
||||
},
|
||||
origin: DomainEventService.SyncingServer,
|
||||
},
|
||||
payload: dto,
|
||||
}
|
||||
}
|
||||
|
||||
createRevisionsCopyRequestedEvent(
|
||||
userUuid: string,
|
||||
dto: {
|
||||
|
||||
@@ -9,6 +9,7 @@ import {
|
||||
ItemsSyncedEvent,
|
||||
OneDriveBackupFailedEvent,
|
||||
RevisionsCopyRequestedEvent,
|
||||
RevisionsOwnershipUpdateRequestedEvent,
|
||||
UserContentSizeRecalculationRequestedEvent,
|
||||
} from '@standardnotes/domain-events'
|
||||
|
||||
@@ -40,4 +41,8 @@ export interface DomainEventFactoryInterface {
|
||||
userUuid: string,
|
||||
dto: { originalItemUuid: string; newItemUuid: string },
|
||||
): RevisionsCopyRequestedEvent
|
||||
createRevisionsOwnershipUpdateRequestedEvent(dto: {
|
||||
userUuid: string
|
||||
itemUuid: string
|
||||
}): RevisionsOwnershipUpdateRequestedEvent
|
||||
}
|
||||
|
||||
@@ -9,4 +9,6 @@ export type ItemQuery = {
|
||||
deleted?: boolean
|
||||
offset?: number
|
||||
limit?: number
|
||||
createdBefore?: Date
|
||||
selectFields?: string[]
|
||||
}
|
||||
|
||||
@@ -130,8 +130,12 @@ export class MySQLItemRepository implements ItemRepositoryInterface {
|
||||
|
||||
private createFindAllQueryBuilder(query: ItemQuery): SelectQueryBuilder<Item> {
|
||||
const queryBuilder = this.ormRepository.createQueryBuilder('item')
|
||||
|
||||
queryBuilder.orderBy(`item.${query.sortBy}`, query.sortOrder)
|
||||
|
||||
if (query.selectFields !== undefined) {
|
||||
queryBuilder.select(query.selectFields.map((field) => `item.${field}`))
|
||||
}
|
||||
if (query.userUuid !== undefined) {
|
||||
queryBuilder.where('item.user_uuid = :userUuid', { userUuid: query.userUuid })
|
||||
}
|
||||
@@ -149,6 +153,9 @@ export class MySQLItemRepository implements ItemRepositoryInterface {
|
||||
lastSyncTime: query.lastSyncTime,
|
||||
})
|
||||
}
|
||||
if (query.createdBefore !== undefined) {
|
||||
queryBuilder.andWhere('item.created_at < :createdAt', { createdAt: query.createdBefore.toISOString() })
|
||||
}
|
||||
if (query.offset !== undefined) {
|
||||
queryBuilder.skip(query.offset)
|
||||
}
|
||||
|
||||
@@ -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.4.34](https://github.com/standardnotes/server/compare/@standardnotes/websockets-server@1.4.33...@standardnotes/websockets-server@1.4.34) (2022-12-05)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/websockets-server
|
||||
|
||||
## [1.4.33](https://github.com/standardnotes/server/compare/@standardnotes/websockets-server@1.4.32...@standardnotes/websockets-server@1.4.33) (2022-11-30)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/websockets-server
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/websockets-server",
|
||||
"version": "1.4.33",
|
||||
"version": "1.4.34",
|
||||
"engines": {
|
||||
"node": ">=18.0.0 <19.0.0"
|
||||
},
|
||||
|
||||
@@ -3,6 +3,10 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.17.33](https://github.com/standardnotes/server/compare/@standardnotes/workspace-server@1.17.32...@standardnotes/workspace-server@1.17.33) (2022-12-05)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/workspace-server
|
||||
|
||||
## [1.17.32](https://github.com/standardnotes/server/compare/@standardnotes/workspace-server@1.17.31...@standardnotes/workspace-server@1.17.32) (2022-11-30)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/workspace-server
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/workspace-server",
|
||||
"version": "1.17.32",
|
||||
"version": "1.17.33",
|
||||
"engines": {
|
||||
"node": ">=18.0.0 <19.0.0"
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user