@fluojs/discord 1.0.0 → 1.0.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 CHANGED
@@ -96,6 +96,7 @@ Behavioral contract 메모:
96
96
 
97
97
  - `DiscordService.send(...)`는 전달 전에 `defaultThreadId`를 해석합니다.
98
98
  - 서비스는 모듈 bootstrap 시 transport를 초기화하고, factory가 소유한 리소스만 애플리케이션 shutdown 시 닫습니다.
99
+ - send는 bootstrap이 transport를 `ready`로 표시한 뒤에만 허용됩니다. bootstrap 전, startup 중, bootstrap 실패 후, shutdown 중, shutdown 후 시도는 전달 전에 거부됩니다.
99
100
  - 서비스가 shutdown 중이거나 이미 stopped 상태라면 cached transport를 재사용하지 않고 send를 거부합니다.
100
101
  - 빈 `defaultThreadId`와 `notifications.channel` 값은 trim 후 무시됩니다. notifications channel은 기본적으로 `discord`입니다.
101
102
  - 이 패키지는 절대로 `process.env`를 직접 읽지 않습니다. 모든 설정은 명시적인 옵션 또는 DI를 통해 들어와야 합니다.
@@ -166,8 +167,8 @@ bot 기반 REST 전달처럼 더 풍부한 API 연동이 필요하다면 export
166
167
  Behavioral contract 메모:
167
168
 
168
169
  - 내장 webhook transport는 `408`, `429`, `5xx` 같은 일시적 응답뿐 아니라 transport-level exception도 bounded exponential backoff로 재시도한 뒤 호출자에게 에러를 노출합니다. 영구적인 upstream 응답은 재시도하지 않습니다.
170
+ - 성공한 webhook 응답은 `DiscordSendResult.response`로 노출됩니다. rate-limit 재시도가 끝내 실패한 경우를 포함해, 호출자에게 보이는 `DiscordTransportError` 메시지는 기본적으로 raw upstream response body를 포함하지 않습니다.
169
171
  - 잘못되었거나 절대 URL이 아닌 `webhookUrl` 값은 전달 실패로 재시도하지 않고 즉시 `DiscordConfigurationError`로 거부됩니다.
170
- - 호출자에게 보이는 `DiscordTransportError` 메시지는 기본적으로 raw upstream response body를 포함하지 않습니다.
171
172
 
172
173
  ### 의도적인 제한 사항
173
174
 
@@ -184,7 +185,10 @@ Discord 패키지는 의도적으로 다음을 **포함하지 않습니다**:
184
185
 
185
186
  ### 핵심
186
187
 
188
+ - `Discord`
187
189
  - `DiscordModule.forRoot(options)` / `DiscordModule.forRootAsync(options)`
190
+ - `DiscordModuleOptions`
191
+ - `DiscordAsyncModuleOptions`
188
192
  - `DiscordService`
189
193
  - `DiscordChannel`
190
194
  - `DISCORD`
@@ -196,11 +200,11 @@ Discord 패키지는 의도적으로 다음을 **포함하지 않습니다**:
196
200
 
197
201
  - `DiscordMessage`
198
202
  - `NormalizedDiscordMessage`
199
- - `DiscordAsyncModuleOptions`
200
203
  - `DiscordWebhookTransportOptions`
201
204
  - `DiscordFetchLike`
202
205
  - `DiscordFetchResponse`
203
206
  - `DiscordSendResult`
207
+ - `DiscordSendOptions`
204
208
  - `DiscordSendManyOptions`
205
209
  - `DiscordSendBatchResult`
206
210
  - `DiscordSendFailure`
@@ -212,7 +216,9 @@ Discord 패키지는 의도적으로 다음을 **포함하지 않습니다**:
212
216
  - `DiscordEmbed`
213
217
  - `DiscordPoll`
214
218
  - `DiscordTransport`
219
+ - `DiscordTransportContext`
215
220
  - `DiscordTransportFactory`
