livepasses 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/LICENSE +21 -0
- package/README.md +431 -0
- package/dist/index.d.mts +677 -0
- package/dist/index.d.ts +677 -0
- package/dist/index.js +590 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +576 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +59 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,590 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
// src/types/common.ts
|
|
6
|
+
var ApiErrorCodes = {
|
|
7
|
+
// General Errors
|
|
8
|
+
GENERAL_ERROR: "GENERAL_ERROR",
|
|
9
|
+
INTERNAL_SERVER_ERROR: "INTERNAL_SERVER_ERROR",
|
|
10
|
+
SERVICE_UNAVAILABLE: "SERVICE_UNAVAILABLE",
|
|
11
|
+
// Authentication & Authorization
|
|
12
|
+
UNAUTHORIZED: "UNAUTHORIZED",
|
|
13
|
+
FORBIDDEN: "FORBIDDEN",
|
|
14
|
+
INVALID_API_KEY: "INVALID_API_KEY",
|
|
15
|
+
API_KEY_EXPIRED: "API_KEY_EXPIRED",
|
|
16
|
+
API_KEY_REVOKED: "API_KEY_REVOKED",
|
|
17
|
+
INSUFFICIENT_PERMISSIONS: "INSUFFICIENT_PERMISSIONS",
|
|
18
|
+
// Validation
|
|
19
|
+
VALIDATION_ERROR: "VALIDATION_ERROR",
|
|
20
|
+
REQUIRED_FIELD_MISSING: "REQUIRED_FIELD_MISSING",
|
|
21
|
+
INVALID_FIELD_VALUE: "INVALID_FIELD_VALUE",
|
|
22
|
+
INVALID_FIELD_FORMAT: "INVALID_FIELD_FORMAT",
|
|
23
|
+
FIELD_TOO_LONG: "FIELD_TOO_LONG",
|
|
24
|
+
FIELD_TOO_SHORT: "FIELD_TOO_SHORT",
|
|
25
|
+
// Resource
|
|
26
|
+
NOT_FOUND: "NOT_FOUND",
|
|
27
|
+
RESOURCE_EXISTS: "RESOURCE_EXISTS",
|
|
28
|
+
RESOURCE_LOCKED: "RESOURCE_LOCKED",
|
|
29
|
+
RESOURCE_EXPIRED: "RESOURCE_EXPIRED",
|
|
30
|
+
// Business Rules
|
|
31
|
+
BUSINESS_RULE_VIOLATION: "BUSINESS_RULE_VIOLATION",
|
|
32
|
+
INSUFFICIENT_FUNDS: "INSUFFICIENT_FUNDS",
|
|
33
|
+
QUOTA_EXCEEDED: "QUOTA_EXCEEDED",
|
|
34
|
+
OPERATION_NOT_ALLOWED: "OPERATION_NOT_ALLOWED",
|
|
35
|
+
// Subscription
|
|
36
|
+
SUBSCRIPTION_REQUIRED: "SUBSCRIPTION_REQUIRED",
|
|
37
|
+
FEATURE_NOT_AVAILABLE: "FEATURE_NOT_AVAILABLE",
|
|
38
|
+
// Rate Limiting
|
|
39
|
+
RATE_LIMIT_EXCEEDED: "RATE_LIMIT_EXCEEDED",
|
|
40
|
+
TOO_MANY_REQUESTS: "TOO_MANY_REQUESTS",
|
|
41
|
+
API_QUOTA_EXCEEDED: "API_QUOTA_EXCEEDED",
|
|
42
|
+
// Tenant & Partnership
|
|
43
|
+
TENANT_NOT_FOUND: "TENANT_NOT_FOUND",
|
|
44
|
+
PARTNERSHIP_NOT_FOUND: "PARTNERSHIP_NOT_FOUND",
|
|
45
|
+
PARTNERSHIP_INACTIVE: "PARTNERSHIP_INACTIVE",
|
|
46
|
+
TENANT_SUSPENDED: "TENANT_SUSPENDED",
|
|
47
|
+
PARTNERSHIP_TIER_LIMIT_REACHED: "PARTNERSHIP_TIER_LIMIT_REACHED",
|
|
48
|
+
// Pass & Template
|
|
49
|
+
TEMPLATE_NOT_FOUND: "TEMPLATE_NOT_FOUND",
|
|
50
|
+
PASS_NOT_FOUND: "PASS_NOT_FOUND",
|
|
51
|
+
PASS_EXPIRED: "PASS_EXPIRED",
|
|
52
|
+
PASS_ALREADY_USED: "PASS_ALREADY_USED",
|
|
53
|
+
INVALID_PASS_FORMAT: "INVALID_PASS_FORMAT",
|
|
54
|
+
TEMPLATE_INACTIVE: "TEMPLATE_INACTIVE",
|
|
55
|
+
// External Services
|
|
56
|
+
EXTERNAL_SERVICE_ERROR: "EXTERNAL_SERVICE_ERROR",
|
|
57
|
+
PAYMENT_SERVICE_ERROR: "PAYMENT_SERVICE_ERROR",
|
|
58
|
+
EMAIL_SERVICE_ERROR: "EMAIL_SERVICE_ERROR",
|
|
59
|
+
SMS_SERVICE_ERROR: "SMS_SERVICE_ERROR",
|
|
60
|
+
APPLE_WALLET_ERROR: "APPLE_WALLET_ERROR",
|
|
61
|
+
GOOGLE_WALLET_ERROR: "GOOGLE_WALLET_ERROR"
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
// src/errors.ts
|
|
65
|
+
var LivepassesError = class extends Error {
|
|
66
|
+
status;
|
|
67
|
+
code;
|
|
68
|
+
details;
|
|
69
|
+
constructor(message, status, code, details) {
|
|
70
|
+
super(message);
|
|
71
|
+
this.name = "LivepassesError";
|
|
72
|
+
this.status = status;
|
|
73
|
+
this.code = code;
|
|
74
|
+
this.details = details;
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
var AuthenticationError = class extends LivepassesError {
|
|
78
|
+
constructor(message, code, details) {
|
|
79
|
+
super(message, 401, code, details);
|
|
80
|
+
this.name = "AuthenticationError";
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
var ValidationError = class extends LivepassesError {
|
|
84
|
+
constructor(message, code, details) {
|
|
85
|
+
super(message, 400, code, details);
|
|
86
|
+
this.name = "ValidationError";
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
var ForbiddenError = class extends LivepassesError {
|
|
90
|
+
constructor(message, code, details) {
|
|
91
|
+
super(message, 403, code, details);
|
|
92
|
+
this.name = "ForbiddenError";
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
var NotFoundError = class extends LivepassesError {
|
|
96
|
+
constructor(message, code, details) {
|
|
97
|
+
super(message, 404, code, details);
|
|
98
|
+
this.name = "NotFoundError";
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
var RateLimitError = class extends LivepassesError {
|
|
102
|
+
/** Seconds to wait before retrying, from Retry-After header */
|
|
103
|
+
retryAfter;
|
|
104
|
+
constructor(message, code, retryAfter, details) {
|
|
105
|
+
super(message, 429, code, details);
|
|
106
|
+
this.name = "RateLimitError";
|
|
107
|
+
this.retryAfter = retryAfter;
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
var QuotaExceededError = class extends LivepassesError {
|
|
111
|
+
constructor(message, code, details) {
|
|
112
|
+
super(message, 403, code, details);
|
|
113
|
+
this.name = "QuotaExceededError";
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
var BusinessRuleError = class extends LivepassesError {
|
|
117
|
+
constructor(message, code, details) {
|
|
118
|
+
super(message, 422, code, details);
|
|
119
|
+
this.name = "BusinessRuleError";
|
|
120
|
+
}
|
|
121
|
+
};
|
|
122
|
+
var AUTH_CODES = /* @__PURE__ */ new Set([
|
|
123
|
+
ApiErrorCodes.UNAUTHORIZED,
|
|
124
|
+
ApiErrorCodes.INVALID_API_KEY,
|
|
125
|
+
ApiErrorCodes.API_KEY_EXPIRED,
|
|
126
|
+
ApiErrorCodes.API_KEY_REVOKED
|
|
127
|
+
]);
|
|
128
|
+
var FORBIDDEN_CODES = /* @__PURE__ */ new Set([
|
|
129
|
+
ApiErrorCodes.FORBIDDEN,
|
|
130
|
+
ApiErrorCodes.INSUFFICIENT_PERMISSIONS
|
|
131
|
+
]);
|
|
132
|
+
var VALIDATION_CODES = /* @__PURE__ */ new Set([
|
|
133
|
+
ApiErrorCodes.VALIDATION_ERROR,
|
|
134
|
+
ApiErrorCodes.REQUIRED_FIELD_MISSING,
|
|
135
|
+
ApiErrorCodes.INVALID_FIELD_VALUE,
|
|
136
|
+
ApiErrorCodes.INVALID_FIELD_FORMAT,
|
|
137
|
+
ApiErrorCodes.FIELD_TOO_LONG,
|
|
138
|
+
ApiErrorCodes.FIELD_TOO_SHORT
|
|
139
|
+
]);
|
|
140
|
+
var NOT_FOUND_CODES = /* @__PURE__ */ new Set([
|
|
141
|
+
ApiErrorCodes.NOT_FOUND,
|
|
142
|
+
ApiErrorCodes.PASS_NOT_FOUND,
|
|
143
|
+
ApiErrorCodes.TEMPLATE_NOT_FOUND,
|
|
144
|
+
ApiErrorCodes.TENANT_NOT_FOUND,
|
|
145
|
+
ApiErrorCodes.PARTNERSHIP_NOT_FOUND
|
|
146
|
+
]);
|
|
147
|
+
var RATE_LIMIT_CODES = /* @__PURE__ */ new Set([
|
|
148
|
+
ApiErrorCodes.RATE_LIMIT_EXCEEDED,
|
|
149
|
+
ApiErrorCodes.TOO_MANY_REQUESTS
|
|
150
|
+
]);
|
|
151
|
+
var QUOTA_CODES = /* @__PURE__ */ new Set([
|
|
152
|
+
ApiErrorCodes.QUOTA_EXCEEDED,
|
|
153
|
+
ApiErrorCodes.API_QUOTA_EXCEEDED,
|
|
154
|
+
ApiErrorCodes.SUBSCRIPTION_REQUIRED,
|
|
155
|
+
ApiErrorCodes.FEATURE_NOT_AVAILABLE
|
|
156
|
+
]);
|
|
157
|
+
var BUSINESS_RULE_CODES = /* @__PURE__ */ new Set([
|
|
158
|
+
ApiErrorCodes.BUSINESS_RULE_VIOLATION,
|
|
159
|
+
ApiErrorCodes.OPERATION_NOT_ALLOWED,
|
|
160
|
+
ApiErrorCodes.PASS_EXPIRED,
|
|
161
|
+
ApiErrorCodes.PASS_ALREADY_USED,
|
|
162
|
+
ApiErrorCodes.TEMPLATE_INACTIVE,
|
|
163
|
+
ApiErrorCodes.RESOURCE_LOCKED,
|
|
164
|
+
ApiErrorCodes.RESOURCE_EXPIRED
|
|
165
|
+
]);
|
|
166
|
+
function createTypedError(message, status, code, details, retryAfter) {
|
|
167
|
+
if (AUTH_CODES.has(code)) return new AuthenticationError(message, code, details);
|
|
168
|
+
if (FORBIDDEN_CODES.has(code)) return new ForbiddenError(message, code, details);
|
|
169
|
+
if (VALIDATION_CODES.has(code)) return new ValidationError(message, code, details);
|
|
170
|
+
if (NOT_FOUND_CODES.has(code)) return new NotFoundError(message, code, details);
|
|
171
|
+
if (RATE_LIMIT_CODES.has(code)) return new RateLimitError(message, code, retryAfter, details);
|
|
172
|
+
if (QUOTA_CODES.has(code)) return new QuotaExceededError(message, code, details);
|
|
173
|
+
if (BUSINESS_RULE_CODES.has(code)) return new BusinessRuleError(message, code, details);
|
|
174
|
+
if (status === 401) return new AuthenticationError(message, code, details);
|
|
175
|
+
if (status === 403) return new ForbiddenError(message, code, details);
|
|
176
|
+
if (status === 404) return new NotFoundError(message, code, details);
|
|
177
|
+
if (status === 429) return new RateLimitError(message, code, retryAfter, details);
|
|
178
|
+
return new LivepassesError(message, status, code, details);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// src/http.ts
|
|
182
|
+
var HttpClient = class {
|
|
183
|
+
config;
|
|
184
|
+
constructor(config) {
|
|
185
|
+
this.config = config;
|
|
186
|
+
}
|
|
187
|
+
async get(path, params) {
|
|
188
|
+
return this.request("GET", path, { params });
|
|
189
|
+
}
|
|
190
|
+
async post(path, body) {
|
|
191
|
+
return this.request("POST", path, { body });
|
|
192
|
+
}
|
|
193
|
+
async put(path, body) {
|
|
194
|
+
return this.request("PUT", path, { body });
|
|
195
|
+
}
|
|
196
|
+
async delete(path) {
|
|
197
|
+
return this.request("DELETE", path);
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Like get() but returns the full paginated response instead of unwrapping.
|
|
201
|
+
*/
|
|
202
|
+
async getPaged(path, params) {
|
|
203
|
+
return this.requestPaged("GET", path, { params });
|
|
204
|
+
}
|
|
205
|
+
async request(method, path, options) {
|
|
206
|
+
const response = await this.fetchWithRetry(method, path, options);
|
|
207
|
+
const json = await response.json();
|
|
208
|
+
if (!json.success) {
|
|
209
|
+
const err = json.error;
|
|
210
|
+
throw createTypedError(
|
|
211
|
+
err?.message ?? `API request failed with status ${response.status}`,
|
|
212
|
+
response.status,
|
|
213
|
+
err?.code ?? "GENERAL_ERROR",
|
|
214
|
+
err?.details,
|
|
215
|
+
parseRetryAfter(response)
|
|
216
|
+
);
|
|
217
|
+
}
|
|
218
|
+
return json.data;
|
|
219
|
+
}
|
|
220
|
+
async requestPaged(method, path, options) {
|
|
221
|
+
const response = await this.fetchWithRetry(method, path, options);
|
|
222
|
+
const json = await response.json();
|
|
223
|
+
if (!json.success) {
|
|
224
|
+
const err = json.error;
|
|
225
|
+
throw createTypedError(
|
|
226
|
+
err?.message ?? `API request failed with status ${response.status}`,
|
|
227
|
+
response.status,
|
|
228
|
+
err?.code ?? "GENERAL_ERROR",
|
|
229
|
+
err?.details,
|
|
230
|
+
parseRetryAfter(response)
|
|
231
|
+
);
|
|
232
|
+
}
|
|
233
|
+
return json;
|
|
234
|
+
}
|
|
235
|
+
async fetchWithRetry(method, path, options) {
|
|
236
|
+
const url = this.buildUrl(path, options?.params);
|
|
237
|
+
const headers = {
|
|
238
|
+
"X-API-Key": this.config.apiKey,
|
|
239
|
+
"Accept": "application/json"
|
|
240
|
+
};
|
|
241
|
+
if (options?.body !== void 0) {
|
|
242
|
+
headers["Content-Type"] = "application/json";
|
|
243
|
+
}
|
|
244
|
+
let lastError;
|
|
245
|
+
const maxAttempts = this.config.maxRetries + 1;
|
|
246
|
+
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
247
|
+
const controller = new AbortController();
|
|
248
|
+
const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);
|
|
249
|
+
try {
|
|
250
|
+
const response = await fetch(url, {
|
|
251
|
+
method,
|
|
252
|
+
headers,
|
|
253
|
+
body: options?.body !== void 0 ? JSON.stringify(options.body) : void 0,
|
|
254
|
+
signal: options?.signal ?? controller.signal
|
|
255
|
+
});
|
|
256
|
+
clearTimeout(timeoutId);
|
|
257
|
+
if (response.status === 429 && attempt < maxAttempts) {
|
|
258
|
+
const retryAfter = parseRetryAfter(response);
|
|
259
|
+
const delay = retryAfter ? retryAfter * 1e3 : getBackoffDelay(attempt);
|
|
260
|
+
await sleep(delay);
|
|
261
|
+
continue;
|
|
262
|
+
}
|
|
263
|
+
if (response.status >= 500 && attempt < Math.min(maxAttempts, 3)) {
|
|
264
|
+
await sleep(getBackoffDelay(attempt));
|
|
265
|
+
continue;
|
|
266
|
+
}
|
|
267
|
+
return response;
|
|
268
|
+
} catch (err) {
|
|
269
|
+
clearTimeout(timeoutId);
|
|
270
|
+
lastError = err;
|
|
271
|
+
if (lastError.name === "AbortError") {
|
|
272
|
+
throw new LivepassesError(
|
|
273
|
+
`Request timed out after ${this.config.timeout}ms`,
|
|
274
|
+
0,
|
|
275
|
+
"TIMEOUT"
|
|
276
|
+
);
|
|
277
|
+
}
|
|
278
|
+
if (attempt < maxAttempts) {
|
|
279
|
+
await sleep(getBackoffDelay(attempt));
|
|
280
|
+
continue;
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
throw new LivepassesError(
|
|
285
|
+
lastError?.message ?? "Request failed after retries",
|
|
286
|
+
0,
|
|
287
|
+
"NETWORK_ERROR"
|
|
288
|
+
);
|
|
289
|
+
}
|
|
290
|
+
buildUrl(path, params) {
|
|
291
|
+
const base = this.config.baseUrl.replace(/\/+$/, "");
|
|
292
|
+
const cleanPath = path.startsWith("/") ? path : `/${path}`;
|
|
293
|
+
const url = new URL(`${base}${cleanPath}`);
|
|
294
|
+
if (params) {
|
|
295
|
+
for (const [key, value] of Object.entries(params)) {
|
|
296
|
+
if (value !== void 0 && value !== null) {
|
|
297
|
+
url.searchParams.set(key, String(value));
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
return url.toString();
|
|
302
|
+
}
|
|
303
|
+
};
|
|
304
|
+
function parseRetryAfter(response) {
|
|
305
|
+
const header = response.headers.get("Retry-After");
|
|
306
|
+
if (!header) return void 0;
|
|
307
|
+
const seconds = parseInt(header, 10);
|
|
308
|
+
return isNaN(seconds) ? void 0 : seconds;
|
|
309
|
+
}
|
|
310
|
+
function getBackoffDelay(attempt) {
|
|
311
|
+
const base = Math.min(1e3 * Math.pow(2, attempt - 1), 3e4);
|
|
312
|
+
const jitter = Math.random() * 500;
|
|
313
|
+
return base + jitter;
|
|
314
|
+
}
|
|
315
|
+
function sleep(ms) {
|
|
316
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
// src/utils/polling.ts
|
|
320
|
+
async function pollUntilComplete(fn, isComplete, options) {
|
|
321
|
+
const interval = options?.interval ?? 2e3;
|
|
322
|
+
const maxAttempts = options?.maxAttempts ?? 150;
|
|
323
|
+
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
324
|
+
const result = await fn();
|
|
325
|
+
options?.onProgress?.(result);
|
|
326
|
+
if (isComplete(result)) {
|
|
327
|
+
return result;
|
|
328
|
+
}
|
|
329
|
+
if (attempt < maxAttempts) {
|
|
330
|
+
await new Promise((resolve) => setTimeout(resolve, interval));
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
const finalResult = await fn();
|
|
334
|
+
options?.onProgress?.(finalResult);
|
|
335
|
+
return finalResult;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
// src/utils/pagination.ts
|
|
339
|
+
async function* autoPaginate(fn) {
|
|
340
|
+
let page = 1;
|
|
341
|
+
while (true) {
|
|
342
|
+
const response = await fn(page);
|
|
343
|
+
for (const item of response.items) {
|
|
344
|
+
yield item;
|
|
345
|
+
}
|
|
346
|
+
if (page >= response.pagination.totalPages || response.items.length === 0) {
|
|
347
|
+
break;
|
|
348
|
+
}
|
|
349
|
+
page++;
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
// src/resources/passes.ts
|
|
354
|
+
var PassesResource = class {
|
|
355
|
+
constructor(http) {
|
|
356
|
+
this.http = http;
|
|
357
|
+
}
|
|
358
|
+
/**
|
|
359
|
+
* Generate passes for one or more recipients.
|
|
360
|
+
* For a single recipient, the pass is returned synchronously.
|
|
361
|
+
* For multiple recipients, returns immediately with a batchId — poll with `getBatchStatus()`.
|
|
362
|
+
*
|
|
363
|
+
* @see generateAndWait for an auto-polling helper
|
|
364
|
+
*/
|
|
365
|
+
async generate(params) {
|
|
366
|
+
return this.http.post("/api/passes/generate", params);
|
|
367
|
+
}
|
|
368
|
+
/**
|
|
369
|
+
* Generate passes and automatically poll until the batch is complete.
|
|
370
|
+
* This is the recommended method for most use cases.
|
|
371
|
+
*
|
|
372
|
+
* For sync generation (1 recipient), returns immediately.
|
|
373
|
+
* For async batches (>1 recipient), polls `getBatchStatus()` until done.
|
|
374
|
+
*/
|
|
375
|
+
async generateAndWait(params, options) {
|
|
376
|
+
const result = await this.generate(params);
|
|
377
|
+
if (!result.isAsyncProcessing) {
|
|
378
|
+
return result;
|
|
379
|
+
}
|
|
380
|
+
const batchId = result.batchId;
|
|
381
|
+
const batchStatus = await pollUntilComplete(
|
|
382
|
+
() => this.getBatchStatus(batchId),
|
|
383
|
+
(status) => status.isCompleted,
|
|
384
|
+
{
|
|
385
|
+
interval: options?.pollInterval ?? 2e3,
|
|
386
|
+
maxAttempts: options?.maxAttempts ?? 150,
|
|
387
|
+
onProgress: options?.onProgress
|
|
388
|
+
}
|
|
389
|
+
);
|
|
390
|
+
return {
|
|
391
|
+
...result,
|
|
392
|
+
passes: (batchStatus.generatedPasses ?? []).map((p) => ({
|
|
393
|
+
id: p.id,
|
|
394
|
+
customerEmail: p.holderEmail,
|
|
395
|
+
confirmationCode: void 0,
|
|
396
|
+
platforms: {
|
|
397
|
+
apple: { available: p.hasApplePass, features: [] },
|
|
398
|
+
google: { available: p.hasGooglePass, features: [] }
|
|
399
|
+
},
|
|
400
|
+
businessData: {},
|
|
401
|
+
qrCode: void 0,
|
|
402
|
+
status: p.status,
|
|
403
|
+
analytics: void 0
|
|
404
|
+
}))
|
|
405
|
+
};
|
|
406
|
+
}
|
|
407
|
+
/**
|
|
408
|
+
* List passes (paginated).
|
|
409
|
+
*/
|
|
410
|
+
async list(params) {
|
|
411
|
+
return this.http.getPaged("/api/passes", params);
|
|
412
|
+
}
|
|
413
|
+
/**
|
|
414
|
+
* Auto-paginate through all passes matching the given filters.
|
|
415
|
+
*
|
|
416
|
+
* @example
|
|
417
|
+
* ```ts
|
|
418
|
+
* for await (const pass of livepasses.passes.listAutoPaginate({ templateId: '...' })) {
|
|
419
|
+
* console.log(pass.id);
|
|
420
|
+
* }
|
|
421
|
+
* ```
|
|
422
|
+
*/
|
|
423
|
+
listAutoPaginate(params) {
|
|
424
|
+
return autoPaginate(
|
|
425
|
+
(page) => this.list({ ...params, page })
|
|
426
|
+
);
|
|
427
|
+
}
|
|
428
|
+
/**
|
|
429
|
+
* Look up a pass by ID or pass number.
|
|
430
|
+
*/
|
|
431
|
+
async lookup(params) {
|
|
432
|
+
return this.http.get("/api/passes/lookup", params);
|
|
433
|
+
}
|
|
434
|
+
/**
|
|
435
|
+
* Validate a pass before redemption.
|
|
436
|
+
*/
|
|
437
|
+
async validate(passId) {
|
|
438
|
+
return this.http.get(`/api/passes/${passId}/validate`);
|
|
439
|
+
}
|
|
440
|
+
/**
|
|
441
|
+
* Update a pass's business data.
|
|
442
|
+
*/
|
|
443
|
+
async update(passId, params) {
|
|
444
|
+
await this.http.put(`/api/passes/${passId}`, params);
|
|
445
|
+
}
|
|
446
|
+
/**
|
|
447
|
+
* Bulk update multiple passes.
|
|
448
|
+
*/
|
|
449
|
+
async bulkUpdate(params) {
|
|
450
|
+
await this.http.post("/api/passes/bulk-update", params);
|
|
451
|
+
}
|
|
452
|
+
/**
|
|
453
|
+
* Redeem a pass (generic redemption).
|
|
454
|
+
*/
|
|
455
|
+
async redeem(passId, params) {
|
|
456
|
+
return this.http.post(`/api/passes/${passId}/redeem`, params);
|
|
457
|
+
}
|
|
458
|
+
/**
|
|
459
|
+
* Check in an event pass.
|
|
460
|
+
*/
|
|
461
|
+
async checkIn(passId, params) {
|
|
462
|
+
return this.http.post(`/api/passes/${passId}/check-in`, params);
|
|
463
|
+
}
|
|
464
|
+
/**
|
|
465
|
+
* Redeem a coupon pass.
|
|
466
|
+
*/
|
|
467
|
+
async redeemCoupon(passId, params) {
|
|
468
|
+
return this.http.post(`/api/passes/${passId}/redeem-coupon`, params);
|
|
469
|
+
}
|
|
470
|
+
/**
|
|
471
|
+
* Earn or spend loyalty points.
|
|
472
|
+
*/
|
|
473
|
+
async loyaltyTransact(passId, params) {
|
|
474
|
+
return this.http.post(`/api/passes/${passId}/loyalty/transact`, params);
|
|
475
|
+
}
|
|
476
|
+
/**
|
|
477
|
+
* Get the status of a batch pass generation operation.
|
|
478
|
+
*/
|
|
479
|
+
async getBatchStatus(batchId) {
|
|
480
|
+
return this.http.get(`/api/passes/batch/${batchId}/status`);
|
|
481
|
+
}
|
|
482
|
+
};
|
|
483
|
+
|
|
484
|
+
// src/resources/templates.ts
|
|
485
|
+
var TemplatesResource = class {
|
|
486
|
+
constructor(http) {
|
|
487
|
+
this.http = http;
|
|
488
|
+
}
|
|
489
|
+
/**
|
|
490
|
+
* List templates (paginated).
|
|
491
|
+
*/
|
|
492
|
+
async list(params) {
|
|
493
|
+
return this.http.getPaged("/api/templates", params);
|
|
494
|
+
}
|
|
495
|
+
/**
|
|
496
|
+
* Get a single template by ID.
|
|
497
|
+
*/
|
|
498
|
+
async get(templateId) {
|
|
499
|
+
return this.http.get(`/api/templates/${templateId}`);
|
|
500
|
+
}
|
|
501
|
+
/**
|
|
502
|
+
* Create a new template.
|
|
503
|
+
*/
|
|
504
|
+
async create(params) {
|
|
505
|
+
return this.http.post("/api/templates", params);
|
|
506
|
+
}
|
|
507
|
+
/**
|
|
508
|
+
* Update a template.
|
|
509
|
+
*/
|
|
510
|
+
async update(templateId, params) {
|
|
511
|
+
return this.http.put(`/api/templates/${templateId}`, params);
|
|
512
|
+
}
|
|
513
|
+
/**
|
|
514
|
+
* Activate a template for pass generation.
|
|
515
|
+
*/
|
|
516
|
+
async activate(templateId) {
|
|
517
|
+
await this.http.post(`/api/templates/${templateId}/activate`);
|
|
518
|
+
}
|
|
519
|
+
/**
|
|
520
|
+
* Deactivate a template.
|
|
521
|
+
*/
|
|
522
|
+
async deactivate(templateId) {
|
|
523
|
+
await this.http.post(`/api/templates/${templateId}/deactivate`);
|
|
524
|
+
}
|
|
525
|
+
};
|
|
526
|
+
|
|
527
|
+
// src/resources/webhooks.ts
|
|
528
|
+
var WebhooksResource = class {
|
|
529
|
+
constructor(http) {
|
|
530
|
+
this.http = http;
|
|
531
|
+
}
|
|
532
|
+
/**
|
|
533
|
+
* Create a webhook endpoint.
|
|
534
|
+
*/
|
|
535
|
+
async create(params) {
|
|
536
|
+
return this.http.post("/api/webhooks", params);
|
|
537
|
+
}
|
|
538
|
+
/**
|
|
539
|
+
* List all registered webhooks.
|
|
540
|
+
*/
|
|
541
|
+
async list() {
|
|
542
|
+
return this.http.get("/api/webhooks");
|
|
543
|
+
}
|
|
544
|
+
/**
|
|
545
|
+
* Delete a webhook by ID.
|
|
546
|
+
*/
|
|
547
|
+
async delete(webhookId) {
|
|
548
|
+
await this.http.delete(`/api/webhooks/${webhookId}`);
|
|
549
|
+
}
|
|
550
|
+
};
|
|
551
|
+
|
|
552
|
+
// src/client.ts
|
|
553
|
+
var DEFAULT_BASE_URL = "https://api.livepasses.com";
|
|
554
|
+
var DEFAULT_TIMEOUT = 3e4;
|
|
555
|
+
var DEFAULT_MAX_RETRIES = 3;
|
|
556
|
+
var Livepasses = class {
|
|
557
|
+
passes;
|
|
558
|
+
templates;
|
|
559
|
+
webhooks;
|
|
560
|
+
constructor(apiKey, options) {
|
|
561
|
+
if (!apiKey) {
|
|
562
|
+
throw new Error(
|
|
563
|
+
"An API key is required. Get yours at https://dashboard.livepasses.com/api-keys"
|
|
564
|
+
);
|
|
565
|
+
}
|
|
566
|
+
const http = new HttpClient({
|
|
567
|
+
apiKey,
|
|
568
|
+
baseUrl: options?.baseUrl ?? DEFAULT_BASE_URL,
|
|
569
|
+
timeout: options?.timeout ?? DEFAULT_TIMEOUT,
|
|
570
|
+
maxRetries: options?.maxRetries ?? DEFAULT_MAX_RETRIES
|
|
571
|
+
});
|
|
572
|
+
this.passes = new PassesResource(http);
|
|
573
|
+
this.templates = new TemplatesResource(http);
|
|
574
|
+
this.webhooks = new WebhooksResource(http);
|
|
575
|
+
}
|
|
576
|
+
};
|
|
577
|
+
|
|
578
|
+
exports.ApiErrorCodes = ApiErrorCodes;
|
|
579
|
+
exports.AuthenticationError = AuthenticationError;
|
|
580
|
+
exports.BusinessRuleError = BusinessRuleError;
|
|
581
|
+
exports.ForbiddenError = ForbiddenError;
|
|
582
|
+
exports.Livepasses = Livepasses;
|
|
583
|
+
exports.LivepassesError = LivepassesError;
|
|
584
|
+
exports.NotFoundError = NotFoundError;
|
|
585
|
+
exports.QuotaExceededError = QuotaExceededError;
|
|
586
|
+
exports.RateLimitError = RateLimitError;
|
|
587
|
+
exports.ValidationError = ValidationError;
|
|
588
|
+
exports.default = Livepasses;
|
|
589
|
+
//# sourceMappingURL=index.js.map
|
|
590
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/types/common.ts","../src/errors.ts","../src/http.ts","../src/utils/polling.ts","../src/utils/pagination.ts","../src/resources/passes.ts","../src/resources/templates.ts","../src/resources/webhooks.ts","../src/client.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Standard API response envelope.\n * All Livepasses API endpoints return this structure.\n */\nexport interface ApiResponse<T> {\n success: boolean;\n data?: T;\n error?: ApiError;\n message?: string;\n meta?: ResponseMetadata;\n}\n\n/**\n * Paginated API response envelope.\n */\nexport interface ApiPagedResponse<T> {\n success: boolean;\n items: T[];\n pagination: PaginationMetadata;\n error?: ApiError;\n message?: string;\n meta?: ResponseMetadata;\n}\n\nexport interface PaginationMetadata {\n currentPage: number;\n pageSize: number;\n totalPages: number;\n totalItems: number;\n}\n\nexport interface ResponseMetadata {\n traceId?: string;\n processingTimeMs?: number;\n timestamp?: string;\n}\n\nexport interface ApiError {\n message: string;\n code: string;\n details?: string;\n timestamp?: string;\n traceId?: string;\n}\n\n/**\n * Base parameters for paginated list queries.\n */\nexport interface PagedParams {\n page?: number;\n pageSize?: number;\n searchTerm?: string;\n sortBy?: string;\n sortDescending?: boolean;\n}\n\n/**\n * All API error codes returned by the Livepasses API.\n * Mirrors ApiErrorCodes.cs 1:1.\n */\nexport const ApiErrorCodes = {\n // General Errors\n GENERAL_ERROR: 'GENERAL_ERROR',\n INTERNAL_SERVER_ERROR: 'INTERNAL_SERVER_ERROR',\n SERVICE_UNAVAILABLE: 'SERVICE_UNAVAILABLE',\n\n // Authentication & Authorization\n UNAUTHORIZED: 'UNAUTHORIZED',\n FORBIDDEN: 'FORBIDDEN',\n INVALID_API_KEY: 'INVALID_API_KEY',\n API_KEY_EXPIRED: 'API_KEY_EXPIRED',\n API_KEY_REVOKED: 'API_KEY_REVOKED',\n INSUFFICIENT_PERMISSIONS: 'INSUFFICIENT_PERMISSIONS',\n\n // Validation\n VALIDATION_ERROR: 'VALIDATION_ERROR',\n REQUIRED_FIELD_MISSING: 'REQUIRED_FIELD_MISSING',\n INVALID_FIELD_VALUE: 'INVALID_FIELD_VALUE',\n INVALID_FIELD_FORMAT: 'INVALID_FIELD_FORMAT',\n FIELD_TOO_LONG: 'FIELD_TOO_LONG',\n FIELD_TOO_SHORT: 'FIELD_TOO_SHORT',\n\n // Resource\n NOT_FOUND: 'NOT_FOUND',\n RESOURCE_EXISTS: 'RESOURCE_EXISTS',\n RESOURCE_LOCKED: 'RESOURCE_LOCKED',\n RESOURCE_EXPIRED: 'RESOURCE_EXPIRED',\n\n // Business Rules\n BUSINESS_RULE_VIOLATION: 'BUSINESS_RULE_VIOLATION',\n INSUFFICIENT_FUNDS: 'INSUFFICIENT_FUNDS',\n QUOTA_EXCEEDED: 'QUOTA_EXCEEDED',\n OPERATION_NOT_ALLOWED: 'OPERATION_NOT_ALLOWED',\n\n // Subscription\n SUBSCRIPTION_REQUIRED: 'SUBSCRIPTION_REQUIRED',\n FEATURE_NOT_AVAILABLE: 'FEATURE_NOT_AVAILABLE',\n\n // Rate Limiting\n RATE_LIMIT_EXCEEDED: 'RATE_LIMIT_EXCEEDED',\n TOO_MANY_REQUESTS: 'TOO_MANY_REQUESTS',\n API_QUOTA_EXCEEDED: 'API_QUOTA_EXCEEDED',\n\n // Tenant & Partnership\n TENANT_NOT_FOUND: 'TENANT_NOT_FOUND',\n PARTNERSHIP_NOT_FOUND: 'PARTNERSHIP_NOT_FOUND',\n PARTNERSHIP_INACTIVE: 'PARTNERSHIP_INACTIVE',\n TENANT_SUSPENDED: 'TENANT_SUSPENDED',\n PARTNERSHIP_TIER_LIMIT_REACHED: 'PARTNERSHIP_TIER_LIMIT_REACHED',\n\n // Pass & Template\n TEMPLATE_NOT_FOUND: 'TEMPLATE_NOT_FOUND',\n PASS_NOT_FOUND: 'PASS_NOT_FOUND',\n PASS_EXPIRED: 'PASS_EXPIRED',\n PASS_ALREADY_USED: 'PASS_ALREADY_USED',\n INVALID_PASS_FORMAT: 'INVALID_PASS_FORMAT',\n TEMPLATE_INACTIVE: 'TEMPLATE_INACTIVE',\n\n // External Services\n EXTERNAL_SERVICE_ERROR: 'EXTERNAL_SERVICE_ERROR',\n PAYMENT_SERVICE_ERROR: 'PAYMENT_SERVICE_ERROR',\n EMAIL_SERVICE_ERROR: 'EMAIL_SERVICE_ERROR',\n SMS_SERVICE_ERROR: 'SMS_SERVICE_ERROR',\n APPLE_WALLET_ERROR: 'APPLE_WALLET_ERROR',\n GOOGLE_WALLET_ERROR: 'GOOGLE_WALLET_ERROR',\n} as const;\n\nexport type ApiErrorCode = (typeof ApiErrorCodes)[keyof typeof ApiErrorCodes];\n","import { ApiErrorCodes } from './types/common.js';\n\n/**\n * Base error class for all Livepasses API errors.\n * Contains the HTTP status code, API error code, and optional details.\n */\nexport class LivepassesError extends Error {\n readonly status: number;\n readonly code: string;\n readonly details?: string;\n\n constructor(message: string, status: number, code: string, details?: string) {\n super(message);\n this.name = 'LivepassesError';\n this.status = status;\n this.code = code;\n this.details = details;\n }\n}\n\n/** Thrown for 401 responses - invalid or missing API key */\nexport class AuthenticationError extends LivepassesError {\n constructor(message: string, code: string, details?: string) {\n super(message, 401, code, details);\n this.name = 'AuthenticationError';\n }\n}\n\n/** Thrown for validation errors (400) - invalid input data */\nexport class ValidationError extends LivepassesError {\n constructor(message: string, code: string, details?: string) {\n super(message, 400, code, details);\n this.name = 'ValidationError';\n }\n}\n\n/** Thrown for 403 responses - insufficient permissions */\nexport class ForbiddenError extends LivepassesError {\n constructor(message: string, code: string, details?: string) {\n super(message, 403, code, details);\n this.name = 'ForbiddenError';\n }\n}\n\n/** Thrown for 404 responses - resource not found */\nexport class NotFoundError extends LivepassesError {\n constructor(message: string, code: string, details?: string) {\n super(message, 404, code, details);\n this.name = 'NotFoundError';\n }\n}\n\n/** Thrown for 429 responses - rate limit exceeded */\nexport class RateLimitError extends LivepassesError {\n /** Seconds to wait before retrying, from Retry-After header */\n readonly retryAfter?: number;\n\n constructor(message: string, code: string, retryAfter?: number, details?: string) {\n super(message, 429, code, details);\n this.name = 'RateLimitError';\n this.retryAfter = retryAfter;\n }\n}\n\n/** Thrown when subscription quota is exceeded */\nexport class QuotaExceededError extends LivepassesError {\n constructor(message: string, code: string, details?: string) {\n super(message, 403, code, details);\n this.name = 'QuotaExceededError';\n }\n}\n\n/** Thrown for business rule violations */\nexport class BusinessRuleError extends LivepassesError {\n constructor(message: string, code: string, details?: string) {\n super(message, 422, code, details);\n this.name = 'BusinessRuleError';\n }\n}\n\n// Error codes that map to each error class\nconst AUTH_CODES: Set<string> = new Set([\n ApiErrorCodes.UNAUTHORIZED,\n ApiErrorCodes.INVALID_API_KEY,\n ApiErrorCodes.API_KEY_EXPIRED,\n ApiErrorCodes.API_KEY_REVOKED,\n]);\n\nconst FORBIDDEN_CODES: Set<string> = new Set([\n ApiErrorCodes.FORBIDDEN,\n ApiErrorCodes.INSUFFICIENT_PERMISSIONS,\n]);\n\nconst VALIDATION_CODES: Set<string> = new Set([\n ApiErrorCodes.VALIDATION_ERROR,\n ApiErrorCodes.REQUIRED_FIELD_MISSING,\n ApiErrorCodes.INVALID_FIELD_VALUE,\n ApiErrorCodes.INVALID_FIELD_FORMAT,\n ApiErrorCodes.FIELD_TOO_LONG,\n ApiErrorCodes.FIELD_TOO_SHORT,\n]);\n\nconst NOT_FOUND_CODES: Set<string> = new Set([\n ApiErrorCodes.NOT_FOUND,\n ApiErrorCodes.PASS_NOT_FOUND,\n ApiErrorCodes.TEMPLATE_NOT_FOUND,\n ApiErrorCodes.TENANT_NOT_FOUND,\n ApiErrorCodes.PARTNERSHIP_NOT_FOUND,\n]);\n\nconst RATE_LIMIT_CODES: Set<string> = new Set([\n ApiErrorCodes.RATE_LIMIT_EXCEEDED,\n ApiErrorCodes.TOO_MANY_REQUESTS,\n]);\n\nconst QUOTA_CODES: Set<string> = new Set([\n ApiErrorCodes.QUOTA_EXCEEDED,\n ApiErrorCodes.API_QUOTA_EXCEEDED,\n ApiErrorCodes.SUBSCRIPTION_REQUIRED,\n ApiErrorCodes.FEATURE_NOT_AVAILABLE,\n]);\n\nconst BUSINESS_RULE_CODES: Set<string> = new Set([\n ApiErrorCodes.BUSINESS_RULE_VIOLATION,\n ApiErrorCodes.OPERATION_NOT_ALLOWED,\n ApiErrorCodes.PASS_EXPIRED,\n ApiErrorCodes.PASS_ALREADY_USED,\n ApiErrorCodes.TEMPLATE_INACTIVE,\n ApiErrorCodes.RESOURCE_LOCKED,\n ApiErrorCodes.RESOURCE_EXPIRED,\n]);\n\n/**\n * Creates a typed error from an API error code and HTTP status.\n * @internal\n */\nexport function createTypedError(\n message: string,\n status: number,\n code: string,\n details?: string,\n retryAfter?: number,\n): LivepassesError {\n if (AUTH_CODES.has(code)) return new AuthenticationError(message, code, details);\n if (FORBIDDEN_CODES.has(code)) return new ForbiddenError(message, code, details);\n if (VALIDATION_CODES.has(code)) return new ValidationError(message, code, details);\n if (NOT_FOUND_CODES.has(code)) return new NotFoundError(message, code, details);\n if (RATE_LIMIT_CODES.has(code)) return new RateLimitError(message, code, retryAfter, details);\n if (QUOTA_CODES.has(code)) return new QuotaExceededError(message, code, details);\n if (BUSINESS_RULE_CODES.has(code)) return new BusinessRuleError(message, code, details);\n\n // Fallback: map by HTTP status\n if (status === 401) return new AuthenticationError(message, code, details);\n if (status === 403) return new ForbiddenError(message, code, details);\n if (status === 404) return new NotFoundError(message, code, details);\n if (status === 429) return new RateLimitError(message, code, retryAfter, details);\n\n return new LivepassesError(message, status, code, details);\n}\n","import type { ApiResponse, ApiPagedResponse } from './types/common.js';\nimport { LivepassesError, createTypedError } from './errors.js';\n\nexport interface HttpClientConfig {\n apiKey: string;\n baseUrl: string;\n timeout: number;\n maxRetries: number;\n}\n\ninterface RequestOptions {\n params?: Record<string, string | number | boolean | undefined>;\n body?: unknown;\n signal?: AbortSignal;\n}\n\n/**\n * Internal HTTP client that wraps native fetch with:\n * - API key injection\n * - ApiResponse<T> envelope unwrapping\n * - Typed error mapping\n * - Automatic retry with exponential backoff for 429 and 5xx\n */\nexport class HttpClient {\n private readonly config: HttpClientConfig;\n\n constructor(config: HttpClientConfig) {\n this.config = config;\n }\n\n async get<T>(path: string, params?: Record<string, string | number | boolean | undefined>): Promise<T> {\n return this.request<T>('GET', path, { params });\n }\n\n async post<T>(path: string, body?: unknown): Promise<T> {\n return this.request<T>('POST', path, { body });\n }\n\n async put<T>(path: string, body?: unknown): Promise<T> {\n return this.request<T>('PUT', path, { body });\n }\n\n async delete<T>(path: string): Promise<T> {\n return this.request<T>('DELETE', path);\n }\n\n /**\n * Like get() but returns the full paginated response instead of unwrapping.\n */\n async getPaged<T>(path: string, params?: Record<string, string | number | boolean | undefined>): Promise<ApiPagedResponse<T>> {\n return this.requestPaged<T>('GET', path, { params });\n }\n\n private async request<T>(method: string, path: string, options?: RequestOptions): Promise<T> {\n const response = await this.fetchWithRetry(method, path, options);\n const json = (await response.json()) as ApiResponse<T>;\n\n if (!json.success) {\n const err = json.error;\n throw createTypedError(\n err?.message ?? `API request failed with status ${response.status}`,\n response.status,\n err?.code ?? 'GENERAL_ERROR',\n err?.details,\n parseRetryAfter(response),\n );\n }\n\n return json.data as T;\n }\n\n private async requestPaged<T>(method: string, path: string, options?: RequestOptions): Promise<ApiPagedResponse<T>> {\n const response = await this.fetchWithRetry(method, path, options);\n const json = (await response.json()) as ApiPagedResponse<T>;\n\n if (!json.success) {\n const err = json.error;\n throw createTypedError(\n err?.message ?? `API request failed with status ${response.status}`,\n response.status,\n err?.code ?? 'GENERAL_ERROR',\n err?.details,\n parseRetryAfter(response),\n );\n }\n\n return json;\n }\n\n private async fetchWithRetry(method: string, path: string, options?: RequestOptions): Promise<Response> {\n const url = this.buildUrl(path, options?.params);\n const headers: Record<string, string> = {\n 'X-API-Key': this.config.apiKey,\n 'Accept': 'application/json',\n };\n\n if (options?.body !== undefined) {\n headers['Content-Type'] = 'application/json';\n }\n\n let lastError: Error | undefined;\n const maxAttempts = this.config.maxRetries + 1;\n\n for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);\n\n try {\n const response = await fetch(url, {\n method,\n headers,\n body: options?.body !== undefined ? JSON.stringify(options.body) : undefined,\n signal: options?.signal ?? controller.signal,\n });\n\n clearTimeout(timeoutId);\n\n // Retry on 429 (rate limit)\n if (response.status === 429 && attempt < maxAttempts) {\n const retryAfter = parseRetryAfter(response);\n const delay = retryAfter ? retryAfter * 1000 : getBackoffDelay(attempt);\n await sleep(delay);\n continue;\n }\n\n // Retry on 5xx (server error) — fewer retries\n if (response.status >= 500 && attempt < Math.min(maxAttempts, 3)) {\n await sleep(getBackoffDelay(attempt));\n continue;\n }\n\n return response;\n } catch (err) {\n clearTimeout(timeoutId);\n lastError = err as Error;\n\n // Abort errors should not be retried\n if (lastError.name === 'AbortError') {\n throw new LivepassesError(\n `Request timed out after ${this.config.timeout}ms`,\n 0,\n 'TIMEOUT',\n );\n }\n\n // Network errors: retry\n if (attempt < maxAttempts) {\n await sleep(getBackoffDelay(attempt));\n continue;\n }\n }\n }\n\n throw new LivepassesError(\n lastError?.message ?? 'Request failed after retries',\n 0,\n 'NETWORK_ERROR',\n );\n }\n\n private buildUrl(path: string, params?: Record<string, string | number | boolean | undefined>): string {\n const base = this.config.baseUrl.replace(/\\/+$/, '');\n const cleanPath = path.startsWith('/') ? path : `/${path}`;\n const url = new URL(`${base}${cleanPath}`);\n\n if (params) {\n for (const [key, value] of Object.entries(params)) {\n if (value !== undefined && value !== null) {\n url.searchParams.set(key, String(value));\n }\n }\n }\n\n return url.toString();\n }\n}\n\nfunction parseRetryAfter(response: Response): number | undefined {\n const header = response.headers.get('Retry-After');\n if (!header) return undefined;\n const seconds = parseInt(header, 10);\n return isNaN(seconds) ? undefined : seconds;\n}\n\nfunction getBackoffDelay(attempt: number): number {\n // Exponential backoff: 1s, 2s, 4s, 8s... with jitter\n const base = Math.min(1000 * Math.pow(2, attempt - 1), 30000);\n const jitter = Math.random() * 500;\n return base + jitter;\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n","/**\n * Polls a function until a condition is met.\n *\n * @param fn - Async function to call on each poll\n * @param isComplete - Predicate that returns true when polling should stop\n * @param options - Polling configuration\n * @returns The final result that satisfied isComplete\n */\nexport async function pollUntilComplete<T>(\n fn: () => Promise<T>,\n isComplete: (result: T) => boolean,\n options?: {\n /** Polling interval in ms. Default: 2000 */\n interval?: number;\n /** Maximum number of poll attempts. Default: 150 */\n maxAttempts?: number;\n /** Called on each poll with the current result */\n onProgress?: (result: T) => void;\n },\n): Promise<T> {\n const interval = options?.interval ?? 2000;\n const maxAttempts = options?.maxAttempts ?? 150;\n\n for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n const result = await fn();\n\n options?.onProgress?.(result);\n\n if (isComplete(result)) {\n return result;\n }\n\n if (attempt < maxAttempts) {\n await new Promise((resolve) => setTimeout(resolve, interval));\n }\n }\n\n // Return the last result even if not complete\n const finalResult = await fn();\n options?.onProgress?.(finalResult);\n return finalResult;\n}\n","import type { ApiPagedResponse } from '../types/common.js';\n\n/**\n * Returns an async generator that automatically paginates through all pages.\n *\n * @example\n * ```ts\n * for await (const pass of autoPaginate((page) => client.passes.list({ page }))) {\n * console.log(pass.id);\n * }\n * ```\n */\nexport async function* autoPaginate<T>(\n fn: (page: number) => Promise<ApiPagedResponse<T>>,\n): AsyncGenerator<T, void, undefined> {\n let page = 1;\n\n while (true) {\n const response = await fn(page);\n\n for (const item of response.items) {\n yield item;\n }\n\n if (page >= response.pagination.totalPages || response.items.length === 0) {\n break;\n }\n\n page++;\n }\n}\n","import type { HttpClient } from '../http.js';\nimport type { ApiPagedResponse } from '../types/common.js';\nimport type {\n GeneratePassesParams,\n PassGenerationResult,\n ListPassesParams,\n GlobalPassDto,\n LookupPassParams,\n PassLookupResult,\n PassValidationResult,\n UpdatePassParams,\n BulkUpdatePassesParams,\n RedeemPassParams,\n PassRedemptionResult,\n CheckInParams,\n RedeemCouponParams,\n LoyaltyTransactionParams,\n BatchStatusResult,\n GenerateAndWaitOptions,\n} from '../types/passes.js';\nimport { pollUntilComplete } from '../utils/polling.js';\nimport { autoPaginate } from '../utils/pagination.js';\n\nexport class PassesResource {\n constructor(private readonly http: HttpClient) {}\n\n /**\n * Generate passes for one or more recipients.\n * For a single recipient, the pass is returned synchronously.\n * For multiple recipients, returns immediately with a batchId — poll with `getBatchStatus()`.\n *\n * @see generateAndWait for an auto-polling helper\n */\n async generate(params: GeneratePassesParams): Promise<PassGenerationResult> {\n return this.http.post<PassGenerationResult>('/api/passes/generate', params);\n }\n\n /**\n * Generate passes and automatically poll until the batch is complete.\n * This is the recommended method for most use cases.\n *\n * For sync generation (1 recipient), returns immediately.\n * For async batches (>1 recipient), polls `getBatchStatus()` until done.\n */\n async generateAndWait(\n params: GeneratePassesParams,\n options?: GenerateAndWaitOptions,\n ): Promise<PassGenerationResult> {\n const result = await this.generate(params);\n\n if (!result.isAsyncProcessing) {\n return result;\n }\n\n const batchId = result.batchId;\n const batchStatus = await pollUntilComplete(\n () => this.getBatchStatus(batchId),\n (status) => status.isCompleted,\n {\n interval: options?.pollInterval ?? 2000,\n maxAttempts: options?.maxAttempts ?? 150,\n onProgress: options?.onProgress,\n },\n );\n\n // Merge batch status into the original result for a unified return\n return {\n ...result,\n passes: (batchStatus.generatedPasses ?? []).map((p) => ({\n id: p.id,\n customerEmail: p.holderEmail,\n confirmationCode: undefined,\n platforms: {\n apple: { available: p.hasApplePass, features: [] },\n google: { available: p.hasGooglePass, features: [] },\n },\n businessData: {},\n qrCode: undefined,\n status: p.status,\n analytics: undefined,\n })),\n };\n }\n\n /**\n * List passes (paginated).\n */\n async list(params?: ListPassesParams): Promise<ApiPagedResponse<GlobalPassDto>> {\n return this.http.getPaged<GlobalPassDto>('/api/passes', params as Record<string, string | number | boolean | undefined>);\n }\n\n /**\n * Auto-paginate through all passes matching the given filters.\n *\n * @example\n * ```ts\n * for await (const pass of livepasses.passes.listAutoPaginate({ templateId: '...' })) {\n * console.log(pass.id);\n * }\n * ```\n */\n listAutoPaginate(params?: Omit<ListPassesParams, 'page'>): AsyncGenerator<GlobalPassDto, void, undefined> {\n return autoPaginate((page) =>\n this.list({ ...params, page }),\n );\n }\n\n /**\n * Look up a pass by ID or pass number.\n */\n async lookup(params: LookupPassParams): Promise<PassLookupResult> {\n return this.http.get<PassLookupResult>('/api/passes/lookup', params as Record<string, string | undefined>);\n }\n\n /**\n * Validate a pass before redemption.\n */\n async validate(passId: string): Promise<PassValidationResult> {\n return this.http.get<PassValidationResult>(`/api/passes/${passId}/validate`);\n }\n\n /**\n * Update a pass's business data.\n */\n async update(passId: string, params: UpdatePassParams): Promise<void> {\n await this.http.put<unknown>(`/api/passes/${passId}`, params);\n }\n\n /**\n * Bulk update multiple passes.\n */\n async bulkUpdate(params: BulkUpdatePassesParams): Promise<void> {\n await this.http.post<unknown>('/api/passes/bulk-update', params);\n }\n\n /**\n * Redeem a pass (generic redemption).\n */\n async redeem(passId: string, params?: RedeemPassParams): Promise<PassRedemptionResult> {\n return this.http.post<PassRedemptionResult>(`/api/passes/${passId}/redeem`, params);\n }\n\n /**\n * Check in an event pass.\n */\n async checkIn(passId: string, params?: CheckInParams): Promise<PassRedemptionResult> {\n return this.http.post<PassRedemptionResult>(`/api/passes/${passId}/check-in`, params);\n }\n\n /**\n * Redeem a coupon pass.\n */\n async redeemCoupon(passId: string, params?: RedeemCouponParams): Promise<PassRedemptionResult> {\n return this.http.post<PassRedemptionResult>(`/api/passes/${passId}/redeem-coupon`, params);\n }\n\n /**\n * Earn or spend loyalty points.\n */\n async loyaltyTransact(passId: string, params: LoyaltyTransactionParams): Promise<PassRedemptionResult> {\n return this.http.post<PassRedemptionResult>(`/api/passes/${passId}/loyalty/transact`, params);\n }\n\n /**\n * Get the status of a batch pass generation operation.\n */\n async getBatchStatus(batchId: string): Promise<BatchStatusResult> {\n return this.http.get<BatchStatusResult>(`/api/passes/batch/${batchId}/status`);\n }\n}\n","import type { HttpClient } from '../http.js';\nimport type { ApiPagedResponse } from '../types/common.js';\nimport type {\n TemplateListItem,\n TemplateDetail,\n ListTemplatesParams,\n CreateTemplateParams,\n UpdateTemplateParams,\n} from '../types/templates.js';\n\nexport class TemplatesResource {\n constructor(private readonly http: HttpClient) {}\n\n /**\n * List templates (paginated).\n */\n async list(params?: ListTemplatesParams): Promise<ApiPagedResponse<TemplateListItem>> {\n return this.http.getPaged<TemplateListItem>('/api/templates', params as Record<string, string | number | boolean | undefined>);\n }\n\n /**\n * Get a single template by ID.\n */\n async get(templateId: string): Promise<TemplateDetail> {\n return this.http.get<TemplateDetail>(`/api/templates/${templateId}`);\n }\n\n /**\n * Create a new template.\n */\n async create(params: CreateTemplateParams): Promise<TemplateDetail> {\n return this.http.post<TemplateDetail>('/api/templates', params);\n }\n\n /**\n * Update a template.\n */\n async update(templateId: string, params: UpdateTemplateParams): Promise<TemplateDetail> {\n return this.http.put<TemplateDetail>(`/api/templates/${templateId}`, params);\n }\n\n /**\n * Activate a template for pass generation.\n */\n async activate(templateId: string): Promise<void> {\n await this.http.post<unknown>(`/api/templates/${templateId}/activate`);\n }\n\n /**\n * Deactivate a template.\n */\n async deactivate(templateId: string): Promise<void> {\n await this.http.post<unknown>(`/api/templates/${templateId}/deactivate`);\n }\n}\n","import type { HttpClient } from '../http.js';\nimport type { Webhook, CreateWebhookParams } from '../types/webhooks.js';\n\nexport class WebhooksResource {\n constructor(private readonly http: HttpClient) {}\n\n /**\n * Create a webhook endpoint.\n */\n async create(params: CreateWebhookParams): Promise<Webhook> {\n return this.http.post<Webhook>('/api/webhooks', params);\n }\n\n /**\n * List all registered webhooks.\n */\n async list(): Promise<Webhook[]> {\n return this.http.get<Webhook[]>('/api/webhooks');\n }\n\n /**\n * Delete a webhook by ID.\n */\n async delete(webhookId: string): Promise<void> {\n await this.http.delete<unknown>(`/api/webhooks/${webhookId}`);\n }\n}\n","import { HttpClient } from './http.js';\nimport { PassesResource } from './resources/passes.js';\nimport { TemplatesResource } from './resources/templates.js';\nimport { WebhooksResource } from './resources/webhooks.js';\n\nexport interface LivepassesOptions {\n /** API base URL. Default: https://api.livepasses.com */\n baseUrl?: string;\n /** Request timeout in milliseconds. Default: 30000 */\n timeout?: number;\n /** Maximum number of retries for failed requests. Default: 3 */\n maxRetries?: number;\n}\n\nconst DEFAULT_BASE_URL = 'https://api.livepasses.com';\nconst DEFAULT_TIMEOUT = 30_000;\nconst DEFAULT_MAX_RETRIES = 3;\n\n/**\n * Livepasses API client.\n *\n * @example\n * ```ts\n * import { Livepasses } from 'livepasses';\n *\n * const client = new Livepasses('lp_api_key_...');\n * const result = await client.passes.generate({\n * templateId: 'template-id',\n * passes: [{\n * customer: { firstName: 'Jane', lastName: 'Doe', email: 'jane@example.com' },\n * businessData: { sectionInfo: 'A', rowInfo: '12', seatNumber: '5' },\n * }],\n * });\n * ```\n */\nexport class Livepasses {\n readonly passes: PassesResource;\n readonly templates: TemplatesResource;\n readonly webhooks: WebhooksResource;\n\n constructor(apiKey: string, options?: LivepassesOptions) {\n if (!apiKey) {\n throw new Error(\n 'An API key is required. Get yours at https://dashboard.livepasses.com/api-keys',\n );\n }\n\n const http = new HttpClient({\n apiKey,\n baseUrl: options?.baseUrl ?? DEFAULT_BASE_URL,\n timeout: options?.timeout ?? DEFAULT_TIMEOUT,\n maxRetries: options?.maxRetries ?? DEFAULT_MAX_RETRIES,\n });\n\n this.passes = new PassesResource(http);\n this.templates = new TemplatesResource(http);\n this.webhooks = new WebhooksResource(http);\n }\n}\n"]}
|