@auto-engineer/server-generator-apollo-emmett 0.1.4 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/.turbo/turbo-test.log +117 -171
  3. package/.turbo/turbo-type-check.log +4 -5
  4. package/CHANGELOG.md +12 -0
  5. package/dist/commands/generate-server.d.ts +11 -45
  6. package/dist/commands/generate-server.d.ts.map +1 -1
  7. package/dist/commands/generate-server.js +29 -24
  8. package/dist/commands/generate-server.js.map +1 -1
  9. package/dist/index.d.ts +11 -2
  10. package/dist/index.d.ts.map +1 -1
  11. package/dist/index.js +2 -2
  12. package/dist/index.js.map +1 -1
  13. package/package.json +4 -4
  14. package/src/commands/generate-server.ts +29 -28
  15. package/src/index.ts +8 -2
  16. package/tsconfig.tsbuildinfo +1 -1
  17. package/.tmp/server-test-output/server/package.json +0 -26
  18. package/.tmp/server-test-output/server/scripts/generate-schema.ts +0 -31
  19. package/.tmp/server-test-output/server/src/domain/flows/add-item/create-item/commands.ts +0 -8
  20. package/.tmp/server-test-output/server/src/domain/flows/add-item/create-item/decide.specs.ts +0 -36
  21. package/.tmp/server-test-output/server/src/domain/flows/add-item/create-item/decide.ts +0 -33
  22. package/.tmp/server-test-output/server/src/domain/flows/add-item/create-item/events.ts +0 -10
  23. package/.tmp/server-test-output/server/src/domain/flows/add-item/create-item/evolve.ts +0 -28
  24. package/.tmp/server-test-output/server/src/domain/flows/add-item/create-item/handle.ts +0 -24
  25. package/.tmp/server-test-output/server/src/domain/flows/add-item/create-item/mutation.resolver.ts +0 -25
  26. package/.tmp/server-test-output/server/src/domain/flows/add-item/create-item/register.ts +0 -7
  27. package/.tmp/server-test-output/server/src/domain/flows/add-item/create-item/state.ts +0 -47
  28. package/.tmp/server-test-output/server/src/domain/flows/add-item/get-available-items/projection.specs.ts +0 -46
  29. package/.tmp/server-test-output/server/src/domain/flows/add-item/get-available-items/projection.ts +0 -38
  30. package/.tmp/server-test-output/server/src/domain/flows/add-item/get-available-items/query.resolver.ts +0 -39
  31. package/.tmp/server-test-output/server/src/domain/flows/add-item/get-available-items/state.ts +0 -5
  32. package/.tmp/server-test-output/server/src/domain/flows/add-item/notify-new-item/commands.ts +0 -8
  33. package/.tmp/server-test-output/server/src/domain/flows/add-item/notify-new-item/decide.specs.ts +0 -36
  34. package/.tmp/server-test-output/server/src/domain/flows/add-item/notify-new-item/decide.ts +0 -33
  35. package/.tmp/server-test-output/server/src/domain/flows/add-item/notify-new-item/events.ts +0 -3
  36. package/.tmp/server-test-output/server/src/domain/flows/add-item/notify-new-item/evolve.ts +0 -28
  37. package/.tmp/server-test-output/server/src/domain/flows/add-item/notify-new-item/handle.ts +0 -24
  38. package/.tmp/server-test-output/server/src/domain/flows/add-item/notify-new-item/mutation.resolver.ts +0 -25
  39. package/.tmp/server-test-output/server/src/domain/flows/add-item/notify-new-item/register.ts +0 -7
  40. package/.tmp/server-test-output/server/src/domain/flows/add-item/notify-new-item/state.ts +0 -47
  41. package/.tmp/server-test-output/server/src/domain/flows/add-item/notify-on-new-item/react.specs.ts +0 -49
  42. package/.tmp/server-test-output/server/src/domain/flows/add-item/notify-on-new-item/react.ts +0 -43
  43. package/.tmp/server-test-output/server/src/domain/flows/add-item/notify-on-new-item/register.ts +0 -24
  44. package/.tmp/server-test-output/server/src/domain/shared/ReadModel.ts +0 -26
  45. package/.tmp/server-test-output/server/src/domain/shared/index.ts +0 -4
  46. package/.tmp/server-test-output/server/src/domain/shared/reactorSpecification.ts +0 -257
  47. package/.tmp/server-test-output/server/src/domain/shared/sendCommand.ts +0 -21
  48. package/.tmp/server-test-output/server/src/domain/shared/types.ts +0 -31
  49. package/.tmp/server-test-output/server/src/server.ts +0 -43
  50. package/.tmp/server-test-output/server/src/utils/index.ts +0 -3
  51. package/.tmp/server-test-output/server/src/utils/loadProjections.ts +0 -30
  52. package/.tmp/server-test-output/server/src/utils/loadRegisterFiles.ts +0 -41
  53. package/.tmp/server-test-output/server/src/utils/loadResolvers.ts +0 -36
  54. package/.tmp/server-test-output/server/tsconfig.json +0 -19
  55. package/.tmp/server-test-output/server/vitest.config.ts +0 -7
  56. package/.turbo/turbo-format.log +0 -57
  57. package/.turbo/turbo-lint.log +0 -5
  58. package/dist/cli-manifest.d.ts +0 -3
  59. package/dist/cli-manifest.d.ts.map +0 -1
  60. package/dist/cli-manifest.js +0 -35
  61. package/dist/cli-manifest.js.map +0 -1
  62. package/src/cli-manifest.ts +0 -37
