@gramio/composer 0.3.1 → 0.3.4
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.md +57 -0
- package/dist/index.cjs +33 -2
- package/dist/index.d.cts +50 -1
- package/dist/index.d.ts +50 -1
- package/dist/index.js +33 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -521,6 +521,63 @@ command<TThis extends ComposerLike<TThis>>(
|
|
|
521
521
|
): TThis
|
|
522
522
|
```
|
|
523
523
|
|
|
524
|
+
#### `EventContextOf<T, E>` — extract context for a specific event (global + per-event derives)
|
|
525
|
+
|
|
526
|
+
Like `ContextOf<T>`, but also includes per-event derives registered via `derive(event, handler)`.
|
|
527
|
+
|
|
528
|
+
| | Includes |
|
|
529
|
+
|---|---|
|
|
530
|
+
| `ContextOf<TThis>` | `TOut` — global derives only |
|
|
531
|
+
| `EventContextOf<TThis, "message">` | `TOut & TDerives["message"]` — global **and** per-event derives |
|
|
532
|
+
|
|
533
|
+
**Why it matters:** when a custom method always routes to a specific event (e.g. `command` → `"message"`), its handler should see per-event derives too. With `ContextOf` alone, a `derive("message", ...)` plugin's types are invisible inside the handler even though the value is there at runtime.
|
|
534
|
+
|
|
535
|
+
```ts
|
|
536
|
+
import { createComposer, defineComposerMethods, eventTypes } from "@gramio/composer";
|
|
537
|
+
import type { ComposerLike, EventContextOf, Middleware } from "@gramio/composer";
|
|
538
|
+
|
|
539
|
+
const methods = defineComposerMethods({
|
|
540
|
+
command<TThis extends ComposerLike<TThis>>(
|
|
541
|
+
this: TThis,
|
|
542
|
+
name: string,
|
|
543
|
+
// ↓ EventContextOf instead of ContextOf
|
|
544
|
+
handler: Middleware<MessageCtx & EventContextOf<TThis, "message">>,
|
|
545
|
+
): TThis {
|
|
546
|
+
return this.on("message", (ctx: any, next: Next) => {
|
|
547
|
+
if (ctx.text === `/${name}`) return handler(ctx, next);
|
|
548
|
+
return next();
|
|
549
|
+
});
|
|
550
|
+
},
|
|
551
|
+
});
|
|
552
|
+
|
|
553
|
+
const { Composer } = createComposer<BaseCtx, { message: MessageCtx }, typeof methods>({
|
|
554
|
+
discriminator: (ctx) => ctx.updateType,
|
|
555
|
+
methods,
|
|
556
|
+
});
|
|
557
|
+
|
|
558
|
+
// Per-event plugin that adds `t` only for message events:
|
|
559
|
+
const i18nPlugin = new Composer({ name: "i18n" })
|
|
560
|
+
.derive("message", (ctx) => ({
|
|
561
|
+
t: i18n.buildT(ctx.from?.languageCode ?? "en"),
|
|
562
|
+
}))
|
|
563
|
+
.as("scoped");
|
|
564
|
+
|
|
565
|
+
new Composer()
|
|
566
|
+
.extend(i18nPlugin)
|
|
567
|
+
.command("start", (ctx, next) => {
|
|
568
|
+
ctx.t("Hello"); // ✅ typed — EventContextOf sees TDerives["message"]
|
|
569
|
+
ctx.text; // ✅ string | undefined — from MessageCtx
|
|
570
|
+
return next();
|
|
571
|
+
})
|
|
572
|
+
.on("message", (ctx, next) => {
|
|
573
|
+
ctx.t("Hi"); // ✅ also works here via ResolveEventCtx
|
|
574
|
+
return next();
|
|
575
|
+
});
|
|
576
|
+
```
|
|
577
|
+
|
|
578
|
+
> [!NOTE]
|
|
579
|
+
> If the derive is registered globally (`.derive(() => ...)` without an event name), both `ContextOf` and `EventContextOf` will see it. Per-event derives (`derive("message", ...)`) are only visible through `EventContextOf` in custom method signatures, or directly inside `.on("message", ...)` handlers.
|
|
580
|
+
|
|
524
581
|
#### `ComposerLike<T>` — minimal structural type for `this` constraints
|
|
525
582
|
|
|
526
583
|
A minimal interface `{ on(event: any, handler: any): T }` used as an F-bounded constraint on `TThis`. Makes `this.on(...)` fully typed and return `TThis` without casts.
|
package/dist/index.cjs
CHANGED
|
@@ -313,7 +313,10 @@ class Composer {
|
|
|
313
313
|
for (const key of preKeys) snapshot[key] = ctx[key];
|
|
314
314
|
await chain(ctx, noopNext);
|
|
315
315
|
for (const key of Object.keys(ctx)) {
|
|
316
|
-
if (!preKeys.has(key))
|
|
316
|
+
if (!preKeys.has(key)) {
|
|
317
|
+
const desc = Object.getOwnPropertyDescriptor(ctx, key);
|
|
318
|
+
if (desc?.configurable) delete ctx[key];
|
|
319
|
+
}
|
|
317
320
|
}
|
|
318
321
|
Object.assign(ctx, snapshot);
|
|
319
322
|
return next();
|
|
@@ -355,7 +358,10 @@ class Composer {
|
|
|
355
358
|
for (const key of preKeys) snapshot[key] = ctx[key];
|
|
356
359
|
await chain(ctx, noopNext);
|
|
357
360
|
for (const key of Object.keys(ctx)) {
|
|
358
|
-
if (!preKeys.has(key))
|
|
361
|
+
if (!preKeys.has(key)) {
|
|
362
|
+
const desc = Object.getOwnPropertyDescriptor(ctx, key);
|
|
363
|
+
if (desc?.configurable) delete ctx[key];
|
|
364
|
+
}
|
|
359
365
|
}
|
|
360
366
|
Object.assign(ctx, snapshot);
|
|
361
367
|
return next();
|
|
@@ -380,6 +386,31 @@ class Composer {
|
|
|
380
386
|
return info;
|
|
381
387
|
});
|
|
382
388
|
}
|
|
389
|
+
/**
|
|
390
|
+
* Returns a Set of all event names registered via `.on()` and event-specific `.derive()`.
|
|
391
|
+
*
|
|
392
|
+
* Useful for introspecting which update types the middleware chain handles,
|
|
393
|
+
* e.g. to auto-derive `allowed_updates` for the Telegram Bot API.
|
|
394
|
+
*
|
|
395
|
+
* @example
|
|
396
|
+
* ```typescript
|
|
397
|
+
* composer.on("message", handler);
|
|
398
|
+
* composer.on(["callback_query", "inline_query"], handler);
|
|
399
|
+
* composer.registeredEvents(); // Set {"message", "callback_query", "inline_query"}
|
|
400
|
+
* ```
|
|
401
|
+
*/
|
|
402
|
+
registeredEvents() {
|
|
403
|
+
const events = /* @__PURE__ */ new Set();
|
|
404
|
+
for (const mw of this["~"].middlewares) {
|
|
405
|
+
if ((mw.type === "on" || mw.type === "derive") && mw.name) {
|
|
406
|
+
for (const part of mw.name.split("|")) {
|
|
407
|
+
const eventPart = part.includes(":") ? part.split(":")[0] : part;
|
|
408
|
+
if (eventPart) events.add(eventPart);
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
return events;
|
|
413
|
+
}
|
|
383
414
|
trace(handler) {
|
|
384
415
|
this["~"].tracer = handler;
|
|
385
416
|
this.invalidate();
|
package/dist/index.d.cts
CHANGED
|
@@ -191,6 +191,20 @@ declare class Composer<TIn extends object = {}, TOut extends TIn = TIn, TExposed
|
|
|
191
191
|
group(fn: (composer: Composer<TOut, TOut, {}>) => void): Composer<TIn, TOut, TExposed>;
|
|
192
192
|
extend<UIn extends object, UOut extends UIn, UExposed extends object, UMacros extends MacroDefinitions = {}>(other: Composer<UIn, UOut, UExposed, UMacros>): Composer<TIn, TOut & UExposed, TExposed, TMacros & UMacros>;
|
|
193
193
|
inspect(): MiddlewareInfo[];
|
|
194
|
+
/**
|
|
195
|
+
* Returns a Set of all event names registered via `.on()` and event-specific `.derive()`.
|
|
196
|
+
*
|
|
197
|
+
* Useful for introspecting which update types the middleware chain handles,
|
|
198
|
+
* e.g. to auto-derive `allowed_updates` for the Telegram Bot API.
|
|
199
|
+
*
|
|
200
|
+
* @example
|
|
201
|
+
* ```typescript
|
|
202
|
+
* composer.on("message", handler);
|
|
203
|
+
* composer.on(["callback_query", "inline_query"], handler);
|
|
204
|
+
* composer.registeredEvents(); // Set {"message", "callback_query", "inline_query"}
|
|
205
|
+
* ```
|
|
206
|
+
*/
|
|
207
|
+
registeredEvents(): Set<string>;
|
|
194
208
|
trace(handler: TraceHandler): this;
|
|
195
209
|
compose(): ComposedMiddleware<TIn>;
|
|
196
210
|
run(context: TIn, next?: Next): Promise<void>;
|
|
@@ -301,6 +315,7 @@ interface EventComposer<TBase extends object, TEventMap extends Record<string, T
|
|
|
301
315
|
/** Register multiple macros at once */
|
|
302
316
|
macro<const TDefs extends Record<string, MacroDef<any, any>>>(definitions: TDefs): EventComposer<TBase, TEventMap, TIn, TOut, TExposed, TDerives, TMethods, TMacros & TDefs> & TMethods;
|
|
303
317
|
inspect(): MiddlewareInfo[];
|
|
318
|
+
registeredEvents(): Set<string>;
|
|
304
319
|
trace(handler: TraceHandler): this;
|
|
305
320
|
compose(): ComposedMiddleware<TIn>;
|
|
306
321
|
run(context: TIn, next?: Next): Promise<void>;
|
|
@@ -379,6 +394,40 @@ type ContextOf<T> = T extends {
|
|
|
379
394
|
Out: infer O;
|
|
380
395
|
};
|
|
381
396
|
} ? O : never;
|
|
397
|
+
/**
|
|
398
|
+
* Extracts the context type for a specific event from an EventComposer instance,
|
|
399
|
+
* combining global `TOut` (like `ContextOf`) **and** per-event `TDerives[E]`.
|
|
400
|
+
*
|
|
401
|
+
* Use this in custom event-specific methods (e.g. `command`, `hears`) instead of
|
|
402
|
+
* `ContextOf<T>` so that handlers registered via `derive(event, handler)` are
|
|
403
|
+
* visible in the handler's type:
|
|
404
|
+
*
|
|
405
|
+
* @example
|
|
406
|
+
* ```ts
|
|
407
|
+
* const methods = defineComposerMethods({
|
|
408
|
+
* command<TThis extends ComposerLike<TThis>>(
|
|
409
|
+
* this: TThis,
|
|
410
|
+
* name: string,
|
|
411
|
+
* handler: Middleware<MsgCtx & EventContextOf<TThis, "message">>,
|
|
412
|
+
* ): TThis {
|
|
413
|
+
* return this.on("message", (ctx, next) => {
|
|
414
|
+
* if (ctx.text === `/${name}`) return handler(ctx, next);
|
|
415
|
+
* return next();
|
|
416
|
+
* });
|
|
417
|
+
* },
|
|
418
|
+
* });
|
|
419
|
+
*
|
|
420
|
+
* new Composer()
|
|
421
|
+
* .derive("message", () => ({ t: (s: string) => s }))
|
|
422
|
+
* .command("start", (ctx) => ctx.t("Hi!")); // ✅ t is visible
|
|
423
|
+
* ```
|
|
424
|
+
*/
|
|
425
|
+
type EventContextOf<T, E extends string> = T extends {
|
|
426
|
+
"~": {
|
|
427
|
+
Out: infer O extends object;
|
|
428
|
+
Derives: infer D extends Record<string, object>;
|
|
429
|
+
};
|
|
430
|
+
} ? O & (E extends keyof D ? D[E] : {}) : never;
|
|
382
431
|
/**
|
|
383
432
|
* Helper to define custom composer methods with full TypeScript inference.
|
|
384
433
|
*
|
|
@@ -466,4 +515,4 @@ declare const skip: Middleware<any>;
|
|
|
466
515
|
declare const stop: Middleware<any>;
|
|
467
516
|
|
|
468
517
|
export { Composer, EventQueue, buildFromOptions, compose, createComposer, defineComposerMethods, eventTypes, noopNext, skip, stop };
|
|
469
|
-
export type { CompatibleEvents, ComposedMiddleware, ComposerLike, ComposerOptions, ContextCallback, ContextOf, DeriveFromOptions, DeriveHandler, ErrorHandler, EventComposer, EventComposerConstructor, HandlerOptions, LazyFactory, MacroDef, MacroDefinitions, MacroDeriveType, MacroHooks, MacroOptionType, MaybeArray, Middleware, MiddlewareInfo, MiddlewareType, Next, RouteBuilder, RouteHandler, Scope, TraceHandler, WithCtx };
|
|
518
|
+
export type { CompatibleEvents, ComposedMiddleware, ComposerLike, ComposerOptions, ContextCallback, ContextOf, DeriveFromOptions, DeriveHandler, ErrorHandler, EventComposer, EventComposerConstructor, EventContextOf, HandlerOptions, LazyFactory, MacroDef, MacroDefinitions, MacroDeriveType, MacroHooks, MacroOptionType, MaybeArray, Middleware, MiddlewareInfo, MiddlewareType, Next, RouteBuilder, RouteHandler, Scope, TraceHandler, WithCtx };
|
package/dist/index.d.ts
CHANGED
|
@@ -191,6 +191,20 @@ declare class Composer<TIn extends object = {}, TOut extends TIn = TIn, TExposed
|
|
|
191
191
|
group(fn: (composer: Composer<TOut, TOut, {}>) => void): Composer<TIn, TOut, TExposed>;
|
|
192
192
|
extend<UIn extends object, UOut extends UIn, UExposed extends object, UMacros extends MacroDefinitions = {}>(other: Composer<UIn, UOut, UExposed, UMacros>): Composer<TIn, TOut & UExposed, TExposed, TMacros & UMacros>;
|
|
193
193
|
inspect(): MiddlewareInfo[];
|
|
194
|
+
/**
|
|
195
|
+
* Returns a Set of all event names registered via `.on()` and event-specific `.derive()`.
|
|
196
|
+
*
|
|
197
|
+
* Useful for introspecting which update types the middleware chain handles,
|
|
198
|
+
* e.g. to auto-derive `allowed_updates` for the Telegram Bot API.
|
|
199
|
+
*
|
|
200
|
+
* @example
|
|
201
|
+
* ```typescript
|
|
202
|
+
* composer.on("message", handler);
|
|
203
|
+
* composer.on(["callback_query", "inline_query"], handler);
|
|
204
|
+
* composer.registeredEvents(); // Set {"message", "callback_query", "inline_query"}
|
|
205
|
+
* ```
|
|
206
|
+
*/
|
|
207
|
+
registeredEvents(): Set<string>;
|
|
194
208
|
trace(handler: TraceHandler): this;
|
|
195
209
|
compose(): ComposedMiddleware<TIn>;
|
|
196
210
|
run(context: TIn, next?: Next): Promise<void>;
|
|
@@ -301,6 +315,7 @@ interface EventComposer<TBase extends object, TEventMap extends Record<string, T
|
|
|
301
315
|
/** Register multiple macros at once */
|
|
302
316
|
macro<const TDefs extends Record<string, MacroDef<any, any>>>(definitions: TDefs): EventComposer<TBase, TEventMap, TIn, TOut, TExposed, TDerives, TMethods, TMacros & TDefs> & TMethods;
|
|
303
317
|
inspect(): MiddlewareInfo[];
|
|
318
|
+
registeredEvents(): Set<string>;
|
|
304
319
|
trace(handler: TraceHandler): this;
|
|
305
320
|
compose(): ComposedMiddleware<TIn>;
|
|
306
321
|
run(context: TIn, next?: Next): Promise<void>;
|
|
@@ -379,6 +394,40 @@ type ContextOf<T> = T extends {
|
|
|
379
394
|
Out: infer O;
|
|
380
395
|
};
|
|
381
396
|
} ? O : never;
|
|
397
|
+
/**
|
|
398
|
+
* Extracts the context type for a specific event from an EventComposer instance,
|
|
399
|
+
* combining global `TOut` (like `ContextOf`) **and** per-event `TDerives[E]`.
|
|
400
|
+
*
|
|
401
|
+
* Use this in custom event-specific methods (e.g. `command`, `hears`) instead of
|
|
402
|
+
* `ContextOf<T>` so that handlers registered via `derive(event, handler)` are
|
|
403
|
+
* visible in the handler's type:
|
|
404
|
+
*
|
|
405
|
+
* @example
|
|
406
|
+
* ```ts
|
|
407
|
+
* const methods = defineComposerMethods({
|
|
408
|
+
* command<TThis extends ComposerLike<TThis>>(
|
|
409
|
+
* this: TThis,
|
|
410
|
+
* name: string,
|
|
411
|
+
* handler: Middleware<MsgCtx & EventContextOf<TThis, "message">>,
|
|
412
|
+
* ): TThis {
|
|
413
|
+
* return this.on("message", (ctx, next) => {
|
|
414
|
+
* if (ctx.text === `/${name}`) return handler(ctx, next);
|
|
415
|
+
* return next();
|
|
416
|
+
* });
|
|
417
|
+
* },
|
|
418
|
+
* });
|
|
419
|
+
*
|
|
420
|
+
* new Composer()
|
|
421
|
+
* .derive("message", () => ({ t: (s: string) => s }))
|
|
422
|
+
* .command("start", (ctx) => ctx.t("Hi!")); // ✅ t is visible
|
|
423
|
+
* ```
|
|
424
|
+
*/
|
|
425
|
+
type EventContextOf<T, E extends string> = T extends {
|
|
426
|
+
"~": {
|
|
427
|
+
Out: infer O extends object;
|
|
428
|
+
Derives: infer D extends Record<string, object>;
|
|
429
|
+
};
|
|
430
|
+
} ? O & (E extends keyof D ? D[E] : {}) : never;
|
|
382
431
|
/**
|
|
383
432
|
* Helper to define custom composer methods with full TypeScript inference.
|
|
384
433
|
*
|
|
@@ -466,4 +515,4 @@ declare const skip: Middleware<any>;
|
|
|
466
515
|
declare const stop: Middleware<any>;
|
|
467
516
|
|
|
468
517
|
export { Composer, EventQueue, buildFromOptions, compose, createComposer, defineComposerMethods, eventTypes, noopNext, skip, stop };
|
|
469
|
-
export type { CompatibleEvents, ComposedMiddleware, ComposerLike, ComposerOptions, ContextCallback, ContextOf, DeriveFromOptions, DeriveHandler, ErrorHandler, EventComposer, EventComposerConstructor, HandlerOptions, LazyFactory, MacroDef, MacroDefinitions, MacroDeriveType, MacroHooks, MacroOptionType, MaybeArray, Middleware, MiddlewareInfo, MiddlewareType, Next, RouteBuilder, RouteHandler, Scope, TraceHandler, WithCtx };
|
|
518
|
+
export type { CompatibleEvents, ComposedMiddleware, ComposerLike, ComposerOptions, ContextCallback, ContextOf, DeriveFromOptions, DeriveHandler, ErrorHandler, EventComposer, EventComposerConstructor, EventContextOf, HandlerOptions, LazyFactory, MacroDef, MacroDefinitions, MacroDeriveType, MacroHooks, MacroOptionType, MaybeArray, Middleware, MiddlewareInfo, MiddlewareType, Next, RouteBuilder, RouteHandler, Scope, TraceHandler, WithCtx };
|
package/dist/index.js
CHANGED
|
@@ -310,7 +310,10 @@ class Composer {
|
|
|
310
310
|
for (const key of preKeys) snapshot[key] = ctx[key];
|
|
311
311
|
await chain(ctx, noopNext);
|
|
312
312
|
for (const key of Object.keys(ctx)) {
|
|
313
|
-
if (!preKeys.has(key))
|
|
313
|
+
if (!preKeys.has(key)) {
|
|
314
|
+
const desc = Object.getOwnPropertyDescriptor(ctx, key);
|
|
315
|
+
if (desc?.configurable) delete ctx[key];
|
|
316
|
+
}
|
|
314
317
|
}
|
|
315
318
|
Object.assign(ctx, snapshot);
|
|
316
319
|
return next();
|
|
@@ -352,7 +355,10 @@ class Composer {
|
|
|
352
355
|
for (const key of preKeys) snapshot[key] = ctx[key];
|
|
353
356
|
await chain(ctx, noopNext);
|
|
354
357
|
for (const key of Object.keys(ctx)) {
|
|
355
|
-
if (!preKeys.has(key))
|
|
358
|
+
if (!preKeys.has(key)) {
|
|
359
|
+
const desc = Object.getOwnPropertyDescriptor(ctx, key);
|
|
360
|
+
if (desc?.configurable) delete ctx[key];
|
|
361
|
+
}
|
|
356
362
|
}
|
|
357
363
|
Object.assign(ctx, snapshot);
|
|
358
364
|
return next();
|
|
@@ -377,6 +383,31 @@ class Composer {
|
|
|
377
383
|
return info;
|
|
378
384
|
});
|
|
379
385
|
}
|
|
386
|
+
/**
|
|
387
|
+
* Returns a Set of all event names registered via `.on()` and event-specific `.derive()`.
|
|
388
|
+
*
|
|
389
|
+
* Useful for introspecting which update types the middleware chain handles,
|
|
390
|
+
* e.g. to auto-derive `allowed_updates` for the Telegram Bot API.
|
|
391
|
+
*
|
|
392
|
+
* @example
|
|
393
|
+
* ```typescript
|
|
394
|
+
* composer.on("message", handler);
|
|
395
|
+
* composer.on(["callback_query", "inline_query"], handler);
|
|
396
|
+
* composer.registeredEvents(); // Set {"message", "callback_query", "inline_query"}
|
|
397
|
+
* ```
|
|
398
|
+
*/
|
|
399
|
+
registeredEvents() {
|
|
400
|
+
const events = /* @__PURE__ */ new Set();
|
|
401
|
+
for (const mw of this["~"].middlewares) {
|
|
402
|
+
if ((mw.type === "on" || mw.type === "derive") && mw.name) {
|
|
403
|
+
for (const part of mw.name.split("|")) {
|
|
404
|
+
const eventPart = part.includes(":") ? part.split(":")[0] : part;
|
|
405
|
+
if (eventPart) events.add(eventPart);
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
return events;
|
|
410
|
+
}
|
|
380
411
|
trace(handler) {
|
|
381
412
|
this["~"].tracer = handler;
|
|
382
413
|
this.invalidate();
|