@waffo/pancake-nextjs 0.7.0 → 0.9.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/CHANGELOG.md +31 -0
- package/README.md +128 -8
- package/dist/index.cjs +2 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +24 -9
- package/dist/index.d.ts +24 -9
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/server.cjs +72 -11
- package/dist/server.cjs.map +1 -1
- package/dist/server.d.cts +155 -9
- package/dist/server.d.ts +155 -9
- package/dist/server.js +71 -11
- package/dist/server.js.map +1 -1
- package/package.json +2 -2
package/dist/server.d.cts
CHANGED
|
@@ -1,20 +1,37 @@
|
|
|
1
|
-
import { IssueSessionTokenParams, SessionToken, AnonymousCheckoutParams, AuthenticatedCheckoutParams, CheckoutSessionResult, AuthenticatedCheckoutResult, GraphQLParams, GraphQLResponse, WaffoPancakeConfig } from '@waffo/pancake-ts';
|
|
1
|
+
import { RequestOptions, IssueSessionTokenParams, SessionToken, AnonymousCheckoutParams, AuthenticatedCheckoutParams, CreatePlanChangeSessionParams, AuthenticatedPlanChangeParams, CheckoutSessionResult, AuthenticatedCheckoutResult, GraphQLParams, GraphQLResponse, WaffoPancakeConfig } from '@waffo/pancake-ts';
|
|
2
2
|
|
|
3
|
-
/**
|
|
3
|
+
/**
|
|
4
|
+
* Parameters for the checkout server action.
|
|
5
|
+
*
|
|
6
|
+
* The `type` field selects the flow: a new purchase (`anonymous` / `authenticated`)
|
|
7
|
+
* or a plan change for an existing subscription (`planChange` /
|
|
8
|
+
* `authenticatedPlanChange`, which carry the required `originOrderId`).
|
|
9
|
+
*/
|
|
4
10
|
type CheckoutActionParams = ({
|
|
5
11
|
type?: "anonymous";
|
|
6
12
|
} & AnonymousCheckoutParams) | ({
|
|
7
13
|
type: "authenticated";
|
|
8
|
-
} & AuthenticatedCheckoutParams)
|
|
14
|
+
} & AuthenticatedCheckoutParams) | ({
|
|
15
|
+
type: "planChange";
|
|
16
|
+
} & CreatePlanChangeSessionParams) | ({
|
|
17
|
+
type: "authenticatedPlanChange";
|
|
18
|
+
} & AuthenticatedPlanChangeParams);
|
|
9
19
|
/** Result of the checkout server action */
|
|
10
20
|
type CheckoutActionResult = CheckoutSessionResult | AuthenticatedCheckoutResult;
|
|
11
|
-
/**
|
|
12
|
-
|
|
21
|
+
/**
|
|
22
|
+
* Server action signature for checkout.
|
|
23
|
+
*
|
|
24
|
+
* The optional `options` carries an `idempotencyKey`; without one no key is sent
|
|
25
|
+
* and a retried call creates a second session.
|
|
26
|
+
*/
|
|
27
|
+
type CheckoutAction = (params: CheckoutActionParams, options?: RequestOptions) => Promise<CheckoutActionResult>;
|
|
13
28
|
/**
|
|
14
29
|
* Create a server action that handles checkout session creation.
|
|
15
30
|
*
|
|
16
31
|
* The private key is captured in the closure and never sent to the client.
|
|
17
32
|
*
|
|
33
|
+
* Handles both new purchases and plan changes; `params.type` selects the flow.
|
|
34
|
+
*
|
|
18
35
|
* @param config - WaffoPancake client configuration (merchantId + privateKey)
|
|
19
36
|
* @returns A server action function
|
|
20
37
|
*
|
|
@@ -28,13 +45,32 @@ type CheckoutAction = (params: CheckoutActionParams) => Promise<CheckoutActionRe
|
|
|
28
45
|
* privateKey: process.env.WAFFO_PRIVATE_KEY!,
|
|
29
46
|
* });
|
|
30
47
|
* ```
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* ```ts
|
|
51
|
+
* // Plan change link for an existing subscription — originOrderId is required
|
|
52
|
+
* const session = await checkout({
|
|
53
|
+
* type: "planChange",
|
|
54
|
+
* originOrderId: "ORD_xxx",
|
|
55
|
+
* productId: "PROD_target_plan",
|
|
56
|
+
* currency: "USD",
|
|
57
|
+
* });
|
|
58
|
+
* // session.checkoutUrl points at the change confirmation page
|
|
59
|
+
* ```
|
|
31
60
|
*/
|
|
32
61
|
declare function createCheckoutAction(config: WaffoPancakeConfig): CheckoutAction;
|
|
33
62
|
/** Server action signature for issuing customer tokens */
|
|
34
|
-
type CustomerTokenAction = (params: IssueSessionTokenParams) => Promise<SessionToken>;
|
|
63
|
+
type CustomerTokenAction = (params: IssueSessionTokenParams, options?: RequestOptions) => Promise<SessionToken>;
|
|
35
64
|
/**
|
|
36
65
|
* Create a server action that issues customer session tokens.
|
|
37
66
|
*
|
|
67
|
+
* This is a generic token primitive: it signs whatever `buyerIdentity` it is
|
|
68
|
+
* handed. Never expose it to the browser as a portal or sign-in entry — a
|
|
69
|
+
* Server Action is callable with arbitrary arguments, so a client-chosen
|
|
70
|
+
* `buyerIdentity` would yield another customer's token. To send a signed-in
|
|
71
|
+
* customer to the customer portal, use {@link createCustomerPortalRedirect},
|
|
72
|
+
* which derives identity from your own session.
|
|
73
|
+
*
|
|
38
74
|
* @param config - WaffoPancake client configuration
|
|
39
75
|
* @returns A server action function
|
|
40
76
|
*
|
|
@@ -50,16 +86,126 @@ type CustomerTokenAction = (params: IssueSessionTokenParams) => Promise<SessionT
|
|
|
50
86
|
* ```
|
|
51
87
|
*/
|
|
52
88
|
declare function createCustomerTokenAction(config: WaffoPancakeConfig): CustomerTokenAction;
|
|
89
|
+
/**
|
|
90
|
+
* Store and customer identity for a customer portal link, resolved by the
|
|
91
|
+
* merchant app from its own authenticated session.
|
|
92
|
+
*/
|
|
93
|
+
interface AuthenticatedPortalCustomer {
|
|
94
|
+
/** Store ID (Short ID `STO_xxx`) whose portal the customer enters */
|
|
95
|
+
storeId: string;
|
|
96
|
+
/** Customer identity in your system — the same value used for authenticated checkout */
|
|
97
|
+
buyerIdentity: string;
|
|
98
|
+
}
|
|
99
|
+
/** Options for {@link createCustomerPortalRedirect}. */
|
|
100
|
+
interface CustomerPortalRedirectOptions {
|
|
101
|
+
/**
|
|
102
|
+
* Resolve the signed-in customer from YOUR app's authenticated session
|
|
103
|
+
* (session cookie, auth library, …). Return `null` when nobody is signed in.
|
|
104
|
+
*
|
|
105
|
+
* Must not read `buyerIdentity` or `storeId` from anything the browser
|
|
106
|
+
* controls — query string, body, form fields or custom headers. Whoever
|
|
107
|
+
* controls `buyerIdentity` gets that customer's portal.
|
|
108
|
+
*/
|
|
109
|
+
resolveAuthenticatedCustomer: (request: Request) => Promise<AuthenticatedPortalCustomer | null> | AuthenticatedPortalCustomer | null;
|
|
110
|
+
/**
|
|
111
|
+
* Where to send a visitor for whom the resolver returned `null`. A path or
|
|
112
|
+
* absolute URL, resolved against the request URL; a function receives the
|
|
113
|
+
* request (e.g. to add your own `returnTo`). Omit to answer 401 instead.
|
|
114
|
+
*
|
|
115
|
+
* Build it from constants or an allow-list, never by copying request
|
|
116
|
+
* parameters verbatim (e.g. a `?next=` value) — that turns this route into an
|
|
117
|
+
* open redirect.
|
|
118
|
+
*/
|
|
119
|
+
loginUrl?: string | ((request: Request) => string);
|
|
120
|
+
/**
|
|
121
|
+
* Build the response when creating the portal link fails (API error, invalid
|
|
122
|
+
* store ID, network error). This is the place for your own logging and error
|
|
123
|
+
* reporting. Defaults to a 502 JSON `{ error }` response with a generic
|
|
124
|
+
* message, after one `console.error` line carrying only the error message;
|
|
125
|
+
* the error itself is not echoed to the browser.
|
|
126
|
+
*/
|
|
127
|
+
onError?: (error: unknown, request: Request) => Response | Promise<Response>;
|
|
128
|
+
}
|
|
129
|
+
/** GET Route Handler returned by {@link createCustomerPortalRedirect}. */
|
|
130
|
+
type CustomerPortalRouteHandler = (request: Request) => Promise<Response>;
|
|
131
|
+
/**
|
|
132
|
+
* Create a GET Route Handler that sends the signed-in customer to your store's
|
|
133
|
+
* Pancake customer portal, without the portal's email verification step.
|
|
134
|
+
*
|
|
135
|
+
* Behavior:
|
|
136
|
+
* - Calls `resolveAuthenticatedCustomer(request)` — your own session check — to
|
|
137
|
+
* get `{ storeId, buyerIdentity }`. Nothing is read from the request's query
|
|
138
|
+
* string, body or headers by the SDK
|
|
139
|
+
* - Signed in: creates a portal link with `client.auth.createCustomerPortalLink()`
|
|
140
|
+
* and answers `302` to `portalUrl` (which carries `#token=...`)
|
|
141
|
+
* - Not signed in: `302` to `loginUrl` when set, otherwise `401`
|
|
142
|
+
* - Link creation fails: `onError(error, request)`, or by default one server-side
|
|
143
|
+
* `console.error` line with the error message and a generic `502 { error }`
|
|
144
|
+
*
|
|
145
|
+
* Side effects:
|
|
146
|
+
* - One signed API request per signed-in visit; each visit issues a new portal session
|
|
147
|
+
* - Every response it builds (not a custom `onError` one) sets `Cache-Control: no-store` and `Referrer-Policy: no-referrer`
|
|
148
|
+
* so the tokenized `Location` is neither cached nor forwarded as a Referer
|
|
149
|
+
*
|
|
150
|
+
* Boundary conditions:
|
|
151
|
+
* - The portal environment is the environment of the API Key in `config`
|
|
152
|
+
* (test key → test portal, prod key → prod portal)
|
|
153
|
+
* - Errors thrown by `resolveAuthenticatedCustomer` propagate (Next.js answers 500)
|
|
154
|
+
* - The default error log is the message only, with any `#token=` fragment redacted;
|
|
155
|
+
* pass `onError` to log or report failures your own way
|
|
156
|
+
* - `loginUrl` must not echo request parameters verbatim, or the route becomes an open redirect
|
|
157
|
+
*
|
|
158
|
+
* A Route Handler rather than a Server Action: the portal entry is a plain link
|
|
159
|
+
* navigation, and only an HTTP redirect keeps the tokenized URL out of client
|
|
160
|
+
* JavaScript while letting the response carry `no-store` / `no-referrer`.
|
|
161
|
+
*
|
|
162
|
+
* @param config - WaffoPancake client configuration (merchantId + privateKey)
|
|
163
|
+
* @param options - Session resolver, login redirect and error handling
|
|
164
|
+
* @returns A Next.js GET Route Handler
|
|
165
|
+
*
|
|
166
|
+
* @example
|
|
167
|
+
* ```ts
|
|
168
|
+
* // app/account/billing-portal/route.ts
|
|
169
|
+
* import { createCustomerPortalRedirect } from "@waffo/pancake-nextjs/server";
|
|
170
|
+
* import { auth } from "@/lib/auth"; // your auth library
|
|
171
|
+
*
|
|
172
|
+
* export const dynamic = "force-dynamic";
|
|
173
|
+
*
|
|
174
|
+
* export const GET = createCustomerPortalRedirect(
|
|
175
|
+
* { merchantId: process.env.WAFFO_MERCHANT_ID!, privateKey: process.env.WAFFO_PRIVATE_KEY! },
|
|
176
|
+
* {
|
|
177
|
+
* resolveAuthenticatedCustomer: async () => {
|
|
178
|
+
* const session = await auth();
|
|
179
|
+
* if (!session?.user) return null;
|
|
180
|
+
* return { storeId: process.env.WAFFO_STORE_ID!, buyerIdentity: session.user.id };
|
|
181
|
+
* },
|
|
182
|
+
* loginUrl: "/login?returnTo=/account/billing-portal",
|
|
183
|
+
* },
|
|
184
|
+
* );
|
|
185
|
+
* // In a page: <a href="/account/billing-portal">Manage billing</a>
|
|
186
|
+
* ```
|
|
187
|
+
*/
|
|
188
|
+
declare function createCustomerPortalRedirect(config: WaffoPancakeConfig, options: CustomerPortalRedirectOptions): CustomerPortalRouteHandler;
|
|
53
189
|
/** Customer action types */
|
|
54
|
-
type CustomerSessionActionType = "cancelSubscription" | "cancelOnetimeOrder" | "reactivateSubscription" | "createRefundTicket" | "resubmitRefundTicket" | "query";
|
|
190
|
+
type CustomerSessionActionType = "cancelSubscription" | "cancelOnetimeOrder" | "reactivateSubscription" | "createRefundTicket" | "resubmitRefundTicket" | "createPlanChangeSession" | "query";
|
|
55
191
|
/** Server action signature for customer session operations */
|
|
56
|
-
type CustomerSessionAction = (token: string, actionType: CustomerSessionActionType, params: unknown) => Promise<unknown>;
|
|
192
|
+
type CustomerSessionAction = (token: string, actionType: CustomerSessionActionType, params: unknown, options?: RequestOptions) => Promise<unknown>;
|
|
57
193
|
/**
|
|
58
194
|
* Create a server action that executes customer self-service operations.
|
|
59
195
|
*
|
|
60
196
|
* `config.environment` is required — session tokens carry no environment, and the
|
|
61
197
|
* gateway rejects a session request without the matching header.
|
|
62
198
|
*
|
|
199
|
+
* `createPlanChangeSession` is the customer-driven half of a plan change: it returns
|
|
200
|
+
* a confirmation-page URL, and the platform allows it only when the subscription
|
|
201
|
+
* belongs to that customer, the target plan is in the same product group, and that
|
|
202
|
+
* group's `selfServicePlanChange` is on — otherwise 403. The merchant-only pricing
|
|
203
|
+
* fields are not part of its params; the platform drops them on this path silently.
|
|
204
|
+
*
|
|
205
|
+
* No call sends an idempotency key unless you pass one (`options.idempotencyKey`,
|
|
206
|
+
* the last argument) — the same rule as every other method in the SDK — so a write
|
|
207
|
+
* retried after a timeout executes twice.
|
|
208
|
+
*
|
|
63
209
|
* @param config - WaffoPancake client configuration
|
|
64
210
|
* @returns A server action function
|
|
65
211
|
*
|
|
@@ -107,4 +253,4 @@ type BuyerSessionAction = CustomerSessionAction;
|
|
|
107
253
|
/** @deprecated Use {@link createCustomerSessionAction} instead. */
|
|
108
254
|
declare const createBuyerSessionAction: typeof createCustomerSessionAction;
|
|
109
255
|
|
|
110
|
-
export { type BuyerSessionAction, type BuyerSessionActionType, type BuyerTokenAction, type CheckoutAction, type CheckoutActionParams, type CheckoutActionResult, type CustomerSessionAction, type CustomerSessionActionType, type CustomerTokenAction, type MerchantQueryAction, createBuyerSessionAction, createBuyerTokenAction, createCheckoutAction, createCustomerSessionAction, createCustomerTokenAction, createMerchantQueryAction };
|
|
256
|
+
export { type AuthenticatedPortalCustomer, type BuyerSessionAction, type BuyerSessionActionType, type BuyerTokenAction, type CheckoutAction, type CheckoutActionParams, type CheckoutActionResult, type CustomerPortalRedirectOptions, type CustomerPortalRouteHandler, type CustomerSessionAction, type CustomerSessionActionType, type CustomerTokenAction, type MerchantQueryAction, createBuyerSessionAction, createBuyerTokenAction, createCheckoutAction, createCustomerPortalRedirect, createCustomerSessionAction, createCustomerTokenAction, createMerchantQueryAction };
|
package/dist/server.d.ts
CHANGED
|
@@ -1,20 +1,37 @@
|
|
|
1
|
-
import { IssueSessionTokenParams, SessionToken, AnonymousCheckoutParams, AuthenticatedCheckoutParams, CheckoutSessionResult, AuthenticatedCheckoutResult, GraphQLParams, GraphQLResponse, WaffoPancakeConfig } from '@waffo/pancake-ts';
|
|
1
|
+
import { RequestOptions, IssueSessionTokenParams, SessionToken, AnonymousCheckoutParams, AuthenticatedCheckoutParams, CreatePlanChangeSessionParams, AuthenticatedPlanChangeParams, CheckoutSessionResult, AuthenticatedCheckoutResult, GraphQLParams, GraphQLResponse, WaffoPancakeConfig } from '@waffo/pancake-ts';
|
|
2
2
|
|
|
3
|
-
/**
|
|
3
|
+
/**
|
|
4
|
+
* Parameters for the checkout server action.
|
|
5
|
+
*
|
|
6
|
+
* The `type` field selects the flow: a new purchase (`anonymous` / `authenticated`)
|
|
7
|
+
* or a plan change for an existing subscription (`planChange` /
|
|
8
|
+
* `authenticatedPlanChange`, which carry the required `originOrderId`).
|
|
9
|
+
*/
|
|
4
10
|
type CheckoutActionParams = ({
|
|
5
11
|
type?: "anonymous";
|
|
6
12
|
} & AnonymousCheckoutParams) | ({
|
|
7
13
|
type: "authenticated";
|
|
8
|
-
} & AuthenticatedCheckoutParams)
|
|
14
|
+
} & AuthenticatedCheckoutParams) | ({
|
|
15
|
+
type: "planChange";
|
|
16
|
+
} & CreatePlanChangeSessionParams) | ({
|
|
17
|
+
type: "authenticatedPlanChange";
|
|
18
|
+
} & AuthenticatedPlanChangeParams);
|
|
9
19
|
/** Result of the checkout server action */
|
|
10
20
|
type CheckoutActionResult = CheckoutSessionResult | AuthenticatedCheckoutResult;
|
|
11
|
-
/**
|
|
12
|
-
|
|
21
|
+
/**
|
|
22
|
+
* Server action signature for checkout.
|
|
23
|
+
*
|
|
24
|
+
* The optional `options` carries an `idempotencyKey`; without one no key is sent
|
|
25
|
+
* and a retried call creates a second session.
|
|
26
|
+
*/
|
|
27
|
+
type CheckoutAction = (params: CheckoutActionParams, options?: RequestOptions) => Promise<CheckoutActionResult>;
|
|
13
28
|
/**
|
|
14
29
|
* Create a server action that handles checkout session creation.
|
|
15
30
|
*
|
|
16
31
|
* The private key is captured in the closure and never sent to the client.
|
|
17
32
|
*
|
|
33
|
+
* Handles both new purchases and plan changes; `params.type` selects the flow.
|
|
34
|
+
*
|
|
18
35
|
* @param config - WaffoPancake client configuration (merchantId + privateKey)
|
|
19
36
|
* @returns A server action function
|
|
20
37
|
*
|
|
@@ -28,13 +45,32 @@ type CheckoutAction = (params: CheckoutActionParams) => Promise<CheckoutActionRe
|
|
|
28
45
|
* privateKey: process.env.WAFFO_PRIVATE_KEY!,
|
|
29
46
|
* });
|
|
30
47
|
* ```
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* ```ts
|
|
51
|
+
* // Plan change link for an existing subscription — originOrderId is required
|
|
52
|
+
* const session = await checkout({
|
|
53
|
+
* type: "planChange",
|
|
54
|
+
* originOrderId: "ORD_xxx",
|
|
55
|
+
* productId: "PROD_target_plan",
|
|
56
|
+
* currency: "USD",
|
|
57
|
+
* });
|
|
58
|
+
* // session.checkoutUrl points at the change confirmation page
|
|
59
|
+
* ```
|
|
31
60
|
*/
|
|
32
61
|
declare function createCheckoutAction(config: WaffoPancakeConfig): CheckoutAction;
|
|
33
62
|
/** Server action signature for issuing customer tokens */
|
|
34
|
-
type CustomerTokenAction = (params: IssueSessionTokenParams) => Promise<SessionToken>;
|
|
63
|
+
type CustomerTokenAction = (params: IssueSessionTokenParams, options?: RequestOptions) => Promise<SessionToken>;
|
|
35
64
|
/**
|
|
36
65
|
* Create a server action that issues customer session tokens.
|
|
37
66
|
*
|
|
67
|
+
* This is a generic token primitive: it signs whatever `buyerIdentity` it is
|
|
68
|
+
* handed. Never expose it to the browser as a portal or sign-in entry — a
|
|
69
|
+
* Server Action is callable with arbitrary arguments, so a client-chosen
|
|
70
|
+
* `buyerIdentity` would yield another customer's token. To send a signed-in
|
|
71
|
+
* customer to the customer portal, use {@link createCustomerPortalRedirect},
|
|
72
|
+
* which derives identity from your own session.
|
|
73
|
+
*
|
|
38
74
|
* @param config - WaffoPancake client configuration
|
|
39
75
|
* @returns A server action function
|
|
40
76
|
*
|
|
@@ -50,16 +86,126 @@ type CustomerTokenAction = (params: IssueSessionTokenParams) => Promise<SessionT
|
|
|
50
86
|
* ```
|
|
51
87
|
*/
|
|
52
88
|
declare function createCustomerTokenAction(config: WaffoPancakeConfig): CustomerTokenAction;
|
|
89
|
+
/**
|
|
90
|
+
* Store and customer identity for a customer portal link, resolved by the
|
|
91
|
+
* merchant app from its own authenticated session.
|
|
92
|
+
*/
|
|
93
|
+
interface AuthenticatedPortalCustomer {
|
|
94
|
+
/** Store ID (Short ID `STO_xxx`) whose portal the customer enters */
|
|
95
|
+
storeId: string;
|
|
96
|
+
/** Customer identity in your system — the same value used for authenticated checkout */
|
|
97
|
+
buyerIdentity: string;
|
|
98
|
+
}
|
|
99
|
+
/** Options for {@link createCustomerPortalRedirect}. */
|
|
100
|
+
interface CustomerPortalRedirectOptions {
|
|
101
|
+
/**
|
|
102
|
+
* Resolve the signed-in customer from YOUR app's authenticated session
|
|
103
|
+
* (session cookie, auth library, …). Return `null` when nobody is signed in.
|
|
104
|
+
*
|
|
105
|
+
* Must not read `buyerIdentity` or `storeId` from anything the browser
|
|
106
|
+
* controls — query string, body, form fields or custom headers. Whoever
|
|
107
|
+
* controls `buyerIdentity` gets that customer's portal.
|
|
108
|
+
*/
|
|
109
|
+
resolveAuthenticatedCustomer: (request: Request) => Promise<AuthenticatedPortalCustomer | null> | AuthenticatedPortalCustomer | null;
|
|
110
|
+
/**
|
|
111
|
+
* Where to send a visitor for whom the resolver returned `null`. A path or
|
|
112
|
+
* absolute URL, resolved against the request URL; a function receives the
|
|
113
|
+
* request (e.g. to add your own `returnTo`). Omit to answer 401 instead.
|
|
114
|
+
*
|
|
115
|
+
* Build it from constants or an allow-list, never by copying request
|
|
116
|
+
* parameters verbatim (e.g. a `?next=` value) — that turns this route into an
|
|
117
|
+
* open redirect.
|
|
118
|
+
*/
|
|
119
|
+
loginUrl?: string | ((request: Request) => string);
|
|
120
|
+
/**
|
|
121
|
+
* Build the response when creating the portal link fails (API error, invalid
|
|
122
|
+
* store ID, network error). This is the place for your own logging and error
|
|
123
|
+
* reporting. Defaults to a 502 JSON `{ error }` response with a generic
|
|
124
|
+
* message, after one `console.error` line carrying only the error message;
|
|
125
|
+
* the error itself is not echoed to the browser.
|
|
126
|
+
*/
|
|
127
|
+
onError?: (error: unknown, request: Request) => Response | Promise<Response>;
|
|
128
|
+
}
|
|
129
|
+
/** GET Route Handler returned by {@link createCustomerPortalRedirect}. */
|
|
130
|
+
type CustomerPortalRouteHandler = (request: Request) => Promise<Response>;
|
|
131
|
+
/**
|
|
132
|
+
* Create a GET Route Handler that sends the signed-in customer to your store's
|
|
133
|
+
* Pancake customer portal, without the portal's email verification step.
|
|
134
|
+
*
|
|
135
|
+
* Behavior:
|
|
136
|
+
* - Calls `resolveAuthenticatedCustomer(request)` — your own session check — to
|
|
137
|
+
* get `{ storeId, buyerIdentity }`. Nothing is read from the request's query
|
|
138
|
+
* string, body or headers by the SDK
|
|
139
|
+
* - Signed in: creates a portal link with `client.auth.createCustomerPortalLink()`
|
|
140
|
+
* and answers `302` to `portalUrl` (which carries `#token=...`)
|
|
141
|
+
* - Not signed in: `302` to `loginUrl` when set, otherwise `401`
|
|
142
|
+
* - Link creation fails: `onError(error, request)`, or by default one server-side
|
|
143
|
+
* `console.error` line with the error message and a generic `502 { error }`
|
|
144
|
+
*
|
|
145
|
+
* Side effects:
|
|
146
|
+
* - One signed API request per signed-in visit; each visit issues a new portal session
|
|
147
|
+
* - Every response it builds (not a custom `onError` one) sets `Cache-Control: no-store` and `Referrer-Policy: no-referrer`
|
|
148
|
+
* so the tokenized `Location` is neither cached nor forwarded as a Referer
|
|
149
|
+
*
|
|
150
|
+
* Boundary conditions:
|
|
151
|
+
* - The portal environment is the environment of the API Key in `config`
|
|
152
|
+
* (test key → test portal, prod key → prod portal)
|
|
153
|
+
* - Errors thrown by `resolveAuthenticatedCustomer` propagate (Next.js answers 500)
|
|
154
|
+
* - The default error log is the message only, with any `#token=` fragment redacted;
|
|
155
|
+
* pass `onError` to log or report failures your own way
|
|
156
|
+
* - `loginUrl` must not echo request parameters verbatim, or the route becomes an open redirect
|
|
157
|
+
*
|
|
158
|
+
* A Route Handler rather than a Server Action: the portal entry is a plain link
|
|
159
|
+
* navigation, and only an HTTP redirect keeps the tokenized URL out of client
|
|
160
|
+
* JavaScript while letting the response carry `no-store` / `no-referrer`.
|
|
161
|
+
*
|
|
162
|
+
* @param config - WaffoPancake client configuration (merchantId + privateKey)
|
|
163
|
+
* @param options - Session resolver, login redirect and error handling
|
|
164
|
+
* @returns A Next.js GET Route Handler
|
|
165
|
+
*
|
|
166
|
+
* @example
|
|
167
|
+
* ```ts
|
|
168
|
+
* // app/account/billing-portal/route.ts
|
|
169
|
+
* import { createCustomerPortalRedirect } from "@waffo/pancake-nextjs/server";
|
|
170
|
+
* import { auth } from "@/lib/auth"; // your auth library
|
|
171
|
+
*
|
|
172
|
+
* export const dynamic = "force-dynamic";
|
|
173
|
+
*
|
|
174
|
+
* export const GET = createCustomerPortalRedirect(
|
|
175
|
+
* { merchantId: process.env.WAFFO_MERCHANT_ID!, privateKey: process.env.WAFFO_PRIVATE_KEY! },
|
|
176
|
+
* {
|
|
177
|
+
* resolveAuthenticatedCustomer: async () => {
|
|
178
|
+
* const session = await auth();
|
|
179
|
+
* if (!session?.user) return null;
|
|
180
|
+
* return { storeId: process.env.WAFFO_STORE_ID!, buyerIdentity: session.user.id };
|
|
181
|
+
* },
|
|
182
|
+
* loginUrl: "/login?returnTo=/account/billing-portal",
|
|
183
|
+
* },
|
|
184
|
+
* );
|
|
185
|
+
* // In a page: <a href="/account/billing-portal">Manage billing</a>
|
|
186
|
+
* ```
|
|
187
|
+
*/
|
|
188
|
+
declare function createCustomerPortalRedirect(config: WaffoPancakeConfig, options: CustomerPortalRedirectOptions): CustomerPortalRouteHandler;
|
|
53
189
|
/** Customer action types */
|
|
54
|
-
type CustomerSessionActionType = "cancelSubscription" | "cancelOnetimeOrder" | "reactivateSubscription" | "createRefundTicket" | "resubmitRefundTicket" | "query";
|
|
190
|
+
type CustomerSessionActionType = "cancelSubscription" | "cancelOnetimeOrder" | "reactivateSubscription" | "createRefundTicket" | "resubmitRefundTicket" | "createPlanChangeSession" | "query";
|
|
55
191
|
/** Server action signature for customer session operations */
|
|
56
|
-
type CustomerSessionAction = (token: string, actionType: CustomerSessionActionType, params: unknown) => Promise<unknown>;
|
|
192
|
+
type CustomerSessionAction = (token: string, actionType: CustomerSessionActionType, params: unknown, options?: RequestOptions) => Promise<unknown>;
|
|
57
193
|
/**
|
|
58
194
|
* Create a server action that executes customer self-service operations.
|
|
59
195
|
*
|
|
60
196
|
* `config.environment` is required — session tokens carry no environment, and the
|
|
61
197
|
* gateway rejects a session request without the matching header.
|
|
62
198
|
*
|
|
199
|
+
* `createPlanChangeSession` is the customer-driven half of a plan change: it returns
|
|
200
|
+
* a confirmation-page URL, and the platform allows it only when the subscription
|
|
201
|
+
* belongs to that customer, the target plan is in the same product group, and that
|
|
202
|
+
* group's `selfServicePlanChange` is on — otherwise 403. The merchant-only pricing
|
|
203
|
+
* fields are not part of its params; the platform drops them on this path silently.
|
|
204
|
+
*
|
|
205
|
+
* No call sends an idempotency key unless you pass one (`options.idempotencyKey`,
|
|
206
|
+
* the last argument) — the same rule as every other method in the SDK — so a write
|
|
207
|
+
* retried after a timeout executes twice.
|
|
208
|
+
*
|
|
63
209
|
* @param config - WaffoPancake client configuration
|
|
64
210
|
* @returns A server action function
|
|
65
211
|
*
|
|
@@ -107,4 +253,4 @@ type BuyerSessionAction = CustomerSessionAction;
|
|
|
107
253
|
/** @deprecated Use {@link createCustomerSessionAction} instead. */
|
|
108
254
|
declare const createBuyerSessionAction: typeof createCustomerSessionAction;
|
|
109
255
|
|
|
110
|
-
export { type BuyerSessionAction, type BuyerSessionActionType, type BuyerTokenAction, type CheckoutAction, type CheckoutActionParams, type CheckoutActionResult, type CustomerSessionAction, type CustomerSessionActionType, type CustomerTokenAction, type MerchantQueryAction, createBuyerSessionAction, createBuyerTokenAction, createCheckoutAction, createCustomerSessionAction, createCustomerTokenAction, createMerchantQueryAction };
|
|
256
|
+
export { type AuthenticatedPortalCustomer, type BuyerSessionAction, type BuyerSessionActionType, type BuyerTokenAction, type CheckoutAction, type CheckoutActionParams, type CheckoutActionResult, type CustomerPortalRedirectOptions, type CustomerPortalRouteHandler, type CustomerSessionAction, type CustomerSessionActionType, type CustomerTokenAction, type MerchantQueryAction, createBuyerSessionAction, createBuyerTokenAction, createCheckoutAction, createCustomerPortalRedirect, createCustomerSessionAction, createCustomerTokenAction, createMerchantQueryAction };
|
package/dist/server.js
CHANGED
|
@@ -2,36 +2,95 @@
|
|
|
2
2
|
import { WaffoPancake } from "@waffo/pancake-ts";
|
|
3
3
|
function createCheckoutAction(config) {
|
|
4
4
|
const client = new WaffoPancake(config);
|
|
5
|
-
return async (params) => {
|
|
5
|
+
return async (params, options) => {
|
|
6
6
|
if (params.type === "authenticated") {
|
|
7
7
|
const { type: type2, ...sdkParams2 } = params;
|
|
8
|
-
return client.checkout.authenticated.create(sdkParams2);
|
|
8
|
+
return client.checkout.authenticated.create(sdkParams2, options);
|
|
9
|
+
}
|
|
10
|
+
if (params.type === "planChange") {
|
|
11
|
+
const { type: type2, ...sdkParams2 } = params;
|
|
12
|
+
return client.checkout.createPlanChangeSession(sdkParams2, options);
|
|
13
|
+
}
|
|
14
|
+
if (params.type === "authenticatedPlanChange") {
|
|
15
|
+
const { type: type2, ...sdkParams2 } = params;
|
|
16
|
+
return client.checkout.authenticated.createPlanChange(sdkParams2, options);
|
|
9
17
|
}
|
|
10
18
|
const { type, ...sdkParams } = params;
|
|
11
|
-
return client.checkout.anonymous.create(sdkParams);
|
|
19
|
+
return client.checkout.anonymous.create(sdkParams, options);
|
|
12
20
|
};
|
|
13
21
|
}
|
|
14
22
|
function createCustomerTokenAction(config) {
|
|
15
23
|
const client = new WaffoPancake(config);
|
|
16
|
-
return async (params) => {
|
|
17
|
-
return client.auth.issueSessionToken(params);
|
|
24
|
+
return async (params, options) => {
|
|
25
|
+
return client.auth.issueSessionToken(params, options);
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
function portalHeaders(extra) {
|
|
29
|
+
const headers = new Headers(extra);
|
|
30
|
+
headers.set("Cache-Control", "no-store");
|
|
31
|
+
headers.set("Referrer-Policy", "no-referrer");
|
|
32
|
+
return headers;
|
|
33
|
+
}
|
|
34
|
+
function safeErrorMessage(error) {
|
|
35
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
36
|
+
return message.replace(/#token=[^\s"'&]*/g, "#token=[redacted]").replace(/\s+/g, " ");
|
|
37
|
+
}
|
|
38
|
+
function createCustomerPortalRedirect(config, options) {
|
|
39
|
+
const client = new WaffoPancake(config);
|
|
40
|
+
return async function GET(request) {
|
|
41
|
+
const customer = await options.resolveAuthenticatedCustomer(request);
|
|
42
|
+
if (!customer) {
|
|
43
|
+
if (options.loginUrl === void 0) {
|
|
44
|
+
return new Response(JSON.stringify({ error: "Unauthorized" }), {
|
|
45
|
+
status: 401,
|
|
46
|
+
headers: portalHeaders({ "Content-Type": "application/json" })
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
const loginUrl = typeof options.loginUrl === "function" ? options.loginUrl(request) : options.loginUrl;
|
|
50
|
+
return new Response(null, {
|
|
51
|
+
status: 302,
|
|
52
|
+
headers: portalHeaders({ Location: new URL(loginUrl, request.url).toString() })
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
let portalUrl;
|
|
56
|
+
try {
|
|
57
|
+
({ portalUrl } = await client.auth.createCustomerPortalLink({
|
|
58
|
+
storeId: customer.storeId,
|
|
59
|
+
buyerIdentity: customer.buyerIdentity
|
|
60
|
+
}));
|
|
61
|
+
} catch (error) {
|
|
62
|
+
if (options.onError) {
|
|
63
|
+
return options.onError(error, request);
|
|
64
|
+
}
|
|
65
|
+
console.error("[waffo-pancake] createCustomerPortalRedirect failed:", safeErrorMessage(error));
|
|
66
|
+
return new Response(JSON.stringify({ error: "Failed to create customer portal link" }), {
|
|
67
|
+
status: 502,
|
|
68
|
+
headers: portalHeaders({ "Content-Type": "application/json" })
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
return new Response(null, {
|
|
72
|
+
status: 302,
|
|
73
|
+
headers: portalHeaders({ Location: portalUrl })
|
|
74
|
+
});
|
|
18
75
|
};
|
|
19
76
|
}
|
|
20
77
|
function createCustomerSessionAction(config) {
|
|
21
78
|
const client = new WaffoPancake(config);
|
|
22
|
-
return async (token, actionType, params) => {
|
|
79
|
+
return async (token, actionType, params, options) => {
|
|
23
80
|
const customer = client.buyer(token);
|
|
24
81
|
switch (actionType) {
|
|
25
82
|
case "cancelSubscription":
|
|
26
|
-
return customer.cancelSubscription(params);
|
|
83
|
+
return customer.cancelSubscription(params, options);
|
|
27
84
|
case "cancelOnetimeOrder":
|
|
28
|
-
return customer.cancelOnetimeOrder(params);
|
|
85
|
+
return customer.cancelOnetimeOrder(params, options);
|
|
29
86
|
case "reactivateSubscription":
|
|
30
|
-
return customer.reactivateSubscription(params);
|
|
87
|
+
return customer.reactivateSubscription(params, options);
|
|
31
88
|
case "createRefundTicket":
|
|
32
|
-
return customer.createRefundTicket(params);
|
|
89
|
+
return customer.createRefundTicket(params, options);
|
|
33
90
|
case "resubmitRefundTicket":
|
|
34
|
-
return customer.resubmitRefundTicket(params);
|
|
91
|
+
return customer.resubmitRefundTicket(params, options);
|
|
92
|
+
case "createPlanChangeSession":
|
|
93
|
+
return customer.createPlanChangeSession(params, options);
|
|
35
94
|
case "query":
|
|
36
95
|
return customer.graphql.query(params);
|
|
37
96
|
default:
|
|
@@ -51,6 +110,7 @@ export {
|
|
|
51
110
|
createBuyerSessionAction,
|
|
52
111
|
createBuyerTokenAction,
|
|
53
112
|
createCheckoutAction,
|
|
113
|
+
createCustomerPortalRedirect,
|
|
54
114
|
createCustomerSessionAction,
|
|
55
115
|
createCustomerTokenAction,
|
|
56
116
|
createMerchantQueryAction
|
package/dist/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/server.ts"],"sourcesContent":["/**\n * Server-side entry point for @waffo/pancake-nextjs.\n *\n * All functions in this module use the private key for RSA signing\n * and must only run on the server (Next.js Server Actions / Route Handlers).\n *\n * @example\n * ```ts\n * // app/lib/waffo.ts\n * \"use server\";\n * import { createCheckoutAction, createCustomerTokenAction, createMerchantQueryAction } from \"@waffo/pancake-nextjs/server\";\n *\n * const config = {\n * merchantId: process.env.WAFFO_MERCHANT_ID!,\n * privateKey: process.env.WAFFO_PRIVATE_KEY!,\n * };\n *\n * export const checkout = createCheckoutAction(config);\n * export const issueCustomerToken = createCustomerTokenAction(config);\n * export const merchantQuery = createMerchantQueryAction(config);\n * ```\n */\nimport { WaffoPancake } from \"@waffo/pancake-ts\";\n\nimport type {\n WaffoPancakeConfig,\n AnonymousCheckoutParams,\n AuthenticatedCheckoutParams,\n CheckoutSessionResult,\n AuthenticatedCheckoutResult,\n IssueSessionTokenParams,\n SessionToken,\n GraphQLParams,\n GraphQLResponse,\n} from \"@waffo/pancake-ts\";\n\n// ============================================================\n// Checkout Action\n// ============================================================\n\n/** Parameters for the checkout server action */\nexport type CheckoutActionParams =\n | ({ type?: \"anonymous\" } & AnonymousCheckoutParams)\n | ({ type: \"authenticated\" } & AuthenticatedCheckoutParams);\n\n/** Result of the checkout server action */\nexport type CheckoutActionResult = CheckoutSessionResult | AuthenticatedCheckoutResult;\n\n/** Server action signature for checkout */\nexport type CheckoutAction = (params: CheckoutActionParams) => Promise<CheckoutActionResult>;\n\n/**\n * Create a server action that handles checkout session creation.\n *\n * The private key is captured in the closure and never sent to the client.\n *\n * @param config - WaffoPancake client configuration (merchantId + privateKey)\n * @returns A server action function\n *\n * @example\n * ```ts\n * \"use server\";\n * import { createCheckoutAction } from \"@waffo/pancake-nextjs/server\";\n *\n * export const checkout = createCheckoutAction({\n * merchantId: process.env.WAFFO_MERCHANT_ID!,\n * privateKey: process.env.WAFFO_PRIVATE_KEY!,\n * });\n * ```\n */\nexport function createCheckoutAction(config: WaffoPancakeConfig): CheckoutAction {\n const client = new WaffoPancake(config);\n\n return async (params: CheckoutActionParams): Promise<CheckoutActionResult> => {\n if (params.type === \"authenticated\") {\n // eslint-disable-next-line @typescript-eslint/no-unused-vars -- remove type field before passing to SDK\n const { type, ...sdkParams } = params;\n return client.checkout.authenticated.create(sdkParams);\n }\n // eslint-disable-next-line @typescript-eslint/no-unused-vars -- remove type field before passing to SDK\n const { type, ...sdkParams } = params;\n return client.checkout.anonymous.create(sdkParams);\n };\n}\n\n// ============================================================\n// Customer Token Action\n// ============================================================\n\n/** Server action signature for issuing customer tokens */\nexport type CustomerTokenAction = (params: IssueSessionTokenParams) => Promise<SessionToken>;\n\n/**\n * Create a server action that issues customer session tokens.\n *\n * @param config - WaffoPancake client configuration\n * @returns A server action function\n *\n * @example\n * ```ts\n * \"use server\";\n * import { createCustomerTokenAction } from \"@waffo/pancake-nextjs/server\";\n *\n * export const issueCustomerToken = createCustomerTokenAction({\n * merchantId: process.env.WAFFO_MERCHANT_ID!,\n * privateKey: process.env.WAFFO_PRIVATE_KEY!,\n * });\n * ```\n */\nexport function createCustomerTokenAction(config: WaffoPancakeConfig): CustomerTokenAction {\n const client = new WaffoPancake(config);\n\n return async (params: IssueSessionTokenParams): Promise<SessionToken> => {\n return client.auth.issueSessionToken(params);\n };\n}\n\n// ============================================================\n// Customer Session Action\n// ============================================================\n\n/** Customer action types */\nexport type CustomerSessionActionType =\n | \"cancelSubscription\"\n | \"cancelOnetimeOrder\"\n | \"reactivateSubscription\"\n | \"createRefundTicket\"\n | \"resubmitRefundTicket\"\n | \"query\";\n\n/** Server action signature for customer session operations */\nexport type CustomerSessionAction = (token: string, actionType: CustomerSessionActionType, params: unknown) => Promise<unknown>;\n\n/**\n * Create a server action that executes customer self-service operations.\n *\n * `config.environment` is required — session tokens carry no environment, and the\n * gateway rejects a session request without the matching header.\n *\n * @param config - WaffoPancake client configuration\n * @returns A server action function\n *\n * @example\n * ```ts\n * \"use server\";\n * import { createCustomerSessionAction } from \"@waffo/pancake-nextjs/server\";\n *\n * export const customerAction = createCustomerSessionAction({\n * merchantId: process.env.WAFFO_MERCHANT_ID!,\n * privateKey: process.env.WAFFO_PRIVATE_KEY!,\n * environment: \"test\",\n * });\n * ```\n */\nexport function createCustomerSessionAction(config: WaffoPancakeConfig): CustomerSessionAction {\n const client = new WaffoPancake(config);\n\n return async (token: string, actionType: CustomerSessionActionType, params: unknown): Promise<unknown> => {\n const customer = client.buyer(token);\n switch (actionType) {\n case \"cancelSubscription\":\n return customer.cancelSubscription(params as Parameters<typeof customer.cancelSubscription>[0]);\n case \"cancelOnetimeOrder\":\n return customer.cancelOnetimeOrder(params as Parameters<typeof customer.cancelOnetimeOrder>[0]);\n case \"reactivateSubscription\":\n return customer.reactivateSubscription(params as Parameters<typeof customer.reactivateSubscription>[0]);\n case \"createRefundTicket\":\n return customer.createRefundTicket(params as Parameters<typeof customer.createRefundTicket>[0]);\n case \"resubmitRefundTicket\":\n return customer.resubmitRefundTicket(params as Parameters<typeof customer.resubmitRefundTicket>[0]);\n case \"query\":\n return customer.graphql.query(params as GraphQLParams);\n default:\n throw new Error(`Unknown customer action: ${actionType}`);\n }\n };\n}\n\n// ============================================================\n// Merchant Query Action\n// ============================================================\n\n/** Server action signature for merchant GraphQL queries */\nexport type MerchantQueryAction = (params: GraphQLParams) => Promise<GraphQLResponse>;\n\n/**\n * Create a server action that executes merchant GraphQL queries.\n *\n * @param config - WaffoPancake client configuration\n * @returns A server action function\n *\n * @example\n * ```ts\n * \"use server\";\n * import { createMerchantQueryAction } from \"@waffo/pancake-nextjs/server\";\n *\n * export const merchantQuery = createMerchantQueryAction({\n * merchantId: process.env.WAFFO_MERCHANT_ID!,\n * privateKey: process.env.WAFFO_PRIVATE_KEY!,\n * });\n * ```\n */\nexport function createMerchantQueryAction(config: WaffoPancakeConfig): MerchantQueryAction {\n const client = new WaffoPancake(config);\n\n return async (params: GraphQLParams): Promise<GraphQLResponse> => {\n return client.graphql.query(params);\n };\n}\n\n// ============================================================\n// Deprecated Aliases\n// ============================================================\n\n/** @deprecated Use {@link CustomerTokenAction} instead. */\nexport type BuyerTokenAction = CustomerTokenAction;\n\n/** @deprecated Use {@link createCustomerTokenAction} instead. */\nexport const createBuyerTokenAction = createCustomerTokenAction;\n\n/** @deprecated Use {@link CustomerSessionActionType} instead. */\nexport type BuyerSessionActionType = CustomerSessionActionType;\n\n/** @deprecated Use {@link CustomerSessionAction} instead. */\nexport type BuyerSessionAction = CustomerSessionAction;\n\n/** @deprecated Use {@link createCustomerSessionAction} instead. */\nexport const createBuyerSessionAction = createCustomerSessionAction;\n"],"mappings":";AAsBA,SAAS,oBAAoB;AAgDtB,SAAS,qBAAqB,QAA4C;AAC/E,QAAM,SAAS,IAAI,aAAa,MAAM;AAEtC,SAAO,OAAO,WAAgE;AAC5E,QAAI,OAAO,SAAS,iBAAiB;AAEnC,YAAM,EAAE,MAAAA,OAAM,GAAGC,WAAU,IAAI;AAC/B,aAAO,OAAO,SAAS,cAAc,OAAOA,UAAS;AAAA,IACvD;AAEA,UAAM,EAAE,MAAM,GAAG,UAAU,IAAI;AAC/B,WAAO,OAAO,SAAS,UAAU,OAAO,SAAS;AAAA,EACnD;AACF;AA0BO,SAAS,0BAA0B,QAAiD;AACzF,QAAM,SAAS,IAAI,aAAa,MAAM;AAEtC,SAAO,OAAO,WAA2D;AACvE,WAAO,OAAO,KAAK,kBAAkB,MAAM;AAAA,EAC7C;AACF;AAuCO,SAAS,4BAA4B,QAAmD;AAC7F,QAAM,SAAS,IAAI,aAAa,MAAM;AAEtC,SAAO,OAAO,OAAe,YAAuC,WAAsC;AACxG,UAAM,WAAW,OAAO,MAAM,KAAK;AACnC,YAAQ,YAAY;AAAA,MAClB,KAAK;AACH,eAAO,SAAS,mBAAmB,MAA2D;AAAA,MAChG,KAAK;AACH,eAAO,SAAS,mBAAmB,MAA2D;AAAA,MAChG,KAAK;AACH,eAAO,SAAS,uBAAuB,MAA+D;AAAA,MACxG,KAAK;AACH,eAAO,SAAS,mBAAmB,MAA2D;AAAA,MAChG,KAAK;AACH,eAAO,SAAS,qBAAqB,MAA6D;AAAA,MACpG,KAAK;AACH,eAAO,SAAS,QAAQ,MAAM,MAAuB;AAAA,MACvD;AACE,cAAM,IAAI,MAAM,4BAA4B,UAAU,EAAE;AAAA,IAC5D;AAAA,EACF;AACF;AA0BO,SAAS,0BAA0B,QAAiD;AACzF,QAAM,SAAS,IAAI,aAAa,MAAM;AAEtC,SAAO,OAAO,WAAoD;AAChE,WAAO,OAAO,QAAQ,MAAM,MAAM;AAAA,EACpC;AACF;AAUO,IAAM,yBAAyB;AAS/B,IAAM,2BAA2B;","names":["type","sdkParams"]}
|
|
1
|
+
{"version":3,"sources":["../src/server.ts"],"sourcesContent":["/**\n * Server-side entry point for @waffo/pancake-nextjs.\n *\n * All functions in this module use the private key for RSA signing\n * and must only run on the server (Next.js Server Actions / Route Handlers).\n *\n * @example\n * ```ts\n * // app/lib/waffo.ts\n * \"use server\";\n * import { createCheckoutAction, createCustomerTokenAction, createMerchantQueryAction } from \"@waffo/pancake-nextjs/server\";\n *\n * const config = {\n * merchantId: process.env.WAFFO_MERCHANT_ID!,\n * privateKey: process.env.WAFFO_PRIVATE_KEY!,\n * };\n *\n * export const checkout = createCheckoutAction(config);\n * export const issueCustomerToken = createCustomerTokenAction(config);\n * export const merchantQuery = createMerchantQueryAction(config);\n * ```\n *\n * @example\n * ```ts\n * // app/account/billing-portal/route.ts — customer portal entry from your own login\n * import { createCustomerPortalRedirect } from \"@waffo/pancake-nextjs/server\";\n *\n * export const GET = createCustomerPortalRedirect(config, {\n * resolveAuthenticatedCustomer: async (request) => getSignedInCustomer(request), // your session\n * });\n * ```\n */\nimport { WaffoPancake } from \"@waffo/pancake-ts\";\n\nimport type {\n RequestOptions,\n WaffoPancakeConfig,\n AnonymousCheckoutParams,\n AuthenticatedCheckoutParams,\n AuthenticatedPlanChangeParams,\n CreatePlanChangeSessionParams,\n CheckoutSessionResult,\n AuthenticatedCheckoutResult,\n IssueSessionTokenParams,\n SessionToken,\n GraphQLParams,\n GraphQLResponse,\n} from \"@waffo/pancake-ts\";\n\n// ============================================================\n// Checkout Action\n// ============================================================\n\n/**\n * Parameters for the checkout server action.\n *\n * The `type` field selects the flow: a new purchase (`anonymous` / `authenticated`)\n * or a plan change for an existing subscription (`planChange` /\n * `authenticatedPlanChange`, which carry the required `originOrderId`).\n */\nexport type CheckoutActionParams =\n | ({ type?: \"anonymous\" } & AnonymousCheckoutParams)\n | ({ type: \"authenticated\" } & AuthenticatedCheckoutParams)\n | ({ type: \"planChange\" } & CreatePlanChangeSessionParams)\n | ({ type: \"authenticatedPlanChange\" } & AuthenticatedPlanChangeParams);\n\n/** Result of the checkout server action */\nexport type CheckoutActionResult = CheckoutSessionResult | AuthenticatedCheckoutResult;\n\n/**\n * Server action signature for checkout.\n *\n * The optional `options` carries an `idempotencyKey`; without one no key is sent\n * and a retried call creates a second session.\n */\nexport type CheckoutAction = (params: CheckoutActionParams, options?: RequestOptions) => Promise<CheckoutActionResult>;\n\n/**\n * Create a server action that handles checkout session creation.\n *\n * The private key is captured in the closure and never sent to the client.\n *\n * Handles both new purchases and plan changes; `params.type` selects the flow.\n *\n * @param config - WaffoPancake client configuration (merchantId + privateKey)\n * @returns A server action function\n *\n * @example\n * ```ts\n * \"use server\";\n * import { createCheckoutAction } from \"@waffo/pancake-nextjs/server\";\n *\n * export const checkout = createCheckoutAction({\n * merchantId: process.env.WAFFO_MERCHANT_ID!,\n * privateKey: process.env.WAFFO_PRIVATE_KEY!,\n * });\n * ```\n *\n * @example\n * ```ts\n * // Plan change link for an existing subscription — originOrderId is required\n * const session = await checkout({\n * type: \"planChange\",\n * originOrderId: \"ORD_xxx\",\n * productId: \"PROD_target_plan\",\n * currency: \"USD\",\n * });\n * // session.checkoutUrl points at the change confirmation page\n * ```\n */\nexport function createCheckoutAction(config: WaffoPancakeConfig): CheckoutAction {\n const client = new WaffoPancake(config);\n\n return async (params: CheckoutActionParams, options?: RequestOptions): Promise<CheckoutActionResult> => {\n if (params.type === \"authenticated\") {\n // eslint-disable-next-line @typescript-eslint/no-unused-vars -- remove type field before passing to SDK\n const { type, ...sdkParams } = params;\n return client.checkout.authenticated.create(sdkParams, options);\n }\n if (params.type === \"planChange\") {\n // eslint-disable-next-line @typescript-eslint/no-unused-vars -- remove type field before passing to SDK\n const { type, ...sdkParams } = params;\n return client.checkout.createPlanChangeSession(sdkParams, options);\n }\n if (params.type === \"authenticatedPlanChange\") {\n // eslint-disable-next-line @typescript-eslint/no-unused-vars -- remove type field before passing to SDK\n const { type, ...sdkParams } = params;\n return client.checkout.authenticated.createPlanChange(sdkParams, options);\n }\n // eslint-disable-next-line @typescript-eslint/no-unused-vars -- remove type field before passing to SDK\n const { type, ...sdkParams } = params;\n return client.checkout.anonymous.create(sdkParams, options);\n };\n}\n\n// ============================================================\n// Customer Token Action\n// ============================================================\n\n/** Server action signature for issuing customer tokens */\nexport type CustomerTokenAction = (params: IssueSessionTokenParams, options?: RequestOptions) => Promise<SessionToken>;\n\n/**\n * Create a server action that issues customer session tokens.\n *\n * This is a generic token primitive: it signs whatever `buyerIdentity` it is\n * handed. Never expose it to the browser as a portal or sign-in entry — a\n * Server Action is callable with arbitrary arguments, so a client-chosen\n * `buyerIdentity` would yield another customer's token. To send a signed-in\n * customer to the customer portal, use {@link createCustomerPortalRedirect},\n * which derives identity from your own session.\n *\n * @param config - WaffoPancake client configuration\n * @returns A server action function\n *\n * @example\n * ```ts\n * \"use server\";\n * import { createCustomerTokenAction } from \"@waffo/pancake-nextjs/server\";\n *\n * export const issueCustomerToken = createCustomerTokenAction({\n * merchantId: process.env.WAFFO_MERCHANT_ID!,\n * privateKey: process.env.WAFFO_PRIVATE_KEY!,\n * });\n * ```\n */\nexport function createCustomerTokenAction(config: WaffoPancakeConfig): CustomerTokenAction {\n const client = new WaffoPancake(config);\n\n return async (params: IssueSessionTokenParams, options?: RequestOptions): Promise<SessionToken> => {\n return client.auth.issueSessionToken(params, options);\n };\n}\n\n// ============================================================\n// Customer Portal Redirect\n// ============================================================\n\n/**\n * Store and customer identity for a customer portal link, resolved by the\n * merchant app from its own authenticated session.\n */\nexport interface AuthenticatedPortalCustomer {\n /** Store ID (Short ID `STO_xxx`) whose portal the customer enters */\n storeId: string;\n /** Customer identity in your system — the same value used for authenticated checkout */\n buyerIdentity: string;\n}\n\n/** Options for {@link createCustomerPortalRedirect}. */\nexport interface CustomerPortalRedirectOptions {\n /**\n * Resolve the signed-in customer from YOUR app's authenticated session\n * (session cookie, auth library, …). Return `null` when nobody is signed in.\n *\n * Must not read `buyerIdentity` or `storeId` from anything the browser\n * controls — query string, body, form fields or custom headers. Whoever\n * controls `buyerIdentity` gets that customer's portal.\n */\n resolveAuthenticatedCustomer: (request: Request) => Promise<AuthenticatedPortalCustomer | null> | AuthenticatedPortalCustomer | null;\n /**\n * Where to send a visitor for whom the resolver returned `null`. A path or\n * absolute URL, resolved against the request URL; a function receives the\n * request (e.g. to add your own `returnTo`). Omit to answer 401 instead.\n *\n * Build it from constants or an allow-list, never by copying request\n * parameters verbatim (e.g. a `?next=` value) — that turns this route into an\n * open redirect.\n */\n loginUrl?: string | ((request: Request) => string);\n /**\n * Build the response when creating the portal link fails (API error, invalid\n * store ID, network error). This is the place for your own logging and error\n * reporting. Defaults to a 502 JSON `{ error }` response with a generic\n * message, after one `console.error` line carrying only the error message;\n * the error itself is not echoed to the browser.\n */\n onError?: (error: unknown, request: Request) => Response | Promise<Response>;\n}\n\n/** GET Route Handler returned by {@link createCustomerPortalRedirect}. */\nexport type CustomerPortalRouteHandler = (request: Request) => Promise<Response>;\n\n/**\n * Build headers for a portal route response. Every response — redirect, 401 or\n * error — is `no-store` and `no-referrer`, so a tokenized `Location` is neither\n * cached nor forwarded as a Referer.\n */\nfunction portalHeaders(extra: Record<string, string>): Headers {\n const headers = new Headers(extra);\n headers.set(\"Cache-Control\", \"no-store\");\n headers.set(\"Referrer-Policy\", \"no-referrer\");\n return headers;\n}\n\n/**\n * One-line, log-safe description of a portal link failure: the error message\n * only (never the error object, which may carry a response body), with any\n * `#token=...` fragment redacted.\n */\nfunction safeErrorMessage(error: unknown): string {\n const message = error instanceof Error ? error.message : String(error);\n return message.replace(/#token=[^\\s\"'&]*/g, \"#token=[redacted]\").replace(/\\s+/g, \" \");\n}\n\n/**\n * Create a GET Route Handler that sends the signed-in customer to your store's\n * Pancake customer portal, without the portal's email verification step.\n *\n * Behavior:\n * - Calls `resolveAuthenticatedCustomer(request)` — your own session check — to\n * get `{ storeId, buyerIdentity }`. Nothing is read from the request's query\n * string, body or headers by the SDK\n * - Signed in: creates a portal link with `client.auth.createCustomerPortalLink()`\n * and answers `302` to `portalUrl` (which carries `#token=...`)\n * - Not signed in: `302` to `loginUrl` when set, otherwise `401`\n * - Link creation fails: `onError(error, request)`, or by default one server-side\n * `console.error` line with the error message and a generic `502 { error }`\n *\n * Side effects:\n * - One signed API request per signed-in visit; each visit issues a new portal session\n * - Every response it builds (not a custom `onError` one) sets `Cache-Control: no-store` and `Referrer-Policy: no-referrer`\n * so the tokenized `Location` is neither cached nor forwarded as a Referer\n *\n * Boundary conditions:\n * - The portal environment is the environment of the API Key in `config`\n * (test key → test portal, prod key → prod portal)\n * - Errors thrown by `resolveAuthenticatedCustomer` propagate (Next.js answers 500)\n * - The default error log is the message only, with any `#token=` fragment redacted;\n * pass `onError` to log or report failures your own way\n * - `loginUrl` must not echo request parameters verbatim, or the route becomes an open redirect\n *\n * A Route Handler rather than a Server Action: the portal entry is a plain link\n * navigation, and only an HTTP redirect keeps the tokenized URL out of client\n * JavaScript while letting the response carry `no-store` / `no-referrer`.\n *\n * @param config - WaffoPancake client configuration (merchantId + privateKey)\n * @param options - Session resolver, login redirect and error handling\n * @returns A Next.js GET Route Handler\n *\n * @example\n * ```ts\n * // app/account/billing-portal/route.ts\n * import { createCustomerPortalRedirect } from \"@waffo/pancake-nextjs/server\";\n * import { auth } from \"@/lib/auth\"; // your auth library\n *\n * export const dynamic = \"force-dynamic\";\n *\n * export const GET = createCustomerPortalRedirect(\n * { merchantId: process.env.WAFFO_MERCHANT_ID!, privateKey: process.env.WAFFO_PRIVATE_KEY! },\n * {\n * resolveAuthenticatedCustomer: async () => {\n * const session = await auth();\n * if (!session?.user) return null;\n * return { storeId: process.env.WAFFO_STORE_ID!, buyerIdentity: session.user.id };\n * },\n * loginUrl: \"/login?returnTo=/account/billing-portal\",\n * },\n * );\n * // In a page: <a href=\"/account/billing-portal\">Manage billing</a>\n * ```\n */\nexport function createCustomerPortalRedirect(\n config: WaffoPancakeConfig,\n options: CustomerPortalRedirectOptions,\n): CustomerPortalRouteHandler {\n const client = new WaffoPancake(config);\n\n return async function GET(request: Request): Promise<Response> {\n const customer = await options.resolveAuthenticatedCustomer(request);\n\n if (!customer) {\n if (options.loginUrl === undefined) {\n return new Response(JSON.stringify({ error: \"Unauthorized\" }), {\n status: 401,\n headers: portalHeaders({ \"Content-Type\": \"application/json\" }),\n });\n }\n const loginUrl = typeof options.loginUrl === \"function\" ? options.loginUrl(request) : options.loginUrl;\n return new Response(null, {\n status: 302,\n headers: portalHeaders({ Location: new URL(loginUrl, request.url).toString() }),\n });\n }\n\n let portalUrl: string;\n try {\n ({ portalUrl } = await client.auth.createCustomerPortalLink({\n storeId: customer.storeId,\n buyerIdentity: customer.buyerIdentity,\n }));\n } catch (error) {\n if (options.onError) {\n return options.onError(error, request);\n }\n console.error(\"[waffo-pancake] createCustomerPortalRedirect failed:\", safeErrorMessage(error));\n return new Response(JSON.stringify({ error: \"Failed to create customer portal link\" }), {\n status: 502,\n headers: portalHeaders({ \"Content-Type\": \"application/json\" }),\n });\n }\n\n return new Response(null, {\n status: 302,\n headers: portalHeaders({ Location: portalUrl }),\n });\n };\n}\n\n// ============================================================\n// Customer Session Action\n// ============================================================\n\n/** Customer action types */\nexport type CustomerSessionActionType =\n | \"cancelSubscription\"\n | \"cancelOnetimeOrder\"\n | \"reactivateSubscription\"\n | \"createRefundTicket\"\n | \"resubmitRefundTicket\"\n | \"createPlanChangeSession\"\n | \"query\";\n\n/** Server action signature for customer session operations */\nexport type CustomerSessionAction = (\n token: string,\n actionType: CustomerSessionActionType,\n params: unknown,\n options?: RequestOptions,\n) => Promise<unknown>;\n\n/**\n * Create a server action that executes customer self-service operations.\n *\n * `config.environment` is required — session tokens carry no environment, and the\n * gateway rejects a session request without the matching header.\n *\n * `createPlanChangeSession` is the customer-driven half of a plan change: it returns\n * a confirmation-page URL, and the platform allows it only when the subscription\n * belongs to that customer, the target plan is in the same product group, and that\n * group's `selfServicePlanChange` is on — otherwise 403. The merchant-only pricing\n * fields are not part of its params; the platform drops them on this path silently.\n *\n * No call sends an idempotency key unless you pass one (`options.idempotencyKey`,\n * the last argument) — the same rule as every other method in the SDK — so a write\n * retried after a timeout executes twice.\n *\n * @param config - WaffoPancake client configuration\n * @returns A server action function\n *\n * @example\n * ```ts\n * \"use server\";\n * import { createCustomerSessionAction } from \"@waffo/pancake-nextjs/server\";\n *\n * export const customerAction = createCustomerSessionAction({\n * merchantId: process.env.WAFFO_MERCHANT_ID!,\n * privateKey: process.env.WAFFO_PRIVATE_KEY!,\n * environment: \"test\",\n * });\n * ```\n */\nexport function createCustomerSessionAction(config: WaffoPancakeConfig): CustomerSessionAction {\n const client = new WaffoPancake(config);\n\n return async (token: string, actionType: CustomerSessionActionType, params: unknown, options?: RequestOptions): Promise<unknown> => {\n const customer = client.buyer(token);\n switch (actionType) {\n case \"cancelSubscription\":\n return customer.cancelSubscription(params as Parameters<typeof customer.cancelSubscription>[0], options);\n case \"cancelOnetimeOrder\":\n return customer.cancelOnetimeOrder(params as Parameters<typeof customer.cancelOnetimeOrder>[0], options);\n case \"reactivateSubscription\":\n return customer.reactivateSubscription(params as Parameters<typeof customer.reactivateSubscription>[0], options);\n case \"createRefundTicket\":\n return customer.createRefundTicket(params as Parameters<typeof customer.createRefundTicket>[0], options);\n case \"resubmitRefundTicket\":\n return customer.resubmitRefundTicket(params as Parameters<typeof customer.resubmitRefundTicket>[0], options);\n case \"createPlanChangeSession\":\n return customer.createPlanChangeSession(params as Parameters<typeof customer.createPlanChangeSession>[0], options);\n case \"query\":\n // Reads take no key: a cached replay would serve stale data.\n return customer.graphql.query(params as GraphQLParams);\n default:\n throw new Error(`Unknown customer action: ${actionType}`);\n }\n };\n}\n\n// ============================================================\n// Merchant Query Action\n// ============================================================\n\n/** Server action signature for merchant GraphQL queries */\nexport type MerchantQueryAction = (params: GraphQLParams) => Promise<GraphQLResponse>;\n\n/**\n * Create a server action that executes merchant GraphQL queries.\n *\n * @param config - WaffoPancake client configuration\n * @returns A server action function\n *\n * @example\n * ```ts\n * \"use server\";\n * import { createMerchantQueryAction } from \"@waffo/pancake-nextjs/server\";\n *\n * export const merchantQuery = createMerchantQueryAction({\n * merchantId: process.env.WAFFO_MERCHANT_ID!,\n * privateKey: process.env.WAFFO_PRIVATE_KEY!,\n * });\n * ```\n */\nexport function createMerchantQueryAction(config: WaffoPancakeConfig): MerchantQueryAction {\n const client = new WaffoPancake(config);\n\n return async (params: GraphQLParams): Promise<GraphQLResponse> => {\n return client.graphql.query(params);\n };\n}\n\n// ============================================================\n// Deprecated Aliases\n// ============================================================\n\n/** @deprecated Use {@link CustomerTokenAction} instead. */\nexport type BuyerTokenAction = CustomerTokenAction;\n\n/** @deprecated Use {@link createCustomerTokenAction} instead. */\nexport const createBuyerTokenAction = createCustomerTokenAction;\n\n/** @deprecated Use {@link CustomerSessionActionType} instead. */\nexport type BuyerSessionActionType = CustomerSessionActionType;\n\n/** @deprecated Use {@link CustomerSessionAction} instead. */\nexport type BuyerSessionAction = CustomerSessionAction;\n\n/** @deprecated Use {@link createCustomerSessionAction} instead. */\nexport const createBuyerSessionAction = createCustomerSessionAction;\n"],"mappings":"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","names":["type","sdkParams"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@waffo/pancake-nextjs",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"description": "Next.js SDK for Waffo Pancake — checkout components and hooks",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
},
|
|
49
49
|
"license": "MIT",
|
|
50
50
|
"dependencies": {
|
|
51
|
-
"@waffo/pancake-ts": "^0.
|
|
51
|
+
"@waffo/pancake-ts": "^0.26.0",
|
|
52
52
|
"next": ">=14.0.0",
|
|
53
53
|
"react": ">=18.0.0",
|
|
54
54
|
"react-dom": ">=18.0.0"
|