@solvapay/next 1.0.7 → 1.0.8-preview.2
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/index.cjs +66 -93
- package/dist/index.d.cts +41 -37
- package/dist/index.d.ts +41 -37
- package/dist/index.js +60 -89
- package/package.json +4 -4
package/dist/index.cjs
CHANGED
|
@@ -43,6 +43,8 @@ __export(index_exports, {
|
|
|
43
43
|
createTopupPaymentIntent: () => createTopupPaymentIntent,
|
|
44
44
|
getAuthenticatedUser: () => getAuthenticatedUser,
|
|
45
45
|
getCustomerBalance: () => getCustomerBalance,
|
|
46
|
+
getMerchant: () => getMerchant,
|
|
47
|
+
getProduct: () => getProduct,
|
|
46
48
|
getPurchaseCacheStats: () => getPurchaseCacheStats,
|
|
47
49
|
listPlans: () => listPlans,
|
|
48
50
|
processPaymentIntent: () => processPaymentIntent,
|
|
@@ -51,9 +53,8 @@ __export(index_exports, {
|
|
|
51
53
|
trackUsage: () => trackUsage
|
|
52
54
|
});
|
|
53
55
|
module.exports = __toCommonJS(index_exports);
|
|
54
|
-
var
|
|
55
|
-
var
|
|
56
|
-
var import_core = require("@solvapay/core");
|
|
56
|
+
var import_server24 = require("next/server");
|
|
57
|
+
var import_server25 = require("@solvapay/server");
|
|
57
58
|
|
|
58
59
|
// src/cache.ts
|
|
59
60
|
function createRequestDeduplicator(options = {}) {
|
|
@@ -366,8 +367,8 @@ async function reactivateRenewal(request, body, options = {}) {
|
|
|
366
367
|
// src/helpers/plans.ts
|
|
367
368
|
var import_server15 = require("next/server");
|
|
368
369
|
var import_server16 = require("@solvapay/server");
|
|
369
|
-
async function listPlans(request) {
|
|
370
|
-
const result = await (0, import_server16.listPlansCore)(request);
|
|
370
|
+
async function listPlans(request, options = {}) {
|
|
371
|
+
const result = await (0, import_server16.listPlansCore)(request, options);
|
|
371
372
|
if ((0, import_server16.isErrorResult)(result)) {
|
|
372
373
|
return import_server15.NextResponse.json(
|
|
373
374
|
{ error: result.error, details: result.details },
|
|
@@ -377,52 +378,57 @@ async function listPlans(request) {
|
|
|
377
378
|
return result;
|
|
378
379
|
}
|
|
379
380
|
|
|
380
|
-
// src/helpers/
|
|
381
|
+
// src/helpers/merchant.ts
|
|
381
382
|
var import_server17 = require("next/server");
|
|
382
383
|
var import_server18 = require("@solvapay/server");
|
|
383
|
-
async function
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
if ((0, import_server18.isErrorResult)(userResult)) {
|
|
387
|
-
return import_server17.NextResponse.json(
|
|
388
|
-
{ error: userResult.error, details: userResult.details },
|
|
389
|
-
{ status: userResult.status }
|
|
390
|
-
);
|
|
391
|
-
}
|
|
392
|
-
const { userId, email, name } = userResult;
|
|
393
|
-
const solvaPay = options.solvaPay || (0, import_server18.createSolvaPay)();
|
|
394
|
-
const customerRef = await solvaPay.ensureCustomer(userId, userId, {
|
|
395
|
-
email: email || void 0,
|
|
396
|
-
name: name || void 0
|
|
397
|
-
});
|
|
398
|
-
await solvaPay.trackUsage({
|
|
399
|
-
customerRef,
|
|
400
|
-
actionType: body.actionType,
|
|
401
|
-
units: body.units,
|
|
402
|
-
productRef: body.productRef,
|
|
403
|
-
description: body.description,
|
|
404
|
-
metadata: body.metadata
|
|
405
|
-
});
|
|
406
|
-
return import_server17.NextResponse.json({ success: true });
|
|
407
|
-
} catch (error) {
|
|
408
|
-
console.error("[trackUsage] Error:", error);
|
|
409
|
-
const message = error instanceof Error ? error.message : "Unknown error";
|
|
384
|
+
async function getMerchant(request, options = {}) {
|
|
385
|
+
const result = await (0, import_server18.getMerchantCore)(request, options);
|
|
386
|
+
if ((0, import_server18.isErrorResult)(result)) {
|
|
410
387
|
return import_server17.NextResponse.json(
|
|
411
|
-
{ error:
|
|
412
|
-
{ status:
|
|
388
|
+
{ error: result.error, details: result.details },
|
|
389
|
+
{ status: result.status }
|
|
413
390
|
);
|
|
414
391
|
}
|
|
392
|
+
return result;
|
|
415
393
|
}
|
|
416
394
|
|
|
417
|
-
// src/helpers/
|
|
395
|
+
// src/helpers/product.ts
|
|
418
396
|
var import_server19 = require("next/server");
|
|
397
|
+
var import_server20 = require("@solvapay/server");
|
|
398
|
+
async function getProduct(request, options = {}) {
|
|
399
|
+
const result = await (0, import_server20.getProductCore)(request, options);
|
|
400
|
+
if ((0, import_server20.isErrorResult)(result)) {
|
|
401
|
+
return import_server19.NextResponse.json(
|
|
402
|
+
{ error: result.error, details: result.details },
|
|
403
|
+
{ status: result.status }
|
|
404
|
+
);
|
|
405
|
+
}
|
|
406
|
+
return result;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
// src/helpers/usage.ts
|
|
410
|
+
var import_server21 = require("next/server");
|
|
411
|
+
var import_server22 = require("@solvapay/server");
|
|
412
|
+
async function trackUsage(request, body, options = {}) {
|
|
413
|
+
const result = await (0, import_server22.trackUsageCore)(request, body, options);
|
|
414
|
+
if ((0, import_server22.isErrorResult)(result)) {
|
|
415
|
+
return import_server21.NextResponse.json(
|
|
416
|
+
{ error: result.error, details: result.details },
|
|
417
|
+
{ status: result.status }
|
|
418
|
+
);
|
|
419
|
+
}
|
|
420
|
+
return import_server21.NextResponse.json(result);
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
// src/helpers/middleware.ts
|
|
424
|
+
var import_server23 = require("next/server");
|
|
419
425
|
function createAuthMiddleware(options) {
|
|
420
426
|
const { adapter, publicRoutes = [], userIdHeader = "x-user-id" } = options;
|
|
421
427
|
return async function middleware(request) {
|
|
422
428
|
const req = request;
|
|
423
429
|
const { pathname } = req.nextUrl;
|
|
424
430
|
if (!pathname.startsWith("/api")) {
|
|
425
|
-
return
|
|
431
|
+
return import_server23.NextResponse.next();
|
|
426
432
|
}
|
|
427
433
|
const isPublicRoute = publicRoutes.some((route) => pathname.startsWith(route));
|
|
428
434
|
const userId = await adapter.getUserIdFromRequest(req);
|
|
@@ -431,21 +437,21 @@ function createAuthMiddleware(options) {
|
|
|
431
437
|
if (userId) {
|
|
432
438
|
requestHeaders2.set(userIdHeader, userId);
|
|
433
439
|
}
|
|
434
|
-
return
|
|
440
|
+
return import_server23.NextResponse.next({
|
|
435
441
|
request: {
|
|
436
442
|
headers: requestHeaders2
|
|
437
443
|
}
|
|
438
444
|
});
|
|
439
445
|
}
|
|
440
446
|
if (!userId) {
|
|
441
|
-
return
|
|
447
|
+
return import_server23.NextResponse.json(
|
|
442
448
|
{ error: "Unauthorized", details: "Valid authentication required" },
|
|
443
449
|
{ status: 401 }
|
|
444
450
|
);
|
|
445
451
|
}
|
|
446
452
|
const requestHeaders = new Headers(req.headers);
|
|
447
453
|
requestHeaders.set(userIdHeader, userId);
|
|
448
|
-
return
|
|
454
|
+
return import_server23.NextResponse.next({
|
|
449
455
|
request: {
|
|
450
456
|
headers: requestHeaders
|
|
451
457
|
}
|
|
@@ -486,72 +492,37 @@ function createSupabaseAuthMiddleware(options = {}) {
|
|
|
486
492
|
|
|
487
493
|
// src/index.ts
|
|
488
494
|
async function checkPurchase(request, options = {}) {
|
|
495
|
+
const deduplicator = getSharedDeduplicator(options.deduplication);
|
|
489
496
|
try {
|
|
490
|
-
const { requireUserId
|
|
497
|
+
const { requireUserId } = await import("@solvapay/auth");
|
|
491
498
|
const userIdOrError = requireUserId(request);
|
|
492
499
|
if (userIdOrError instanceof Response) {
|
|
493
500
|
const clonedResponse = userIdOrError.clone();
|
|
494
501
|
const body = await clonedResponse.json().catch(() => ({ error: "Unauthorized" }));
|
|
495
|
-
return
|
|
502
|
+
return import_server24.NextResponse.json(body, { status: userIdOrError.status });
|
|
496
503
|
}
|
|
497
504
|
const userId = userIdOrError;
|
|
498
|
-
const
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
if (customer && customer.customerRef) {
|
|
506
|
-
if (customer.externalRef && customer.externalRef === userId) {
|
|
507
|
-
const filteredPurchases = (customer.purchases || []).filter(
|
|
508
|
-
(p) => p.status === "active"
|
|
509
|
-
);
|
|
510
|
-
return {
|
|
511
|
-
customerRef: customer.customerRef,
|
|
512
|
-
email: customer.email,
|
|
513
|
-
name: customer.name,
|
|
514
|
-
purchases: filteredPurchases
|
|
515
|
-
};
|
|
516
|
-
}
|
|
517
|
-
}
|
|
518
|
-
} catch {
|
|
519
|
-
}
|
|
520
|
-
}
|
|
521
|
-
const deduplicator = getSharedDeduplicator(options.deduplication);
|
|
522
|
-
const response = await deduplicator.deduplicate(userId, async () => {
|
|
523
|
-
try {
|
|
524
|
-
const ensuredCustomerRef = await solvaPay.ensureCustomer(userId, userId, {
|
|
525
|
-
email: email || void 0,
|
|
526
|
-
name: name || void 0
|
|
505
|
+
const response = await deduplicator.deduplicate(
|
|
506
|
+
userId,
|
|
507
|
+
async () => {
|
|
508
|
+
return await (0, import_server25.checkPurchaseCore)(request, {
|
|
509
|
+
solvaPay: options.solvaPay,
|
|
510
|
+
includeEmail: options.includeEmail,
|
|
511
|
+
includeName: options.includeName
|
|
527
512
|
});
|
|
528
|
-
const customer = await solvaPay.getCustomer({ customerRef: ensuredCustomerRef });
|
|
529
|
-
const filteredPurchases = (customer.purchases || []).filter(
|
|
530
|
-
(p) => p.status === "active"
|
|
531
|
-
);
|
|
532
|
-
const result = {
|
|
533
|
-
customerRef: customer.customerRef || userId,
|
|
534
|
-
email: customer.email,
|
|
535
|
-
name: customer.name,
|
|
536
|
-
purchases: filteredPurchases
|
|
537
|
-
};
|
|
538
|
-
return result;
|
|
539
|
-
} catch (error) {
|
|
540
|
-
console.error("[checkPurchase] Error fetching customer:", error);
|
|
541
|
-
return {
|
|
542
|
-
customerRef: userId,
|
|
543
|
-
purchases: []
|
|
544
|
-
};
|
|
545
513
|
}
|
|
546
|
-
|
|
514
|
+
);
|
|
515
|
+
if ((0, import_server25.isErrorResult)(response)) {
|
|
516
|
+
return import_server24.NextResponse.json(
|
|
517
|
+
{ error: response.error, details: response.details },
|
|
518
|
+
{ status: response.status }
|
|
519
|
+
);
|
|
520
|
+
}
|
|
547
521
|
return response;
|
|
548
522
|
} catch (error) {
|
|
549
523
|
console.error("Check purchase failed:", error);
|
|
550
|
-
if (error instanceof import_core.SolvaPayError) {
|
|
551
|
-
return import_server20.NextResponse.json({ error: error.message }, { status: 500 });
|
|
552
|
-
}
|
|
553
524
|
const errorMessage = error instanceof Error ? error.message : "Unknown error";
|
|
554
|
-
return
|
|
525
|
+
return import_server24.NextResponse.json(
|
|
555
526
|
{ error: "Failed to check purchase", details: errorMessage },
|
|
556
527
|
{ status: 500 }
|
|
557
528
|
);
|
|
@@ -572,6 +543,8 @@ async function checkPurchase(request, options = {}) {
|
|
|
572
543
|
createTopupPaymentIntent,
|
|
573
544
|
getAuthenticatedUser,
|
|
574
545
|
getCustomerBalance,
|
|
546
|
+
getMerchant,
|
|
547
|
+
getProduct,
|
|
575
548
|
getPurchaseCacheStats,
|
|
576
549
|
listPlans,
|
|
577
550
|
processPaymentIntent,
|
package/dist/index.d.cts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { NextResponse } from 'next/server';
|
|
2
2
|
import * as _solvapay_server from '@solvapay/server';
|
|
3
|
-
import { AuthenticatedUser, SolvaPay, CustomerBalanceResult, ActivatePlanResult, listPlansCore } from '@solvapay/server';
|
|
3
|
+
import { AuthenticatedUser, SolvaPay, CustomerBalanceResult, ActivatePlanResult, listPlansCore, getMerchantCore, getProductCore } from '@solvapay/server';
|
|
4
4
|
export { AuthMiddlewareOptions, SupabaseAuthMiddlewareOptions, createAuthMiddleware, createSupabaseAuthMiddleware } from './middleware.cjs';
|
|
5
5
|
import '@solvapay/auth';
|
|
6
6
|
|
|
@@ -322,7 +322,43 @@ type ListPlansSuccess = Exclude<Awaited<ReturnType<typeof listPlansCore>>, {
|
|
|
322
322
|
/**
|
|
323
323
|
* Next.js Plans Helper
|
|
324
324
|
*/
|
|
325
|
-
declare function listPlans(request: globalThis.Request
|
|
325
|
+
declare function listPlans(request: globalThis.Request, options?: {
|
|
326
|
+
solvaPay?: SolvaPay;
|
|
327
|
+
}): Promise<ListPlansSuccess | NextResponse>;
|
|
328
|
+
|
|
329
|
+
type GetMerchantSuccess = Exclude<Awaited<ReturnType<typeof getMerchantCore>>, {
|
|
330
|
+
error: string;
|
|
331
|
+
}>;
|
|
332
|
+
/**
|
|
333
|
+
* Next.js route wrapper for GET /api/merchant.
|
|
334
|
+
*
|
|
335
|
+
* @example
|
|
336
|
+
* ```ts
|
|
337
|
+
* // app/api/merchant/route.ts
|
|
338
|
+
* import { getMerchant } from '@solvapay/next/helpers'
|
|
339
|
+
* export const GET = (request: Request) => getMerchant(request)
|
|
340
|
+
* ```
|
|
341
|
+
*/
|
|
342
|
+
declare function getMerchant(request: globalThis.Request, options?: {
|
|
343
|
+
solvaPay?: SolvaPay;
|
|
344
|
+
}): Promise<GetMerchantSuccess | NextResponse>;
|
|
345
|
+
|
|
346
|
+
type GetProductSuccess = Exclude<Awaited<ReturnType<typeof getProductCore>>, {
|
|
347
|
+
error: string;
|
|
348
|
+
}>;
|
|
349
|
+
/**
|
|
350
|
+
* Next.js route wrapper for GET /api/get-product?productRef=...
|
|
351
|
+
*
|
|
352
|
+
* @example
|
|
353
|
+
* ```ts
|
|
354
|
+
* // app/api/get-product/route.ts
|
|
355
|
+
* import { getProduct } from '@solvapay/next/helpers'
|
|
356
|
+
* export const GET = (request: Request) => getProduct(request)
|
|
357
|
+
* ```
|
|
358
|
+
*/
|
|
359
|
+
declare function getProduct(request: globalThis.Request, options?: {
|
|
360
|
+
solvaPay?: SolvaPay;
|
|
361
|
+
}): Promise<GetProductSuccess | NextResponse>;
|
|
326
362
|
|
|
327
363
|
declare function trackUsage(request: globalThis.Request, body: {
|
|
328
364
|
actionType?: 'transaction' | 'api_call' | 'hour' | 'email' | 'storage' | 'custom';
|
|
@@ -380,41 +416,9 @@ interface CheckPurchaseOptions {
|
|
|
380
416
|
* - Fast path optimization using cached customer references from client
|
|
381
417
|
* - Automatic customer creation if needed
|
|
382
418
|
*
|
|
383
|
-
*
|
|
384
|
-
*
|
|
385
|
-
* 2. Gets user email and name from Supabase JWT token (if available)
|
|
386
|
-
* 3. Validates cached customer reference (if provided via header)
|
|
387
|
-
* 4. Ensures customer exists in SolvaPay backend
|
|
388
|
-
* 5. Returns customer purchase information
|
|
389
|
-
*
|
|
390
|
-
* @param request - Next.js request object (NextRequest extends Request)
|
|
391
|
-
* @param options - Configuration options
|
|
392
|
-
* @param options.deduplication - Request deduplication options (see {@link RequestDeduplicationOptions})
|
|
393
|
-
* @param options.solvaPay - Optional SolvaPay instance (creates new one if not provided)
|
|
394
|
-
* @param options.includeEmail - Whether to include email in response (default: true)
|
|
395
|
-
* @param options.includeName - Whether to include name in response (default: true)
|
|
396
|
-
* @returns Purchase check result with customer data and purchases, or NextResponse error
|
|
397
|
-
*
|
|
398
|
-
* @example
|
|
399
|
-
* ```typescript
|
|
400
|
-
* import { NextRequest, NextResponse } from 'next/server';
|
|
401
|
-
* import { checkPurchase } from '@solvapay/next';
|
|
402
|
-
*
|
|
403
|
-
* export async function GET(request: NextRequest) {
|
|
404
|
-
* const result = await checkPurchase(request);
|
|
405
|
-
*
|
|
406
|
-
* if (result instanceof NextResponse) {
|
|
407
|
-
* return result; // Error response
|
|
408
|
-
* }
|
|
409
|
-
*
|
|
410
|
-
* return NextResponse.json(result);
|
|
411
|
-
* }
|
|
412
|
-
* ```
|
|
413
|
-
*
|
|
414
|
-
* @see {@link clearPurchaseCache} for cache management
|
|
415
|
-
* @see {@link getPurchaseCacheStats} for cache monitoring
|
|
416
|
-
* @since 1.0.0
|
|
419
|
+
* Delegates to `checkPurchaseCore` from `@solvapay/server` for the actual logic,
|
|
420
|
+
* wrapping with Next.js-specific deduplication and response formatting.
|
|
417
421
|
*/
|
|
418
422
|
declare function checkPurchase(request: Request, options?: CheckPurchaseOptions): Promise<PurchaseCheckResult | NextResponse>;
|
|
419
423
|
|
|
420
|
-
export { type CheckPurchaseOptions, type PurchaseCheckResult, type RequestDeduplicationOptions, activatePlan, cancelRenewal, checkPurchase, clearAllPurchaseCache, clearPurchaseCache, createCheckoutSession, createCustomerSession, createPaymentIntent, createTopupPaymentIntent, getAuthenticatedUser, getCustomerBalance, getPurchaseCacheStats, listPlans, processPaymentIntent, reactivateRenewal, syncCustomer, trackUsage };
|
|
424
|
+
export { type CheckPurchaseOptions, type PurchaseCheckResult, type RequestDeduplicationOptions, activatePlan, cancelRenewal, checkPurchase, clearAllPurchaseCache, clearPurchaseCache, createCheckoutSession, createCustomerSession, createPaymentIntent, createTopupPaymentIntent, getAuthenticatedUser, getCustomerBalance, getMerchant, getProduct, getPurchaseCacheStats, listPlans, processPaymentIntent, reactivateRenewal, syncCustomer, trackUsage };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { NextResponse } from 'next/server';
|
|
2
2
|
import * as _solvapay_server from '@solvapay/server';
|
|
3
|
-
import { AuthenticatedUser, SolvaPay, CustomerBalanceResult, ActivatePlanResult, listPlansCore } from '@solvapay/server';
|
|
3
|
+
import { AuthenticatedUser, SolvaPay, CustomerBalanceResult, ActivatePlanResult, listPlansCore, getMerchantCore, getProductCore } from '@solvapay/server';
|
|
4
4
|
export { AuthMiddlewareOptions, SupabaseAuthMiddlewareOptions, createAuthMiddleware, createSupabaseAuthMiddleware } from './middleware.js';
|
|
5
5
|
import '@solvapay/auth';
|
|
6
6
|
|
|
@@ -322,7 +322,43 @@ type ListPlansSuccess = Exclude<Awaited<ReturnType<typeof listPlansCore>>, {
|
|
|
322
322
|
/**
|
|
323
323
|
* Next.js Plans Helper
|
|
324
324
|
*/
|
|
325
|
-
declare function listPlans(request: globalThis.Request
|
|
325
|
+
declare function listPlans(request: globalThis.Request, options?: {
|
|
326
|
+
solvaPay?: SolvaPay;
|
|
327
|
+
}): Promise<ListPlansSuccess | NextResponse>;
|
|
328
|
+
|
|
329
|
+
type GetMerchantSuccess = Exclude<Awaited<ReturnType<typeof getMerchantCore>>, {
|
|
330
|
+
error: string;
|
|
331
|
+
}>;
|
|
332
|
+
/**
|
|
333
|
+
* Next.js route wrapper for GET /api/merchant.
|
|
334
|
+
*
|
|
335
|
+
* @example
|
|
336
|
+
* ```ts
|
|
337
|
+
* // app/api/merchant/route.ts
|
|
338
|
+
* import { getMerchant } from '@solvapay/next/helpers'
|
|
339
|
+
* export const GET = (request: Request) => getMerchant(request)
|
|
340
|
+
* ```
|
|
341
|
+
*/
|
|
342
|
+
declare function getMerchant(request: globalThis.Request, options?: {
|
|
343
|
+
solvaPay?: SolvaPay;
|
|
344
|
+
}): Promise<GetMerchantSuccess | NextResponse>;
|
|
345
|
+
|
|
346
|
+
type GetProductSuccess = Exclude<Awaited<ReturnType<typeof getProductCore>>, {
|
|
347
|
+
error: string;
|
|
348
|
+
}>;
|
|
349
|
+
/**
|
|
350
|
+
* Next.js route wrapper for GET /api/get-product?productRef=...
|
|
351
|
+
*
|
|
352
|
+
* @example
|
|
353
|
+
* ```ts
|
|
354
|
+
* // app/api/get-product/route.ts
|
|
355
|
+
* import { getProduct } from '@solvapay/next/helpers'
|
|
356
|
+
* export const GET = (request: Request) => getProduct(request)
|
|
357
|
+
* ```
|
|
358
|
+
*/
|
|
359
|
+
declare function getProduct(request: globalThis.Request, options?: {
|
|
360
|
+
solvaPay?: SolvaPay;
|
|
361
|
+
}): Promise<GetProductSuccess | NextResponse>;
|
|
326
362
|
|
|
327
363
|
declare function trackUsage(request: globalThis.Request, body: {
|
|
328
364
|
actionType?: 'transaction' | 'api_call' | 'hour' | 'email' | 'storage' | 'custom';
|
|
@@ -380,41 +416,9 @@ interface CheckPurchaseOptions {
|
|
|
380
416
|
* - Fast path optimization using cached customer references from client
|
|
381
417
|
* - Automatic customer creation if needed
|
|
382
418
|
*
|
|
383
|
-
*
|
|
384
|
-
*
|
|
385
|
-
* 2. Gets user email and name from Supabase JWT token (if available)
|
|
386
|
-
* 3. Validates cached customer reference (if provided via header)
|
|
387
|
-
* 4. Ensures customer exists in SolvaPay backend
|
|
388
|
-
* 5. Returns customer purchase information
|
|
389
|
-
*
|
|
390
|
-
* @param request - Next.js request object (NextRequest extends Request)
|
|
391
|
-
* @param options - Configuration options
|
|
392
|
-
* @param options.deduplication - Request deduplication options (see {@link RequestDeduplicationOptions})
|
|
393
|
-
* @param options.solvaPay - Optional SolvaPay instance (creates new one if not provided)
|
|
394
|
-
* @param options.includeEmail - Whether to include email in response (default: true)
|
|
395
|
-
* @param options.includeName - Whether to include name in response (default: true)
|
|
396
|
-
* @returns Purchase check result with customer data and purchases, or NextResponse error
|
|
397
|
-
*
|
|
398
|
-
* @example
|
|
399
|
-
* ```typescript
|
|
400
|
-
* import { NextRequest, NextResponse } from 'next/server';
|
|
401
|
-
* import { checkPurchase } from '@solvapay/next';
|
|
402
|
-
*
|
|
403
|
-
* export async function GET(request: NextRequest) {
|
|
404
|
-
* const result = await checkPurchase(request);
|
|
405
|
-
*
|
|
406
|
-
* if (result instanceof NextResponse) {
|
|
407
|
-
* return result; // Error response
|
|
408
|
-
* }
|
|
409
|
-
*
|
|
410
|
-
* return NextResponse.json(result);
|
|
411
|
-
* }
|
|
412
|
-
* ```
|
|
413
|
-
*
|
|
414
|
-
* @see {@link clearPurchaseCache} for cache management
|
|
415
|
-
* @see {@link getPurchaseCacheStats} for cache monitoring
|
|
416
|
-
* @since 1.0.0
|
|
419
|
+
* Delegates to `checkPurchaseCore` from `@solvapay/server` for the actual logic,
|
|
420
|
+
* wrapping with Next.js-specific deduplication and response formatting.
|
|
417
421
|
*/
|
|
418
422
|
declare function checkPurchase(request: Request, options?: CheckPurchaseOptions): Promise<PurchaseCheckResult | NextResponse>;
|
|
419
423
|
|
|
420
|
-
export { type CheckPurchaseOptions, type PurchaseCheckResult, type RequestDeduplicationOptions, activatePlan, cancelRenewal, checkPurchase, clearAllPurchaseCache, clearPurchaseCache, createCheckoutSession, createCustomerSession, createPaymentIntent, createTopupPaymentIntent, getAuthenticatedUser, getCustomerBalance, getPurchaseCacheStats, listPlans, processPaymentIntent, reactivateRenewal, syncCustomer, trackUsage };
|
|
424
|
+
export { type CheckPurchaseOptions, type PurchaseCheckResult, type RequestDeduplicationOptions, activatePlan, cancelRenewal, checkPurchase, clearAllPurchaseCache, clearPurchaseCache, createCheckoutSession, createCustomerSession, createPaymentIntent, createTopupPaymentIntent, getAuthenticatedUser, getCustomerBalance, getMerchant, getProduct, getPurchaseCacheStats, listPlans, processPaymentIntent, reactivateRenewal, syncCustomer, trackUsage };
|
package/dist/index.js
CHANGED
|
@@ -4,9 +4,8 @@ import {
|
|
|
4
4
|
} from "./chunk-F7TBIH6W.js";
|
|
5
5
|
|
|
6
6
|
// src/index.ts
|
|
7
|
-
import { NextResponse as
|
|
8
|
-
import {
|
|
9
|
-
import { SolvaPayError } from "@solvapay/core";
|
|
7
|
+
import { NextResponse as NextResponse11 } from "next/server";
|
|
8
|
+
import { checkPurchaseCore, isErrorResult as isErrorResult11 } from "@solvapay/server";
|
|
10
9
|
|
|
11
10
|
// src/cache.ts
|
|
12
11
|
function createRequestDeduplicator(options = {}) {
|
|
@@ -336,8 +335,8 @@ async function reactivateRenewal(request, body, options = {}) {
|
|
|
336
335
|
// src/helpers/plans.ts
|
|
337
336
|
import { NextResponse as NextResponse7 } from "next/server";
|
|
338
337
|
import { listPlansCore, isErrorResult as isErrorResult7 } from "@solvapay/server";
|
|
339
|
-
async function listPlans(request) {
|
|
340
|
-
const result = await listPlansCore(request);
|
|
338
|
+
async function listPlans(request, options = {}) {
|
|
339
|
+
const result = await listPlansCore(request, options);
|
|
341
340
|
if (isErrorResult7(result)) {
|
|
342
341
|
return NextResponse7.json(
|
|
343
342
|
{ error: result.error, details: result.details },
|
|
@@ -347,111 +346,81 @@ async function listPlans(request) {
|
|
|
347
346
|
return result;
|
|
348
347
|
}
|
|
349
348
|
|
|
350
|
-
// src/helpers/
|
|
349
|
+
// src/helpers/merchant.ts
|
|
351
350
|
import { NextResponse as NextResponse8 } from "next/server";
|
|
352
|
-
import {
|
|
353
|
-
async function
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
if (isErrorResult8(userResult)) {
|
|
357
|
-
return NextResponse8.json(
|
|
358
|
-
{ error: userResult.error, details: userResult.details },
|
|
359
|
-
{ status: userResult.status }
|
|
360
|
-
);
|
|
361
|
-
}
|
|
362
|
-
const { userId, email, name } = userResult;
|
|
363
|
-
const solvaPay = options.solvaPay || createSolvaPay();
|
|
364
|
-
const customerRef = await solvaPay.ensureCustomer(userId, userId, {
|
|
365
|
-
email: email || void 0,
|
|
366
|
-
name: name || void 0
|
|
367
|
-
});
|
|
368
|
-
await solvaPay.trackUsage({
|
|
369
|
-
customerRef,
|
|
370
|
-
actionType: body.actionType,
|
|
371
|
-
units: body.units,
|
|
372
|
-
productRef: body.productRef,
|
|
373
|
-
description: body.description,
|
|
374
|
-
metadata: body.metadata
|
|
375
|
-
});
|
|
376
|
-
return NextResponse8.json({ success: true });
|
|
377
|
-
} catch (error) {
|
|
378
|
-
console.error("[trackUsage] Error:", error);
|
|
379
|
-
const message = error instanceof Error ? error.message : "Unknown error";
|
|
351
|
+
import { getMerchantCore, isErrorResult as isErrorResult8 } from "@solvapay/server";
|
|
352
|
+
async function getMerchant(request, options = {}) {
|
|
353
|
+
const result = await getMerchantCore(request, options);
|
|
354
|
+
if (isErrorResult8(result)) {
|
|
380
355
|
return NextResponse8.json(
|
|
381
|
-
{ error:
|
|
382
|
-
{ status:
|
|
356
|
+
{ error: result.error, details: result.details },
|
|
357
|
+
{ status: result.status }
|
|
358
|
+
);
|
|
359
|
+
}
|
|
360
|
+
return result;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
// src/helpers/product.ts
|
|
364
|
+
import { NextResponse as NextResponse9 } from "next/server";
|
|
365
|
+
import { getProductCore, isErrorResult as isErrorResult9 } from "@solvapay/server";
|
|
366
|
+
async function getProduct(request, options = {}) {
|
|
367
|
+
const result = await getProductCore(request, options);
|
|
368
|
+
if (isErrorResult9(result)) {
|
|
369
|
+
return NextResponse9.json(
|
|
370
|
+
{ error: result.error, details: result.details },
|
|
371
|
+
{ status: result.status }
|
|
372
|
+
);
|
|
373
|
+
}
|
|
374
|
+
return result;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
// src/helpers/usage.ts
|
|
378
|
+
import { NextResponse as NextResponse10 } from "next/server";
|
|
379
|
+
import { trackUsageCore, isErrorResult as isErrorResult10 } from "@solvapay/server";
|
|
380
|
+
async function trackUsage(request, body, options = {}) {
|
|
381
|
+
const result = await trackUsageCore(request, body, options);
|
|
382
|
+
if (isErrorResult10(result)) {
|
|
383
|
+
return NextResponse10.json(
|
|
384
|
+
{ error: result.error, details: result.details },
|
|
385
|
+
{ status: result.status }
|
|
383
386
|
);
|
|
384
387
|
}
|
|
388
|
+
return NextResponse10.json(result);
|
|
385
389
|
}
|
|
386
390
|
|
|
387
391
|
// src/index.ts
|
|
388
392
|
async function checkPurchase(request, options = {}) {
|
|
393
|
+
const deduplicator = getSharedDeduplicator(options.deduplication);
|
|
389
394
|
try {
|
|
390
|
-
const { requireUserId
|
|
395
|
+
const { requireUserId } = await import("@solvapay/auth");
|
|
391
396
|
const userIdOrError = requireUserId(request);
|
|
392
397
|
if (userIdOrError instanceof Response) {
|
|
393
398
|
const clonedResponse = userIdOrError.clone();
|
|
394
399
|
const body = await clonedResponse.json().catch(() => ({ error: "Unauthorized" }));
|
|
395
|
-
return
|
|
400
|
+
return NextResponse11.json(body, { status: userIdOrError.status });
|
|
396
401
|
}
|
|
397
402
|
const userId = userIdOrError;
|
|
398
|
-
const
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
if (customer && customer.customerRef) {
|
|
406
|
-
if (customer.externalRef && customer.externalRef === userId) {
|
|
407
|
-
const filteredPurchases = (customer.purchases || []).filter(
|
|
408
|
-
(p) => p.status === "active"
|
|
409
|
-
);
|
|
410
|
-
return {
|
|
411
|
-
customerRef: customer.customerRef,
|
|
412
|
-
email: customer.email,
|
|
413
|
-
name: customer.name,
|
|
414
|
-
purchases: filteredPurchases
|
|
415
|
-
};
|
|
416
|
-
}
|
|
417
|
-
}
|
|
418
|
-
} catch {
|
|
419
|
-
}
|
|
420
|
-
}
|
|
421
|
-
const deduplicator = getSharedDeduplicator(options.deduplication);
|
|
422
|
-
const response = await deduplicator.deduplicate(userId, async () => {
|
|
423
|
-
try {
|
|
424
|
-
const ensuredCustomerRef = await solvaPay.ensureCustomer(userId, userId, {
|
|
425
|
-
email: email || void 0,
|
|
426
|
-
name: name || void 0
|
|
403
|
+
const response = await deduplicator.deduplicate(
|
|
404
|
+
userId,
|
|
405
|
+
async () => {
|
|
406
|
+
return await checkPurchaseCore(request, {
|
|
407
|
+
solvaPay: options.solvaPay,
|
|
408
|
+
includeEmail: options.includeEmail,
|
|
409
|
+
includeName: options.includeName
|
|
427
410
|
});
|
|
428
|
-
const customer = await solvaPay.getCustomer({ customerRef: ensuredCustomerRef });
|
|
429
|
-
const filteredPurchases = (customer.purchases || []).filter(
|
|
430
|
-
(p) => p.status === "active"
|
|
431
|
-
);
|
|
432
|
-
const result = {
|
|
433
|
-
customerRef: customer.customerRef || userId,
|
|
434
|
-
email: customer.email,
|
|
435
|
-
name: customer.name,
|
|
436
|
-
purchases: filteredPurchases
|
|
437
|
-
};
|
|
438
|
-
return result;
|
|
439
|
-
} catch (error) {
|
|
440
|
-
console.error("[checkPurchase] Error fetching customer:", error);
|
|
441
|
-
return {
|
|
442
|
-
customerRef: userId,
|
|
443
|
-
purchases: []
|
|
444
|
-
};
|
|
445
411
|
}
|
|
446
|
-
|
|
412
|
+
);
|
|
413
|
+
if (isErrorResult11(response)) {
|
|
414
|
+
return NextResponse11.json(
|
|
415
|
+
{ error: response.error, details: response.details },
|
|
416
|
+
{ status: response.status }
|
|
417
|
+
);
|
|
418
|
+
}
|
|
447
419
|
return response;
|
|
448
420
|
} catch (error) {
|
|
449
421
|
console.error("Check purchase failed:", error);
|
|
450
|
-
if (error instanceof SolvaPayError) {
|
|
451
|
-
return NextResponse9.json({ error: error.message }, { status: 500 });
|
|
452
|
-
}
|
|
453
422
|
const errorMessage = error instanceof Error ? error.message : "Unknown error";
|
|
454
|
-
return
|
|
423
|
+
return NextResponse11.json(
|
|
455
424
|
{ error: "Failed to check purchase", details: errorMessage },
|
|
456
425
|
{ status: 500 }
|
|
457
426
|
);
|
|
@@ -471,6 +440,8 @@ export {
|
|
|
471
440
|
createTopupPaymentIntent,
|
|
472
441
|
getAuthenticatedUser,
|
|
473
442
|
getCustomerBalance,
|
|
443
|
+
getMerchant,
|
|
444
|
+
getProduct,
|
|
474
445
|
getPurchaseCacheStats,
|
|
475
446
|
listPlans,
|
|
476
447
|
processPaymentIntent,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@solvapay/next",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.8-preview.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.cjs",
|
|
6
6
|
"module": "./dist/index.js",
|
|
@@ -34,9 +34,9 @@
|
|
|
34
34
|
},
|
|
35
35
|
"sideEffects": false,
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@solvapay/auth": "1.0.
|
|
38
|
-
"@solvapay/
|
|
39
|
-
"@solvapay/
|
|
37
|
+
"@solvapay/auth": "1.0.8-preview.2",
|
|
38
|
+
"@solvapay/server": "1.0.8-preview.2",
|
|
39
|
+
"@solvapay/core": "1.0.8-preview.2"
|
|
40
40
|
},
|
|
41
41
|
"peerDependencies": {
|
|
42
42
|
"next": ">=13.0.0"
|