@minesa-org/mini-interaction 0.2.23 → 0.2.24

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.
@@ -37,6 +37,25 @@ export type InteractionHandlerResult = {
37
37
  body: APIInteractionResponse | {
38
38
  error: string;
39
39
  };
40
+ /**
41
+ * Promise that resolves when all background work (like editReply) completes.
42
+ * Pass this to Vercel's waitUntil() to prevent premature termination.
43
+ *
44
+ * @example
45
+ * ```typescript
46
+ * // In Next.js App Router
47
+ * import { waitUntil } from '@vercel/functions';
48
+ *
49
+ * export async function POST(request: Request) {
50
+ * const result = await client.handleRequest({ ... });
51
+ * if (result.backgroundWork) {
52
+ * waitUntil(result.backgroundWork);
53
+ * }
54
+ * return Response.json(result.body, { status: result.status });
55
+ * }
56
+ * ```
57
+ */
58
+ backgroundWork?: Promise<void>;
40
59
  };
41
60
  /** Configuration for interaction timeout handling. */
42
61
  export type InteractionTimeoutConfig = {
@@ -1142,10 +1142,11 @@ export class MiniInteraction {
1142
1142
  }
1143
1143
  return resolvedResponse;
1144
1144
  }, this.timeoutConfig.initialResponseTimeout, `Component "${customId}"`, this.timeoutConfig.enableTimeoutWarnings, ackPromise);
1145
- const resolvedResponse = await timeoutWrapper();
1145
+ const { response: resolvedResponse, backgroundWork } = await timeoutWrapper();
1146
1146
  return {
1147
1147
  status: 200,
1148
1148
  body: resolvedResponse,
1149
+ backgroundWork,
1149
1150
  };
1150
1151
  }
1151
1152
  catch (error) {
@@ -1208,10 +1209,11 @@ export class MiniInteraction {
1208
1209
  }
1209
1210
  return resolvedResponse;
1210
1211
  }, this.timeoutConfig.initialResponseTimeout, `Modal "${customId}"`, this.timeoutConfig.enableTimeoutWarnings, ackPromise);
1211
- const resolvedResponse = await timeoutWrapper();
1212
+ const { response: resolvedResponse, backgroundWork } = await timeoutWrapper();
1212
1213
  return {
1213
1214
  status: 200,
1214
1215
  body: resolvedResponse,
1216
+ backgroundWork,
1215
1217
  };
1216
1218
  }
1217
1219
  catch (error) {
@@ -1324,7 +1326,7 @@ export class MiniInteraction {
1324
1326
  }
1325
1327
  return resolvedResponse;
1326
1328
  }, this.timeoutConfig.initialResponseTimeout, `Command "${commandName}"`, this.timeoutConfig.enableTimeoutWarnings, ackPromise);
1327
- const finalResponse = await timeoutWrapper();
1329
+ const { response: finalResponse, backgroundWork } = await timeoutWrapper();
1328
1330
  if (this.timeoutConfig.enableResponseDebugLogging) {
1329
1331
  console.log(`[MiniInteraction] handleApplicationCommand: initial response determined (type=${finalResponse?.type})`);
1330
1332
  }
@@ -1344,6 +1346,7 @@ export class MiniInteraction {
1344
1346
  return {
1345
1347
  status: 200,
1346
1348
  body: finalResponse,
1349
+ backgroundWork,
1347
1350
  };
1348
1351
  }
1349
1352
  catch (error) {
@@ -1607,12 +1610,16 @@ function createTimeoutWrapper(handler, timeoutMs, handlerName, enableWarnings =
1607
1610
  });
1608
1611
  // Start handler execution immediately (don't await yet)
1609
1612
  const handlerPromise = Promise.resolve(handler(...args));
1613
+ // Attach a default error handler to prevent unhandled rejections
1614
+ const backgroundWork = handlerPromise.catch((error) => {
1615
+ console.error(`[MiniInteraction] ${handlerName} background execution failed:`, error instanceof Error ? error.message : String(error));
1616
+ }).then(() => {
1617
+ // Ensure it always resolves to void
1618
+ });
1610
1619
  // If we have an ackPromise, race between ACK and timeout
1611
- // When ACK is received, return IMMEDIATELY so Discord gets the response
1612
- // Handler continues in background
1613
1620
  if (ackPromise) {
1614
1621
  try {
1615
- const ackResult = await Promise.race([
1622
+ const response = await Promise.race([
1616
1623
  ackPromise,
1617
1624
  timeoutPromise,
1618
1625
  ]);
@@ -1620,11 +1627,7 @@ function createTimeoutWrapper(handler, timeoutMs, handlerName, enableWarnings =
1620
1627
  if (timeoutId) {
1621
1628
  clearTimeout(timeoutId);
1622
1629
  }
1623
- // Handler continues in background - attach error handler
1624
- handlerPromise.catch((error) => {
1625
- console.error(`[MiniInteraction] ${handlerName} background execution failed:`, error instanceof Error ? error.message : String(error));
1626
- });
1627
- return ackResult;
1630
+ return { response, backgroundWork };
1628
1631
  }
1629
1632
  catch (error) {
1630
1633
  // Timeout occurred before ACK - fall through to check handler
@@ -1636,7 +1639,7 @@ function createTimeoutWrapper(handler, timeoutMs, handlerName, enableWarnings =
1636
1639
  }
1637
1640
  // No ACK promise - wait for handler with timeout
1638
1641
  try {
1639
- const handlerResult = await Promise.race([
1642
+ const response = await Promise.race([
1640
1643
  handlerPromise,
1641
1644
  timeoutPromise,
1642
1645
  ]);
@@ -1647,7 +1650,7 @@ function createTimeoutWrapper(handler, timeoutMs, handlerName, enableWarnings =
1647
1650
  if (enableWarnings && elapsed > timeoutMs * 0.8) {
1648
1651
  console.warn(`[MiniInteraction] ${handlerName} completed in ${elapsed}ms (${Math.round((elapsed / timeoutMs) * 100)}% of timeout limit)`);
1649
1652
  }
1650
- return handlerResult;
1653
+ return { response, backgroundWork };
1651
1654
  }
1652
1655
  catch (error) {
1653
1656
  if (timeoutId) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@minesa-org/mini-interaction",
3
- "version": "0.2.23",
3
+ "version": "0.2.24",
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",