@neetru/sdk 1.0.0 → 1.1.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 +32 -1
- package/dist/auth.cjs +177 -1
- package/dist/auth.cjs.map +1 -1
- package/dist/auth.d.cts +1 -1
- package/dist/auth.d.ts +1 -1
- package/dist/auth.mjs +177 -1
- package/dist/auth.mjs.map +1 -1
- package/dist/catalog.d.cts +1 -1
- package/dist/catalog.d.ts +1 -1
- package/dist/checkout.cjs +275 -0
- package/dist/checkout.cjs.map +1 -0
- package/dist/checkout.d.cts +1 -0
- package/dist/checkout.d.ts +1 -0
- package/dist/checkout.mjs +272 -0
- package/dist/checkout.mjs.map +1 -0
- package/dist/db.d.cts +1 -1
- package/dist/db.d.ts +1 -1
- package/dist/entitlements.d.cts +1 -1
- package/dist/entitlements.d.ts +1 -1
- package/dist/index.cjs +180 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.mjs +179 -3
- package/dist/index.mjs.map +1 -1
- package/dist/mocks.d.cts +1 -1
- package/dist/mocks.d.ts +1 -1
- package/dist/react.cjs +158 -0
- package/dist/react.cjs.map +1 -0
- package/dist/react.d.cts +112 -0
- package/dist/react.d.ts +112 -0
- package/dist/react.mjs +134 -0
- package/dist/react.mjs.map +1 -0
- package/dist/support.d.cts +1 -1
- package/dist/support.d.ts +1 -1
- package/dist/telemetry.d.cts +1 -1
- package/dist/telemetry.d.ts +1 -1
- package/dist/{types-PKUaFtBY.d.cts → types-BA53dd8S.d.cts} +83 -1
- package/dist/{types-PKUaFtBY.d.ts → types-BA53dd8S.d.ts} +83 -1
- package/dist/usage.d.cts +1 -1
- package/dist/usage.d.ts +1 -1
- package/package.json +18 -2
package/dist/catalog.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { R as ResolvedConfig, C as CatalogListOptions, c as CatalogListResponse, P as Product } from './types-
|
|
1
|
+
import { R as ResolvedConfig, C as CatalogListOptions, c as CatalogListResponse, P as Product } from './types-BA53dd8S.cjs';
|
|
2
2
|
|
|
3
3
|
declare function createCatalogNamespace(config: ResolvedConfig): {
|
|
4
4
|
/**
|
package/dist/catalog.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { R as ResolvedConfig, C as CatalogListOptions, c as CatalogListResponse, P as Product } from './types-
|
|
1
|
+
import { R as ResolvedConfig, C as CatalogListOptions, c as CatalogListResponse, P as Product } from './types-BA53dd8S.js';
|
|
2
2
|
|
|
3
3
|
declare function createCatalogNamespace(config: ResolvedConfig): {
|
|
4
4
|
/**
|
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// src/errors.ts
|
|
4
|
+
var NeetruError = class _NeetruError extends Error {
|
|
5
|
+
code;
|
|
6
|
+
status;
|
|
7
|
+
requestId;
|
|
8
|
+
constructor(code, message, status, requestId) {
|
|
9
|
+
super(message);
|
|
10
|
+
this.name = "NeetruError";
|
|
11
|
+
this.code = code;
|
|
12
|
+
this.status = status;
|
|
13
|
+
this.requestId = requestId;
|
|
14
|
+
Object.setPrototypeOf(this, _NeetruError.prototype);
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
// src/http.ts
|
|
19
|
+
function statusToCode(status) {
|
|
20
|
+
if (status === 401) return "unauthorized";
|
|
21
|
+
if (status === 403) return "forbidden";
|
|
22
|
+
if (status === 404) return "not_found";
|
|
23
|
+
if (status === 422 || status === 400) return "validation_failed";
|
|
24
|
+
if (status === 429) return "rate_limited";
|
|
25
|
+
if (status >= 500) return "server_error";
|
|
26
|
+
return "unknown";
|
|
27
|
+
}
|
|
28
|
+
function buildUrl(baseUrl, path, query) {
|
|
29
|
+
const base = baseUrl.replace(/\/+$/, "");
|
|
30
|
+
const p = path.startsWith("/") ? path : `/${path}`;
|
|
31
|
+
const url = new URL(`${base}${p}`);
|
|
32
|
+
if (query) {
|
|
33
|
+
for (const [k, v] of Object.entries(query)) {
|
|
34
|
+
if (v === void 0) continue;
|
|
35
|
+
url.searchParams.set(k, String(v));
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return url.toString();
|
|
39
|
+
}
|
|
40
|
+
async function safeJson(res) {
|
|
41
|
+
const text = await res.text();
|
|
42
|
+
if (!text) return void 0;
|
|
43
|
+
try {
|
|
44
|
+
return JSON.parse(text);
|
|
45
|
+
} catch {
|
|
46
|
+
return void 0;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
async function httpRequest(config, opts) {
|
|
50
|
+
const method = opts.method ?? "GET";
|
|
51
|
+
const url = buildUrl(config.baseUrl, opts.path, opts.query);
|
|
52
|
+
const headers = {
|
|
53
|
+
accept: "application/json",
|
|
54
|
+
...opts.headers
|
|
55
|
+
};
|
|
56
|
+
if (opts.requireAuth) {
|
|
57
|
+
if (!config.apiKey) {
|
|
58
|
+
throw new NeetruError(
|
|
59
|
+
"missing_api_key",
|
|
60
|
+
"This operation requires an apiKey. Pass it to createNeetruClient({ apiKey }) or set NEETRU_API_KEY env var."
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
headers.authorization = `Bearer ${config.apiKey}`;
|
|
64
|
+
}
|
|
65
|
+
const init = { method, headers };
|
|
66
|
+
if (opts.body !== void 0 && method !== "GET" && method !== "DELETE") {
|
|
67
|
+
headers["content-type"] = "application/json";
|
|
68
|
+
init.body = JSON.stringify(opts.body);
|
|
69
|
+
}
|
|
70
|
+
let res;
|
|
71
|
+
try {
|
|
72
|
+
res = await config.fetch(url, init);
|
|
73
|
+
} catch (err) {
|
|
74
|
+
const message = err instanceof Error ? err.message : "fetch failed";
|
|
75
|
+
throw new NeetruError("network_error", `Network error: ${message}`);
|
|
76
|
+
}
|
|
77
|
+
const requestId = res.headers.get("x-request-id") ?? res.headers.get("x-correlation-id") ?? void 0;
|
|
78
|
+
if (!res.ok) {
|
|
79
|
+
const body = await safeJson(res);
|
|
80
|
+
let code = statusToCode(res.status);
|
|
81
|
+
let message = `HTTP ${res.status}`;
|
|
82
|
+
if (body && typeof body === "object" && "error" in body) {
|
|
83
|
+
const errField = body.error;
|
|
84
|
+
if (typeof errField === "string") {
|
|
85
|
+
message = errField;
|
|
86
|
+
} else if (errField && typeof errField === "object") {
|
|
87
|
+
if (typeof errField.code === "string") code = errField.code;
|
|
88
|
+
if (typeof errField.message === "string") message = errField.message;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
throw new NeetruError(code, message, res.status, requestId);
|
|
92
|
+
}
|
|
93
|
+
const parsed = await safeJson(res);
|
|
94
|
+
return parsed;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// src/checkout.ts
|
|
98
|
+
function parseStartResponse(raw) {
|
|
99
|
+
if (!raw || typeof raw !== "object") {
|
|
100
|
+
throw new NeetruError("invalid_response", "checkout.start response is not an object");
|
|
101
|
+
}
|
|
102
|
+
const r = raw;
|
|
103
|
+
if (typeof r.intentId !== "string" || !r.intentId) {
|
|
104
|
+
throw new NeetruError("invalid_response", "checkout.start response missing intentId");
|
|
105
|
+
}
|
|
106
|
+
if (typeof r.redirectUrl !== "string" || !r.redirectUrl) {
|
|
107
|
+
throw new NeetruError("invalid_response", "checkout.start response missing redirectUrl");
|
|
108
|
+
}
|
|
109
|
+
return {
|
|
110
|
+
intentId: r.intentId,
|
|
111
|
+
redirectUrl: r.redirectUrl,
|
|
112
|
+
status: r.status ?? "pending",
|
|
113
|
+
expiresAt: typeof r.expiresAt === "string" ? r.expiresAt : (/* @__PURE__ */ new Date()).toISOString(),
|
|
114
|
+
requiresKyc: r.requiresKyc === true
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
function parseGetResponse(raw) {
|
|
118
|
+
if (!raw || typeof raw !== "object") {
|
|
119
|
+
throw new NeetruError("invalid_response", "checkout.get response is not an object");
|
|
120
|
+
}
|
|
121
|
+
const r = raw;
|
|
122
|
+
const intent = r.intent;
|
|
123
|
+
if (!intent || typeof intent !== "object") {
|
|
124
|
+
throw new NeetruError("invalid_response", "checkout.get response missing intent");
|
|
125
|
+
}
|
|
126
|
+
if (typeof intent.intentId !== "string") {
|
|
127
|
+
throw new NeetruError("invalid_response", "checkout.get response missing intentId");
|
|
128
|
+
}
|
|
129
|
+
return {
|
|
130
|
+
intentId: intent.intentId,
|
|
131
|
+
uid: intent.uid ?? "",
|
|
132
|
+
targetTenantId: intent.targetTenantId ?? "",
|
|
133
|
+
targetTenantType: intent.targetTenantType ?? "pf",
|
|
134
|
+
productId: intent.productId ?? "",
|
|
135
|
+
planId: intent.planId ?? "",
|
|
136
|
+
callbackUrl: intent.callbackUrl ?? "",
|
|
137
|
+
status: intent.status ?? "pending",
|
|
138
|
+
stripeSessionId: intent.stripeSessionId ?? null,
|
|
139
|
+
expiresAt: intent.expiresAt ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
140
|
+
isStale: r.isStale === true
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
function inBrowser() {
|
|
144
|
+
try {
|
|
145
|
+
return typeof globalThis !== "undefined" && typeof globalThis.window !== "undefined" && typeof globalThis.location !== "undefined" && typeof globalThis.location.assign === "function";
|
|
146
|
+
} catch {
|
|
147
|
+
return false;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
function performRedirect(url) {
|
|
151
|
+
try {
|
|
152
|
+
globalThis.location.assign(url);
|
|
153
|
+
} catch {
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
function createHttpCheckoutNamespace(config) {
|
|
157
|
+
return {
|
|
158
|
+
async start(input) {
|
|
159
|
+
if (!input?.productId) {
|
|
160
|
+
throw new NeetruError("validation_failed", "checkout.start: productId is required");
|
|
161
|
+
}
|
|
162
|
+
if (!input?.planId) {
|
|
163
|
+
throw new NeetruError("validation_failed", "checkout.start: planId is required");
|
|
164
|
+
}
|
|
165
|
+
if (!input?.callbackUrl) {
|
|
166
|
+
throw new NeetruError("validation_failed", "checkout.start: callbackUrl is required");
|
|
167
|
+
}
|
|
168
|
+
const body = {
|
|
169
|
+
productId: input.productId,
|
|
170
|
+
planId: input.planId,
|
|
171
|
+
callbackUrl: input.callbackUrl
|
|
172
|
+
};
|
|
173
|
+
if (input.tenantType) body.targetTenantType = input.tenantType;
|
|
174
|
+
if (input.tenantId) body.targetTenantId = input.tenantId;
|
|
175
|
+
const raw = await httpRequest(config, {
|
|
176
|
+
method: "POST",
|
|
177
|
+
path: "/api/v1/checkout/intents",
|
|
178
|
+
body,
|
|
179
|
+
requireAuth: true
|
|
180
|
+
});
|
|
181
|
+
const result = parseStartResponse(raw);
|
|
182
|
+
const shouldRedirect = input.autoRedirect !== false;
|
|
183
|
+
if (shouldRedirect && inBrowser()) {
|
|
184
|
+
performRedirect(result.redirectUrl);
|
|
185
|
+
}
|
|
186
|
+
return result;
|
|
187
|
+
},
|
|
188
|
+
async get(intentId) {
|
|
189
|
+
if (!intentId || typeof intentId !== "string") {
|
|
190
|
+
throw new NeetruError("validation_failed", "checkout.get: intentId is required");
|
|
191
|
+
}
|
|
192
|
+
const raw = await httpRequest(config, {
|
|
193
|
+
method: "GET",
|
|
194
|
+
path: `/api/v1/checkout/intents/${encodeURIComponent(intentId)}`,
|
|
195
|
+
requireAuth: true
|
|
196
|
+
});
|
|
197
|
+
return parseGetResponse(raw);
|
|
198
|
+
},
|
|
199
|
+
async cancel(intentId) {
|
|
200
|
+
if (!intentId || typeof intentId !== "string") {
|
|
201
|
+
throw new NeetruError("validation_failed", "checkout.cancel: intentId is required");
|
|
202
|
+
}
|
|
203
|
+
const raw = await httpRequest(config, {
|
|
204
|
+
method: "DELETE",
|
|
205
|
+
path: `/api/v1/checkout/intents/${encodeURIComponent(intentId)}`,
|
|
206
|
+
requireAuth: true
|
|
207
|
+
});
|
|
208
|
+
return {
|
|
209
|
+
ok: true,
|
|
210
|
+
alreadyCancelled: raw?.alreadyCancelled === true
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
var MockCheckout = class {
|
|
216
|
+
intents = /* @__PURE__ */ new Map();
|
|
217
|
+
async start(input) {
|
|
218
|
+
if (!input?.productId) {
|
|
219
|
+
throw new NeetruError("validation_failed", "checkout.start: productId is required");
|
|
220
|
+
}
|
|
221
|
+
if (!input?.planId) {
|
|
222
|
+
throw new NeetruError("validation_failed", "checkout.start: planId is required");
|
|
223
|
+
}
|
|
224
|
+
if (!input?.callbackUrl) {
|
|
225
|
+
throw new NeetruError("validation_failed", "checkout.start: callbackUrl is required");
|
|
226
|
+
}
|
|
227
|
+
const intentId = `chk_mock_${Math.random().toString(36).slice(2, 10)}`;
|
|
228
|
+
const expiresAt = new Date(Date.now() + 15 * 60 * 1e3).toISOString();
|
|
229
|
+
const redirectUrl = `https://localhost:9003/portal/checkout/${intentId}`;
|
|
230
|
+
this.intents.set(intentId, {
|
|
231
|
+
intentId,
|
|
232
|
+
uid: "dev-fixture-uid",
|
|
233
|
+
targetTenantId: input.tenantId ?? "dev-fixture-uid",
|
|
234
|
+
targetTenantType: input.tenantType ?? "pf",
|
|
235
|
+
productId: input.productId,
|
|
236
|
+
planId: input.planId,
|
|
237
|
+
callbackUrl: input.callbackUrl,
|
|
238
|
+
status: "pending",
|
|
239
|
+
stripeSessionId: null,
|
|
240
|
+
expiresAt
|
|
241
|
+
});
|
|
242
|
+
return {
|
|
243
|
+
intentId,
|
|
244
|
+
redirectUrl,
|
|
245
|
+
status: "pending",
|
|
246
|
+
expiresAt,
|
|
247
|
+
requiresKyc: false
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
async get(intentId) {
|
|
251
|
+
const found = this.intents.get(intentId);
|
|
252
|
+
if (!found) {
|
|
253
|
+
throw new NeetruError("not_found", `Mock intent ${intentId} not found`);
|
|
254
|
+
}
|
|
255
|
+
return { ...found };
|
|
256
|
+
}
|
|
257
|
+
async cancel(intentId) {
|
|
258
|
+
const found = this.intents.get(intentId);
|
|
259
|
+
if (!found) {
|
|
260
|
+
throw new NeetruError("not_found", `Mock intent ${intentId} not found`);
|
|
261
|
+
}
|
|
262
|
+
const alreadyCancelled = found.status === "cancelled";
|
|
263
|
+
this.intents.set(intentId, { ...found, status: "cancelled" });
|
|
264
|
+
return { ok: true, alreadyCancelled };
|
|
265
|
+
}
|
|
266
|
+
};
|
|
267
|
+
function createCheckoutNamespace(config) {
|
|
268
|
+
if (config.env === "dev") return new MockCheckout();
|
|
269
|
+
return createHttpCheckoutNamespace(config);
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
exports.MockCheckout = MockCheckout;
|
|
273
|
+
exports.createCheckoutNamespace = createCheckoutNamespace;
|
|
274
|
+
//# sourceMappingURL=checkout.cjs.map
|
|
275
|
+
//# sourceMappingURL=checkout.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/errors.ts","../src/http.ts","../src/checkout.ts"],"names":[],"mappings":"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","file":"checkout.cjs","sourcesContent":["/**\n * Erros tipados do SDK.\n *\n * Todo erro lançado pelo SDK estende `NeetruError` — caller pode discriminar\n * por `.code` (string estável) sem parsing de message.\n */\n\n/** Códigos de erro estáveis do SDK. Adicionar aqui requer minor bump. */\nexport type NeetruErrorCode =\n | 'invalid_config'\n | 'missing_api_key'\n | 'unauthorized'\n | 'forbidden'\n | 'not_found'\n | 'rate_limited'\n | 'validation_failed'\n | 'network_error'\n | 'invalid_response'\n | 'server_error'\n | 'unknown';\n\n/**\n * Erro tipado padrão do SDK. Sempre lançado em vez de Error genérico.\n *\n * @example\n * ```ts\n * try { await client.catalog.list(); }\n * catch (e) {\n * if (e instanceof NeetruError && e.code === 'rate_limited') retry();\n * }\n * ```\n */\nexport class NeetruError extends Error {\n public readonly code: NeetruErrorCode | string;\n public readonly status?: number;\n public readonly requestId?: string;\n\n constructor(\n code: NeetruErrorCode | string,\n message: string,\n status?: number,\n requestId?: string,\n ) {\n super(message);\n this.name = 'NeetruError';\n this.code = code;\n this.status = status;\n this.requestId = requestId;\n // Preserva o prototype chain ao herdar de Error (downlevel quirk de TS).\n Object.setPrototypeOf(this, NeetruError.prototype);\n }\n}\n","/**\n * HTTP transport interno do SDK.\n *\n * Responsabilidades:\n * - Construir URL absoluta a partir de `baseUrl` + path\n * - Injetar Bearer token quando `requireAuth=true`\n * - Mapear status HTTP → `NeetruError` com `code` estável\n * - Parse defensivo de JSON (não lança em body vazio em 204)\n *\n * Não faz retry/backoff em v0.1 (carry-over Sprint 3+).\n */\nimport { NeetruError, type NeetruErrorCode } from './errors';\nimport type { ResolvedConfig } from './types';\n\n/** Opções da request HTTP. */\nexport interface HttpRequestOptions {\n method?: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';\n /** Path relativo (ex: `/api/v1/cli/catalog`). Concatenado a `baseUrl`. */\n path: string;\n /** Query string params (chave → valor primitivo). Valores `undefined` ignorados. */\n query?: Record<string, string | number | boolean | undefined>;\n /** Body JSON-serializável. Ignorado em GET/DELETE. */\n body?: unknown;\n /**\n * Se true, injeta `Authorization: Bearer <apiKey>`. Lança `missing_api_key`\n * se config.apiKey ausente. Default false.\n */\n requireAuth?: boolean;\n /** Cabeçalhos extras. */\n headers?: Record<string, string>;\n}\n\n/** Mapeamento status → code estável do NeetruError. */\nfunction statusToCode(status: number): NeetruErrorCode {\n if (status === 401) return 'unauthorized';\n if (status === 403) return 'forbidden';\n if (status === 404) return 'not_found';\n if (status === 422 || status === 400) return 'validation_failed';\n if (status === 429) return 'rate_limited';\n if (status >= 500) return 'server_error';\n return 'unknown';\n}\n\nfunction buildUrl(baseUrl: string, path: string, query?: HttpRequestOptions['query']): string {\n // Trim trailing slash em base e leading em path pra evitar `//`.\n const base = baseUrl.replace(/\\/+$/, '');\n const p = path.startsWith('/') ? path : `/${path}`;\n const url = new URL(`${base}${p}`);\n if (query) {\n for (const [k, v] of Object.entries(query)) {\n if (v === undefined) continue;\n url.searchParams.set(k, String(v));\n }\n }\n return url.toString();\n}\n\n/** Parse JSON defensivo — retorna `undefined` em body vazio. */\nasync function safeJson(res: Response): Promise<unknown> {\n const text = await res.text();\n if (!text) return undefined;\n try {\n return JSON.parse(text);\n } catch {\n return undefined;\n }\n}\n\n/**\n * Executa request HTTP. Em sucesso retorna body parseado; em erro lança\n * `NeetruError` com `code` derivado do status.\n */\nexport async function httpRequest<T>(\n config: ResolvedConfig,\n opts: HttpRequestOptions,\n): Promise<T> {\n const method = opts.method ?? 'GET';\n const url = buildUrl(config.baseUrl, opts.path, opts.query);\n\n const headers: Record<string, string> = {\n accept: 'application/json',\n ...opts.headers,\n };\n\n if (opts.requireAuth) {\n if (!config.apiKey) {\n throw new NeetruError(\n 'missing_api_key',\n 'This operation requires an apiKey. Pass it to createNeetruClient({ apiKey }) or set NEETRU_API_KEY env var.',\n );\n }\n headers.authorization = `Bearer ${config.apiKey}`;\n }\n\n const init: RequestInit = { method, headers };\n if (opts.body !== undefined && method !== 'GET' && method !== 'DELETE') {\n headers['content-type'] = 'application/json';\n init.body = JSON.stringify(opts.body);\n }\n\n let res: Response;\n try {\n res = await config.fetch(url, init);\n } catch (err) {\n const message = err instanceof Error ? err.message : 'fetch failed';\n throw new NeetruError('network_error', `Network error: ${message}`);\n }\n\n const requestId = res.headers.get('x-request-id') ?? res.headers.get('x-correlation-id') ?? undefined;\n\n if (!res.ok) {\n const body = (await safeJson(res)) as { error?: { code?: string; message?: string } | string } | undefined;\n let code: string = statusToCode(res.status);\n let message = `HTTP ${res.status}`;\n if (body && typeof body === 'object' && 'error' in body) {\n const errField = body.error;\n if (typeof errField === 'string') {\n message = errField;\n } else if (errField && typeof errField === 'object') {\n if (typeof errField.code === 'string') code = errField.code;\n if (typeof errField.message === 'string') message = errField.message;\n }\n }\n throw new NeetruError(code, message, res.status, requestId);\n }\n\n const parsed = await safeJson(res);\n // Caller é responsável por validar shape; SDK assume backend correto.\n return parsed as T;\n}\n","/**\n * Checkout namespace (v1.1) — `client.checkout.*`\n *\n * Fluxo canônico (vide `docs/FLUXO_SIGNUP_BILLING_CHECKOUT.md` §6):\n * 1. SaaS produto chama `client.checkout.start({productId, planId, callbackUrl})`.\n * 2. SDK posta em `POST /api/v1/checkout/intents` (Bearer access_token OIDC).\n * 3. Core cria `checkout_intents/{intentId}` (TTL 15min) + retorna `redirectUrl`.\n * 4. Em browser, SDK redireciona automaticamente pra `redirectUrl`. Em\n * Node/SSR, retorna o objeto `{intentId, redirectUrl}` sem redirect.\n * 5. Portal (`minhaconta.neetru.com/portal/kyc/{intentId}`) coleta KYC + cartão.\n * 6. Usuário volta pra `callbackUrl?status=success&intentId=...` quando completo.\n *\n * **Dev mode** (`NEETRU_ENV=dev`): `start()` retorna URL fake sem network call.\n * Útil pra dev externo SaaS testar UI sem provisionar conta Neetru.\n *\n * **Estabilidade**: minor bump v1.0 → v1.1 (feature add, sem breaking).\n */\nimport { NeetruError } from './errors';\nimport { httpRequest } from './http';\nimport type { ResolvedConfig } from './types';\n\n// ─── Types públicos ─────────────────────────────────────────────────────────\n\n/** Tipo do tenant alvo da subscription (PF=uid, PJ=orgId). */\nexport type CheckoutTenantType = 'pf' | 'pj';\n\n/** Status do `checkout_intents/{intentId}` no Core. */\nexport type CheckoutIntentStatus =\n | 'pending'\n | 'kyc_in_progress'\n | 'stripe_redirected'\n | 'completed'\n | 'expired'\n | 'cancelled';\n\nexport interface CheckoutStartInput {\n /** Slug do produto no catálogo (ex: `neetru-pulse`). */\n productId: string;\n /** Slug do plano no catálogo do produto (ex: `pro_monthly`). */\n planId: string;\n /** Pra onde o produto SaaS quer voltar pós-checkout. https obrigatório (ou http://localhost em dev). */\n callbackUrl: string;\n /** Override pra checkout em nome de uma org. Default: PF do uid logado. */\n tenantType?: CheckoutTenantType;\n /** Quando `tenantType='pj'`, id da org. Ignorado quando PF. */\n tenantId?: string;\n /**\n * Em browsers, default `true` — SDK faz `window.location.href = redirectUrl`.\n * Passe `false` se quiser controlar o redirect manualmente.\n */\n autoRedirect?: boolean;\n}\n\nexport interface CheckoutStartResult {\n intentId: string;\n redirectUrl: string;\n status: CheckoutIntentStatus;\n expiresAt: string;\n /** True se KYC ainda precisa ser coletado no portal. UI pode mostrar hint. */\n requiresKyc: boolean;\n}\n\nexport interface CheckoutIntentInfo {\n intentId: string;\n uid: string;\n targetTenantId: string;\n targetTenantType: CheckoutTenantType;\n productId: string;\n planId: string;\n callbackUrl: string;\n status: CheckoutIntentStatus;\n /** Stripe Checkout Session id quando avançou pra `stripe_redirected`. */\n stripeSessionId?: string | null;\n expiresAt: string;\n /** True se já passou `expiresAt` mas Core ainda não marcou expired. */\n isStale?: boolean;\n}\n\nexport interface CheckoutNamespace {\n /**\n * Inicia checkout. Em browser, redireciona automaticamente pro portal.\n * Em Node/SSR, retorna o resultado sem efeitos colaterais — caller decide\n * o que fazer com `redirectUrl`.\n *\n * Dev mode (`NEETRU_ENV=dev`): retorna URL fake `https://localhost:9003/portal/checkout/mock-XXXX`.\n */\n start(input: CheckoutStartInput): Promise<CheckoutStartResult>;\n /** Lê estado atual do intent (Core). */\n get(intentId: string): Promise<CheckoutIntentInfo>;\n /** Cancela um intent que ainda não virou `stripe_redirected`. */\n cancel(intentId: string): Promise<{ ok: true; alreadyCancelled: boolean }>;\n}\n\n// ─── Implementação real (HTTP) ─────────────────────────────────────────────\n\ninterface RawStartCheckoutResponse {\n ok?: boolean;\n intentId?: string;\n redirectUrl?: string;\n status?: string;\n expiresAt?: string;\n requiresKyc?: boolean;\n}\n\ninterface RawGetCheckoutResponse {\n ok?: boolean;\n intent?: {\n intentId?: string;\n uid?: string;\n targetTenantId?: string;\n targetTenantType?: string;\n productId?: string;\n planId?: string;\n callbackUrl?: string;\n status?: string;\n stripeSessionId?: string | null;\n expiresAt?: string;\n };\n isStale?: boolean;\n}\n\nfunction parseStartResponse(raw: unknown): CheckoutStartResult {\n if (!raw || typeof raw !== 'object') {\n throw new NeetruError('invalid_response', 'checkout.start response is not an object');\n }\n const r = raw as RawStartCheckoutResponse;\n if (typeof r.intentId !== 'string' || !r.intentId) {\n throw new NeetruError('invalid_response', 'checkout.start response missing intentId');\n }\n if (typeof r.redirectUrl !== 'string' || !r.redirectUrl) {\n throw new NeetruError('invalid_response', 'checkout.start response missing redirectUrl');\n }\n return {\n intentId: r.intentId,\n redirectUrl: r.redirectUrl,\n status: (r.status as CheckoutIntentStatus | undefined) ?? 'pending',\n expiresAt: typeof r.expiresAt === 'string' ? r.expiresAt : new Date().toISOString(),\n requiresKyc: r.requiresKyc === true,\n };\n}\n\nfunction parseGetResponse(raw: unknown): CheckoutIntentInfo {\n if (!raw || typeof raw !== 'object') {\n throw new NeetruError('invalid_response', 'checkout.get response is not an object');\n }\n const r = raw as RawGetCheckoutResponse;\n const intent = r.intent;\n if (!intent || typeof intent !== 'object') {\n throw new NeetruError('invalid_response', 'checkout.get response missing intent');\n }\n if (typeof intent.intentId !== 'string') {\n throw new NeetruError('invalid_response', 'checkout.get response missing intentId');\n }\n return {\n intentId: intent.intentId,\n uid: intent.uid ?? '',\n targetTenantId: intent.targetTenantId ?? '',\n targetTenantType: (intent.targetTenantType as CheckoutTenantType | undefined) ?? 'pf',\n productId: intent.productId ?? '',\n planId: intent.planId ?? '',\n callbackUrl: intent.callbackUrl ?? '',\n status: (intent.status as CheckoutIntentStatus | undefined) ?? 'pending',\n stripeSessionId: intent.stripeSessionId ?? null,\n expiresAt: intent.expiresAt ?? new Date().toISOString(),\n isStale: r.isStale === true,\n };\n}\n\n/**\n * Detecta se estamos em browser context. Em SSR / Node / Edge, `window`\n * pode não existir — fazemos check defensivo.\n */\nfunction inBrowser(): boolean {\n try {\n return (\n typeof globalThis !== 'undefined' &&\n typeof (globalThis as { window?: { location?: { href?: string } } }).window !== 'undefined' &&\n typeof globalThis.location !== 'undefined' &&\n typeof globalThis.location.assign === 'function'\n );\n } catch {\n return false;\n }\n}\n\nfunction performRedirect(url: string): void {\n try {\n globalThis.location.assign(url);\n } catch {\n /* noop em runtimes sem location.assign — caller decide */\n }\n}\n\n/**\n * Implementação HTTP real. Posta no Core, parse response, redireciona se browser.\n */\nfunction createHttpCheckoutNamespace(config: ResolvedConfig): CheckoutNamespace {\n return {\n async start(input: CheckoutStartInput): Promise<CheckoutStartResult> {\n if (!input?.productId) {\n throw new NeetruError('validation_failed', 'checkout.start: productId is required');\n }\n if (!input?.planId) {\n throw new NeetruError('validation_failed', 'checkout.start: planId is required');\n }\n if (!input?.callbackUrl) {\n throw new NeetruError('validation_failed', 'checkout.start: callbackUrl is required');\n }\n\n const body: Record<string, unknown> = {\n productId: input.productId,\n planId: input.planId,\n callbackUrl: input.callbackUrl,\n };\n if (input.tenantType) body.targetTenantType = input.tenantType;\n if (input.tenantId) body.targetTenantId = input.tenantId;\n\n const raw = await httpRequest<RawStartCheckoutResponse>(config, {\n method: 'POST',\n path: '/api/v1/checkout/intents',\n body,\n requireAuth: true,\n });\n const result = parseStartResponse(raw);\n\n const shouldRedirect = input.autoRedirect !== false;\n if (shouldRedirect && inBrowser()) {\n performRedirect(result.redirectUrl);\n }\n return result;\n },\n\n async get(intentId: string): Promise<CheckoutIntentInfo> {\n if (!intentId || typeof intentId !== 'string') {\n throw new NeetruError('validation_failed', 'checkout.get: intentId is required');\n }\n const raw = await httpRequest<RawGetCheckoutResponse>(config, {\n method: 'GET',\n path: `/api/v1/checkout/intents/${encodeURIComponent(intentId)}`,\n requireAuth: true,\n });\n return parseGetResponse(raw);\n },\n\n async cancel(intentId: string): Promise<{ ok: true; alreadyCancelled: boolean }> {\n if (!intentId || typeof intentId !== 'string') {\n throw new NeetruError('validation_failed', 'checkout.cancel: intentId is required');\n }\n const raw = await httpRequest<{ ok?: boolean; alreadyCancelled?: boolean }>(config, {\n method: 'DELETE',\n path: `/api/v1/checkout/intents/${encodeURIComponent(intentId)}`,\n requireAuth: true,\n });\n return {\n ok: true,\n alreadyCancelled: (raw as { alreadyCancelled?: boolean })?.alreadyCancelled === true,\n };\n },\n };\n}\n\n// ─── Mock dev (sem network) ─────────────────────────────────────────────────\n\n/**\n * Mock dev — retorna URL fake `https://localhost:9003/portal/checkout/mock-XXXX`\n * sem tocar no Core. Útil pra dev externo SaaS testar UI/redirect sem precisar\n * de Bearer token Neetru.\n *\n * Dev mode persiste intents em mapa in-memory pro `get`/`cancel` retornarem\n * resultado consistente.\n */\nexport class MockCheckout implements CheckoutNamespace {\n private readonly intents = new Map<string, CheckoutIntentInfo>();\n\n async start(input: CheckoutStartInput): Promise<CheckoutStartResult> {\n if (!input?.productId) {\n throw new NeetruError('validation_failed', 'checkout.start: productId is required');\n }\n if (!input?.planId) {\n throw new NeetruError('validation_failed', 'checkout.start: planId is required');\n }\n if (!input?.callbackUrl) {\n throw new NeetruError('validation_failed', 'checkout.start: callbackUrl is required');\n }\n\n const intentId = `chk_mock_${Math.random().toString(36).slice(2, 10)}`;\n const expiresAt = new Date(Date.now() + 15 * 60 * 1000).toISOString();\n const redirectUrl = `https://localhost:9003/portal/checkout/${intentId}`;\n\n this.intents.set(intentId, {\n intentId,\n uid: 'dev-fixture-uid',\n targetTenantId: input.tenantId ?? 'dev-fixture-uid',\n targetTenantType: input.tenantType ?? 'pf',\n productId: input.productId,\n planId: input.planId,\n callbackUrl: input.callbackUrl,\n status: 'pending',\n stripeSessionId: null,\n expiresAt,\n });\n\n return {\n intentId,\n redirectUrl,\n status: 'pending',\n expiresAt,\n requiresKyc: false,\n };\n }\n\n async get(intentId: string): Promise<CheckoutIntentInfo> {\n const found = this.intents.get(intentId);\n if (!found) {\n throw new NeetruError('not_found', `Mock intent ${intentId} not found`);\n }\n return { ...found };\n }\n\n async cancel(intentId: string): Promise<{ ok: true; alreadyCancelled: boolean }> {\n const found = this.intents.get(intentId);\n if (!found) {\n throw new NeetruError('not_found', `Mock intent ${intentId} not found`);\n }\n const alreadyCancelled = found.status === 'cancelled';\n this.intents.set(intentId, { ...found, status: 'cancelled' });\n return { ok: true, alreadyCancelled };\n }\n}\n\n// ─── Factory ────────────────────────────────────────────────────────────────\n\nexport function createCheckoutNamespace(config: ResolvedConfig): CheckoutNamespace {\n if (config.env === 'dev') return new MockCheckout();\n return createHttpCheckoutNamespace(config);\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { d as CheckoutIntentInfo, e as CheckoutIntentStatus, f as CheckoutNamespace, g as CheckoutStartInput, h as CheckoutStartResult, i as CheckoutTenantType, M as MockCheckout, z as createCheckoutNamespace } from './types-BA53dd8S.cjs';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { d as CheckoutIntentInfo, e as CheckoutIntentStatus, f as CheckoutNamespace, g as CheckoutStartInput, h as CheckoutStartResult, i as CheckoutTenantType, M as MockCheckout, z as createCheckoutNamespace } from './types-BA53dd8S.js';
|
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
// src/errors.ts
|
|
2
|
+
var NeetruError = class _NeetruError extends Error {
|
|
3
|
+
code;
|
|
4
|
+
status;
|
|
5
|
+
requestId;
|
|
6
|
+
constructor(code, message, status, requestId) {
|
|
7
|
+
super(message);
|
|
8
|
+
this.name = "NeetruError";
|
|
9
|
+
this.code = code;
|
|
10
|
+
this.status = status;
|
|
11
|
+
this.requestId = requestId;
|
|
12
|
+
Object.setPrototypeOf(this, _NeetruError.prototype);
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
// src/http.ts
|
|
17
|
+
function statusToCode(status) {
|
|
18
|
+
if (status === 401) return "unauthorized";
|
|
19
|
+
if (status === 403) return "forbidden";
|
|
20
|
+
if (status === 404) return "not_found";
|
|
21
|
+
if (status === 422 || status === 400) return "validation_failed";
|
|
22
|
+
if (status === 429) return "rate_limited";
|
|
23
|
+
if (status >= 500) return "server_error";
|
|
24
|
+
return "unknown";
|
|
25
|
+
}
|
|
26
|
+
function buildUrl(baseUrl, path, query) {
|
|
27
|
+
const base = baseUrl.replace(/\/+$/, "");
|
|
28
|
+
const p = path.startsWith("/") ? path : `/${path}`;
|
|
29
|
+
const url = new URL(`${base}${p}`);
|
|
30
|
+
if (query) {
|
|
31
|
+
for (const [k, v] of Object.entries(query)) {
|
|
32
|
+
if (v === void 0) continue;
|
|
33
|
+
url.searchParams.set(k, String(v));
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return url.toString();
|
|
37
|
+
}
|
|
38
|
+
async function safeJson(res) {
|
|
39
|
+
const text = await res.text();
|
|
40
|
+
if (!text) return void 0;
|
|
41
|
+
try {
|
|
42
|
+
return JSON.parse(text);
|
|
43
|
+
} catch {
|
|
44
|
+
return void 0;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
async function httpRequest(config, opts) {
|
|
48
|
+
const method = opts.method ?? "GET";
|
|
49
|
+
const url = buildUrl(config.baseUrl, opts.path, opts.query);
|
|
50
|
+
const headers = {
|
|
51
|
+
accept: "application/json",
|
|
52
|
+
...opts.headers
|
|
53
|
+
};
|
|
54
|
+
if (opts.requireAuth) {
|
|
55
|
+
if (!config.apiKey) {
|
|
56
|
+
throw new NeetruError(
|
|
57
|
+
"missing_api_key",
|
|
58
|
+
"This operation requires an apiKey. Pass it to createNeetruClient({ apiKey }) or set NEETRU_API_KEY env var."
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
headers.authorization = `Bearer ${config.apiKey}`;
|
|
62
|
+
}
|
|
63
|
+
const init = { method, headers };
|
|
64
|
+
if (opts.body !== void 0 && method !== "GET" && method !== "DELETE") {
|
|
65
|
+
headers["content-type"] = "application/json";
|
|
66
|
+
init.body = JSON.stringify(opts.body);
|
|
67
|
+
}
|
|
68
|
+
let res;
|
|
69
|
+
try {
|
|
70
|
+
res = await config.fetch(url, init);
|
|
71
|
+
} catch (err) {
|
|
72
|
+
const message = err instanceof Error ? err.message : "fetch failed";
|
|
73
|
+
throw new NeetruError("network_error", `Network error: ${message}`);
|
|
74
|
+
}
|
|
75
|
+
const requestId = res.headers.get("x-request-id") ?? res.headers.get("x-correlation-id") ?? void 0;
|
|
76
|
+
if (!res.ok) {
|
|
77
|
+
const body = await safeJson(res);
|
|
78
|
+
let code = statusToCode(res.status);
|
|
79
|
+
let message = `HTTP ${res.status}`;
|
|
80
|
+
if (body && typeof body === "object" && "error" in body) {
|
|
81
|
+
const errField = body.error;
|
|
82
|
+
if (typeof errField === "string") {
|
|
83
|
+
message = errField;
|
|
84
|
+
} else if (errField && typeof errField === "object") {
|
|
85
|
+
if (typeof errField.code === "string") code = errField.code;
|
|
86
|
+
if (typeof errField.message === "string") message = errField.message;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
throw new NeetruError(code, message, res.status, requestId);
|
|
90
|
+
}
|
|
91
|
+
const parsed = await safeJson(res);
|
|
92
|
+
return parsed;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// src/checkout.ts
|
|
96
|
+
function parseStartResponse(raw) {
|
|
97
|
+
if (!raw || typeof raw !== "object") {
|
|
98
|
+
throw new NeetruError("invalid_response", "checkout.start response is not an object");
|
|
99
|
+
}
|
|
100
|
+
const r = raw;
|
|
101
|
+
if (typeof r.intentId !== "string" || !r.intentId) {
|
|
102
|
+
throw new NeetruError("invalid_response", "checkout.start response missing intentId");
|
|
103
|
+
}
|
|
104
|
+
if (typeof r.redirectUrl !== "string" || !r.redirectUrl) {
|
|
105
|
+
throw new NeetruError("invalid_response", "checkout.start response missing redirectUrl");
|
|
106
|
+
}
|
|
107
|
+
return {
|
|
108
|
+
intentId: r.intentId,
|
|
109
|
+
redirectUrl: r.redirectUrl,
|
|
110
|
+
status: r.status ?? "pending",
|
|
111
|
+
expiresAt: typeof r.expiresAt === "string" ? r.expiresAt : (/* @__PURE__ */ new Date()).toISOString(),
|
|
112
|
+
requiresKyc: r.requiresKyc === true
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
function parseGetResponse(raw) {
|
|
116
|
+
if (!raw || typeof raw !== "object") {
|
|
117
|
+
throw new NeetruError("invalid_response", "checkout.get response is not an object");
|
|
118
|
+
}
|
|
119
|
+
const r = raw;
|
|
120
|
+
const intent = r.intent;
|
|
121
|
+
if (!intent || typeof intent !== "object") {
|
|
122
|
+
throw new NeetruError("invalid_response", "checkout.get response missing intent");
|
|
123
|
+
}
|
|
124
|
+
if (typeof intent.intentId !== "string") {
|
|
125
|
+
throw new NeetruError("invalid_response", "checkout.get response missing intentId");
|
|
126
|
+
}
|
|
127
|
+
return {
|
|
128
|
+
intentId: intent.intentId,
|
|
129
|
+
uid: intent.uid ?? "",
|
|
130
|
+
targetTenantId: intent.targetTenantId ?? "",
|
|
131
|
+
targetTenantType: intent.targetTenantType ?? "pf",
|
|
132
|
+
productId: intent.productId ?? "",
|
|
133
|
+
planId: intent.planId ?? "",
|
|
134
|
+
callbackUrl: intent.callbackUrl ?? "",
|
|
135
|
+
status: intent.status ?? "pending",
|
|
136
|
+
stripeSessionId: intent.stripeSessionId ?? null,
|
|
137
|
+
expiresAt: intent.expiresAt ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
138
|
+
isStale: r.isStale === true
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
function inBrowser() {
|
|
142
|
+
try {
|
|
143
|
+
return typeof globalThis !== "undefined" && typeof globalThis.window !== "undefined" && typeof globalThis.location !== "undefined" && typeof globalThis.location.assign === "function";
|
|
144
|
+
} catch {
|
|
145
|
+
return false;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
function performRedirect(url) {
|
|
149
|
+
try {
|
|
150
|
+
globalThis.location.assign(url);
|
|
151
|
+
} catch {
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
function createHttpCheckoutNamespace(config) {
|
|
155
|
+
return {
|
|
156
|
+
async start(input) {
|
|
157
|
+
if (!input?.productId) {
|
|
158
|
+
throw new NeetruError("validation_failed", "checkout.start: productId is required");
|
|
159
|
+
}
|
|
160
|
+
if (!input?.planId) {
|
|
161
|
+
throw new NeetruError("validation_failed", "checkout.start: planId is required");
|
|
162
|
+
}
|
|
163
|
+
if (!input?.callbackUrl) {
|
|
164
|
+
throw new NeetruError("validation_failed", "checkout.start: callbackUrl is required");
|
|
165
|
+
}
|
|
166
|
+
const body = {
|
|
167
|
+
productId: input.productId,
|
|
168
|
+
planId: input.planId,
|
|
169
|
+
callbackUrl: input.callbackUrl
|
|
170
|
+
};
|
|
171
|
+
if (input.tenantType) body.targetTenantType = input.tenantType;
|
|
172
|
+
if (input.tenantId) body.targetTenantId = input.tenantId;
|
|
173
|
+
const raw = await httpRequest(config, {
|
|
174
|
+
method: "POST",
|
|
175
|
+
path: "/api/v1/checkout/intents",
|
|
176
|
+
body,
|
|
177
|
+
requireAuth: true
|
|
178
|
+
});
|
|
179
|
+
const result = parseStartResponse(raw);
|
|
180
|
+
const shouldRedirect = input.autoRedirect !== false;
|
|
181
|
+
if (shouldRedirect && inBrowser()) {
|
|
182
|
+
performRedirect(result.redirectUrl);
|
|
183
|
+
}
|
|
184
|
+
return result;
|
|
185
|
+
},
|
|
186
|
+
async get(intentId) {
|
|
187
|
+
if (!intentId || typeof intentId !== "string") {
|
|
188
|
+
throw new NeetruError("validation_failed", "checkout.get: intentId is required");
|
|
189
|
+
}
|
|
190
|
+
const raw = await httpRequest(config, {
|
|
191
|
+
method: "GET",
|
|
192
|
+
path: `/api/v1/checkout/intents/${encodeURIComponent(intentId)}`,
|
|
193
|
+
requireAuth: true
|
|
194
|
+
});
|
|
195
|
+
return parseGetResponse(raw);
|
|
196
|
+
},
|
|
197
|
+
async cancel(intentId) {
|
|
198
|
+
if (!intentId || typeof intentId !== "string") {
|
|
199
|
+
throw new NeetruError("validation_failed", "checkout.cancel: intentId is required");
|
|
200
|
+
}
|
|
201
|
+
const raw = await httpRequest(config, {
|
|
202
|
+
method: "DELETE",
|
|
203
|
+
path: `/api/v1/checkout/intents/${encodeURIComponent(intentId)}`,
|
|
204
|
+
requireAuth: true
|
|
205
|
+
});
|
|
206
|
+
return {
|
|
207
|
+
ok: true,
|
|
208
|
+
alreadyCancelled: raw?.alreadyCancelled === true
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
var MockCheckout = class {
|
|
214
|
+
intents = /* @__PURE__ */ new Map();
|
|
215
|
+
async start(input) {
|
|
216
|
+
if (!input?.productId) {
|
|
217
|
+
throw new NeetruError("validation_failed", "checkout.start: productId is required");
|
|
218
|
+
}
|
|
219
|
+
if (!input?.planId) {
|
|
220
|
+
throw new NeetruError("validation_failed", "checkout.start: planId is required");
|
|
221
|
+
}
|
|
222
|
+
if (!input?.callbackUrl) {
|
|
223
|
+
throw new NeetruError("validation_failed", "checkout.start: callbackUrl is required");
|
|
224
|
+
}
|
|
225
|
+
const intentId = `chk_mock_${Math.random().toString(36).slice(2, 10)}`;
|
|
226
|
+
const expiresAt = new Date(Date.now() + 15 * 60 * 1e3).toISOString();
|
|
227
|
+
const redirectUrl = `https://localhost:9003/portal/checkout/${intentId}`;
|
|
228
|
+
this.intents.set(intentId, {
|
|
229
|
+
intentId,
|
|
230
|
+
uid: "dev-fixture-uid",
|
|
231
|
+
targetTenantId: input.tenantId ?? "dev-fixture-uid",
|
|
232
|
+
targetTenantType: input.tenantType ?? "pf",
|
|
233
|
+
productId: input.productId,
|
|
234
|
+
planId: input.planId,
|
|
235
|
+
callbackUrl: input.callbackUrl,
|
|
236
|
+
status: "pending",
|
|
237
|
+
stripeSessionId: null,
|
|
238
|
+
expiresAt
|
|
239
|
+
});
|
|
240
|
+
return {
|
|
241
|
+
intentId,
|
|
242
|
+
redirectUrl,
|
|
243
|
+
status: "pending",
|
|
244
|
+
expiresAt,
|
|
245
|
+
requiresKyc: false
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
async get(intentId) {
|
|
249
|
+
const found = this.intents.get(intentId);
|
|
250
|
+
if (!found) {
|
|
251
|
+
throw new NeetruError("not_found", `Mock intent ${intentId} not found`);
|
|
252
|
+
}
|
|
253
|
+
return { ...found };
|
|
254
|
+
}
|
|
255
|
+
async cancel(intentId) {
|
|
256
|
+
const found = this.intents.get(intentId);
|
|
257
|
+
if (!found) {
|
|
258
|
+
throw new NeetruError("not_found", `Mock intent ${intentId} not found`);
|
|
259
|
+
}
|
|
260
|
+
const alreadyCancelled = found.status === "cancelled";
|
|
261
|
+
this.intents.set(intentId, { ...found, status: "cancelled" });
|
|
262
|
+
return { ok: true, alreadyCancelled };
|
|
263
|
+
}
|
|
264
|
+
};
|
|
265
|
+
function createCheckoutNamespace(config) {
|
|
266
|
+
if (config.env === "dev") return new MockCheckout();
|
|
267
|
+
return createHttpCheckoutNamespace(config);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
export { MockCheckout, createCheckoutNamespace };
|
|
271
|
+
//# sourceMappingURL=checkout.mjs.map
|
|
272
|
+
//# sourceMappingURL=checkout.mjs.map
|