221
+ - `DiscordTransportReceipt`
216
222
  - `DiscordTemplateRenderInput`
217
223
  - `DiscordTemplateRenderResult`
218
224
  - `DiscordTemplateRenderer`
@@ -222,6 +228,8 @@ Discord 패키지는 의도적으로 다음을 **포함하지 않습니다**:
222
228
 
223
229
  - `createDiscordPlatformStatusSnapshot(...)`
224
230
  - `DiscordLifecycleState`
231
+ - `DiscordPlatformStatusSnapshot`
232
+ - `DiscordStatusAdapterInput`
225
233
  - `DiscordConfigurationError`
226
234
  - `DiscordMessageValidationError`
227
235
  - `DiscordTransportError`
package/README.md CHANGED
@@ -96,6 +96,7 @@ Behavioral contract notes:
96
96
 
97
97
  - `DiscordService.send(...)` resolves `defaultThreadId` before delivery.
98
98
  - The service initializes the configured transport during module bootstrap and closes factory-owned resources during application shutdown.
99
+ - Sends are accepted only after bootstrap marks the transport `ready`; attempts before bootstrap, during startup, after failed bootstrap, while shutting down, or after shutdown are rejected before delivery.
99
100
  - Sends attempted while the service is shutting down or already stopped are rejected before reusing the cached transport.
100
101
  - Blank `defaultThreadId` and `notifications.channel` values are trimmed and ignored; the notifications channel defaults to `discord`.
101
102
  - The package never reads `process.env` directly. All configuration must enter through explicit options or DI.
@@ -166,8 +167,8 @@ For richer API integrations such as bot-backed REST delivery, implement the expo
166
167
  Behavioral contract notes:
167
168
 
168
169
  - The built-in webhook transport retries transient `408`, `429`, and `5xx` responses, and also retries transport-level exceptions, using bounded exponential backoff before surfacing an error. Permanent upstream responses are not retried.
170
+ - Successful webhook responses are exposed through `DiscordSendResult.response`; caller-visible `DiscordTransportError` messages still omit raw upstream response bodies by default, including after rate-limit retries fail.
169
171
  - Malformed or non-absolute `webhookUrl` values are rejected immediately as `DiscordConfigurationError` instead of being retried as delivery failures.
170
- - Caller-visible `DiscordTransportError` messages omit raw upstream response bodies by default.
171
172
 
172
173
  ### Intentional limitations
173
174
 
@@ -184,7 +185,10 @@ These limitations are part of the package contract so runtime choice, provider c
184
185
 
185
186
  ### Core
186
187
 
188
+ - `Discord`
187
189
  - `DiscordModule.forRoot(options)` / `DiscordModule.forRootAsync(options)`
190
+ - `DiscordModuleOptions`
191
+ - `DiscordAsyncModuleOptions`
188
192
  - `DiscordService`
189
193
  - `DiscordChannel`
190
194
  - `DISCORD`
@@ -196,11 +200,11 @@ Compose applications through `DiscordModule` and integrate notifications through
196
200
 
197
201
  - `DiscordMessage`
198
202
  - `NormalizedDiscordMessage`
199
- - `DiscordAsyncModuleOptions`
200
203
  - `DiscordWebhookTransportOptions`
201
204
  - `DiscordFetchLike`
202
205
  - `DiscordFetchResponse`
203
206
  - `DiscordSendResult`
207
+ - `DiscordSendOptions`
204
208
  - `DiscordSendManyOptions`
205
209
  - `DiscordSendBatchResult`
206
210
  - `DiscordSendFailure`
@@ -212,7 +216,9 @@ Compose applications through `DiscordModule` and integrate notifications through
212
216
  - `DiscordEmbed`
213
217
  - `DiscordPoll`
214
218
  - `DiscordTransport`
219
+ - `DiscordTransportContext`
215
220
  - `DiscordTransportFactory`
