@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 +112 -5
- package/dist/actors/nest-actor-manager.js +7 -2
- package/package.json +3 -3
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
|
|
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.
|
|
39
|
-
Runtime version: 1.
|
|
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
|
|
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 = (
|
|
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.
|
|
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
|
},
|