@@ -1,26 +0,0 @@
1
- {
2
- "name": "generated-server",
3
- "version": "0.0.0",
4
- "private": true,
5
- "type": "module",
6
- "scripts": {
7
- "start": "tsx src/server.ts",
8
- "type-check": "tsc --noEmit",
9
- "test": "vitest run",
10
- "dev": "tsx src/server.ts"
11
- },
12
- "dependencies": {
13
- "@event-driven-io/emmett": "^0.38.2",
14
- "type-graphql": "^2.0.0-rc.2",
15
- "graphql": "^16.11.0",
16
- "fast-glob": "^3.3.3",
17
- "reflect-metadata": "^0.2.2",
18
- "apollo-server": "^3.13.0",
19
- "uuid": "^10.0.0"
20
- },
21
- "devDependencies": {
22
- "typescript": "~5.5.0",
23
- "vitest": "^3.2.3",
24
- "tsx": "^4.7.1"
25
- }
26
- }
@@ -1,31 +0,0 @@
1
- import 'reflect-metadata';
2
- import { buildSchema } from 'type-graphql';
3
- import { printSchema } from 'graphql';
4
- import { writeFile } from 'fs/promises';
5
- import * as path from 'path';
6
- import { loadResolvers } from '../src/utils/loadResolvers.js';
7
-
8
- async function main() {
9
- try {
10
- const resolvers = await loadResolvers('src/domain/flows/**/*.resolver.{ts,js}');
11
- const schema = await buildSchema({
12
- resolvers: resolvers as any,
13
- emitSchemaFile: false,
14
- });
15
- const printedSchema = printSchema(schema);
16
-
17
- const contextDir = path.resolve('/Users/sam/WebstormProjects/auto-engineer/packages/emmett-generator/.tmp/server-test-output', '.context');
18
- const schemaPath = path.join(contextDir, 'schema.graphql');
19
- await writeFile(schemaPath, printedSchema, 'utf-8');
20
-
21
- console.log(`✅ GraphQL schema generated at: ${schemaPath}`);
22
- } catch (error) {
23
- console.error(`❌ GraphQL schema generation failed: ${error instanceof Error ? error.message : 'Unknown error'}`);
24
- process.exit(1);
25
- }
26
- }
27
-
28
- main().catch((err) => {
29
- console.error(err);
30
- process.exit(1);
31
- });
@@ -1,8 +0,0 @@
1
- import { Command } from '@event-driven-io/emmett';
2
- export type CreateItem = Command<
3
- 'CreateItem',
4
- {
5
- itemId: string;
6
- description: string;
7
- }
8
- >;
@@ -1,36 +0,0 @@
1
- import { describe, it } from 'vitest';
2
- import { DeciderSpecification } from '@event-driven-io/emmett';
3
- import { decide } from './decide';
4
- import { evolve } from './evolve';
5
- import { initialState } from './state';
6
-
7
- describe('Add item | Create item', () => {
8
- const given = DeciderSpecification.for({
9
- decide,
10
- evolve,
11
- initialState,
12
- });
13
-
14
- it('should emit ItemCreated for valid CreateItem', () => {
15
- given([])
16
- .when({
17
- type: 'CreateItem',
18
- data: {
19
- itemId: 'item_123',
20
- description: 'A new item',
21
- },
22
- metadata: { now: new Date() },
23
- })
24
-
25
- .then([
26
- {
27
- type: 'ItemCreated',
28
- data: {
29
- id: 'item_123',
30
- description: 'A new item',
31
- addedAt: new Date('2024-01-15T10:00:00.000Z'),
32
- },
33
- },
34
- ]);
35
- });
36
- });
@@ -1,33 +0,0 @@
1
- import { IllegalStateError } from '@event-driven-io/emmett';
2
- import type { State } from './state';
3
- import type { CreateItem } from './commands';
4
- import type { ItemCreated } from './events';
5
-
6
- export const decide = (command: CreateItem, state: State): ItemCreated => {
7
- switch (command.type) {
8
- case 'CreateItem': {
9
- /**
10
- * ## IMPLEMENTATION INSTRUCTIONS ##
11
- *
12
- * This command can directly emit one or more events based on the input.
13
- *
14
- * You should:
15
- * - Validate the command input fields
16
- * - Inspect the current domain `state` to determine if the command is allowed
17
- * - If invalid, throw one of the following domain errors: `NotFoundError`, `ValidationError`, or `IllegalStateError`
18
- * - If valid, return one or more events with the correct structure
19
- *
20
- * ⚠️ Only read from inputs — never mutate them. `evolve.ts` handles state updates.
21
- */
22
-
23
- // return {
24
- // type: 'ItemCreated',
25
- // data: { ...command.data },
26
- // } as ItemCreated;
27
-
28
- throw new IllegalStateError('Not yet implemented: ' + command.type);
29
- }
30
- default:
31
- throw new IllegalStateError('Unexpected command type: ' + command.type);
32
- }
33
- };
@@ -1,10 +0,0 @@
1
- import type { Event } from '@event-driven-io/emmett';
2
-
3
- export type ItemCreated = Event<
4
- 'ItemCreated',
5
- {
6
- id: string;
7
- description: string;
8
- addedAt: Date;
9
- }
10
- >;
@@ -1,28 +0,0 @@
1
- import type { State } from './state';
2
- import type { ItemCreated } from './events';
3
-
4
- /**
5
- * ## IMPLEMENTATION INSTRUCTIONS ##
6
- *
7
- * This function defines how the domain state evolves in response to events.
8
- *
9
- * Guidelines:
10
- * - Apply only the **minimal** necessary changes for future decisions in `decide.ts`.
11
- * - Ignore any event fields not required for decision-making logic.
12
- * - If the event doesn’t change decision-relevant state, return the existing `state`.
13
- * - Prefer immutability: always return a **new state object**.
14
- * - Avoid spreading all of `event.data` unless all fields are relevant.
15
- */
16
-
17
- export const evolve = (state: State, event: ItemCreated): State => {
18
- switch (event.type) {
19
- case 'ItemCreated': {
20
- // TODO: Update state based on ItemCreated
21
- return {
22
- ...state,
23
- };
24
- }
25
- default:
26
- return state;
27
- }
28
- };
@@ -1,24 +0,0 @@
1
- import { CommandHandler, type EventStore, type MessageHandlerResult } from '@event-driven-io/emmett';
2
- import { evolve } from './evolve';
3
- import { initialState } from './state';
4
- import { decide } from './decide';
5
- import type { CreateItem } from './commands';
6
-
7
- const handler = CommandHandler({
8
- evolve,
9
- initialState,
10
- });
11
-
12
- export const handle = async (eventStore: EventStore, command: CreateItem): Promise<MessageHandlerResult> => {
13
- const streamId = 'unknown-stream';
14
-
15
- try {
16
- await handler(eventStore, streamId, (state) => decide(command, state));
17
- return; // success (returns void)
18
- } catch (error: any) {
19
- return {
20
- type: 'SKIP',
21
- reason: `Command failed: ${error?.message ?? 'Unknown'}`,
22
- };
23
- }
24
- };
@@ -1,25 +0,0 @@
1
- import { Mutation, Resolver, Arg, Ctx, Field, InputType } from 'type-graphql';
2
- import { type GraphQLContext, sendCommand, MutationResponse } from '../../../shared';
3
-
4
- @InputType()
5
- export class CreateItemInput {
6
- @Field(() => String)
7
- itemId!: string;
8
- @Field(() => String)
9
- description!: string;
10
- }
11
-
12
- @Resolver()
13
- export class CreateItemResolver {
14
- @Mutation(() => MutationResponse)
15
- async createItem(
16
- @Arg('input', () => CreateItemInput) input: CreateItemInput,
17
- @Ctx() ctx: GraphQLContext,
18
- ): Promise<MutationResponse> {
19
- return await sendCommand(ctx.messageBus, {
20
- type: 'CreateItem',
21
- kind: 'Command',
22
- data: { ...input },
23
- });
24
- }
25
- }
@@ -1,7 +0,0 @@
1
- import type { CommandProcessor, EventStore } from '@event-driven-io/emmett';
2
- import { handle } from './handle';
3
- import type { CreateItem } from './commands';
4
-
5
- export function register(messageBus: CommandProcessor, eventStore: EventStore) {
6
- messageBus.handle((command: CreateItem) => handle(eventStore, command), 'CreateItem');
7
- }
@@ -1,47 +0,0 @@
1
- /**
2
- * ## IMPLEMENTATION INSTRUCTIONS ##
3
- *
4
- * Define the shape of the domain state for the current slice below. This state is used by `decide.ts`
5
- * to determine whether a command is valid.
6
- *
7
- * The state is evolved over time by applying domain events (in `evolve.ts`).
8
- * Each event updates the state incrementally based on business rules.
9
- *
10
- * Guidelines:
11
- * - Include only fields that are **read** during command validation.
12
- * - Use discriminated unions (e.g., `status: 'Pending' | 'Done'`) to model state transitions.
13
- * - Prefer primitive types: `string`, `boolean`, `number`.
14
- * - Use objects or maps only when structure is essential for decision logic.
15
- *
16
- * Do NOT include:
17
- * - Redundant data already emitted in events unless required to enforce business rules.
18
- * - Fields used only for projections, UI, or query purposes.
19
- *
20
- * ### Example (for a Task domain):
21
- *
22
- * ```ts
23
- * export type PendingTask = {
24
- * status: 'Pending';
25
- * };
26
- *
27
- * export type InProgressTask = {
28
- * status: 'InProgress';
29
- * startedAt: string;
30
- * };
31
- *
32
- * export type CompletedTask = {
33
- * status: 'Completed';
34
- * completedAt: string;
35
- * };
36
- *
37
- * export type State = PendingTask | InProgressTask | CompletedTask;
38
- * ```
39
- */
40
-
41
- // TODO: Replace with a discriminated union of domain states for the current slice
42
- export type State = {};
43
-
44
- // TODO: Replace the Return with the initial domain state of the current slice
45
- export const initialState = (): State => {
46
- return {};
47
- };
@@ -1,46 +0,0 @@
1
- import { describe, it, beforeEach, expect } from 'vitest';
2
- import { InMemoryProjectionSpec } from '@event-driven-io/emmett';
3
- import { projection } from './projection';
4
- import type { ItemCreated } from '../create-item/events';
5
- import { AvailableItems } from './state';
6
-
7
- type ProjectionEvent = ItemCreated;
8
-
9
- describe('ItemCreated Projection', () => {
10
- let given: InMemoryProjectionSpec<ProjectionEvent>;
11
-
12
- beforeEach(() => {
13
- given = InMemoryProjectionSpec.for({ projection });
14
- });
15
-
16
- it('creates or updates AvailableItems document - case 1', () =>
17
- given([
18
- {
19
- type: 'ItemCreated',
20
- data: {
21
- id: 'item_123',
22
- description: 'A new item',
23
- addedAt: new Date('2024-01-15T10:00:00.000Z'),
24
- },
25
- metadata: {
26
- streamName: 'ignored-stream',
27
- streamPosition: 1n,
28
- globalPosition: 1n,
29
- },
30
- },
31
- ])
32
- .when([])
33
- .then(async (state) => {
34
- const document = await state.database
35
- .collection<AvailableItems>('item-created')
36
- .findOne((doc) => doc.id === 'item_123');
37
-
38
- const expected: AvailableItems = {
39
- id: 'item_123',
40
- description: 'A new item',
41
- addedAt: new Date('2024-01-15T10:00:00.000Z'),
42
- };
43
-
44
- expect(document).toMatchObject(expected);
45
- }));
46
- });
@@ -1,38 +0,0 @@
1
- import {
2
- inMemorySingleStreamProjection,
3
- type ReadEvent,
4
- type InMemoryReadEventMetadata,
5
- } from '@event-driven-io/emmett';
6
- import type { AvailableItems } from './state';
7
- import type { ItemCreated } from '../create-item/events';
8
-
9
- type AllEvents = ItemCreated;
10
-
11
- export const projection = inMemorySingleStreamProjection<AvailableItems, AllEvents>({
12
- collectionName: 'item-created',
13
- canHandle: ['ItemCreated'],
14
- getDocumentId: (event) => event.data.id,
15
- evolve: (
16
- document: AvailableItems | null,
17
- event: ReadEvent<AllEvents, InMemoryReadEventMetadata>,
18
- ): AvailableItems | null => {
19
- switch (event.type) {
20
- case 'ItemCreated': {
21
- /**
22
- * ## IMPLEMENTATION INSTRUCTIONS ##
23
- * This event adds or updates the document.
24
- * Implement the correct fields as needed for your read model.
25
- */
26
- return {
27
- id: /* TODO: map from event.data */ '',
28
- description: /* TODO: map from event.data */ '',
29
- addedAt: /* TODO: map from event.data */ new Date(),
30
- };
31
- }
32
- default:
33
- return document;
34
- }
35
- },
36
- });
37
-
38
- export default projection;
@@ -1,39 +0,0 @@
1
- import { Query, Resolver, Arg, Ctx, ObjectType, Field } from 'type-graphql';
2
- import { type GraphQLContext, ReadModel } from '../../../shared';
3
-
4
- @ObjectType()
5
- export class AvailableItems {
6
- @Field(() => String)
7
- id!: string;
8
-
9
- @Field(() => String)
10
- description!: string;
11
-
12
- @Field(() => Date)
13
- addedAt!: Date;
14
-
15
- [key: string]: unknown;
16
- }
17
-
18
- @Resolver()
19
- export class GetAvailableItemsQueryResolver {
20
- @Query(() => [AvailableItems])
21
- async getAvailableItems(@Ctx() ctx: GraphQLContext): Promise<AvailableItems[]> {
22
- const model = new ReadModel<AvailableItems>(ctx.eventStore, 'ItemCreated');
23
-
24
- // ## IMPLEMENTATION INSTRUCTIONS ##
25
- // You can query the projection using the ReadModel API:
26
- //
27
- // - model.getAll() — fetch all documents
28
- // - model.getById(id) — fetch a single document by ID (default key: 'id')
29
- // - model.find(filterFn) — filter documents using a predicate
30
- // - model.first(filterFn) — fetch the first document matching a predicate
31
- //
32
- // Example below uses `.find()` to filter
33
- // change the logic for the query as needed to meet the requirements for the current slice.
34
-
35
- return model.find((item) => {
36
- return true;
37
- });
38
- }
39
- }
@@ -1,5 +0,0 @@
1
- export type AvailableItems = {
2
- id: string;
3
- description: string;
4
- addedAt: Date;
5
- };
@@ -1,8 +0,0 @@
1
- import { Command } from '@event-driven-io/emmett';
2
- export type NotifyNewItem = Command<
3
- 'NotifyNewItem',
4
- {
5
- itemId: string;
6
- message: string;
7
- }
8
- >;
@@ -1,36 +0,0 @@
1
- import { describe, it } from 'vitest';
2
- import { DeciderSpecification } from '@event-driven-io/emmett';
3
- import { decide } from './decide';
4
- import { evolve } from './evolve';
5
- import { initialState } from './state';
6
-
7
- describe('Add item | Notify new item', () => {
8
- const given = DeciderSpecification.for({
9
- decide,
10
- evolve,
11
- initialState,
12
- });
13
-
14
- it('should emit NotificationSent for valid NotifyNewItem', () => {
15
- given([])
16
- .when({
17
- type: 'NotifyNewItem',
18
- data: {
19
- itemId: 'item_123',
20
- message: 'A new item was added to the system.',
21
- },
22
- metadata: { now: new Date() },
23
- })
24
-
25
- .then([
26
- {
27
- type: 'NotificationSent',
28
- data: {
29
- itemId: 'item_123',
30
- message: 'A new item was added to the system.',
31
- sentAt: '2024-01-15T10:00:00.000Z',
32
- },
33
- },
34
- ]);
35
- });
36
- });
@@ -1,33 +0,0 @@
1
- import { IllegalStateError } from '@event-driven-io/emmett';
2
- import type { State } from './state';
3
- import type { NotifyNewItem } from './commands';
4
- import type { NotificationSent } from './events';
5
-
6
- export const decide = (command: NotifyNewItem, state: State): NotificationSent => {
7
- switch (command.type) {
8
- case 'NotifyNewItem': {
9
- /**
10
- * ## IMPLEMENTATION INSTRUCTIONS ##
11
- *
12
- * This command can directly emit one or more events based on the input.
13
- *
14
- * You should:
15
- * - Validate the command input fields
16
- * - Inspect the current domain `state` to determine if the command is allowed
17
- * - If invalid, throw one of the following domain errors: `NotFoundError`, `ValidationError`, or `IllegalStateError`
18
- * - If valid, return one or more events with the correct structure
19
- *
20
- * ⚠️ Only read from inputs — never mutate them. `evolve.ts` handles state updates.
21
- */
22
-
23
- // return {
24
- // type: 'NotificationSent',
25
- // data: { ...command.data },
26
- // } as NotificationSent;
27
-
28
- throw new IllegalStateError('Not yet implemented: ' + command.type);
29
- }
30
- default:
31
- throw new IllegalStateError('Unexpected command type: ' + command.type);
32
- }
33
- };
@@ -1,3 +0,0 @@
1
- import type { Event } from '@event-driven-io/emmett';
2
-
3
- export type NotificationSent = Event<'NotificationSent', {}>;
@@ -1,28 +0,0 @@
1
- import type { State } from './state';
2
- import type { NotificationSent } from './events';
3
-
4
- /**
5
- * ## IMPLEMENTATION INSTRUCTIONS ##
6
- *
7
- * This function defines how the domain state evolves in response to events.
8
- *
9
- * Guidelines:
10
- * - Apply only the **minimal** necessary changes for future decisions in `decide.ts`.
11
- * - Ignore any event fields not required for decision-making logic.
12
- * - If the event doesn’t change decision-relevant state, return the existing `state`.
13
- * - Prefer immutability: always return a **new state object**.
14
- * - Avoid spreading all of `event.data` unless all fields are relevant.
15
- */
16
-
17
- export const evolve = (state: State, event: NotificationSent): State => {
18
- switch (event.type) {
19
- case 'NotificationSent': {
20
- // TODO: Update state based on NotificationSent
21
- return {
22
- ...state,
23
- };
24
- }
25
- default:
26
- return state;
27
- }
28
- };
@@ -1,24 +0,0 @@
1
- import { CommandHandler, type EventStore, type MessageHandlerResult } from '@event-driven-io/emmett';
2
- import { evolve } from './evolve';
3
- import { initialState } from './state';
4
- import { decide } from './decide';
5
- import type { NotifyNewItem } from './commands';
6
-
7
- const handler = CommandHandler({
8
- evolve,
9
- initialState,
10
- });
11
-
12
- export const handle = async (eventStore: EventStore, command: NotifyNewItem): Promise<MessageHandlerResult> => {
13
- const streamId = 'unknown-stream';
14
-
15
- try {
16
- await handler(eventStore, streamId, (state) => decide(command, state));
17
- return; // success (returns void)
18
- } catch (error: any) {
19
- return {
20
- type: 'SKIP',
21
- reason: `Command failed: ${error?.message ?? 'Unknown'}`,
22
- };
23
- }
24
- };
@@ -1,25 +0,0 @@
1
- import { Mutation, Resolver, Arg, Ctx, Field, InputType } from 'type-graphql';
2
- import { type GraphQLContext, sendCommand, MutationResponse } from '../../../shared';
3
-
4
- @InputType()
5
- export class NotifyNewItemInput {
6
- @Field(() => String)
7
- itemId!: string;
8
- @Field(() => String)
9
- message!: string;
10
- }
11
-
12
- @Resolver()
13
- export class NotifyNewItemResolver {
14
- @Mutation(() => MutationResponse)
15
- async notifyNewItem(
16
- @Arg('input', () => NotifyNewItemInput) input: NotifyNewItemInput,
17
- @Ctx() ctx: GraphQLContext,
18
- ): Promise<MutationResponse> {
19
- return await sendCommand(ctx.messageBus, {
20
- type: 'NotifyNewItem',
21
- kind: 'Command',
22
- data: { ...input },
23
- });
24
- }
25
- }
@@ -1,7 +0,0 @@
1
- import type { CommandProcessor, EventStore } from '@event-driven-io/emmett';
2
- import { handle } from './handle';
3
- import type { NotifyNewItem } from './commands';
4
-
5
- export function register(messageBus: CommandProcessor, eventStore: EventStore) {
6
- messageBus.handle((command: NotifyNewItem) => handle(eventStore, command), 'NotifyNewItem');
7
- }
@@ -1,47 +0,0 @@
1
- /**
2
- * ## IMPLEMENTATION INSTRUCTIONS ##
3
- *
4
- * Define the shape of the domain state for the current slice below. This state is used by `decide.ts`
5
- * to determine whether a command is valid.
6
- *
7
- * The state is evolved over time by applying domain events (in `evolve.ts`).
8
- * Each event updates the state incrementally based on business rules.
9
- *
10
- * Guidelines:
11
- * - Include only fields that are **read** during command validation.
12
- * - Use discriminated unions (e.g., `status: 'Pending' | 'Done'`) to model state transitions.
13
- * - Prefer primitive types: `string`, `boolean`, `number`.
14
- * - Use objects or maps only when structure is essential for decision logic.
15
- *
16
- * Do NOT include:
17
- * - Redundant data already emitted in events unless required to enforce business rules.
18
- * - Fields used only for projections, UI, or query purposes.
19
- *
20
- * ### Example (for a Task domain):
21
- *
22
- * ```ts
23
- * export type PendingTask = {
24
- * status: 'Pending';
25
- * };
26
- *
27
- * export type InProgressTask = {
28
- * status: 'InProgress';
29
- * startedAt: string;
30
- * };
31
- *
32
- * export type CompletedTask = {
33
- * status: 'Completed';
34
- * completedAt: string;
35
- * };
36
- *
37
- * export type State = PendingTask | InProgressTask | CompletedTask;
38
- * ```
39
- */
40
-
41
- // TODO: Replace with a discriminated union of domain states for the current slice
42
- export type State = {};
43
-
44
- // TODO: Replace the Return with the initial domain state of the current slice
45
- export const initialState = (): State => {
46
- return {};
47
- };