🚀 Socket Launch Week Day 5:Introducing Repository Access Permissions and Custom Roles.Learn more
Sign In

@fluojs/discord

Package Overview
Dependencies
Maintainers
1
Versions
8
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@fluojs/discord - npm Package Compare versions

Comparing version
1.0.3
to
1.0.4
+2
-0
dist/service.d.ts

@@ -15,5 +15,7 @@ import type { OnApplicationShutdown, OnModuleInit } from '@fluojs/runtime';

private resolvedTransport;
private shutdownPromise;
private transportPromise;
constructor(options: NormalizedDiscordModuleOptions);
onApplicationShutdown(): Promise<void>;
private closeOwnedTransport;
onModuleInit(): Promise<void>;

@@ -20,0 +22,0 @@ /**

+1
-1

@@ -1,1 +0,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"}
{"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;AA+CpB;;;;;;;GAOG;AACH,qBACa,cAAe,YAAW,OAAO,EAAE,YAAY,EAAE,qBAAqB;IAMrE,OAAO,CAAC,QAAQ,CAAC,OAAO;IALpC,OAAO,CAAC,cAAc,CAA2C;IACjE,OAAO,CAAC,iBAAiB,CAA+B;IACxD,OAAO,CAAC,eAAe,CAA4B;IACnD,OAAO,CAAC,gBAAgB,CAAwC;gBAEnC,OAAO,EAAE,8BAA8B;IAE9D,qBAAqB,IAAI,OAAO,CAAC,IAAI,CAAC;YAgB9B,mBAAmB;IAe3B,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;IAiCnC;;;;OAIG;IACH,4BAA4B;IAW5B;;;;;;;;;;;;;;OAcG;IACG,IAAI,CAAC,OAAO,EAAE,cAAc,EAAE,OAAO,GAAE,kBAAuB,GAAG,OAAO,CAAC,iBAAiB,CAAC;IA0BjG;;;;;;;;;;;;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;IAuB7B,OAAO,CAAC,kBAAkB;IAU1B,OAAO,CAAC,gBAAgB;IAkBxB,OAAO,CAAC,2BAA2B;YAkBrB,kBAAkB;CAejC"}

@@ -25,2 +25,5 @@ let _initClass;

}
function isShutdownLifecycleState(state) {
return state === 'stopping' || state === 'stopped';
}
function normalizeOptionalString(value) {

@@ -50,2 +53,3 @@ const trimmed = value?.trim();

resolvedTransport;
shutdownPromise;
transportPromise;

@@ -56,6 +60,17 @@ constructor(options) {

async onApplicationShutdown() {
if (this.lifecycleState === 'stopped') {
return;
}
if (this.shutdownPromise) {
return this.shutdownPromise;
}
this.lifecycleState = 'stopping';
this.shutdownPromise = this.closeOwnedTransport();
return this.shutdownPromise;
}
async closeOwnedTransport() {
try {
if (this.resolvedTransport && this.options.transport.ownsResources && this.resolvedTransport.close) {
await this.resolvedTransport.close();
const transport = this.resolvedTransport ?? (this.transportPromise ? await this.transportPromise : undefined);
if (transport && this.options.transport.ownsResources && transport.close) {
await transport.close();
}

@@ -71,10 +86,22 @@ this.lifecycleState = 'stopped';

async onModuleInit() {
if (isShutdownLifecycleState(this.lifecycleState)) {
return;
}
this.lifecycleState = 'starting';
try {
const transport = await this.ensureTransport();
if (this.lifecycleState !== 'starting') {
return;
}
if (this.options.verifyOnModuleInit && transport.verify) {
await transport.verify();
}
if (this.lifecycleState !== 'starting') {
return;
}
this.lifecycleState = 'ready';
} catch (error) {
if (isShutdownLifecycleState(this.lifecycleState)) {
throw error;
}
this.lifecycleState = 'failed';

@@ -124,2 +151,3 @@ throw new Error('Discord transport failed to initialize.', {

const transport = await this.ensureTransport();
this.assertReadyForSend();
const normalized = this.normalizeMessage(message);

@@ -228,2 +256,8 @@ assertMessageContent(normalized);

async ensureTransport() {
if (this.lifecycleState === 'stopping' || this.lifecycleState === 'stopped') {
throw createStoppedTransportError();
}
if (this.lifecycleState === 'failed') {
throw createLifecycleReadinessError(this.lifecycleState);
}
if (this.resolvedTransport) {

@@ -230,0 +264,0 @@ return this.resolvedTransport;

@@ -12,3 +12,3 @@ {

],
"version": "1.0.3",
"version": "1.0.4",
"private": false,

@@ -41,5 +41,5 @@ "license": "MIT",

"@fluojs/core": "^1.0.3",
"@fluojs/notifications": "^1.0.1",
"@fluojs/runtime": "^1.1.1",
"@fluojs/di": "^1.0.3"
"@fluojs/di": "^1.1.0",
"@fluojs/notifications": "^1.0.2",
"@fluojs/runtime": "^1.1.8"
},

@@ -46,0 +46,0 @@ "devDependencies": {

@@ -7,2 +7,4 @@ # @fluojs/discord

마이그레이션 경계: 이 모듈 API는 의도적으로 Nest-like이지만 NestJS dynamic-module clone은 아닙니다. `DiscordModule`은 `global: options.global ?? true`로 기본 global이며, `forRootAsync(...)`는 `inject`와 `useFactory`만 지원하고, 내부 provider helper/token은 private으로 유지되어 애플리케이션은 module facade와 export된 service/channel token으로 Discord를 조합해야 합니다.
## 목차

@@ -96,9 +98,13 @@

`forRootAsync(...)`는 fluo async 형태만 받습니다. 필요한 의존성은 애플리케이션 module graph에 먼저 등록하고, token을 `inject`에 나열한 뒤, `useFactory`에서 최종 `DiscordModuleOptions`를 반환하세요. NestJS `imports`, `useClass`, `useExisting` 변형은 소비하지 않으므로 그런 패턴은 Discord에 option을 넘기기 전에 application-owned provider로 옮겨야 합니다.
Behavioral contract 메모:
- `DiscordModule.forRoot(...)`와 `DiscordModule.forRootAsync(...)`는 `DiscordService`, `DiscordChannel`, `DISCORD`, `DISCORD_CHANNEL`을 기본 global로 export합니다. fluo 옵션인 `global?: boolean`을 사용하고, migrated code가 Discord provider를 importing module 안에만 유지해야 할 때만 `global: false`를 설정하세요. NestJS `isGlobal`은 지원하지 않습니다.
- `DiscordService.send(...)`는 전달 전에 `defaultThreadId`를 해석합니다.
- `DiscordService.sendMany(...)`는 `DiscordMessage[]`를 직접 순차 전송하는 batch API이며 `continueOnError`를 지원합니다. 이는 multi-recipient `@fluojs/notifications` dispatch shortcut이 아닙니다.
- 서비스는 모듈 bootstrap 시 transport를 초기화하고, factory가 소유한 리소스만 애플리케이션 shutdown 시 닫습니다.
- 서비스는 모듈 bootstrap 시 transport를 초기화하고, shutdown 전에 시작된 factory 생성 transport가 아직 완료되지 않았더라도 이를 기다린 뒤 factory가 소유한 리소스를 애플리케이션 shutdown 시 닫습니다.
- send는 bootstrap이 transport를 `ready`로 표시한 뒤에만 허용됩니다. bootstrap 전, startup 중, bootstrap 실패 후, shutdown 중, shutdown 후 시도는 전달 전에 거부됩니다.
- 서비스가 shutdown 중이거나 이미 stopped 상태라면 cached transport를 재사용하지 않고 send를 거부합니다.
- `DiscordService.createPlatformStatusSnapshot()`은 `createDiscordPlatformStatusSnapshot(...)`과 같은 status 계약을 노출합니다. 여기에는 lifecycle/readiness, health, transport kind와 ownership, 기본 thread 구성, bootstrap verification 상태, notifications channel dependency details가 포함되어, 호출자가 내부 옵션에 접근하지 않고도 Discord wiring을 관찰할 수 있습니다.
- 빈 `defaultThreadId`와 `notifications.channel` 값은 trim 후 무시됩니다. notifications channel은 기본적으로 `discord`입니다.

@@ -183,2 +189,3 @@ - 이 패키지는 절대로 `process.env`를 직접 읽지 않습니다. 모든 설정은 명시적인 옵션 또는 DI를 통해 들어와야 합니다.

- webhook helper와 export된 transport 계약 이상으로 하나의 provider 전략을 강제하는 것
- 애플리케이션 import용 내부 provider helper, normalized option token, 또는 NestJS-style custom provider replacement seam을 노출하는 것
- 하나의 dispatch 호출 안에서 multi-thread fan-out을 자동 변환하는 것

@@ -197,2 +204,6 @@

- `DiscordService`
- `DiscordService.send(message, options)`
- `DiscordService.sendMany(messages, options)`
- `DiscordService.sendNotification(notification, options)`
- `DiscordService.createPlatformStatusSnapshot()`
- `DiscordChannel`

@@ -204,2 +215,4 @@ - `DISCORD`

이 패키지는 `createDiscordProviders(...)`, `DISCORD_OPTIONS`, `NormalizedDiscordModuleOptions`를 public root barrel에 의도적으로 노출하지 않습니다. 기존 migration이 NestJS 내부 provider token이나 custom provider seam을 바꾸고 있었다면 private helper를 import하지 말고 `DiscordModule.forRoot(...)` / `forRootAsync(...)`를 감싸는 app-owned module을 구성하세요.
### 계약과 헬퍼

@@ -235,2 +248,3 @@

- `DiscordService.createPlatformStatusSnapshot()`
- `createDiscordPlatformStatusSnapshot(...)`

@@ -237,0 +251,0 @@ - `DiscordLifecycleState`

@@ -7,2 +7,4 @@ # @fluojs/discord

Migration boundary: the module API is intentionally Nest-like but not a NestJS dynamic-module clone. `DiscordModule` is global by default through `global: options.global ?? true`, `forRootAsync(...)` supports only `inject` plus `useFactory`, and internal provider helpers/tokens stay private so applications compose Discord through the module facade and exported service/channel tokens.
## Table of Contents

@@ -96,9 +98,13 @@

`forRootAsync(...)` accepts the fluo async shape only: register dependencies elsewhere in the application graph, list their tokens in `inject`, and return final `DiscordModuleOptions` from `useFactory`. It does not consume NestJS `imports`, `useClass`, or `useExisting` variants, so migrate those patterns to application-owned providers before passing resolved options to Discord.
Behavioral contract notes:
- `DiscordModule.forRoot(...)` and `DiscordModule.forRootAsync(...)` export `DiscordService`, `DiscordChannel`, `DISCORD`, and `DISCORD_CHANNEL` globally by default. Use the fluo `global?: boolean` option and set `global: false` only when migrated code must keep Discord providers local to importing modules; NestJS `isGlobal` is not supported.
- `DiscordService.send(...)` resolves `defaultThreadId` before delivery.
- `DiscordService.sendMany(...)` is a direct `DiscordMessage[]` batch API that sends messages sequentially and supports `continueOnError`; it is not a multi-recipient `@fluojs/notifications` dispatch shortcut.
- The service initializes the configured transport during module bootstrap and closes factory-owned resources during application shutdown.
- The service initializes the configured transport during module bootstrap and closes factory-owned resources during application shutdown, including any in-flight factory-created transport before shutdown began.
- 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.
- Sends attempted while the service is shutting down or already stopped are rejected before reusing the cached transport.
- `DiscordService.createPlatformStatusSnapshot()` exposes the same status contract as `createDiscordPlatformStatusSnapshot(...)`: lifecycle/readiness, health, transport kind and ownership, default thread configuration, bootstrap verification state, and notifications channel dependency details, so callers can observe Discord wiring without reaching into internal options.
- Blank `defaultThreadId` and `notifications.channel` values are trimmed and ignored; the notifications channel defaults to `discord`.

@@ -183,2 +189,3 @@ - The package never reads `process.env` directly. All configuration must enter through explicit options or DI.

- force one provider strategy beyond the webhook-first helper and exported transport contract
- expose internal provider helpers, normalized option tokens, or NestJS-style custom provider replacement seams for application imports
- translate one notification into multi-thread fan-out inside a single dispatch call

@@ -197,2 +204,6 @@

- `DiscordService`
- `DiscordService.send(message, options)`
- `DiscordService.sendMany(messages, options)`
- `DiscordService.sendNotification(notification, options)`
- `DiscordService.createPlatformStatusSnapshot()`
- `DiscordChannel`

@@ -204,2 +215,4 @@ - `DISCORD`

The package intentionally keeps `createDiscordProviders(...)`, `DISCORD_OPTIONS`, and `NormalizedDiscordModuleOptions` out of the public root barrel. If a migration previously customized NestJS internals or provider tokens, wrap `DiscordModule.forRoot(...)` / `forRootAsync(...)` in an app-owned module instead of importing private helpers.
### Contracts and helpers

@@ -235,2 +248,3 @@

- `DiscordService.createPlatformStatusSnapshot()`
- `createDiscordPlatformStatusSnapshot(...)`

@@ -237,0 +251,0 @@ - `DiscordLifecycleState`