@usequota/nextjs 0.1.0 → 0.2.1
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 +64 -6
- package/dist/index.d.ts +64 -6
- package/dist/index.js +63 -23
- package/dist/index.mjs +62 -23
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @usequota/nextjs
|
|
2
2
|
|
|
3
|
-
Next.js SDK for [Quota](https://
|
|
3
|
+
Next.js SDK for [Quota](https://usequota.app) - AI credit wallet and multi-provider inference API.
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
@@ -106,7 +106,7 @@ export function MyComponent() {
|
|
|
106
106
|
return (
|
|
107
107
|
<div>
|
|
108
108
|
<p>Welcome, {user.email}!</p>
|
|
109
|
-
<p>Balance: {user.balance}
|
|
109
|
+
<p>Balance: ${(user.balance / 1_000_000).toFixed(2)}</p>
|
|
110
110
|
</div>
|
|
111
111
|
);
|
|
112
112
|
}
|
package/dist/index.d.mts
CHANGED
|
@@ -2,7 +2,7 @@ import { NextRequest, NextResponse } from 'next/server';
|
|
|
2
2
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
3
3
|
import * as react from 'react';
|
|
4
4
|
import { ReactNode } from 'react';
|
|
5
|
-
import { QuotaUser } from '@usequota/types';
|
|
5
|
+
import { QuotaUser, CreditPackage } from '@usequota/types';
|
|
6
6
|
export { ChatCompletionRequest, ChatCompletionResponse, ChatMessage, CreditPackage, QuotaError as QuotaErrorResponse, QuotaMetadata, QuotaSession, QuotaUser, Tool, ToolCall } from '@usequota/types';
|
|
7
7
|
export { Q as QuotaError, a as QuotaInsufficientCreditsError, b as QuotaNotConnectedError, d as QuotaRateLimitError, c as QuotaTokenExpiredError } from './errors-CmNx3kSz.mjs';
|
|
8
8
|
|
|
@@ -115,8 +115,19 @@ interface QuotaContextValue {
|
|
|
115
115
|
* Refetches user data from the server
|
|
116
116
|
*/
|
|
117
117
|
refetch: () => Promise<void>;
|
|
118
|
+
/**
|
|
119
|
+
* Quota API base URL
|
|
120
|
+
*/
|
|
121
|
+
baseUrl: string;
|
|
118
122
|
}
|
|
119
123
|
declare const QuotaContext: react.Context<QuotaContextValue | null>;
|
|
124
|
+
/**
|
|
125
|
+
* Controls when the provider fetches user data.
|
|
126
|
+
*
|
|
127
|
+
* - `"eager"` — fetches on mount (default, current behavior)
|
|
128
|
+
* - `"lazy"` — does NOT fetch on mount; only fetches when `refetch()` is called
|
|
129
|
+
*/
|
|
130
|
+
type QuotaFetchStrategy = "eager" | "lazy";
|
|
120
131
|
interface QuotaProviderProps {
|
|
121
132
|
children: ReactNode;
|
|
122
133
|
/**
|
|
@@ -138,6 +149,15 @@ interface QuotaProviderProps {
|
|
|
138
149
|
* @default '/api/quota/me'
|
|
139
150
|
*/
|
|
140
151
|
apiPath?: string;
|
|
152
|
+
/**
|
|
153
|
+
* Controls when user data is fetched.
|
|
154
|
+
*
|
|
155
|
+
* - `"eager"` (default) — fetches on mount
|
|
156
|
+
* - `"lazy"` — does NOT fetch on mount; only fetches when `refetch()` is called
|
|
157
|
+
*
|
|
158
|
+
* @default 'eager'
|
|
159
|
+
*/
|
|
160
|
+
fetchStrategy?: "eager" | "lazy";
|
|
141
161
|
}
|
|
142
162
|
/**
|
|
143
163
|
* React context provider for Quota authentication
|
|
@@ -160,7 +180,7 @@ interface QuotaProviderProps {
|
|
|
160
180
|
* }
|
|
161
181
|
* ```
|
|
162
182
|
*/
|
|
163
|
-
declare function QuotaProvider({ children, clientId, baseUrl, callbackPath, apiPath, }: QuotaProviderProps): react_jsx_runtime.JSX.Element;
|
|
183
|
+
declare function QuotaProvider({ children, clientId, baseUrl, callbackPath, apiPath, fetchStrategy, }: QuotaProviderProps): react_jsx_runtime.JSX.Element;
|
|
164
184
|
/**
|
|
165
185
|
* Hook to access Quota authentication context
|
|
166
186
|
*
|
|
@@ -203,7 +223,7 @@ declare function useQuota(): QuotaContextValue;
|
|
|
203
223
|
* return (
|
|
204
224
|
* <div>
|
|
205
225
|
* <p>Email: {user.email}</p>
|
|
206
|
-
* <p>Balance: {user.balance}
|
|
226
|
+
* <p>Balance: ${(user.balance / 1_000_000).toFixed(2)}</p>
|
|
207
227
|
* </div>
|
|
208
228
|
* );
|
|
209
229
|
* }
|
|
@@ -235,7 +255,9 @@ declare function useQuotaAuth(): {
|
|
|
235
255
|
logout: () => Promise<void>;
|
|
236
256
|
};
|
|
237
257
|
/**
|
|
238
|
-
* Hook to get user's credit balance
|
|
258
|
+
* Hook to get user's credit balance.
|
|
259
|
+
* Balance is in micro-dollars (1 unit = $0.000001).
|
|
260
|
+
* To convert to USD: balance / 1_000_000
|
|
239
261
|
*
|
|
240
262
|
* @example
|
|
241
263
|
* ```tsx
|
|
@@ -250,7 +272,7 @@ declare function useQuotaAuth(): {
|
|
|
250
272
|
*
|
|
251
273
|
* return (
|
|
252
274
|
* <div>
|
|
253
|
-
* Balance:
|
|
275
|
+
* Balance: ${(balance / 1_000_000).toFixed(2)}
|
|
254
276
|
* </div>
|
|
255
277
|
* );
|
|
256
278
|
* }
|
|
@@ -262,6 +284,42 @@ declare function useQuotaBalance(): {
|
|
|
262
284
|
error: Error | null;
|
|
263
285
|
refetch: () => Promise<void>;
|
|
264
286
|
};
|
|
287
|
+
/**
|
|
288
|
+
* Hook to fetch available credit packages from the Quota API
|
|
289
|
+
*
|
|
290
|
+
* Fetches from the public `/v1/packages` endpoint (no auth required).
|
|
291
|
+
* Results are cached for the lifetime of the component — subsequent calls
|
|
292
|
+
* return the cached data without re-fetching.
|
|
293
|
+
*
|
|
294
|
+
* @example
|
|
295
|
+
* ```tsx
|
|
296
|
+
* 'use client';
|
|
297
|
+
* import { useQuotaPackages } from '@usequota/nextjs';
|
|
298
|
+
*
|
|
299
|
+
* export function BuyCredits() {
|
|
300
|
+
* const { packages, isLoading, error, refetch } = useQuotaPackages();
|
|
301
|
+
*
|
|
302
|
+
* if (isLoading) return <div>Loading packages...</div>;
|
|
303
|
+
* if (error) return <div>Error: {error.message}</div>;
|
|
304
|
+
*
|
|
305
|
+
* return (
|
|
306
|
+
* <ul>
|
|
307
|
+
* {packages.map((pkg) => (
|
|
308
|
+
* <li key={pkg.id}>
|
|
309
|
+
* {pkg.credits} credits — {pkg.price_display}
|
|
310
|
+
* </li>
|
|
311
|
+
* ))}
|
|
312
|
+
* </ul>
|
|
313
|
+
* );
|
|
314
|
+
* }
|
|
315
|
+
* ```
|
|
316
|
+
*/
|
|
317
|
+
declare function useQuotaPackages(): {
|
|
318
|
+
packages: CreditPackage[];
|
|
319
|
+
isLoading: boolean;
|
|
320
|
+
error: Error | null;
|
|
321
|
+
refetch: () => Promise<void>;
|
|
322
|
+
};
|
|
265
323
|
|
|
266
324
|
interface QuotaConnectButtonProps {
|
|
267
325
|
/**
|
|
@@ -582,4 +640,4 @@ declare function parseWebhook(req: Request, secret: string): Promise<WebhookEven
|
|
|
582
640
|
*/
|
|
583
641
|
declare function createWebhookHandler(secret: string, handlers: Partial<Record<WebhookEvent["type"], (event: WebhookEvent) => Promise<void>>>): (req: Request) => Promise<Response>;
|
|
584
642
|
|
|
585
|
-
export { QuotaBalance, type QuotaBalanceProps, QuotaBuyCredits, type QuotaBuyCreditsProps, type QuotaConfig, QuotaConnectButton, type QuotaConnectButtonProps, QuotaContext, type QuotaContextValue, QuotaProvider, type QuotaProviderProps, QuotaUserMenu, type QuotaUserMenuProps, type VerifyWebhookOptions, type WebhookEvent, createQuotaMiddleware, createWebhookHandler, parseWebhook, useQuota, useQuotaAuth, useQuotaBalance, useQuotaUser, verifyWebhookSignature };
|
|
643
|
+
export { QuotaBalance, type QuotaBalanceProps, QuotaBuyCredits, type QuotaBuyCreditsProps, type QuotaConfig, QuotaConnectButton, type QuotaConnectButtonProps, QuotaContext, type QuotaContextValue, type QuotaFetchStrategy, QuotaProvider, type QuotaProviderProps, QuotaUserMenu, type QuotaUserMenuProps, type VerifyWebhookOptions, type WebhookEvent, createQuotaMiddleware, createWebhookHandler, parseWebhook, useQuota, useQuotaAuth, useQuotaBalance, useQuotaPackages, useQuotaUser, verifyWebhookSignature };
|
package/dist/index.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { NextRequest, NextResponse } from 'next/server';
|
|
|
2
2
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
3
3
|
import * as react from 'react';
|
|
4
4
|
import { ReactNode } from 'react';
|
|
5
|
-
import { QuotaUser } from '@usequota/types';
|
|
5
|
+
import { QuotaUser, CreditPackage } from '@usequota/types';
|
|
6
6
|
export { ChatCompletionRequest, ChatCompletionResponse, ChatMessage, CreditPackage, QuotaError as QuotaErrorResponse, QuotaMetadata, QuotaSession, QuotaUser, Tool, ToolCall } from '@usequota/types';
|
|
7
7
|
export { Q as QuotaError, a as QuotaInsufficientCreditsError, b as QuotaNotConnectedError, d as QuotaRateLimitError, c as QuotaTokenExpiredError } from './errors-CmNx3kSz.js';
|
|
8
8
|
|
|
@@ -115,8 +115,19 @@ interface QuotaContextValue {
|
|
|
115
115
|
* Refetches user data from the server
|
|
116
116
|
*/
|
|
117
117
|
refetch: () => Promise<void>;
|
|
118
|
+
/**
|
|
119
|
+
* Quota API base URL
|
|
120
|
+
*/
|
|
121
|
+
baseUrl: string;
|
|
118
122
|
}
|
|
119
123
|
declare const QuotaContext: react.Context<QuotaContextValue | null>;
|
|
124
|
+
/**
|
|
125
|
+
* Controls when the provider fetches user data.
|
|
126
|
+
*
|
|
127
|
+
* - `"eager"` — fetches on mount (default, current behavior)
|
|
128
|
+
* - `"lazy"` — does NOT fetch on mount; only fetches when `refetch()` is called
|
|
129
|
+
*/
|
|
130
|
+
type QuotaFetchStrategy = "eager" | "lazy";
|
|
120
131
|
interface QuotaProviderProps {
|
|
121
132
|
children: ReactNode;
|
|
122
133
|
/**
|
|
@@ -138,6 +149,15 @@ interface QuotaProviderProps {
|
|
|
138
149
|
* @default '/api/quota/me'
|
|
139
150
|
*/
|
|
140
151
|
apiPath?: string;
|
|
152
|
+
/**
|
|
153
|
+
* Controls when user data is fetched.
|
|
154
|
+
*
|
|
155
|
+
* - `"eager"` (default) — fetches on mount
|
|
156
|
+
* - `"lazy"` — does NOT fetch on mount; only fetches when `refetch()` is called
|
|
157
|
+
*
|
|
158
|
+
* @default 'eager'
|
|
159
|
+
*/
|
|
160
|
+
fetchStrategy?: "eager" | "lazy";
|
|
141
161
|
}
|
|
142
162
|
/**
|
|
143
163
|
* React context provider for Quota authentication
|
|
@@ -160,7 +180,7 @@ interface QuotaProviderProps {
|
|
|
160
180
|
* }
|
|
161
181
|
* ```
|
|
162
182
|
*/
|
|
163
|
-
declare function QuotaProvider({ children, clientId, baseUrl, callbackPath, apiPath, }: QuotaProviderProps): react_jsx_runtime.JSX.Element;
|
|
183
|
+
declare function QuotaProvider({ children, clientId, baseUrl, callbackPath, apiPath, fetchStrategy, }: QuotaProviderProps): react_jsx_runtime.JSX.Element;
|
|
164
184
|
/**
|
|
165
185
|
* Hook to access Quota authentication context
|
|
166
186
|
*
|
|
@@ -203,7 +223,7 @@ declare function useQuota(): QuotaContextValue;
|
|
|
203
223
|
* return (
|
|
204
224
|
* <div>
|
|
205
225
|
* <p>Email: {user.email}</p>
|
|
206
|
-
* <p>Balance: {user.balance}
|
|
226
|
+
* <p>Balance: ${(user.balance / 1_000_000).toFixed(2)}</p>
|
|
207
227
|
* </div>
|
|
208
228
|
* );
|
|
209
229
|
* }
|
|
@@ -235,7 +255,9 @@ declare function useQuotaAuth(): {
|
|
|
235
255
|
logout: () => Promise<void>;
|
|
236
256
|
};
|
|
237
257
|
/**
|
|
238
|
-
* Hook to get user's credit balance
|
|
258
|
+
* Hook to get user's credit balance.
|
|
259
|
+
* Balance is in micro-dollars (1 unit = $0.000001).
|
|
260
|
+
* To convert to USD: balance / 1_000_000
|
|
239
261
|
*
|
|
240
262
|
* @example
|
|
241
263
|
* ```tsx
|
|
@@ -250,7 +272,7 @@ declare function useQuotaAuth(): {
|
|
|
250
272
|
*
|
|
251
273
|
* return (
|
|
252
274
|
* <div>
|
|
253
|
-
* Balance:
|
|
275
|
+
* Balance: ${(balance / 1_000_000).toFixed(2)}
|
|
254
276
|
* </div>
|
|
255
277
|
* );
|
|
256
278
|
* }
|
|
@@ -262,6 +284,42 @@ declare function useQuotaBalance(): {
|
|
|
262
284
|
error: Error | null;
|
|
263
285
|
refetch: () => Promise<void>;
|
|
264
286
|
};
|
|
287
|
+
/**
|
|
288
|
+
* Hook to fetch available credit packages from the Quota API
|
|
289
|
+
*
|
|
290
|
+
* Fetches from the public `/v1/packages` endpoint (no auth required).
|
|
291
|
+
* Results are cached for the lifetime of the component — subsequent calls
|
|
292
|
+
* return the cached data without re-fetching.
|
|
293
|
+
*
|
|
294
|
+
* @example
|
|
295
|
+
* ```tsx
|
|
296
|
+
* 'use client';
|
|
297
|
+
* import { useQuotaPackages } from '@usequota/nextjs';
|
|
298
|
+
*
|
|
299
|
+
* export function BuyCredits() {
|
|
300
|
+
* const { packages, isLoading, error, refetch } = useQuotaPackages();
|
|
301
|
+
*
|
|
302
|
+
* if (isLoading) return <div>Loading packages...</div>;
|
|
303
|
+
* if (error) return <div>Error: {error.message}</div>;
|
|
304
|
+
*
|
|
305
|
+
* return (
|
|
306
|
+
* <ul>
|
|
307
|
+
* {packages.map((pkg) => (
|
|
308
|
+
* <li key={pkg.id}>
|
|
309
|
+
* {pkg.credits} credits — {pkg.price_display}
|
|
310
|
+
* </li>
|
|
311
|
+
* ))}
|
|
312
|
+
* </ul>
|
|
313
|
+
* );
|
|
314
|
+
* }
|
|
315
|
+
* ```
|
|
316
|
+
*/
|
|
317
|
+
declare function useQuotaPackages(): {
|
|
318
|
+
packages: CreditPackage[];
|
|
319
|
+
isLoading: boolean;
|
|
320
|
+
error: Error | null;
|
|
321
|
+
refetch: () => Promise<void>;
|
|
322
|
+
};
|
|
265
323
|
|
|
266
324
|
interface QuotaConnectButtonProps {
|
|
267
325
|
/**
|
|
@@ -582,4 +640,4 @@ declare function parseWebhook(req: Request, secret: string): Promise<WebhookEven
|
|
|
582
640
|
*/
|
|
583
641
|
declare function createWebhookHandler(secret: string, handlers: Partial<Record<WebhookEvent["type"], (event: WebhookEvent) => Promise<void>>>): (req: Request) => Promise<Response>;
|
|
584
642
|
|
|
585
|
-
export { QuotaBalance, type QuotaBalanceProps, QuotaBuyCredits, type QuotaBuyCreditsProps, type QuotaConfig, QuotaConnectButton, type QuotaConnectButtonProps, QuotaContext, type QuotaContextValue, QuotaProvider, type QuotaProviderProps, QuotaUserMenu, type QuotaUserMenuProps, type VerifyWebhookOptions, type WebhookEvent, createQuotaMiddleware, createWebhookHandler, parseWebhook, useQuota, useQuotaAuth, useQuotaBalance, useQuotaUser, verifyWebhookSignature };
|
|
643
|
+
export { QuotaBalance, type QuotaBalanceProps, QuotaBuyCredits, type QuotaBuyCreditsProps, type QuotaConfig, QuotaConnectButton, type QuotaConnectButtonProps, QuotaContext, type QuotaContextValue, type QuotaFetchStrategy, QuotaProvider, type QuotaProviderProps, QuotaUserMenu, type QuotaUserMenuProps, type VerifyWebhookOptions, type WebhookEvent, createQuotaMiddleware, createWebhookHandler, parseWebhook, useQuota, useQuotaAuth, useQuotaBalance, useQuotaPackages, useQuotaUser, verifyWebhookSignature };
|
package/dist/index.js
CHANGED
|
@@ -47,6 +47,7 @@ __export(index_exports, {
|
|
|
47
47
|
useQuota: () => useQuota,
|
|
48
48
|
useQuotaAuth: () => useQuotaAuth,
|
|
49
49
|
useQuotaBalance: () => useQuotaBalance,
|
|
50
|
+
useQuotaPackages: () => useQuotaPackages,
|
|
50
51
|
useQuotaUser: () => useQuotaUser,
|
|
51
52
|
verifyWebhookSignature: () => verifyWebhookSignature
|
|
52
53
|
});
|
|
@@ -210,10 +211,12 @@ function QuotaProvider({
|
|
|
210
211
|
clientId,
|
|
211
212
|
baseUrl = DEFAULT_BASE_URL2,
|
|
212
213
|
callbackPath = DEFAULT_CALLBACK_PATH2,
|
|
213
|
-
apiPath = DEFAULT_API_PATH
|
|
214
|
+
apiPath = DEFAULT_API_PATH,
|
|
215
|
+
fetchStrategy = "eager"
|
|
214
216
|
}) {
|
|
217
|
+
const isLazy = fetchStrategy === "lazy";
|
|
215
218
|
const [user, setUser] = (0, import_react.useState)(null);
|
|
216
|
-
const [isLoading, setIsLoading] = (0, import_react.useState)(
|
|
219
|
+
const [isLoading, setIsLoading] = (0, import_react.useState)(!isLazy);
|
|
217
220
|
const [error, setError] = (0, import_react.useState)(null);
|
|
218
221
|
const fetchUser = (0, import_react.useCallback)(async () => {
|
|
219
222
|
try {
|
|
@@ -240,8 +243,9 @@ function QuotaProvider({
|
|
|
240
243
|
}
|
|
241
244
|
}, [apiPath]);
|
|
242
245
|
(0, import_react.useEffect)(() => {
|
|
246
|
+
if (isLazy) return;
|
|
243
247
|
void fetchUser();
|
|
244
|
-
}, [fetchUser]);
|
|
248
|
+
}, [fetchUser, isLazy]);
|
|
245
249
|
const login = (0, import_react.useCallback)(() => {
|
|
246
250
|
const state = generateRandomState();
|
|
247
251
|
if (typeof window !== "undefined") {
|
|
@@ -283,7 +287,8 @@ function QuotaProvider({
|
|
|
283
287
|
error,
|
|
284
288
|
login,
|
|
285
289
|
logout,
|
|
286
|
-
refetch
|
|
290
|
+
refetch,
|
|
291
|
+
baseUrl
|
|
287
292
|
};
|
|
288
293
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(QuotaContext.Provider, { value, children });
|
|
289
294
|
}
|
|
@@ -311,6 +316,7 @@ function getRedirectUri(callbackPath) {
|
|
|
311
316
|
}
|
|
312
317
|
|
|
313
318
|
// src/hooks.ts
|
|
319
|
+
var import_react2 = require("react");
|
|
314
320
|
function useQuotaUser() {
|
|
315
321
|
const { user } = useQuota();
|
|
316
322
|
return user;
|
|
@@ -333,9 +339,42 @@ function useQuotaBalance() {
|
|
|
333
339
|
refetch
|
|
334
340
|
};
|
|
335
341
|
}
|
|
342
|
+
function useQuotaPackages() {
|
|
343
|
+
const { baseUrl } = useQuota();
|
|
344
|
+
const [packages, setPackages] = (0, import_react2.useState)([]);
|
|
345
|
+
const [isLoading, setIsLoading] = (0, import_react2.useState)(false);
|
|
346
|
+
const [error, setError] = (0, import_react2.useState)(null);
|
|
347
|
+
const hasFetched = (0, import_react2.useRef)(false);
|
|
348
|
+
const fetchPackages = (0, import_react2.useCallback)(async () => {
|
|
349
|
+
try {
|
|
350
|
+
setIsLoading(true);
|
|
351
|
+
setError(null);
|
|
352
|
+
const response = await fetch(`${baseUrl}/v1/packages`);
|
|
353
|
+
if (!response.ok) {
|
|
354
|
+
throw new Error(`Failed to fetch packages: ${response.statusText}`);
|
|
355
|
+
}
|
|
356
|
+
const data = await response.json();
|
|
357
|
+
setPackages(data.packages);
|
|
358
|
+
hasFetched.current = true;
|
|
359
|
+
} catch (err) {
|
|
360
|
+
const errorObj = err instanceof Error ? err : new Error("Unknown error");
|
|
361
|
+
setError(errorObj);
|
|
362
|
+
} finally {
|
|
363
|
+
setIsLoading(false);
|
|
364
|
+
}
|
|
365
|
+
}, [baseUrl]);
|
|
366
|
+
if (!hasFetched.current && !isLoading && error === null) {
|
|
367
|
+
void fetchPackages();
|
|
368
|
+
}
|
|
369
|
+
const refetch = (0, import_react2.useCallback)(async () => {
|
|
370
|
+
hasFetched.current = false;
|
|
371
|
+
await fetchPackages();
|
|
372
|
+
}, [fetchPackages]);
|
|
373
|
+
return { packages, isLoading, error, refetch };
|
|
374
|
+
}
|
|
336
375
|
|
|
337
376
|
// src/components/QuotaConnectButton.tsx
|
|
338
|
-
var
|
|
377
|
+
var import_react3 = require("react");
|
|
339
378
|
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
340
379
|
function QuotaConnectButton({
|
|
341
380
|
children,
|
|
@@ -347,9 +386,9 @@ function QuotaConnectButton({
|
|
|
347
386
|
showWhenConnected = false
|
|
348
387
|
}) {
|
|
349
388
|
const { user, login, isLoading, error } = useQuota();
|
|
350
|
-
const wasLoadingRef = (0,
|
|
351
|
-
const hadUserRef = (0,
|
|
352
|
-
(0,
|
|
389
|
+
const wasLoadingRef = (0, import_react3.useRef)(isLoading);
|
|
390
|
+
const hadUserRef = (0, import_react3.useRef)(!!user);
|
|
391
|
+
(0, import_react3.useEffect)(() => {
|
|
353
392
|
const wasLoading = wasLoadingRef.current;
|
|
354
393
|
const hadUser = hadUserRef.current;
|
|
355
394
|
wasLoadingRef.current = isLoading;
|
|
@@ -358,7 +397,7 @@ function QuotaConnectButton({
|
|
|
358
397
|
onSuccess?.();
|
|
359
398
|
}
|
|
360
399
|
}, [user, isLoading, onSuccess]);
|
|
361
|
-
const handleClick = (0,
|
|
400
|
+
const handleClick = (0, import_react3.useCallback)(() => {
|
|
362
401
|
try {
|
|
363
402
|
login();
|
|
364
403
|
} catch (err) {
|
|
@@ -595,7 +634,7 @@ function ErrorIcon() {
|
|
|
595
634
|
}
|
|
596
635
|
|
|
597
636
|
// src/components/QuotaBuyCredits.tsx
|
|
598
|
-
var
|
|
637
|
+
var import_react4 = require("react");
|
|
599
638
|
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
600
639
|
function QuotaBuyCredits({
|
|
601
640
|
packageId,
|
|
@@ -609,9 +648,9 @@ function QuotaBuyCredits({
|
|
|
609
648
|
disabled = false
|
|
610
649
|
}) {
|
|
611
650
|
const { user } = useQuota();
|
|
612
|
-
const [isLoading, setIsLoading] = (0,
|
|
613
|
-
const [error, setError] = (0,
|
|
614
|
-
const handlePurchase = (0,
|
|
651
|
+
const [isLoading, setIsLoading] = (0, import_react4.useState)(false);
|
|
652
|
+
const [error, setError] = (0, import_react4.useState)(null);
|
|
653
|
+
const handlePurchase = (0, import_react4.useCallback)(async () => {
|
|
615
654
|
if (!user) {
|
|
616
655
|
const err = new Error("Must be logged in to purchase credits");
|
|
617
656
|
setError(err);
|
|
@@ -704,7 +743,7 @@ function CartIcon() {
|
|
|
704
743
|
}
|
|
705
744
|
|
|
706
745
|
// src/components/QuotaUserMenu.tsx
|
|
707
|
-
var
|
|
746
|
+
var import_react5 = require("react");
|
|
708
747
|
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
709
748
|
function QuotaUserMenu({
|
|
710
749
|
className,
|
|
@@ -715,11 +754,11 @@ function QuotaUserMenu({
|
|
|
715
754
|
}) {
|
|
716
755
|
const { user, logout, isLoading: authLoading } = useQuota();
|
|
717
756
|
const { balance } = useQuotaBalance();
|
|
718
|
-
const [isOpen, setIsOpen] = (0,
|
|
719
|
-
const [isLoggingOut, setIsLoggingOut] = (0,
|
|
720
|
-
const menuRef = (0,
|
|
721
|
-
const triggerRef = (0,
|
|
722
|
-
(0,
|
|
757
|
+
const [isOpen, setIsOpen] = (0, import_react5.useState)(false);
|
|
758
|
+
const [isLoggingOut, setIsLoggingOut] = (0, import_react5.useState)(false);
|
|
759
|
+
const menuRef = (0, import_react5.useRef)(null);
|
|
760
|
+
const triggerRef = (0, import_react5.useRef)(null);
|
|
761
|
+
(0, import_react5.useEffect)(() => {
|
|
723
762
|
if (!isOpen) return;
|
|
724
763
|
const handleClickOutside = (event) => {
|
|
725
764
|
if (menuRef.current && !menuRef.current.contains(event.target)) {
|
|
@@ -739,10 +778,10 @@ function QuotaUserMenu({
|
|
|
739
778
|
document.removeEventListener("keydown", handleEscape);
|
|
740
779
|
};
|
|
741
780
|
}, [isOpen]);
|
|
742
|
-
const handleToggle = (0,
|
|
781
|
+
const handleToggle = (0, import_react5.useCallback)(() => {
|
|
743
782
|
setIsOpen((prev) => !prev);
|
|
744
783
|
}, []);
|
|
745
|
-
const handleKeyDown = (0,
|
|
784
|
+
const handleKeyDown = (0, import_react5.useCallback)(
|
|
746
785
|
(event) => {
|
|
747
786
|
if (event.key === "Enter" || event.key === " ") {
|
|
748
787
|
event.preventDefault();
|
|
@@ -755,7 +794,7 @@ function QuotaUserMenu({
|
|
|
755
794
|
},
|
|
756
795
|
[isOpen]
|
|
757
796
|
);
|
|
758
|
-
const handleLogout = (0,
|
|
797
|
+
const handleLogout = (0, import_react5.useCallback)(async () => {
|
|
759
798
|
setIsLoggingOut(true);
|
|
760
799
|
try {
|
|
761
800
|
await logout();
|
|
@@ -765,7 +804,7 @@ function QuotaUserMenu({
|
|
|
765
804
|
setIsOpen(false);
|
|
766
805
|
}
|
|
767
806
|
}, [logout, onLogout]);
|
|
768
|
-
const handleBuyCredits = (0,
|
|
807
|
+
const handleBuyCredits = (0, import_react5.useCallback)(() => {
|
|
769
808
|
setIsOpen(false);
|
|
770
809
|
onBuyCredits?.();
|
|
771
810
|
}, [onBuyCredits]);
|
|
@@ -1074,6 +1113,7 @@ function createWebhookHandler(secret, handlers) {
|
|
|
1074
1113
|
useQuota,
|
|
1075
1114
|
useQuotaAuth,
|
|
1076
1115
|
useQuotaBalance,
|
|
1116
|
+
useQuotaPackages,
|
|
1077
1117
|
useQuotaUser,
|
|
1078
1118
|
verifyWebhookSignature
|
|
1079
1119
|
});
|
package/dist/index.mjs
CHANGED
|
@@ -170,10 +170,12 @@ function QuotaProvider({
|
|
|
170
170
|
clientId,
|
|
171
171
|
baseUrl = DEFAULT_BASE_URL2,
|
|
172
172
|
callbackPath = DEFAULT_CALLBACK_PATH2,
|
|
173
|
-
apiPath = DEFAULT_API_PATH
|
|
173
|
+
apiPath = DEFAULT_API_PATH,
|
|
174
|
+
fetchStrategy = "eager"
|
|
174
175
|
}) {
|
|
176
|
+
const isLazy = fetchStrategy === "lazy";
|
|
175
177
|
const [user, setUser] = useState(null);
|
|
176
|
-
const [isLoading, setIsLoading] = useState(
|
|
178
|
+
const [isLoading, setIsLoading] = useState(!isLazy);
|
|
177
179
|
const [error, setError] = useState(null);
|
|
178
180
|
const fetchUser = useCallback(async () => {
|
|
179
181
|
try {
|
|
@@ -200,8 +202,9 @@ function QuotaProvider({
|
|
|
200
202
|
}
|
|
201
203
|
}, [apiPath]);
|
|
202
204
|
useEffect(() => {
|
|
205
|
+
if (isLazy) return;
|
|
203
206
|
void fetchUser();
|
|
204
|
-
}, [fetchUser]);
|
|
207
|
+
}, [fetchUser, isLazy]);
|
|
205
208
|
const login = useCallback(() => {
|
|
206
209
|
const state = generateRandomState();
|
|
207
210
|
if (typeof window !== "undefined") {
|
|
@@ -243,7 +246,8 @@ function QuotaProvider({
|
|
|
243
246
|
error,
|
|
244
247
|
login,
|
|
245
248
|
logout,
|
|
246
|
-
refetch
|
|
249
|
+
refetch,
|
|
250
|
+
baseUrl
|
|
247
251
|
};
|
|
248
252
|
return /* @__PURE__ */ jsx(QuotaContext.Provider, { value, children });
|
|
249
253
|
}
|
|
@@ -271,6 +275,7 @@ function getRedirectUri(callbackPath) {
|
|
|
271
275
|
}
|
|
272
276
|
|
|
273
277
|
// src/hooks.ts
|
|
278
|
+
import { useState as useState2, useCallback as useCallback2, useRef } from "react";
|
|
274
279
|
function useQuotaUser() {
|
|
275
280
|
const { user } = useQuota();
|
|
276
281
|
return user;
|
|
@@ -293,9 +298,42 @@ function useQuotaBalance() {
|
|
|
293
298
|
refetch
|
|
294
299
|
};
|
|
295
300
|
}
|
|
301
|
+
function useQuotaPackages() {
|
|
302
|
+
const { baseUrl } = useQuota();
|
|
303
|
+
const [packages, setPackages] = useState2([]);
|
|
304
|
+
const [isLoading, setIsLoading] = useState2(false);
|
|
305
|
+
const [error, setError] = useState2(null);
|
|
306
|
+
const hasFetched = useRef(false);
|
|
307
|
+
const fetchPackages = useCallback2(async () => {
|
|
308
|
+
try {
|
|
309
|
+
setIsLoading(true);
|
|
310
|
+
setError(null);
|
|
311
|
+
const response = await fetch(`${baseUrl}/v1/packages`);
|
|
312
|
+
if (!response.ok) {
|
|
313
|
+
throw new Error(`Failed to fetch packages: ${response.statusText}`);
|
|
314
|
+
}
|
|
315
|
+
const data = await response.json();
|
|
316
|
+
setPackages(data.packages);
|
|
317
|
+
hasFetched.current = true;
|
|
318
|
+
} catch (err) {
|
|
319
|
+
const errorObj = err instanceof Error ? err : new Error("Unknown error");
|
|
320
|
+
setError(errorObj);
|
|
321
|
+
} finally {
|
|
322
|
+
setIsLoading(false);
|
|
323
|
+
}
|
|
324
|
+
}, [baseUrl]);
|
|
325
|
+
if (!hasFetched.current && !isLoading && error === null) {
|
|
326
|
+
void fetchPackages();
|
|
327
|
+
}
|
|
328
|
+
const refetch = useCallback2(async () => {
|
|
329
|
+
hasFetched.current = false;
|
|
330
|
+
await fetchPackages();
|
|
331
|
+
}, [fetchPackages]);
|
|
332
|
+
return { packages, isLoading, error, refetch };
|
|
333
|
+
}
|
|
296
334
|
|
|
297
335
|
// src/components/QuotaConnectButton.tsx
|
|
298
|
-
import { useCallback as
|
|
336
|
+
import { useCallback as useCallback3, useEffect as useEffect2, useRef as useRef2 } from "react";
|
|
299
337
|
import { Fragment, jsx as jsx2, jsxs } from "react/jsx-runtime";
|
|
300
338
|
function QuotaConnectButton({
|
|
301
339
|
children,
|
|
@@ -307,8 +345,8 @@ function QuotaConnectButton({
|
|
|
307
345
|
showWhenConnected = false
|
|
308
346
|
}) {
|
|
309
347
|
const { user, login, isLoading, error } = useQuota();
|
|
310
|
-
const wasLoadingRef =
|
|
311
|
-
const hadUserRef =
|
|
348
|
+
const wasLoadingRef = useRef2(isLoading);
|
|
349
|
+
const hadUserRef = useRef2(!!user);
|
|
312
350
|
useEffect2(() => {
|
|
313
351
|
const wasLoading = wasLoadingRef.current;
|
|
314
352
|
const hadUser = hadUserRef.current;
|
|
@@ -318,7 +356,7 @@ function QuotaConnectButton({
|
|
|
318
356
|
onSuccess?.();
|
|
319
357
|
}
|
|
320
358
|
}, [user, isLoading, onSuccess]);
|
|
321
|
-
const handleClick =
|
|
359
|
+
const handleClick = useCallback3(() => {
|
|
322
360
|
try {
|
|
323
361
|
login();
|
|
324
362
|
} catch (err) {
|
|
@@ -555,7 +593,7 @@ function ErrorIcon() {
|
|
|
555
593
|
}
|
|
556
594
|
|
|
557
595
|
// src/components/QuotaBuyCredits.tsx
|
|
558
|
-
import { useState as
|
|
596
|
+
import { useState as useState3, useCallback as useCallback4 } from "react";
|
|
559
597
|
import { Fragment as Fragment2, jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
560
598
|
function QuotaBuyCredits({
|
|
561
599
|
packageId,
|
|
@@ -569,9 +607,9 @@ function QuotaBuyCredits({
|
|
|
569
607
|
disabled = false
|
|
570
608
|
}) {
|
|
571
609
|
const { user } = useQuota();
|
|
572
|
-
const [isLoading, setIsLoading] =
|
|
573
|
-
const [error, setError] =
|
|
574
|
-
const handlePurchase =
|
|
610
|
+
const [isLoading, setIsLoading] = useState3(false);
|
|
611
|
+
const [error, setError] = useState3(null);
|
|
612
|
+
const handlePurchase = useCallback4(async () => {
|
|
575
613
|
if (!user) {
|
|
576
614
|
const err = new Error("Must be logged in to purchase credits");
|
|
577
615
|
setError(err);
|
|
@@ -665,9 +703,9 @@ function CartIcon() {
|
|
|
665
703
|
|
|
666
704
|
// src/components/QuotaUserMenu.tsx
|
|
667
705
|
import {
|
|
668
|
-
useState as
|
|
669
|
-
useCallback as
|
|
670
|
-
useRef as
|
|
706
|
+
useState as useState4,
|
|
707
|
+
useCallback as useCallback5,
|
|
708
|
+
useRef as useRef3,
|
|
671
709
|
useEffect as useEffect3
|
|
672
710
|
} from "react";
|
|
673
711
|
import { Fragment as Fragment3, jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
@@ -680,10 +718,10 @@ function QuotaUserMenu({
|
|
|
680
718
|
}) {
|
|
681
719
|
const { user, logout, isLoading: authLoading } = useQuota();
|
|
682
720
|
const { balance } = useQuotaBalance();
|
|
683
|
-
const [isOpen, setIsOpen] =
|
|
684
|
-
const [isLoggingOut, setIsLoggingOut] =
|
|
685
|
-
const menuRef =
|
|
686
|
-
const triggerRef =
|
|
721
|
+
const [isOpen, setIsOpen] = useState4(false);
|
|
722
|
+
const [isLoggingOut, setIsLoggingOut] = useState4(false);
|
|
723
|
+
const menuRef = useRef3(null);
|
|
724
|
+
const triggerRef = useRef3(null);
|
|
687
725
|
useEffect3(() => {
|
|
688
726
|
if (!isOpen) return;
|
|
689
727
|
const handleClickOutside = (event) => {
|
|
@@ -704,10 +742,10 @@ function QuotaUserMenu({
|
|
|
704
742
|
document.removeEventListener("keydown", handleEscape);
|
|
705
743
|
};
|
|
706
744
|
}, [isOpen]);
|
|
707
|
-
const handleToggle =
|
|
745
|
+
const handleToggle = useCallback5(() => {
|
|
708
746
|
setIsOpen((prev) => !prev);
|
|
709
747
|
}, []);
|
|
710
|
-
const handleKeyDown =
|
|
748
|
+
const handleKeyDown = useCallback5(
|
|
711
749
|
(event) => {
|
|
712
750
|
if (event.key === "Enter" || event.key === " ") {
|
|
713
751
|
event.preventDefault();
|
|
@@ -720,7 +758,7 @@ function QuotaUserMenu({
|
|
|
720
758
|
},
|
|
721
759
|
[isOpen]
|
|
722
760
|
);
|
|
723
|
-
const handleLogout =
|
|
761
|
+
const handleLogout = useCallback5(async () => {
|
|
724
762
|
setIsLoggingOut(true);
|
|
725
763
|
try {
|
|
726
764
|
await logout();
|
|
@@ -730,7 +768,7 @@ function QuotaUserMenu({
|
|
|
730
768
|
setIsOpen(false);
|
|
731
769
|
}
|
|
732
770
|
}, [logout, onLogout]);
|
|
733
|
-
const handleBuyCredits =
|
|
771
|
+
const handleBuyCredits = useCallback5(() => {
|
|
734
772
|
setIsOpen(false);
|
|
735
773
|
onBuyCredits?.();
|
|
736
774
|
}, [onBuyCredits]);
|
|
@@ -963,6 +1001,7 @@ export {
|
|
|
963
1001
|
useQuota,
|
|
964
1002
|
useQuotaAuth,
|
|
965
1003
|
useQuotaBalance,
|
|
1004
|
+
useQuotaPackages,
|
|
966
1005
|
useQuotaUser,
|
|
967
1006
|
verifyWebhookSignature
|
|
968
1007
|
};
|