Skip to content

Commit ac16a6e

Browse files
authored
Merge pull request #526 from bitloops/feature-orchestrator
changes for orchestrator support
2 parents ed3dc01 + a087bff commit ac16a6e

File tree

9 files changed

+103
-16
lines changed

9 files changed

+103
-16
lines changed

boilerplate/ts/core/package-lock.json

+2-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

boilerplate/ts/core/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@bitloops/bl-boilerplate-core",
3-
"version": "1.0.0",
3+
"version": "1.1.4",
44
"description": "TypeScript boilerplate code for Bitloops Language generated projects",
55
"engines": {
66
"node": ">= 13"

boilerplate/ts/core/src/application/UseCase.ts

+42
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1+
import { Message } from '../domain/messages/IMessage.js';
2+
import { UUIDv4 } from '../domain/UUIDv4.js';
13
import { Either } from '../Either';
4+
import { asyncLocalStorage } from '../helpers/asyncLocalStorage.js';
25
import { ICoreError } from '../ICoreError';
36

47
/**
@@ -34,3 +37,42 @@ export interface QueryHandler<IRequest, IOkResponse> {
3437
get boundedContext(): string;
3538
execute(request?: IRequest): Promise<Either<IOkResponse, ICoreError>>;
3639
}
40+
41+
const CONTEXT = 'context';
42+
export abstract class OrchestratorHandler<IRequest, IOkResponse> {
43+
abstract get triggerMessage(): any;
44+
abstract get boundedContext(): string; // TODO check if we can add many
45+
abstract get domainEvents(): any[];
46+
abstract get systemEventNames(): string[];
47+
abstract get integrationEvents(): any[];
48+
abstract listen(message: Message): Promise<Either<IOkResponse, ICoreError>>;
49+
50+
get orchestratorNameId(): string {
51+
return this.constructor.name;
52+
}
53+
54+
protected isTriggerMessage(message: Message): boolean {
55+
return message.metadata.name === this.triggerMessage.name;
56+
}
57+
58+
async trigger(message: Message): Promise<void> {
59+
const orchestratorInstanceId = new UUIDv4().toString();
60+
const store = asyncLocalStorage.getStore();
61+
if (!store) {
62+
throw new Error('No store found, did you forget to attach correlation middleware?');
63+
}
64+
const ctx = store.get(CONTEXT);
65+
const ctxWithStorybookPort = {
66+
...ctx,
67+
orchestratorInstanceId,
68+
};
69+
store.set(CONTEXT, ctxWithStorybookPort);
70+
message.metadata.context.orchestratorInstanceId = orchestratorInstanceId;
71+
}
72+
73+
public getOrchestratorNameId() {
74+
return {
75+
orchestratorNameId: this.orchestratorNameId,
76+
};
77+
}
78+
}

boilerplate/ts/core/src/domain/commands/Command.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ export interface ICommand {
3030
export abstract class Command extends Message implements ICommand {
3131
[x: string]: any;
3232
public declare readonly metadata: CommandMetadata;
33-
constructor(boundedContextId: string, metadata?: Partial<CommandMetadata>) {
33+
constructor(boundedContextId: string, metadata: Partial<CommandMetadata> = {}) {
3434
super(metadata);
3535
this.metadata.boundedContextId = boundedContextId;
3636
}
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
export type TContext = {
22
jwt: string;
33
userId?: string;
4+
orchestratorInstanceId?: string;
45
};

boilerplate/ts/core/src/domain/messages/IMessage.ts

+9
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ export type TMessageMetadata = {
2828
createdTimestamp: number;
2929
messageId: string;
3030
correlationId?: string;
31+
orchestratorInstanceId?: string;
32+
name: string;
3133
context: TContext | Record<string, never>; // type of empty object
3234
};
3335

@@ -39,12 +41,19 @@ export abstract class Message implements IMessage {
3941
messageId: new UUIDv4().toString(),
4042
correlationId: metadata?.correlationId,
4143
context: metadata?.context || {},
44+
name: this.constructor.name,
45+
orchestratorInstanceId: metadata?.orchestratorInstanceId,
4246
};
4347
}
4448

4549
set correlationId(correlationId: string) {
4650
this.metadata.correlationId = correlationId;
4751
}
52+
53+
set orchestratorInstanceId(orchestratorInstanceId: string) {
54+
this.metadata.orchestratorInstanceId = orchestratorInstanceId;
55+
}
56+
4857
set context(context: TContext) {
4958
this.metadata.context = context;
5059
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { TEventMetadata } from '../events/IEvent';
2+
import { Message } from './IMessage';
3+
4+
export type SystemEventProps<T> = {
5+
boundedContextId: string;
6+
name: string; // TODO or commandHandlerName
7+
result: T;
8+
metadata?: Partial<TEventMetadata>;
9+
};
10+
11+
export class SystemEvent<T> extends Message {
12+
readonly name: string;
13+
readonly result: T;
14+
declare metadata: TEventMetadata;
15+
constructor({ boundedContextId, name, result, metadata }: SystemEventProps<T>) {
16+
super(metadata);
17+
this.metadata.boundedContextId = boundedContextId;
18+
this.name = name;
19+
this.result = result;
20+
}
21+
}

boilerplate/ts/core/src/index.ts

+15-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,12 @@
22
import 'reflect-metadata';
33
import { AppError } from './application/AppError';
44
import { CRUDReadRepoPort, CRUDWriteRepoPort, UpdateOptions } from './application/ICRUDRepoPort';
5-
import { CommandHandler, UseCase, QueryHandler } from './application/UseCase';
5+
import {
6+
CommandHandler,
7+
UseCase,
8+
QueryHandler,
9+
OrchestratorHandler as OrchestratorHandlerImport,
10+
} from './application/UseCase';
611
import { AggregateRoot } from './domain/AggregateRoot';
712
import { applyRules as applyRulesImport } from './domain/applyRule';
813
import {
@@ -57,6 +62,8 @@ import { ReturnUnexpectedError as ReturnUnexpectedErrorImport } from './errors/r
5762
import { TEventMetadata } from './domain/events/IEvent';
5863
import { asyncLocalStorage, AsyncLocalStorageStore } from './helpers/asyncLocalStorage';
5964
import { ConcurrencyOrNotFoundError } from './errors/repository/ConcurrencyOrNotFoundError';
65+
import { Message as MessageImport } from './domain/messages/IMessage';
66+
import { SystemEvent as SystemEventImport } from './domain/messages/SystemEvent';
6067

6168
namespace Domain {
6269
export class Error extends DomainError {}
@@ -86,6 +93,10 @@ namespace Application {
8693
export type ICommandHandler<IRequest, IResponse> = CommandHandler<IRequest, IResponse>;
8794
export type IQueryHandler<IRequest, IResponse> = QueryHandler<IRequest, IResponse>;
8895
export type IHandleDomainEvent = IHandleImport;
96+
export abstract class OrchestratorHandler<IRequest, IResponse> extends OrchestratorHandlerImport<
97+
IRequest,
98+
IResponse
99+
> {}
89100
export interface IHandleIntegrationEvent extends IHandleImport {
90101
version: string;
91102
}
@@ -122,6 +133,9 @@ namespace Infra {
122133
export abstract class IntegrationEvent<T> extends IntegrationEventImport<T> {}
123134
export type IEventBus = IEventBusImport;
124135
export type IEvent<T> = IEventImport<T>;
136+
export type Message = MessageImport;
137+
export class SystemEvent<T> extends SystemEventImport<T> {}
138+
export type IHandle = IHandleImport;
125139
}
126140
export namespace CommandBus {
127141
export type IPubSubCommandBus = IPubSubCommandBusImport;

boilerplate/ts/core/yarn.lock

+11-11
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@
6969
"@nodelib/fs.stat" "2.0.5"
7070
run-parallel "^1.1.9"
7171

72-
"@nodelib/[email protected].5", "@nodelib/fs.stat@^2.0.2":
72+
"@nodelib/fs.stat@^2.0.2", "@nodelib/[email protected].5":
7373
version "2.0.5"
7474
resolved "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz"
7575
integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==
@@ -107,7 +107,7 @@
107107
resolved "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz"
108108
integrity sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==
109109

110-
"@types/node@^18.15.11":
110+
"@types/node@*", "@types/node@^18.15.11":
111111
version "18.15.11"
112112
resolved "https://registry.npmjs.org/@types/node/-/node-18.15.11.tgz"
113113
integrity sha512-E5Kwq2n4SbMzQOn6wnmBjuK9ouqlURrcZDVfbo9ftDDTFt3nk7ZKK4GMOzoYgnpQJKcxwQw+lGaBvvlMo0qN/Q==
@@ -133,7 +133,7 @@
133133
semver "^7.3.7"
134134
tsutils "^3.21.0"
135135

136-
"@typescript-eslint/parser@^5.40.0":
136+
"@typescript-eslint/parser@^5.0.0", "@typescript-eslint/parser@^5.40.0":
137137
version "5.51.0"
138138
resolved "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.51.0.tgz"
139139
integrity sha512-fEV0R9gGmfpDeRzJXn+fGQKcl0inIeYobmmUWijZh9zA7bxJ8clPhV9up2ZQzATxAiFAECqPQyMDB4o4B81AaA==
@@ -211,16 +211,16 @@ acorn-walk@^8.1.1:
211211
resolved "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz"
212212
integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==
213213

214+
"acorn@^6.0.0 || ^7.0.0 || ^8.0.0", acorn@^8.8.0:
215+
version "8.8.0"
216+
resolved "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz"
217+
integrity sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==
218+
214219
acorn@^8.4.1:
215220
version "8.8.1"
216221
resolved "https://registry.npmjs.org/acorn/-/acorn-8.8.1.tgz"
217222
integrity sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA==
218223

219-
acorn@^8.8.0:
220-
version "8.8.0"
221-
resolved "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz"
222-
integrity sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==
223-
224224
ajv@^6.10.0, ajv@^6.12.4:
225225
version "6.12.6"
226226
resolved "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz"
@@ -408,7 +408,7 @@ eslint-visitor-keys@^3.3.0:
408408
resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz"
409409
integrity sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==
410410

411-
eslint@^8.25.0:
411+
eslint@*, "eslint@^6.0.0 || ^7.0.0 || ^8.0.0", eslint@^8.25.0, eslint@>=5, eslint@>=7.0.0, eslint@>=7.28.0:
412412
version "8.33.0"
413413
resolved "https://registry.npmjs.org/eslint/-/eslint-8.33.0.tgz"
414414
integrity sha512-WjOpFQgKK8VrCnAtl8We0SUOy/oVZ5NHykyMiagV1M9r8IFpIJX7DduK6n1mpfhlG7T1NLWm2SuD8QB7KFySaA==
@@ -863,7 +863,7 @@ prettier-linter-helpers@^1.0.0:
863863
dependencies:
864864
fast-diff "^1.1.2"
865865

866-
prettier@^2.7.1:
866+
prettier@^2.7.1, prettier@>=2.0.0:
867867
version "2.8.3"
868868
resolved "https://registry.npmjs.org/prettier/-/prettier-2.8.3.tgz"
869869
integrity sha512-tJ/oJ4amDihPoufT5sM0Z1SKEuKay8LfVAMlbbhnnkvt6BUserZylqo2PN+p9KeljLr0OHa2rXHU1T8reeoTrw==
@@ -1015,7 +1015,7 @@ type-fest@^0.20.2:
10151015
resolved "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz"
10161016
integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==
10171017

1018-
typescript@^4.8.4:
1018+
typescript@^4.8.4, typescript@>=2.7, "typescript@>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta":
10191019
version "4.9.5"
10201020
resolved "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz"
10211021
integrity sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==

0 commit comments

Comments
 (0)