@rayondigital/nest-dapr 0.10.3 → 0.10.5

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.
package/README.md CHANGED
@@ -5,23 +5,23 @@ Develop NestJs microservices using [Dapr](https://dapr.io/) pubsub, actors and b
5
5
 
6
6
  # Description
7
7
 
8
- Dapr Module for [Nest](https://github.com/nestjs/nest) built on top of the [Dapr JS SDK](https://github.com/dapr/js-sdk).
8
+ Dapr Module for [Nest](https://github.com/nestjs/nest) built on top of the latest [Dapr JS SDK](https://github.com/dapr/js-sdk).
9
9
 
10
10
 
11
11
  # Supported features
12
12
  - [x] [Actors](https://docs.dapr.io/developing-applications/building-blocks/actors/actors-overview/)
13
13
  - [x] [PubSub](https://docs.dapr.io/developing-applications/building-blocks/pubsub/pubsub-overview/)
14
14
  - [x] [Bindings](https://docs.dapr.io/developing-applications/building-blocks/bindings/bindings-overview/)
15
+ - [x] [Workflows](https://docs.dapr.io/developing-applications/building-blocks/workflow/workflow-overview/)
15
16
  - [ ] [Distributed Lock](https://docs.dapr.io/developing-applications/building-blocks/distributed-lock/)
16
17
  - [ ] [State](https://docs.dapr.io/developing-applications/building-blocks/state-management/state-management-overview/)
17
18
  - [ ] [Service Invocation](https://docs.dapr.io/developing-applications/building-blocks/service-invocation/service-invocation-overview/)
18
- - [ ] [Workflows](https://docs.dapr.io/developing-applications/building-blocks/workflow/workflow-overview/)
19
19
 
20
20
 
21
21
  # Installation
22
22
 
23
23
  ```bash
24
- npm i --save @rayondigital/nest-dapr
24
+ npm i @rayondigital/nest-dapr
25
25
  ```
26
26
 
27
27
  # Requirements
@@ -35,8 +35,8 @@ dapr --version
35
35
  Output:
36
36
 
37
37
  ```
38
- CLI version: 1.12.0
39
- Runtime version: 1.12.2
38
+ CLI version: 1.15.1
39
+ Runtime version: 1.15.4
40
40
  ```
41
41
 
42
42
  # Quick start
@@ -99,6 +99,7 @@ export class AppController {
99
99
  Create actors and connect them to your NestJS application using the `@DaprActor` decorator.
100
100
  This decorator takes in the interface of the actor, and marks the Actor as transient inside the NestJS
101
101
  dependency injection container.
102
+ Ensure your actor classes are added to the `providers` array of your NestJS module.
102
103
 
103
104
  ```typescript
104
105
  // You must expose your actors interface as an abstract class because Typescript interfaces are not available at runtime (erasure).
@@ -168,6 +169,112 @@ export class CounterController {
168
169
  }
169
170
  ```
170
171
 
172
+ ## Workflows
173
+
174
+ Workflows and Activities are annotated with the `@DaprWorkflow` and `@DaprActivity` decorators respectively.
175
+ When added to the `providers` array of a NestJS module, they are automatically registered with the Dapr server.
176
+
177
+ Note: Take care to ensure that your activities are stateless, and idempotent.
178
+ Be very careful with the state, and services you have inside your workflows.
179
+
180
+
181
+ ```typescript
182
+ @DaprActivity()
183
+ export class HelloActivity implements WorkflowActivity<string, string> {
184
+ async run(context: WorkflowActivityContext, name: string): Promise<string> {
185
+ return `Hello ${name}!`;
186
+ }
187
+ }
188
+
189
+ @DaprActivity()
190
+ export class CreateEntityActivity implements WorkflowActivity<string, Entity> {
191
+ @Inject()
192
+ private readonly entityService: EntityService;
193
+
194
+ constructor(private readonly cacheService: CacheService) {}
195
+
196
+ async run(context: WorkflowActivityContext, id: string): Promise<Entity> {
197
+ const entity: Entity = { id: id, createdAt: new Date(), lastUpdatedAt: new Date(), status: 'created', data: {} };
198
+ await this.entityService.update(entity);
199
+ console.log('entity', entity);
200
+ return entity;
201
+ }
202
+ }
203
+
204
+ @DaprActivity()
205
+ export class GetEntityActivity implements WorkflowActivity<string, Entity> {
206
+ @Inject()
207
+ private readonly entityService: EntityService;
208
+
209
+ constructor(private readonly cacheService: CacheService) {}
210
+
211
+ async run(context: WorkflowActivityContext, id: string): Promise<Entity> {
212
+ const entity = await this.entityService.get(id);
213
+ console.log('entity', entity);
214
+ return entity;
215
+ }
216
+ }
217
+
218
+ @DaprWorkflow()
219
+ export class HelloWorkflow implements Workflow<string[], string> {
220
+ async *run(ctx: WorkflowContext, input: string): AsyncGenerator<unknown, string[]> {
221
+ const cities: string[] = [];
222
+
223
+ let entity = expect<Entity>(yield ctx.callActivity(CreateEntityActivity, '12345'));
224
+ ctx.setCustomStatus('Entity');
225
+
226
+ entity = expect<Entity>(yield ctx.callActivity(GetEntityActivity, '12345'));
227
+ console.log('entity', entity);
228
+ ctx.setCustomStatus('Entity');
229
+
230
+ const result1 = expect<string>(yield ctx.callActivity(HelloActivity, 'Tokyo'));
231
+ ctx.setCustomStatus('Tokyo');
232
+
233
+ const event = yield ctx.waitForExternalEvent('next');
234
+ console.log('event', event);
235
+
236
+ const result2 = expect<string>(yield ctx.callActivity(HelloActivity, 'Seattle'));
237
+ ctx.setCustomStatus('Seattle');
238
+
239
+ const result3 = expect<string>(yield ctx.callActivity(HelloActivity, 'London'));
240
+ ctx.setCustomStatus('London');
241
+
242
+ return cities;
243
+ }
244
+ }
245
+ ```
246
+
247
+ ### Workflow Client
248
+
249
+ ```typescript
250
+ @Controller()
251
+ export class WorkflowController {
252
+ constructor(
253
+ private readonly workflowClient: DaprWorkflowClient,
254
+ ) {}
255
+
256
+ @Get(":id")
257
+ async start(@Param("id") uuid: string): Promise<string> {
258
+ const id = await workflowClient.scheduleNewWorkflow(HelloWorkflow, 'Hello', uuid);
259
+ // Workflow is started, and the id is returned.
260
+ // You can wait for the workflow to start and get the initial state.
261
+ const initialState = await workflowClient.waitForWorkflowStart(id, undefined, 15);
262
+
263
+ // You can raise events
264
+ // await workflowClient.raiseEvent(id, 'next', { input: 'next' });
265
+
266
+ // Optionally you can also wait for it to complete.
267
+ // const state = await workflowClient.waitForWorkflowCompletion(id, undefined, 15);
268
+ // Use the workflowOutput helper to get typed variables
269
+ // const value = workflowOutput(HelloWorkflow, state);
270
+ return {
271
+ id: id,
272
+ state: initialState
273
+ }
274
+ }
275
+ }
276
+ ```
277
+
171
278
  ## PubSub
172
279
 
173
280
  Create pubsub & topic names used for pubsub operations and message interface
@@ -96,6 +96,7 @@ let NestActorManager = NestActorManager_1 = class NestActorManager {
96
96
  const isLoggingEnabled = (_b = (_a = options === null || options === void 0 ? void 0 : options.logging) === null || _a === void 0 ? void 0 : _a.enabled) !== null && _b !== void 0 ? _b : true;
97
97
  const originalCallActor = ActorManager_1.default.prototype.callActorMethod;
98
98
  ActorManager_1.default.prototype.callActorMethod = function (actorId, methodName, data) {
99
+ var _a;
99
100
  return __awaiter(this, void 0, void 0, function* () {
100
101
  try {
101
102
  if (isLoggingEnabled) {
@@ -112,12 +113,12 @@ let NestActorManager = NestActorManager_1 = class NestActorManager {
112
113
  }
113
114
  else {
114
115
  return yield clsService.run(() => __awaiter(this, void 0, void 0, function* () {
115
- var _a;
116
+ var _b;
116
117
  contextService.setIdIfNotDefined();
117
118
  const context = NestActorManager_1.extractContext(data);
118
119
  if (context) {
119
120
  contextService.set(context);
120
- const correlationId = (_a = context[dapr_context_service_1.DAPR_CORRELATION_ID_KEY]) !== null && _a !== void 0 ? _a : (0, crypto_1.randomUUID)();
121
+ const correlationId = (_b = context[dapr_context_service_1.DAPR_CORRELATION_ID_KEY]) !== null && _b !== void 0 ? _b : (0, crypto_1.randomUUID)();
121
122
  if (correlationId) {
122
123
  contextService.setCorrelationId(correlationId);
123
124
  }
@@ -141,6 +142,10 @@ let NestActorManager = NestActorManager_1 = class NestActorManager {
141
142
  if (error.stack) {
142
143
  common_1.Logger.error(error.stack);
143
144
  }
145
+ if (serializable_error_1.SerializableError.isSerializableError(error)) {
146
+ error.statusCode = (_a = error.statusCode) !== null && _a !== void 0 ? _a : HttpStatusCode_enum_1.default.BAD_REQUEST;
147
+ return error;
148
+ }
144
149
  throw error;
145
150
  }
146
151
  });
package/package.json CHANGED
@@ -1,14 +1,14 @@
1
1
  {
2
2
  "name": "@rayondigital/nest-dapr",
3
- "version": "0.10.3",
4
- "description": "Develop NestJs microservices using Dapr pubsub, actors and other bindings",
3
+ "version": "0.10.5",
4
+ "description": "Develop NestJs microservices using Dapr pubsub, actors, workflows and other bindings",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
7
7
  "scripts": {
8
8
  "build": "rimraf -rf dist && tsc -p tsconfig.json",
9
9
  "lint": "eslint \"{lib,tests}/**/*.ts\" --fix",
10
10
  "test": "jest --runInBand",
11
- "test:in-memory": "dapr run --app-id testing --app-protocol http --app-port 3001 --dapr-http-port 3500 --resources-path ./tests/components npm run test",
11
+ "test:in-memory": "dapr run --app-id testing --app-protocol http --app-port 3001 --dapr-http-port 3500 --dapr-grpc-port 3501 --resources-path ./tests/components npm run test",
12
12
  "start:test": "nodemon tests/e2e/main.ts",
13
13
  "push:version": "git push --follow-tags"
14
14
  },