@usequota/nextjs 0.2.1 → 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/README.md +2 -2
- package/dist/index.d.mts +2 -101
- package/dist/index.d.ts +2 -101
- package/dist/index.js +13 -158
- package/dist/index.mjs +15 -73
- package/dist/server.d.mts +3 -89
- package/dist/server.d.ts +3 -89
- package/dist/server.js +79 -183
- package/dist/server.mjs +59 -49
- package/package.json +3 -2
package/dist/server.d.ts
CHANGED
|
@@ -1,93 +1,7 @@
|
|
|
1
|
-
|
|
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
|
|
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
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
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
|
-
|
|
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
|
-
|
|
50
|
-
var
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
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
|
|
166
|
-
|
|
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
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
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
|
-
|
|
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
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
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
|
});
|