/** * Namespaced callback-data registry. * * gramio's `CallbackData` schemas are dispatched by name (hashed to a * 6-char prefix on the wire). When multiple plugins each declare their * own short schema names (`payWcs`, `acA`, `mNav`, …) two real risks * accumulate: * * 1. **Cross-plugin name collision.** A future plugin picks a name * another plugin already uses and gramio dispatches to the wrong * handler. Silent. * * 2. **Drift in name shape.** Each plugin invents its own * abbreviation style. `payWcs` vs `pay_w_consent` vs * `payments:waiver:consent` — no convention. * * `callbackNs(prefix)` solves both: * * - Reserves a prefix per plugin (`pay`, `ac`, `m`, …) so names * can't collide across plugins by construction (`pay:wcs` is * disjoint from `ac:wcs`). * * - Maintains a process-wide `Set` of registered fully- * qualified names. A second registration of the same name with * conflicting field shape throws at construction (loud + early); * an identical re-registration is idempotent (HMR / dual-import * safe). * * The encoded callback_data length is unaffected — gramio hashes the * full name to a 6-char prefix regardless of how long the name is. So * `pay:waiver:consent` packs as compactly as `pwc`. * * ## Usage * * ```ts * // src/bot/payments/waiver.ts * import { callbackNs } from "../callbacks.js"; * * const cb = callbackNs("pay"); * * export const waiverConsent = cb.data("waiver:consent", { pk: "string" }); * export const waiverCancel = cb.data("waiver:cancel", {}); * * // usage matches gramio's CallbackData verbatim — same .pack / .unpack: * waiverConsent.pack({ pk: "vip.1" }) * bot.callbackQuery(waiverConsent, (ctx) => { ctx.queryData.pk }) * ``` */ import { CallbackData } from "gramio"; type FieldType = "string" | "number" | "string?" | "number?"; type FieldDef = Readonly>; type RequiredFieldKeys = { [K in keyof F]: F[K] extends "string" | "number" ? K : never; }[keyof F]; type FieldBase = T extends `string${string}` ? string : number; type SchemaOf = { [K in RequiredFieldKeys & string]: FieldBase; } & { [K in Exclude> & string]?: FieldBase; }; type TypedCallbackData = CallbackData, SchemaOf>; export type CallbackNamespace = { readonly prefix: string; /** * Declare a callback schema under this namespace. `fields` is a * field-type map. Suffix a type with `?` to mark optional (e.g. * `{ uid: 'number', v: 'string?' }`). * * Registering the same `fullName` (prefix:name) twice with matching * field shape returns the cached `CallbackData` (idempotent for * HMR / dual-import). A second registration with different fields * panics — that's a programming error, not a runtime issue. */ data: (name: string, fields: F) => TypedCallbackData; }; /** * Reserve a callback-data prefix for a plugin. Returns a namespace * with a `data(name, fields)` factory. * * Prefix must be `[a-z][a-z0-9]*` — lowercased letter + alphanumerics, * no separator chars. Names within a namespace can use `:` for * sub-grouping (`waiver:consent`, `refund:approve`). */ export declare const callbackNs: (prefix: string) => CallbackNamespace; export {}; //# sourceMappingURL=callbacks.d.ts.map