@fluojs/microservices 1.0.0-beta.1
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/LICENSE +21 -0
- package/README.ko.md +182 -0
- package/README.md +179 -0
- package/dist/decorators.d.ts +51 -0
- package/dist/decorators.d.ts.map +1 -0
- package/dist/decorators.js +106 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +13 -0
- package/dist/metadata.d.ts +9 -0
- package/dist/metadata.d.ts.map +1 -0
- package/dist/metadata.js +48 -0
- package/dist/module.d.ts +23 -0
- package/dist/module.d.ts.map +1 -0
- package/dist/module.js +55 -0
- package/dist/service.d.ts +116 -0
- package/dist/service.d.ts.map +1 -0
- package/dist/service.js +550 -0
- package/dist/status.d.ts +30 -0
- package/dist/status.d.ts.map +1 -0
- package/dist/status.js +79 -0
- package/dist/tokens.d.ts +7 -0
- package/dist/tokens.d.ts.map +1 -0
- package/dist/tokens.js +4 -0
- package/dist/transports/event-handler-logger.d.ts +3 -0
- package/dist/transports/event-handler-logger.d.ts.map +1 -0
- package/dist/transports/event-handler-logger.js +3 -0
- package/dist/transports/grpc-transport.d.ts +193 -0
- package/dist/transports/grpc-transport.d.ts.map +1 -0
- package/dist/transports/grpc-transport.js +1035 -0
- package/dist/transports/kafka-transport.d.ts +77 -0
- package/dist/transports/kafka-transport.d.ts.map +1 -0
- package/dist/transports/kafka-transport.js +289 -0
- package/dist/transports/mqtt-transport.d.ts +124 -0
- package/dist/transports/mqtt-transport.d.ts.map +1 -0
- package/dist/transports/mqtt-transport.js +460 -0
- package/dist/transports/nats-transport.d.ts +92 -0
- package/dist/transports/nats-transport.d.ts.map +1 -0
- package/dist/transports/nats-transport.js +218 -0
- package/dist/transports/rabbitmq-transport.d.ts +77 -0
- package/dist/transports/rabbitmq-transport.d.ts.map +1 -0
- package/dist/transports/rabbitmq-transport.js +263 -0
- package/dist/transports/redis-streams-transport.d.ts +136 -0
- package/dist/transports/redis-streams-transport.d.ts.map +1 -0
- package/dist/transports/redis-streams-transport.js +482 -0
- package/dist/transports/redis-transport.d.ts +73 -0
- package/dist/transports/redis-transport.d.ts.map +1 -0
- package/dist/transports/redis-transport.js +152 -0
- package/dist/transports/tcp-transport.d.ts +66 -0
- package/dist/transports/tcp-transport.d.ts.map +1 -0
- package/dist/transports/tcp-transport.js +283 -0
- package/dist/types.d.ts +105 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +1 -0
- package/package.json +105 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 fluo contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.ko.md
ADDED
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
# @fluojs/microservices
|
|
2
|
+
|
|
3
|
+
<p><a href="./README.md"><kbd>English</kbd></a> <strong><kbd>한국어</kbd></strong></p>
|
|
4
|
+
|
|
5
|
+
fluo용 트랜스포트 기반 마이크로서비스 패키지입니다. TCP, Redis, NATS, Kafka, RabbitMQ, MQTT, gRPC 같은 여러 프로토콜 위에서 동일한 데코레이터 기반 프로그래밍 모델을 제공합니다.
|
|
6
|
+
|
|
7
|
+
## 목차
|
|
8
|
+
|
|
9
|
+
- [설치](#설치)
|
|
10
|
+
- [사용 시점](#사용-시점)
|
|
11
|
+
- [빠른 시작](#빠른-시작)
|
|
12
|
+
- [주요 기능](#주요-기능)
|
|
13
|
+
- [공통 패턴](#공통-패턴)
|
|
14
|
+
- [공개 API 개요](#공개-api-개요)
|
|
15
|
+
- [관련 패키지](#관련-패키지)
|
|
16
|
+
- [예제 소스](#예제-소스)
|
|
17
|
+
|
|
18
|
+
## 설치
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
pnpm add @fluojs/microservices
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
선택적 트랜스포트 의존성:
|
|
25
|
+
|
|
26
|
+
- `@fluojs/microservices`가 직접 로드하는 선택적 peer: `@grpc/grpc-js`, `@grpc/proto-loader`, `ioredis`, `mqtt`
|
|
27
|
+
- 애플리케이션이 transport에 명시적으로 넘겨야 하는 caller-owned broker client: `nats`, `kafkajs`, `amqplib`
|
|
28
|
+
|
|
29
|
+
## 사용 시점
|
|
30
|
+
|
|
31
|
+
- 서비스 간 통신을 메시지나 이벤트 중심으로 분리하고 싶을 때
|
|
32
|
+
- TCP, NATS, Kafka 같은 여러 트랜스포트 위에서 같은 핸들러 모델을 유지하고 싶을 때
|
|
33
|
+
- 요청-응답과 이벤트 fan-out을 같은 프레임워크 규약으로 다루고 싶을 때
|
|
34
|
+
- gRPC 스트리밍을 포함한 복수의 마이크로서비스 프로토콜을 fluo DI와 함께 사용하고 싶을 때
|
|
35
|
+
|
|
36
|
+
## 빠른 시작
|
|
37
|
+
|
|
38
|
+
```ts
|
|
39
|
+
import { MessagePattern, MicroservicesModule, TcpMicroserviceTransport } from '@fluojs/microservices';
|
|
40
|
+
import { Module } from '@fluojs/core';
|
|
41
|
+
import { fluoFactory } from '@fluojs/runtime';
|
|
42
|
+
|
|
43
|
+
class MathHandler {
|
|
44
|
+
@MessagePattern('math.sum')
|
|
45
|
+
sum(data: { a: number; b: number }) {
|
|
46
|
+
return data.a + data.b;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
@Module({
|
|
51
|
+
imports: [
|
|
52
|
+
MicroservicesModule.forRoot({
|
|
53
|
+
transport: new TcpMicroserviceTransport({ port: 4000 }),
|
|
54
|
+
}),
|
|
55
|
+
],
|
|
56
|
+
providers: [MathHandler],
|
|
57
|
+
})
|
|
58
|
+
class AppModule {}
|
|
59
|
+
|
|
60
|
+
const microservice = await fluoFactory.createMicroservice(AppModule);
|
|
61
|
+
await microservice.listen();
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
`fluo new`는 NATS, Kafka, RabbitMQ를 숨겨진 내장 구현이 아니라 caller-owned bootstrap contract로 취급합니다. 생성된 스타터는 `src/app.ts`에서 `nats` + `JSONCodec()`, `kafkajs` producer/consumer collaborator, `amqplib` publisher/consumer collaborator를 직접 연결하고, 외부 broker 의존성은 `.env`와 생성된 README에 그대로 드러냅니다. 이 패키지 자체가 해당 런타임을 직접 로드하지 않으므로 `@fluojs/microservices`의 peer dependency로도 선언하지 않습니다.
|
|
65
|
+
|
|
66
|
+
## 주요 기능
|
|
67
|
+
|
|
68
|
+
### 다중 트랜스포트 지원
|
|
69
|
+
|
|
70
|
+
비즈니스 핸들러는 그대로 두고 TCP, Redis Pub/Sub, Redis Streams, NATS, Kafka, RabbitMQ, MQTT, gRPC 같은 트랜스포트만 바꿔 배치할 수 있습니다.
|
|
71
|
+
|
|
72
|
+
### 패턴 기반 라우팅
|
|
73
|
+
|
|
74
|
+
`@MessagePattern`은 요청-응답 흐름에, `@EventPattern`은 fire-and-forget 이벤트에 사용합니다. 문자열과 정규식 패턴 모두 지원합니다.
|
|
75
|
+
|
|
76
|
+
### gRPC 스트리밍
|
|
77
|
+
|
|
78
|
+
`@ServerStreamPattern`, `@ClientStreamPattern`, `@BidiStreamPattern`으로 unary 외의 스트리밍 패턴도 다룰 수 있습니다.
|
|
79
|
+
|
|
80
|
+
### 요청 단위 DI scope
|
|
81
|
+
|
|
82
|
+
마이크로서비스 핸들러도 fluo의 request/transient scope 모델을 그대로 따르므로, 메시지 또는 이벤트 단위로 격리된 상태를 안전하게 사용할 수 있습니다.
|
|
83
|
+
|
|
84
|
+
### 전달 안전 기본값
|
|
85
|
+
|
|
86
|
+
- TCP 프레임은 기본적으로 newline-delimited 메시지당 1 MiB로 제한되며, 한도를 넘는 프레임은 요청 버퍼를 무한히 키우는 대신 소켓을 종료합니다.
|
|
87
|
+
- Redis Streams는 요청/이벤트 엔트리를 핸들러 처리가 끝난 뒤에만 ACK합니다. 실패한 이벤트는 조기 ACK로 유실하지 않고 broker 복구/재전달 경로에 남겨 둡니다.
|
|
88
|
+
- Redis Streams는 기본적으로 live request/event stream에 publish-time trimming을 적용하지 않으므로, pending 엔트리가 `xack` 또는 consumer-group 복구 경로가 끝나기 전에 잘리지 않습니다. ACK가 끝난 request/reply 엔트리는 정리되고, 인스턴스별 response stream은 기본적으로 bounded retention(`responseRetentionMaxLen: 1_000`)을 유지한 뒤 `close()` 중 삭제됩니다.
|
|
89
|
+
- Redis Streams는 `close()` 중 인스턴스별 response stream은 항상 삭제하지만, 활성 fleet 전체에서 ownership를 증명할 수 없으면 공유 request consumer group은 보수적으로 유지합니다. lease-capable listener는 coordination metadata만 정리하고, mixed/fallback fleet에서는 살아 있는 다른 listener가 여전히 필요로 할 수 있으므로 공유 request group을 제거하지 않습니다.
|
|
90
|
+
- `messageRetentionMaxLen`과 `eventRetentionMaxLen`은 고급 opt-in 설정으로 남아 있습니다. 이를 켜면 Redis가 ACK 전 pending live-stream 엔트리를 먼저 trim할 수 있으므로 broker-managed recovery 보장을 일부 포기하는 운영 판단이 됩니다.
|
|
91
|
+
- RabbitMQ 요청-응답은 기본적으로 인스턴스별 response queue를 사용합니다. 공유 reply topology를 의도적으로 운영할 때만 `responseQueue`를 명시적으로 지정하세요.
|
|
92
|
+
- transport logger를 통해 이벤트 핸들러 실패를 기록하는 경로(`RedisPubSubMicroserviceTransport`, `RedisStreamsMicroserviceTransport`, `NatsMicroserviceTransport`, `MqttMicroserviceTransport`, gRPC event emit)는 끝까지 logger-driven observability를 유지합니다. transport logger를 주입하지 않으면 fluo는 해당 실패를 raw `console.error` fallback으로 복제하지 않습니다.
|
|
93
|
+
|
|
94
|
+
## 공통 패턴
|
|
95
|
+
|
|
96
|
+
### 커스텀 모듈 등록
|
|
97
|
+
|
|
98
|
+
custom provider/export/non-global 구성이 필요할 때도 raw provider array로 내려가지 말고 `MicroservicesModule.forRoot({ transport, module: { ... } })`를 우선 사용하세요.
|
|
99
|
+
|
|
100
|
+
```ts
|
|
101
|
+
import { Module } from '@fluojs/core';
|
|
102
|
+
import { MicroservicesModule } from '@fluojs/microservices';
|
|
103
|
+
|
|
104
|
+
const EXTRA_MICROSERVICE_EXPORT = Symbol('extra-microservice-export');
|
|
105
|
+
|
|
106
|
+
@Module({
|
|
107
|
+
imports: [
|
|
108
|
+
MicroservicesModule.forRoot({
|
|
109
|
+
transport: customTransport,
|
|
110
|
+
module: {
|
|
111
|
+
global: false,
|
|
112
|
+
providers: [{ provide: EXTRA_MICROSERVICE_EXPORT, useValue: 'custom-module-value' }],
|
|
113
|
+
additionalExports: [EXTRA_MICROSERVICE_EXPORT],
|
|
114
|
+
},
|
|
115
|
+
}),
|
|
116
|
+
],
|
|
117
|
+
})
|
|
118
|
+
class FeatureModule {}
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
Behavioral contract notes:
|
|
122
|
+
|
|
123
|
+
- 이 모듈 경로는 기본 `MicroservicesModule.forRoot(...)` 호출과 동일한 `MICROSERVICE_OPTIONS`, `MicroserviceLifecycleService`, `MICROSERVICE` wiring을 그대로 설치합니다.
|
|
124
|
+
- `module.providers`는 내장 런타임 wiring 뒤에 추가 provider를 붙이고, `module.additionalExports`는 기본 export 토큰을 교체하지 않고 확장합니다.
|
|
125
|
+
- `module.global`을 사용하면 등록 범위를 로컬로 제한할 수 있습니다.
|
|
126
|
+
|
|
127
|
+
### provider 배열 헬퍼
|
|
128
|
+
|
|
129
|
+
`createMicroservicesProviders(...)`는 실제로 low-level provider array 자체가 필요한 호출자에게만 남아 있습니다.
|
|
130
|
+
|
|
131
|
+
`createMicroservicesProviders(...)`는 커스텀 모듈 조합에 provider 배열이 필요할 때 사용할 수 있습니다.
|
|
132
|
+
|
|
133
|
+
`createMicroservicesProviders(...)`는 실제로 low-level provider array 자체가 필요한 호출자에게만 남아 있습니다.
|
|
134
|
+
|
|
135
|
+
```ts
|
|
136
|
+
import { Module } from '@fluojs/core';
|
|
137
|
+
import { createMicroservicesProviders } from '@fluojs/microservices';
|
|
138
|
+
|
|
139
|
+
@Module({
|
|
140
|
+
providers: [...createMicroservicesProviders({ transport: customTransport })],
|
|
141
|
+
})
|
|
142
|
+
class ManualMicroserviceProvidersModule {}
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
## 공개 API 개요
|
|
146
|
+
|
|
147
|
+
### 루트 배럴 (`@fluojs/microservices`)
|
|
148
|
+
|
|
149
|
+
- `MicroservicesModule`, `createMicroservicesProviders`: 모듈 등록 진입점입니다.
|
|
150
|
+
- `MicroservicesModule.forRoot(...)`: `module: { global, providers, additionalExports }`와 함께 트랜스포트와 모듈 구성을 설정합니다.
|
|
151
|
+
- `createMicroservicesProviders(...)`: 커스텀 모듈 조합용 provider 배열을 생성합니다.
|
|
152
|
+
- `MessagePattern`, `EventPattern`, `ServerStreamPattern`, `ClientStreamPattern`, `BidiStreamPattern`: 라우팅/스트리밍 데코레이터입니다.
|
|
153
|
+
- `TcpMicroserviceTransport`, `RedisPubSubMicroserviceTransport`, `RedisStreamsMicroserviceTransport`, `NatsMicroserviceTransport`, `KafkaMicroserviceTransport`, `RabbitMqMicroserviceTransport`, `GrpcMicroserviceTransport`, `MqttMicroserviceTransport`: 루트 배럴에서 제공하는 트랜스포트 어댑터입니다.
|
|
154
|
+
- `MicroserviceLifecycleService`, `MICROSERVICE`: 런타임 접근용 서비스와 토큰입니다.
|
|
155
|
+
- `createMicroservicePlatformStatusSnapshot`, `ServerStreamWriter`: 상태 스냅샷/TypeScript 계약 헬퍼입니다.
|
|
156
|
+
|
|
157
|
+
### 지원되는 트랜스포트 서브패스
|
|
158
|
+
|
|
159
|
+
- `@fluojs/microservices/tcp`
|
|
160
|
+
- `@fluojs/microservices/redis` (Redis Pub/Sub 트랜스포트)
|
|
161
|
+
- `@fluojs/microservices/nats`
|
|
162
|
+
- `@fluojs/microservices/kafka`
|
|
163
|
+
- `@fluojs/microservices/rabbitmq`
|
|
164
|
+
- `@fluojs/microservices/grpc`
|
|
165
|
+
- `@fluojs/microservices/mqtt`
|
|
166
|
+
|
|
167
|
+
`RedisStreamsMicroserviceTransport`는 현재 루트 배럴에서만 지원하며, `@fluojs/microservices/redis-streams` 전용 export는 없습니다.
|
|
168
|
+
|
|
169
|
+
## 관련 패키지
|
|
170
|
+
|
|
171
|
+
- `@fluojs/core`: 모듈과 DI 메타데이터의 기반 패키지입니다.
|
|
172
|
+
- `@fluojs/runtime`: 마이크로서비스 부트스트랩과 팩토리 API를 제공합니다.
|
|
173
|
+
- `@fluojs/di`: 핸들러와 provider를 resolve하는 DI 엔진입니다.
|
|
174
|
+
|
|
175
|
+
## 예제 소스
|
|
176
|
+
|
|
177
|
+
- `packages/microservices/src/module.test.ts`: 모든 트랜스포트 통합 계약을 검증합니다.
|
|
178
|
+
- `packages/microservices/src/public-api.test.ts`: 모듈 등록 override와 `createMicroservicesProviders(...)`를 포함한 루트 배럴 export 계약을 검증합니다.
|
|
179
|
+
- `packages/microservices/src/public-surface.test.ts`: 문서화된 공개 surface를 검증합니다.
|
|
180
|
+
- `packages/microservices/src/public-subpaths.test.ts`: 문서화된 트랜스포트 서브패스 export map 계약을 검증합니다.
|
|
181
|
+
- `examples/microservices-tcp`: 기본 TCP 마이크로서비스 예제입니다.
|
|
182
|
+
- `examples/microservices-kafka`: Kafka 기반 분산 아키텍처 예제입니다.
|
package/README.md
ADDED
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
# @fluojs/microservices
|
|
2
|
+
|
|
3
|
+
<p><strong><kbd>English</kbd></strong> <a href="./README.ko.md"><kbd>한국어</kbd></a></p>
|
|
4
|
+
|
|
5
|
+
Transport-driven microservices for fluo. Build scalable, message-driven architectures with deep DI integration and support for multiple transport protocols including TCP, Redis, NATS, Kafka, RabbitMQ, and gRPC.
|
|
6
|
+
|
|
7
|
+
## Table of Contents
|
|
8
|
+
|
|
9
|
+
- [Installation](#installation)
|
|
10
|
+
- [When to Use](#when-to-use)
|
|
11
|
+
- [Quick Start](#quick-start)
|
|
12
|
+
- [Core Capabilities](#core-capabilities)
|
|
13
|
+
- [Common Patterns](#common-patterns)
|
|
14
|
+
- [Public API Overview](#public-api-overview)
|
|
15
|
+
- [Related Packages](#related-packages)
|
|
16
|
+
- [Example Sources](#example-sources)
|
|
17
|
+
|
|
18
|
+
## Installation
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
pnpm add @fluojs/microservices
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Optional transport-specific dependencies:
|
|
25
|
+
|
|
26
|
+
- Package-managed optional peers loaded by `@fluojs/microservices`: `@grpc/grpc-js`, `@grpc/proto-loader`, `ioredis`, `mqtt`
|
|
27
|
+
- Caller-owned broker clients passed explicitly to transports: `nats`, `kafkajs`, `amqplib`
|
|
28
|
+
|
|
29
|
+
## When to Use
|
|
30
|
+
|
|
31
|
+
- When building a **Distributed System** where services communicate via messages or events.
|
|
32
|
+
- When you need a **Unified Programming Model** across different transport protocols (TCP, NATS, Kafka, etc.).
|
|
33
|
+
- When you require **Request-Response** or **Event-Driven** patterns between isolated services.
|
|
34
|
+
- When integrating with specialized protocols like **gRPC** (including streaming support).
|
|
35
|
+
|
|
36
|
+
## Quick Start
|
|
37
|
+
|
|
38
|
+
Define a message handler and bootstrap the microservice using the TCP transport.
|
|
39
|
+
|
|
40
|
+
```typescript
|
|
41
|
+
import { Module } from '@fluojs/core';
|
|
42
|
+
import { fluoFactory } from '@fluojs/runtime';
|
|
43
|
+
import { MicroservicesModule, MessagePattern, TcpMicroserviceTransport } from '@fluojs/microservices';
|
|
44
|
+
|
|
45
|
+
class MathHandler {
|
|
46
|
+
@MessagePattern('math.sum')
|
|
47
|
+
sum(data: { a: number; b: number }) {
|
|
48
|
+
return data.a + data.b;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
@Module({
|
|
53
|
+
imports: [
|
|
54
|
+
MicroservicesModule.forRoot({
|
|
55
|
+
transport: new TcpMicroserviceTransport({ port: 4000 })
|
|
56
|
+
})
|
|
57
|
+
],
|
|
58
|
+
providers: [MathHandler]
|
|
59
|
+
})
|
|
60
|
+
class AppModule {}
|
|
61
|
+
|
|
62
|
+
const microservice = await fluoFactory.createMicroservice(AppModule);
|
|
63
|
+
await microservice.listen();
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
`fluo new` treats NATS, Kafka, and RabbitMQ as explicit caller-owned bootstrap contracts rather than hidden built-ins. The generated starters wire `nats` + `JSONCodec()`, `kafkajs` producer/consumer collaborators, and `amqplib` publisher/consumer collaborators in `src/app.ts`, while still making the external broker dependency visible through `.env` and the generated README. Those packages are not loaded from `@fluojs/microservices` itself and therefore are not declared as package peers here.
|
|
67
|
+
|
|
68
|
+
## Core Capabilities
|
|
69
|
+
|
|
70
|
+
### Multi-Transport Support
|
|
71
|
+
Write your business logic once and deploy it across various transports. Supports TCP, Redis (Pub/Sub and Streams), NATS, Kafka, RabbitMQ, MQTT, and gRPC.
|
|
72
|
+
|
|
73
|
+
### Pattern-Based Routing
|
|
74
|
+
Use `@MessagePattern` for request-response flows and `@EventPattern` for fire-and-forget event broadcasting. Patterns support string matching and regular expressions.
|
|
75
|
+
|
|
76
|
+
### Advanced gRPC Streaming
|
|
77
|
+
First-party support for all gRPC streaming modes: Server-side, Client-side, and Bidirectional streaming using `@ServerStreamPattern`, `@ClientStreamPattern`, and `@BidiStreamPattern`.
|
|
78
|
+
|
|
79
|
+
### Request-Scoped DI
|
|
80
|
+
Microservice handlers fully support fluo's DI scopes. Request-scoped providers are isolated per message or per event, ensuring safe state management in concurrent processing.
|
|
81
|
+
|
|
82
|
+
### Delivery Safety Defaults
|
|
83
|
+
- TCP frames are bounded to 1 MiB per newline-delimited message by default; oversized frames close the socket instead of growing the request buffer without limit.
|
|
84
|
+
- Redis Streams acknowledges request/event entries only after handler-side processing finishes. Failed events stay pending for broker-managed recovery instead of being acknowledged early.
|
|
85
|
+
- Redis Streams does not apply publish-time trimming to live request/event streams by default, so pending entries remain recoverable until `xack` or consumer-group recovery completes. Acked request/reply entries are cleaned up, each per-consumer response stream keeps bounded retention by default (`responseRetentionMaxLen: 1_000`), and each response stream is deleted during `close()`.
|
|
86
|
+
- Redis Streams always deletes each per-consumer response stream during `close()`, but it retains the shared request consumer group conservatively once ownership cannot be proven across the active fleet. Lease-capable listeners clean up only their coordination metadata, and mixed or fallback listener fleets keep the shared request group in place so one peer cannot destroy a group that another live listener still needs.
|
|
87
|
+
- `messageRetentionMaxLen` and `eventRetentionMaxLen` remain available as advanced opt-in knobs. Enabling them can trade away broker-managed recovery guarantees because Redis may trim pending live-stream entries before they are acknowledged.
|
|
88
|
+
- RabbitMQ request/reply uses an instance-scoped response queue by default. Pass `responseQueue` explicitly only when you intentionally own and coordinate a shared reply topology.
|
|
89
|
+
- Event-handler failures that flow through the transport logger (`RedisPubSubMicroserviceTransport`, `RedisStreamsMicroserviceTransport`, `NatsMicroserviceTransport`, `MqttMicroserviceTransport`, and gRPC event emits) remain logger-driven. If you do not inject a transport logger, fluo does not mirror those failures through a raw `console.error` fallback.
|
|
90
|
+
|
|
91
|
+
## Common Patterns
|
|
92
|
+
|
|
93
|
+
### Custom module registration
|
|
94
|
+
|
|
95
|
+
Use `MicroservicesModule.forRoot({ transport, module: { ... } })` when you want custom providers, exports, or non-global registration without dropping back to raw provider arrays.
|
|
96
|
+
|
|
97
|
+
```typescript
|
|
98
|
+
import { Module } from '@fluojs/core';
|
|
99
|
+
import { MicroservicesModule, MicroserviceLifecycleService, MICROSERVICE } from '@fluojs/microservices';
|
|
100
|
+
|
|
101
|
+
const EXTRA_MICROSERVICE_EXPORT = Symbol('extra-microservice-export');
|
|
102
|
+
|
|
103
|
+
@Module({
|
|
104
|
+
imports: [
|
|
105
|
+
MicroservicesModule.forRoot({
|
|
106
|
+
transport: customTransport,
|
|
107
|
+
module: {
|
|
108
|
+
global: false,
|
|
109
|
+
providers: [{ provide: EXTRA_MICROSERVICE_EXPORT, useValue: 'custom-module-value' }],
|
|
110
|
+
additionalExports: [EXTRA_MICROSERVICE_EXPORT],
|
|
111
|
+
},
|
|
112
|
+
}),
|
|
113
|
+
],
|
|
114
|
+
})
|
|
115
|
+
class FeatureModule {}
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Behavioral contract notes:
|
|
119
|
+
|
|
120
|
+
- The module path still installs the same built-in `MICROSERVICE_OPTIONS`, `MicroserviceLifecycleService`, and `MICROSERVICE` wiring as the default `MicroservicesModule.forRoot(...)` call.
|
|
121
|
+
- `module.providers` appends extra providers after the built-in runtime wiring, while `module.additionalExports` extends the default exported tokens instead of replacing them.
|
|
122
|
+
- `module.global` lets advanced callers keep the registration local.
|
|
123
|
+
|
|
124
|
+
### Provider-array helper
|
|
125
|
+
|
|
126
|
+
`createMicroservicesProviders(...)` remains available only for callers that truly need the low-level provider array itself.
|
|
127
|
+
|
|
128
|
+
Use `createMicroservicesProviders(...)` when you need a provider array for custom module assembly.
|
|
129
|
+
|
|
130
|
+
`createMicroservicesProviders(...)` remains available only for callers that truly need the low-level provider array itself.
|
|
131
|
+
|
|
132
|
+
```typescript
|
|
133
|
+
import { Module } from '@fluojs/core';
|
|
134
|
+
import { createMicroservicesProviders } from '@fluojs/microservices';
|
|
135
|
+
|
|
136
|
+
@Module({
|
|
137
|
+
providers: [...createMicroservicesProviders({ transport: customTransport })],
|
|
138
|
+
})
|
|
139
|
+
class ManualMicroserviceProvidersModule {}
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
## Public API Overview
|
|
143
|
+
|
|
144
|
+
### Root barrel (`@fluojs/microservices`)
|
|
145
|
+
|
|
146
|
+
- `MicroservicesModule`, `createMicroservicesProviders`: module registration helpers.
|
|
147
|
+
- `MicroservicesModule.forRoot(...)`: Configures a transport plus optional module customization via `module: { global, providers, additionalExports }`.
|
|
148
|
+
- `createMicroservicesProviders(...)`: Builds provider arrays for custom module assembly.
|
|
149
|
+
- `MessagePattern`, `EventPattern`, `ServerStreamPattern`, `ClientStreamPattern`, `BidiStreamPattern`: routing and streaming decorators.
|
|
150
|
+
- `TcpMicroserviceTransport`, `RedisPubSubMicroserviceTransport`, `RedisStreamsMicroserviceTransport`, `NatsMicroserviceTransport`, `KafkaMicroserviceTransport`, `RabbitMqMicroserviceTransport`, `GrpcMicroserviceTransport`, `MqttMicroserviceTransport`: transport adapters exported from the root barrel.
|
|
151
|
+
- `MicroserviceLifecycleService`, `MICROSERVICE`: programmatic runtime access token and service.
|
|
152
|
+
- `createMicroservicePlatformStatusSnapshot`, `ServerStreamWriter`: status and TypeScript contract helpers.
|
|
153
|
+
|
|
154
|
+
### Supported transport subpaths
|
|
155
|
+
|
|
156
|
+
- `@fluojs/microservices/tcp`
|
|
157
|
+
- `@fluojs/microservices/redis` (Redis Pub/Sub transport)
|
|
158
|
+
- `@fluojs/microservices/nats`
|
|
159
|
+
- `@fluojs/microservices/kafka`
|
|
160
|
+
- `@fluojs/microservices/rabbitmq`
|
|
161
|
+
- `@fluojs/microservices/grpc`
|
|
162
|
+
- `@fluojs/microservices/mqtt`
|
|
163
|
+
|
|
164
|
+
`RedisStreamsMicroserviceTransport` is currently supported from the root barrel only; there is no dedicated `@fluojs/microservices/redis-streams` export.
|
|
165
|
+
|
|
166
|
+
## Related Packages
|
|
167
|
+
|
|
168
|
+
- `@fluojs/core`: Core DI and module system.
|
|
169
|
+
- `@fluojs/runtime`: Microservice bootstrap and factory.
|
|
170
|
+
- `@fluojs/di`: Underlying dependency injection engine.
|
|
171
|
+
|
|
172
|
+
## Example Sources
|
|
173
|
+
|
|
174
|
+
- `packages/microservices/src/module.test.ts`: Integration tests for all transports.
|
|
175
|
+
- `packages/microservices/src/public-api.test.ts`: Root-barrel export coverage, including module registration overrides and `createMicroservicesProviders(...)`.
|
|
176
|
+
- `packages/microservices/src/public-surface.test.ts`: Root-barrel snapshot coverage for the documented public surface.
|
|
177
|
+
- `packages/microservices/src/public-subpaths.test.ts`: Export-map coverage for documented transport subpaths.
|
|
178
|
+
- `examples/microservices-tcp`: Basic TCP microservice example.
|
|
179
|
+
- `examples/microservices-kafka`: Distributed Kafka-based architecture example.
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { Pattern } from './types.js';
|
|
2
|
+
type MethodDecoratorLike = (value: Function, context: ClassMethodDecoratorContext) => void;
|
|
3
|
+
/**
|
|
4
|
+
* Marks a public instance method as the request-response handler for one message pattern.
|
|
5
|
+
*
|
|
6
|
+
* @param pattern String or `RegExp` pattern matched against inbound transport packets.
|
|
7
|
+
* @returns A method decorator that stores message-handler metadata for runtime discovery.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```ts
|
|
11
|
+
* import { MessagePattern } from '@fluojs/microservices';
|
|
12
|
+
*
|
|
13
|
+
* export class MathHandler {
|
|
14
|
+
* @MessagePattern('math.sum')
|
|
15
|
+
* sum(data: { a: number; b: number }) {
|
|
16
|
+
* return data.a + data.b;
|
|
17
|
+
* }
|
|
18
|
+
* }
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
export declare function MessagePattern(pattern: Pattern): MethodDecoratorLike;
|
|
22
|
+
/**
|
|
23
|
+
* Marks a public instance method as the fire-and-forget handler for one event pattern.
|
|
24
|
+
*
|
|
25
|
+
* @param pattern String or `RegExp` pattern matched against inbound event packets.
|
|
26
|
+
* @returns A method decorator that stores event-handler metadata for runtime discovery.
|
|
27
|
+
*/
|
|
28
|
+
export declare function EventPattern(pattern: Pattern): MethodDecoratorLike;
|
|
29
|
+
/**
|
|
30
|
+
* Marks a public instance method as the server-streaming handler for one pattern.
|
|
31
|
+
*
|
|
32
|
+
* @param pattern String or `RegExp` pattern matched against inbound server-stream packets.
|
|
33
|
+
* @returns A method decorator that stores server-stream metadata for runtime discovery.
|
|
34
|
+
*/
|
|
35
|
+
export declare function ServerStreamPattern(pattern: Pattern): MethodDecoratorLike;
|
|
36
|
+
/**
|
|
37
|
+
* Marks a public instance method as the client-streaming handler for one pattern.
|
|
38
|
+
*
|
|
39
|
+
* @param pattern String or `RegExp` pattern matched against inbound client-stream packets.
|
|
40
|
+
* @returns A method decorator that stores client-stream metadata for runtime discovery.
|
|
41
|
+
*/
|
|
42
|
+
export declare function ClientStreamPattern(pattern: Pattern): MethodDecoratorLike;
|
|
43
|
+
/**
|
|
44
|
+
* Marks a public instance method as the bidirectional streaming handler for one pattern.
|
|
45
|
+
*
|
|
46
|
+
* @param pattern String or `RegExp` pattern matched against inbound bidirectional stream packets.
|
|
47
|
+
* @returns A method decorator that stores bidi-stream metadata for runtime discovery.
|
|
48
|
+
*/
|
|
49
|
+
export declare function BidiStreamPattern(pattern: Pattern): MethodDecoratorLike;
|
|
50
|
+
export {};
|
|
51
|
+
//# sourceMappingURL=decorators.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"decorators.d.ts","sourceRoot":"","sources":["../src/decorators.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAgC,OAAO,EAAE,MAAM,YAAY,CAAC;AAGxE,KAAK,mBAAmB,GAAG,CAAC,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,2BAA2B,KAAK,IAAI,CAAC;AA0D3F;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,OAAO,GAAG,mBAAmB,CAEpE;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,OAAO,GAAG,mBAAmB,CAElE;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,GAAG,mBAAmB,CAEzE;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,GAAG,mBAAmB,CAEzE;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,OAAO,GAAG,mBAAmB,CAEvE"}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { metadataSymbol } from '@fluojs/core/internal';
|
|
2
|
+
import { microserviceMetadataSymbol } from './metadata.js';
|
|
3
|
+
function getStandardMetadataBag(metadata) {
|
|
4
|
+
void metadataSymbol;
|
|
5
|
+
return metadata;
|
|
6
|
+
}
|
|
7
|
+
function defineStandardHandlerMetadata(metadata, propertyKey, handlerMetadata) {
|
|
8
|
+
const bag = getStandardMetadataBag(metadata);
|
|
9
|
+
const current = bag[microserviceMetadataSymbol];
|
|
10
|
+
const map = current ?? new Map();
|
|
11
|
+
const entries = map.get(propertyKey) ?? [];
|
|
12
|
+
entries.push(handlerMetadata);
|
|
13
|
+
map.set(propertyKey, entries);
|
|
14
|
+
bag[microserviceMetadataSymbol] = map;
|
|
15
|
+
}
|
|
16
|
+
function decoratorDisplayName(kind) {
|
|
17
|
+
if (kind === 'message') {
|
|
18
|
+
return 'MessagePattern';
|
|
19
|
+
}
|
|
20
|
+
if (kind === 'server-stream') {
|
|
21
|
+
return 'ServerStreamPattern';
|
|
22
|
+
}
|
|
23
|
+
if (kind === 'client-stream') {
|
|
24
|
+
return 'ClientStreamPattern';
|
|
25
|
+
}
|
|
26
|
+
if (kind === 'bidi-stream') {
|
|
27
|
+
return 'BidiStreamPattern';
|
|
28
|
+
}
|
|
29
|
+
return 'EventPattern';
|
|
30
|
+
}
|
|
31
|
+
function createPatternDecorator(kind, pattern) {
|
|
32
|
+
return (_value, context) => {
|
|
33
|
+
if (context.private) {
|
|
34
|
+
throw new Error(`@${decoratorDisplayName(kind)}() cannot be used on private methods.`);
|
|
35
|
+
}
|
|
36
|
+
if (context.static) {
|
|
37
|
+
throw new Error(`@${decoratorDisplayName(kind)}() cannot be used on static methods.`);
|
|
38
|
+
}
|
|
39
|
+
defineStandardHandlerMetadata(context.metadata, context.name, {
|
|
40
|
+
kind,
|
|
41
|
+
pattern
|
|
42
|
+
});
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Marks a public instance method as the request-response handler for one message pattern.
|
|
48
|
+
*
|
|
49
|
+
* @param pattern String or `RegExp` pattern matched against inbound transport packets.
|
|
50
|
+
* @returns A method decorator that stores message-handler metadata for runtime discovery.
|
|
51
|
+
*
|
|
52
|
+
* @example
|
|
53
|
+
* ```ts
|
|
54
|
+
* import { MessagePattern } from '@fluojs/microservices';
|
|
55
|
+
*
|
|
56
|
+
* export class MathHandler {
|
|
57
|
+
* @MessagePattern('math.sum')
|
|
58
|
+
* sum(data: { a: number; b: number }) {
|
|
59
|
+
* return data.a + data.b;
|
|
60
|
+
* }
|
|
61
|
+
* }
|
|
62
|
+
* ```
|
|
63
|
+
*/
|
|
64
|
+
export function MessagePattern(pattern) {
|
|
65
|
+
return createPatternDecorator('message', pattern);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Marks a public instance method as the fire-and-forget handler for one event pattern.
|
|
70
|
+
*
|
|
71
|
+
* @param pattern String or `RegExp` pattern matched against inbound event packets.
|
|
72
|
+
* @returns A method decorator that stores event-handler metadata for runtime discovery.
|
|
73
|
+
*/
|
|
74
|
+
export function EventPattern(pattern) {
|
|
75
|
+
return createPatternDecorator('event', pattern);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Marks a public instance method as the server-streaming handler for one pattern.
|
|
80
|
+
*
|
|
81
|
+
* @param pattern String or `RegExp` pattern matched against inbound server-stream packets.
|
|
82
|
+
* @returns A method decorator that stores server-stream metadata for runtime discovery.
|
|
83
|
+
*/
|
|
84
|
+
export function ServerStreamPattern(pattern) {
|
|
85
|
+
return createPatternDecorator('server-stream', pattern);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Marks a public instance method as the client-streaming handler for one pattern.
|
|
90
|
+
*
|
|
91
|
+
* @param pattern String or `RegExp` pattern matched against inbound client-stream packets.
|
|
92
|
+
* @returns A method decorator that stores client-stream metadata for runtime discovery.
|
|
93
|
+
*/
|
|
94
|
+
export function ClientStreamPattern(pattern) {
|
|
95
|
+
return createPatternDecorator('client-stream', pattern);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Marks a public instance method as the bidirectional streaming handler for one pattern.
|
|
100
|
+
*
|
|
101
|
+
* @param pattern String or `RegExp` pattern matched against inbound bidirectional stream packets.
|
|
102
|
+
* @returns A method decorator that stores bidi-stream metadata for runtime discovery.
|
|
103
|
+
*/
|
|
104
|
+
export function BidiStreamPattern(pattern) {
|
|
105
|
+
return createPatternDecorator('bidi-stream', pattern);
|
|
106
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export { BidiStreamPattern, ClientStreamPattern, EventPattern, MessagePattern, ServerStreamPattern, } from './decorators.js';
|
|
2
|
+
export { GrpcMicroserviceTransport, type GrpcMicroserviceTransportOptions } from './transports/grpc-transport.js';
|
|
3
|
+
export { KafkaMicroserviceTransport, type KafkaMicroserviceTransportOptions } from './transports/kafka-transport.js';
|
|
4
|
+
export { MicroservicesModule, createMicroservicesProviders } from './module.js';
|
|
5
|
+
export { MicroserviceLifecycleService } from './service.js';
|
|
6
|
+
export { MqttMicroserviceTransport, type MqttMicroserviceTransportOptions } from './transports/mqtt-transport.js';
|
|
7
|
+
export { NatsMicroserviceTransport, type NatsMicroserviceTransportOptions } from './transports/nats-transport.js';
|
|
8
|
+
export { RedisPubSubMicroserviceTransport, type RedisPubSubMicroserviceTransportOptions, } from './transports/redis-transport.js';
|
|
9
|
+
export { RedisStreamsMicroserviceTransport, type RedisStreamClientLike, type RedisStreamsMicroserviceTransportOptions, } from './transports/redis-streams-transport.js';
|
|
10
|
+
export { RabbitMqMicroserviceTransport, type RabbitMqMicroserviceTransportOptions, } from './transports/rabbitmq-transport.js';
|
|
11
|
+
export * from './status.js';
|
|
12
|
+
export { TcpMicroserviceTransport } from './transports/tcp-transport.js';
|
|
13
|
+
export { MICROSERVICE } from './tokens.js';
|
|
14
|
+
export type { Microservice, MicroserviceModuleOptions, MicroserviceModuleRegistrationOptions, MicroserviceTransport, Pattern, ServerStreamWriter, } from './types.js';
|
|
15
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,iBAAiB,EACjB,mBAAmB,EACnB,YAAY,EACZ,cAAc,EACd,mBAAmB,GACpB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,yBAAyB,EAAE,KAAK,gCAAgC,EAAE,MAAM,gCAAgC,CAAC;AAClH,OAAO,EAAE,0BAA0B,EAAE,KAAK,iCAAiC,EAAE,MAAM,iCAAiC,CAAC;AACrH,OAAO,EAAE,mBAAmB,EAAE,4BAA4B,EAAE,MAAM,aAAa,CAAC;AAChF,OAAO,EAAE,4BAA4B,EAAE,MAAM,cAAc,CAAC;AAC5D,OAAO,EAAE,yBAAyB,EAAE,KAAK,gCAAgC,EAAE,MAAM,gCAAgC,CAAC;AAClH,OAAO,EAAE,yBAAyB,EAAE,KAAK,gCAAgC,EAAE,MAAM,gCAAgC,CAAC;AAClH,OAAO,EACL,gCAAgC,EAChC,KAAK,uCAAuC,GAC7C,MAAM,iCAAiC,CAAC;AACzC,OAAO,EACL,iCAAiC,EACjC,KAAK,qBAAqB,EAC1B,KAAK,wCAAwC,GAC9C,MAAM,yCAAyC,CAAC;AACjD,OAAO,EACL,6BAA6B,EAC7B,KAAK,oCAAoC,GAC1C,MAAM,oCAAoC,CAAC;AAC5C,cAAc,aAAa,CAAC;AAC5B,OAAO,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAC;AACzE,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,YAAY,EACV,YAAY,EACZ,yBAAyB,EACzB,qCAAqC,EACrC,qBAAqB,EACrB,OAAO,EACP,kBAAkB,GACnB,MAAM,YAAY,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export { BidiStreamPattern, ClientStreamPattern, EventPattern, MessagePattern, ServerStreamPattern } from './decorators.js';
|
|
2
|
+
export { GrpcMicroserviceTransport } from './transports/grpc-transport.js';
|
|
3
|
+
export { KafkaMicroserviceTransport } from './transports/kafka-transport.js';
|
|
4
|
+
export { MicroservicesModule, createMicroservicesProviders } from './module.js';
|
|
5
|
+
export { MicroserviceLifecycleService } from './service.js';
|
|
6
|
+
export { MqttMicroserviceTransport } from './transports/mqtt-transport.js';
|
|
7
|
+
export { NatsMicroserviceTransport } from './transports/nats-transport.js';
|
|
8
|
+
export { RedisPubSubMicroserviceTransport } from './transports/redis-transport.js';
|
|
9
|
+
export { RedisStreamsMicroserviceTransport } from './transports/redis-streams-transport.js';
|
|
10
|
+
export { RabbitMqMicroserviceTransport } from './transports/rabbitmq-transport.js';
|
|
11
|
+
export * from './status.js';
|
|
12
|
+
export { TcpMicroserviceTransport } from './transports/tcp-transport.js';
|
|
13
|
+
export { MICROSERVICE } from './tokens.js';
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { type MetadataPropertyKey } from '@fluojs/core';
|
|
2
|
+
import type { HandlerMetadata } from './types.js';
|
|
3
|
+
export declare function defineHandlerMetadata(target: object, propertyKey: MetadataPropertyKey, metadata: HandlerMetadata): void;
|
|
4
|
+
export declare function getHandlerMetadataEntries(target: object): Array<{
|
|
5
|
+
metadata: HandlerMetadata;
|
|
6
|
+
propertyKey: MetadataPropertyKey;
|
|
7
|
+
}>;
|
|
8
|
+
export declare const microserviceMetadataSymbol: symbol;
|
|
9
|
+
//# sourceMappingURL=metadata.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metadata.d.ts","sourceRoot":"","sources":["../src/metadata.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAGxD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAuClD,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,mBAAmB,EAAE,QAAQ,EAAE,eAAe,GAAG,IAAI,CAKvH;AAED,wBAAgB,yBAAyB,CACvC,MAAM,EAAE,MAAM,GACb,KAAK,CAAC;IAAE,QAAQ,EAAE,eAAe,CAAC;IAAC,WAAW,EAAE,mBAAmB,CAAA;CAAE,CAAC,CAkBxE;AAED,eAAO,MAAM,0BAA0B,QAAkC,CAAC"}
|
package/dist/metadata.js
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { ensureSymbolMetadataPolyfill, metadataSymbol } from '@fluojs/core/internal';
|
|
2
|
+
void ensureSymbolMetadataPolyfill();
|
|
3
|
+
const standardMicroserviceMetadataKey = Symbol.for('fluo.microservices.standard.handler');
|
|
4
|
+
const handlerMetadataStore = new WeakMap();
|
|
5
|
+
function cloneHandlerMetadata(metadata) {
|
|
6
|
+
return {
|
|
7
|
+
kind: metadata.kind,
|
|
8
|
+
pattern: metadata.pattern
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
function getStandardMetadataBag(target) {
|
|
12
|
+
return target[metadataSymbol];
|
|
13
|
+
}
|
|
14
|
+
function getStandardHandlerMap(target) {
|
|
15
|
+
const constructor = target.constructor;
|
|
16
|
+
return constructor ? getStandardMetadataBag(constructor)?.[standardMicroserviceMetadataKey] : undefined;
|
|
17
|
+
}
|
|
18
|
+
function getOrCreateHandlerMap(target) {
|
|
19
|
+
let map = handlerMetadataStore.get(target);
|
|
20
|
+
if (!map) {
|
|
21
|
+
map = new Map();
|
|
22
|
+
handlerMetadataStore.set(target, map);
|
|
23
|
+
}
|
|
24
|
+
return map;
|
|
25
|
+
}
|
|
26
|
+
export function defineHandlerMetadata(target, propertyKey, metadata) {
|
|
27
|
+
const map = getOrCreateHandlerMap(target);
|
|
28
|
+
const current = map.get(propertyKey) ?? [];
|
|
29
|
+
current.push(cloneHandlerMetadata(metadata));
|
|
30
|
+
map.set(propertyKey, current);
|
|
31
|
+
}
|
|
32
|
+
export function getHandlerMetadataEntries(target) {
|
|
33
|
+
const stored = handlerMetadataStore.get(target) ?? new Map();
|
|
34
|
+
const standard = getStandardHandlerMap(target) ?? new Map();
|
|
35
|
+
const keys = new Set([...stored.keys(), ...standard.keys()]);
|
|
36
|
+
const entries = [];
|
|
37
|
+
for (const propertyKey of keys) {
|
|
38
|
+
const metadataList = [...(stored.get(propertyKey) ?? []), ...(standard.get(propertyKey) ?? [])];
|
|
39
|
+
for (const metadata of metadataList) {
|
|
40
|
+
entries.push({
|
|
41
|
+
metadata: cloneHandlerMetadata(metadata),
|
|
42
|
+
propertyKey
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return entries;
|
|
47
|
+
}
|
|
48
|
+
export const microserviceMetadataSymbol = standardMicroserviceMetadataKey;
|