mirror of
https://github.com/standardnotes/server
synced 2026-01-19 20:04:28 -05:00
Compare commits
8 Commits
@standardn
...
@standardn
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0f3615ee65 | ||
|
|
567bcf26b5 | ||
|
|
9d49764b84 | ||
|
|
5c9f493b67 | ||
|
|
4fe8e9a79f | ||
|
|
f975dd9697 | ||
|
|
10832f7001 | ||
|
|
86b050865f |
2
.github/ci.env
vendored
2
.github/ci.env
vendored
@@ -28,3 +28,5 @@ AUTH_SERVER_ENCRYPTION_SERVER_KEY=1087415dfde3093797f9a7ca93a49e7d7aa1861735eb0d
|
||||
VALET_TOKEN_SECRET=4b886819ebe1e908077c6cae96311b48a8416bd60cc91c03060e15bdf6b30d1f
|
||||
|
||||
SYNCING_SERVER_CONTENT_SIZE_TRANSFER_LIMIT=100000
|
||||
|
||||
HTTP_REQUEST_PAYLOAD_LIMIT_MEGABYTES=1
|
||||
|
||||
36
.github/workflows/common-server-application.yml
vendored
36
.github/workflows/common-server-application.yml
vendored
@@ -42,26 +42,26 @@ jobs:
|
||||
workspace_name: ${{ inputs.workspace_name }}
|
||||
secrets: inherit
|
||||
|
||||
deploy-web:
|
||||
if: ${{ inputs.deploy_web }}
|
||||
# deploy-web:
|
||||
# if: ${{ inputs.deploy_web }}
|
||||
|
||||
needs: publish
|
||||
# needs: publish
|
||||
|
||||
name: Deploy Web
|
||||
uses: standardnotes/server/.github/workflows/common-deploy.yml@main
|
||||
with:
|
||||
service_name: ${{ inputs.service_name }}
|
||||
docker_image: ${{ inputs.service_name }}:${{ github.sha }}
|
||||
secrets: inherit
|
||||
# name: Deploy Web
|
||||
# uses: standardnotes/server/.github/workflows/common-deploy.yml@main
|
||||
# with:
|
||||
# service_name: ${{ inputs.service_name }}
|
||||
# docker_image: ${{ inputs.service_name }}:${{ github.sha }}
|
||||
# secrets: inherit
|
||||
|
||||
deploy-worker:
|
||||
if: ${{ inputs.deploy_worker }}
|
||||
# deploy-worker:
|
||||
# if: ${{ inputs.deploy_worker }}
|
||||
|
||||
needs: publish
|
||||
# needs: publish
|
||||
|
||||
name: Deploy Worker
|
||||
uses: standardnotes/server/.github/workflows/common-deploy.yml@main
|
||||
with:
|
||||
service_name: ${{ inputs.service_name }}-worker
|
||||
docker_image: ${{ inputs.service_name }}:${{ github.sha }}
|
||||
secrets: inherit
|
||||
# name: Deploy Worker
|
||||
# uses: standardnotes/server/.github/workflows/common-deploy.yml@main
|
||||
# with:
|
||||
# service_name: ${{ inputs.service_name }}-worker
|
||||
# docker_image: ${{ inputs.service_name }}:${{ github.sha }}
|
||||
# secrets: inherit
|
||||
|
||||
1
.github/workflows/e2e-home-server.yml
vendored
1
.github/workflows/e2e-home-server.yml
vendored
@@ -71,6 +71,7 @@ jobs:
|
||||
echo "REFRESH_TOKEN_AGE=10" >> packages/home-server/.env
|
||||
echo "REVISIONS_FREQUENCY=2" >> packages/home-server/.env
|
||||
echo "CONTENT_SIZE_TRANSFER_LIMIT=100000" >> packages/home-server/.env
|
||||
echo "HTTP_REQUEST_PAYLOAD_LIMIT_MEGABYTES=1" >> packages/home-server/.env
|
||||
echo "DB_HOST=localhost" >> packages/home-server/.env
|
||||
echo "DB_PORT=3306" >> packages/home-server/.env
|
||||
echo "DB_DATABASE=standardnotes" >> packages/home-server/.env
|
||||
|
||||
34
.github/workflows/publish.yml
vendored
34
.github/workflows/publish.yml
vendored
@@ -98,30 +98,32 @@ jobs:
|
||||
- name: Test
|
||||
run: yarn test
|
||||
|
||||
e2e-base:
|
||||
needs: build
|
||||
name: E2E Base Suite
|
||||
uses: standardnotes/server/.github/workflows/common-e2e.yml@main
|
||||
with:
|
||||
snjs_image_tag: 'latest'
|
||||
suite: 'base'
|
||||
# e2e-base:
|
||||
# needs: build
|
||||
# name: E2E Base Suite
|
||||
# uses: standardnotes/server/.github/workflows/common-e2e.yml@main
|
||||
# with:
|
||||
# snjs_image_tag: 'latest'
|
||||
# suite: 'base'
|
||||
|
||||
e2e-vaults:
|
||||
needs: build
|
||||
name: E2E Vaults Suite
|
||||
uses: standardnotes/server/.github/workflows/common-e2e.yml@main
|
||||
with:
|
||||
snjs_image_tag: 'latest'
|
||||
suite: 'vaults'
|
||||
# e2e-vaults:
|
||||
# needs: build
|
||||
# name: E2E Vaults Suite
|
||||
# uses: standardnotes/server/.github/workflows/common-e2e.yml@main
|
||||
# with:
|
||||
# snjs_image_tag: 'latest'
|
||||
# suite: 'vaults'
|
||||
|
||||
publish-self-hosting:
|
||||
needs: [ test, lint, e2e-base, e2e-vaults ]
|
||||
# needs: [ test, lint, e2e-base, e2e-vaults ]
|
||||
needs: [ test, lint ]
|
||||
name: Publish Self Hosting Docker Image
|
||||
uses: standardnotes/server/.github/workflows/common-self-hosting.yml@main
|
||||
secrets: inherit
|
||||
|
||||
publish-services:
|
||||
needs: [ test, lint, e2e-base, e2e-vaults ]
|
||||
# needs: [ test, lint, e2e-base, e2e-vaults ]
|
||||
needs: [ test, lint ]
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
## [2.34.16](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.34.15...@standardnotes/analytics@2.34.16) (2024-01-19)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/analytics
|
||||
|
||||
## [2.34.15](https://github.com/standardnotes/server/compare/@standardnotes/analytics@2.34.14...@standardnotes/analytics@2.34.15) (2024-01-18)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/analytics
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/analytics",
|
||||
"version": "2.34.15",
|
||||
"version": "2.34.16",
|
||||
"engines": {
|
||||
"node": ">=18.0.0 <21.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.90.1](https://github.com/standardnotes/server/compare/@standardnotes/api-gateway@1.90.0...@standardnotes/api-gateway@1.90.1) (2024-01-19)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/api-gateway
|
||||
|
||||
# [1.90.0](https://github.com/standardnotes/server/compare/@standardnotes/api-gateway@1.89.20...@standardnotes/api-gateway@1.90.0) (2024-01-18)
|
||||
|
||||
### Features
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/api-gateway",
|
||||
"version": "1.90.0",
|
||||
"version": "1.90.1",
|
||||
"engines": {
|
||||
"node": ">=18.0.0 <21.0.0"
|
||||
},
|
||||
|
||||
@@ -3,6 +3,24 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.178.2](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.178.1...@standardnotes/auth-server@1.178.2) (2024-03-15)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* allow handling of new api version ([9d49764](https://github.com/standardnotes/server/commit/9d49764b841e73655e19523eddf10498addc9fb4))
|
||||
|
||||
## [1.178.1](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.178.0...@standardnotes/auth-server@1.178.1) (2024-02-09)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* allow expired offline subscriptions to receive dashboard emails ([#1041](https://github.com/standardnotes/server/issues/1041)) ([4fe8e9a](https://github.com/standardnotes/server/commit/4fe8e9a79f652f3e39608d6683cb17cc08bb8717))
|
||||
|
||||
# [1.178.0](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.177.20...@standardnotes/auth-server@1.178.0) (2024-01-19)
|
||||
|
||||
### Features
|
||||
|
||||
* **auth:** add script for fixing subscriptions with missing id state ([#1030](https://github.com/standardnotes/server/issues/1030)) ([86b0508](https://github.com/standardnotes/server/commit/86b050865f8090ed33d5ce05528ff0e1e23657ef))
|
||||
|
||||
## [1.177.20](https://github.com/standardnotes/server/compare/@standardnotes/auth-server@1.177.19...@standardnotes/auth-server@1.177.20) (2024-01-18)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/auth-server
|
||||
|
||||
74
packages/auth/bin/fix_subscriptions.ts
Normal file
74
packages/auth/bin/fix_subscriptions.ts
Normal file
@@ -0,0 +1,74 @@
|
||||
import 'reflect-metadata'
|
||||
|
||||
import { Logger } from 'winston'
|
||||
|
||||
import { ContainerConfigLoader } from '../src/Bootstrap/Container'
|
||||
import TYPES from '../src/Bootstrap/Types'
|
||||
import { Env } from '../src/Bootstrap/Env'
|
||||
import { UserSubscriptionRepositoryInterface } from '../src/Domain/Subscription/UserSubscriptionRepositoryInterface'
|
||||
import { DomainEventFactoryInterface } from '../src/Domain/Event/DomainEventFactoryInterface'
|
||||
import { DomainEventPublisherInterface } from '@standardnotes/domain-events'
|
||||
import { UserRepositoryInterface } from '../src/Domain/User/UserRepositoryInterface'
|
||||
import { Uuid } from '@standardnotes/domain-core'
|
||||
|
||||
const fixSubscriptions = async (
|
||||
userRepository: UserRepositoryInterface,
|
||||
userSubscriptionRepository: UserSubscriptionRepositoryInterface,
|
||||
domainEventFactory: DomainEventFactoryInterface,
|
||||
domainEventPublisher: DomainEventPublisherInterface,
|
||||
): Promise<void> => {
|
||||
const subscriptions = await userSubscriptionRepository.findBySubscriptionId(0)
|
||||
|
||||
for (const subscription of subscriptions) {
|
||||
const userUuidOrError = Uuid.create(subscription.userUuid)
|
||||
if (userUuidOrError.isFailed()) {
|
||||
continue
|
||||
}
|
||||
const userUuid = userUuidOrError.getValue()
|
||||
|
||||
const user = await userRepository.findOneByUuid(userUuid)
|
||||
if (!user) {
|
||||
continue
|
||||
}
|
||||
|
||||
await domainEventPublisher.publish(
|
||||
domainEventFactory.createSubscriptionStateRequestedEvent({
|
||||
userEmail: user.email,
|
||||
}),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const container = new ContainerConfigLoader('worker')
|
||||
void container.load().then((container) => {
|
||||
const env: Env = new Env()
|
||||
env.load()
|
||||
|
||||
const logger: Logger = container.get(TYPES.Auth_Logger)
|
||||
|
||||
logger.info('Starting to fix subscriptions with missing subscriptionId ...')
|
||||
|
||||
const userRepository = container.get<UserRepositoryInterface>(TYPES.Auth_UserRepository)
|
||||
const userSubscriptionRepository = container.get<UserSubscriptionRepositoryInterface>(
|
||||
TYPES.Auth_UserSubscriptionRepository,
|
||||
)
|
||||
const domainEventFactory = container.get<DomainEventFactoryInterface>(TYPES.Auth_DomainEventFactory)
|
||||
const domainEventPublisher = container.get<DomainEventPublisherInterface>(TYPES.Auth_DomainEventPublisher)
|
||||
|
||||
Promise.resolve(
|
||||
fixSubscriptions(userRepository, userSubscriptionRepository, domainEventFactory, domainEventPublisher),
|
||||
)
|
||||
.then(() => {
|
||||
logger.info('Finished fixing subscriptions with missing subscriptionId.')
|
||||
|
||||
process.exit(0)
|
||||
})
|
||||
.catch((error) => {
|
||||
logger.error('Failed to fix subscriptions with missing subscriptionId.', {
|
||||
error: error.message,
|
||||
stack: error.stack,
|
||||
})
|
||||
|
||||
process.exit(1)
|
||||
})
|
||||
})
|
||||
11
packages/auth/docker/entrypoint-fix-subscriptions.js
Normal file
11
packages/auth/docker/entrypoint-fix-subscriptions.js
Normal file
@@ -0,0 +1,11 @@
|
||||
'use strict'
|
||||
|
||||
const path = require('path')
|
||||
|
||||
const pnp = require(path.normalize(path.resolve(__dirname, '../../..', '.pnp.cjs'))).setup()
|
||||
|
||||
const index = require(path.normalize(path.resolve(__dirname, '../dist/bin/fix_subscriptions.js')))
|
||||
|
||||
Object.defineProperty(exports, '__esModule', { value: true })
|
||||
|
||||
exports.default = index
|
||||
@@ -42,6 +42,10 @@ case "$COMMAND" in
|
||||
exec node docker/entrypoint-fix-roles.js
|
||||
;;
|
||||
|
||||
'fix-subscriptions' )
|
||||
exec node docker/entrypoint-fix-subscriptions.js
|
||||
;;
|
||||
|
||||
'delete-accounts' )
|
||||
FILE_NAME=$1 && shift 1
|
||||
MODE=$1 && shift 1
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/auth-server",
|
||||
"version": "1.177.20",
|
||||
"version": "1.178.2",
|
||||
"engines": {
|
||||
"node": ">=18.0.0 <21.0.0"
|
||||
},
|
||||
|
||||
@@ -285,6 +285,7 @@ import { RenewSharedSubscriptions } from '../Domain/UseCase/RenewSharedSubscript
|
||||
import { FixStorageQuotaForUser } from '../Domain/UseCase/FixStorageQuotaForUser/FixStorageQuotaForUser'
|
||||
import { FileQuotaRecalculatedEventHandler } from '../Domain/Handler/FileQuotaRecalculatedEventHandler'
|
||||
import { SessionServiceInterface } from '../Domain/Session/SessionServiceInterface'
|
||||
import { SubscriptionStateFetchedEventHandler } from '../Domain/Handler/SubscriptionStateFetchedEventHandler'
|
||||
|
||||
export class ContainerConfigLoader {
|
||||
constructor(private mode: 'server' | 'worker' = 'server') {}
|
||||
@@ -1579,6 +1580,16 @@ export class ContainerConfigLoader {
|
||||
container.get<winston.Logger>(TYPES.Auth_Logger),
|
||||
),
|
||||
)
|
||||
container
|
||||
.bind<SubscriptionStateFetchedEventHandler>(TYPES.Auth_SubscriptionStateFetchedEventHandler)
|
||||
.toConstantValue(
|
||||
new SubscriptionStateFetchedEventHandler(
|
||||
container.get<UserRepositoryInterface>(TYPES.Auth_UserRepository),
|
||||
container.get<UserSubscriptionRepositoryInterface>(TYPES.Auth_UserSubscriptionRepository),
|
||||
container.get<OfflineUserSubscriptionRepositoryInterface>(TYPES.Auth_OfflineUserSubscriptionRepository),
|
||||
container.get<winston.Logger>(TYPES.Auth_Logger),
|
||||
),
|
||||
)
|
||||
|
||||
const eventHandlers: Map<string, DomainEventHandlerInterface> = new Map([
|
||||
['ACCOUNT_DELETION_REQUESTED', container.get(TYPES.Auth_AccountDeletionRequestedEventHandler)],
|
||||
@@ -1620,6 +1631,7 @@ export class ContainerConfigLoader {
|
||||
'FILE_QUOTA_RECALCULATED',
|
||||
container.get<FileQuotaRecalculatedEventHandler>(TYPES.Auth_FileQuotaRecalculatedEventHandler),
|
||||
],
|
||||
['SUBSCRIPTION_STATE_FETCHED', container.get(TYPES.Auth_SubscriptionStateFetchedEventHandler)],
|
||||
])
|
||||
|
||||
if (isConfiguredForHomeServer) {
|
||||
|
||||
@@ -205,6 +205,7 @@ const TYPES = {
|
||||
),
|
||||
Auth_UserInvitedToSharedVaultEventHandler: Symbol.for('Auth_UserInvitedToSharedVaultEventHandler'),
|
||||
Auth_FileQuotaRecalculatedEventHandler: Symbol.for('Auth_FileQuotaRecalculatedEventHandler'),
|
||||
Auth_SubscriptionStateFetchedEventHandler: Symbol.for('Auth_SubscriptionStateFetchedEventHandler'),
|
||||
// Services
|
||||
Auth_DeviceDetector: Symbol.for('Auth_DeviceDetector'),
|
||||
Auth_SessionService: Symbol.for('Auth_SessionService'),
|
||||
|
||||
@@ -2,4 +2,5 @@ export enum ApiVersion {
|
||||
v20161215 = '20161215',
|
||||
v20190520 = '20190520',
|
||||
v20200115 = '20200115',
|
||||
v20240226 = '20240226',
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ export class AuthResponseFactoryResolver implements AuthResponseFactoryResolverI
|
||||
case ApiVersion.v20190520:
|
||||
return this.authResponseFactory20190520
|
||||
case ApiVersion.v20200115:
|
||||
case ApiVersion.v20240226:
|
||||
return this.authResponseFactory20200115
|
||||
default:
|
||||
return this.authResponseFactory20161215
|
||||
|
||||
@@ -22,6 +22,7 @@ import {
|
||||
SessionRefreshedEvent,
|
||||
AccountDeletionVerificationRequestedEvent,
|
||||
FileQuotaRecalculationRequestedEvent,
|
||||
SubscriptionStateRequestedEvent,
|
||||
} from '@standardnotes/domain-events'
|
||||
import { Predicate, PredicateVerificationResult } from '@standardnotes/predicates'
|
||||
import { TimerInterface } from '@standardnotes/time'
|
||||
@@ -34,6 +35,21 @@ import { KeyParamsData } from '@standardnotes/responses'
|
||||
@injectable()
|
||||
export class DomainEventFactory implements DomainEventFactoryInterface {
|
||||
constructor(@inject(TYPES.Auth_Timer) private timer: TimerInterface) {}
|
||||
createSubscriptionStateRequestedEvent(dto: { userEmail: string }): SubscriptionStateRequestedEvent {
|
||||
return {
|
||||
type: 'SUBSCRIPTION_STATE_REQUESTED',
|
||||
createdAt: this.timer.getUTCDate(),
|
||||
meta: {
|
||||
correlation: {
|
||||
userIdentifier: dto.userEmail,
|
||||
userIdentifierType: 'email',
|
||||
},
|
||||
origin: DomainEventService.Auth,
|
||||
},
|
||||
payload: dto,
|
||||
}
|
||||
}
|
||||
|
||||
createFileQuotaRecalculationRequestedEvent(dto: { userUuid: string }): FileQuotaRecalculationRequestedEvent {
|
||||
return {
|
||||
type: 'FILE_QUOTA_RECALCULATION_REQUESTED',
|
||||
|
||||
@@ -20,11 +20,13 @@ import {
|
||||
SessionRefreshedEvent,
|
||||
AccountDeletionVerificationRequestedEvent,
|
||||
FileQuotaRecalculationRequestedEvent,
|
||||
SubscriptionStateRequestedEvent,
|
||||
} from '@standardnotes/domain-events'
|
||||
import { InviteeIdentifierType } from '../SharedSubscription/InviteeIdentifierType'
|
||||
import { KeyParamsData } from '@standardnotes/responses'
|
||||
|
||||
export interface DomainEventFactoryInterface {
|
||||
createSubscriptionStateRequestedEvent(dto: { userEmail: string }): SubscriptionStateRequestedEvent
|
||||
createFileQuotaRecalculationRequestedEvent(dto: { userUuid: string }): FileQuotaRecalculationRequestedEvent
|
||||
createWebSocketMessageRequestedEvent(dto: { userUuid: string; message: JSONString }): WebSocketMessageRequestedEvent
|
||||
createEmailRequestedEvent(dto: {
|
||||
|
||||
@@ -4,6 +4,7 @@ import { inject, injectable } from 'inversify'
|
||||
import TYPES from '../../Bootstrap/Types'
|
||||
import { UserSubscriptionRepositoryInterface } from '../Subscription/UserSubscriptionRepositoryInterface'
|
||||
import { OfflineUserSubscriptionRepositoryInterface } from '../Subscription/OfflineUserSubscriptionRepositoryInterface'
|
||||
import { Logger } from 'winston'
|
||||
|
||||
@injectable()
|
||||
export class SubscriptionCancelledEventHandler implements DomainEventHandlerInterface {
|
||||
@@ -12,9 +13,20 @@ export class SubscriptionCancelledEventHandler implements DomainEventHandlerInte
|
||||
private userSubscriptionRepository: UserSubscriptionRepositoryInterface,
|
||||
@inject(TYPES.Auth_OfflineUserSubscriptionRepository)
|
||||
private offlineUserSubscriptionRepository: OfflineUserSubscriptionRepositoryInterface,
|
||||
@inject(TYPES.Auth_Logger) private logger: Logger,
|
||||
) {}
|
||||
|
||||
async handle(event: SubscriptionCancelledEvent): Promise<void> {
|
||||
if (!event.payload.subscriptionId) {
|
||||
this.logger.error('Subscription ID is missing', {
|
||||
codeTag: 'SubscriptionCancelledEventHandler.handle',
|
||||
subscriptionId: event.payload.subscriptionId,
|
||||
userId: event.payload.userEmail,
|
||||
})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if (event.payload.offline) {
|
||||
await this.updateOfflineSubscriptionCancelled(event.payload.subscriptionId, event.payload.timestamp)
|
||||
|
||||
|
||||
@@ -22,6 +22,16 @@ export class SubscriptionExpiredEventHandler implements DomainEventHandlerInterf
|
||||
) {}
|
||||
|
||||
async handle(event: SubscriptionExpiredEvent): Promise<void> {
|
||||
if (!event.payload.subscriptionId) {
|
||||
this.logger.error('Subscription ID is missing', {
|
||||
codeTag: 'SubscriptionExpiredEventHandler.handle',
|
||||
subscriptionId: event.payload.subscriptionId,
|
||||
userId: event.payload.userEmail,
|
||||
})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if (event.payload.offline) {
|
||||
await this.updateOfflineSubscriptionEndsAt(event.payload.subscriptionId, event.payload.timestamp)
|
||||
|
||||
|
||||
@@ -25,6 +25,16 @@ export class SubscriptionPurchasedEventHandler implements DomainEventHandlerInte
|
||||
) {}
|
||||
|
||||
async handle(event: SubscriptionPurchasedEvent): Promise<void> {
|
||||
if (!event.payload.subscriptionId) {
|
||||
this.logger.error('Subscription ID is missing', {
|
||||
codeTag: 'SubscriptionPurchasedEventHandler.handle',
|
||||
subscriptionId: event.payload.subscriptionId,
|
||||
userId: event.payload.userEmail,
|
||||
})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if (event.payload.offline) {
|
||||
const offlineUserSubscription = await this.createOfflineSubscription(
|
||||
event.payload.subscriptionId,
|
||||
|
||||
@@ -22,6 +22,16 @@ export class SubscriptionReassignedEventHandler implements DomainEventHandlerInt
|
||||
) {}
|
||||
|
||||
async handle(event: SubscriptionReassignedEvent): Promise<void> {
|
||||
if (!event.payload.subscriptionId) {
|
||||
this.logger.error('Subscription ID is missing', {
|
||||
codeTag: 'SubscriptionReassignedEventHandler.handle',
|
||||
subscriptionId: event.payload.subscriptionId,
|
||||
userId: event.payload.userEmail,
|
||||
})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
const usernameOrError = Username.create(event.payload.userEmail)
|
||||
if (usernameOrError.isFailed()) {
|
||||
return
|
||||
|
||||
@@ -22,6 +22,16 @@ export class SubscriptionRefundedEventHandler implements DomainEventHandlerInter
|
||||
) {}
|
||||
|
||||
async handle(event: SubscriptionRefundedEvent): Promise<void> {
|
||||
if (!event.payload.subscriptionId) {
|
||||
this.logger.error('Subscription ID is missing', {
|
||||
codeTag: 'SubscriptionRefundedEventHandler.handle',
|
||||
subscriptionId: event.payload.subscriptionId,
|
||||
userId: event.payload.userEmail,
|
||||
})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if (event.payload.offline) {
|
||||
await this.updateOfflineSubscriptionEndsAt(event.payload.subscriptionId, event.payload.timestamp)
|
||||
|
||||
|
||||
@@ -23,6 +23,16 @@ export class SubscriptionRenewedEventHandler implements DomainEventHandlerInterf
|
||||
) {}
|
||||
|
||||
async handle(event: SubscriptionRenewedEvent): Promise<void> {
|
||||
if (!event.payload.subscriptionId) {
|
||||
this.logger.error('Subscription ID is missing', {
|
||||
codeTag: 'SubscriptionRenewedEventHandler.handle',
|
||||
subscriptionId: event.payload.subscriptionId,
|
||||
userId: event.payload.userEmail,
|
||||
})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if (event.payload.offline) {
|
||||
const offlineUserSubscription = await this.offlineUserSubscriptionRepository.findOneBySubscriptionId(
|
||||
event.payload.subscriptionId,
|
||||
|
||||
@@ -0,0 +1,123 @@
|
||||
import { Username } from '@standardnotes/domain-core'
|
||||
import { DomainEventHandlerInterface, SubscriptionStateFetchedEvent } from '@standardnotes/domain-events'
|
||||
import { Logger } from 'winston'
|
||||
|
||||
import { UserRepositoryInterface } from '../User/UserRepositoryInterface'
|
||||
import { UserSubscriptionRepositoryInterface } from '../Subscription/UserSubscriptionRepositoryInterface'
|
||||
import { OfflineUserSubscriptionRepositoryInterface } from '../Subscription/OfflineUserSubscriptionRepositoryInterface'
|
||||
|
||||
export class SubscriptionStateFetchedEventHandler implements DomainEventHandlerInterface {
|
||||
constructor(
|
||||
private userRepository: UserRepositoryInterface,
|
||||
private userSubscriptionRepository: UserSubscriptionRepositoryInterface,
|
||||
private offlineUserSubscriptionRepository: OfflineUserSubscriptionRepositoryInterface,
|
||||
private logger: Logger,
|
||||
) {}
|
||||
|
||||
async handle(event: SubscriptionStateFetchedEvent): Promise<void> {
|
||||
if (!event.payload.subscriptionId) {
|
||||
this.logger.error('Subscription ID is missing', {
|
||||
codeTag: 'SubscriptionStateFetchedEventHandler.handle',
|
||||
subscriptionId: event.payload.subscriptionId,
|
||||
userId: event.payload.userEmail,
|
||||
})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
this.logger.info('Subscription state update fetched', {
|
||||
subscriptionId: event.payload.subscriptionId,
|
||||
})
|
||||
|
||||
if (event.payload.offline) {
|
||||
this.logger.info('Updating offline subscription', {
|
||||
subscriptionId: event.payload.subscriptionId,
|
||||
})
|
||||
|
||||
const subscription = await this.offlineUserSubscriptionRepository.findOneByEmailAndSubscriptionId(
|
||||
event.payload.userEmail,
|
||||
0,
|
||||
)
|
||||
if (!subscription) {
|
||||
this.logger.error('Offline subscription not found', {
|
||||
subscriptionId: event.payload.subscriptionId,
|
||||
})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
subscription.planName = event.payload.subscriptionName
|
||||
subscription.email = event.payload.userEmail
|
||||
subscription.endsAt = event.payload.subscriptionExpiresAt
|
||||
subscription.cancelled = event.payload.canceled
|
||||
if (subscription.subscriptionId !== event.payload.subscriptionId) {
|
||||
this.logger.warn('Subscription IDs do not match', {
|
||||
previousSubscriptionId: subscription.subscriptionId,
|
||||
subscriptionId: event.payload.subscriptionId,
|
||||
})
|
||||
}
|
||||
subscription.subscriptionId = event.payload.subscriptionId
|
||||
|
||||
await this.offlineUserSubscriptionRepository.save(subscription)
|
||||
|
||||
this.logger.info('Offline subscription updated', {
|
||||
subscriptionId: event.payload.subscriptionId,
|
||||
})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
const usernameOrError = Username.create(event.payload.userEmail)
|
||||
if (usernameOrError.isFailed()) {
|
||||
this.logger.warn(`Could not update subscription: ${usernameOrError.getError()}`, {
|
||||
subscriptionId: event.payload.subscriptionId,
|
||||
})
|
||||
|
||||
return
|
||||
}
|
||||
const username = usernameOrError.getValue()
|
||||
|
||||
const user = await this.userRepository.findOneByUsernameOrEmail(username)
|
||||
|
||||
if (user === null) {
|
||||
this.logger.warn(`Could not find user with email: ${username.value}`, {
|
||||
subscriptionId: event.payload.subscriptionId,
|
||||
})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
this.logger.info('Updating subscription', {
|
||||
userId: user.uuid,
|
||||
subscriptionId: event.payload.subscriptionId,
|
||||
})
|
||||
|
||||
const subscription = await this.userSubscriptionRepository.findOneByUserUuidAndSubscriptionId(user.uuid, 0)
|
||||
if (!subscription) {
|
||||
this.logger.error('Subscription not found', {
|
||||
userId: user.uuid,
|
||||
subscriptionId: event.payload.subscriptionId,
|
||||
})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
subscription.planName = event.payload.subscriptionName
|
||||
subscription.endsAt = event.payload.subscriptionExpiresAt
|
||||
subscription.cancelled = event.payload.canceled
|
||||
if (subscription.subscriptionId !== event.payload.subscriptionId) {
|
||||
this.logger.warn('Subscription IDs do not match', {
|
||||
previousSubscriptionId: subscription.subscriptionId,
|
||||
subscriptionId: event.payload.subscriptionId,
|
||||
})
|
||||
}
|
||||
subscription.subscriptionId = event.payload.subscriptionId
|
||||
|
||||
await this.userSubscriptionRepository.save(subscription)
|
||||
|
||||
this.logger.info('Subscription updated to current state', {
|
||||
userId: user.uuid,
|
||||
subscriptionId: event.payload.subscriptionId,
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -33,6 +33,16 @@ export class SubscriptionSyncRequestedEventHandler implements DomainEventHandler
|
||||
) {}
|
||||
|
||||
async handle(event: SubscriptionSyncRequestedEvent): Promise<void> {
|
||||
if (!event.payload.subscriptionId) {
|
||||
this.logger.error('Subscription ID is missing', {
|
||||
codeTag: 'SubscriptionSyncRequestedEventHandler.handle',
|
||||
subscriptionId: event.payload.subscriptionId,
|
||||
userId: event.payload.userEmail,
|
||||
})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
this.logger.info('Subscription sync requested', {
|
||||
subscriptionId: event.payload.subscriptionId,
|
||||
})
|
||||
|
||||
@@ -2,6 +2,7 @@ import { OfflineUserSubscription } from './OfflineUserSubscription'
|
||||
|
||||
export interface OfflineUserSubscriptionRepositoryInterface {
|
||||
findOneByEmail(email: string): Promise<OfflineUserSubscription | null>
|
||||
findOneByEmailAndSubscriptionId(email: string, subscriptionId: number): Promise<OfflineUserSubscription | null>
|
||||
findOneBySubscriptionId(subscriptionId: number): Promise<OfflineUserSubscription | null>
|
||||
findByEmail(email: string, activeAfter: number): Promise<OfflineUserSubscription[]>
|
||||
updateEndsAt(subscriptionId: number, endsAt: number, updatedAt: number): Promise<void>
|
||||
|
||||
@@ -89,42 +89,4 @@ describe('CreateOfflineSubscriptionToken', () => {
|
||||
expect(domainEventFactory.createEmailRequestedEvent).not.toHaveBeenCalled()
|
||||
expect(domainEventPublisher.publish).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('should not create an offline subscription token if email has a cancelled subscription', async () => {
|
||||
offlineUserSubscriptionRepository.findOneByEmail = jest
|
||||
.fn()
|
||||
.mockReturnValue({ cancelled: true, endsAt: 100 } as jest.Mocked<OfflineUserSubscription>)
|
||||
|
||||
expect(
|
||||
await createUseCase().execute({
|
||||
userEmail: 'test@test.com',
|
||||
}),
|
||||
).toEqual({
|
||||
success: false,
|
||||
error: 'subscription-canceled',
|
||||
})
|
||||
|
||||
expect(offlineSubscriptionTokenRepository.save).not.toHaveBeenCalled()
|
||||
expect(domainEventFactory.createEmailRequestedEvent).not.toHaveBeenCalled()
|
||||
expect(domainEventPublisher.publish).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('should not create an offline subscription token if email has an outdated subscription', async () => {
|
||||
offlineUserSubscriptionRepository.findOneByEmail = jest
|
||||
.fn()
|
||||
.mockReturnValue({ cancelled: false, endsAt: 2 } as jest.Mocked<OfflineUserSubscription>)
|
||||
|
||||
expect(
|
||||
await createUseCase().execute({
|
||||
userEmail: 'test@test.com',
|
||||
}),
|
||||
).toEqual({
|
||||
success: false,
|
||||
error: 'subscription-expired',
|
||||
})
|
||||
|
||||
expect(offlineSubscriptionTokenRepository.save).not.toHaveBeenCalled()
|
||||
expect(domainEventFactory.createEmailRequestedEvent).not.toHaveBeenCalled()
|
||||
expect(domainEventPublisher.publish).not.toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
|
||||
@@ -37,20 +37,6 @@ export class CreateOfflineSubscriptionToken implements UseCaseInterface {
|
||||
}
|
||||
}
|
||||
|
||||
if (existingSubscription.cancelled) {
|
||||
return {
|
||||
success: false,
|
||||
error: 'subscription-canceled',
|
||||
}
|
||||
}
|
||||
|
||||
if (existingSubscription.endsAt < this.timer.getTimestampInMicroseconds()) {
|
||||
return {
|
||||
success: false,
|
||||
error: 'subscription-expired',
|
||||
}
|
||||
}
|
||||
|
||||
const token = await this.cryptoNode.generateRandomKey(128)
|
||||
|
||||
const offlineSubscriptionToken = {
|
||||
|
||||
@@ -12,6 +12,19 @@ export class TypeORMOfflineUserSubscriptionRepository implements OfflineUserSubs
|
||||
private ormRepository: Repository<OfflineUserSubscription>,
|
||||
) {}
|
||||
|
||||
async findOneByEmailAndSubscriptionId(
|
||||
email: string,
|
||||
subscriptionId: number,
|
||||
): Promise<OfflineUserSubscription | null> {
|
||||
return await this.ormRepository
|
||||
.createQueryBuilder()
|
||||
.where('email = :email AND subscription_id = :subscriptionId', {
|
||||
email,
|
||||
subscriptionId,
|
||||
})
|
||||
.getOne()
|
||||
}
|
||||
|
||||
async save(offlineUserSubscription: OfflineUserSubscription): Promise<OfflineUserSubscription> {
|
||||
return this.ormRepository.save(offlineUserSubscription)
|
||||
}
|
||||
|
||||
@@ -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.23.3](https://github.com/standardnotes/server/compare/@standardnotes/domain-events-infra@1.23.2...@standardnotes/domain-events-infra@1.23.3) (2024-01-19)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/domain-events-infra
|
||||
|
||||
## [1.23.2](https://github.com/standardnotes/server/compare/@standardnotes/domain-events-infra@1.23.1...@standardnotes/domain-events-infra@1.23.2) (2024-01-18)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/domain-events-infra
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/domain-events-infra",
|
||||
"version": "1.23.2",
|
||||
"version": "1.23.3",
|
||||
"engines": {
|
||||
"node": ">=18.0.0 <21.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.141.0](https://github.com/standardnotes/server/compare/@standardnotes/domain-events@2.140.0...@standardnotes/domain-events@2.141.0) (2024-01-19)
|
||||
|
||||
### Features
|
||||
|
||||
* **auth:** add script for fixing subscriptions with missing id state ([#1030](https://github.com/standardnotes/server/issues/1030)) ([86b0508](https://github.com/standardnotes/server/commit/86b050865f8090ed33d5ce05528ff0e1e23657ef))
|
||||
|
||||
# [2.140.0](https://github.com/standardnotes/server/compare/@standardnotes/domain-events@2.139.3...@standardnotes/domain-events@2.140.0) (2024-01-18)
|
||||
|
||||
### Features
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/domain-events",
|
||||
"version": "2.140.0",
|
||||
"version": "2.141.0",
|
||||
"engines": {
|
||||
"node": ">=18.0.0 <21.0.0"
|
||||
},
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
import { DomainEventInterface } from './DomainEventInterface'
|
||||
|
||||
import { SubscriptionStateFetchedEventPayload } from './SubscriptionStateFetchedEventPayload'
|
||||
|
||||
export interface SubscriptionStateFetchedEvent extends DomainEventInterface {
|
||||
type: 'SUBSCRIPTION_STATE_FETCHED'
|
||||
payload: SubscriptionStateFetchedEventPayload
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
export interface SubscriptionStateFetchedEventPayload {
|
||||
userEmail: string
|
||||
subscriptionId: number
|
||||
subscriptionName: string
|
||||
subscriptionExpiresAt: number
|
||||
timestamp: number
|
||||
offline: boolean
|
||||
canceled: boolean
|
||||
extensionKey: string
|
||||
offlineFeaturesToken: string
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
import { DomainEventInterface } from './DomainEventInterface'
|
||||
|
||||
import { SubscriptionStateRequestedEventPayload } from './SubscriptionStateRequestedEventPayload'
|
||||
|
||||
export interface SubscriptionStateRequestedEvent extends DomainEventInterface {
|
||||
type: 'SUBSCRIPTION_STATE_REQUESTED'
|
||||
payload: SubscriptionStateRequestedEventPayload
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
export interface SubscriptionStateRequestedEventPayload {
|
||||
userEmail: string
|
||||
}
|
||||
@@ -110,6 +110,10 @@ export * from './Event/SubscriptionExpiredEvent'
|
||||
export * from './Event/SubscriptionExpiredEventPayload'
|
||||
export * from './Event/SubscriptionRevertRequestedEvent'
|
||||
export * from './Event/SubscriptionRevertRequestedEventPayload'
|
||||
export * from './Event/SubscriptionStateFetchedEvent'
|
||||
export * from './Event/SubscriptionStateFetchedEventPayload'
|
||||
export * from './Event/SubscriptionStateRequestedEvent'
|
||||
export * from './Event/SubscriptionStateRequestedEventPayload'
|
||||
export * from './Event/SubscriptionSyncRequestedEvent'
|
||||
export * from './Event/SubscriptionSyncRequestedEventPayload'
|
||||
export * from './Event/UserAddedToSharedVaultEvent'
|
||||
|
||||
@@ -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.37.11](https://github.com/standardnotes/server/compare/@standardnotes/files-server@1.37.10...@standardnotes/files-server@1.37.11) (2024-01-19)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/files-server
|
||||
|
||||
## [1.37.10](https://github.com/standardnotes/server/compare/@standardnotes/files-server@1.37.9...@standardnotes/files-server@1.37.10) (2024-01-18)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/files-server
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/files-server",
|
||||
"version": "1.37.10",
|
||||
"version": "1.37.11",
|
||||
"engines": {
|
||||
"node": ">=18.0.0 <21.0.0"
|
||||
},
|
||||
|
||||
@@ -3,6 +3,18 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.22.65](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.22.64...@standardnotes/home-server@1.22.65) (2024-03-15)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/home-server
|
||||
|
||||
## [1.22.64](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.22.63...@standardnotes/home-server@1.22.64) (2024-02-09)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/home-server
|
||||
|
||||
## [1.22.63](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.22.62...@standardnotes/home-server@1.22.63) (2024-01-19)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/home-server
|
||||
|
||||
## [1.22.62](https://github.com/standardnotes/server/compare/@standardnotes/home-server@1.22.61...@standardnotes/home-server@1.22.62) (2024-01-18)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/home-server
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/home-server",
|
||||
"version": "1.22.62",
|
||||
"version": "1.22.65",
|
||||
"engines": {
|
||||
"node": ">=18.0.0 <21.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.51.16](https://github.com/standardnotes/server/compare/@standardnotes/revisions-server@1.51.15...@standardnotes/revisions-server@1.51.16) (2024-01-19)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/revisions-server
|
||||
|
||||
## [1.51.15](https://github.com/standardnotes/server/compare/@standardnotes/revisions-server@1.51.14...@standardnotes/revisions-server@1.51.15) (2024-01-18)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/revisions-server
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/revisions-server",
|
||||
"version": "1.51.15",
|
||||
"version": "1.51.16",
|
||||
"engines": {
|
||||
"node": ">=18.0.0 <21.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.27.21](https://github.com/standardnotes/server/compare/@standardnotes/scheduler-server@1.27.20...@standardnotes/scheduler-server@1.27.21) (2024-01-19)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/scheduler-server
|
||||
|
||||
## [1.27.20](https://github.com/standardnotes/server/compare/@standardnotes/scheduler-server@1.27.19...@standardnotes/scheduler-server@1.27.20) (2024-01-18)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/scheduler-server
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/scheduler-server",
|
||||
"version": "1.27.20",
|
||||
"version": "1.27.21",
|
||||
"engines": {
|
||||
"node": ">=18.0.0 <21.0.0"
|
||||
},
|
||||
|
||||
@@ -3,6 +3,16 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [1.136.2](https://github.com/standardnotes/server/compare/@standardnotes/syncing-server@1.136.1...@standardnotes/syncing-server@1.136.2) (2024-03-15)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* allow handling of new api version ([9d49764](https://github.com/standardnotes/server/commit/9d49764b841e73655e19523eddf10498addc9fb4))
|
||||
|
||||
## [1.136.1](https://github.com/standardnotes/server/compare/@standardnotes/syncing-server@1.136.0...@standardnotes/syncing-server@1.136.1) (2024-01-19)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/syncing-server
|
||||
|
||||
# [1.136.0](https://github.com/standardnotes/server/compare/@standardnotes/syncing-server@1.135.0...@standardnotes/syncing-server@1.136.0) (2024-01-18)
|
||||
|
||||
### Features
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/syncing-server",
|
||||
"version": "1.136.0",
|
||||
"version": "1.136.2",
|
||||
"engines": {
|
||||
"node": ">=18.0.0 <21.0.0"
|
||||
},
|
||||
|
||||
@@ -2,4 +2,5 @@ export enum ApiVersion {
|
||||
v20161215 = '20161215',
|
||||
v20190520 = '20190520',
|
||||
v20200115 = '20200115',
|
||||
v20240226 = '20240226',
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ export class SyncResponseFactoryResolver implements SyncResponseFactoryResolverI
|
||||
switch (apiVersion) {
|
||||
case ApiVersion.v20190520:
|
||||
case ApiVersion.v20200115:
|
||||
case ApiVersion.v20240226:
|
||||
return this.syncResponseFactory20200115
|
||||
default:
|
||||
return this.syncResponseFactory20161215
|
||||
|
||||
@@ -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.22.12](https://github.com/standardnotes/server/compare/@standardnotes/websockets-server@1.22.11...@standardnotes/websockets-server@1.22.12) (2024-01-19)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/websockets-server
|
||||
|
||||
## [1.22.11](https://github.com/standardnotes/server/compare/@standardnotes/websockets-server@1.22.10...@standardnotes/websockets-server@1.22.11) (2024-01-18)
|
||||
|
||||
**Note:** Version bump only for package @standardnotes/websockets-server
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@standardnotes/websockets-server",
|
||||
"version": "1.22.11",
|
||||
"version": "1.22.12",
|
||||
"engines": {
|
||||
"node": ">=18.0.0 <21.0.0"
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user