equalweb-sdk 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js ADDED
@@ -0,0 +1,568 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ AuditApi: () => AuditApi,
24
+ AuthenticationError: () => AuthenticationError,
25
+ DocumentsApi: () => DocumentsApi,
26
+ DownloadsApi: () => DownloadsApi,
27
+ EqualWeb: () => EqualWeb,
28
+ EqualWebError: () => EqualWebError,
29
+ GroupsApi: () => GroupsApi,
30
+ InfoApi: () => InfoApi,
31
+ RateLimitError: () => RateLimitError,
32
+ ReportsApi: () => ReportsApi
33
+ });
34
+ module.exports = __toCommonJS(index_exports);
35
+
36
+ // src/types.ts
37
+ var EqualWebError = class extends Error {
38
+ statusCode;
39
+ response;
40
+ constructor(message, statusCode, response) {
41
+ super(message);
42
+ this.name = "EqualWebError";
43
+ this.statusCode = statusCode;
44
+ this.response = response;
45
+ }
46
+ };
47
+ var RateLimitError = class extends EqualWebError {
48
+ retryAfter;
49
+ constructor(message, retryAfter) {
50
+ super(message, 429);
51
+ this.name = "RateLimitError";
52
+ this.retryAfter = retryAfter;
53
+ }
54
+ };
55
+ var AuthenticationError = class extends EqualWebError {
56
+ constructor(message = "Invalid or missing API key") {
57
+ super(message, 401);
58
+ this.name = "AuthenticationError";
59
+ }
60
+ };
61
+
62
+ // src/client.ts
63
+ var DEFAULT_BASE_URL = "https://login.equalweb.com/api/v2";
64
+ var DEFAULT_TIMEOUT = 3e4;
65
+ var HttpClient = class {
66
+ apiKey;
67
+ baseUrl;
68
+ timeout;
69
+ constructor(config) {
70
+ if (!config.apiKey || config.apiKey.trim().length === 0) {
71
+ throw new Error("API key is required and cannot be empty");
72
+ }
73
+ if (config.timeout !== void 0 && config.timeout < 0) {
74
+ throw new Error("timeout must be a positive number");
75
+ }
76
+ if (config.baseUrl) {
77
+ try {
78
+ new URL(config.baseUrl);
79
+ } catch {
80
+ throw new Error("baseUrl must be a valid URL");
81
+ }
82
+ }
83
+ this.apiKey = config.apiKey;
84
+ this.baseUrl = config.baseUrl?.replace(/\/$/, "") ?? DEFAULT_BASE_URL;
85
+ this.timeout = config.timeout ?? DEFAULT_TIMEOUT;
86
+ }
87
+ async request(options) {
88
+ const { method, path, query, body, isFormData, responseType = "json" } = options;
89
+ const url = new URL(path, this.baseUrl + "/");
90
+ if (query) {
91
+ Object.entries(query).forEach(([key, value]) => {
92
+ if (value !== void 0) {
93
+ url.searchParams.set(key, String(value));
94
+ }
95
+ });
96
+ }
97
+ const headers = {
98
+ "x-a11y-api-key": this.apiKey
99
+ };
100
+ if (!isFormData && body) {
101
+ headers["Content-Type"] = "application/json";
102
+ }
103
+ const controller = new AbortController();
104
+ const timeoutId = setTimeout(() => controller.abort(), this.timeout);
105
+ try {
106
+ const response = await fetch(url.toString(), {
107
+ method,
108
+ headers,
109
+ body: isFormData ? body : body ? JSON.stringify(body) : void 0,
110
+ signal: controller.signal
111
+ });
112
+ clearTimeout(timeoutId);
113
+ if (!response.ok) {
114
+ await this.handleErrorResponse(response);
115
+ }
116
+ if (responseType === "blob") {
117
+ return response.blob();
118
+ }
119
+ const text = await response.text();
120
+ if (!text) {
121
+ return {};
122
+ }
123
+ try {
124
+ return JSON.parse(text);
125
+ } catch (parseError) {
126
+ const preview = text.length > 100 ? text.substring(0, 100) + "..." : text;
127
+ throw new EqualWebError(`Failed to parse JSON response: ${preview}`, 0);
128
+ }
129
+ } catch (error) {
130
+ clearTimeout(timeoutId);
131
+ if (error instanceof EqualWebError) {
132
+ throw error;
133
+ }
134
+ if (error instanceof Error) {
135
+ if (error.name === "AbortError") {
136
+ throw new EqualWebError("Request timeout", 408);
137
+ }
138
+ throw new EqualWebError(error.message, 0);
139
+ }
140
+ throw new EqualWebError("Unknown error occurred", 0);
141
+ }
142
+ }
143
+ async handleErrorResponse(response) {
144
+ let errorData;
145
+ try {
146
+ const text = await response.text();
147
+ if (text) {
148
+ errorData = JSON.parse(text);
149
+ }
150
+ } catch {
151
+ }
152
+ const message = errorData?.error ?? errorData?.message ?? response.statusText;
153
+ switch (response.status) {
154
+ case 401:
155
+ throw new AuthenticationError(message);
156
+ case 429: {
157
+ const retryAfter = response.headers.get("Retry-After");
158
+ throw new RateLimitError(
159
+ message || "Rate limit exceeded",
160
+ retryAfter ? parseInt(retryAfter, 10) : void 0
161
+ );
162
+ }
163
+ default:
164
+ throw new EqualWebError(message, response.status, errorData);
165
+ }
166
+ }
167
+ get(path, query) {
168
+ return this.request({ method: "GET", path, query });
169
+ }
170
+ post(path, body) {
171
+ return this.request({ method: "POST", path, body });
172
+ }
173
+ put(path, body, isFormData = false) {
174
+ return this.request({ method: "PUT", path, body, isFormData });
175
+ }
176
+ delete(path, body) {
177
+ return this.request({ method: "DELETE", path, body });
178
+ }
179
+ getBlob(path, query) {
180
+ return this.request({ method: "GET", path, query, responseType: "blob" });
181
+ }
182
+ postBlob(path, body) {
183
+ return this.request({ method: "POST", path, body, responseType: "blob" });
184
+ }
185
+ };
186
+
187
+ // src/api/info.ts
188
+ var InfoApi = class {
189
+ constructor(client) {
190
+ this.client = client;
191
+ }
192
+ /**
193
+ * Get the current credit balance for your account
194
+ * @returns The current credit balance
195
+ */
196
+ async getBalance() {
197
+ const response = await this.client.get("info/balance");
198
+ return response.results;
199
+ }
200
+ };
201
+
202
+ // src/api/documents.ts
203
+ var DocumentsApi = class {
204
+ constructor(client) {
205
+ this.client = client;
206
+ }
207
+ /**
208
+ * Get all documents
209
+ * @param params - Optional filters for groupID, archived status, and document type
210
+ * @returns Array of documents
211
+ */
212
+ async getAll(params) {
213
+ return this.client.get("docs", {
214
+ groupID: params?.groupID,
215
+ archived: params?.archived,
216
+ type: params?.type
217
+ });
218
+ }
219
+ /**
220
+ * Get the status of a specific document
221
+ * @param reportID - The report ID of the document
222
+ * @returns The document status
223
+ */
224
+ async getStatus(reportID) {
225
+ if (!reportID || reportID.trim().length === 0) {
226
+ throw new Error("reportID cannot be empty");
227
+ }
228
+ const response = await this.client.get(`docs/status/${reportID}`);
229
+ return response.status;
230
+ }
231
+ /**
232
+ * Upload a document for processing
233
+ * Supported formats: PDF, XLSX, DOCX, PPTX
234
+ * @param file - The file to upload (File, Blob, ArrayBuffer, or Uint8Array)
235
+ * @param filename - Optional filename (required if file is an ArrayBuffer or Uint8Array)
236
+ * @returns Upload response with document ID and metadata
237
+ */
238
+ async upload(file, filename) {
239
+ if (!file) {
240
+ throw new Error("file cannot be null or undefined");
241
+ }
242
+ let sizeInBytes = 0;
243
+ if (file instanceof ArrayBuffer) {
244
+ sizeInBytes = file.byteLength;
245
+ } else if (file instanceof Uint8Array) {
246
+ sizeInBytes = file.byteLength;
247
+ } else if (file instanceof Blob) {
248
+ sizeInBytes = file.size;
249
+ }
250
+ if (sizeInBytes === 0) {
251
+ throw new Error("file is empty");
252
+ }
253
+ const formData = new FormData();
254
+ if (file instanceof ArrayBuffer || file instanceof Uint8Array) {
255
+ const blob = new Blob([file]);
256
+ formData.append("file", blob, filename ?? "document.pdf");
257
+ } else if (file instanceof Blob) {
258
+ const defaultFilename = file?.name ?? "document.pdf";
259
+ formData.append("file", file, filename ?? defaultFilename);
260
+ } else {
261
+ formData.append("file", file);
262
+ }
263
+ return this.client.put("docs/upload", formData, true);
264
+ }
265
+ /**
266
+ * Delete multiple documents
267
+ * @param files - Array of document IDs to delete
268
+ * @returns Results indicating success/failure for each document
269
+ */
270
+ async delete(files) {
271
+ if (!files || files.length === 0) {
272
+ throw new Error("files array cannot be empty");
273
+ }
274
+ const params = { files };
275
+ return this.client.delete("docs", params);
276
+ }
277
+ /**
278
+ * Archive documents
279
+ * @param files - Array of document IDs to archive
280
+ * @returns Result of the operation
281
+ */
282
+ async archive(files) {
283
+ if (!files || files.length === 0) {
284
+ throw new Error("files array cannot be empty");
285
+ }
286
+ const params = { files, archive: true };
287
+ return this.client.post("docs/archive", params);
288
+ }
289
+ /**
290
+ * Restore archived documents
291
+ * @param files - Array of document IDs to restore
292
+ * @returns Result of the operation
293
+ */
294
+ async restore(files) {
295
+ if (!files || files.length === 0) {
296
+ throw new Error("files array cannot be empty");
297
+ }
298
+ const params = { files, archive: false };
299
+ return this.client.post("docs/archive", params);
300
+ }
301
+ };
302
+
303
+ // src/api/groups.ts
304
+ var GroupsApi = class {
305
+ constructor(client) {
306
+ this.client = client;
307
+ }
308
+ /**
309
+ * Get all document groups
310
+ * @returns Array of document groups
311
+ */
312
+ async getAll() {
313
+ return this.client.get("docs/groups");
314
+ }
315
+ /**
316
+ * Add documents to a new group
317
+ * @param files - Array of document IDs to group
318
+ * @param groupName - Name of the new group to create
319
+ * @returns Result of the operation
320
+ */
321
+ async createGroup(files, groupName) {
322
+ if (!files || files.length === 0) {
323
+ throw new Error("files array cannot be empty");
324
+ }
325
+ if (!groupName || groupName.trim().length === 0) {
326
+ throw new Error("groupName cannot be empty");
327
+ }
328
+ const params = { files, newGroup: groupName };
329
+ return this.client.post("docs/group", params);
330
+ }
331
+ /**
332
+ * Add documents to an existing group
333
+ * @param files - Array of document IDs to group
334
+ * @param groupID - ID of the existing group
335
+ * @returns Result of the operation
336
+ */
337
+ async addToGroup(files, groupID) {
338
+ if (!files || files.length === 0) {
339
+ throw new Error("files array cannot be empty");
340
+ }
341
+ if (!groupID || groupID.trim().length === 0) {
342
+ throw new Error("groupID cannot be empty");
343
+ }
344
+ const params = { files, selectedGroup: groupID };
345
+ return this.client.post("docs/group", params);
346
+ }
347
+ /**
348
+ * Rename a document group
349
+ * @param groupID - ID of the group to rename
350
+ * @param groupName - New name for the group
351
+ * @returns Result of the operation
352
+ */
353
+ async rename(groupID, groupName) {
354
+ if (!groupID || groupID.trim().length === 0) {
355
+ throw new Error("groupID cannot be empty");
356
+ }
357
+ if (!groupName || groupName.trim().length === 0) {
358
+ throw new Error("groupName cannot be empty");
359
+ }
360
+ const params = { groupID, groupName };
361
+ return this.client.post("group-name", params);
362
+ }
363
+ };
364
+
365
+ // src/api/audit.ts
366
+ var AuditApi = class {
367
+ constructor(client) {
368
+ this.client = client;
369
+ }
370
+ /**
371
+ * Start a full audit on documents
372
+ * This performs accessibility remediation and generates detailed reports
373
+ * @param files - Array of document IDs to audit
374
+ * @returns Result of the operation (202 Accepted - processing is async)
375
+ */
376
+ async audit(files) {
377
+ if (!files || files.length === 0) {
378
+ throw new Error("files array cannot be empty");
379
+ }
380
+ const params = { files, type: "audit" };
381
+ return this.client.post("docs/audit", params);
382
+ }
383
+ /**
384
+ * Perform a quick check on documents without full remediation
385
+ * @param files - Array of document IDs to check
386
+ * @returns Result of the operation (202 Accepted - processing is async)
387
+ */
388
+ async check(files) {
389
+ if (!files || files.length === 0) {
390
+ throw new Error("files array cannot be empty");
391
+ }
392
+ const params = { files, type: "check" };
393
+ return this.client.post("docs/audit", params);
394
+ }
395
+ /**
396
+ * Start an audit with custom type
397
+ * @param files - Array of document IDs to process
398
+ * @param type - Type of audit: "audit" for full audit, "check" for quick check
399
+ * @returns Result of the operation (202 Accepted - processing is async)
400
+ */
401
+ async process(files, type) {
402
+ if (!files || files.length === 0) {
403
+ throw new Error("files array cannot be empty");
404
+ }
405
+ if (!type || type.trim().length === 0) {
406
+ throw new Error("type cannot be empty");
407
+ }
408
+ const params = { files, type };
409
+ return this.client.post("docs/audit", params);
410
+ }
411
+ };
412
+
413
+ // src/api/reports.ts
414
+ var REPORTS_BASE_URL = "https://login.equalweb.com/reports/pdf";
415
+ var ReportsApi = class {
416
+ constructor(client) {
417
+ this.client = client;
418
+ }
419
+ /**
420
+ * Get the JSON report for a document
421
+ * @param reportID - The report ID
422
+ * @param type - Which report to retrieve: "audited", "original", or "both"
423
+ * @returns The report data
424
+ */
425
+ async get(reportID, type = "audited") {
426
+ const params = { type };
427
+ return this.client.get(`docs/report/${reportID}`, {
428
+ type: params.type
429
+ });
430
+ }
431
+ /**
432
+ * Get the audited report for a document
433
+ * @param reportID - The report ID
434
+ * @returns The audited report data
435
+ */
436
+ async getAudited(reportID) {
437
+ return this.get(reportID, "audited");
438
+ }
439
+ /**
440
+ * Get the original report for a document
441
+ * @param reportID - The report ID
442
+ * @returns The original report data
443
+ */
444
+ async getOriginal(reportID) {
445
+ return this.get(reportID, "original");
446
+ }
447
+ /**
448
+ * Get both audited and original reports for a document
449
+ * @param reportID - The report ID
450
+ * @returns Both report data
451
+ */
452
+ async getBoth(reportID) {
453
+ return this.get(reportID, "both");
454
+ }
455
+ /**
456
+ * Get the URL to view the report in a browser
457
+ * Note: This URL does not require authentication
458
+ * @param reportID - The report ID
459
+ * @returns The browser-viewable URL
460
+ */
461
+ getBrowserUrl(reportID) {
462
+ return `${REPORTS_BASE_URL}/${reportID}`;
463
+ }
464
+ };
465
+
466
+ // src/api/downloads.ts
467
+ var DownloadsApi = class {
468
+ constructor(client) {
469
+ this.client = client;
470
+ }
471
+ /**
472
+ * Download a single document file
473
+ * @param reportID - The report ID of the document
474
+ * @param options - Download options (original file, file type)
475
+ * @returns The file as a Blob
476
+ */
477
+ async file(reportID, options) {
478
+ return this.client.getBlob(`docs/download/file/${reportID}`, {
479
+ original: options?.original,
480
+ type: options?.type
481
+ });
482
+ }
483
+ /**
484
+ * Download the audited/processed version of a document
485
+ * @param reportID - The report ID of the document
486
+ * @param type - File type to download (pdf or xlsx)
487
+ * @returns The processed file as a Blob
488
+ */
489
+ async audited(reportID, type = "pdf") {
490
+ return this.file(reportID, { original: false, type });
491
+ }
492
+ /**
493
+ * Download the original version of a document
494
+ * @param reportID - The report ID of the document
495
+ * @param type - File type to download (pdf or xlsx)
496
+ * @returns The original file as a Blob
497
+ */
498
+ async original(reportID, type = "pdf") {
499
+ return this.file(reportID, { original: true, type });
500
+ }
501
+ /**
502
+ * Download multiple documents as a ZIP file
503
+ * @param files - Array of document IDs to include in the ZIP
504
+ * @returns The ZIP file as a Blob
505
+ */
506
+ async zipped(files) {
507
+ const params = { files };
508
+ return this.client.postBlob("docs/download/zipped", params);
509
+ }
510
+ };
511
+
512
+ // src/equalweb.ts
513
+ var EqualWeb = class {
514
+ client;
515
+ info;
516
+ documents;
517
+ groups;
518
+ audit;
519
+ reports;
520
+ downloads;
521
+ /**
522
+ * Create a new EqualWeb API client
523
+ * @param config - Configuration object with API key and optional settings
524
+ * @example
525
+ * ```typescript
526
+ * const client = new EqualWeb({ apiKey: 'your-api-key' });
527
+ *
528
+ * // Get credit balance
529
+ * const balance = await client.info.getBalance();
530
+ *
531
+ * // Upload a document
532
+ * const file = new File([...], 'document.pdf');
533
+ * const upload = await client.documents.upload(file);
534
+ *
535
+ * // Start an audit
536
+ * await client.audit.audit([upload.id]);
537
+ *
538
+ * // Check status
539
+ * const status = await client.documents.getStatus(upload.id);
540
+ *
541
+ * // Download the audited file
542
+ * const blob = await client.downloads.audited(upload.id);
543
+ * ```
544
+ */
545
+ constructor(config) {
546
+ this.client = new HttpClient(config);
547
+ this.info = new InfoApi(this.client);
548
+ this.documents = new DocumentsApi(this.client);
549
+ this.groups = new GroupsApi(this.client);
550
+ this.audit = new AuditApi(this.client);
551
+ this.reports = new ReportsApi(this.client);
552
+ this.downloads = new DownloadsApi(this.client);
553
+ }
554
+ };
555
+ // Annotate the CommonJS export names for ESM import in node:
556
+ 0 && (module.exports = {
557
+ AuditApi,
558
+ AuthenticationError,
559
+ DocumentsApi,
560
+ DownloadsApi,
561
+ EqualWeb,
562
+ EqualWebError,
563
+ GroupsApi,
564
+ InfoApi,
565
+ RateLimitError,
566
+ ReportsApi
567
+ });
568
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/types.ts","../src/client.ts","../src/api/info.ts","../src/api/documents.ts","../src/api/groups.ts","../src/api/audit.ts","../src/api/reports.ts","../src/api/downloads.ts","../src/equalweb.ts"],"sourcesContent":["// Main client\r\nexport { EqualWeb } from \"./equalweb\";\r\n\r\n// Types\r\nexport type {\r\n // Config\r\n EqualWebConfig,\r\n\r\n // Common\r\n DocumentStatus,\r\n AuditType,\r\n ReportType,\r\n DownloadFileType,\r\n\r\n // Info\r\n BalanceResponse,\r\n\r\n // Documents\r\n Document,\r\n GetDocumentsParams,\r\n DocumentStatusResponse,\r\n UploadResponse,\r\n DeleteDocumentsParams,\r\n DeleteDocumentsResponse,\r\n ArchiveDocumentsParams,\r\n ArchiveDocumentsResponse,\r\n\r\n // Groups\r\n DocumentGroup,\r\n GroupDocumentsParams,\r\n GroupDocumentsResponse,\r\n RenameGroupParams,\r\n RenameGroupResponse,\r\n\r\n // Audit\r\n AuditDocumentsParams,\r\n AuditDocumentsResponse,\r\n\r\n // Reports\r\n ReportRule,\r\n ReportSummary,\r\n DetailedReport,\r\n ReportCustomData,\r\n AuditedReport,\r\n OriginalReport,\r\n GetReportParams,\r\n ReportResponse,\r\n\r\n // Downloads\r\n DownloadFileParams,\r\n DownloadZippedParams,\r\n\r\n // Errors\r\n EqualWebErrorResponse,\r\n} from \"./types\";\r\n\r\n// Error classes\r\nexport { EqualWebError, RateLimitError, AuthenticationError } from \"./types\";\r\n\r\n// API classes (for advanced usage)\r\nexport { InfoApi } from \"./api/info\";\r\nexport { DocumentsApi } from \"./api/documents\";\r\nexport { GroupsApi } from \"./api/groups\";\r\nexport { AuditApi } from \"./api/audit\";\r\nexport { ReportsApi } from \"./api/reports\";\r\nexport { DownloadsApi } from \"./api/downloads\";\r\n","// ============================================================================\r\n// Configuration Types\r\n// ============================================================================\r\n\r\nexport interface EqualWebConfig {\r\n apiKey: string;\r\n baseUrl?: string;\r\n timeout?: number;\r\n}\r\n\r\n// ============================================================================\r\n// Common Types\r\n// ============================================================================\r\n\r\nexport type DocumentStatus = \"done\" | \"pending\" | \"processing\" | string;\r\n\r\nexport type AuditType = \"audit\" | \"check\";\r\n\r\nexport type ReportType = \"audited\" | \"original\" | \"both\";\r\n\r\nexport type DownloadFileType = \"pdf\" | \"xlsx\";\r\n\r\n// ============================================================================\r\n// Info Types\r\n// ============================================================================\r\n\r\nexport interface BalanceResponse {\r\n results: number;\r\n}\r\n\r\n// ============================================================================\r\n// Document Types\r\n// ============================================================================\r\n\r\nexport interface Document {\r\n numberOfPages: number;\r\n createdAt: string;\r\n group: number | null;\r\n archived: boolean;\r\n reportID: string;\r\n status: DocumentStatus;\r\n}\r\n\r\nexport interface GetDocumentsParams {\r\n groupID?: string;\r\n archived?: boolean;\r\n type?: string;\r\n}\r\n\r\nexport interface DocumentStatusResponse {\r\n status: DocumentStatus;\r\n}\r\n\r\nexport interface UploadResponse {\r\n id: string;\r\n createdAt: string;\r\n numberOfPages: number;\r\n}\r\n\r\nexport interface DeleteDocumentsParams {\r\n files: string[];\r\n}\r\n\r\nexport interface DeleteDocumentsResponse {\r\n results: Record<string, boolean | { error: string }>;\r\n}\r\n\r\nexport interface ArchiveDocumentsParams {\r\n files: string[];\r\n archive?: boolean;\r\n}\r\n\r\nexport interface ArchiveDocumentsResponse {\r\n results: \"ok\";\r\n}\r\n\r\n// ============================================================================\r\n// Group Types\r\n// ============================================================================\r\n\r\nexport interface DocumentGroup {\r\n id: number;\r\n name: string;\r\n createdAt: string;\r\n}\r\n\r\nexport interface GroupDocumentsParams {\r\n files: string[];\r\n newGroup?: string;\r\n selectedGroup?: string;\r\n}\r\n\r\nexport interface GroupDocumentsResponse {\r\n results: \"ok\";\r\n}\r\n\r\nexport interface RenameGroupParams {\r\n groupID: string;\r\n groupName: string;\r\n}\r\n\r\nexport interface RenameGroupResponse {\r\n results: \"ok\";\r\n}\r\n\r\n// ============================================================================\r\n// Audit Types\r\n// ============================================================================\r\n\r\nexport interface AuditDocumentsParams {\r\n files: string[];\r\n type?: AuditType;\r\n}\r\n\r\nexport interface AuditDocumentsResponse {\r\n results: \"ok\";\r\n}\r\n\r\n// ============================================================================\r\n// Report Types\r\n// ============================================================================\r\n\r\nexport interface ReportRule {\r\n Rule: string;\r\n Status: \"Passed\" | \"Failed\" | \"Needs manual check\" | string;\r\n Description: string;\r\n}\r\n\r\nexport interface ReportSummary {\r\n \"Passed\"?: number;\r\n \"Failed\"?: number;\r\n \"Needs manual check\"?: number;\r\n Description?: string;\r\n}\r\n\r\nexport interface DetailedReport {\r\n Document?: ReportRule[];\r\n \"Page Content\"?: ReportRule[];\r\n Forms?: ReportRule[];\r\n \"Alternate Text\"?: ReportRule[];\r\n Tables?: ReportRule[];\r\n Lists?: ReportRule[];\r\n Headings?: ReportRule[];\r\n}\r\n\r\nexport interface ReportCustomData {\r\n fileName?: string;\r\n fileSize?: number;\r\n numberOfPages?: number;\r\n tags?: Record<string, number>;\r\n [key: string]: unknown;\r\n}\r\n\r\nexport interface AuditedReport {\r\n Summary?: ReportSummary;\r\n \"Detailed Report\"?: DetailedReport;\r\n customData?: ReportCustomData;\r\n}\r\n\r\nexport interface OriginalReport {\r\n Summary?: ReportSummary;\r\n \"Detailed Report\"?: DetailedReport;\r\n customData?: ReportCustomData;\r\n}\r\n\r\nexport interface GetReportParams {\r\n type?: ReportType;\r\n}\r\n\r\nexport interface ReportResponse {\r\n original?: OriginalReport;\r\n audited?: AuditedReport;\r\n}\r\n\r\n// ============================================================================\r\n// Download Types\r\n// ============================================================================\r\n\r\nexport interface DownloadFileParams {\r\n original?: boolean;\r\n type?: DownloadFileType;\r\n}\r\n\r\nexport interface DownloadZippedParams {\r\n files: string[];\r\n}\r\n\r\n// ============================================================================\r\n// Error Types\r\n// ============================================================================\r\n\r\nexport interface EqualWebErrorResponse {\r\n error?: string;\r\n message?: string;\r\n statusCode?: number;\r\n}\r\n\r\nexport class EqualWebError extends Error {\r\n public readonly statusCode: number;\r\n public readonly response?: EqualWebErrorResponse;\r\n\r\n constructor(message: string, statusCode: number, response?: EqualWebErrorResponse) {\r\n super(message);\r\n this.name = \"EqualWebError\";\r\n this.statusCode = statusCode;\r\n this.response = response;\r\n }\r\n}\r\n\r\nexport class RateLimitError extends EqualWebError {\r\n public readonly retryAfter?: number;\r\n\r\n constructor(message: string, retryAfter?: number) {\r\n super(message, 429);\r\n this.name = \"RateLimitError\";\r\n this.retryAfter = retryAfter;\r\n }\r\n}\r\n\r\nexport class AuthenticationError extends EqualWebError {\r\n constructor(message: string = \"Invalid or missing API key\") {\r\n super(message, 401);\r\n this.name = \"AuthenticationError\";\r\n }\r\n}\r\n","import {\r\n EqualWebConfig,\r\n EqualWebError,\r\n EqualWebErrorResponse,\r\n RateLimitError,\r\n AuthenticationError,\r\n} from \"./types\";\r\n\r\nconst DEFAULT_BASE_URL = \"https://login.equalweb.com/api/v2\";\r\nconst DEFAULT_TIMEOUT = 30000;\r\n\r\nexport interface RequestOptions {\r\n method: \"GET\" | \"POST\" | \"PUT\" | \"DELETE\";\r\n path: string;\r\n query?: Record<string, string | boolean | undefined>;\r\n body?: unknown;\r\n isFormData?: boolean;\r\n responseType?: \"json\" | \"blob\";\r\n}\r\n\r\nexport class HttpClient {\r\n private readonly apiKey: string;\r\n private readonly baseUrl: string;\r\n private readonly timeout: number;\r\n\r\n constructor(config: EqualWebConfig) {\r\n if (!config.apiKey || config.apiKey.trim().length === 0) {\r\n throw new Error(\"API key is required and cannot be empty\");\r\n }\r\n\r\n if (config.timeout !== undefined && config.timeout < 0) {\r\n throw new Error(\"timeout must be a positive number\");\r\n }\r\n\r\n if (config.baseUrl) {\r\n try {\r\n new URL(config.baseUrl);\r\n } catch {\r\n throw new Error(\"baseUrl must be a valid URL\");\r\n }\r\n }\r\n\r\n this.apiKey = config.apiKey;\r\n this.baseUrl = config.baseUrl?.replace(/\\/$/, \"\") ?? DEFAULT_BASE_URL;\r\n this.timeout = config.timeout ?? DEFAULT_TIMEOUT;\r\n }\r\n\r\n async request<T>(options: RequestOptions): Promise<T> {\r\n const { method, path, query, body, isFormData, responseType = \"json\" } = options;\r\n\r\n const url = new URL(path, this.baseUrl + \"/\");\r\n\r\n if (query) {\r\n Object.entries(query).forEach(([key, value]) => {\r\n if (value !== undefined) {\r\n url.searchParams.set(key, String(value));\r\n }\r\n });\r\n }\r\n\r\n const headers: Record<string, string> = {\r\n \"x-a11y-api-key\": this.apiKey,\r\n };\r\n\r\n if (!isFormData && body) {\r\n headers[\"Content-Type\"] = \"application/json\";\r\n }\r\n\r\n const controller = new AbortController();\r\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\r\n\r\n try {\r\n const response = await fetch(url.toString(), {\r\n method,\r\n headers,\r\n body: isFormData ? (body as FormData) : body ? JSON.stringify(body) : undefined,\r\n signal: controller.signal,\r\n });\r\n\r\n clearTimeout(timeoutId);\r\n\r\n if (!response.ok) {\r\n await this.handleErrorResponse(response);\r\n }\r\n\r\n if (responseType === \"blob\") {\r\n return response.blob() as Promise<T>;\r\n }\r\n\r\n const text = await response.text();\r\n if (!text) {\r\n return {} as T;\r\n }\r\n\r\n try {\r\n return JSON.parse(text) as T;\r\n } catch (parseError) {\r\n const preview = text.length > 100 ? text.substring(0, 100) + \"...\" : text;\r\n throw new EqualWebError(`Failed to parse JSON response: ${preview}`, 0);\r\n }\r\n } catch (error) {\r\n clearTimeout(timeoutId);\r\n\r\n if (error instanceof EqualWebError) {\r\n throw error;\r\n }\r\n\r\n if (error instanceof Error) {\r\n if (error.name === \"AbortError\") {\r\n throw new EqualWebError(\"Request timeout\", 408);\r\n }\r\n throw new EqualWebError(error.message, 0);\r\n }\r\n\r\n throw new EqualWebError(\"Unknown error occurred\", 0);\r\n }\r\n }\r\n\r\n private async handleErrorResponse(response: Response): Promise<never> {\r\n let errorData: EqualWebErrorResponse | undefined;\r\n\r\n try {\r\n const text = await response.text();\r\n if (text) {\r\n errorData = JSON.parse(text);\r\n }\r\n } catch {\r\n // Response body is not JSON\r\n }\r\n\r\n const message = errorData?.error ?? errorData?.message ?? response.statusText;\r\n\r\n switch (response.status) {\r\n case 401:\r\n throw new AuthenticationError(message);\r\n case 429: {\r\n const retryAfter = response.headers.get(\"Retry-After\");\r\n throw new RateLimitError(\r\n message || \"Rate limit exceeded\",\r\n retryAfter ? parseInt(retryAfter, 10) : undefined\r\n );\r\n }\r\n default:\r\n throw new EqualWebError(message, response.status, errorData);\r\n }\r\n }\r\n\r\n get<T>(path: string, query?: Record<string, string | boolean | undefined>): Promise<T> {\r\n return this.request<T>({ method: \"GET\", path, query });\r\n }\r\n\r\n post<T>(path: string, body?: unknown): Promise<T> {\r\n return this.request<T>({ method: \"POST\", path, body });\r\n }\r\n\r\n put<T>(path: string, body?: unknown, isFormData = false): Promise<T> {\r\n return this.request<T>({ method: \"PUT\", path, body, isFormData });\r\n }\r\n\r\n delete<T>(path: string, body?: unknown): Promise<T> {\r\n return this.request<T>({ method: \"DELETE\", path, body });\r\n }\r\n\r\n getBlob(path: string, query?: Record<string, string | boolean | undefined>): Promise<Blob> {\r\n return this.request<Blob>({ method: \"GET\", path, query, responseType: \"blob\" });\r\n }\r\n\r\n postBlob(path: string, body?: unknown): Promise<Blob> {\r\n return this.request<Blob>({ method: \"POST\", path, body, responseType: \"blob\" });\r\n }\r\n}\r\n","import { HttpClient } from \"../client\";\r\nimport { BalanceResponse } from \"../types\";\r\n\r\nexport class InfoApi {\r\n constructor(private readonly client: HttpClient) {}\r\n\r\n /**\r\n * Get the current credit balance for your account\r\n * @returns The current credit balance\r\n */\r\n async getBalance(): Promise<number> {\r\n const response = await this.client.get<BalanceResponse>(\"info/balance\");\r\n return response.results;\r\n }\r\n}\r\n","import { HttpClient } from \"../client\";\r\nimport {\r\n Document,\r\n GetDocumentsParams,\r\n DocumentStatusResponse,\r\n UploadResponse,\r\n DeleteDocumentsParams,\r\n DeleteDocumentsResponse,\r\n ArchiveDocumentsParams,\r\n ArchiveDocumentsResponse,\r\n} from \"../types\";\r\n\r\nexport class DocumentsApi {\r\n constructor(private readonly client: HttpClient) {}\r\n\r\n /**\r\n * Get all documents\r\n * @param params - Optional filters for groupID, archived status, and document type\r\n * @returns Array of documents\r\n */\r\n async getAll(params?: GetDocumentsParams): Promise<Document[]> {\r\n return this.client.get<Document[]>(\"docs\", {\r\n groupID: params?.groupID,\r\n archived: params?.archived,\r\n type: params?.type,\r\n });\r\n }\r\n\r\n /**\r\n * Get the status of a specific document\r\n * @param reportID - The report ID of the document\r\n * @returns The document status\r\n */\r\n async getStatus(reportID: string): Promise<string> {\r\n if (!reportID || reportID.trim().length === 0) {\r\n throw new Error(\"reportID cannot be empty\");\r\n }\r\n const response = await this.client.get<DocumentStatusResponse>(`docs/status/${reportID}`);\r\n return response.status;\r\n }\r\n\r\n /**\r\n * Upload a document for processing\r\n * Supported formats: PDF, XLSX, DOCX, PPTX\r\n * @param file - The file to upload (File, Blob, ArrayBuffer, or Uint8Array)\r\n * @param filename - Optional filename (required if file is an ArrayBuffer or Uint8Array)\r\n * @returns Upload response with document ID and metadata\r\n */\r\n async upload(\r\n file: File | Blob | ArrayBuffer | Uint8Array,\r\n filename?: string\r\n ): Promise<UploadResponse> {\r\n if (!file) {\r\n throw new Error(\"file cannot be null or undefined\");\r\n }\r\n\r\n // Validate file size\r\n let sizeInBytes = 0;\r\n if (file instanceof ArrayBuffer) {\r\n sizeInBytes = file.byteLength;\r\n } else if (file instanceof Uint8Array) {\r\n sizeInBytes = file.byteLength;\r\n } else if (file instanceof Blob) {\r\n sizeInBytes = file.size;\r\n }\r\n\r\n if (sizeInBytes === 0) {\r\n throw new Error(\"file is empty\");\r\n }\r\n\r\n const formData = new FormData();\r\n\r\n if (file instanceof ArrayBuffer || file instanceof Uint8Array) {\r\n const blob = new Blob([file as BlobPart]);\r\n formData.append(\"file\", blob, filename ?? \"document.pdf\");\r\n } else if (file instanceof Blob) {\r\n // Use optional chaining for safer property access\r\n const defaultFilename = (file as any)?.name ?? \"document.pdf\";\r\n formData.append(\"file\", file, filename ?? defaultFilename);\r\n } else {\r\n formData.append(\"file\", file);\r\n }\r\n\r\n return this.client.put<UploadResponse>(\"docs/upload\", formData, true);\r\n }\r\n\r\n /**\r\n * Delete multiple documents\r\n * @param files - Array of document IDs to delete\r\n * @returns Results indicating success/failure for each document\r\n */\r\n async delete(files: string[]): Promise<DeleteDocumentsResponse> {\r\n if (!files || files.length === 0) {\r\n throw new Error(\"files array cannot be empty\");\r\n }\r\n const params: DeleteDocumentsParams = { files };\r\n return this.client.delete<DeleteDocumentsResponse>(\"docs\", params);\r\n }\r\n\r\n /**\r\n * Archive documents\r\n * @param files - Array of document IDs to archive\r\n * @returns Result of the operation\r\n */\r\n async archive(files: string[]): Promise<ArchiveDocumentsResponse> {\r\n if (!files || files.length === 0) {\r\n throw new Error(\"files array cannot be empty\");\r\n }\r\n const params: ArchiveDocumentsParams = { files, archive: true };\r\n return this.client.post<ArchiveDocumentsResponse>(\"docs/archive\", params);\r\n }\r\n\r\n /**\r\n * Restore archived documents\r\n * @param files - Array of document IDs to restore\r\n * @returns Result of the operation\r\n */\r\n async restore(files: string[]): Promise<ArchiveDocumentsResponse> {\r\n if (!files || files.length === 0) {\r\n throw new Error(\"files array cannot be empty\");\r\n }\r\n const params: ArchiveDocumentsParams = { files, archive: false };\r\n return this.client.post<ArchiveDocumentsResponse>(\"docs/archive\", params);\r\n }\r\n}\r\n","import { HttpClient } from \"../client\";\r\nimport {\r\n DocumentGroup,\r\n GroupDocumentsParams,\r\n GroupDocumentsResponse,\r\n RenameGroupParams,\r\n RenameGroupResponse,\r\n} from \"../types\";\r\n\r\nexport class GroupsApi {\r\n constructor(private readonly client: HttpClient) {}\r\n\r\n /**\r\n * Get all document groups\r\n * @returns Array of document groups\r\n */\r\n async getAll(): Promise<DocumentGroup[]> {\r\n return this.client.get<DocumentGroup[]>(\"docs/groups\");\r\n }\r\n\r\n /**\r\n * Add documents to a new group\r\n * @param files - Array of document IDs to group\r\n * @param groupName - Name of the new group to create\r\n * @returns Result of the operation\r\n */\r\n async createGroup(files: string[], groupName: string): Promise<GroupDocumentsResponse> {\r\n if (!files || files.length === 0) {\r\n throw new Error(\"files array cannot be empty\");\r\n }\r\n if (!groupName || groupName.trim().length === 0) {\r\n throw new Error(\"groupName cannot be empty\");\r\n }\r\n const params: GroupDocumentsParams = { files, newGroup: groupName };\r\n return this.client.post<GroupDocumentsResponse>(\"docs/group\", params);\r\n }\r\n\r\n /**\r\n * Add documents to an existing group\r\n * @param files - Array of document IDs to group\r\n * @param groupID - ID of the existing group\r\n * @returns Result of the operation\r\n */\r\n async addToGroup(files: string[], groupID: string): Promise<GroupDocumentsResponse> {\r\n if (!files || files.length === 0) {\r\n throw new Error(\"files array cannot be empty\");\r\n }\r\n if (!groupID || groupID.trim().length === 0) {\r\n throw new Error(\"groupID cannot be empty\");\r\n }\r\n const params: GroupDocumentsParams = { files, selectedGroup: groupID };\r\n return this.client.post<GroupDocumentsResponse>(\"docs/group\", params);\r\n }\r\n\r\n /**\r\n * Rename a document group\r\n * @param groupID - ID of the group to rename\r\n * @param groupName - New name for the group\r\n * @returns Result of the operation\r\n */\r\n async rename(groupID: string, groupName: string): Promise<RenameGroupResponse> {\r\n if (!groupID || groupID.trim().length === 0) {\r\n throw new Error(\"groupID cannot be empty\");\r\n }\r\n if (!groupName || groupName.trim().length === 0) {\r\n throw new Error(\"groupName cannot be empty\");\r\n }\r\n const params: RenameGroupParams = { groupID, groupName };\r\n return this.client.post<RenameGroupResponse>(\"group-name\", params);\r\n }\r\n}\r\n","import { HttpClient } from \"../client\";\r\nimport { AuditDocumentsParams, AuditDocumentsResponse, AuditType } from \"../types\";\r\n\r\nexport class AuditApi {\r\n constructor(private readonly client: HttpClient) {}\r\n\r\n /**\r\n * Start a full audit on documents\r\n * This performs accessibility remediation and generates detailed reports\r\n * @param files - Array of document IDs to audit\r\n * @returns Result of the operation (202 Accepted - processing is async)\r\n */\r\n async audit(files: string[]): Promise<AuditDocumentsResponse> {\r\n if (!files || files.length === 0) {\r\n throw new Error(\"files array cannot be empty\");\r\n }\r\n const params: AuditDocumentsParams = { files, type: \"audit\" };\r\n return this.client.post<AuditDocumentsResponse>(\"docs/audit\", params);\r\n }\r\n\r\n /**\r\n * Perform a quick check on documents without full remediation\r\n * @param files - Array of document IDs to check\r\n * @returns Result of the operation (202 Accepted - processing is async)\r\n */\r\n async check(files: string[]): Promise<AuditDocumentsResponse> {\r\n if (!files || files.length === 0) {\r\n throw new Error(\"files array cannot be empty\");\r\n }\r\n const params: AuditDocumentsParams = { files, type: \"check\" };\r\n return this.client.post<AuditDocumentsResponse>(\"docs/audit\", params);\r\n }\r\n\r\n /**\r\n * Start an audit with custom type\r\n * @param files - Array of document IDs to process\r\n * @param type - Type of audit: \"audit\" for full audit, \"check\" for quick check\r\n * @returns Result of the operation (202 Accepted - processing is async)\r\n */\r\n async process(files: string[], type: AuditType): Promise<AuditDocumentsResponse> {\r\n if (!files || files.length === 0) {\r\n throw new Error(\"files array cannot be empty\");\r\n }\r\n if (!type || type.trim().length === 0) {\r\n throw new Error(\"type cannot be empty\");\r\n }\r\n const params: AuditDocumentsParams = { files, type };\r\n return this.client.post<AuditDocumentsResponse>(\"docs/audit\", params);\r\n }\r\n}\r\n","import { HttpClient } from \"../client\";\r\nimport { ReportResponse, ReportType, GetReportParams } from \"../types\";\r\n\r\nconst REPORTS_BASE_URL = \"https://login.equalweb.com/reports/pdf\";\r\n\r\nexport class ReportsApi {\r\n constructor(private readonly client: HttpClient) {}\r\n\r\n /**\r\n * Get the JSON report for a document\r\n * @param reportID - The report ID\r\n * @param type - Which report to retrieve: \"audited\", \"original\", or \"both\"\r\n * @returns The report data\r\n */\r\n async get(reportID: string, type: ReportType = \"audited\"): Promise<ReportResponse> {\r\n const params: GetReportParams = { type };\r\n return this.client.get<ReportResponse>(`docs/report/${reportID}`, {\r\n type: params.type,\r\n });\r\n }\r\n\r\n /**\r\n * Get the audited report for a document\r\n * @param reportID - The report ID\r\n * @returns The audited report data\r\n */\r\n async getAudited(reportID: string): Promise<ReportResponse> {\r\n return this.get(reportID, \"audited\");\r\n }\r\n\r\n /**\r\n * Get the original report for a document\r\n * @param reportID - The report ID\r\n * @returns The original report data\r\n */\r\n async getOriginal(reportID: string): Promise<ReportResponse> {\r\n return this.get(reportID, \"original\");\r\n }\r\n\r\n /**\r\n * Get both audited and original reports for a document\r\n * @param reportID - The report ID\r\n * @returns Both report data\r\n */\r\n async getBoth(reportID: string): Promise<ReportResponse> {\r\n return this.get(reportID, \"both\");\r\n }\r\n\r\n /**\r\n * Get the URL to view the report in a browser\r\n * Note: This URL does not require authentication\r\n * @param reportID - The report ID\r\n * @returns The browser-viewable URL\r\n */\r\n getBrowserUrl(reportID: string): string {\r\n return `${REPORTS_BASE_URL}/${reportID}`;\r\n }\r\n}\r\n","import { HttpClient } from \"../client\";\r\nimport { DownloadFileParams, DownloadZippedParams, DownloadFileType } from \"../types\";\r\n\r\nexport class DownloadsApi {\r\n constructor(private readonly client: HttpClient) {}\r\n\r\n /**\r\n * Download a single document file\r\n * @param reportID - The report ID of the document\r\n * @param options - Download options (original file, file type)\r\n * @returns The file as a Blob\r\n */\r\n async file(reportID: string, options?: DownloadFileParams): Promise<Blob> {\r\n return this.client.getBlob(`docs/download/file/${reportID}`, {\r\n original: options?.original,\r\n type: options?.type,\r\n });\r\n }\r\n\r\n /**\r\n * Download the audited/processed version of a document\r\n * @param reportID - The report ID of the document\r\n * @param type - File type to download (pdf or xlsx)\r\n * @returns The processed file as a Blob\r\n */\r\n async audited(reportID: string, type: DownloadFileType = \"pdf\"): Promise<Blob> {\r\n return this.file(reportID, { original: false, type });\r\n }\r\n\r\n /**\r\n * Download the original version of a document\r\n * @param reportID - The report ID of the document\r\n * @param type - File type to download (pdf or xlsx)\r\n * @returns The original file as a Blob\r\n */\r\n async original(reportID: string, type: DownloadFileType = \"pdf\"): Promise<Blob> {\r\n return this.file(reportID, { original: true, type });\r\n }\r\n\r\n /**\r\n * Download multiple documents as a ZIP file\r\n * @param files - Array of document IDs to include in the ZIP\r\n * @returns The ZIP file as a Blob\r\n */\r\n async zipped(files: string[]): Promise<Blob> {\r\n const params: DownloadZippedParams = { files };\r\n return this.client.postBlob(\"docs/download/zipped\", params);\r\n }\r\n}\r\n","import { HttpClient } from \"./client\";\r\nimport { InfoApi, DocumentsApi, GroupsApi, AuditApi, ReportsApi, DownloadsApi } from \"./api\";\r\nimport { EqualWebConfig } from \"./types\";\r\n\r\nexport class EqualWeb {\r\n private readonly client: HttpClient;\r\n\r\n public readonly info: InfoApi;\r\n public readonly documents: DocumentsApi;\r\n public readonly groups: GroupsApi;\r\n public readonly audit: AuditApi;\r\n public readonly reports: ReportsApi;\r\n public readonly downloads: DownloadsApi;\r\n\r\n /**\r\n * Create a new EqualWeb API client\r\n * @param config - Configuration object with API key and optional settings\r\n * @example\r\n * ```typescript\r\n * const client = new EqualWeb({ apiKey: 'your-api-key' });\r\n *\r\n * // Get credit balance\r\n * const balance = await client.info.getBalance();\r\n *\r\n * // Upload a document\r\n * const file = new File([...], 'document.pdf');\r\n * const upload = await client.documents.upload(file);\r\n *\r\n * // Start an audit\r\n * await client.audit.audit([upload.id]);\r\n *\r\n * // Check status\r\n * const status = await client.documents.getStatus(upload.id);\r\n *\r\n * // Download the audited file\r\n * const blob = await client.downloads.audited(upload.id);\r\n * ```\r\n */\r\n constructor(config: EqualWebConfig) {\r\n this.client = new HttpClient(config);\r\n\r\n this.info = new InfoApi(this.client);\r\n this.documents = new DocumentsApi(this.client);\r\n this.groups = new GroupsApi(this.client);\r\n this.audit = new AuditApi(this.client);\r\n this.reports = new ReportsApi(this.client);\r\n this.downloads = new DownloadsApi(this.client);\r\n }\r\n}\r\n"],"mappings":"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","names":[]}