@minesa-org/mini-interaction 0.2.24 → 0.2.26

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.
@@ -7,8 +7,8 @@ import { type ModalSubmitInteraction } from "../utils/ModalSubmitInteraction.js"
7
7
  import { type OAuthConfig, type OAuthTokens, type DiscordUser } from "../oauth/DiscordOAuth.js";
8
8
  /** Configuration parameters for the MiniInteraction client. */
9
9
  export type InteractionClientOptions = {
10
- applicationId: string;
11
- publicKey: string;
10
+ applicationId?: string;
11
+ publicKey?: string;
12
12
  commandsDirectory?: string | false;
13
13
  componentsDirectory?: string | false;
14
14
  utilsDirectory?: string | false;
@@ -190,6 +190,8 @@ export declare class MiniInteraction {
190
190
  private loadComponentsPromise;
191
191
  private registerCommandsPromise;
192
192
  private registerCommandsSignature;
193
+ private vercelWaitUntil;
194
+ private searchedForVercel;
193
195
  /**
194
196
  * Creates a new MiniInteraction client with optional command auto-loading and custom runtime hooks.
195
197
  */
@@ -208,6 +210,10 @@ export declare class MiniInteraction {
208
210
  * Call this periodically to clean up old interaction data.
209
211
  */
210
212
  cleanupExpiredInteractions(): number;
213
+ /**
214
+ * Attempt to find a waitUntil implementation in the environment (e.g. Vercel or Cloudflare).
215
+ */
216
+ private getAutoWaitUntil;
211
217
  private normalizeCommandData;
212
218
  private registerCommand;
213
219
  /**
@@ -286,7 +292,9 @@ export declare class MiniInteraction {
286
292
  * Creates a Node.js style request handler compatible with Express, Next.js API routes,
287
293
  * Vercel serverless functions, and any runtime that expects a `(req, res)` listener.
288
294
  */
289
- createNodeHandler(): InteractionNodeHandler;
295
+ createNodeHandler(options?: {
296
+ waitUntil?: (promise: Promise<void>) => void;
297
+ }): InteractionNodeHandler;
290
298
  /**
291
299
  * Generates a lightweight verification handler that serves an HTML page with an embedded OAuth link.
292
300
  *
@@ -340,7 +348,13 @@ export declare class MiniInteraction {
340
348
  /**
341
349
  * Creates a Fetch API compatible handler for runtimes like Workers or Deno.
342
350
  */
343
- createFetchHandler(): InteractionFetchHandler;
351
+ /**
352
+ * Generates a Fetch-standard request handler compatible with Cloudflare Workers,
353
+ * Bun, Deno, and Next.js Edge Runtime.
354
+ */
355
+ createFetchHandler(options?: {
356
+ waitUntil?: (promise: Promise<void>) => void;
357
+ }): InteractionFetchHandler;
344
358
  /**
345
359
  * Checks if the provided directory path exists on disk.
346
360
  */
@@ -43,22 +43,26 @@ export class MiniInteraction {
43
43
  loadComponentsPromise = null;
44
44
  registerCommandsPromise = null;
45
45
  registerCommandsSignature = null;
46
+ vercelWaitUntil = null;
47
+ searchedForVercel = false;
46
48
  /**
47
49
  * Creates a new MiniInteraction client with optional command auto-loading and custom runtime hooks.
48
50
  */
49
51
  constructor({ applicationId, publicKey, commandsDirectory, componentsDirectory, utilsDirectory, fetchImplementation, verifyKeyImplementation, timeoutConfig, }) {
50
- if (!applicationId) {
51
- throw new Error("[MiniInteraction] applicationId is required");
52
+ const resolvedAppId = applicationId ?? (typeof process !== "undefined" ? process.env.DISCORD_APPLICATION_ID : undefined);
53
+ const resolvedPublicKey = publicKey ?? (typeof process !== "undefined" ? process.env.DISCORD_PUBLIC_KEY : undefined);
54
+ if (!resolvedAppId) {
55
+ throw new Error("[MiniInteraction] applicationId is required (or DISCORD_APPLICATION_ID env var)");
52
56
  }
53
- if (!publicKey) {
54
- throw new Error("[MiniInteraction] publicKey is required");
57
+ if (!resolvedPublicKey) {
58
+ throw new Error("[MiniInteraction] publicKey is required (or DISCORD_PUBLIC_KEY env var)");
55
59
  }
56
60
  const fetchImpl = fetchImplementation ?? globalThis.fetch;
57
61
  if (typeof fetchImpl !== "function") {
58
62
  throw new Error("[MiniInteraction] fetch is not available. Provide a global fetch implementation.");
59
63
  }
60
- this.applicationId = applicationId;
61
- this.publicKey = publicKey;
64
+ this.applicationId = resolvedAppId;
65
+ this.publicKey = resolvedPublicKey;
62
66
  this.fetchImpl = fetchImpl;
63
67
  this.verifyKeyImpl = verifyKeyImplementation ?? verifyKey;
64
68
  this.commandsDirectory =
@@ -129,6 +133,33 @@ export class MiniInteraction {
129
133
  }
130
134
  return cleaned;
131
135
  }
136
+ /**
137
+ * Attempt to find a waitUntil implementation in the environment (e.g. Vercel or Cloudflare).
138
+ */
139
+ async getAutoWaitUntil() {
140
+ if (this.searchedForVercel)
141
+ return this.vercelWaitUntil;
142
+ this.searchedForVercel = true;
143
+ // Try Vercel's @vercel/functions
144
+ try {
145
+ // @ts-ignore - Dynamic import to avoid hard dependency or build errors in non-vercel environments
146
+ const { waitUntil } = await import("@vercel/functions");
147
+ if (typeof waitUntil === "function") {
148
+ this.vercelWaitUntil = waitUntil;
149
+ return waitUntil;
150
+ }
151
+ }
152
+ catch {
153
+ // Ignore if not found
154
+ }
155
+ // Try globalThis.waitUntil (some edge runtimes)
156
+ // @ts-ignore
157
+ if (typeof globalThis.waitUntil === "function") {
158
+ // @ts-ignore
159
+ return globalThis.waitUntil;
160
+ }
161
+ return null;
162
+ }
132
163
  normalizeCommandData(data) {
133
164
  if (typeof data === "object" && data !== null) {
134
165
  return resolveJSONEncodable(data);
@@ -471,7 +502,8 @@ export class MiniInteraction {
471
502
  * Creates a Node.js style request handler compatible with Express, Next.js API routes,
472
503
  * Vercel serverless functions, and any runtime that expects a `(req, res)` listener.
473
504
  */
474
- createNodeHandler() {
505
+ createNodeHandler(options) {
506
+ const { waitUntil } = options ?? {};
475
507
  return (request, response) => {
476
508
  if (request.method !== "POST") {
477
509
  response.statusCode = 405;
@@ -508,6 +540,12 @@ export class MiniInteraction {
508
540
  signature,
509
541
  timestamp,
510
542
  });
543
+ if (result.backgroundWork) {
544
+ const resolvedWaitUntil = waitUntil ?? await this.getAutoWaitUntil();
545
+ if (resolvedWaitUntil) {
546
+ resolvedWaitUntil(result.backgroundWork);
547
+ }
548
+ }
511
549
  response.statusCode = result.status;
512
550
  response.setHeader("content-type", "application/json");
513
551
  response.end(JSON.stringify(result.body));
@@ -756,7 +794,12 @@ export class MiniInteraction {
756
794
  /**
757
795
  * Creates a Fetch API compatible handler for runtimes like Workers or Deno.
758
796
  */
759
- createFetchHandler() {
797
+ /**
798
+ * Generates a Fetch-standard request handler compatible with Cloudflare Workers,
799
+ * Bun, Deno, and Next.js Edge Runtime.
800
+ */
801
+ createFetchHandler(options) {
802
+ const { waitUntil } = options ?? {};
760
803
  return async (request) => {
761
804
  if (request.method !== "POST") {
762
805
  return new Response(JSON.stringify({
@@ -776,6 +819,12 @@ export class MiniInteraction {
776
819
  signature,
777
820
  timestamp,
778
821
  });
822
+ if (result.backgroundWork) {
823
+ const resolvedWaitUntil = waitUntil ?? await this.getAutoWaitUntil();
824
+ if (resolvedWaitUntil) {
825
+ resolvedWaitUntil(result.backgroundWork);
826
+ }
827
+ }
779
828
  return new Response(JSON.stringify(result.body), {
780
829
  status: result.status,
781
830
  headers: { "content-type": "application/json" },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@minesa-org/mini-interaction",
3
- "version": "0.2.24",
3
+ "version": "0.2.26",
4
4
  "description": "Mini interaction, connecting your app with Discord via HTTP-interaction (Vercel support).",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",