@fluojs/slack 1.1.4 → 2.0.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.
- package/README.ko.md +4 -2
- package/README.md +4 -2
- package/dist/service.d.ts +2 -0
- package/dist/service.d.ts.map +1 -1
- package/dist/service.js +20 -3
- package/package.json +7 -7
package/README.ko.md
CHANGED
|
@@ -28,7 +28,7 @@ fluo를 위한 webhook-first, transport-agnostic Slack 전달 코어 패키지
|
|
|
28
28
|
npm install @fluojs/slack @fluojs/notifications
|
|
29
29
|
```
|
|
30
30
|
|
|
31
|
-
이 패키지는
|
|
31
|
+
이 패키지는 패키지 자체의 지원 계약에 따라 Node.js `>=24.0.0 <27`을 요구합니다. Node 20 및 Node 22 host를 Node.js `>=24.0.0 <27`로 올리세요. Node 24 미만과 Node 27 이상은 지원하지 않으므로 process를 지원되는 line으로 옮겨야 합니다. 런타임 전달 계약 자체는 명시적인 fetch-compatible 경계를 통해 계속 transport-agnostic하게 유지됩니다.
|
|
32
32
|
|
|
33
33
|
## 사용 시점
|
|
34
34
|
|
|
@@ -141,7 +141,7 @@ Behavioral contract 메모:
|
|
|
141
141
|
- `SlackService.send(...)`, `SlackService.sendMany(...)`, `SlackService.sendNotification(...)`은 provider handoff 전에 이미 abort된 signal을 존중합니다. Abort된 signal 또는 transport의 `AbortError`는 `continueOnError`보다 우선하며, 같은 signal은 notification channel을 거쳐 transport 호출까지 전달됩니다.
|
|
142
142
|
- 서비스는 모듈 bootstrap 시 transport를 초기화하고, factory가 소유한 리소스만 애플리케이션 shutdown 시 닫습니다.
|
|
143
143
|
- 직접 전달과 notifications 기반 전달은 lifecycle이 `ready`일 때만 허용됩니다. `onModuleInit()`이 끝나기 전, 초기화 실패 뒤, 또는 shutdown 중 호출하면 transport를 lazy 생성하거나 재사용하지 않고 `SlackLifecycleError`로 실패합니다.
|
|
144
|
-
- shutdown은 새 전달을 거부하고,
|
|
144
|
+
- shutdown은 새 전달을 거부하고, 진행 중인 factory 소유 transport 생성과 `verify()` 호출을 포함하는 공유 bootstrap initialization promise가 settle되기를 기다린 뒤 활성 전달을 drain하고, 소유한 transport를 닫고 완료됩니다.
|
|
145
145
|
- factory 소유 transport cleanup은 bootstrap 실패 cleanup과 application shutdown 사이에서 직렬화되므로, 두 경로가 경합해도 같은 owned transport는 최대 한 번만 닫힙니다.
|
|
146
146
|
- `SlackService.createPlatformStatusSnapshot()`은 호출자가 내부 옵션에 접근하지 않아도 lifecycle, readiness, transport 소유권을 보고합니다.
|
|
147
147
|
- 이 패키지는 절대로 `process.env`를 직접 읽지 않습니다. 모든 설정은 명시적인 옵션 또는 DI를 통해 들어와야 합니다.
|
|
@@ -208,6 +208,7 @@ Behavioral contract 메모:
|
|
|
208
208
|
|
|
209
209
|
- `verifyOnModuleInit`은 선택 사항이며 기본값은 `false`입니다.
|
|
210
210
|
- 검증은 capability 기반입니다. `verify()`를 노출하는 transport만 호출하므로 webhook-only 또는 애플리케이션이 소유한 transport가 no-op verifier를 추가할 필요는 없습니다.
|
|
211
|
+
- Bootstrap initialization과 verification은 shutdown과 하나의 promise를 공유하므로, factory 소유 transport는 진행 중인 `verify()`가 settle될 때까지 열린 상태를 유지하고 이후 최대 한 번만 닫힙니다.
|
|
211
212
|
- `transport.verify()`가 reject되면 bootstrap은 초기화 실패를 감싼 `SlackLifecycleError`로 실패하고, service lifecycle은 `failed`로 이동하며, readiness/status snapshot은 provider를 not ready로 보고하고, 이미 해석된 factory 소유 transport는 오류를 다시 던지기 전에 닫습니다. 그 cleanup이 진행 중일 때 shutdown이 시작되면 두 호출자는 같은 close 작업을 기다립니다.
|
|
212
213
|
- `SlackService.createPlatformStatusSnapshot()`은 bootstrap 검증 요청 여부를 health/readiness tooling이 확인할 수 있도록 `verifiedOnModuleInit`을 포함합니다.
|
|
213
214
|
|
|
@@ -405,5 +406,6 @@ Slack 패키지는 의도적으로 다음을 **포함하지 않습니다**:
|
|
|
405
406
|
## 예제 소스
|
|
406
407
|
|
|
407
408
|
- `packages/slack/src/module.test.ts`: 모듈 등록, `createSlackProviders(...)` helper coverage, async wiring, webhook transport, notifications integration 예제.
|
|
409
|
+
- `packages/slack/src/lifecycle-regression.test.ts`: Bootstrap verification과 shutdown 순서의 regression coverage.
|
|
408
410
|
- `packages/slack/src/public-surface.test.ts`: 공개 export와 TypeScript 계약 검증 예제.
|
|
409
411
|
- `packages/slack/src/status.test.ts`: health/readiness 계약 예제.
|
package/README.md
CHANGED
|
@@ -28,7 +28,7 @@ Webhook-first, transport-agnostic Slack delivery core for fluo. It provides a Ne
|
|
|
28
28
|
npm install @fluojs/slack @fluojs/notifications
|
|
29
29
|
```
|
|
30
30
|
|
|
31
|
-
This package
|
|
31
|
+
This package requires Node.js `>=24.0.0 <27` as its package-owned support contract. Upgrade Node 20 and Node 22 hosts to Node.js `>=24.0.0 <27`; Node versions below 24 and Node 27+ are unsupported, so move the process to a supported line. Its delivery contract remains transport-agnostic at runtime through explicit fetch-compatible boundaries.
|
|
32
32
|
|
|
33
33
|
## When to Use
|
|
34
34
|
|
|
@@ -141,7 +141,7 @@ Behavioral contract notes:
|
|
|
141
141
|
- `SlackService.send(...)`, `SlackService.sendMany(...)`, and `SlackService.sendNotification(...)` honor already-aborted signals before provider handoff. An aborted signal or a transport `AbortError` takes precedence over `continueOnError`, and the same signal is propagated through notification channels to transport calls.
|
|
142
142
|
- The service initializes the configured transport during module bootstrap and closes factory-owned resources during application shutdown.
|
|
143
143
|
- Direct and notification-backed delivery require the lifecycle to be `ready`; calls before `onModuleInit()` finishes, after initialization failure, or during shutdown fail with `SlackLifecycleError` instead of lazily creating or reusing transports.
|
|
144
|
-
- Shutdown rejects new deliveries, waits for
|
|
144
|
+
- Shutdown rejects new deliveries, waits for the shared bootstrap initialization promise—including any in-flight factory-owned transport creation and `verify()` call—to settle, drains active deliveries, and then closes the owned transport before completion.
|
|
145
145
|
- Factory-owned transport cleanup is serialized across bootstrap-failure cleanup and application shutdown, so the same owned transport is closed at most once even when those paths race.
|
|
146
146
|
- `SlackService.createPlatformStatusSnapshot()` reports lifecycle, readiness, and transport ownership without requiring callers to reach into internal options.
|
|
147
147
|
- The package never reads `process.env` directly. All configuration must enter through explicit options or DI.
|
|
@@ -208,6 +208,7 @@ Behavioral contract notes:
|
|
|
208
208
|
|
|
209
209
|
- `verifyOnModuleInit` is optional and defaults to `false`.
|
|
210
210
|
- Verification is capability-based: only transports that expose `verify()` are called, so webhook-only or app-owned transports do not have to add a no-op verifier.
|
|
211
|
+
- Bootstrap initialization and verification share one promise with shutdown, so a factory-owned transport remains open until an in-flight `verify()` call settles and is then closed at most once.
|
|
211
212
|
- If `transport.verify()` rejects, bootstrap fails with `SlackLifecycleError` wrapping the initialization failure, the service lifecycle moves to `failed`, readiness/status snapshots report the provider as not ready, and factory-owned transports that were already resolved are closed before the error is rethrown. If shutdown starts while that cleanup is still in progress, both callers await the same close work.
|
|
212
213
|
- `SlackService.createPlatformStatusSnapshot()` includes `verifiedOnModuleInit` so health/readiness tooling can tell whether bootstrap verification was requested.
|
|
213
214
|
|
|
@@ -405,5 +406,6 @@ These limitations are part of the package contract so runtime choice, provider c
|
|
|
405
406
|
## Example Sources
|
|
406
407
|
|
|
407
408
|
- `packages/slack/src/module.test.ts`: Module registration, `createSlackProviders(...)` helper coverage, async wiring, webhook transport, and notifications integration examples.
|
|
409
|
+
- `packages/slack/src/lifecycle-regression.test.ts`: Bootstrap verification and shutdown ordering regression coverage.
|
|
408
410
|
- `packages/slack/src/public-surface.test.ts`: Public export and TypeScript contract verification.
|
|
409
411
|
- `packages/slack/src/status.test.ts`: Health/readiness contract examples.
|
package/dist/service.d.ts
CHANGED
|
@@ -11,6 +11,7 @@ import type { NormalizedSlackModuleOptions, Slack, SlackMessage, SlackNotificati
|
|
|
11
11
|
export declare class SlackService implements Slack, OnModuleInit, OnApplicationShutdown {
|
|
12
12
|
private readonly options;
|
|
13
13
|
private readonly inFlightDeliveries;
|
|
14
|
+
private initializationPromise;
|
|
14
15
|
private lifecycleState;
|
|
15
16
|
private ownedTransportCleanupPromise;
|
|
16
17
|
private resolvedTransport;
|
|
@@ -23,6 +24,7 @@ export declare class SlackService implements Slack, OnModuleInit, OnApplicationS
|
|
|
23
24
|
private closeOwnedTransportResourcesOnce;
|
|
24
25
|
private resolveTransportForCleanup;
|
|
25
26
|
onModuleInit(): Promise<void>;
|
|
27
|
+
private initializeTransport;
|
|
26
28
|
/**
|
|
27
29
|
* Creates a platform status snapshot for the active Slack transport wiring.
|
|
28
30
|
*
|
package/dist/service.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,qBAAqB,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAK3E,OAAO,KAAK,EAEV,4BAA4B,EAC5B,KAAK,EACL,YAAY,EACZ,gCAAgC,EAChC,oBAAoB,EAEpB,oBAAoB,EACpB,gBAAgB,EAChB,eAAe,EAGhB,MAAM,YAAY,CAAC;AAsDpB;;;;;;;GAOG;AACH,qBACa,YAAa,YAAW,KAAK,EAAE,YAAY,EAAE,qBAAqB;
|
|
1
|
+
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../src/service.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,qBAAqB,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAK3E,OAAO,KAAK,EAEV,4BAA4B,EAC5B,KAAK,EACL,YAAY,EACZ,gCAAgC,EAChC,oBAAoB,EAEpB,oBAAoB,EACpB,gBAAgB,EAChB,eAAe,EAGhB,MAAM,YAAY,CAAC;AAsDpB;;;;;;;GAOG;AACH,qBACa,YAAa,YAAW,KAAK,EAAE,YAAY,EAAE,qBAAqB;IASjE,OAAO,CAAC,QAAQ,CAAC,OAAO;IARpC,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAA+B;IAClE,OAAO,CAAC,qBAAqB,CAA4B;IACzD,OAAO,CAAC,cAAc,CAAyC;IAC/D,OAAO,CAAC,4BAA4B,CAA4B;IAChE,OAAO,CAAC,iBAAiB,CAA6B;IACtD,OAAO,CAAC,eAAe,CAA4B;IACnD,OAAO,CAAC,gBAAgB,CAAsC;gBAEjC,OAAO,EAAE,4BAA4B;IAE5D,qBAAqB,IAAI,OAAO,CAAC,IAAI,CAAC;YAgB9B,mBAAmB;IAoBjC,OAAO,CAAC,4BAA4B;YAQtB,gCAAgC;YAYhC,0BAA0B;IAexC,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;YAoBf,mBAAmB;IAsBjC;;;;OAIG;IACH,4BAA4B;IAW5B;;;;;;;;;;;;;;;;OAgBG;IACG,IAAI,CAAC,OAAO,EAAE,YAAY,EAAE,OAAO,GAAE,gBAAqB,GAAG,OAAO,CAAC,eAAe,CAAC;IAyB3F;;;;;;;;;;;;;OAaG;IACG,QAAQ,CAAC,QAAQ,EAAE,SAAS,YAAY,EAAE,EAAE,OAAO,GAAE,oBAAyB,GAAG,OAAO,CAAC,oBAAoB,CAAC;IAgCpH;;;;;;;;;;;;;;;;;OAiBG;IACG,gBAAgB,CACpB,YAAY,EAAE,gCAAgC,EAC9C,OAAO,GAAE,gBAAqB,GAC7B,OAAO,CAAC,eAAe,CAAC;YAkCb,eAAe;IAiB7B,OAAO,CAAC,sBAAsB;YAKhB,oCAAoC;YAsBpC,uBAAuB;YAMvB,qBAAqB;IAWnC,OAAO,CAAC,6BAA6B;IAMrC,OAAO,CAAC,gBAAgB;IAMxB,OAAO,CAAC,gBAAgB;IAkBxB,OAAO,CAAC,0BAA0B;YAkBpB,kBAAkB;CAkBjC"}
|
package/dist/service.js
CHANGED
|
@@ -59,6 +59,7 @@ class SlackService {
|
|
|
59
59
|
[_SlackService, _initClass] = _applyDecs(this, [Inject(SLACK_OPTIONS)], []).c;
|
|
60
60
|
}
|
|
61
61
|
inFlightDeliveries = new Set();
|
|
62
|
+
initializationPromise;
|
|
62
63
|
lifecycleState = 'created';
|
|
63
64
|
ownedTransportCleanupPromise;
|
|
64
65
|
resolvedTransport;
|
|
@@ -80,6 +81,10 @@ class SlackService {
|
|
|
80
81
|
}
|
|
81
82
|
async closeOwnedTransport() {
|
|
82
83
|
try {
|
|
84
|
+
const initializationPromise = this.initializationPromise;
|
|
85
|
+
if (initializationPromise) {
|
|
86
|
+
await initializationPromise.then(() => undefined, () => undefined);
|
|
87
|
+
}
|
|
83
88
|
await this.drainInFlightDeliveries();
|
|
84
89
|
await this.closeOwnedTransportResources();
|
|
85
90
|
this.lifecycleState = 'stopped';
|
|
@@ -113,11 +118,23 @@ class SlackService {
|
|
|
113
118
|
}
|
|
114
119
|
return this.transportPromise.then(transport => transport, () => undefined);
|
|
115
120
|
}
|
|
116
|
-
|
|
121
|
+
onModuleInit() {
|
|
117
122
|
if (this.lifecycleState === 'stopping' || this.lifecycleState === 'stopped') {
|
|
118
|
-
return;
|
|
123
|
+
return Promise.resolve();
|
|
119
124
|
}
|
|
120
|
-
this.
|
|
125
|
+
if (!this.initializationPromise) {
|
|
126
|
+
let resolveInitialization = () => undefined;
|
|
127
|
+
let rejectInitialization = _reason => undefined;
|
|
128
|
+
this.lifecycleState = 'starting';
|
|
129
|
+
this.initializationPromise = new Promise((resolve, reject) => {
|
|
130
|
+
resolveInitialization = resolve;
|
|
131
|
+
rejectInitialization = reject;
|
|
132
|
+
});
|
|
133
|
+
void this.initializeTransport().then(resolveInitialization, rejectInitialization);
|
|
134
|
+
}
|
|
135
|
+
return this.initializationPromise;
|
|
136
|
+
}
|
|
137
|
+
async initializeTransport() {
|
|
121
138
|
try {
|
|
122
139
|
const transport = await this.ensureTransport();
|
|
123
140
|
if (this.lifecycleState !== 'starting') {
|
package/package.json
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"portable",
|
|
10
10
|
"fetch"
|
|
11
11
|
],
|
|
12
|
-
"version": "
|
|
12
|
+
"version": "2.0.0",
|
|
13
13
|
"private": false,
|
|
14
14
|
"license": "MIT",
|
|
15
15
|
"repository": {
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
"directory": "packages/slack"
|
|
19
19
|
},
|
|
20
20
|
"engines": {
|
|
21
|
-
"node": ">=
|
|
21
|
+
"node": ">=24.0.0 <27"
|
|
22
22
|
},
|
|
23
23
|
"publishConfig": {
|
|
24
24
|
"access": "public"
|
|
@@ -36,13 +36,13 @@
|
|
|
36
36
|
"dist"
|
|
37
37
|
],
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"@fluojs/core": "^
|
|
40
|
-
"@fluojs/di": "^
|
|
41
|
-
"@fluojs/notifications": "^
|
|
42
|
-
"@fluojs/runtime": "^
|
|
39
|
+
"@fluojs/core": "^2.0.0",
|
|
40
|
+
"@fluojs/di": "^3.0.0",
|
|
41
|
+
"@fluojs/notifications": "^2.0.0",
|
|
42
|
+
"@fluojs/runtime": "^3.0.0"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
45
|
-
"vitest": "^
|
|
45
|
+
"vitest": "^4.1.11"
|
|
46
46
|
},
|
|
47
47
|
"scripts": {
|
|
48
48
|
"prebuild": "node ../../tooling/scripts/clean-dist.mjs",
|