@fluojs/slack 1.1.0 → 1.1.2
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 +3 -0
- package/README.md +3 -0
- package/dist/module.d.ts +4 -1
- package/dist/module.d.ts.map +1 -1
- package/dist/module.js +4 -1
- package/dist/service.d.ts.map +1 -1
- package/dist/service.js +5 -2
- package/dist/webhook.d.ts.map +1 -1
- package/dist/webhook.js +3 -0
- package/package.json +5 -5
package/README.ko.md
CHANGED
|
@@ -127,6 +127,7 @@ Behavioral contract 메모:
|
|
|
127
127
|
|
|
128
128
|
- `SlackService.send(...)`는 전달 전에 `defaultChannel`을 해석합니다.
|
|
129
129
|
- `SlackService.sendMany(...)`는 메시지를 순차적으로 보내며, fail-fast 대신 batch result가 필요한 호출자를 위해 `continueOnError`를 지원합니다.
|
|
130
|
+
- `SlackService.send(...)`, `SlackService.sendMany(...)`, `SlackService.sendNotification(...)`은 provider handoff 전에 이미 abort된 signal을 존중하며, 같은 signal을 transport 호출로 전달합니다.
|
|
130
131
|
- 서비스는 모듈 bootstrap 시 transport를 초기화하고, factory가 소유한 리소스만 애플리케이션 shutdown 시 닫습니다.
|
|
131
132
|
- shutdown이 시작된 뒤에는 `SlackService.send(...)`와 `SlackService.sendNotification(...)`이 transport를 재사용하거나 lazy 생성하지 않고 `SlackLifecycleError`로 실패합니다. 진행 중인 factory 소유 transport 생성은 shutdown이 기다린 뒤 닫습니다.
|
|
132
133
|
- `SlackService.createPlatformStatusSnapshot()`은 호출자가 내부 옵션에 접근하지 않아도 lifecycle, readiness, transport 소유권을 보고합니다.
|
|
@@ -198,7 +199,9 @@ await slack.send({
|
|
|
198
199
|
|
|
199
200
|
Behavioral contract 메모:
|
|
200
201
|
|
|
202
|
+
- `fetch`를 명시적으로 전달하는 방식이 portable path이며 모든 지원 런타임에서 권장됩니다. 하위 호환성을 위해 `fetch`를 생략하면 ambient runtime API인 `globalThis.fetch`가 있을 때 이를 폴백으로 사용합니다. `globalThis.fetch`가 없는 런타임에서는 `SlackConfigurationError`로 빠르게 실패합니다.
|
|
201
203
|
- 내장 webhook transport는 `408`, `429`, `5xx` 같은 일시적 실패를 호출자에게 에러를 노출하기 전에 bounded exponential backoff로 재시도합니다.
|
|
204
|
+
- Abort signal은 주입된 `fetch` 경계로 전달되며, retry backoff를 취소할 때 `AbortError`를 `SlackTransportError`로 감싸지 않습니다.
|
|
202
205
|
- 호출자에게 보이는 `SlackTransportError` 메시지는 기본적으로 raw upstream response body를 포함하지 않습니다.
|
|
203
206
|
|
|
204
207
|
### 의도적인 제한 사항
|
package/README.md
CHANGED
|
@@ -127,6 +127,7 @@ Behavioral contract notes:
|
|
|
127
127
|
|
|
128
128
|
- `SlackService.send(...)` resolves `defaultChannel` before delivery.
|
|
129
129
|
- `SlackService.sendMany(...)` sends messages sequentially and supports `continueOnError` when callers need a batch result instead of fail-fast behavior.
|
|
130
|
+
- `SlackService.send(...)`, `SlackService.sendMany(...)`, and `SlackService.sendNotification(...)` honor already-aborted signals before provider handoff, and the same signal is propagated to transport calls.
|
|
130
131
|
- The service initializes the configured transport during module bootstrap and closes factory-owned resources during application shutdown.
|
|
131
132
|
- Once shutdown starts, `SlackService.send(...)` and `SlackService.sendNotification(...)` fail with `SlackLifecycleError` instead of reusing or lazily creating transports; any in-flight factory-owned transport creation is awaited and closed by shutdown.
|
|
132
133
|
- `SlackService.createPlatformStatusSnapshot()` reports lifecycle, readiness, and transport ownership without requiring callers to reach into internal options.
|
|
@@ -198,7 +199,9 @@ For richer API integrations such as `chat.postMessage`, implement the exported `
|
|
|
198
199
|
|
|
199
200
|
Behavioral contract notes:
|
|
200
201
|
|
|
202
|
+
- Passing `fetch` explicitly is the portable path and is recommended for all supported runtimes. For backward compatibility, omitting `fetch` falls back to `globalThis.fetch` when that ambient runtime API exists; runtimes without `globalThis.fetch` fail fast with `SlackConfigurationError`.
|
|
201
203
|
- The built-in webhook transport retries transient `408`, `429`, and `5xx` failures with bounded exponential backoff before surfacing an error.
|
|
204
|
+
- Abort signals are passed to the injected `fetch` boundary and cancel retry backoff without wrapping `AbortError` values as `SlackTransportError`.
|
|
202
205
|
- Caller-visible `SlackTransportError` messages omit raw upstream response bodies by default.
|
|
203
206
|
|
|
204
207
|
### Intentional limitations
|
package/dist/module.d.ts
CHANGED
|
@@ -19,7 +19,10 @@ export declare class SlackModule {
|
|
|
19
19
|
* @example
|
|
20
20
|
* ```ts
|
|
21
21
|
* SlackModule.forRoot({
|
|
22
|
-
* transport: createSlackWebhookTransport({
|
|
22
|
+
* transport: createSlackWebhookTransport({
|
|
23
|
+
* fetch: runtime.fetch,
|
|
24
|
+
* webhookUrl: 'https://hooks.slack.com/services/...',
|
|
25
|
+
* }),
|
|
23
26
|
* });
|
|
24
27
|
* ```
|
|
25
28
|
*/
|
package/dist/module.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"module.d.ts","sourceRoot":"","sources":["../src/module.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,EAAgB,KAAK,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAMhE,OAAO,KAAK,EAGV,uBAAuB,EACvB,kBAAkB,EAGnB,MAAM,YAAY,CAAC;AA0DpB;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,kBAAkB,GAAG,QAAQ,EAAE,CAK5E;AAsCD,kFAAkF;AAClF,qBAAa,WAAW;IACtB
|
|
1
|
+
{"version":3,"file":"module.d.ts","sourceRoot":"","sources":["../src/module.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,EAAgB,KAAK,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAMhE,OAAO,KAAK,EAGV,uBAAuB,EACvB,kBAAkB,EAGnB,MAAM,YAAY,CAAC;AA0DpB;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,kBAAkB,GAAG,QAAQ,EAAE,CAK5E;AAsCD,kFAAkF;AAClF,qBAAa,WAAW;IACtB;;;;;;;;;;;;;;;OAeG;IACH,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,kBAAkB,GAAG,UAAU;IAIvD;;;;;;;;;;;;;;;;;;;OAmBG;IACH,MAAM,CAAC,YAAY,CAAC,OAAO,EAAE,uBAAuB,GAAG,UAAU;CAGlE"}
|
package/dist/module.js
CHANGED
|
@@ -99,7 +99,10 @@ export class SlackModule {
|
|
|
99
99
|
* @example
|
|
100
100
|
* ```ts
|
|
101
101
|
* SlackModule.forRoot({
|
|
102
|
-
* transport: createSlackWebhookTransport({
|
|
102
|
+
* transport: createSlackWebhookTransport({
|
|
103
|
+
* fetch: runtime.fetch,
|
|
104
|
+
* webhookUrl: 'https://hooks.slack.com/services/...',
|
|
105
|
+
* }),
|
|
103
106
|
* });
|
|
104
107
|
* ```
|
|
105
108
|
*/
|
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;AA2CpB;;;;;;;GAOG;AACH,qBACa,YAAa,YAAW,KAAK,EAAE,YAAY,EAAE,qBAAqB;IAKjE,OAAO,CAAC,QAAQ,CAAC,OAAO;IAJpC,OAAO,CAAC,cAAc,CAAyC;IAC/D,OAAO,CAAC,iBAAiB,CAA6B;IACtD,OAAO,CAAC,gBAAgB,CAAsC;gBAEjC,OAAO,EAAE,4BAA4B;IAE5D,qBAAqB,IAAI,OAAO,CAAC,IAAI,CAAC;IAiBtC,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;IAiCnC;;;;OAIG;IACH,4BAA4B;IAW5B;;;;;;;;;;;;;;;OAeG;IACG,IAAI,CAAC,OAAO,EAAE,YAAY,EAAE,OAAO,GAAE,gBAAqB,GAAG,OAAO,CAAC,eAAe,CAAC;
|
|
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;AA2CpB;;;;;;;GAOG;AACH,qBACa,YAAa,YAAW,KAAK,EAAE,YAAY,EAAE,qBAAqB;IAKjE,OAAO,CAAC,QAAQ,CAAC,OAAO;IAJpC,OAAO,CAAC,cAAc,CAAyC;IAC/D,OAAO,CAAC,iBAAiB,CAA6B;IACtD,OAAO,CAAC,gBAAgB,CAAsC;gBAEjC,OAAO,EAAE,4BAA4B;IAE5D,qBAAqB,IAAI,OAAO,CAAC,IAAI,CAAC;IAiBtC,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;IAiCnC;;;;OAIG;IACH,4BAA4B;IAW5B;;;;;;;;;;;;;;;OAeG;IACG,IAAI,CAAC,OAAO,EAAE,YAAY,EAAE,OAAO,GAAE,gBAAqB,GAAG,OAAO,CAAC,eAAe,CAAC;IAsB3F;;;;;;;;;;;;OAYG;IACG,QAAQ,CAAC,QAAQ,EAAE,SAAS,YAAY,EAAE,EAAE,OAAO,GAAE,oBAAyB,GAAG,OAAO,CAAC,oBAAoB,CAAC;IA6BpH;;;;;;;;;;;;;;;;OAgBG;IACG,gBAAgB,CACpB,YAAY,EAAE,gCAAgC,EAC9C,OAAO,GAAE,gBAAqB,GAC7B,OAAO,CAAC,eAAe,CAAC;YAkCb,eAAe;IAiB7B,OAAO,CAAC,6BAA6B;IAMrC,OAAO,CAAC,gBAAgB;IAIxB,OAAO,CAAC,gBAAgB;IAkBxB,OAAO,CAAC,0BAA0B;YAkBpB,kBAAkB;CAkBjC"}
|
package/dist/service.js
CHANGED
|
@@ -135,6 +135,7 @@ class SlackService {
|
|
|
135
135
|
const transport = await this.ensureTransport();
|
|
136
136
|
const normalized = this.normalizeMessage(message);
|
|
137
137
|
assertMessageContent(normalized);
|
|
138
|
+
assertNotAborted(options.signal);
|
|
138
139
|
this.assertCanDeliver();
|
|
139
140
|
const result = await transport.send(normalized, options);
|
|
140
141
|
return {
|
|
@@ -207,7 +208,8 @@ class SlackService {
|
|
|
207
208
|
assertNotAborted(options.signal);
|
|
208
209
|
this.assertCanDeliver();
|
|
209
210
|
const payload = notification.payload;
|
|
210
|
-
const rendered = await this.renderNotification(notification);
|
|
211
|
+
const rendered = await this.renderNotification(notification, options.signal);
|
|
212
|
+
assertNotAborted(options.signal);
|
|
211
213
|
return this.send({
|
|
212
214
|
attachments: payload.attachments ?? rendered?.attachments,
|
|
213
215
|
blocks: payload.blocks ?? rendered?.blocks,
|
|
@@ -282,10 +284,11 @@ class SlackService {
|
|
|
282
284
|
}
|
|
283
285
|
return recipients[0] ?? this.options.defaultChannel;
|
|
284
286
|
}
|
|
285
|
-
async renderNotification(notification) {
|
|
287
|
+
async renderNotification(notification, signal) {
|
|
286
288
|
if (!notification.template || !this.options.renderer) {
|
|
287
289
|
return undefined;
|
|
288
290
|
}
|
|
291
|
+
assertNotAborted(signal);
|
|
289
292
|
return this.options.renderer.render({
|
|
290
293
|
locale: notification.locale,
|
|
291
294
|
metadata: notification.metadata,
|
package/dist/webhook.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"webhook.d.ts","sourceRoot":"","sources":["../src/webhook.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAIV,cAAc,EAEd,4BAA4B,EAC7B,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"webhook.d.ts","sourceRoot":"","sources":["../src/webhook.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAIV,cAAc,EAEd,4BAA4B,EAC7B,MAAM,YAAY,CAAC;AA4FpB;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,2BAA2B,CAAC,OAAO,EAAE,4BAA4B,GAAG,cAAc,CA6DjG"}
|
package/dist/webhook.js
CHANGED
|
@@ -80,6 +80,9 @@ async function waitForRetry(delayMs, signal) {
|
|
|
80
80
|
if (delayMs <= 0) {
|
|
81
81
|
return;
|
|
82
82
|
}
|
|
83
|
+
if (signal?.aborted) {
|
|
84
|
+
throw signal.reason ?? new DOMException('The operation was aborted.', 'AbortError');
|
|
85
|
+
}
|
|
83
86
|
await new Promise((resolve, reject) => {
|
|
84
87
|
const timer = setTimeout(() => {
|
|
85
88
|
signal?.removeEventListener('abort', onAbort);
|
package/package.json
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"portable",
|
|
10
10
|
"fetch"
|
|
11
11
|
],
|
|
12
|
-
"version": "1.1.
|
|
12
|
+
"version": "1.1.2",
|
|
13
13
|
"private": false,
|
|
14
14
|
"license": "MIT",
|
|
15
15
|
"repository": {
|
|
@@ -36,10 +36,10 @@
|
|
|
36
36
|
"dist"
|
|
37
37
|
],
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"@fluojs/core": "^1.0.
|
|
40
|
-
"@fluojs/di": "^1.0.
|
|
41
|
-
"@fluojs/notifications": "^1.0.
|
|
42
|
-
"@fluojs/runtime": "^1.1.
|
|
39
|
+
"@fluojs/core": "^1.0.3",
|
|
40
|
+
"@fluojs/di": "^1.0.3",
|
|
41
|
+
"@fluojs/notifications": "^1.0.1",
|
|
42
|
+
"@fluojs/runtime": "^1.1.2"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
45
45
|
"vitest": "^3.2.4"
|