@usequota/nextjs 0.2.0 → 0.3.0

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/dist/server.d.mts CHANGED
@@ -1,93 +1,7 @@
1
- export { Q as QuotaError, a as QuotaInsufficientCreditsError, b as QuotaNotConnectedError, d as QuotaRateLimitError, c as QuotaTokenExpiredError, e as errorFromResponse } from './errors-CmNx3kSz.mjs';
1
+ import { QuotaTokenStorage } from '@usequota/core';
2
+ export { InMemoryTokenStorage, OAuthTokenResponse, QuotaClient, QuotaClientConfig, QuotaError, QuotaInsufficientCreditsError, QuotaNotConnectedError, QuotaRateLimitError, QuotaTokenExpiredError, QuotaTokenStorage, VerifyWebhookOptions, WebhookEvent, createWebhookHandler, errorFromResponse, exchangeCodeForToken, parseSSEStream, parseWebhook, refreshAccessToken, verifyWebhookSignature } from '@usequota/core';
2
3
  import { QuotaUser, CreditPackage } from '@usequota/types';
3
4
 
4
- /**
5
- * @usequota/nextjs - Token Storage Adapter
6
- *
7
- * Defines the interface for pluggable token storage backends.
8
- * The default implementation uses httpOnly cookies, but apps can
9
- * provide their own (e.g., Supabase, Redis, a database).
10
- */
11
- /**
12
- * Pluggable token storage adapter for the Quota SDK.
13
- *
14
- * Implement this interface to store Quota OAuth tokens in your own backend
15
- * (database, Redis, etc.) instead of the default httpOnly cookies.
16
- *
17
- * @example
18
- * ```typescript
19
- * import { QuotaTokenStorage } from '@usequota/nextjs/server';
20
- * import { createClient } from '@supabase/supabase-js';
21
- *
22
- * const supabaseTokenStorage: QuotaTokenStorage = {
23
- * async getTokens(request) {
24
- * const supabase = createClient(...);
25
- * const userId = await getUserId(request);
26
- * const { data } = await supabase
27
- * .from('quota_accounts')
28
- * .select('access_token, refresh_token')
29
- * .eq('user_id', userId)
30
- * .single();
31
- * if (!data) return null;
32
- * return { accessToken: data.access_token, refreshToken: data.refresh_token };
33
- * },
34
- *
35
- * async setTokens(tokens, request) {
36
- * const supabase = createClient(...);
37
- * const userId = await getUserId(request);
38
- * await supabase.from('quota_accounts').upsert({
39
- * user_id: userId,
40
- * access_token: tokens.accessToken,
41
- * refresh_token: tokens.refreshToken,
42
- * });
43
- * },
44
- *
45
- * async deleteTokens(request) {
46
- * const supabase = createClient(...);
47
- * const userId = await getUserId(request);
48
- * await supabase.from('quota_accounts').delete().eq('user_id', userId);
49
- * },
50
- * };
51
- * ```
52
- */
53
- interface QuotaTokenStorage {
54
- /**
55
- * Retrieve stored tokens for the current request's user.
56
- * Return null if no tokens are stored.
57
- */
58
- getTokens(request: Request): Promise<{
59
- accessToken: string;
60
- refreshToken?: string;
61
- } | null>;
62
- /**
63
- * Persist tokens for the current request's user.
64
- * Called after OAuth callback and after token refresh.
65
- *
66
- * For storage backends that modify the Response (like cookies),
67
- * return the modified Response. For backends that don't modify
68
- * the Response (like databases), return void.
69
- */
70
- setTokens(tokens: {
71
- accessToken: string;
72
- refreshToken?: string;
73
- expiresIn?: number;
74
- }, request: Request, response?: Response): Promise<Response | void>;
75
- /**
76
- * Delete all stored tokens for the current request's user.
77
- * Called on disconnect.
78
- *
79
- * For storage backends that modify the Response (like cookies),
80
- * return the modified Response. For backends that don't modify
81
- * the Response (like databases), return void.
82
- */
83
- deleteTokens(request: Request, response?: Response): Promise<Response | void>;
84
- /**
85
- * Get the external user ID for hosted mode.
86
- * Only required if you use hosted storage mode alongside tokenStorage.
87
- */
88
- getExternalUserId?(request: Request): Promise<string | null>;
89
- }
90
-
91
5
  /**
92
6
  * @usequota/nextjs - Route Handler Factory
93
7
  *
@@ -474,4 +388,4 @@ declare function clearQuotaAuth(config?: {
474
388
  cookiePrefix?: string;
475
389
  }): Promise<void>;
476
390
 
477
- export { type QuotaAuthContext, type QuotaRouteHandlerConfig, type QuotaRouteHandlers, type QuotaServerConfig, type QuotaTokenStorage, type WithQuotaAuthConfig, clearQuotaAuth, createQuotaCheckout, createQuotaRouteHandlers, getQuotaPackages, getQuotaUser, requireQuotaAuth, withQuotaAuth };
391
+ export { type QuotaAuthContext, type QuotaRouteHandlerConfig, type QuotaRouteHandlers, type QuotaServerConfig, type WithQuotaAuthConfig, clearQuotaAuth, createQuotaCheckout, createQuotaRouteHandlers, getQuotaPackages, getQuotaUser, requireQuotaAuth, withQuotaAuth };
package/dist/server.d.ts CHANGED
@@ -1,93 +1,7 @@
1
- export { Q as QuotaError, a as QuotaInsufficientCreditsError, b as QuotaNotConnectedError, d as QuotaRateLimitError, c as QuotaTokenExpiredError, e as errorFromResponse } from './errors-CmNx3kSz.js';
1
+ import { QuotaTokenStorage } from '@usequota/core';
2
+ export { InMemoryTokenStorage, OAuthTokenResponse, QuotaClient, QuotaClientConfig, QuotaError, QuotaInsufficientCreditsError, QuotaNotConnectedError, QuotaRateLimitError, QuotaTokenExpiredError, QuotaTokenStorage, VerifyWebhookOptions, WebhookEvent, createWebhookHandler, errorFromResponse, exchangeCodeForToken, parseSSEStream, parseWebhook, refreshAccessToken, verifyWebhookSignature } from '@usequota/core';
2
3
  import { QuotaUser, CreditPackage } from '@usequota/types';
3
4
 
4
- /**
5
- * @usequota/nextjs - Token Storage Adapter
6
- *
7
- * Defines the interface for pluggable token storage backends.
8
- * The default implementation uses httpOnly cookies, but apps can
9
- * provide their own (e.g., Supabase, Redis, a database).
10
- */
11
- /**
12
- * Pluggable token storage adapter for the Quota SDK.
13
- *
14
- * Implement this interface to store Quota OAuth tokens in your own backend
15
- * (database, Redis, etc.) instead of the default httpOnly cookies.
16
- *
17
- * @example
18
- * ```typescript
19
- * import { QuotaTokenStorage } from '@usequota/nextjs/server';
20
- * import { createClient } from '@supabase/supabase-js';
21
- *
22
- * const supabaseTokenStorage: QuotaTokenStorage = {
23
- * async getTokens(request) {
24
- * const supabase = createClient(...);
25
- * const userId = await getUserId(request);
26
- * const { data } = await supabase
27
- * .from('quota_accounts')
28
- * .select('access_token, refresh_token')
29
- * .eq('user_id', userId)
30
- * .single();
31
- * if (!data) return null;
32
- * return { accessToken: data.access_token, refreshToken: data.refresh_token };
33
- * },
34
- *
35
- * async setTokens(tokens, request) {
36
- * const supabase = createClient(...);
37
- * const userId = await getUserId(request);
38
- * await supabase.from('quota_accounts').upsert({
39
- * user_id: userId,
40
- * access_token: tokens.accessToken,
41
- * refresh_token: tokens.refreshToken,
42
- * });
43
- * },
44
- *
45
- * async deleteTokens(request) {
46
- * const supabase = createClient(...);
47
- * const userId = await getUserId(request);
48
- * await supabase.from('quota_accounts').delete().eq('user_id', userId);
49
- * },
50
- * };
51
- * ```
52
- */
53
- interface QuotaTokenStorage {
54
- /**
55
- * Retrieve stored tokens for the current request's user.
56
- * Return null if no tokens are stored.
57
- */
58
- getTokens(request: Request): Promise<{
59
- accessToken: string;
60
- refreshToken?: string;
61
- } | null>;
62
- /**
63
- * Persist tokens for the current request's user.
64
- * Called after OAuth callback and after token refresh.
65
- *
66
- * For storage backends that modify the Response (like cookies),
67
- * return the modified Response. For backends that don't modify
68
- * the Response (like databases), return void.
69
- */
70
- setTokens(tokens: {
71
- accessToken: string;
72
- refreshToken?: string;
73
- expiresIn?: number;
74
- }, request: Request, response?: Response): Promise<Response | void>;
75
- /**
76
- * Delete all stored tokens for the current request's user.
77
- * Called on disconnect.
78
- *
79
- * For storage backends that modify the Response (like cookies),
80
- * return the modified Response. For backends that don't modify
81
- * the Response (like databases), return void.
82
- */
83
- deleteTokens(request: Request, response?: Response): Promise<Response | void>;
84
- /**
85
- * Get the external user ID for hosted mode.
86
- * Only required if you use hosted storage mode alongside tokenStorage.
87
- */
88
- getExternalUserId?(request: Request): Promise<string | null>;
89
- }
90
-
91
5
  /**
92
6
  * @usequota/nextjs - Route Handler Factory
93
7
  *
@@ -474,4 +388,4 @@ declare function clearQuotaAuth(config?: {
474
388
  cookiePrefix?: string;
475
389
  }): Promise<void>;
476
390
 
477
- export { type QuotaAuthContext, type QuotaRouteHandlerConfig, type QuotaRouteHandlers, type QuotaServerConfig, type QuotaTokenStorage, type WithQuotaAuthConfig, clearQuotaAuth, createQuotaCheckout, createQuotaRouteHandlers, getQuotaPackages, getQuotaUser, requireQuotaAuth, withQuotaAuth };
391
+ export { type QuotaAuthContext, type QuotaRouteHandlerConfig, type QuotaRouteHandlers, type QuotaServerConfig, type WithQuotaAuthConfig, clearQuotaAuth, createQuotaCheckout, createQuotaRouteHandlers, getQuotaPackages, getQuotaUser, requireQuotaAuth, withQuotaAuth };
package/dist/server.js CHANGED
@@ -30,169 +30,53 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
30
30
  // src/server.ts
31
31
  var server_exports = {};
32
32
  __export(server_exports, {
33
- QuotaError: () => QuotaError,
34
- QuotaInsufficientCreditsError: () => QuotaInsufficientCreditsError,
35
- QuotaNotConnectedError: () => QuotaNotConnectedError,
36
- QuotaRateLimitError: () => QuotaRateLimitError,
37
- QuotaTokenExpiredError: () => QuotaTokenExpiredError,
33
+ InMemoryTokenStorage: () => import_core10.InMemoryTokenStorage,
34
+ QuotaClient: () => import_core6.QuotaClient,
35
+ QuotaError: () => import_core5.QuotaError,
36
+ QuotaInsufficientCreditsError: () => import_core5.QuotaInsufficientCreditsError,
37
+ QuotaNotConnectedError: () => import_core5.QuotaNotConnectedError,
38
+ QuotaRateLimitError: () => import_core5.QuotaRateLimitError,
39
+ QuotaTokenExpiredError: () => import_core5.QuotaTokenExpiredError,
38
40
  clearQuotaAuth: () => clearQuotaAuth,
39
41
  createQuotaCheckout: () => createQuotaCheckout,
40
42
  createQuotaRouteHandlers: () => createQuotaRouteHandlers,
41
- errorFromResponse: () => errorFromResponse,
43
+ createWebhookHandler: () => import_core9.createWebhookHandler,
44
+ errorFromResponse: () => import_core5.errorFromResponse,
45
+ exchangeCodeForToken: () => import_core8.exchangeCodeForToken,
42
46
  getQuotaPackages: () => getQuotaPackages,
43
47
  getQuotaUser: () => getQuotaUser,
48
+ parseSSEStream: () => import_core7.parseSSEStream,
49
+ parseWebhook: () => import_core9.parseWebhook,
50
+ refreshAccessToken: () => import_core8.refreshAccessToken,
44
51
  requireQuotaAuth: () => requireQuotaAuth,
52
+ verifyWebhookSignature: () => import_core9.verifyWebhookSignature,
45
53
  withQuotaAuth: () => withQuotaAuth
46
54
  });
47
55
  module.exports = __toCommonJS(server_exports);
48
-
49
- // src/errors.ts
50
- var QuotaError = class extends Error {
51
- /** Machine-readable error code */
52
- code;
53
- /** HTTP status code associated with this error */
54
- statusCode;
55
- /** Optional hint for resolving the error */
56
- hint;
57
- constructor(message, code, statusCode, hint) {
58
- super(message);
59
- this.name = "QuotaError";
60
- this.code = code;
61
- this.statusCode = statusCode;
62
- this.hint = hint;
63
- Object.setPrototypeOf(this, new.target.prototype);
64
- }
65
- };
66
- var QuotaInsufficientCreditsError = class extends QuotaError {
67
- /** Current balance (if available) */
68
- balance;
69
- /** Credits required for the operation (if available) */
70
- required;
71
- constructor(message, options) {
72
- super(
73
- message ?? "Insufficient credits to complete this operation",
74
- "insufficient_credits",
75
- 402,
76
- "Purchase more credits or reduce usage"
77
- );
78
- this.name = "QuotaInsufficientCreditsError";
79
- this.balance = options?.balance;
80
- this.required = options?.required;
81
- Object.setPrototypeOf(this, new.target.prototype);
82
- }
83
- };
84
- var QuotaNotConnectedError = class extends QuotaError {
85
- constructor(message) {
86
- super(
87
- message ?? "User has not connected a Quota account",
88
- "not_connected",
89
- 401,
90
- "Connect your Quota account to use this feature"
91
- );
92
- this.name = "QuotaNotConnectedError";
93
- Object.setPrototypeOf(this, new.target.prototype);
94
- }
95
- };
96
- var QuotaTokenExpiredError = class extends QuotaError {
97
- constructor(message) {
98
- super(
99
- message ?? "Quota access token has expired and could not be refreshed",
100
- "token_expired",
101
- 401,
102
- "Reconnect your Quota account"
103
- );
104
- this.name = "QuotaTokenExpiredError";
105
- Object.setPrototypeOf(this, new.target.prototype);
106
- }
107
- };
108
- var QuotaRateLimitError = class extends QuotaError {
109
- /** Seconds until the rate limit resets */
110
- retryAfter;
111
- constructor(message, retryAfter) {
112
- super(
113
- message ?? "Rate limit exceeded",
114
- "rate_limit_exceeded",
115
- 429,
116
- "Wait before retrying"
117
- );
118
- this.name = "QuotaRateLimitError";
119
- this.retryAfter = retryAfter ?? 60;
120
- Object.setPrototypeOf(this, new.target.prototype);
121
- }
122
- };
123
- async function errorFromResponse(response) {
124
- if (response.ok) {
125
- return null;
126
- }
127
- let body;
128
- try {
129
- body = await response.json();
130
- } catch {
131
- }
132
- const message = body?.error?.message ?? response.statusText;
133
- const code = body?.error?.code;
134
- switch (response.status) {
135
- case 402: {
136
- const opts = {};
137
- if (body?.error?.balance !== void 0) opts.balance = body.error.balance;
138
- if (body?.error?.required !== void 0)
139
- opts.required = body.error.required;
140
- return new QuotaInsufficientCreditsError(message, opts);
141
- }
142
- case 429: {
143
- const parsed = parseInt(response.headers.get("retry-after") ?? "60", 10);
144
- const retryAfter = Number.isNaN(parsed) ? 60 : parsed;
145
- return new QuotaRateLimitError(message, retryAfter);
146
- }
147
- case 401: {
148
- if (code === "not_connected") {
149
- return new QuotaNotConnectedError(message);
150
- }
151
- if (code === "token_expired") {
152
- return new QuotaTokenExpiredError(message);
153
- }
154
- return new QuotaTokenExpiredError(message);
155
- }
156
- default:
157
- return new QuotaError(message, code ?? "unknown", response.status);
158
- }
159
- }
56
+ var import_core5 = require("@usequota/core");
57
+ var import_core6 = require("@usequota/core");
58
+ var import_core7 = require("@usequota/core");
59
+ var import_core8 = require("@usequota/core");
60
+ var import_core9 = require("@usequota/core");
61
+ var import_core10 = require("@usequota/core");
160
62
 
