@spaire/nextjs 1.0.1 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +191 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +35 -0
- package/dist/index.d.ts +35 -0
- package/dist/index.js +165 -0
- package/dist/index.js.map +1 -0
- package/package.json +5 -2
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
Checkout: () => Checkout,
|
|
24
|
+
CustomerPortal: () => CustomerPortal,
|
|
25
|
+
EntitlementStrategy: () => import_adapter_utils2.EntitlementStrategy,
|
|
26
|
+
Entitlements: () => import_adapter_utils2.Entitlements,
|
|
27
|
+
Webhooks: () => Webhooks
|
|
28
|
+
});
|
|
29
|
+
module.exports = __toCommonJS(index_exports);
|
|
30
|
+
|
|
31
|
+
// src/checkout/checkout.ts
|
|
32
|
+
var import_sdk = require("@spaire/sdk");
|
|
33
|
+
var import_server = require("next/server");
|
|
34
|
+
var Checkout = ({
|
|
35
|
+
accessToken,
|
|
36
|
+
successUrl,
|
|
37
|
+
returnUrl,
|
|
38
|
+
server,
|
|
39
|
+
theme,
|
|
40
|
+
includeCheckoutId = true
|
|
41
|
+
}) => {
|
|
42
|
+
const spaire = new import_sdk.Spaire({
|
|
43
|
+
accessToken,
|
|
44
|
+
server
|
|
45
|
+
});
|
|
46
|
+
return async (req) => {
|
|
47
|
+
const url = new URL(req.url);
|
|
48
|
+
const products = url.searchParams.getAll("products");
|
|
49
|
+
if (products.length === 0) {
|
|
50
|
+
return import_server.NextResponse.json(
|
|
51
|
+
{ error: "Missing products in query params" },
|
|
52
|
+
{ status: 400 }
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
const success = successUrl ? new URL(successUrl) : void 0;
|
|
56
|
+
if (success && includeCheckoutId) {
|
|
57
|
+
success.searchParams.set("checkoutId", "{CHECKOUT_ID}");
|
|
58
|
+
}
|
|
59
|
+
const retUrl = returnUrl ? new URL(returnUrl) : void 0;
|
|
60
|
+
try {
|
|
61
|
+
const result = await spaire.checkouts.create({
|
|
62
|
+
products,
|
|
63
|
+
successUrl: success ? decodeURI(success.toString()) : void 0,
|
|
64
|
+
customerId: url.searchParams.get("customerId") ?? void 0,
|
|
65
|
+
externalCustomerId: url.searchParams.get("customerExternalId") ?? void 0,
|
|
66
|
+
customerEmail: url.searchParams.get("customerEmail") ?? void 0,
|
|
67
|
+
customerName: url.searchParams.get("customerName") ?? void 0,
|
|
68
|
+
customerBillingAddress: url.searchParams.has("customerBillingAddress") ? JSON.parse(url.searchParams.get("customerBillingAddress") ?? "{}") : void 0,
|
|
69
|
+
customerTaxId: url.searchParams.get("customerTaxId") ?? void 0,
|
|
70
|
+
customerIpAddress: url.searchParams.get("customerIpAddress") ?? void 0,
|
|
71
|
+
customerMetadata: url.searchParams.has("customerMetadata") ? JSON.parse(url.searchParams.get("customerMetadata") ?? "{}") : void 0,
|
|
72
|
+
allowDiscountCodes: url.searchParams.has("allowDiscountCodes") ? url.searchParams.get("allowDiscountCodes") === "true" : void 0,
|
|
73
|
+
discountId: url.searchParams.get("discountId") ?? void 0,
|
|
74
|
+
metadata: url.searchParams.has("metadata") ? JSON.parse(url.searchParams.get("metadata") ?? "{}") : void 0,
|
|
75
|
+
seats: url.searchParams.has("seats") ? Number.parseInt(url.searchParams.get("seats") ?? "1", 10) : void 0,
|
|
76
|
+
returnUrl: retUrl ? decodeURI(retUrl.toString()) : void 0
|
|
77
|
+
});
|
|
78
|
+
const redirectUrl = new URL(result.url);
|
|
79
|
+
if (theme) {
|
|
80
|
+
redirectUrl.searchParams.set("theme", theme);
|
|
81
|
+
}
|
|
82
|
+
return import_server.NextResponse.redirect(redirectUrl.toString());
|
|
83
|
+
} catch (error) {
|
|
84
|
+
console.error(error);
|
|
85
|
+
return import_server.NextResponse.error();
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
// src/customerPortal/customerPortal.ts
|
|
91
|
+
var import_sdk2 = require("@spaire/sdk");
|
|
92
|
+
var import_server2 = require("next/server");
|
|
93
|
+
function configIsExternalCustomerIdConfig(config) {
|
|
94
|
+
return typeof config.getExternalCustomerId === "function";
|
|
95
|
+
}
|
|
96
|
+
var CustomerPortal = (config) => {
|
|
97
|
+
const { accessToken, server, returnUrl } = config;
|
|
98
|
+
const spaire = new import_sdk2.Spaire({
|
|
99
|
+
accessToken,
|
|
100
|
+
server
|
|
101
|
+
});
|
|
102
|
+
return async (req) => {
|
|
103
|
+
const decodedReturnUrl = returnUrl ? decodeURI(new URL(returnUrl).toString()) : void 0;
|
|
104
|
+
if (configIsExternalCustomerIdConfig(config)) {
|
|
105
|
+
const externalCustomerId = await config.getExternalCustomerId(req);
|
|
106
|
+
if (!externalCustomerId) {
|
|
107
|
+
return import_server2.NextResponse.json(
|
|
108
|
+
{ error: "externalCustomerId not defined" },
|
|
109
|
+
{ status: 400 }
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
try {
|
|
113
|
+
const { customerPortalUrl } = await spaire.customerSessions.create({
|
|
114
|
+
returnUrl: decodedReturnUrl,
|
|
115
|
+
externalCustomerId
|
|
116
|
+
});
|
|
117
|
+
return import_server2.NextResponse.redirect(customerPortalUrl);
|
|
118
|
+
} catch (error) {
|
|
119
|
+
console.error(error);
|
|
120
|
+
return import_server2.NextResponse.error();
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
const customerId = await config.getCustomerId(req);
|
|
124
|
+
if (!customerId) {
|
|
125
|
+
return import_server2.NextResponse.json(
|
|
126
|
+
{ error: "customerId not defined" },
|
|
127
|
+
{ status: 400 }
|
|
128
|
+
);
|
|
129
|
+
}
|
|
130
|
+
try {
|
|
131
|
+
const { customerPortalUrl } = await spaire.customerSessions.create({
|
|
132
|
+
returnUrl: decodedReturnUrl,
|
|
133
|
+
customerId
|
|
134
|
+
});
|
|
135
|
+
return import_server2.NextResponse.redirect(customerPortalUrl);
|
|
136
|
+
} catch (error) {
|
|
137
|
+
console.error(error);
|
|
138
|
+
return import_server2.NextResponse.error();
|
|
139
|
+
}
|
|
140
|
+
};
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
// src/webhooks/webhooks.ts
|
|
144
|
+
var import_adapter_utils = require("@spaire/adapter-utils");
|
|
145
|
+
var import_webhooks = require("@spaire/sdk/webhooks");
|
|
146
|
+
var import_server3 = require("next/server");
|
|
147
|
+
var import_adapter_utils2 = require("@spaire/adapter-utils");
|
|
148
|
+
var Webhooks = ({
|
|
149
|
+
webhookSecret,
|
|
150
|
+
entitlements,
|
|
151
|
+
onPayload,
|
|
152
|
+
...eventHandlers
|
|
153
|
+
}) => {
|
|
154
|
+
return async (request) => {
|
|
155
|
+
const requestBody = await request.text();
|
|
156
|
+
const webhookHeaders = {
|
|
157
|
+
"webhook-id": request.headers.get("webhook-id") ?? "",
|
|
158
|
+
"webhook-timestamp": request.headers.get("webhook-timestamp") ?? "",
|
|
159
|
+
"webhook-signature": request.headers.get("webhook-signature") ?? ""
|
|
160
|
+
};
|
|
161
|
+
let webhookPayload;
|
|
162
|
+
try {
|
|
163
|
+
webhookPayload = (0, import_webhooks.validateEvent)(
|
|
164
|
+
requestBody,
|
|
165
|
+
webhookHeaders,
|
|
166
|
+
webhookSecret
|
|
167
|
+
);
|
|
168
|
+
} catch (error) {
|
|
169
|
+
if (error instanceof import_webhooks.WebhookVerificationError) {
|
|
170
|
+
return import_server3.NextResponse.json({ received: false }, { status: 403 });
|
|
171
|
+
}
|
|
172
|
+
throw error;
|
|
173
|
+
}
|
|
174
|
+
await (0, import_adapter_utils.handleWebhookPayload)(webhookPayload, {
|
|
175
|
+
webhookSecret,
|
|
176
|
+
entitlements,
|
|
177
|
+
onPayload,
|
|
178
|
+
...eventHandlers
|
|
179
|
+
});
|
|
180
|
+
return import_server3.NextResponse.json({ received: true });
|
|
181
|
+
};
|
|
182
|
+
};
|
|
183
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
184
|
+
0 && (module.exports = {
|
|
185
|
+
Checkout,
|
|
186
|
+
CustomerPortal,
|
|
187
|
+
EntitlementStrategy,
|
|
188
|
+
Entitlements,
|
|
189
|
+
Webhooks
|
|
190
|
+
});
|
|
191
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/checkout/checkout.ts","../src/customerPortal/customerPortal.ts","../src/webhooks/webhooks.ts"],"sourcesContent":["export * from \"./checkout/checkout\";\nexport * from \"./customerPortal/customerPortal\";\nexport * from \"./webhooks/webhooks\";\n","import { Spaire } from \"@spaire/sdk\";\nimport { NextResponse } from \"next/server\";\nimport type { NextRequest } from \"next/server\";\n\nexport interface CheckoutConfig {\n\taccessToken?: string;\n\tsuccessUrl?: string;\n\treturnUrl?: string;\n\tincludeCheckoutId?: boolean;\n\tserver?: \"sandbox\" | \"production\";\n\ttheme?: \"light\" | \"dark\";\n}\n\nexport const Checkout = ({\n\taccessToken,\n\tsuccessUrl,\n\treturnUrl,\n\tserver,\n\ttheme,\n\tincludeCheckoutId = true,\n}: CheckoutConfig) => {\n\tconst spaire = new Spaire({\n\t\taccessToken,\n\t\tserver,\n\t});\n\n\treturn async (req: NextRequest) => {\n\t\tconst url = new URL(req.url);\n\t\tconst products = url.searchParams.getAll(\"products\");\n\n\t\tif (products.length === 0) {\n\t\t\treturn NextResponse.json(\n\t\t\t\t{ error: \"Missing products in query params\" },\n\t\t\t\t{ status: 400 },\n\t\t\t);\n\t\t}\n\n\t\tconst success = successUrl ? new URL(successUrl) : undefined;\n\n\t\tif (success && includeCheckoutId) {\n\t\t\tsuccess.searchParams.set(\"checkoutId\", \"{CHECKOUT_ID}\");\n\t\t}\n\n\t\tconst retUrl = returnUrl ? new URL(returnUrl) : undefined;\n\n\t\ttry {\n\t\t\tconst result = await spaire.checkouts.create({\n\t\t\t\tproducts,\n\t\t\t\tsuccessUrl: success ? decodeURI(success.toString()) : undefined,\n\t\t\t\tcustomerId: url.searchParams.get(\"customerId\") ?? undefined,\n\t\t\t\texternalCustomerId:\n\t\t\t\t\turl.searchParams.get(\"customerExternalId\") ?? undefined,\n\t\t\t\tcustomerEmail: url.searchParams.get(\"customerEmail\") ?? undefined,\n\t\t\t\tcustomerName: url.searchParams.get(\"customerName\") ?? undefined,\n\t\t\t\tcustomerBillingAddress: url.searchParams.has(\"customerBillingAddress\")\n\t\t\t\t\t? JSON.parse(url.searchParams.get(\"customerBillingAddress\") ?? \"{}\")\n\t\t\t\t\t: undefined,\n\t\t\t\tcustomerTaxId: url.searchParams.get(\"customerTaxId\") ?? undefined,\n\t\t\t\tcustomerIpAddress:\n\t\t\t\t\turl.searchParams.get(\"customerIpAddress\") ?? undefined,\n\t\t\t\tcustomerMetadata: url.searchParams.has(\"customerMetadata\")\n\t\t\t\t\t? JSON.parse(url.searchParams.get(\"customerMetadata\") ?? \"{}\")\n\t\t\t\t\t: undefined,\n\t\t\t\tallowDiscountCodes: url.searchParams.has(\"allowDiscountCodes\")\n\t\t\t\t\t? url.searchParams.get(\"allowDiscountCodes\") === \"true\"\n\t\t\t\t\t: undefined,\n\t\t\t\tdiscountId: url.searchParams.get(\"discountId\") ?? undefined,\n\t\t\t\tmetadata: url.searchParams.has(\"metadata\")\n\t\t\t\t\t? JSON.parse(url.searchParams.get(\"metadata\") ?? \"{}\")\n\t\t\t\t\t: undefined,\n\t\t\t\tseats: url.searchParams.has(\"seats\")\n\t\t\t\t\t? Number.parseInt(url.searchParams.get(\"seats\") ?? \"1\", 10)\n\t\t\t\t\t: undefined,\n\t\t\t\treturnUrl: retUrl ? decodeURI(retUrl.toString()) : undefined,\n\t\t\t});\n\n\t\t\tconst redirectUrl = new URL(result.url);\n\n\t\t\tif (theme) {\n\t\t\t\tredirectUrl.searchParams.set(\"theme\", theme);\n\t\t\t}\n\n\t\t\treturn NextResponse.redirect(redirectUrl.toString());\n\t\t} catch (error) {\n\t\t\tconsole.error(error);\n\t\t\treturn NextResponse.error();\n\t\t}\n\t};\n};\n","import { Spaire } from \"@spaire/sdk\";\nimport { type NextRequest, NextResponse } from \"next/server\";\n\ninterface CustomerPortalBaseConfig {\n\taccessToken: string;\n\tserver: \"sandbox\" | \"production\";\n\treturnUrl?: string;\n}\n\ninterface CustomerPortalCustomerIdConfig extends CustomerPortalBaseConfig {\n\tgetCustomerId: (req: NextRequest) => Promise<string>;\n\tgetExternalCustomerId?: never;\n}\n\ninterface CustomerPortalExternalCustomerIdConfig\n\textends CustomerPortalBaseConfig {\n\tgetCustomerId?: never;\n\tgetExternalCustomerId: (req: NextRequest) => Promise<string>;\n}\n\nfunction configIsExternalCustomerIdConfig(\n\tconfig: CustomerPortalConfig,\n): config is CustomerPortalExternalCustomerIdConfig {\n\treturn typeof config.getExternalCustomerId === \"function\";\n}\n\nexport type CustomerPortalConfig =\n\t| CustomerPortalCustomerIdConfig\n\t| CustomerPortalExternalCustomerIdConfig;\n\nexport const CustomerPortal = (config: CustomerPortalConfig) => {\n\tconst { accessToken, server, returnUrl } = config;\n\n\tconst spaire = new Spaire({\n\t\taccessToken,\n\t\tserver,\n\t});\n\n\treturn async (req: NextRequest) => {\n\t\tconst decodedReturnUrl = returnUrl\n\t\t\t? decodeURI(new URL(returnUrl).toString())\n\t\t\t: undefined;\n\n\t\tif (configIsExternalCustomerIdConfig(config)) {\n\t\t\tconst externalCustomerId = await config.getExternalCustomerId(req);\n\n\t\t\tif (!externalCustomerId) {\n\t\t\t\treturn NextResponse.json(\n\t\t\t\t\t{ error: \"externalCustomerId not defined\" },\n\t\t\t\t\t{ status: 400 },\n\t\t\t\t);\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tconst { customerPortalUrl } = await spaire.customerSessions.create({\n\t\t\t\t\treturnUrl: decodedReturnUrl,\n\t\t\t\t\texternalCustomerId,\n\t\t\t\t});\n\n\t\t\t\treturn NextResponse.redirect(customerPortalUrl);\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error(error);\n\t\t\t\treturn NextResponse.error();\n\t\t\t}\n\t\t}\n\n\t\tconst customerId = await config.getCustomerId(req);\n\n\t\tif (!customerId) {\n\t\t\treturn NextResponse.json(\n\t\t\t\t{ error: \"customerId not defined\" },\n\t\t\t\t{ status: 400 },\n\t\t\t);\n\t\t}\n\n\t\ttry {\n\t\t\tconst { customerPortalUrl } = await spaire.customerSessions.create({\n\t\t\t\treturnUrl: decodedReturnUrl,\n\t\t\t\tcustomerId,\n\t\t\t});\n\n\t\t\treturn NextResponse.redirect(customerPortalUrl);\n\t\t} catch (error) {\n\t\t\tconsole.error(error);\n\t\t\treturn NextResponse.error();\n\t\t}\n\t};\n};\n","import {\n\ttype WebhooksConfig,\n\thandleWebhookPayload,\n} from \"@spaire/adapter-utils\";\nimport { WebhookVerificationError, validateEvent } from \"@spaire/sdk/webhooks\";\nimport { type NextRequest, NextResponse } from \"next/server\";\n\nexport {\n\ttype EntitlementContext,\n\ttype EntitlementHandler,\n\ttype EntitlementProperties,\n\tEntitlementStrategy,\n\tEntitlements,\n} from \"@spaire/adapter-utils\";\n\nexport const Webhooks = ({\n\twebhookSecret,\n\tentitlements,\n\tonPayload,\n\t...eventHandlers\n}: WebhooksConfig) => {\n\treturn async (request: NextRequest) => {\n\t\tconst requestBody = await request.text();\n\n\t\tconst webhookHeaders = {\n\t\t\t\"webhook-id\": request.headers.get(\"webhook-id\") ?? \"\",\n\t\t\t\"webhook-timestamp\": request.headers.get(\"webhook-timestamp\") ?? \"\",\n\t\t\t\"webhook-signature\": request.headers.get(\"webhook-signature\") ?? \"\",\n\t\t};\n\n\t\tlet webhookPayload: ReturnType<typeof validateEvent>;\n\t\ttry {\n\t\t\twebhookPayload = validateEvent(\n\t\t\t\trequestBody,\n\t\t\t\twebhookHeaders,\n\t\t\t\twebhookSecret,\n\t\t\t);\n\t\t} catch (error) {\n\t\t\tif (error instanceof WebhookVerificationError) {\n\t\t\t\treturn NextResponse.json({ received: false }, { status: 403 });\n\t\t\t}\n\n\t\t\tthrow error;\n\t\t}\n\n\t\tawait handleWebhookPayload(webhookPayload, {\n\t\t\twebhookSecret,\n\t\t\tentitlements,\n\t\t\tonPayload,\n\t\t\t...eventHandlers,\n\t\t});\n\n\t\treturn NextResponse.json({ received: true });\n\t};\n};\n"],"mappings":"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","names":["import_sdk","import_server","import_server","import_adapter_utils"]}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { NextRequest, NextResponse } from 'next/server';
|
|
2
|
+
import { WebhooksConfig } from '@spaire/adapter-utils';
|
|
3
|
+
export { EntitlementContext, EntitlementHandler, EntitlementProperties, EntitlementStrategy, Entitlements } from '@spaire/adapter-utils';
|
|
4
|
+
|
|
5
|
+
interface CheckoutConfig {
|
|
6
|
+
accessToken?: string;
|
|
7
|
+
successUrl?: string;
|
|
8
|
+
returnUrl?: string;
|
|
9
|
+
includeCheckoutId?: boolean;
|
|
10
|
+
server?: "sandbox" | "production";
|
|
11
|
+
theme?: "light" | "dark";
|
|
12
|
+
}
|
|
13
|
+
declare const Checkout: ({ accessToken, successUrl, returnUrl, server, theme, includeCheckoutId, }: CheckoutConfig) => (req: NextRequest) => Promise<Response>;
|
|
14
|
+
|
|
15
|
+
interface CustomerPortalBaseConfig {
|
|
16
|
+
accessToken: string;
|
|
17
|
+
server: "sandbox" | "production";
|
|
18
|
+
returnUrl?: string;
|
|
19
|
+
}
|
|
20
|
+
interface CustomerPortalCustomerIdConfig extends CustomerPortalBaseConfig {
|
|
21
|
+
getCustomerId: (req: NextRequest) => Promise<string>;
|
|
22
|
+
getExternalCustomerId?: never;
|
|
23
|
+
}
|
|
24
|
+
interface CustomerPortalExternalCustomerIdConfig extends CustomerPortalBaseConfig {
|
|
25
|
+
getCustomerId?: never;
|
|
26
|
+
getExternalCustomerId: (req: NextRequest) => Promise<string>;
|
|
27
|
+
}
|
|
28
|
+
type CustomerPortalConfig = CustomerPortalCustomerIdConfig | CustomerPortalExternalCustomerIdConfig;
|
|
29
|
+
declare const CustomerPortal: (config: CustomerPortalConfig) => (req: NextRequest) => Promise<Response>;
|
|
30
|
+
|
|
31
|
+
declare const Webhooks: ({ webhookSecret, entitlements, onPayload, ...eventHandlers }: WebhooksConfig) => (request: NextRequest) => Promise<NextResponse<{
|
|
32
|
+
received: boolean;
|
|
33
|
+
}>>;
|
|
34
|
+
|
|
35
|
+
export { Checkout, type CheckoutConfig, CustomerPortal, type CustomerPortalConfig, Webhooks };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { NextRequest, NextResponse } from 'next/server';
|
|
2
|
+
import { WebhooksConfig } from '@spaire/adapter-utils';
|
|
3
|
+
export { EntitlementContext, EntitlementHandler, EntitlementProperties, EntitlementStrategy, Entitlements } from '@spaire/adapter-utils';
|
|
4
|
+
|
|
5
|
+
interface CheckoutConfig {
|
|
6
|
+
accessToken?: string;
|
|
7
|
+
successUrl?: string;
|
|
8
|
+
returnUrl?: string;
|
|
9
|
+
includeCheckoutId?: boolean;
|
|
10
|
+
server?: "sandbox" | "production";
|
|
11
|
+
theme?: "light" | "dark";
|
|
12
|
+
}
|
|
13
|
+
declare const Checkout: ({ accessToken, successUrl, returnUrl, server, theme, includeCheckoutId, }: CheckoutConfig) => (req: NextRequest) => Promise<Response>;
|
|
14
|
+
|
|
15
|
+
interface CustomerPortalBaseConfig {
|
|
16
|
+
accessToken: string;
|
|
17
|
+
server: "sandbox" | "production";
|
|
18
|
+
returnUrl?: string;
|
|
19
|
+
}
|
|
20
|
+
interface CustomerPortalCustomerIdConfig extends CustomerPortalBaseConfig {
|
|
21
|
+
getCustomerId: (req: NextRequest) => Promise<string>;
|
|
22
|
+
getExternalCustomerId?: never;
|
|
23
|
+
}
|
|
24
|
+
interface CustomerPortalExternalCustomerIdConfig extends CustomerPortalBaseConfig {
|
|
25
|
+
getCustomerId?: never;
|
|
26
|
+
getExternalCustomerId: (req: NextRequest) => Promise<string>;
|
|
27
|
+
}
|
|
28
|
+
type CustomerPortalConfig = CustomerPortalCustomerIdConfig | CustomerPortalExternalCustomerIdConfig;
|
|
29
|
+
declare const CustomerPortal: (config: CustomerPortalConfig) => (req: NextRequest) => Promise<Response>;
|
|
30
|
+
|
|
31
|
+
declare const Webhooks: ({ webhookSecret, entitlements, onPayload, ...eventHandlers }: WebhooksConfig) => (request: NextRequest) => Promise<NextResponse<{
|
|
32
|
+
received: boolean;
|
|
33
|
+
}>>;
|
|
34
|
+
|
|
35
|
+
export { Checkout, type CheckoutConfig, CustomerPortal, type CustomerPortalConfig, Webhooks };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
// src/checkout/checkout.ts
|
|
2
|
+
import { Spaire } from "@spaire/sdk";
|
|
3
|
+
import { NextResponse } from "next/server";
|
|
4
|
+
var Checkout = ({
|
|
5
|
+
accessToken,
|
|
6
|
+
successUrl,
|
|
7
|
+
returnUrl,
|
|
8
|
+
server,
|
|
9
|
+
theme,
|
|
10
|
+
includeCheckoutId = true
|
|
11
|
+
}) => {
|
|
12
|
+
const spaire = new Spaire({
|
|
13
|
+
accessToken,
|
|
14
|
+
server
|
|
15
|
+
});
|
|
16
|
+
return async (req) => {
|
|
17
|
+
const url = new URL(req.url);
|
|
18
|
+
const products = url.searchParams.getAll("products");
|
|
19
|
+
if (products.length === 0) {
|
|
20
|
+
return NextResponse.json(
|
|
21
|
+
{ error: "Missing products in query params" },
|
|
22
|
+
{ status: 400 }
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
const success = successUrl ? new URL(successUrl) : void 0;
|
|
26
|
+
if (success && includeCheckoutId) {
|
|
27
|
+
success.searchParams.set("checkoutId", "{CHECKOUT_ID}");
|
|
28
|
+
}
|
|
29
|
+
const retUrl = returnUrl ? new URL(returnUrl) : void 0;
|
|
30
|
+
try {
|
|
31
|
+
const result = await spaire.checkouts.create({
|
|
32
|
+
products,
|
|
33
|
+
successUrl: success ? decodeURI(success.toString()) : void 0,
|
|
34
|
+
customerId: url.searchParams.get("customerId") ?? void 0,
|
|
35
|
+
externalCustomerId: url.searchParams.get("customerExternalId") ?? void 0,
|
|
36
|
+
customerEmail: url.searchParams.get("customerEmail") ?? void 0,
|
|
37
|
+
customerName: url.searchParams.get("customerName") ?? void 0,
|
|
38
|
+
customerBillingAddress: url.searchParams.has("customerBillingAddress") ? JSON.parse(url.searchParams.get("customerBillingAddress") ?? "{}") : void 0,
|
|
39
|
+
customerTaxId: url.searchParams.get("customerTaxId") ?? void 0,
|
|
40
|
+
customerIpAddress: url.searchParams.get("customerIpAddress") ?? void 0,
|
|
41
|
+
customerMetadata: url.searchParams.has("customerMetadata") ? JSON.parse(url.searchParams.get("customerMetadata") ?? "{}") : void 0,
|
|
42
|
+
allowDiscountCodes: url.searchParams.has("allowDiscountCodes") ? url.searchParams.get("allowDiscountCodes") === "true" : void 0,
|
|
43
|
+
discountId: url.searchParams.get("discountId") ?? void 0,
|
|
44
|
+
metadata: url.searchParams.has("metadata") ? JSON.parse(url.searchParams.get("metadata") ?? "{}") : void 0,
|
|
45
|
+
seats: url.searchParams.has("seats") ? Number.parseInt(url.searchParams.get("seats") ?? "1", 10) : void 0,
|
|
46
|
+
returnUrl: retUrl ? decodeURI(retUrl.toString()) : void 0
|
|
47
|
+
});
|
|
48
|
+
const redirectUrl = new URL(result.url);
|
|
49
|
+
if (theme) {
|
|
50
|
+
redirectUrl.searchParams.set("theme", theme);
|
|
51
|
+
}
|
|
52
|
+
return NextResponse.redirect(redirectUrl.toString());
|
|
53
|
+
} catch (error) {
|
|
54
|
+
console.error(error);
|
|
55
|
+
return NextResponse.error();
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
// src/customerPortal/customerPortal.ts
|
|
61
|
+
import { Spaire as Spaire2 } from "@spaire/sdk";
|
|
62
|
+
import { NextResponse as NextResponse2 } from "next/server";
|
|
63
|
+
function configIsExternalCustomerIdConfig(config) {
|
|
64
|
+
return typeof config.getExternalCustomerId === "function";
|
|
65
|
+
}
|
|
66
|
+
var CustomerPortal = (config) => {
|
|
67
|
+
const { accessToken, server, returnUrl } = config;
|
|
68
|
+
const spaire = new Spaire2({
|
|
69
|
+
accessToken,
|
|
70
|
+
server
|
|
71
|
+
});
|
|
72
|
+
return async (req) => {
|
|
73
|
+
const decodedReturnUrl = returnUrl ? decodeURI(new URL(returnUrl).toString()) : void 0;
|
|
74
|
+
if (configIsExternalCustomerIdConfig(config)) {
|
|
75
|
+
const externalCustomerId = await config.getExternalCustomerId(req);
|
|
76
|
+
if (!externalCustomerId) {
|
|
77
|
+
return NextResponse2.json(
|
|
78
|
+
{ error: "externalCustomerId not defined" },
|
|
79
|
+
{ status: 400 }
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
try {
|
|
83
|
+
const { customerPortalUrl } = await spaire.customerSessions.create({
|
|
84
|
+
returnUrl: decodedReturnUrl,
|
|
85
|
+
externalCustomerId
|
|
86
|
+
});
|
|
87
|
+
return NextResponse2.redirect(customerPortalUrl);
|
|
88
|
+
} catch (error) {
|
|
89
|
+
console.error(error);
|
|
90
|
+
return NextResponse2.error();
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
const customerId = await config.getCustomerId(req);
|
|
94
|
+
if (!customerId) {
|
|
95
|
+
return NextResponse2.json(
|
|
96
|
+
{ error: "customerId not defined" },
|
|
97
|
+
{ status: 400 }
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
try {
|
|
101
|
+
const { customerPortalUrl } = await spaire.customerSessions.create({
|
|
102
|
+
returnUrl: decodedReturnUrl,
|
|
103
|
+
customerId
|
|
104
|
+
});
|
|
105
|
+
return NextResponse2.redirect(customerPortalUrl);
|
|
106
|
+
} catch (error) {
|
|
107
|
+
console.error(error);
|
|
108
|
+
return NextResponse2.error();
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
// src/webhooks/webhooks.ts
|
|
114
|
+
import {
|
|
115
|
+
handleWebhookPayload
|
|
116
|
+
} from "@spaire/adapter-utils";
|
|
117
|
+
import { WebhookVerificationError, validateEvent } from "@spaire/sdk/webhooks";
|
|
118
|
+
import { NextResponse as NextResponse3 } from "next/server";
|
|
119
|
+
import {
|
|
120
|
+
EntitlementStrategy,
|
|
121
|
+
Entitlements
|
|
122
|
+
} from "@spaire/adapter-utils";
|
|
123
|
+
var Webhooks = ({
|
|
124
|
+
webhookSecret,
|
|
125
|
+
entitlements,
|
|
126
|
+
onPayload,
|
|
127
|
+
...eventHandlers
|
|
128
|
+
}) => {
|
|
129
|
+
return async (request) => {
|
|
130
|
+
const requestBody = await request.text();
|
|
131
|
+
const webhookHeaders = {
|
|
132
|
+
"webhook-id": request.headers.get("webhook-id") ?? "",
|
|
133
|
+
"webhook-timestamp": request.headers.get("webhook-timestamp") ?? "",
|
|
134
|
+
"webhook-signature": request.headers.get("webhook-signature") ?? ""
|
|
135
|
+
};
|
|
136
|
+
let webhookPayload;
|
|
137
|
+
try {
|
|
138
|
+
webhookPayload = validateEvent(
|
|
139
|
+
requestBody,
|
|
140
|
+
webhookHeaders,
|
|
141
|
+
webhookSecret
|
|
142
|
+
);
|
|
143
|
+
} catch (error) {
|
|
144
|
+
if (error instanceof WebhookVerificationError) {
|
|
145
|
+
return NextResponse3.json({ received: false }, { status: 403 });
|
|
146
|
+
}
|
|
147
|
+
throw error;
|
|
148
|
+
}
|
|
149
|
+
await handleWebhookPayload(webhookPayload, {
|
|
150
|
+
webhookSecret,
|
|
151
|
+
entitlements,
|
|
152
|
+
onPayload,
|
|
153
|
+
...eventHandlers
|
|
154
|
+
});
|
|
155
|
+
return NextResponse3.json({ received: true });
|
|
156
|
+
};
|
|
157
|
+
};
|
|
158
|
+
export {
|
|
159
|
+
Checkout,
|
|
160
|
+
CustomerPortal,
|
|
161
|
+
EntitlementStrategy,
|
|
162
|
+
Entitlements,
|
|
163
|
+
Webhooks
|
|
164
|
+
};
|
|
165
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/checkout/checkout.ts","../src/customerPortal/customerPortal.ts","../src/webhooks/webhooks.ts"],"sourcesContent":["import { Spaire } from \"@spaire/sdk\";\nimport { NextResponse } from \"next/server\";\nimport type { NextRequest } from \"next/server\";\n\nexport interface CheckoutConfig {\n\taccessToken?: string;\n\tsuccessUrl?: string;\n\treturnUrl?: string;\n\tincludeCheckoutId?: boolean;\n\tserver?: \"sandbox\" | \"production\";\n\ttheme?: \"light\" | \"dark\";\n}\n\nexport const Checkout = ({\n\taccessToken,\n\tsuccessUrl,\n\treturnUrl,\n\tserver,\n\ttheme,\n\tincludeCheckoutId = true,\n}: CheckoutConfig) => {\n\tconst spaire = new Spaire({\n\t\taccessToken,\n\t\tserver,\n\t});\n\n\treturn async (req: NextRequest) => {\n\t\tconst url = new URL(req.url);\n\t\tconst products = url.searchParams.getAll(\"products\");\n\n\t\tif (products.length === 0) {\n\t\t\treturn NextResponse.json(\n\t\t\t\t{ error: \"Missing products in query params\" },\n\t\t\t\t{ status: 400 },\n\t\t\t);\n\t\t}\n\n\t\tconst success = successUrl ? new URL(successUrl) : undefined;\n\n\t\tif (success && includeCheckoutId) {\n\t\t\tsuccess.searchParams.set(\"checkoutId\", \"{CHECKOUT_ID}\");\n\t\t}\n\n\t\tconst retUrl = returnUrl ? new URL(returnUrl) : undefined;\n\n\t\ttry {\n\t\t\tconst result = await spaire.checkouts.create({\n\t\t\t\tproducts,\n\t\t\t\tsuccessUrl: success ? decodeURI(success.toString()) : undefined,\n\t\t\t\tcustomerId: url.searchParams.get(\"customerId\") ?? undefined,\n\t\t\t\texternalCustomerId:\n\t\t\t\t\turl.searchParams.get(\"customerExternalId\") ?? undefined,\n\t\t\t\tcustomerEmail: url.searchParams.get(\"customerEmail\") ?? undefined,\n\t\t\t\tcustomerName: url.searchParams.get(\"customerName\") ?? undefined,\n\t\t\t\tcustomerBillingAddress: url.searchParams.has(\"customerBillingAddress\")\n\t\t\t\t\t? JSON.parse(url.searchParams.get(\"customerBillingAddress\") ?? \"{}\")\n\t\t\t\t\t: undefined,\n\t\t\t\tcustomerTaxId: url.searchParams.get(\"customerTaxId\") ?? undefined,\n\t\t\t\tcustomerIpAddress:\n\t\t\t\t\turl.searchParams.get(\"customerIpAddress\") ?? undefined,\n\t\t\t\tcustomerMetadata: url.searchParams.has(\"customerMetadata\")\n\t\t\t\t\t? JSON.parse(url.searchParams.get(\"customerMetadata\") ?? \"{}\")\n\t\t\t\t\t: undefined,\n\t\t\t\tallowDiscountCodes: url.searchParams.has(\"allowDiscountCodes\")\n\t\t\t\t\t? url.searchParams.get(\"allowDiscountCodes\") === \"true\"\n\t\t\t\t\t: undefined,\n\t\t\t\tdiscountId: url.searchParams.get(\"discountId\") ?? undefined,\n\t\t\t\tmetadata: url.searchParams.has(\"metadata\")\n\t\t\t\t\t? JSON.parse(url.searchParams.get(\"metadata\") ?? \"{}\")\n\t\t\t\t\t: undefined,\n\t\t\t\tseats: url.searchParams.has(\"seats\")\n\t\t\t\t\t? Number.parseInt(url.searchParams.get(\"seats\") ?? \"1\", 10)\n\t\t\t\t\t: undefined,\n\t\t\t\treturnUrl: retUrl ? decodeURI(retUrl.toString()) : undefined,\n\t\t\t});\n\n\t\t\tconst redirectUrl = new URL(result.url);\n\n\t\t\tif (theme) {\n\t\t\t\tredirectUrl.searchParams.set(\"theme\", theme);\n\t\t\t}\n\n\t\t\treturn NextResponse.redirect(redirectUrl.toString());\n\t\t} catch (error) {\n\t\t\tconsole.error(error);\n\t\t\treturn NextResponse.error();\n\t\t}\n\t};\n};\n","import { Spaire } from \"@spaire/sdk\";\nimport { type NextRequest, NextResponse } from \"next/server\";\n\ninterface CustomerPortalBaseConfig {\n\taccessToken: string;\n\tserver: \"sandbox\" | \"production\";\n\treturnUrl?: string;\n}\n\ninterface CustomerPortalCustomerIdConfig extends CustomerPortalBaseConfig {\n\tgetCustomerId: (req: NextRequest) => Promise<string>;\n\tgetExternalCustomerId?: never;\n}\n\ninterface CustomerPortalExternalCustomerIdConfig\n\textends CustomerPortalBaseConfig {\n\tgetCustomerId?: never;\n\tgetExternalCustomerId: (req: NextRequest) => Promise<string>;\n}\n\nfunction configIsExternalCustomerIdConfig(\n\tconfig: CustomerPortalConfig,\n): config is CustomerPortalExternalCustomerIdConfig {\n\treturn typeof config.getExternalCustomerId === \"function\";\n}\n\nexport type CustomerPortalConfig =\n\t| CustomerPortalCustomerIdConfig\n\t| CustomerPortalExternalCustomerIdConfig;\n\nexport const CustomerPortal = (config: CustomerPortalConfig) => {\n\tconst { accessToken, server, returnUrl } = config;\n\n\tconst spaire = new Spaire({\n\t\taccessToken,\n\t\tserver,\n\t});\n\n\treturn async (req: NextRequest) => {\n\t\tconst decodedReturnUrl = returnUrl\n\t\t\t? decodeURI(new URL(returnUrl).toString())\n\t\t\t: undefined;\n\n\t\tif (configIsExternalCustomerIdConfig(config)) {\n\t\t\tconst externalCustomerId = await config.getExternalCustomerId(req);\n\n\t\t\tif (!externalCustomerId) {\n\t\t\t\treturn NextResponse.json(\n\t\t\t\t\t{ error: \"externalCustomerId not defined\" },\n\t\t\t\t\t{ status: 400 },\n\t\t\t\t);\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tconst { customerPortalUrl } = await spaire.customerSessions.create({\n\t\t\t\t\treturnUrl: decodedReturnUrl,\n\t\t\t\t\texternalCustomerId,\n\t\t\t\t});\n\n\t\t\t\treturn NextResponse.redirect(customerPortalUrl);\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error(error);\n\t\t\t\treturn NextResponse.error();\n\t\t\t}\n\t\t}\n\n\t\tconst customerId = await config.getCustomerId(req);\n\n\t\tif (!customerId) {\n\t\t\treturn NextResponse.json(\n\t\t\t\t{ error: \"customerId not defined\" },\n\t\t\t\t{ status: 400 },\n\t\t\t);\n\t\t}\n\n\t\ttry {\n\t\t\tconst { customerPortalUrl } = await spaire.customerSessions.create({\n\t\t\t\treturnUrl: decodedReturnUrl,\n\t\t\t\tcustomerId,\n\t\t\t});\n\n\t\t\treturn NextResponse.redirect(customerPortalUrl);\n\t\t} catch (error) {\n\t\t\tconsole.error(error);\n\t\t\treturn NextResponse.error();\n\t\t}\n\t};\n};\n","import {\n\ttype WebhooksConfig,\n\thandleWebhookPayload,\n} from \"@spaire/adapter-utils\";\nimport { WebhookVerificationError, validateEvent } from \"@spaire/sdk/webhooks\";\nimport { type NextRequest, NextResponse } from \"next/server\";\n\nexport {\n\ttype EntitlementContext,\n\ttype EntitlementHandler,\n\ttype EntitlementProperties,\n\tEntitlementStrategy,\n\tEntitlements,\n} from \"@spaire/adapter-utils\";\n\nexport const Webhooks = ({\n\twebhookSecret,\n\tentitlements,\n\tonPayload,\n\t...eventHandlers\n}: WebhooksConfig) => {\n\treturn async (request: NextRequest) => {\n\t\tconst requestBody = await request.text();\n\n\t\tconst webhookHeaders = {\n\t\t\t\"webhook-id\": request.headers.get(\"webhook-id\") ?? \"\",\n\t\t\t\"webhook-timestamp\": request.headers.get(\"webhook-timestamp\") ?? \"\",\n\t\t\t\"webhook-signature\": request.headers.get(\"webhook-signature\") ?? \"\",\n\t\t};\n\n\t\tlet webhookPayload: ReturnType<typeof validateEvent>;\n\t\ttry {\n\t\t\twebhookPayload = validateEvent(\n\t\t\t\trequestBody,\n\t\t\t\twebhookHeaders,\n\t\t\t\twebhookSecret,\n\t\t\t);\n\t\t} catch (error) {\n\t\t\tif (error instanceof WebhookVerificationError) {\n\t\t\t\treturn NextResponse.json({ received: false }, { status: 403 });\n\t\t\t}\n\n\t\t\tthrow error;\n\t\t}\n\n\t\tawait handleWebhookPayload(webhookPayload, {\n\t\t\twebhookSecret,\n\t\t\tentitlements,\n\t\t\tonPayload,\n\t\t\t...eventHandlers,\n\t\t});\n\n\t\treturn NextResponse.json({ received: true });\n\t};\n};\n"],"mappings":";AAAA,SAAS,cAAc;AACvB,SAAS,oBAAoB;AAYtB,IAAM,WAAW,CAAC;AAAA,EACxB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,oBAAoB;AACrB,MAAsB;AACrB,QAAM,SAAS,IAAI,OAAO;AAAA,IACzB;AAAA,IACA;AAAA,EACD,CAAC;AAED,SAAO,OAAO,QAAqB;AAClC,UAAM,MAAM,IAAI,IAAI,IAAI,GAAG;AAC3B,UAAM,WAAW,IAAI,aAAa,OAAO,UAAU;AAEnD,QAAI,SAAS,WAAW,GAAG;AAC1B,aAAO,aAAa;AAAA,QACnB,EAAE,OAAO,mCAAmC;AAAA,QAC5C,EAAE,QAAQ,IAAI;AAAA,MACf;AAAA,IACD;AAEA,UAAM,UAAU,aAAa,IAAI,IAAI,UAAU,IAAI;AAEnD,QAAI,WAAW,mBAAmB;AACjC,cAAQ,aAAa,IAAI,cAAc,eAAe;AAAA,IACvD;AAEA,UAAM,SAAS,YAAY,IAAI,IAAI,SAAS,IAAI;AAEhD,QAAI;AACH,YAAM,SAAS,MAAM,OAAO,UAAU,OAAO;AAAA,QAC5C;AAAA,QACA,YAAY,UAAU,UAAU,QAAQ,SAAS,CAAC,IAAI;AAAA,QACtD,YAAY,IAAI,aAAa,IAAI,YAAY,KAAK;AAAA,QAClD,oBACC,IAAI,aAAa,IAAI,oBAAoB,KAAK;AAAA,QAC/C,eAAe,IAAI,aAAa,IAAI,eAAe,KAAK;AAAA,QACxD,cAAc,IAAI,aAAa,IAAI,cAAc,KAAK;AAAA,QACtD,wBAAwB,IAAI,aAAa,IAAI,wBAAwB,IAClE,KAAK,MAAM,IAAI,aAAa,IAAI,wBAAwB,KAAK,IAAI,IACjE;AAAA,QACH,eAAe,IAAI,aAAa,IAAI,eAAe,KAAK;AAAA,QACxD,mBACC,IAAI,aAAa,IAAI,mBAAmB,KAAK;AAAA,QAC9C,kBAAkB,IAAI,aAAa,IAAI,kBAAkB,IACtD,KAAK,MAAM,IAAI,aAAa,IAAI,kBAAkB,KAAK,IAAI,IAC3D;AAAA,QACH,oBAAoB,IAAI,aAAa,IAAI,oBAAoB,IAC1D,IAAI,aAAa,IAAI,oBAAoB,MAAM,SAC/C;AAAA,QACH,YAAY,IAAI,aAAa,IAAI,YAAY,KAAK;AAAA,QAClD,UAAU,IAAI,aAAa,IAAI,UAAU,IACtC,KAAK,MAAM,IAAI,aAAa,IAAI,UAAU,KAAK,IAAI,IACnD;AAAA,QACH,OAAO,IAAI,aAAa,IAAI,OAAO,IAChC,OAAO,SAAS,IAAI,aAAa,IAAI,OAAO,KAAK,KAAK,EAAE,IACxD;AAAA,QACH,WAAW,SAAS,UAAU,OAAO,SAAS,CAAC,IAAI;AAAA,MACpD,CAAC;AAED,YAAM,cAAc,IAAI,IAAI,OAAO,GAAG;AAEtC,UAAI,OAAO;AACV,oBAAY,aAAa,IAAI,SAAS,KAAK;AAAA,MAC5C;AAEA,aAAO,aAAa,SAAS,YAAY,SAAS,CAAC;AAAA,IACpD,SAAS,OAAO;AACf,cAAQ,MAAM,KAAK;AACnB,aAAO,aAAa,MAAM;AAAA,IAC3B;AAAA,EACD;AACD;;;ACxFA,SAAS,UAAAA,eAAc;AACvB,SAA2B,gBAAAC,qBAAoB;AAmB/C,SAAS,iCACR,QACmD;AACnD,SAAO,OAAO,OAAO,0BAA0B;AAChD;AAMO,IAAM,iBAAiB,CAAC,WAAiC;AAC/D,QAAM,EAAE,aAAa,QAAQ,UAAU,IAAI;AAE3C,QAAM,SAAS,IAAID,QAAO;AAAA,IACzB;AAAA,IACA;AAAA,EACD,CAAC;AAED,SAAO,OAAO,QAAqB;AAClC,UAAM,mBAAmB,YACtB,UAAU,IAAI,IAAI,SAAS,EAAE,SAAS,CAAC,IACvC;AAEH,QAAI,iCAAiC,MAAM,GAAG;AAC7C,YAAM,qBAAqB,MAAM,OAAO,sBAAsB,GAAG;AAEjE,UAAI,CAAC,oBAAoB;AACxB,eAAOC,cAAa;AAAA,UACnB,EAAE,OAAO,iCAAiC;AAAA,UAC1C,EAAE,QAAQ,IAAI;AAAA,QACf;AAAA,MACD;AAEA,UAAI;AACH,cAAM,EAAE,kBAAkB,IAAI,MAAM,OAAO,iBAAiB,OAAO;AAAA,UAClE,WAAW;AAAA,UACX;AAAA,QACD,CAAC;AAED,eAAOA,cAAa,SAAS,iBAAiB;AAAA,MAC/C,SAAS,OAAO;AACf,gBAAQ,MAAM,KAAK;AACnB,eAAOA,cAAa,MAAM;AAAA,MAC3B;AAAA,IACD;AAEA,UAAM,aAAa,MAAM,OAAO,cAAc,GAAG;AAEjD,QAAI,CAAC,YAAY;AAChB,aAAOA,cAAa;AAAA,QACnB,EAAE,OAAO,yBAAyB;AAAA,QAClC,EAAE,QAAQ,IAAI;AAAA,MACf;AAAA,IACD;AAEA,QAAI;AACH,YAAM,EAAE,kBAAkB,IAAI,MAAM,OAAO,iBAAiB,OAAO;AAAA,QAClE,WAAW;AAAA,QACX;AAAA,MACD,CAAC;AAED,aAAOA,cAAa,SAAS,iBAAiB;AAAA,IAC/C,SAAS,OAAO;AACf,cAAQ,MAAM,KAAK;AACnB,aAAOA,cAAa,MAAM;AAAA,IAC3B;AAAA,EACD;AACD;;;ACvFA;AAAA,EAEC;AAAA,OACM;AACP,SAAS,0BAA0B,qBAAqB;AACxD,SAA2B,gBAAAC,qBAAoB;AAE/C;AAAA,EAIC;AAAA,EACA;AAAA,OACM;AAEA,IAAM,WAAW,CAAC;AAAA,EACxB;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG;AACJ,MAAsB;AACrB,SAAO,OAAO,YAAyB;AACtC,UAAM,cAAc,MAAM,QAAQ,KAAK;AAEvC,UAAM,iBAAiB;AAAA,MACtB,cAAc,QAAQ,QAAQ,IAAI,YAAY,KAAK;AAAA,MACnD,qBAAqB,QAAQ,QAAQ,IAAI,mBAAmB,KAAK;AAAA,MACjE,qBAAqB,QAAQ,QAAQ,IAAI,mBAAmB,KAAK;AAAA,IAClE;AAEA,QAAI;AACJ,QAAI;AACH,uBAAiB;AAAA,QAChB;AAAA,QACA;AAAA,QACA;AAAA,MACD;AAAA,IACD,SAAS,OAAO;AACf,UAAI,iBAAiB,0BAA0B;AAC9C,eAAOA,cAAa,KAAK,EAAE,UAAU,MAAM,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,MAC9D;AAEA,YAAM;AAAA,IACP;AAEA,UAAM,qBAAqB,gBAAgB;AAAA,MAC1C;AAAA,MACA;AAAA,MACA;AAAA,MACA,GAAG;AAAA,IACJ,CAAC;AAED,WAAOA,cAAa,KAAK,EAAE,UAAU,KAAK,CAAC;AAAA,EAC5C;AACD;","names":["Spaire","NextResponse","NextResponse"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@spaire/nextjs",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"main": "./dist/index.cjs",
|
|
5
5
|
"module": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"dist"
|
|
29
29
|
],
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@spaire/adapter-utils": "
|
|
31
|
+
"@spaire/adapter-utils": "^2.0.0",
|
|
32
32
|
"@spaire/sdk": "^0.45.1"
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
@@ -48,5 +48,8 @@
|
|
|
48
48
|
},
|
|
49
49
|
"peerDependencies": {
|
|
50
50
|
"next": "^15.0.0 || ^16.0.0"
|
|
51
|
+
},
|
|
52
|
+
"publishConfig": {
|
|
53
|
+
"access": "public"
|
|
51
54
|
}
|
|
52
55
|
}
|