@stack0/sdk 0.2.0 → 0.2.1

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.
@@ -0,0 +1,693 @@
1
+ 'use strict';
2
+
3
+ // src/lib/http-client.ts
4
+ var HttpClient = class {
5
+ apiKey;
6
+ baseUrl;
7
+ constructor(config) {
8
+ this.apiKey = config.apiKey;
9
+ this.baseUrl = config.baseUrl || "https://api.stack0.com/v1";
10
+ }
11
+ getHeaders() {
12
+ return {
13
+ "Content-Type": "application/json",
14
+ Authorization: `Bearer ${this.apiKey}`
15
+ };
16
+ }
17
+ async request(method, path, body) {
18
+ const url = `${this.baseUrl}${path}`;
19
+ try {
20
+ const response = await fetch(url, {
21
+ method,
22
+ headers: this.getHeaders(),
23
+ body: body ? JSON.stringify(body) : void 0
24
+ });
25
+ if (!response.ok) {
26
+ await this.handleErrorResponse(response);
27
+ }
28
+ const data = await response.json();
29
+ return data;
30
+ } catch (error) {
31
+ if (error instanceof Error && "statusCode" in error) {
32
+ throw error;
33
+ }
34
+ throw this.createError("Network error", error);
35
+ }
36
+ }
37
+ async handleErrorResponse(response) {
38
+ let errorBody;
39
+ try {
40
+ errorBody = await response.json();
41
+ } catch {
42
+ errorBody = { message: response.statusText };
43
+ }
44
+ const error = new Error(errorBody?.message || `HTTP ${response.status}`);
45
+ error.statusCode = response.status;
46
+ error.code = errorBody?.code ?? "";
47
+ error.response = errorBody;
48
+ throw error;
49
+ }
50
+ createError(message, cause) {
51
+ const error = new Error(message);
52
+ error.cause = cause;
53
+ return error;
54
+ }
55
+ async get(path) {
56
+ return this.request("GET", path);
57
+ }
58
+ async post(path, body) {
59
+ return this.request("POST", path, body);
60
+ }
61
+ async put(path, body) {
62
+ return this.request("PUT", path, body);
63
+ }
64
+ async delete(path) {
65
+ return this.request("DELETE", path);
66
+ }
67
+ };
68
+
69
+ // src/webdata/client.ts
70
+ var Webdata = class {
71
+ http;
72
+ constructor(config) {
73
+ this.http = new HttpClient(config);
74
+ }
75
+ // ==========================================================================
76
+ // SCREENSHOTS
77
+ // ==========================================================================
78
+ /**
79
+ * Capture a screenshot of a URL
80
+ *
81
+ * @example
82
+ * ```typescript
83
+ * const { id, status } = await webdata.screenshot({
84
+ * url: 'https://example.com',
85
+ * format: 'png',
86
+ * fullPage: true,
87
+ * deviceType: 'desktop',
88
+ * });
89
+ *
90
+ * // Poll for completion
91
+ * const screenshot = await webdata.getScreenshot({ id });
92
+ * console.log(screenshot.imageUrl);
93
+ * ```
94
+ */
95
+ async screenshot(request) {
96
+ return this.http.post("/webdata/screenshots", request);
97
+ }
98
+ /**
99
+ * Get a screenshot by ID
100
+ *
101
+ * @example
102
+ * ```typescript
103
+ * const screenshot = await webdata.getScreenshot({ id: 'screenshot-id' });
104
+ * if (screenshot.status === 'completed') {
105
+ * console.log(screenshot.imageUrl);
106
+ * }
107
+ * ```
108
+ */
109
+ async getScreenshot(request) {
110
+ const params = new URLSearchParams();
111
+ if (request.environment) params.set("environment", request.environment);
112
+ if (request.projectId) params.set("projectId", request.projectId);
113
+ const query = params.toString();
114
+ const path = `/webdata/screenshots/${request.id}${query ? `?${query}` : ""}`;
115
+ const response = await this.http.get(path);
116
+ return this.convertScreenshotDates(response);
117
+ }
118
+ /**
119
+ * List screenshots with pagination and filters
120
+ *
121
+ * @example
122
+ * ```typescript
123
+ * const { items, nextCursor } = await webdata.listScreenshots({
124
+ * status: 'completed',
125
+ * limit: 20,
126
+ * });
127
+ * ```
128
+ */
129
+ async listScreenshots(request = {}) {
130
+ const params = new URLSearchParams();
131
+ if (request.environment) params.set("environment", request.environment);
132
+ if (request.projectId) params.set("projectId", request.projectId);
133
+ if (request.status) params.set("status", request.status);
134
+ if (request.url) params.set("url", request.url);
135
+ if (request.limit) params.set("limit", request.limit.toString());
136
+ if (request.cursor) params.set("cursor", request.cursor);
137
+ const query = params.toString();
138
+ const response = await this.http.get(
139
+ `/webdata/screenshots${query ? `?${query}` : ""}`
140
+ );
141
+ return {
142
+ ...response,
143
+ items: response.items.map((item) => this.convertScreenshotDates(item))
144
+ };
145
+ }
146
+ /**
147
+ * Delete a screenshot
148
+ *
149
+ * @example
150
+ * ```typescript
151
+ * await webdata.deleteScreenshot({ id: 'screenshot-id' });
152
+ * ```
153
+ */
154
+ async deleteScreenshot(request) {
155
+ const params = new URLSearchParams();
156
+ if (request.environment) params.set("environment", request.environment);
157
+ if (request.projectId) params.set("projectId", request.projectId);
158
+ const query = params.toString();
159
+ return this.http.delete(
160
+ `/webdata/screenshots/${request.id}${query ? `?${query}` : ""}`
161
+ );
162
+ }
163
+ /**
164
+ * Capture a screenshot and wait for completion
165
+ *
166
+ * @example
167
+ * ```typescript
168
+ * const screenshot = await webdata.screenshotAndWait({
169
+ * url: 'https://example.com',
170
+ * format: 'png',
171
+ * });
172
+ * console.log(screenshot.imageUrl);
173
+ * ```
174
+ */
175
+ async screenshotAndWait(request, options = {}) {
176
+ const { pollInterval = 1e3, timeout = 6e4 } = options;
177
+ const startTime = Date.now();
178
+ const { id } = await this.screenshot(request);
179
+ while (Date.now() - startTime < timeout) {
180
+ const screenshot = await this.getScreenshot({
181
+ id,
182
+ environment: request.environment,
183
+ projectId: request.projectId
184
+ });
185
+ if (screenshot.status === "completed" || screenshot.status === "failed") {
186
+ if (screenshot.status === "failed") {
187
+ throw new Error(screenshot.error || "Screenshot failed");
188
+ }
189
+ return screenshot;
190
+ }
191
+ await new Promise((resolve) => setTimeout(resolve, pollInterval));
192
+ }
193
+ throw new Error("Screenshot timed out");
194
+ }
195
+ // ==========================================================================
196
+ // EXTRACTIONS
197
+ // ==========================================================================
198
+ /**
199
+ * Extract content from a URL
200
+ *
201
+ * @example
202
+ * ```typescript
203
+ * const { id, status } = await webdata.extract({
204
+ * url: 'https://example.com/article',
205
+ * mode: 'markdown',
206
+ * includeMetadata: true,
207
+ * });
208
+ *
209
+ * // Poll for completion
210
+ * const extraction = await webdata.getExtraction({ id });
211
+ * console.log(extraction.markdown);
212
+ * ```
213
+ */
214
+ async extract(request) {
215
+ return this.http.post("/webdata/extractions", request);
216
+ }
217
+ /**
218
+ * Get an extraction by ID
219
+ *
220
+ * @example
221
+ * ```typescript
222
+ * const extraction = await webdata.getExtraction({ id: 'extraction-id' });
223
+ * if (extraction.status === 'completed') {
224
+ * console.log(extraction.markdown);
225
+ * console.log(extraction.pageMetadata);
226
+ * }
227
+ * ```
228
+ */
229
+ async getExtraction(request) {
230
+ const params = new URLSearchParams();
231
+ if (request.environment) params.set("environment", request.environment);
232
+ if (request.projectId) params.set("projectId", request.projectId);
233
+ const query = params.toString();
234
+ const path = `/webdata/extractions/${request.id}${query ? `?${query}` : ""}`;
235
+ const response = await this.http.get(path);
236
+ return this.convertExtractionDates(response);
237
+ }
238
+ /**
239
+ * List extractions with pagination and filters
240
+ *
241
+ * @example
242
+ * ```typescript
243
+ * const { items, nextCursor } = await webdata.listExtractions({
244
+ * status: 'completed',
245
+ * limit: 20,
246
+ * });
247
+ * ```
248
+ */
249
+ async listExtractions(request = {}) {
250
+ const params = new URLSearchParams();
251
+ if (request.environment) params.set("environment", request.environment);
252
+ if (request.projectId) params.set("projectId", request.projectId);
253
+ if (request.status) params.set("status", request.status);
254
+ if (request.url) params.set("url", request.url);
255
+ if (request.limit) params.set("limit", request.limit.toString());
256
+ if (request.cursor) params.set("cursor", request.cursor);
257
+ const query = params.toString();
258
+ const response = await this.http.get(
259
+ `/webdata/extractions${query ? `?${query}` : ""}`
260
+ );
261
+ return {
262
+ ...response,
263
+ items: response.items.map((item) => this.convertExtractionDates(item))
264
+ };
265
+ }
266
+ /**
267
+ * Delete an extraction
268
+ *
269
+ * @example
270
+ * ```typescript
271
+ * await webdata.deleteExtraction({ id: 'extraction-id' });
272
+ * ```
273
+ */
274
+ async deleteExtraction(request) {
275
+ const params = new URLSearchParams();
276
+ if (request.environment) params.set("environment", request.environment);
277
+ if (request.projectId) params.set("projectId", request.projectId);
278
+ const query = params.toString();
279
+ return this.http.delete(
280
+ `/webdata/extractions/${request.id}${query ? `?${query}` : ""}`
281
+ );
282
+ }
283
+ /**
284
+ * Extract content and wait for completion
285
+ *
286
+ * @example
287
+ * ```typescript
288
+ * const extraction = await webdata.extractAndWait({
289
+ * url: 'https://example.com/article',
290
+ * mode: 'markdown',
291
+ * });
292
+ * console.log(extraction.markdown);
293
+ * ```
294
+ */
295
+ async extractAndWait(request, options = {}) {
296
+ const { pollInterval = 1e3, timeout = 6e4 } = options;
297
+ const startTime = Date.now();
298
+ const { id } = await this.extract(request);
299
+ while (Date.now() - startTime < timeout) {
300
+ const extraction = await this.getExtraction({
301
+ id,
302
+ environment: request.environment,
303
+ projectId: request.projectId
304
+ });
305
+ if (extraction.status === "completed" || extraction.status === "failed") {
306
+ if (extraction.status === "failed") {
307
+ throw new Error(extraction.error || "Extraction failed");
308
+ }
309
+ return extraction;
310
+ }
311
+ await new Promise((resolve) => setTimeout(resolve, pollInterval));
312
+ }
313
+ throw new Error("Extraction timed out");
314
+ }
315
+ // ==========================================================================
316
+ // SCHEDULES
317
+ // ==========================================================================
318
+ /**
319
+ * Create a scheduled screenshot or extraction job
320
+ *
321
+ * @example
322
+ * ```typescript
323
+ * const { id } = await webdata.createSchedule({
324
+ * name: 'Daily homepage screenshot',
325
+ * url: 'https://example.com',
326
+ * type: 'screenshot',
327
+ * frequency: 'daily',
328
+ * config: { format: 'png', fullPage: true },
329
+ * });
330
+ * ```
331
+ */
332
+ async createSchedule(request) {
333
+ return this.http.post("/webdata/schedules", request);
334
+ }
335
+ /**
336
+ * Update a schedule
337
+ *
338
+ * @example
339
+ * ```typescript
340
+ * await webdata.updateSchedule({
341
+ * id: 'schedule-id',
342
+ * frequency: 'weekly',
343
+ * isActive: false,
344
+ * });
345
+ * ```
346
+ */
347
+ async updateSchedule(request) {
348
+ const { id, environment, projectId, ...data } = request;
349
+ const params = new URLSearchParams();
350
+ if (environment) params.set("environment", environment);
351
+ if (projectId) params.set("projectId", projectId);
352
+ const query = params.toString();
353
+ return this.http.post(
354
+ `/webdata/schedules/${id}${query ? `?${query}` : ""}`,
355
+ data
356
+ );
357
+ }
358
+ /**
359
+ * Get a schedule by ID
360
+ *
361
+ * @example
362
+ * ```typescript
363
+ * const schedule = await webdata.getSchedule({ id: 'schedule-id' });
364
+ * console.log(schedule.nextRunAt);
365
+ * ```
366
+ */
367
+ async getSchedule(request) {
368
+ const params = new URLSearchParams();
369
+ if (request.environment) params.set("environment", request.environment);
370
+ if (request.projectId) params.set("projectId", request.projectId);
371
+ const query = params.toString();
372
+ const path = `/webdata/schedules/${request.id}${query ? `?${query}` : ""}`;
373
+ const response = await this.http.get(path);
374
+ return this.convertScheduleDates(response);
375
+ }
376
+ /**
377
+ * List schedules with pagination and filters
378
+ *
379
+ * @example
380
+ * ```typescript
381
+ * const { items, nextCursor } = await webdata.listSchedules({
382
+ * type: 'screenshot',
383
+ * isActive: true,
384
+ * });
385
+ * ```
386
+ */
387
+ async listSchedules(request = {}) {
388
+ const params = new URLSearchParams();
389
+ if (request.environment) params.set("environment", request.environment);
390
+ if (request.projectId) params.set("projectId", request.projectId);
391
+ if (request.type) params.set("type", request.type);
392
+ if (request.isActive !== void 0) params.set("isActive", request.isActive.toString());
393
+ if (request.limit) params.set("limit", request.limit.toString());
394
+ if (request.cursor) params.set("cursor", request.cursor);
395
+ const query = params.toString();
396
+ const response = await this.http.get(
397
+ `/webdata/schedules${query ? `?${query}` : ""}`
398
+ );
399
+ return {
400
+ ...response,
401
+ items: response.items.map((item) => this.convertScheduleDates(item))
402
+ };
403
+ }
404
+ /**
405
+ * Delete a schedule
406
+ *
407
+ * @example
408
+ * ```typescript
409
+ * await webdata.deleteSchedule({ id: 'schedule-id' });
410
+ * ```
411
+ */
412
+ async deleteSchedule(request) {
413
+ const params = new URLSearchParams();
414
+ if (request.environment) params.set("environment", request.environment);
415
+ if (request.projectId) params.set("projectId", request.projectId);
416
+ const query = params.toString();
417
+ return this.http.delete(
418
+ `/webdata/schedules/${request.id}${query ? `?${query}` : ""}`
419
+ );
420
+ }
421
+ /**
422
+ * Toggle a schedule on or off
423
+ *
424
+ * @example
425
+ * ```typescript
426
+ * const { isActive } = await webdata.toggleSchedule({ id: 'schedule-id' });
427
+ * console.log(`Schedule is now ${isActive ? 'active' : 'paused'}`);
428
+ * ```
429
+ */
430
+ async toggleSchedule(request) {
431
+ const params = new URLSearchParams();
432
+ if (request.environment) params.set("environment", request.environment);
433
+ if (request.projectId) params.set("projectId", request.projectId);
434
+ const query = params.toString();
435
+ return this.http.post(
436
+ `/webdata/schedules/${request.id}/toggle${query ? `?${query}` : ""}`,
437
+ {}
438
+ );
439
+ }
440
+ // ==========================================================================
441
+ // USAGE
442
+ // ==========================================================================
443
+ /**
444
+ * Get usage statistics
445
+ *
446
+ * @example
447
+ * ```typescript
448
+ * const usage = await webdata.getUsage({
449
+ * periodStart: '2024-01-01T00:00:00Z',
450
+ * periodEnd: '2024-01-31T23:59:59Z',
451
+ * });
452
+ * console.log(`Screenshots: ${usage.screenshotsTotal}`);
453
+ * console.log(`Extractions: ${usage.extractionsTotal}`);
454
+ * ```
455
+ */
456
+ async getUsage(request = {}) {
457
+ const params = new URLSearchParams();
458
+ if (request.environment) params.set("environment", request.environment);
459
+ if (request.periodStart) params.set("periodStart", request.periodStart);
460
+ if (request.periodEnd) params.set("periodEnd", request.periodEnd);
461
+ const query = params.toString();
462
+ const response = await this.http.get(
463
+ `/webdata/usage${query ? `?${query}` : ""}`
464
+ );
465
+ return this.convertUsageDates(response);
466
+ }
467
+ // ==========================================================================
468
+ // BATCH JOBS
469
+ // ==========================================================================
470
+ /**
471
+ * Create a batch screenshot job for multiple URLs
472
+ *
473
+ * @example
474
+ * ```typescript
475
+ * const { id, totalUrls } = await webdata.batchScreenshots({
476
+ * urls: [
477
+ * 'https://example.com',
478
+ * 'https://example.org',
479
+ * ],
480
+ * config: { format: 'png', fullPage: true },
481
+ * });
482
+ *
483
+ * // Poll for completion
484
+ * const job = await webdata.getBatchJob({ id });
485
+ * console.log(`Progress: ${job.processedUrls}/${job.totalUrls}`);
486
+ * ```
487
+ */
488
+ async batchScreenshots(request) {
489
+ return this.http.post("/webdata/batch/screenshots", request);
490
+ }
491
+ /**
492
+ * Create a batch extraction job for multiple URLs
493
+ *
494
+ * @example
495
+ * ```typescript
496
+ * const { id, totalUrls } = await webdata.batchExtractions({
497
+ * urls: [
498
+ * 'https://example.com/article1',
499
+ * 'https://example.com/article2',
500
+ * ],
501
+ * config: { mode: 'markdown' },
502
+ * });
503
+ * ```
504
+ */
505
+ async batchExtractions(request) {
506
+ return this.http.post("/webdata/batch/extractions", request);
507
+ }
508
+ /**
509
+ * Get a batch job by ID
510
+ *
511
+ * @example
512
+ * ```typescript
513
+ * const job = await webdata.getBatchJob({ id: 'batch-id' });
514
+ * console.log(`Status: ${job.status}`);
515
+ * console.log(`Progress: ${job.processedUrls}/${job.totalUrls}`);
516
+ * ```
517
+ */
518
+ async getBatchJob(request) {
519
+ const params = new URLSearchParams();
520
+ if (request.environment) params.set("environment", request.environment);
521
+ if (request.projectId) params.set("projectId", request.projectId);
522
+ const query = params.toString();
523
+ const path = `/webdata/batch/${request.id}${query ? `?${query}` : ""}`;
524
+ const response = await this.http.get(path);
525
+ return this.convertBatchJobDates(response);
526
+ }
527
+ /**
528
+ * List batch jobs with pagination and filters
529
+ *
530
+ * @example
531
+ * ```typescript
532
+ * const { items, nextCursor } = await webdata.listBatchJobs({
533
+ * status: 'completed',
534
+ * type: 'screenshot',
535
+ * limit: 20,
536
+ * });
537
+ * ```
538
+ */
539
+ async listBatchJobs(request = {}) {
540
+ const params = new URLSearchParams();
541
+ if (request.environment) params.set("environment", request.environment);
542
+ if (request.projectId) params.set("projectId", request.projectId);
543
+ if (request.status) params.set("status", request.status);
544
+ if (request.type) params.set("type", request.type);
545
+ if (request.limit) params.set("limit", request.limit.toString());
546
+ if (request.cursor) params.set("cursor", request.cursor);
547
+ const query = params.toString();
548
+ const response = await this.http.get(
549
+ `/webdata/batch${query ? `?${query}` : ""}`
550
+ );
551
+ return {
552
+ ...response,
553
+ items: response.items.map((item) => this.convertBatchJobDates(item))
554
+ };
555
+ }
556
+ /**
557
+ * Cancel a batch job
558
+ *
559
+ * @example
560
+ * ```typescript
561
+ * await webdata.cancelBatchJob({ id: 'batch-id' });
562
+ * ```
563
+ */
564
+ async cancelBatchJob(request) {
565
+ const params = new URLSearchParams();
566
+ if (request.environment) params.set("environment", request.environment);
567
+ if (request.projectId) params.set("projectId", request.projectId);
568
+ const query = params.toString();
569
+ return this.http.post(
570
+ `/webdata/batch/${request.id}/cancel${query ? `?${query}` : ""}`,
571
+ {}
572
+ );
573
+ }
574
+ /**
575
+ * Create a batch screenshot job and wait for completion
576
+ *
577
+ * @example
578
+ * ```typescript
579
+ * const job = await webdata.batchScreenshotsAndWait({
580
+ * urls: ['https://example.com', 'https://example.org'],
581
+ * config: { format: 'png' },
582
+ * });
583
+ * console.log(`Completed: ${job.successfulUrls} successful, ${job.failedUrls} failed`);
584
+ * ```
585
+ */
586
+ async batchScreenshotsAndWait(request, options = {}) {
587
+ const { pollInterval = 2e3, timeout = 3e5 } = options;
588
+ const startTime = Date.now();
589
+ const { id } = await this.batchScreenshots(request);
590
+ while (Date.now() - startTime < timeout) {
591
+ const job = await this.getBatchJob({
592
+ id,
593
+ environment: request.environment,
594
+ projectId: request.projectId
595
+ });
596
+ if (job.status === "completed" || job.status === "failed" || job.status === "cancelled") {
597
+ return job;
598
+ }
599
+ await new Promise((resolve) => setTimeout(resolve, pollInterval));
600
+ }
601
+ throw new Error("Batch job timed out");
602
+ }
603
+ /**
604
+ * Create a batch extraction job and wait for completion
605
+ *
606
+ * @example
607
+ * ```typescript
608
+ * const job = await webdata.batchExtractionsAndWait({
609
+ * urls: ['https://example.com/article1', 'https://example.com/article2'],
610
+ * config: { mode: 'markdown' },
611
+ * });
612
+ * console.log(`Completed: ${job.successfulUrls} successful`);
613
+ * ```
614
+ */
615
+ async batchExtractionsAndWait(request, options = {}) {
616
+ const { pollInterval = 2e3, timeout = 3e5 } = options;
617
+ const startTime = Date.now();
618
+ const { id } = await this.batchExtractions(request);
619
+ while (Date.now() - startTime < timeout) {
620
+ const job = await this.getBatchJob({
621
+ id,
622
+ environment: request.environment,
623
+ projectId: request.projectId
624
+ });
625
+ if (job.status === "completed" || job.status === "failed" || job.status === "cancelled") {
626
+ return job;
627
+ }
628
+ await new Promise((resolve) => setTimeout(resolve, pollInterval));
629
+ }
630
+ throw new Error("Batch job timed out");
631
+ }
632
+ // ==========================================================================
633
+ // HELPERS
634
+ // ==========================================================================
635
+ convertScreenshotDates(screenshot) {
636
+ if (typeof screenshot.createdAt === "string") {
637
+ screenshot.createdAt = new Date(screenshot.createdAt);
638
+ }
639
+ if (screenshot.completedAt && typeof screenshot.completedAt === "string") {
640
+ screenshot.completedAt = new Date(screenshot.completedAt);
641
+ }
642
+ return screenshot;
643
+ }
644
+ convertExtractionDates(extraction) {
645
+ if (typeof extraction.createdAt === "string") {
646
+ extraction.createdAt = new Date(extraction.createdAt);
647
+ }
648
+ if (extraction.completedAt && typeof extraction.completedAt === "string") {
649
+ extraction.completedAt = new Date(extraction.completedAt);
650
+ }
651
+ return extraction;
652
+ }
653
+ convertScheduleDates(schedule) {
654
+ if (typeof schedule.createdAt === "string") {
655
+ schedule.createdAt = new Date(schedule.createdAt);
656
+ }
657
+ if (typeof schedule.updatedAt === "string") {
658
+ schedule.updatedAt = new Date(schedule.updatedAt);
659
+ }
660
+ if (schedule.lastRunAt && typeof schedule.lastRunAt === "string") {
661
+ schedule.lastRunAt = new Date(schedule.lastRunAt);
662
+ }
663
+ if (schedule.nextRunAt && typeof schedule.nextRunAt === "string") {
664
+ schedule.nextRunAt = new Date(schedule.nextRunAt);
665
+ }
666
+ return schedule;
667
+ }
668
+ convertUsageDates(usage) {
669
+ if (typeof usage.periodStart === "string") {
670
+ usage.periodStart = new Date(usage.periodStart);
671
+ }
672
+ if (typeof usage.periodEnd === "string") {
673
+ usage.periodEnd = new Date(usage.periodEnd);
674
+ }
675
+ return usage;
676
+ }
677
+ convertBatchJobDates(job) {
678
+ if (typeof job.createdAt === "string") {
679
+ job.createdAt = new Date(job.createdAt);
680
+ }
681
+ if (job.startedAt && typeof job.startedAt === "string") {
682
+ job.startedAt = new Date(job.startedAt);
683
+ }
684
+ if (job.completedAt && typeof job.completedAt === "string") {
685
+ job.completedAt = new Date(job.completedAt);
686
+ }
687
+ return job;
688
+ }
689
+ };
690
+
691
+ exports.Webdata = Webdata;
692
+ //# sourceMappingURL=index.js.map
693
+ //# sourceMappingURL=index.js.map