161
63
  // src/route-handlers.ts
162
64
  var import_headers = require("next/headers");
163
65
 
164
66
  // src/token-refresh.ts
165
- var FETCH_TIMEOUT_MS = 1e4;
166
- async function refreshAccessTokenWithCredentials(opts) {
67
+ var import_core = require("@usequota/core");
68
+ var import_core2 = require("@usequota/core");
69
+ var import_core3 = require("@usequota/core");
70
+ async function refreshAndPersistTokens(opts) {
71
+ let tokenData;
167
72
  try {
168
- const response = await fetch(`${opts.baseUrl}/oauth/token`, {
169
- method: "POST",
170
- headers: { "Content-Type": "application/json" },
171
- body: JSON.stringify({
172
- grant_type: "refresh_token",
173
- refresh_token: opts.refreshToken,
174
- client_id: opts.clientId,
175
- client_secret: opts.clientSecret
176
- }),
177
- signal: AbortSignal.timeout(FETCH_TIMEOUT_MS)
73
+ tokenData = await (0, import_core.refreshAccessTokenWithCredentials)({
74
+ refreshToken: opts.refreshToken,
75
+ clientId: opts.clientId,
76
+ clientSecret: opts.clientSecret,
77
+ baseUrl: opts.baseUrl
178
78
  });
179
- if (!response.ok) {
180
- return null;
181
- }
182
- return await response.json();
183
- } catch (error) {
184
- console.error("Failed to refresh Quota access token:", error);
185
- return null;
186
- }
187
- }
188
- async function refreshAndPersistTokens(opts) {
189
- const tokenData = await refreshAccessTokenWithCredentials({
190
- refreshToken: opts.refreshToken,
191
- clientId: opts.clientId,
192
- clientSecret: opts.clientSecret,
193
- baseUrl: opts.baseUrl
194
- });
195
- if (!tokenData) {
79
+ } catch {
196
80
  return null;
197
81
  }
198
82
  if (opts.tokenStorage && opts.request) {
@@ -323,7 +207,7 @@ function createQuotaRouteHandlers(config) {
323
207
  method: "POST",
324
208
  headers: { "Content-Type": "application/json" },
325
209
  body: JSON.stringify(tokenBody),
326
- signal: AbortSignal.timeout(FETCH_TIMEOUT_MS)
210
+ signal: AbortSignal.timeout(import_core2.FETCH_TIMEOUT_MS)
327
211
  });
328
212
  if (!tokenResponse.ok) {
329
213
  const redirectUrl2 = new URL(errorRedirect, url.origin);
@@ -368,7 +252,7 @@ function createQuotaRouteHandlers(config) {
368
252
  if (config.callbacks?.onConnect) {
369
253
  const userResponse = await fetch(`${baseUrl}/v1/me`, {
370
254
  headers: { Authorization: `Bearer ${tokenData.access_token}` },
371
- signal: AbortSignal.timeout(FETCH_TIMEOUT_MS)
255
+ signal: AbortSignal.timeout(import_core2.FETCH_TIMEOUT_MS)
372
256
  });
373
257
  if (userResponse.ok) {
374
258
  const user = await userResponse.json();
@@ -422,7 +306,7 @@ function createQuotaRouteHandlers(config) {
422
306
  }
423
307
  const response = await fetch(`${baseUrl}/v1/me`, {
424
308
  headers: { Authorization: `Bearer ${accessToken}` },
425
- signal: AbortSignal.timeout(FETCH_TIMEOUT_MS)
309
+ signal: AbortSignal.timeout(import_core2.FETCH_TIMEOUT_MS)
426
310
  });
427
311
  if (!response.ok) {
428
312
  if (response.status === 401) {
@@ -430,7 +314,7 @@ function createQuotaRouteHandlers(config) {
430
314
  if (refreshed) {
431
315
  const retryResponse = await fetch(`${baseUrl}/v1/me`, {
432
316
  headers: { Authorization: `Bearer ${refreshed}` },
433
- signal: AbortSignal.timeout(FETCH_TIMEOUT_MS)
317
+ signal: AbortSignal.timeout(import_core2.FETCH_TIMEOUT_MS)
434
318
  });
435
319
  if (retryResponse.ok) {
436
320
  const user2 = await retryResponse.json();
@@ -464,7 +348,7 @@ function createQuotaRouteHandlers(config) {
464
348
  async function packages(_request) {
465
349
  try {
466
350
  const response = await fetch(`${baseUrl}/v1/packages`, {
467
- signal: AbortSignal.timeout(FETCH_TIMEOUT_MS)
351
+ signal: AbortSignal.timeout(import_core2.FETCH_TIMEOUT_MS)
468
352
  });
469
353
  if (!response.ok) {
470
354
  return Response.json(
@@ -535,7 +419,7 @@ function createQuotaRouteHandlers(config) {
535
419
  success_url: successUrl,
536
420
  cancel_url: cancelUrl
537
421
  }),
538
- signal: AbortSignal.timeout(FETCH_TIMEOUT_MS)
422
+ signal: AbortSignal.timeout(import_core2.FETCH_TIMEOUT_MS)
539
423
  });
540
424
  if (!response.ok) {
541
425
  return Response.json(
@@ -672,6 +556,7 @@ function createQuotaRouteHandlers(config) {
672
556
 
673
557
  // src/with-quota-auth.ts
674
558
  var import_headers2 = require("next/headers");
559
+ var import_core4 = require("@usequota/core");
675
560
  var DEFAULT_BASE_URL2 = "https://api.usequota.app";
676
561
  var DEFAULT_COOKIE_PREFIX2 = "quota";
677
562
  var DEFAULT_COOKIE_MAX_AGE2 = 60 * 60 * 24 * 7;
@@ -698,7 +583,7 @@ function withQuotaAuth(config, handler) {
698
583
  externalUserId = await config.getExternalUserId(request);
699
584
  }
700
585
  if (!externalUserId) {
701
- throw new QuotaError(
586
+ throw new import_core4.QuotaError(
702
587
  "getExternalUserId is required for hosted storage mode",
703
588
  "configuration_error",
704
589
  500
@@ -710,13 +595,13 @@ function withQuotaAuth(config, handler) {
710
595
  "X-Quota-Client-Secret": config.clientSecret,
711
596
  "X-Quota-User": externalUserId
712
597
  },
713
- signal: AbortSignal.timeout(FETCH_TIMEOUT_MS)
598
+ signal: AbortSignal.timeout(import_core2.FETCH_TIMEOUT_MS)
714
599
  });
715
600
  if (!response.ok) {
716
601
  if (response.status === 401 || response.status === 404) {
717
- throw new QuotaNotConnectedError();
602
+ throw new import_core4.QuotaNotConnectedError();
718
603
  }
719
- throw new QuotaError(
604
+ throw new import_core4.QuotaError(
720
605
  `Failed to fetch user: ${response.statusText}`,
721
606
  "api_error",
722
607
  response.status
@@ -737,15 +622,15 @@ function withQuotaAuth(config, handler) {
737
622
  refreshTokenValue = cookieStore.get(`${cookiePrefix}_refresh_token`)?.value ?? null;
738
623
  }
739
624
  if (!token) {
740
- throw new QuotaNotConnectedError();
625
+ throw new import_core4.QuotaNotConnectedError();
741
626
  }
742
627
  let response = await fetch(`${baseUrl}/v1/me`, {
743
628
  headers: { Authorization: `Bearer ${token}` },
744
- signal: AbortSignal.timeout(FETCH_TIMEOUT_MS)
629
+ signal: AbortSignal.timeout(import_core2.FETCH_TIMEOUT_MS)
745
630
  });
746
631
  if (response.status === 401) {
747
632
  if (!refreshTokenValue) {
748
- throw new QuotaTokenExpiredError();
633
+ throw new import_core4.QuotaTokenExpiredError();
749
634
  }
750
635
  const newAccessToken = await refreshAndPersistTokens({
751
636
  refreshToken: refreshTokenValue,
@@ -781,18 +666,18 @@ function withQuotaAuth(config, handler) {
781
666
  }
782
667
  });
783
668
  if (!newAccessToken) {
784
- throw new QuotaTokenExpiredError();
669
+ throw new import_core4.QuotaTokenExpiredError();
785
670
  }
786
671
  response = await fetch(`${baseUrl}/v1/me`, {
787
672
  headers: { Authorization: `Bearer ${newAccessToken}` },
788
- signal: AbortSignal.timeout(FETCH_TIMEOUT_MS)
673
+ signal: AbortSignal.timeout(import_core2.FETCH_TIMEOUT_MS)
789
674
  });
790
675
  if (!response.ok) {
791
- throw new QuotaTokenExpiredError();
676
+ throw new import_core4.QuotaTokenExpiredError();
792
677
  }
793
678
  accessToken = newAccessToken;
794
679
  } else if (!response.ok) {
795
- throw new QuotaError(
680
+ throw new import_core4.QuotaError(
796
681
  `Failed to fetch user: ${response.statusText}`,
797
682
  "api_error",
798
683
  response.status
@@ -804,13 +689,13 @@ function withQuotaAuth(config, handler) {
804
689
  }
805
690
  return await handler(request, { user, accessToken });
806
691
  } catch (error) {
807
- if (error instanceof QuotaNotConnectedError) {
692
+ if (error instanceof import_core4.QuotaNotConnectedError) {
808
693
  return Response.json(
809
694
  { error: { code: error.code, message: error.message } },
810
695
  { status: 401 }
811
696
  );
812
697
  }
813
- if (error instanceof QuotaTokenExpiredError) {
698
+ if (error instanceof import_core4.QuotaTokenExpiredError) {
814
699
  return Response.json(
815
700
  {
816
701
  error: {
@@ -822,7 +707,7 @@ function withQuotaAuth(config, handler) {
822
707
  { status: 401 }
823
708
  );
824
709
  }
825
- if (error instanceof QuotaInsufficientCreditsError) {
710
+ if (error instanceof import_core4.QuotaInsufficientCreditsError) {
826
711
  return Response.json(
827
712
  {
828
713
  error: {
@@ -834,7 +719,7 @@ function withQuotaAuth(config, handler) {
834
719
  { status: 402 }
835
720
  );
836
721
  }
837
- if (error instanceof QuotaRateLimitError) {
722
+ if (error instanceof import_core4.QuotaRateLimitError) {
838
723
  return new Response(
839
724
  JSON.stringify({
840
725
  error: {
@@ -851,7 +736,7 @@ function withQuotaAuth(config, handler) {
851
736
  }
852
737
  );
853
738
  }
854
- if (error instanceof QuotaError) {
739
+ if (error instanceof import_core4.QuotaError) {
855
740
  return Response.json(
856
741
  { error: { code: error.code, message: error.message } },
857
742
  { status: error.statusCode }
@@ -868,6 +753,7 @@ function withQuotaAuth(config, handler) {
868
753
 
869
754
  // src/server.ts
870
755
  var import_headers3 = require("next/headers");
756
+ var import_core11 = require("@usequota/core");
871
757
  var DEFAULT_BASE_URL3 = "https://api.usequota.app";
872
758
  var DEFAULT_COOKIE_PREFIX3 = "quota";
873
759
  var DEFAULT_STORAGE_MODE = "client";
@@ -891,7 +777,7 @@ async function getQuotaUser(config) {
891
777
  "X-Quota-Client-Secret": config.clientSecret,
892
778
  "X-Quota-User": externalUserId
893
779
  },
894
- signal: AbortSignal.timeout(FETCH_TIMEOUT_MS)
780
+ signal: AbortSignal.timeout(import_core2.FETCH_TIMEOUT_MS)
895
781
  });
896
782
  if (!response2.ok) {
897
783
  if (response2.status === 401 || response2.status === 404) {
@@ -910,7 +796,7 @@ async function getQuotaUser(config) {
910
796
  headers: {
911
797
  Authorization: `Bearer ${accessToken}`
912
798
  },
913
- signal: AbortSignal.timeout(FETCH_TIMEOUT_MS)
799
+ signal: AbortSignal.timeout(import_core2.FETCH_TIMEOUT_MS)
914
800
  });
915
801
  if (!response.ok) {
916
802
  if (response.status === 401) {
@@ -918,13 +804,13 @@ async function getQuotaUser(config) {
918
804
  `${cookiePrefix}_refresh_token`
919
805
  )?.value;
920
806
  if (refreshTokenValue) {
921
- const refreshed = await refreshAccessTokenWithCredentials({
922
- refreshToken: refreshTokenValue,
923
- clientId: config.clientId,
924
- clientSecret: config.clientSecret,
925
- baseUrl
926
- });
927
- if (refreshed) {
807
+ try {
808
+ const refreshed = await (0, import_core3.refreshAccessTokenWithCredentials)({
809
+ refreshToken: refreshTokenValue,
810
+ clientId: config.clientId,
811
+ clientSecret: config.clientSecret,
812
+ baseUrl
813
+ });
928
814
  cookieStore.set(
929
815
  `${cookiePrefix}_access_token`,
930
816
  refreshed.access_token,
@@ -951,11 +837,13 @@ async function getQuotaUser(config) {
951
837
  headers: {
952
838
  Authorization: `Bearer ${refreshed.access_token}`
953
839
  },
954
- signal: AbortSignal.timeout(FETCH_TIMEOUT_MS)
840
+ signal: AbortSignal.timeout(import_core2.FETCH_TIMEOUT_MS)
955
841
  });
956
842
  if (retryResponse.ok) {
957
843
  return await retryResponse.json();
958
844
  }
845
+ } catch {
846
+ return null;
959
847
  }
960
848
  }
961
849
  }
@@ -972,7 +860,7 @@ async function requireQuotaAuth(config) {
972
860
  if (!user) {
973
861
  const { redirect } = await import("next/navigation");
974
862
  redirect("/");
975
- throw new QuotaNotConnectedError("Redirecting to /");
863
+ throw new import_core11.QuotaNotConnectedError("Redirecting to /");
976
864
  }
977
865
  return user;
978
866
  }
@@ -980,7 +868,7 @@ async function getQuotaPackages(config) {
980
868
  const baseUrl = config?.baseUrl ?? DEFAULT_BASE_URL3;
981
869
  try {
982
870
  const response = await fetch(`${baseUrl}/v1/packages`, {
983
- signal: AbortSignal.timeout(FETCH_TIMEOUT_MS)
871
+ signal: AbortSignal.timeout(import_core2.FETCH_TIMEOUT_MS)
984
872
  });
985
873
  if (!response.ok) {
986
874
  throw new Error(`Failed to fetch packages: ${response.statusText}`);
@@ -1015,7 +903,7 @@ async function createQuotaCheckout(config) {
1015
903
  `${cookiePrefix}_access_token`
1016
904
  )?.value;
1017
905
  if (!accessToken) {
1018
- throw new QuotaNotConnectedError("Not authenticated");
906
+ throw new import_core11.QuotaNotConnectedError("Not authenticated");
1019
907
  }
1020
908
  headers["Authorization"] = `Bearer ${accessToken}`;
1021
909
  }
@@ -1027,7 +915,7 @@ async function createQuotaCheckout(config) {
1027
915
  success_url: config.successUrl,
1028
916
  cancel_url: config.cancelUrl
1029
917
  }),
1030
- signal: AbortSignal.timeout(FETCH_TIMEOUT_MS)
918
+ signal: AbortSignal.timeout(import_core2.FETCH_TIMEOUT_MS)
1031
919
  });
1032
920
  if (!response.ok) {
1033
921
  throw new Error(`Failed to create checkout: ${response.statusText}`);
@@ -1052,6 +940,8 @@ async function clearQuotaAuth(config) {
1052
940
  }
1053
941
  // Annotate the CommonJS export names for ESM import in node:
1054
942
  0 && (module.exports = {
943
+ InMemoryTokenStorage,
944
+ QuotaClient,
1055
945
  QuotaError,
1056
946
  QuotaInsufficientCreditsError,
1057
947
  QuotaNotConnectedError,
@@ -1060,9 +950,15 @@ async function clearQuotaAuth(config) {
1060
950
  clearQuotaAuth,
1061
951
  createQuotaCheckout,
1062
952
  createQuotaRouteHandlers,
953
+ createWebhookHandler,
1063
954
  errorFromResponse,
955
+ exchangeCodeForToken,
1064
956
  getQuotaPackages,
1065
957
  getQuotaUser,
958
+ parseSSEStream,
959
+ parseWebhook,
960
+ refreshAccessToken,
1066
961
  requireQuotaAuth,
962
+ verifyWebhookSignature,
1067
963
  withQuotaAuth
1068
964
  });