threeu-sdk 0.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/README.md +176 -0
- package/dist/admin/index.d.ts +22 -0
- package/dist/admin/index.js +17 -0
- package/dist/admin/index.js.map +1 -0
- package/dist/chunk-2TGBSV6L.js +197 -0
- package/dist/chunk-2TGBSV6L.js.map +1 -0
- package/dist/chunk-6S7OFN23.js +81 -0
- package/dist/chunk-6S7OFN23.js.map +1 -0
- package/dist/chunk-6ZCBDWWQ.js +140 -0
- package/dist/chunk-6ZCBDWWQ.js.map +1 -0
- package/dist/chunk-BCUODRZW.js +78 -0
- package/dist/chunk-BCUODRZW.js.map +1 -0
- package/dist/chunk-H3XILKGI.js +70 -0
- package/dist/chunk-H3XILKGI.js.map +1 -0
- package/dist/chunk-HYSJ6YPN.js +425 -0
- package/dist/chunk-HYSJ6YPN.js.map +1 -0
- package/dist/chunk-LFF5LPWT.js +122 -0
- package/dist/chunk-LFF5LPWT.js.map +1 -0
- package/dist/chunk-OXAQGEMQ.js +3 -0
- package/dist/chunk-OXAQGEMQ.js.map +1 -0
- package/dist/chunk-USFJIM5K.js +195 -0
- package/dist/chunk-USFJIM5K.js.map +1 -0
- package/dist/chunk-ZWLFJIAM.js +69 -0
- package/dist/chunk-ZWLFJIAM.js.map +1 -0
- package/dist/define-B6ZJMWDI.d.ts +24 -0
- package/dist/developer/index.d.ts +120 -0
- package/dist/developer/index.js +106 -0
- package/dist/developer/index.js.map +1 -0
- package/dist/errors/index.d.ts +83 -0
- package/dist/errors/index.js +4 -0
- package/dist/errors/index.js.map +1 -0
- package/dist/index-ksmDFDZc.d.ts +90 -0
- package/dist/index.d.ts +68 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -0
- package/dist/plugin/index.d.ts +13 -0
- package/dist/plugin/index.js +27 -0
- package/dist/plugin/index.js.map +1 -0
- package/dist/plugin/server/index.d.ts +70 -0
- package/dist/plugin/server/index.js +105 -0
- package/dist/plugin/server/index.js.map +1 -0
- package/dist/pos/index.d.ts +26 -0
- package/dist/pos/index.js +24 -0
- package/dist/pos/index.js.map +1 -0
- package/dist/react/index.d.ts +5 -0
- package/dist/react/index.js +7 -0
- package/dist/react/index.js.map +1 -0
- package/dist/session-BFDRm-KJ.d.ts +94 -0
- package/dist/storefront/index.d.ts +76 -0
- package/dist/storefront/index.js +6 -0
- package/dist/storefront/index.js.map +1 -0
- package/dist/testing/index.d.ts +82 -0
- package/dist/testing/index.js +106 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/theme/index.d.ts +109 -0
- package/dist/theme/index.js +152 -0
- package/dist/theme/index.js.map +1 -0
- package/dist/threeu-BesFjXdw.d.ts +143 -0
- package/dist/types-BoGD3IXz.d.ts +173 -0
- package/dist/types-DfyYnoLn.d.ts +248 -0
- package/dist/webhooks/index.d.ts +36 -0
- package/dist/webhooks/index.js +4 -0
- package/dist/webhooks/index.js.map +1 -0
- package/package.json +110 -0
|
@@ -0,0 +1,425 @@
|
|
|
1
|
+
import { resolveFetch, detectRuntime, runClientSafetyChecks } from './chunk-H3XILKGI.js';
|
|
2
|
+
import { errorFromResponse, ThreeuError, ThreeuTimeoutError, ThreeuNetworkError } from './chunk-LFF5LPWT.js';
|
|
3
|
+
|
|
4
|
+
// src/version.ts
|
|
5
|
+
var SDK_VERSION = "0.1.0";
|
|
6
|
+
|
|
7
|
+
// src/core/pagination.ts
|
|
8
|
+
var Page = class {
|
|
9
|
+
constructor(items, meta) {
|
|
10
|
+
this.items = items;
|
|
11
|
+
this.meta = meta;
|
|
12
|
+
}
|
|
13
|
+
get length() {
|
|
14
|
+
return this.items.length;
|
|
15
|
+
}
|
|
16
|
+
[Symbol.iterator]() {
|
|
17
|
+
return this.items[Symbol.iterator]();
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
function normalizePage(body) {
|
|
21
|
+
let candidate = body;
|
|
22
|
+
if (body && typeof body === "object" && "success" in body && "data" in body) {
|
|
23
|
+
candidate = body.data;
|
|
24
|
+
}
|
|
25
|
+
if (Array.isArray(candidate)) {
|
|
26
|
+
return new Page(candidate, {
|
|
27
|
+
page: 1,
|
|
28
|
+
perPage: candidate.length,
|
|
29
|
+
total: candidate.length,
|
|
30
|
+
lastPage: 1,
|
|
31
|
+
hasMore: false
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
const paginator = candidate;
|
|
35
|
+
if (paginator && Array.isArray(paginator.data)) {
|
|
36
|
+
const page = paginator.current_page ?? 1;
|
|
37
|
+
const lastPage = paginator.last_page ?? page;
|
|
38
|
+
return new Page(paginator.data, {
|
|
39
|
+
page,
|
|
40
|
+
perPage: paginator.per_page ?? paginator.data.length,
|
|
41
|
+
total: paginator.total ?? paginator.data.length,
|
|
42
|
+
lastPage,
|
|
43
|
+
hasMore: page < lastPage
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
return new Page([], { page: 1, perPage: 0, total: 0, lastPage: 1, hasMore: false });
|
|
47
|
+
}
|
|
48
|
+
async function* iteratePages(fetchPage) {
|
|
49
|
+
let page = 1;
|
|
50
|
+
let safety = 1e5;
|
|
51
|
+
while (safety-- > 0) {
|
|
52
|
+
const result = await fetchPage(page);
|
|
53
|
+
for (const item of result.items) yield item;
|
|
54
|
+
if (!result.meta.hasMore) return;
|
|
55
|
+
page = result.meta.page + 1;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// src/core/redaction.ts
|
|
60
|
+
var SECRET_KEY_PATTERNS = [
|
|
61
|
+
"authorization",
|
|
62
|
+
"token",
|
|
63
|
+
"secret",
|
|
64
|
+
"password",
|
|
65
|
+
"api_key",
|
|
66
|
+
"apikey",
|
|
67
|
+
"credential",
|
|
68
|
+
"signature",
|
|
69
|
+
"x-plugin-signature",
|
|
70
|
+
"x-threeu-signature",
|
|
71
|
+
"webhook_secret",
|
|
72
|
+
"private_key",
|
|
73
|
+
"client_secret",
|
|
74
|
+
"access_token",
|
|
75
|
+
"refresh_token",
|
|
76
|
+
"card",
|
|
77
|
+
"cvv",
|
|
78
|
+
"pan"
|
|
79
|
+
];
|
|
80
|
+
var PII_KEY_PATTERNS = ["email", "phone", "ssn", "iban", "address"];
|
|
81
|
+
var REDACTED = "[redacted]";
|
|
82
|
+
function isSensitiveKey(key, includePii) {
|
|
83
|
+
const k = key.toLowerCase();
|
|
84
|
+
if (SECRET_KEY_PATTERNS.some((p) => k.includes(p))) return true;
|
|
85
|
+
if (includePii && PII_KEY_PATTERNS.some((p) => k.includes(p))) return true;
|
|
86
|
+
return false;
|
|
87
|
+
}
|
|
88
|
+
function redactHeaders(headers) {
|
|
89
|
+
const out = {};
|
|
90
|
+
const entries = headers instanceof Headers ? headers.entries() : Object.entries(headers);
|
|
91
|
+
for (const [key, value] of entries) {
|
|
92
|
+
out[key] = isSensitiveKey(key, false) ? REDACTED : value;
|
|
93
|
+
}
|
|
94
|
+
return out;
|
|
95
|
+
}
|
|
96
|
+
function redactValue(input, includePii = true, depth = 0) {
|
|
97
|
+
if (depth > 4) return "[truncated]";
|
|
98
|
+
if (input === null || typeof input !== "object") return input;
|
|
99
|
+
if (Array.isArray(input)) {
|
|
100
|
+
return input.slice(0, 20).map((v) => redactValue(v, includePii, depth + 1));
|
|
101
|
+
}
|
|
102
|
+
const out = {};
|
|
103
|
+
for (const [key, value] of Object.entries(input)) {
|
|
104
|
+
out[key] = isSensitiveKey(key, includePii) ? REDACTED : redactValue(value, includePii, depth + 1);
|
|
105
|
+
}
|
|
106
|
+
return out;
|
|
107
|
+
}
|
|
108
|
+
function templatizePath(path) {
|
|
109
|
+
const clean = path.split("?")[0] ?? path;
|
|
110
|
+
return clean.split("/").map((seg) => {
|
|
111
|
+
if (!seg) return seg;
|
|
112
|
+
if (/^\d+$/.test(seg)) return ":id";
|
|
113
|
+
if (/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(seg)) return ":id";
|
|
114
|
+
if (/^[A-Za-z0-9_-]{20,}$/.test(seg)) return ":token";
|
|
115
|
+
return seg;
|
|
116
|
+
}).join("/");
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// src/core/telemetry.ts
|
|
120
|
+
var TelemetryClient = class {
|
|
121
|
+
constructor(options = {}, fetchImpl) {
|
|
122
|
+
this.buffer = [];
|
|
123
|
+
this.enabled = options.enabled ?? false;
|
|
124
|
+
this.endpoint = options.endpoint;
|
|
125
|
+
this.sampleRate = clamp(options.sampleRate ?? 1, 0, 1);
|
|
126
|
+
this.flushIntervalMs = options.flushIntervalMs ?? 1e4;
|
|
127
|
+
this.maxBatchSize = options.maxBatchSize ?? 50;
|
|
128
|
+
this.fetchImpl = fetchImpl;
|
|
129
|
+
}
|
|
130
|
+
/** Record an event. Sampling + buffering applied here; never throws. */
|
|
131
|
+
record(event) {
|
|
132
|
+
if (!this.enabled || !this.endpoint) return;
|
|
133
|
+
if (this.sampleRate < 1 && Math.random() > this.sampleRate) return;
|
|
134
|
+
this.buffer.push(redactValue(event));
|
|
135
|
+
if (this.buffer.length >= this.maxBatchSize) {
|
|
136
|
+
void this.flush();
|
|
137
|
+
} else {
|
|
138
|
+
this.ensureTimer();
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
/** Flush buffered events immediately. Resolves even if the network call fails. */
|
|
142
|
+
async flush() {
|
|
143
|
+
if (!this.enabled || !this.endpoint || this.buffer.length === 0) return;
|
|
144
|
+
const batch = this.buffer;
|
|
145
|
+
this.buffer = [];
|
|
146
|
+
try {
|
|
147
|
+
const fetcher = resolveFetch(this.fetchImpl);
|
|
148
|
+
await fetcher(this.endpoint, {
|
|
149
|
+
method: "POST",
|
|
150
|
+
headers: { "Content-Type": "application/json" },
|
|
151
|
+
body: JSON.stringify({ events: batch }),
|
|
152
|
+
keepalive: true
|
|
153
|
+
});
|
|
154
|
+
} catch {
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
/** Stop the background flush timer and flush any remaining events. */
|
|
158
|
+
async close() {
|
|
159
|
+
if (this.timer) {
|
|
160
|
+
clearInterval(this.timer);
|
|
161
|
+
this.timer = void 0;
|
|
162
|
+
}
|
|
163
|
+
await this.flush();
|
|
164
|
+
}
|
|
165
|
+
ensureTimer() {
|
|
166
|
+
if (this.timer || !this.enabled) return;
|
|
167
|
+
this.timer = setInterval(() => void this.flush(), this.flushIntervalMs);
|
|
168
|
+
this.timer.unref?.();
|
|
169
|
+
}
|
|
170
|
+
};
|
|
171
|
+
function clamp(n, min, max) {
|
|
172
|
+
return Math.min(max, Math.max(min, n));
|
|
173
|
+
}
|
|
174
|
+
function emitEvent(event, logger, telemetry) {
|
|
175
|
+
telemetry?.record(event);
|
|
176
|
+
if (!logger) return;
|
|
177
|
+
const level = event.type === "request:error" || event.type === "request:timeout" ? "error" : event.type === "request:retry" || event.type === "request:rate_limited" || event.type === "request:permission_denied" ? "warn" : event.type === "request:start" ? "debug" : "info";
|
|
178
|
+
try {
|
|
179
|
+
logger[level]?.(event);
|
|
180
|
+
} catch {
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// src/core/http-client.ts
|
|
185
|
+
var DEFAULT_BASE_URL = "https://api.threeu.app";
|
|
186
|
+
var DEFAULT_TIMEOUT_MS = 3e4;
|
|
187
|
+
var DEFAULT_RETRIES = 2;
|
|
188
|
+
var requestCounter = 0;
|
|
189
|
+
var ThreeuHttpClient = class {
|
|
190
|
+
constructor(options = {}) {
|
|
191
|
+
this.runtime = detectRuntime();
|
|
192
|
+
this.baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\/+$/, "");
|
|
193
|
+
this.token = options.token;
|
|
194
|
+
this.tokenType = options.tokenType;
|
|
195
|
+
this.brand = options.brand;
|
|
196
|
+
this.timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
197
|
+
this.retries = options.retries ?? DEFAULT_RETRIES;
|
|
198
|
+
this.fetchImpl = resolveFetch(options.fetch);
|
|
199
|
+
this.logger = options.logger;
|
|
200
|
+
this.telemetry = new TelemetryClient(options.telemetry, this.fetchImpl);
|
|
201
|
+
this.defaultHeaders = options.defaultHeaders ?? {};
|
|
202
|
+
this.appName = options.app?.name;
|
|
203
|
+
runClientSafetyChecks({
|
|
204
|
+
tokenType: this.tokenType,
|
|
205
|
+
baseUrl: this.baseUrl,
|
|
206
|
+
runtime: this.runtime,
|
|
207
|
+
suppressWarnings: options.suppressWarnings
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
get(path, options) {
|
|
211
|
+
return this.request("GET", path, options);
|
|
212
|
+
}
|
|
213
|
+
post(path, options) {
|
|
214
|
+
return this.request("POST", path, options);
|
|
215
|
+
}
|
|
216
|
+
put(path, options) {
|
|
217
|
+
return this.request("PUT", path, options);
|
|
218
|
+
}
|
|
219
|
+
patch(path, options) {
|
|
220
|
+
return this.request("PATCH", path, options);
|
|
221
|
+
}
|
|
222
|
+
delete(path, options) {
|
|
223
|
+
return this.request("DELETE", path, options);
|
|
224
|
+
}
|
|
225
|
+
/** Fetch a single page and normalize it into a `Page<T>`. */
|
|
226
|
+
async list(path, options) {
|
|
227
|
+
const body = await this.request("GET", path, options);
|
|
228
|
+
return normalizePage(body);
|
|
229
|
+
}
|
|
230
|
+
/** Async-iterate every item across all pages. */
|
|
231
|
+
iterate(path, options) {
|
|
232
|
+
return iteratePages(
|
|
233
|
+
(page) => this.list(path, { ...options, query: { ...options?.query ?? {}, page } })
|
|
234
|
+
);
|
|
235
|
+
}
|
|
236
|
+
/** Flush and stop telemetry; call on shutdown. */
|
|
237
|
+
async close() {
|
|
238
|
+
await this.telemetry.close();
|
|
239
|
+
}
|
|
240
|
+
async request(method, path, options = {}) {
|
|
241
|
+
const url = this.buildUrl(path, options.query);
|
|
242
|
+
const pathTemplate = templatizePath(path);
|
|
243
|
+
const requestId = nextRequestId();
|
|
244
|
+
const maxRetries = options.idempotent || method === "GET" ? options.retries ?? this.retries : 0;
|
|
245
|
+
const timeoutMs = options.timeoutMs ?? this.timeoutMs;
|
|
246
|
+
const baseEvent = {
|
|
247
|
+
type: "request:start",
|
|
248
|
+
requestId,
|
|
249
|
+
method,
|
|
250
|
+
pathTemplate,
|
|
251
|
+
runtime: this.runtime,
|
|
252
|
+
sdkVersion: SDK_VERSION,
|
|
253
|
+
appName: this.appName,
|
|
254
|
+
brandId: options.brand ?? this.brand
|
|
255
|
+
};
|
|
256
|
+
this.emit(baseEvent);
|
|
257
|
+
let attempt = 0;
|
|
258
|
+
let lastError;
|
|
259
|
+
while (attempt <= maxRetries) {
|
|
260
|
+
const start = Date.now();
|
|
261
|
+
try {
|
|
262
|
+
const response = await this.send(method, url, options, requestId, timeoutMs);
|
|
263
|
+
const durationMs = Date.now() - start;
|
|
264
|
+
const parsed = await parseBody(response);
|
|
265
|
+
if (!response.ok) {
|
|
266
|
+
const retryAfter = parseRetryAfter(response.headers.get("retry-after"));
|
|
267
|
+
const error = errorFromResponse(response.status, parsed, requestId, retryAfter);
|
|
268
|
+
this.emitError(error, baseEvent, durationMs, attempt);
|
|
269
|
+
if (error.retryable && attempt < maxRetries) {
|
|
270
|
+
await backoff(attempt, error);
|
|
271
|
+
attempt++;
|
|
272
|
+
lastError = error;
|
|
273
|
+
continue;
|
|
274
|
+
}
|
|
275
|
+
throw error;
|
|
276
|
+
}
|
|
277
|
+
this.emit({
|
|
278
|
+
...baseEvent,
|
|
279
|
+
type: "request:success",
|
|
280
|
+
statusCode: response.status,
|
|
281
|
+
durationMs,
|
|
282
|
+
retryCount: attempt
|
|
283
|
+
});
|
|
284
|
+
return unwrapEnvelope(parsed);
|
|
285
|
+
} catch (err) {
|
|
286
|
+
const durationMs = Date.now() - start;
|
|
287
|
+
const normalized = this.normalizeThrown(err, requestId);
|
|
288
|
+
if (normalized.retryable && attempt < maxRetries) {
|
|
289
|
+
this.emit({ ...baseEvent, type: "request:retry", durationMs, retryCount: attempt, errorCode: normalized.code });
|
|
290
|
+
await backoff(attempt, normalized);
|
|
291
|
+
attempt++;
|
|
292
|
+
lastError = normalized;
|
|
293
|
+
continue;
|
|
294
|
+
}
|
|
295
|
+
if (normalized instanceof ThreeuError && !(err instanceof ThreeuError)) {
|
|
296
|
+
this.emitError(normalized, baseEvent, durationMs, attempt);
|
|
297
|
+
}
|
|
298
|
+
throw normalized;
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
throw lastError ?? new ThreeuError("Request failed after retries", { requestId });
|
|
302
|
+
}
|
|
303
|
+
async send(method, url, options, requestId, timeoutMs) {
|
|
304
|
+
const controller = new AbortController();
|
|
305
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
306
|
+
const onExternalAbort = () => controller.abort();
|
|
307
|
+
options.signal?.addEventListener("abort", onExternalAbort, { once: true });
|
|
308
|
+
try {
|
|
309
|
+
const init = {
|
|
310
|
+
method,
|
|
311
|
+
headers: this.buildHeaders(method, options, requestId),
|
|
312
|
+
signal: controller.signal
|
|
313
|
+
};
|
|
314
|
+
if (options.form) {
|
|
315
|
+
init.body = options.form;
|
|
316
|
+
} else if (options.body !== void 0 && method !== "GET") {
|
|
317
|
+
init.body = JSON.stringify(options.body);
|
|
318
|
+
}
|
|
319
|
+
return await this.fetchImpl(url, init);
|
|
320
|
+
} finally {
|
|
321
|
+
clearTimeout(timer);
|
|
322
|
+
options.signal?.removeEventListener("abort", onExternalAbort);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
buildHeaders(method, options, requestId) {
|
|
326
|
+
const headers = {
|
|
327
|
+
Accept: "application/json",
|
|
328
|
+
"X-Threeu-Sdk-Version": SDK_VERSION,
|
|
329
|
+
"X-Request-Id": requestId,
|
|
330
|
+
...this.defaultHeaders,
|
|
331
|
+
...options.headers ?? {}
|
|
332
|
+
};
|
|
333
|
+
if (!options.form && options.body !== void 0 && method !== "GET") {
|
|
334
|
+
headers["Content-Type"] = "application/json";
|
|
335
|
+
}
|
|
336
|
+
if (this.token) headers.Authorization = `Bearer ${this.token}`;
|
|
337
|
+
const brand = options.brand ?? this.brand;
|
|
338
|
+
if (brand !== void 0 && brand !== null) {
|
|
339
|
+
headers["platform-id"] = String(brand);
|
|
340
|
+
headers["X-Brand-ID"] = String(brand);
|
|
341
|
+
}
|
|
342
|
+
const idem = options.idempotencyKey ?? (options.idempotent && method !== "GET" ? requestId : void 0);
|
|
343
|
+
if (idem) headers["Idempotency-Key"] = idem;
|
|
344
|
+
return headers;
|
|
345
|
+
}
|
|
346
|
+
buildUrl(path, query) {
|
|
347
|
+
const base = path.startsWith("http") ? path : `${this.baseUrl}/${path.replace(/^\/+/, "")}`;
|
|
348
|
+
if (!query) return base;
|
|
349
|
+
const params = new URLSearchParams();
|
|
350
|
+
for (const [key, value] of Object.entries(query)) {
|
|
351
|
+
if (value === void 0 || value === null) continue;
|
|
352
|
+
if (Array.isArray(value)) {
|
|
353
|
+
for (const v of value) params.append(`${key}[]`, String(v));
|
|
354
|
+
} else {
|
|
355
|
+
params.append(key, String(value));
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
const qs = params.toString();
|
|
359
|
+
return qs ? `${base}${base.includes("?") ? "&" : "?"}${qs}` : base;
|
|
360
|
+
}
|
|
361
|
+
normalizeThrown(err, requestId) {
|
|
362
|
+
if (err instanceof ThreeuError) return err;
|
|
363
|
+
if (err instanceof Error && err.name === "AbortError") {
|
|
364
|
+
return new ThreeuTimeoutError("Request aborted or timed out", { requestId, cause: err });
|
|
365
|
+
}
|
|
366
|
+
return new ThreeuNetworkError(err instanceof Error ? err.message : "Network request failed", {
|
|
367
|
+
requestId,
|
|
368
|
+
cause: err
|
|
369
|
+
});
|
|
370
|
+
}
|
|
371
|
+
emit(event) {
|
|
372
|
+
emitEvent(event, this.logger, this.telemetry);
|
|
373
|
+
}
|
|
374
|
+
emitError(error, base, durationMs, attempt) {
|
|
375
|
+
const type = error.status === 429 ? "request:rate_limited" : error.status === 403 ? "request:permission_denied" : error.status === 422 ? "request:validation_failed" : error.code === "timeout" ? "request:timeout" : "request:error";
|
|
376
|
+
this.emit({
|
|
377
|
+
...base,
|
|
378
|
+
type,
|
|
379
|
+
statusCode: error.status,
|
|
380
|
+
durationMs,
|
|
381
|
+
retryCount: attempt,
|
|
382
|
+
errorCode: error.code,
|
|
383
|
+
errorType: error.name
|
|
384
|
+
});
|
|
385
|
+
}
|
|
386
|
+
};
|
|
387
|
+
function nextRequestId() {
|
|
388
|
+
requestCounter = (requestCounter + 1) % Number.MAX_SAFE_INTEGER;
|
|
389
|
+
const rand = Math.random().toString(36).slice(2, 10);
|
|
390
|
+
return `sdk_${Date.now().toString(36)}_${requestCounter.toString(36)}_${rand}`;
|
|
391
|
+
}
|
|
392
|
+
async function parseBody(response) {
|
|
393
|
+
const contentType = response.headers.get("content-type") ?? "";
|
|
394
|
+
if (response.status === 204) return null;
|
|
395
|
+
if (contentType.includes("application/json")) {
|
|
396
|
+
try {
|
|
397
|
+
return await response.json();
|
|
398
|
+
} catch {
|
|
399
|
+
return null;
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
const text = await response.text();
|
|
403
|
+
return text.length ? text : null;
|
|
404
|
+
}
|
|
405
|
+
function unwrapEnvelope(parsed) {
|
|
406
|
+
if (parsed && typeof parsed === "object" && "success" in parsed && "data" in parsed) {
|
|
407
|
+
return parsed.data;
|
|
408
|
+
}
|
|
409
|
+
return parsed;
|
|
410
|
+
}
|
|
411
|
+
function parseRetryAfter(header) {
|
|
412
|
+
if (!header) return void 0;
|
|
413
|
+
const seconds = Number(header);
|
|
414
|
+
return Number.isFinite(seconds) ? seconds : void 0;
|
|
415
|
+
}
|
|
416
|
+
async function backoff(attempt, error) {
|
|
417
|
+
const retryAfterMs = "retryAfterSeconds" in error && typeof error.retryAfterSeconds === "number" ? error.retryAfterSeconds * 1e3 : void 0;
|
|
418
|
+
const base = retryAfterMs ?? Math.min(1e3 * 2 ** attempt, 8e3);
|
|
419
|
+
const jitter = base * 0.2 * Math.random();
|
|
420
|
+
await new Promise((resolve) => setTimeout(resolve, base + jitter));
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
export { Page, SDK_VERSION, TelemetryClient, ThreeuHttpClient, emitEvent, iteratePages, normalizePage, redactHeaders, redactValue, templatizePath };
|
|
424
|
+
//# sourceMappingURL=chunk-HYSJ6YPN.js.map
|
|
425
|
+
//# sourceMappingURL=chunk-HYSJ6YPN.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/version.ts","../src/core/pagination.ts","../src/core/redaction.ts","../src/core/telemetry.ts","../src/core/http-client.ts"],"names":[],"mappings":"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","file":"chunk-HYSJ6YPN.js","sourcesContent":["/**\n * Single source of truth for the SDK version. Emitted in telemetry events and\n * the User-Agent / X-Threeu-Sdk-Version header. Keep in sync with package.json.\n */\nexport const SDK_VERSION = \"0.1.0\";\n","/**\n * Pagination normalization. The backend wraps a Laravel paginator inside the\n * `data` field: `{ success, data: { data:[...], current_page, per_page, total,\n * last_page } }`; some endpoints return a flat array in `data`\n * (docs/ARCHITECTURE_MAP.md §11). Both shapes normalize to a `Page<T>`.\n */\n\nexport interface PageMeta {\n page: number;\n perPage: number;\n total: number;\n lastPage: number;\n hasMore: boolean;\n}\n\nexport class Page<T> {\n constructor(\n readonly items: T[],\n readonly meta: PageMeta,\n ) {}\n\n get length(): number {\n return this.items.length;\n }\n\n [Symbol.iterator](): Iterator<T> {\n return this.items[Symbol.iterator]();\n }\n}\n\ninterface LaravelPaginator<T> {\n data: T[];\n current_page?: number;\n per_page?: number;\n total?: number;\n last_page?: number;\n}\n\n/**\n * Normalize a parsed response body into a `Page<T>`. Accepts the ThreeU\n * `{ success, data }` envelope where `data` is either a paginator or a flat array.\n */\nexport function normalizePage<T>(body: unknown): Page<T> {\n // `body` may be the full `{ success, data }` envelope, an already-unwrapped\n // paginator object, or a flat array — the transport unwraps the envelope\n // before this runs, so handle all three.\n let candidate: unknown = body;\n if (body && typeof body === \"object\" && \"success\" in body && \"data\" in body) {\n candidate = (body as { data: unknown }).data;\n }\n\n // Flat array response.\n if (Array.isArray(candidate)) {\n return new Page<T>(candidate as T[], {\n page: 1,\n perPage: candidate.length,\n total: candidate.length,\n lastPage: 1,\n hasMore: false,\n });\n }\n\n // Laravel paginator (its own `data` field holds the items).\n const paginator = candidate as LaravelPaginator<T>;\n if (paginator && Array.isArray(paginator.data)) {\n const page = paginator.current_page ?? 1;\n const lastPage = paginator.last_page ?? page;\n return new Page<T>(paginator.data, {\n page,\n perPage: paginator.per_page ?? paginator.data.length,\n total: paginator.total ?? paginator.data.length,\n lastPage,\n hasMore: page < lastPage,\n });\n }\n\n // Unknown shape — surface as an empty page rather than throwing.\n return new Page<T>([], { page: 1, perPage: 0, total: 0, lastPage: 1, hasMore: false });\n}\n\n/**\n * Async generator that walks every page by incrementing `page` until the last\n * page is reached. `fetchPage` receives the 1-based page number.\n */\nexport async function* iteratePages<T>(\n fetchPage: (page: number) => Promise<Page<T>>,\n): AsyncGenerator<T, void, void> {\n let page = 1;\n // Guard against a backend that never advances `hasMore`.\n let safety = 100_000;\n while (safety-- > 0) {\n const result = await fetchPage(page);\n for (const item of result.items) yield item;\n if (!result.meta.hasMore) return;\n page = result.meta.page + 1;\n }\n}\n","/**\n * Redaction utilities. The SDK must NEVER emit tokens, secrets, credentials, or\n * customer PII into logs/telemetry (brief §observability \"Never log\"). Everything\n * that leaves the SDK as a log/telemetry event passes through here first.\n */\n\nconst SECRET_KEY_PATTERNS = [\n \"authorization\",\n \"token\",\n \"secret\",\n \"password\",\n \"api_key\",\n \"apikey\",\n \"credential\",\n \"signature\",\n \"x-plugin-signature\",\n \"x-threeu-signature\",\n \"webhook_secret\",\n \"private_key\",\n \"client_secret\",\n \"access_token\",\n \"refresh_token\",\n \"card\",\n \"cvv\",\n \"pan\",\n];\n\nconst PII_KEY_PATTERNS = [\"email\", \"phone\", \"ssn\", \"iban\", \"address\"];\n\nexport const REDACTED = \"[redacted]\";\n\nfunction isSensitiveKey(key: string, includePii: boolean): boolean {\n const k = key.toLowerCase();\n if (SECRET_KEY_PATTERNS.some((p) => k.includes(p))) return true;\n if (includePii && PII_KEY_PATTERNS.some((p) => k.includes(p))) return true;\n return false;\n}\n\n/** Redact sensitive header values, returning a safe-to-log copy. */\nexport function redactHeaders(headers: Record<string, string> | Headers): Record<string, string> {\n const out: Record<string, string> = {};\n const entries = headers instanceof Headers ? headers.entries() : Object.entries(headers);\n for (const [key, value] of entries) {\n out[key] = isSensitiveKey(key, false) ? REDACTED : value;\n }\n return out;\n}\n\n/**\n * Deep-redact an arbitrary value for logging. Replaces sensitive keys with\n * `[redacted]` and caps depth so we never serialize huge nested payloads.\n */\nexport function redactValue(input: unknown, includePii = true, depth = 0): unknown {\n if (depth > 4) return \"[truncated]\";\n if (input === null || typeof input !== \"object\") return input;\n\n if (Array.isArray(input)) {\n return input.slice(0, 20).map((v) => redactValue(v, includePii, depth + 1));\n }\n\n const out: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(input as Record<string, unknown>)) {\n out[key] = isSensitiveKey(key, includePii) ? REDACTED : redactValue(value, includePii, depth + 1);\n }\n return out;\n}\n\n/**\n * Collapse a concrete path into a template by eliding ids, so telemetry groups\n * `/plugins/42/webhook` and `/plugins/99/webhook` together as\n * `/plugins/:id/webhook`. Numeric and uuid-like segments are masked.\n */\nexport function templatizePath(path: string): string {\n const clean = path.split(\"?\")[0] ?? path;\n return clean\n .split(\"/\")\n .map((seg) => {\n if (!seg) return seg;\n if (/^\\d+$/.test(seg)) return \":id\";\n if (/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(seg)) return \":id\";\n if (/^[A-Za-z0-9_-]{20,}$/.test(seg)) return \":token\";\n return seg;\n })\n .join(\"/\");\n}\n","import type { ThreeuLogEvent, ThreeuLogger, ThreeuTelemetryOptions } from \"./types\";\nimport { redactValue } from \"./redaction\";\nimport { resolveFetch } from \"./runtime\";\n\n/**\n * Telemetry collector. Buffers safe-to-send SDK events, samples them, and flushes\n * batches to a configurable endpoint. Best-effort: a failed flush is swallowed so\n * telemetry can never break the host application. Payloads are redacted before\n * they leave the process.\n *\n * The backend telemetry route (POST /api/sdk/events) is NOT live yet\n * (docs/ARCHITECTURE_MAP.md §13) — until it ships, point `endpoint` at your own\n * collector or leave telemetry disabled.\n */\nexport class TelemetryClient {\n private readonly enabled: boolean;\n private readonly endpoint?: string;\n private readonly sampleRate: number;\n private readonly flushIntervalMs: number;\n private readonly maxBatchSize: number;\n private readonly fetchImpl?: typeof fetch;\n private buffer: ThreeuLogEvent[] = [];\n private timer: ReturnType<typeof setInterval> | undefined;\n\n constructor(options: ThreeuTelemetryOptions = {}, fetchImpl?: typeof fetch) {\n this.enabled = options.enabled ?? false;\n this.endpoint = options.endpoint;\n this.sampleRate = clamp(options.sampleRate ?? 1, 0, 1);\n this.flushIntervalMs = options.flushIntervalMs ?? 10_000;\n this.maxBatchSize = options.maxBatchSize ?? 50;\n this.fetchImpl = fetchImpl;\n }\n\n /** Record an event. Sampling + buffering applied here; never throws. */\n record(event: ThreeuLogEvent): void {\n if (!this.enabled || !this.endpoint) return;\n if (this.sampleRate < 1 && Math.random() > this.sampleRate) return;\n\n this.buffer.push(redactValue(event) as ThreeuLogEvent);\n if (this.buffer.length >= this.maxBatchSize) {\n void this.flush();\n } else {\n this.ensureTimer();\n }\n }\n\n /** Flush buffered events immediately. Resolves even if the network call fails. */\n async flush(): Promise<void> {\n if (!this.enabled || !this.endpoint || this.buffer.length === 0) return;\n const batch = this.buffer;\n this.buffer = [];\n try {\n const fetcher = resolveFetch(this.fetchImpl);\n await fetcher(this.endpoint, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ events: batch }),\n keepalive: true,\n });\n } catch {\n // Best-effort: drop the batch rather than surfacing telemetry failures.\n }\n }\n\n /** Stop the background flush timer and flush any remaining events. */\n async close(): Promise<void> {\n if (this.timer) {\n clearInterval(this.timer);\n this.timer = undefined;\n }\n await this.flush();\n }\n\n private ensureTimer(): void {\n if (this.timer || !this.enabled) return;\n this.timer = setInterval(() => void this.flush(), this.flushIntervalMs);\n // Don't keep a Node process alive purely for telemetry.\n (this.timer as { unref?: () => void }).unref?.();\n }\n}\n\nfunction clamp(n: number, min: number, max: number): number {\n return Math.min(max, Math.max(min, n));\n}\n\n/** Fan an event out to both the user logger and the telemetry collector. */\nexport function emitEvent(\n event: ThreeuLogEvent,\n logger: ThreeuLogger | undefined,\n telemetry: TelemetryClient | undefined,\n): void {\n telemetry?.record(event);\n if (!logger) return;\n const level: keyof ThreeuLogger =\n event.type === \"request:error\" || event.type === \"request:timeout\"\n ? \"error\"\n : event.type === \"request:retry\" ||\n event.type === \"request:rate_limited\" ||\n event.type === \"request:permission_denied\"\n ? \"warn\"\n : event.type === \"request:start\"\n ? \"debug\"\n : \"info\";\n try {\n logger[level]?.(event);\n } catch {\n // A throwing user logger must not break a request.\n }\n}\n","import { SDK_VERSION } from \"../version\";\nimport {\n ThreeuError,\n ThreeuNetworkError,\n ThreeuTimeoutError,\n errorFromResponse,\n} from \"./errors\";\nimport { iteratePages, normalizePage, type Page } from \"./pagination\";\nimport { redactHeaders, templatizePath } from \"./redaction\";\nimport { detectRuntime, resolveFetch } from \"./runtime\";\nimport { runClientSafetyChecks } from \"./safety\";\nimport { TelemetryClient, emitEvent } from \"./telemetry\";\nimport type {\n HttpMethod,\n RequestOptions,\n ThreeuClientOptions,\n ThreeuLogEvent,\n ThreeuLogger,\n TokenType,\n} from \"./types\";\n\nconst DEFAULT_BASE_URL = \"https://api.threeu.app\";\nconst DEFAULT_TIMEOUT_MS = 30_000;\nconst DEFAULT_RETRIES = 2;\n\nlet requestCounter = 0;\n\n/**\n * Central fetch-based transport shared by every client. Owns timeouts, safe\n * retries with backoff, idempotency keys, request-id propagation, query/JSON/\n * multipart serialization, error normalization, and logger/telemetry emission.\n */\nexport class ThreeuHttpClient {\n readonly baseUrl: string;\n private readonly token?: string;\n private readonly tokenType?: TokenType;\n private readonly brand?: string | number;\n private readonly timeoutMs: number;\n private readonly retries: number;\n private readonly fetchImpl: typeof fetch;\n private readonly logger?: ThreeuLogger;\n private readonly telemetry: TelemetryClient;\n private readonly defaultHeaders: Record<string, string>;\n private readonly appName?: string;\n private readonly runtime = detectRuntime();\n\n constructor(options: ThreeuClientOptions = {}) {\n this.baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\\/+$/, \"\");\n this.token = options.token;\n this.tokenType = options.tokenType;\n this.brand = options.brand;\n this.timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n this.retries = options.retries ?? DEFAULT_RETRIES;\n this.fetchImpl = resolveFetch(options.fetch);\n this.logger = options.logger;\n this.telemetry = new TelemetryClient(options.telemetry, this.fetchImpl);\n this.defaultHeaders = options.defaultHeaders ?? {};\n this.appName = options.app?.name;\n\n runClientSafetyChecks({\n tokenType: this.tokenType,\n baseUrl: this.baseUrl,\n runtime: this.runtime,\n suppressWarnings: options.suppressWarnings,\n });\n }\n\n get(path: string, options?: RequestOptions): Promise<unknown> {\n return this.request(\"GET\", path, options);\n }\n post(path: string, options?: RequestOptions): Promise<unknown> {\n return this.request(\"POST\", path, options);\n }\n put(path: string, options?: RequestOptions): Promise<unknown> {\n return this.request(\"PUT\", path, options);\n }\n patch(path: string, options?: RequestOptions): Promise<unknown> {\n return this.request(\"PATCH\", path, options);\n }\n delete(path: string, options?: RequestOptions): Promise<unknown> {\n return this.request(\"DELETE\", path, options);\n }\n\n /** Fetch a single page and normalize it into a `Page<T>`. */\n async list<T>(path: string, options?: RequestOptions): Promise<Page<T>> {\n const body = await this.request(\"GET\", path, options);\n return normalizePage<T>(body);\n }\n\n /** Async-iterate every item across all pages. */\n iterate<T>(path: string, options?: RequestOptions): AsyncGenerator<T, void, void> {\n return iteratePages<T>((page) =>\n this.list<T>(path, { ...options, query: { ...(options?.query ?? {}), page } }),\n );\n }\n\n /** Flush and stop telemetry; call on shutdown. */\n async close(): Promise<void> {\n await this.telemetry.close();\n }\n\n async request(method: HttpMethod, path: string, options: RequestOptions = {}): Promise<unknown> {\n const url = this.buildUrl(path, options.query);\n const pathTemplate = templatizePath(path);\n const requestId = nextRequestId();\n const maxRetries = options.idempotent || method === \"GET\" ? (options.retries ?? this.retries) : 0;\n const timeoutMs = options.timeoutMs ?? this.timeoutMs;\n\n const baseEvent: ThreeuLogEvent = {\n type: \"request:start\",\n requestId,\n method,\n pathTemplate,\n runtime: this.runtime,\n sdkVersion: SDK_VERSION,\n appName: this.appName,\n brandId: options.brand ?? this.brand,\n };\n this.emit(baseEvent);\n\n let attempt = 0;\n let lastError: ThreeuError | undefined;\n\n while (attempt <= maxRetries) {\n const start = Date.now();\n try {\n const response = await this.send(method, url, options, requestId, timeoutMs);\n const durationMs = Date.now() - start;\n const parsed = await parseBody(response);\n\n if (!response.ok) {\n const retryAfter = parseRetryAfter(response.headers.get(\"retry-after\"));\n const error = errorFromResponse(response.status, parsed, requestId, retryAfter);\n this.emitError(error, baseEvent, durationMs, attempt);\n if (error.retryable && attempt < maxRetries) {\n await backoff(attempt, error);\n attempt++;\n lastError = error;\n continue;\n }\n throw error;\n }\n\n this.emit({\n ...baseEvent,\n type: \"request:success\",\n statusCode: response.status,\n durationMs,\n retryCount: attempt,\n });\n return unwrapEnvelope(parsed);\n } catch (err) {\n const durationMs = Date.now() - start;\n const normalized = this.normalizeThrown(err, requestId);\n if (normalized.retryable && attempt < maxRetries) {\n this.emit({ ...baseEvent, type: \"request:retry\", durationMs, retryCount: attempt, errorCode: normalized.code });\n await backoff(attempt, normalized);\n attempt++;\n lastError = normalized;\n continue;\n }\n if (normalized instanceof ThreeuError && !(err instanceof ThreeuError)) {\n this.emitError(normalized, baseEvent, durationMs, attempt);\n }\n throw normalized;\n }\n }\n\n throw lastError ?? new ThreeuError(\"Request failed after retries\", { requestId });\n }\n\n private async send(\n method: HttpMethod,\n url: string,\n options: RequestOptions,\n requestId: string,\n timeoutMs: number,\n ): Promise<Response> {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n const onExternalAbort = () => controller.abort();\n options.signal?.addEventListener(\"abort\", onExternalAbort, { once: true });\n\n try {\n const init: RequestInit = {\n method,\n headers: this.buildHeaders(method, options, requestId),\n signal: controller.signal,\n };\n if (options.form) {\n init.body = options.form;\n } else if (options.body !== undefined && method !== \"GET\") {\n init.body = JSON.stringify(options.body);\n }\n return await this.fetchImpl(url, init);\n } finally {\n clearTimeout(timer);\n options.signal?.removeEventListener(\"abort\", onExternalAbort);\n }\n }\n\n private buildHeaders(method: HttpMethod, options: RequestOptions, requestId: string): Record<string, string> {\n const headers: Record<string, string> = {\n Accept: \"application/json\",\n \"X-Threeu-Sdk-Version\": SDK_VERSION,\n \"X-Request-Id\": requestId,\n ...this.defaultHeaders,\n ...(options.headers ?? {}),\n };\n\n if (!options.form && options.body !== undefined && method !== \"GET\") {\n headers[\"Content-Type\"] = \"application/json\";\n }\n if (this.token) headers.Authorization = `Bearer ${this.token}`;\n\n const brand = options.brand ?? this.brand;\n if (brand !== undefined && brand !== null) {\n headers[\"platform-id\"] = String(brand);\n headers[\"X-Brand-ID\"] = String(brand);\n }\n\n const idem = options.idempotencyKey ?? (options.idempotent && method !== \"GET\" ? requestId : undefined);\n if (idem) headers[\"Idempotency-Key\"] = idem;\n\n return headers;\n }\n\n private buildUrl(path: string, query?: Record<string, unknown>): string {\n const base = path.startsWith(\"http\") ? path : `${this.baseUrl}/${path.replace(/^\\/+/, \"\")}`;\n if (!query) return base;\n const params = new URLSearchParams();\n for (const [key, value] of Object.entries(query)) {\n if (value === undefined || value === null) continue;\n if (Array.isArray(value)) {\n for (const v of value) params.append(`${key}[]`, String(v));\n } else {\n params.append(key, String(value));\n }\n }\n const qs = params.toString();\n return qs ? `${base}${base.includes(\"?\") ? \"&\" : \"?\"}${qs}` : base;\n }\n\n private normalizeThrown(err: unknown, requestId: string): ThreeuError {\n if (err instanceof ThreeuError) return err;\n if (err instanceof Error && err.name === \"AbortError\") {\n return new ThreeuTimeoutError(\"Request aborted or timed out\", { requestId, cause: err });\n }\n return new ThreeuNetworkError(err instanceof Error ? err.message : \"Network request failed\", {\n requestId,\n cause: err,\n });\n }\n\n private emit(event: ThreeuLogEvent): void {\n emitEvent(event, this.logger, this.telemetry);\n }\n\n private emitError(error: ThreeuError, base: ThreeuLogEvent, durationMs: number, attempt: number): void {\n const type: ThreeuLogEvent[\"type\"] =\n error.status === 429\n ? \"request:rate_limited\"\n : error.status === 403\n ? \"request:permission_denied\"\n : error.status === 422\n ? \"request:validation_failed\"\n : error.code === \"timeout\"\n ? \"request:timeout\"\n : \"request:error\";\n this.emit({\n ...base,\n type,\n statusCode: error.status,\n durationMs,\n retryCount: attempt,\n errorCode: error.code,\n errorType: error.name,\n });\n }\n}\n\nfunction nextRequestId(): string {\n requestCounter = (requestCounter + 1) % Number.MAX_SAFE_INTEGER;\n const rand = Math.random().toString(36).slice(2, 10);\n return `sdk_${Date.now().toString(36)}_${requestCounter.toString(36)}_${rand}`;\n}\n\nasync function parseBody(response: Response): Promise<unknown> {\n const contentType = response.headers.get(\"content-type\") ?? \"\";\n if (response.status === 204) return null;\n if (contentType.includes(\"application/json\")) {\n try {\n return await response.json();\n } catch {\n return null;\n }\n }\n const text = await response.text();\n return text.length ? text : null;\n}\n\n/** Unwrap the `{ success, data }` envelope to the `data` payload when present. */\nfunction unwrapEnvelope(parsed: unknown): unknown {\n if (parsed && typeof parsed === \"object\" && \"success\" in parsed && \"data\" in parsed) {\n return (parsed as { data: unknown }).data;\n }\n return parsed;\n}\n\nfunction parseRetryAfter(header: string | null): number | undefined {\n if (!header) return undefined;\n const seconds = Number(header);\n return Number.isFinite(seconds) ? seconds : undefined;\n}\n\nasync function backoff(attempt: number, error: ThreeuError): Promise<void> {\n const retryAfterMs =\n \"retryAfterSeconds\" in error && typeof (error as { retryAfterSeconds?: number }).retryAfterSeconds === \"number\"\n ? (error as { retryAfterSeconds: number }).retryAfterSeconds * 1000\n : undefined;\n const base = retryAfterMs ?? Math.min(1000 * 2 ** attempt, 8000);\n const jitter = base * 0.2 * Math.random();\n await new Promise((resolve) => setTimeout(resolve, base + jitter));\n}\n\nexport { redactHeaders };\n"]}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
// src/core/errors.ts
|
|
2
|
+
var ThreeuError = class extends Error {
|
|
3
|
+
constructor(message, init = {}) {
|
|
4
|
+
super(message);
|
|
5
|
+
this.name = new.target.name;
|
|
6
|
+
this.code = init.code ?? "threeu_error";
|
|
7
|
+
this.status = init.status;
|
|
8
|
+
this.requestId = init.requestId;
|
|
9
|
+
this.details = init.details;
|
|
10
|
+
this.cause = init.cause;
|
|
11
|
+
this.retryable = init.retryable ?? false;
|
|
12
|
+
Object.setPrototypeOf(this, new.target.prototype);
|
|
13
|
+
}
|
|
14
|
+
toJSON() {
|
|
15
|
+
return {
|
|
16
|
+
name: this.name,
|
|
17
|
+
message: this.message,
|
|
18
|
+
code: this.code,
|
|
19
|
+
status: this.status,
|
|
20
|
+
requestId: this.requestId,
|
|
21
|
+
retryable: this.retryable,
|
|
22
|
+
details: this.details
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
var ThreeuApiError = class extends ThreeuError {
|
|
27
|
+
};
|
|
28
|
+
var ThreeuAuthError = class extends ThreeuError {
|
|
29
|
+
constructor(message = "Unauthenticated", init = {}) {
|
|
30
|
+
super(message, { code: "unauthenticated", status: 401, ...init });
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
var ThreeuPermissionError = class extends ThreeuError {
|
|
34
|
+
constructor(message = "Permission denied", init = {}) {
|
|
35
|
+
super(message, { code: "permission_denied", status: 403, ...init });
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
var ThreeuValidationError = class extends ThreeuError {
|
|
39
|
+
constructor(message = "Validation failed", init = {}) {
|
|
40
|
+
super(message, { code: "validation_failed", status: 422, ...init });
|
|
41
|
+
this.fields = init.fields ?? {};
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
var ThreeuNotFoundError = class extends ThreeuError {
|
|
45
|
+
constructor(message = "Not found", init = {}) {
|
|
46
|
+
super(message, { code: "not_found", status: 404, ...init });
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
var ThreeuConflictError = class extends ThreeuError {
|
|
50
|
+
constructor(message = "Conflict", init = {}) {
|
|
51
|
+
super(message, { code: "conflict", status: 409, ...init });
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
var ThreeuRateLimitError = class extends ThreeuError {
|
|
55
|
+
constructor(message = "Rate limited", init = {}) {
|
|
56
|
+
super(message, { code: "rate_limited", status: 429, retryable: true, ...init });
|
|
57
|
+
this.retryAfterSeconds = init.retryAfterSeconds;
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
var ThreeuTimeoutError = class extends ThreeuError {
|
|
61
|
+
constructor(message = "Request timed out", init = {}) {
|
|
62
|
+
super(message, { code: "timeout", retryable: true, ...init });
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
var ThreeuNetworkError = class extends ThreeuError {
|
|
66
|
+
constructor(message = "Network error", init = {}) {
|
|
67
|
+
super(message, { code: "network_error", retryable: true, ...init });
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
var ThreeuWebhookSignatureError = class extends ThreeuError {
|
|
71
|
+
constructor(message = "Invalid webhook signature", init = {}) {
|
|
72
|
+
super(message, { code: "webhook_signature_invalid", ...init });
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
var ThreeuManifestError = class extends ThreeuError {
|
|
76
|
+
constructor(message = "Invalid manifest", init = {}) {
|
|
77
|
+
super(message, { code: "manifest_invalid", ...init });
|
|
78
|
+
this.issues = init.issues ?? [];
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
var ThreeuProviderError = class extends ThreeuError {
|
|
82
|
+
constructor(message = "Provider error", init = {}) {
|
|
83
|
+
super(message, { code: "provider_error", ...init });
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
var ThreeuNotImplementedError = class extends ThreeuError {
|
|
87
|
+
constructor(message = "This endpoint is not yet available on the ThreeU backend", init = {}) {
|
|
88
|
+
super(message, { code: "not_implemented", status: 501, ...init });
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
function errorFromResponse(status, body, requestId, retryAfterSeconds) {
|
|
92
|
+
const record = body && typeof body === "object" ? body : {};
|
|
93
|
+
const message = typeof record.message === "string" && record.message || typeof record.error === "string" && record.error || `Request failed with status ${status}`;
|
|
94
|
+
const init = { status, requestId, details: body };
|
|
95
|
+
switch (status) {
|
|
96
|
+
case 400:
|
|
97
|
+
return new ThreeuApiError(message, { ...init, code: "bad_request" });
|
|
98
|
+
case 401:
|
|
99
|
+
return new ThreeuAuthError(message, init);
|
|
100
|
+
case 403:
|
|
101
|
+
return new ThreeuPermissionError(message, init);
|
|
102
|
+
case 404:
|
|
103
|
+
return new ThreeuNotFoundError(message, init);
|
|
104
|
+
case 409:
|
|
105
|
+
return new ThreeuConflictError(message, init);
|
|
106
|
+
case 422: {
|
|
107
|
+
const fields = record.errors && typeof record.errors === "object" ? record.errors : {};
|
|
108
|
+
return new ThreeuValidationError(message, { ...init, fields });
|
|
109
|
+
}
|
|
110
|
+
case 429:
|
|
111
|
+
return new ThreeuRateLimitError(message, { ...init, retryAfterSeconds });
|
|
112
|
+
case 501:
|
|
113
|
+
return new ThreeuNotImplementedError(message, init);
|
|
114
|
+
default:
|
|
115
|
+
if (status >= 500) return new ThreeuApiError(message, { ...init, code: "server_error", retryable: true });
|
|
116
|
+
return new ThreeuApiError(message, init);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export { ThreeuApiError, ThreeuAuthError, ThreeuConflictError, ThreeuError, ThreeuManifestError, ThreeuNetworkError, ThreeuNotFoundError, ThreeuNotImplementedError, ThreeuPermissionError, ThreeuProviderError, ThreeuRateLimitError, ThreeuTimeoutError, ThreeuValidationError, ThreeuWebhookSignatureError, errorFromResponse };
|
|
121
|
+
//# sourceMappingURL=chunk-LFF5LPWT.js.map
|
|
122
|
+
//# sourceMappingURL=chunk-LFF5LPWT.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/core/errors.ts"],"names":[],"mappings":"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","file":"chunk-LFF5LPWT.js","sourcesContent":["/**\n * Typed error hierarchy. Backend responses (both the `{success,message}`\n * convention and Laravel's `{message,errors}` validation shape — see\n * docs/ARCHITECTURE_MAP.md §10) are normalized into these classes so callers can\n * `catch` precisely and branch on `err.retryable`.\n */\n\nexport interface ThreeuErrorInit {\n code?: string;\n status?: number;\n requestId?: string;\n details?: unknown;\n cause?: unknown;\n retryable?: boolean;\n}\n\nexport class ThreeuError extends Error {\n readonly code: string;\n readonly status?: number;\n readonly requestId?: string;\n readonly details?: unknown;\n readonly cause?: unknown;\n readonly retryable: boolean;\n\n constructor(message: string, init: ThreeuErrorInit = {}) {\n super(message);\n this.name = new.target.name;\n this.code = init.code ?? \"threeu_error\";\n this.status = init.status;\n this.requestId = init.requestId;\n this.details = init.details;\n this.cause = init.cause;\n this.retryable = init.retryable ?? false;\n // Restore prototype chain for instanceof across transpile targets.\n Object.setPrototypeOf(this, new.target.prototype);\n }\n\n toJSON(): Record<string, unknown> {\n return {\n name: this.name,\n message: this.message,\n code: this.code,\n status: this.status,\n requestId: this.requestId,\n retryable: this.retryable,\n details: this.details,\n };\n }\n}\n\n/** A non-2xx HTTP response that didn't match a more specific subclass. */\nexport class ThreeuApiError extends ThreeuError {}\n\nexport class ThreeuAuthError extends ThreeuError {\n constructor(message = \"Unauthenticated\", init: ThreeuErrorInit = {}) {\n super(message, { code: \"unauthenticated\", status: 401, ...init });\n }\n}\n\nexport class ThreeuPermissionError extends ThreeuError {\n constructor(message = \"Permission denied\", init: ThreeuErrorInit = {}) {\n super(message, { code: \"permission_denied\", status: 403, ...init });\n }\n}\n\nexport class ThreeuValidationError extends ThreeuError {\n /** Field → messages map, mirroring Laravel's `errors` bag. */\n readonly fields: Record<string, string[]>;\n constructor(message = \"Validation failed\", init: ThreeuErrorInit & { fields?: Record<string, string[]> } = {}) {\n super(message, { code: \"validation_failed\", status: 422, ...init });\n this.fields = init.fields ?? {};\n }\n}\n\nexport class ThreeuNotFoundError extends ThreeuError {\n constructor(message = \"Not found\", init: ThreeuErrorInit = {}) {\n super(message, { code: \"not_found\", status: 404, ...init });\n }\n}\n\nexport class ThreeuConflictError extends ThreeuError {\n constructor(message = \"Conflict\", init: ThreeuErrorInit = {}) {\n super(message, { code: \"conflict\", status: 409, ...init });\n }\n}\n\nexport class ThreeuRateLimitError extends ThreeuError {\n /** Seconds to wait before retrying, from the `Retry-After` header if present. */\n readonly retryAfterSeconds?: number;\n constructor(message = \"Rate limited\", init: ThreeuErrorInit & { retryAfterSeconds?: number } = {}) {\n super(message, { code: \"rate_limited\", status: 429, retryable: true, ...init });\n this.retryAfterSeconds = init.retryAfterSeconds;\n }\n}\n\nexport class ThreeuTimeoutError extends ThreeuError {\n constructor(message = \"Request timed out\", init: ThreeuErrorInit = {}) {\n super(message, { code: \"timeout\", retryable: true, ...init });\n }\n}\n\nexport class ThreeuNetworkError extends ThreeuError {\n constructor(message = \"Network error\", init: ThreeuErrorInit = {}) {\n super(message, { code: \"network_error\", retryable: true, ...init });\n }\n}\n\nexport class ThreeuWebhookSignatureError extends ThreeuError {\n constructor(message = \"Invalid webhook signature\", init: ThreeuErrorInit = {}) {\n super(message, { code: \"webhook_signature_invalid\", ...init });\n }\n}\n\nexport class ThreeuManifestError extends ThreeuError {\n readonly issues: string[];\n constructor(message = \"Invalid manifest\", init: ThreeuErrorInit & { issues?: string[] } = {}) {\n super(message, { code: \"manifest_invalid\", ...init });\n this.issues = init.issues ?? [];\n }\n}\n\nexport class ThreeuProviderError extends ThreeuError {\n constructor(message = \"Provider error\", init: ThreeuErrorInit = {}) {\n super(message, { code: \"provider_error\", ...init });\n }\n}\n\n/** Thrown by experimental/stubbed methods whose backend route is not yet live. */\nexport class ThreeuNotImplementedError extends ThreeuError {\n constructor(message = \"This endpoint is not yet available on the ThreeU backend\", init: ThreeuErrorInit = {}) {\n super(message, { code: \"not_implemented\", status: 501, ...init });\n }\n}\n\n/**\n * Map an HTTP response (status + parsed body) into the right error class.\n * Handles both ThreeU's `{success,message}` envelope and Laravel's\n * `{message, errors}` validation shape.\n */\nexport function errorFromResponse(\n status: number,\n body: unknown,\n requestId?: string,\n retryAfterSeconds?: number,\n): ThreeuError {\n const record = (body && typeof body === \"object\" ? body : {}) as Record<string, unknown>;\n const message =\n (typeof record.message === \"string\" && record.message) ||\n (typeof record.error === \"string\" && record.error) ||\n `Request failed with status ${status}`;\n const init = { status, requestId, details: body };\n\n switch (status) {\n case 400:\n return new ThreeuApiError(message, { ...init, code: \"bad_request\" });\n case 401:\n return new ThreeuAuthError(message, init);\n case 403:\n return new ThreeuPermissionError(message, init);\n case 404:\n return new ThreeuNotFoundError(message, init);\n case 409:\n return new ThreeuConflictError(message, init);\n case 422: {\n const fields = (record.errors && typeof record.errors === \"object\"\n ? (record.errors as Record<string, string[]>)\n : {});\n return new ThreeuValidationError(message, { ...init, fields });\n }\n case 429:\n return new ThreeuRateLimitError(message, { ...init, retryAfterSeconds });\n case 501:\n return new ThreeuNotImplementedError(message, init);\n default:\n if (status >= 500) return new ThreeuApiError(message, { ...init, code: \"server_error\", retryable: true });\n return new ThreeuApiError(message, init);\n }\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"chunk-OXAQGEMQ.js"}
|