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