From 8a6840e01e9660e385f1c698dee850c9d7eabcac Mon Sep 17 00:00:00 2001 From: Juliette Fournier Date: Fri, 29 Jul 2022 16:11:26 +0200 Subject: [PATCH] :package: isolate jsonSchemaCommand in a package --- .github/workflows/realease-to-npm.yml | 4 + castore.code-workspace | 8 +- demo/blueprint/package.json | 4 +- demo/blueprint/src/commands/createUser.ts | 3 +- demo/blueprint/src/commands/deleteUser.ts | 3 +- .../implementations/jsonSchema.util.test.ts | 120 ------ packages/core/src/index.ts | 2 - packages/json-schema-command/.eslintignore | 1 + packages/json-schema-command/.lintstagedrc.js | 2 + packages/json-schema-command/babel.config.js | 3 + .../json-schema-command/dependency-cruiser.js | 3 + packages/json-schema-command/jest.config.js | 8 + packages/json-schema-command/package.json | 81 +++++ packages/json-schema-command/project.json | 6 + packages/json-schema-command/src/index.ts | 2 + .../src}/jsonSchema.ts | 5 +- .../src}/jsonSchema.type.test.ts | 6 +- .../src}/jsonSchema.unit.test.ts | 11 +- .../src/jsonSchema.util.test.ts | 341 ++++++++++++++++++ .../json-schema-command/tsconfig.build.json | 7 + packages/json-schema-command/tsconfig.json | 13 + workspace.json | 1 + yarn.lock | 30 +- 23 files changed, 521 insertions(+), 143 deletions(-) delete mode 100644 packages/core/src/command/implementations/jsonSchema.util.test.ts create mode 100644 packages/json-schema-command/.eslintignore create mode 100644 packages/json-schema-command/.lintstagedrc.js create mode 100644 packages/json-schema-command/babel.config.js create mode 100644 packages/json-schema-command/dependency-cruiser.js create mode 100644 packages/json-schema-command/jest.config.js create mode 100644 packages/json-schema-command/package.json create mode 100644 packages/json-schema-command/project.json create mode 100644 packages/json-schema-command/src/index.ts rename packages/{core/src/command/implementations => json-schema-command/src}/jsonSchema.ts (94%) rename packages/{core/src/command/implementations => json-schema-command/src}/jsonSchema.type.test.ts (97%) rename packages/{core/src/command/implementations => json-schema-command/src}/jsonSchema.unit.test.ts (95%) create mode 100644 packages/json-schema-command/src/jsonSchema.util.test.ts create mode 100644 packages/json-schema-command/tsconfig.build.json create mode 100644 packages/json-schema-command/tsconfig.json diff --git a/.github/workflows/realease-to-npm.yml b/.github/workflows/realease-to-npm.yml index c4e83d1..b8444ed 100644 --- a/.github/workflows/realease-to-npm.yml +++ b/.github/workflows/realease-to-npm.yml @@ -56,3 +56,7 @@ jobs: # with: # token: ${{ secrets.NPM_TOKEN }} # package: ./packages/test-tools/package.json + # - uses: JS-DevTools/npm-publish@v1 + # with: + # token: ${{ secrets.NPM_TOKEN }} + # package: ./packages/json-schema-command/package.json diff --git a/castore.code-workspace b/castore.code-workspace index c1a16f5..0af8e82 100644 --- a/castore.code-workspace +++ b/castore.code-workspace @@ -50,11 +50,15 @@ }, { "path": "packages/json-schema-event", - "name": "📬 Json Schema" + "name": "📬 Json Schema Event" }, { "path": "packages/zod-event", - "name": "📬 Zod" + "name": "📬 Zod Event" + }, + { + "path": "packages/json-schema-command", + "name": "👮‍♀️ Json Schema Command" }, { "path": "packages/test-tools", diff --git a/demo/blueprint/package.json b/demo/blueprint/package.json index 8700e4a..aeb81e8 100644 --- a/demo/blueprint/package.json +++ b/demo/blueprint/package.json @@ -30,6 +30,8 @@ }, "dependencies": { "@babel/runtime": "^7.18.3", + "@castore/core": "^1.0.3", + "@castore/json-schema-command": "^1.0.3", "@castore/json-schema-event": "^1.0.3", "uuid": "^8.3.2" }, @@ -39,7 +41,6 @@ "@babel/plugin-transform-runtime": "^7.17.0", "@babel/preset-env": "^7.16.11", "@babel/preset-typescript": "^7.16.7", - "@castore/core": "^1.0.3", "@types/node": "^17.0.29", "@zerollup/ts-transform-paths": "^1.7.18", "babel-plugin-module-resolver": "^4.1.0", @@ -70,7 +71,6 @@ } }, "peerDependencies": { - "@castore/core": "^0.7.0", "json-schema-to-ts": "^2.0.0", "uuid": "^8.3.2" } diff --git a/demo/blueprint/src/commands/createUser.ts b/demo/blueprint/src/commands/createUser.ts index f0dc72d..e62d352 100644 --- a/demo/blueprint/src/commands/createUser.ts +++ b/demo/blueprint/src/commands/createUser.ts @@ -1,6 +1,7 @@ import { v4 as uuid } from 'uuid'; -import { JSONSchemaCommand, tuple } from '@castore/core'; +import { tuple } from '@castore/core'; +import { JSONSchemaCommand } from '@castore/json-schema-command'; import { userEventStore, UserStatus } from '~/users'; diff --git a/demo/blueprint/src/commands/deleteUser.ts b/demo/blueprint/src/commands/deleteUser.ts index 532f9fc..afae130 100644 --- a/demo/blueprint/src/commands/deleteUser.ts +++ b/demo/blueprint/src/commands/deleteUser.ts @@ -1,4 +1,5 @@ -import { JSONSchemaCommand, tuple } from '@castore/core'; +import { tuple } from '@castore/core'; +import { JSONSchemaCommand } from '@castore/json-schema-command'; import { userEventStore, UserStatus } from '~/users'; diff --git a/packages/core/src/command/implementations/jsonSchema.util.test.ts b/packages/core/src/command/implementations/jsonSchema.util.test.ts deleted file mode 100644 index 23285e1..0000000 --- a/packages/core/src/command/implementations/jsonSchema.util.test.ts +++ /dev/null @@ -1,120 +0,0 @@ -import { counterEventStore, userEventStore } from '~/eventStore.util.test'; - -import { tuple } from '../command'; -import { JSONSchemaCommand } from './jsonSchema'; - -export const inputSchema = { - type: 'object', - properties: { - counterId: { type: 'string' }, - }, - required: ['counterId'], - additionalProperties: false, -} as const; - -export const outputSchema = { - type: 'object', - properties: { - nextCount: { type: 'integer' }, - }, - required: ['nextCount'], - additionalProperties: false, -} as const; - -export const requiredEventStores = tuple(counterEventStore, userEventStore); - -export const onEventAlreadyExistsMock = jest.fn(); - -export const incrementCounter = new JSONSchemaCommand({ - commandId: 'INCREMENT_COUNTER', - requiredEventStores, - inputSchema, - outputSchema, - handler: async (input, eventStores) => { - const { counterId } = input; - const [countersStore] = eventStores; - - const { aggregate } = await countersStore.getAggregate(counterId); - if (!aggregate) throw new Error(); - - const { count, version } = aggregate; - - await countersStore.pushEvent({ - aggregateId: counterId, - version: version + 1, - type: 'COUNTER_INCREMENTED', - timestamp: new Date().toISOString(), - }); - - return { nextCount: count + 1 }; - }, - eventAlreadyExistsRetries: 2, - onEventAlreadyExists: onEventAlreadyExistsMock, -}); - -export const incrementCounterNoOutput = new JSONSchemaCommand({ - commandId: 'INCREMENT_COUNTER_NO_OUTPUT', - requiredEventStores: tuple(counterEventStore, userEventStore), - inputSchema, - handler: async (input, eventStores) => { - const { counterId } = input; - const [countersStore] = eventStores; - - const { aggregate } = await countersStore.getAggregate(counterId); - if (!aggregate) throw new Error(); - - const { version } = aggregate; - - await countersStore.pushEvent({ - aggregateId: counterId, - type: 'COUNTER_INCREMENTED', - timestamp: new Date().toISOString(), - version: version + 1, - }); - }, -}); - -export const incrementCounterA = new JSONSchemaCommand({ - commandId: 'INCREMENT_COUNTER_A', - requiredEventStores: tuple(counterEventStore, userEventStore), - outputSchema, - handler: async (_, eventStores) => { - const counterId = 'A'; - const [countersStore] = eventStores; - - const { aggregate } = await countersStore.getAggregate(counterId); - if (!aggregate) throw new Error(); - - const { count, version } = aggregate; - - await countersStore.pushEvent({ - aggregateId: counterId, - type: 'COUNTER_INCREMENTED', - timestamp: new Date().toISOString(), - version: version + 1, - }); - - return { nextCount: count + 1 }; - }, -}); - -export const incrementCounterANoOutput = new JSONSchemaCommand({ - commandId: 'INCREMENT_COUNTER_A_NO_OUTPUT', - requiredEventStores: tuple(counterEventStore, userEventStore), - handler: async (_, eventStores) => { - const counterId = 'A'; - const [countersStore] = eventStores; - - const { aggregate } = await countersStore.getAggregate(counterId); - if (!aggregate) throw new Error(); - - const { version } = aggregate; - - await countersStore.pushEvent({ - aggregateId: counterId, - type: 'COUNTER_INCREMENTED', - timestamp: new Date().toISOString(), - version: version + 1, - }); - }, -}); diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index f8eaeb6..96fbe47 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -20,5 +20,3 @@ export type { EventStoreAggregate, } from './eventStore'; export { Command, tuple } from './command/command'; -export { JSONSchemaCommand } from './command/implementations/jsonSchema'; -export type { OnEventAlreadyExistsCallback } from './command/implementations/jsonSchema'; diff --git a/packages/json-schema-command/.eslintignore b/packages/json-schema-command/.eslintignore new file mode 100644 index 0000000..1521c8b --- /dev/null +++ b/packages/json-schema-command/.eslintignore @@ -0,0 +1 @@ +dist diff --git a/packages/json-schema-command/.lintstagedrc.js b/packages/json-schema-command/.lintstagedrc.js new file mode 100644 index 0000000..08c7ed8 --- /dev/null +++ b/packages/json-schema-command/.lintstagedrc.js @@ -0,0 +1,2 @@ +const baseConfig = require('../../.lintstagedrc'); +module.exports = baseConfig; diff --git a/packages/json-schema-command/babel.config.js b/packages/json-schema-command/babel.config.js new file mode 100644 index 0000000..31b1233 --- /dev/null +++ b/packages/json-schema-command/babel.config.js @@ -0,0 +1,3 @@ +const commonBabelConfig = require('../../commonConfiguration/babel.config'); + +module.exports = commonBabelConfig(); diff --git a/packages/json-schema-command/dependency-cruiser.js b/packages/json-schema-command/dependency-cruiser.js new file mode 100644 index 0000000..fd07843 --- /dev/null +++ b/packages/json-schema-command/dependency-cruiser.js @@ -0,0 +1,3 @@ +/** @type {import('dependency-cruiser').IConfiguration} */ +const baseConfig = require('../../dependency-cruiser'); +module.exports = baseConfig; diff --git a/packages/json-schema-command/jest.config.js b/packages/json-schema-command/jest.config.js new file mode 100644 index 0000000..1b9735d --- /dev/null +++ b/packages/json-schema-command/jest.config.js @@ -0,0 +1,8 @@ +const commonConfig = require('../../commonConfiguration/jest.config'); + +const config = { + ...commonConfig, + moduleDirectories: ['node_modules', ''], +}; + +module.exports = config; diff --git a/packages/json-schema-command/package.json b/packages/json-schema-command/package.json new file mode 100644 index 0000000..802290c --- /dev/null +++ b/packages/json-schema-command/package.json @@ -0,0 +1,81 @@ +{ + "name": "@castore/json-schema-command", + "version": "1.0.3", + "license": "MIT", + "homepage": "https://github.com/theodo/castore#readme", + "bugs": "https://github.com/theodo/castore/issues", + "repository": "theodo/castore.git", + "keywords": [ + "event", + "source", + "store", + "typescript" + ], + "publishConfig": { + "access": "public" + }, + "sideEffects": false, + "files": [ + "dist" + ], + "main": "dist/cjs/index.js", + "module": "dist/esm/index.js", + "types": "dist/types/index.d.ts", + "scripts": { + "lint-fix": "yarn linter-base-config --fix", + "lint-fix-all": "yarn lint-fix .", + "linter-base-config": "eslint --ext=js,ts .", + "package": "rm -rf dist && yarn package-cjs && yarn package-esm && yarn package-types", + "package-cjs": "NODE_ENV=cjs yarn transpile --out-dir dist/cjs --source-maps", + "package-esm": "NODE_ENV=esm yarn transpile --out-dir dist/esm --source-maps", + "package-types": "ttsc -p tsconfig.build.json", + "test": "yarn test-linter && yarn test-type && yarn test-circular && yarn test-unit", + "test-circular": "yarn depcruise --validate dependency-cruiser.js .", + "test-linter": "yarn linter-base-config .", + "test-type": "tsc --noEmit --emitDeclarationOnly false", + "test-unit": "yarn jest", + "transpile": "babel src --extensions .ts --quiet", + "watch": "rm -rf dist && concurrently 'yarn:package-* --watch'" + }, + "dependencies": { + "ts-toolbelt": "^9.6.0" + }, + "devDependencies": { + "@babel/cli": "^7.17.6", + "@babel/core": "^7.17.9", + "@babel/plugin-transform-runtime": "^7.17.0", + "@babel/preset-env": "^7.16.11", + "@babel/preset-typescript": "^7.16.7", + "@castore/core": "^1.0.3", + "@types/node": "^17.0.29", + "@zerollup/ts-transform-paths": "^1.7.18", + "babel-plugin-module-resolver": "^4.1.0", + "concurrently": "^7.1.0", + "dependency-cruiser": "^11.7.0", + "eslint": "^8.14.0", + "jest": "^27.5.1", + "json-schema-to-ts": "^2.5.4", + "prettier": "^2.6.2", + "ts-node": "^10.7.0", + "ttypescript": "^1.5.13", + "typescript": "^4.6.3" + }, + "maintainers": [ + "Thomas Aribart", + "Charles Géry", + "Juliette Fournier", + "Valentin Beggi" + ], + "nx": { + "targets": { + "package": { + "outputs": [ + "packages/json-schema-command/dist" + ] + } + } + }, + "peerDependencies": { + "@castore/core": "1.0.3" + } +} diff --git a/packages/json-schema-command/project.json b/packages/json-schema-command/project.json new file mode 100644 index 0000000..d91f154 --- /dev/null +++ b/packages/json-schema-command/project.json @@ -0,0 +1,6 @@ +{ + "root": "packages/json-schema-command", + "projectType": "library", + "tags": [], + "implicitDependencies": ["core"] +} diff --git a/packages/json-schema-command/src/index.ts b/packages/json-schema-command/src/index.ts new file mode 100644 index 0000000..876815d --- /dev/null +++ b/packages/json-schema-command/src/index.ts @@ -0,0 +1,2 @@ +export { JSONSchemaCommand } from './jsonSchema'; +export type { OnEventAlreadyExistsCallback } from './jsonSchema'; diff --git a/packages/core/src/command/implementations/jsonSchema.ts b/packages/json-schema-command/src/jsonSchema.ts similarity index 94% rename from packages/core/src/command/implementations/jsonSchema.ts rename to packages/json-schema-command/src/jsonSchema.ts index 8fb7a02..6146fc9 100644 --- a/packages/core/src/command/implementations/jsonSchema.ts +++ b/packages/json-schema-command/src/jsonSchema.ts @@ -1,9 +1,6 @@ import { FromSchema, JSONSchema } from 'json-schema-to-ts'; -import { EventAlreadyExistsError } from '~/errors/eventAlreadyExists'; -import { EventStore } from '~/eventStore'; - -import { Command } from '../command'; +import { Command, EventAlreadyExistsError, EventStore } from '@castore/core'; export type OnEventAlreadyExistsCallback = ( error: EventAlreadyExistsError, diff --git a/packages/core/src/command/implementations/jsonSchema.type.test.ts b/packages/json-schema-command/src/jsonSchema.type.test.ts similarity index 97% rename from packages/core/src/command/implementations/jsonSchema.type.test.ts rename to packages/json-schema-command/src/jsonSchema.type.test.ts index ea5449c..5c4a13e 100644 --- a/packages/core/src/command/implementations/jsonSchema.type.test.ts +++ b/packages/json-schema-command/src/jsonSchema.type.test.ts @@ -1,17 +1,17 @@ +import { Command } from '@castore/core'; import { FromSchema } from 'json-schema-to-ts'; import { A } from 'ts-toolbelt'; -import { counterEventStore, userEventStore } from '~/eventStore.util.test'; - -import { Command } from '../command'; import { JSONSchemaCommand } from './jsonSchema'; import { + counterEventStore, incrementCounter, incrementCounterA, incrementCounterANoOutput, incrementCounterNoOutput, inputSchema, outputSchema, + userEventStore, } from './jsonSchema.util.test'; type Input = FromSchema; diff --git a/packages/core/src/command/implementations/jsonSchema.unit.test.ts b/packages/json-schema-command/src/jsonSchema.unit.test.ts similarity index 95% rename from packages/core/src/command/implementations/jsonSchema.unit.test.ts rename to packages/json-schema-command/src/jsonSchema.unit.test.ts index fd3572a..a3e9dc1 100644 --- a/packages/core/src/command/implementations/jsonSchema.unit.test.ts +++ b/packages/json-schema-command/src/jsonSchema.unit.test.ts @@ -1,14 +1,9 @@ -import { EventAlreadyExistsError } from '~/errors/eventAlreadyExists'; -import { EventDetail } from '~/event/eventDetail'; +import { EventDetail, EventAlreadyExistsError } from '@castore/core'; + import { counterEventsMocks, counterEventStore, getEventsMock, - pushEventMock, - userEventStore, -} from '~/eventStore.util.test'; - -import { incrementCounter, incrementCounterA, incrementCounterANoOutput, @@ -16,7 +11,9 @@ import { inputSchema, onEventAlreadyExistsMock, outputSchema, + pushEventMock, requiredEventStores, + userEventStore, } from './jsonSchema.util.test'; getEventsMock.mockResolvedValue({ events: counterEventsMocks }); diff --git a/packages/json-schema-command/src/jsonSchema.util.test.ts b/packages/json-schema-command/src/jsonSchema.util.test.ts new file mode 100644 index 0000000..6589569 --- /dev/null +++ b/packages/json-schema-command/src/jsonSchema.util.test.ts @@ -0,0 +1,341 @@ +/* eslint-disable max-lines */ +import { + EventStore, + EventType, + EventTypeDetail, + StorageAdapter, + tuple, +} from '@castore/core'; + +import { JSONSchemaCommand } from './jsonSchema'; + +export const pushEventMock = jest.fn(); +export const pushEventTransactionMock = jest.fn(); +export const getEventsMock = jest.fn(); +export const listAggregateIdsMock = jest.fn(); + +export const mockStorageAdapter = new StorageAdapter({ + pushEvent: pushEventMock, + pushEventTransaction: pushEventTransactionMock, + getEvents: getEventsMock, + listAggregateIds: listAggregateIdsMock, +}); + +// Counters + +export const counterCreatedEvent = new EventType< + 'COUNTER_CREATED', + { + aggregateId: string; + version: number; + type: 'COUNTER_CREATED'; + timestamp: string; + } +>({ + type: 'COUNTER_CREATED', +}); + +export const counterIncrementedEvent = new EventType< + 'COUNTER_INCREMENTED', + { + aggregateId: string; + version: number; + type: 'COUNTER_INCREMENTED'; + timestamp: string; + } +>({ + type: 'COUNTER_INCREMENTED', +}); + +export const counterDeletedEvent = new EventType< + 'COUNTER_DELETED', + { + aggregateId: string; + version: number; + type: 'COUNTER_DELETED'; + timestamp: string; + } +>({ + type: 'COUNTER_DELETED', +}); + +export type CounterEventsDetails = + | EventTypeDetail + | EventTypeDetail + | EventTypeDetail; + +export type CounterAggregate = { + aggregateId: string; + version: number; + count: number; + status: string; +}; + +export const counterIdMock = 'counterId'; +export const counterEventsMocks: [CounterEventsDetails, CounterEventsDetails] = + [ + { + aggregateId: counterIdMock, + version: 1, + type: 'COUNTER_CREATED', + timestamp: '2022', + }, + { + aggregateId: counterIdMock, + version: 2, + type: 'COUNTER_INCREMENTED', + timestamp: '2023', + }, + ]; + +export const countersReducer = ( + counterAggregate: CounterAggregate, + event: CounterEventsDetails, +): CounterAggregate => { + const { version, aggregateId } = event; + + switch (event.type) { + case 'COUNTER_CREATED': + return { + aggregateId, + version: event.version, + count: 0, + status: 'LIVE', + }; + case 'COUNTER_INCREMENTED': + return { + ...counterAggregate, + version, + count: counterAggregate.count + 1, + }; + case 'COUNTER_DELETED': + return { + ...counterAggregate, + version, + status: 'DELETED', + }; + default: { + return { + ...counterAggregate, + version, + }; + } + } +}; + +export const counterEventStore = new EventStore({ + eventStoreId: 'Counters', + eventStoreEvents: [ + counterCreatedEvent, + counterIncrementedEvent, + counterDeletedEvent, + ], + reduce: countersReducer, + storageAdapter: mockStorageAdapter, +}); + +// Users + +export const userCreatedEvent = new EventType< + 'USER_CREATED', + { + aggregateId: string; + version: number; + type: 'USER_CREATED'; + timestamp: string; + payload: { name: string; age: number }; + } +>({ + type: 'USER_CREATED', +}); + +export const userRemovedEvent = new EventType< + 'USER_REMOVED', + { + aggregateId: string; + version: number; + type: 'USER_REMOVED'; + timestamp: string; + } +>({ + type: 'USER_REMOVED', +}); + +export type UserEventsDetails = + | EventTypeDetail + | EventTypeDetail; + +export type UserAggregate = { + aggregateId: string; + version: number; + name: string; + age: number; + status: string; +}; + +export const userIdMock = 'userId'; +export const userEventsMocks: UserEventsDetails[] = [ + { + aggregateId: counterIdMock, + version: 1, + type: 'USER_CREATED', + timestamp: '2022', + payload: { name: 'Toto', age: 42 }, + }, + { + aggregateId: counterIdMock, + version: 2, + type: 'USER_REMOVED', + timestamp: '2023', + }, +]; + +export const usersReducer = ( + userAggregate: UserAggregate, + event: UserEventsDetails, +): UserAggregate => { + const { version, aggregateId } = event; + + switch (event.type) { + case 'USER_CREATED': { + const { name, age } = event.payload; + + return { + aggregateId, + version: event.version, + name, + age, + status: 'CREATED', + }; + } + case 'USER_REMOVED': + return { + ...userAggregate, + version, + status: 'DELETED', + }; + } +}; + +export const userEventStore = new EventStore({ + eventStoreId: 'Users', + eventStoreEvents: [userCreatedEvent, userRemovedEvent], + reduce: usersReducer, + storageAdapter: mockStorageAdapter, +}); + +export const inputSchema = { + type: 'object', + properties: { + counterId: { type: 'string' }, + }, + required: ['counterId'], + additionalProperties: false, +} as const; + +export const outputSchema = { + type: 'object', + properties: { + nextCount: { type: 'integer' }, + }, + required: ['nextCount'], + additionalProperties: false, +} as const; + +export const requiredEventStores = tuple(counterEventStore, userEventStore); + +export const onEventAlreadyExistsMock = jest.fn(); + +export const incrementCounter = new JSONSchemaCommand({ + commandId: 'INCREMENT_COUNTER', + requiredEventStores, + inputSchema, + outputSchema, + handler: async (input, eventStores) => { + const { counterId } = input; + const [countersStore] = eventStores; + + const { aggregate } = await countersStore.getAggregate(counterId); + if (!aggregate) throw new Error(); + + const { count, version } = aggregate; + + await countersStore.pushEvent({ + aggregateId: counterId, + version: version + 1, + type: 'COUNTER_INCREMENTED', + timestamp: new Date().toISOString(), + }); + + return { nextCount: count + 1 }; + }, + eventAlreadyExistsRetries: 2, + onEventAlreadyExists: onEventAlreadyExistsMock, +}); + +export const incrementCounterNoOutput = new JSONSchemaCommand({ + commandId: 'INCREMENT_COUNTER_NO_OUTPUT', + requiredEventStores: tuple(counterEventStore, userEventStore), + inputSchema, + handler: async (input, eventStores) => { + const { counterId } = input; + const [countersStore] = eventStores; + + const { aggregate } = await countersStore.getAggregate(counterId); + if (!aggregate) throw new Error(); + + const { version } = aggregate; + + await countersStore.pushEvent({ + aggregateId: counterId, + type: 'COUNTER_INCREMENTED', + timestamp: new Date().toISOString(), + version: version + 1, + }); + }, +}); + +export const incrementCounterA = new JSONSchemaCommand({ + commandId: 'INCREMENT_COUNTER_A', + requiredEventStores: tuple(counterEventStore, userEventStore), + outputSchema, + handler: async (_, eventStores) => { + const counterId = 'A'; + const [countersStore] = eventStores; + + const { aggregate } = await countersStore.getAggregate(counterId); + if (!aggregate) throw new Error(); + + const { count, version } = aggregate; + + await countersStore.pushEvent({ + aggregateId: counterId, + type: 'COUNTER_INCREMENTED', + timestamp: new Date().toISOString(), + version: version + 1, + }); + + return { nextCount: count + 1 }; + }, +}); + +export const incrementCounterANoOutput = new JSONSchemaCommand({ + commandId: 'INCREMENT_COUNTER_A_NO_OUTPUT', + requiredEventStores: tuple(counterEventStore, userEventStore), + handler: async (_, eventStores) => { + const counterId = 'A'; + const [countersStore] = eventStores; + + const { aggregate } = await countersStore.getAggregate(counterId); + if (!aggregate) throw new Error(); + + const { version } = aggregate; + + await countersStore.pushEvent({ + aggregateId: counterId, + type: 'COUNTER_INCREMENTED', + timestamp: new Date().toISOString(), + version: version + 1, + }); + }, +}); diff --git a/packages/json-schema-command/tsconfig.build.json b/packages/json-schema-command/tsconfig.build.json new file mode 100644 index 0000000..245ebd2 --- /dev/null +++ b/packages/json-schema-command/tsconfig.build.json @@ -0,0 +1,7 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "rootDir": "src" + }, + "exclude": ["./dist", "./jest.config.ts"] +} diff --git a/packages/json-schema-command/tsconfig.json b/packages/json-schema-command/tsconfig.json new file mode 100644 index 0000000..b2cab59 --- /dev/null +++ b/packages/json-schema-command/tsconfig.json @@ -0,0 +1,13 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "baseUrl": "src", + "composite": true, + "plugins": [{ "transform": "@zerollup/ts-transform-paths" }], + "emitDeclarationOnly": true, + "outDir": "./dist/types", + "esModuleInterop": true + }, + "exclude": ["./dist"], + "include": ["./**/*.ts"] +} diff --git a/workspace.json b/workspace.json index e1dfdea..2410708 100644 --- a/workspace.json +++ b/workspace.json @@ -6,6 +6,7 @@ "inmemory-event-storage-adapter": "packages/inmemory-event-storage-adapter", "json-schema-event": "packages/json-schema-event", "zod-event": "packages/zod-event", + "json-schema-command": "packages/json-schema-command", "demo-blueprint": "demo/blueprint", "demo-implementation": "demo/implementation", "demo-visualization": "demo/visualization", diff --git a/yarn.lock b/yarn.lock index becd5c8..bcaa56e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3516,6 +3516,7 @@ __metadata: "@babel/preset-typescript": ^7.16.7 "@babel/runtime": ^7.18.3 "@castore/core": ^1.0.3 + "@castore/json-schema-command": ^1.0.3 "@castore/json-schema-event": ^1.0.3 "@types/node": ^17.0.29 "@zerollup/ts-transform-paths": ^1.7.18 @@ -3532,7 +3533,6 @@ __metadata: typescript: ^4.6.3 uuid: ^8.3.2 peerDependencies: - "@castore/core": ^0.7.0 json-schema-to-ts: ^2.0.0 uuid: ^8.3.2 languageName: unknown @@ -3674,6 +3674,34 @@ __metadata: languageName: unknown linkType: soft +"@castore/json-schema-command@^1.0.3, @castore/json-schema-command@workspace:packages/json-schema-command": + version: 0.0.0-use.local + resolution: "@castore/json-schema-command@workspace:packages/json-schema-command" + dependencies: + "@babel/cli": ^7.17.6 + "@babel/core": ^7.17.9 + "@babel/plugin-transform-runtime": ^7.17.0 + "@babel/preset-env": ^7.16.11 + "@babel/preset-typescript": ^7.16.7 + "@castore/core": ^1.0.3 + "@types/node": ^17.0.29 + "@zerollup/ts-transform-paths": ^1.7.18 + babel-plugin-module-resolver: ^4.1.0 + concurrently: ^7.1.0 + dependency-cruiser: ^11.7.0 + eslint: ^8.14.0 + jest: ^27.5.1 + json-schema-to-ts: ^2.5.4 + prettier: ^2.6.2 + ts-node: ^10.7.0 + ts-toolbelt: ^9.6.0 + ttypescript: ^1.5.13 + typescript: ^4.6.3 + peerDependencies: + "@castore/core": 1.0.3 + languageName: unknown + linkType: soft + "@castore/json-schema-event@^1.0.3, @castore/json-schema-event@workspace:packages/json-schema-event": version: 0.0.0-use.local resolution: "@castore/json-schema-event@workspace:packages/json-schema-event"