221
+ - `DiscordTransportReceipt`
216
222
  - `DiscordTemplateRenderInput`
217
223
  - `DiscordTemplateRenderResult`
218
224
  - `DiscordTemplateRenderer`
@@ -222,6 +228,8 @@ Compose applications through `DiscordModule` and integrate notifications through
222
228
 
223
229
  - `createDiscordPlatformStatusSnapshot(...)`
224
230
  - `DiscordLifecycleState`
231
+ - `DiscordPlatformStatusSnapshot`
232
+ - `DiscordStatusAdapterInput`
225
233
  - `DiscordConfigurationError`
226
234
  - `DiscordMessageValidationError`
227
235
  - `DiscordTransportError`
@@ -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,EACV,OAAO,EACP,cAAc,EACd,kCAAkC,EAClC,sBAAsB,EAEtB,sBAAsB,EACtB,kBAAkB,EAClB,iBAAiB,EAIjB,8BAA8B,EAC/B,MAAM,YAAY,CAAC;AAyBpB;;;;;;;GAOG;AACH,qBACa,cAAe,YAAW,OAAO,EAAE,YAAY,EAAE,qBAAqB;IAKrE,OAAO,CAAC,QAAQ,CAAC,OAAO;IAJpC,OAAO,CAAC,cAAc,CAAmF;IACzG,OAAO,CAAC,iBAAiB,CAA+B;IACxD,OAAO,CAAC,gBAAgB,CAAwC;gBAEnC,OAAO,EAAE,8BAA8B;IAE9D,qBAAqB,IAAI,OAAO,CAAC,IAAI,CAAC;IAetC,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;IAiBnC;;;;OAIG;IACH,4BAA4B;IAW5B;;;;;;;;;;;;;;OAcG;IACG,IAAI,CAAC,OAAO,EAAE,cAAc,EAAE,OAAO,GAAE,kBAAuB,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAyBjG;;;;;;;;;;;;OAYG;IACG,QAAQ,CAAC,QAAQ,EAAE,SAAS,cAAc,EAAE,EAAE,OAAO,GAAE,sBAA2B,GAAG,OAAO,CAAC,sBAAsB,CAAC;IA6B1H;;;;;;;;;;;;;;;;OAgBG;IACG,gBAAgB,CACpB,YAAY,EAAE,kCAAkC,EAChD,OAAO,GAAE,kBAAuB,GAC/B,OAAO,CAAC,iBAAiB,CAAC;YAiCf,eAAe;IAe7B,OAAO,CAAC,kBAAkB;IAM1B,OAAO,CAAC,gBAAgB;IAkBxB,OAAO,CAAC,2BAA2B;YAkBrB,kBAAkB;CAejC"}
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,EACV,OAAO,EACP,cAAc,EACd,kCAAkC,EAClC,sBAAsB,EAEtB,sBAAsB,EACtB,kBAAkB,EAClB,iBAAiB,EAIjB,8BAA8B,EAC/B,MAAM,YAAY,CAAC;AAyCpB;;;;;;;GAOG;AACH,qBACa,cAAe,YAAW,OAAO,EAAE,YAAY,EAAE,qBAAqB;IAKrE,OAAO,CAAC,QAAQ,CAAC,OAAO;IAJpC,OAAO,CAAC,cAAc,CAA2C;IACjE,OAAO,CAAC,iBAAiB,CAA+B;IACxD,OAAO,CAAC,gBAAgB,CAAwC;gBAEnC,OAAO,EAAE,8BAA8B;IAE9D,qBAAqB,IAAI,OAAO,CAAC,IAAI,CAAC;IAetC,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;IAiBnC;;;;OAIG;IACH,4BAA4B;IAW5B;;;;;;;;;;;;;;OAcG;IACG,IAAI,CAAC,OAAO,EAAE,cAAc,EAAE,OAAO,GAAE,kBAAuB,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAyBjG;;;;;;;;;;;;OAYG;IACG,QAAQ,CAAC,QAAQ,EAAE,SAAS,cAAc,EAAE,EAAE,OAAO,GAAE,sBAA2B,GAAG,OAAO,CAAC,sBAAsB,CAAC;IA6B1H;;;;;;;;;;;;;;;;OAgBG;IACG,gBAAgB,CACpB,YAAY,EAAE,kCAAkC,EAChD,OAAO,GAAE,kBAAuB,GAC/B,OAAO,CAAC,iBAAiB,CAAC;YAiCf,eAAe;IAe7B,OAAO,CAAC,kBAAkB;IAU1B,OAAO,CAAC,gBAAgB;IAkBxB,OAAO,CAAC,2BAA2B;YAkBrB,kBAAkB;CAejC"}
package/dist/service.js CHANGED
@@ -16,16 +16,22 @@ function createAbortError() {
16
16
  function createStoppedTransportError() {
17
17
  return new DiscordTransportError('Discord transport is shutting down or already stopped.');
18
18
  }
19
+ function createLifecycleReadinessError(lifecycleState) {
20
+ if (lifecycleState === 'failed') {
21
+ return new DiscordTransportError('Discord transport failed to initialize.');
22
+ }
23
+ return new DiscordTransportError('Discord transport is not ready for delivery.');
24
+ }
19
25
  function normalizeOptionalString(value) {
20
26
  const trimmed = value?.trim();
21
27
  return trimmed && trimmed.length > 0 ? trimmed : undefined;
22
28
  }
23
29
  function assertMessageContent(message) {
24
- if (!message.content && message.embeds.length === 0 && message.components.length === 0 && message.attachments.length === 0) {
25
- throw new DiscordMessageValidationError('Discord messages require `content`, `embeds`, `components`, or `attachments` content.');
30
+ if (!message.content && message.embeds.length === 0 && message.components.length === 0 && message.attachments.length === 0 && !message.poll) {
31
+ throw new DiscordMessageValidationError('Discord messages require `content`, `embeds`, `components`, `attachments`, or `poll` content.');
26
32
  }
27
33
  }
28
-
34
+ let _DiscordService;
29
35
  /**
30
36
  * Injectable Discord delivery service for standalone and notifications-backed usage.
31
37
  *
@@ -34,7 +40,6 @@ function assertMessageContent(message) {
34
40
  * explicitly injected {@link DiscordTransport} contracts, and translates
35
41
  * `@fluojs/notifications` envelopes into concrete Discord messages.
36
42
  */
37
- let _DiscordService;
38
43
  class DiscordService {
39
44
  static {
40
45
  [_DiscordService, _initClass] = _applyDecs(this, [Inject(DISCORD_OPTIONS)], []).c;
@@ -230,6 +235,9 @@ class DiscordService {
230
235
  if (this.lifecycleState === 'stopping' || this.lifecycleState === 'stopped') {
231
236
  throw createStoppedTransportError();
232
237
  }
238
+ if (this.lifecycleState !== 'ready') {
239
+ throw createLifecycleReadinessError(this.lifecycleState);
240
+ }
233
241
  }
234
242
  normalizeMessage(message) {
235
243
  return {
package/package.json CHANGED
@@ -9,7 +9,7 @@
9
9
  "portable",
10
10
  "fetch"
11
11
  ],
12
- "version": "1.0.0",
12
+ "version": "1.0.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.0",
40
- "@fluojs/di": "^1.0.0",
39
+ "@fluojs/core": "^1.0.2",
40
+ "@fluojs/di": "^1.0.2",
41
41
  "@fluojs/notifications": "^1.0.0",
42
- "@fluojs/runtime": "^1.0.0"
42
+ "@fluojs/runtime": "^1.1.0"
43
43
  },
44
44
  "devDependencies": {
45
45
  "vitest": "^3.2.4"