@stack0/sdk 0.2.8 → 0.2.9

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,421 @@
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.dev/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
+ async patch(path, body) {
66
+ return this.request("PATCH", path, body);
67
+ }
68
+ };
69
+
70
+ // src/screenshots/client.ts
71
+ var Screenshots = class {
72
+ http;
73
+ constructor(config) {
74
+ this.http = new HttpClient(config);
75
+ }
76
+ // ==========================================================================
77
+ // SCREENSHOTS
78
+ // ==========================================================================
79
+ /**
80
+ * Capture a screenshot of a URL
81
+ *
82
+ * @example
83
+ * ```typescript
84
+ * const { id, status } = await screenshots.capture({
85
+ * url: 'https://example.com',
86
+ * format: 'png',
87
+ * fullPage: true,
88
+ * deviceType: 'desktop',
89
+ * });
90
+ *
91
+ * // Poll for completion
92
+ * const screenshot = await screenshots.get({ id });
93
+ * console.log(screenshot.imageUrl);
94
+ * ```
95
+ */
96
+ async capture(request) {
97
+ return this.http.post("/webdata/screenshots", request);
98
+ }
99
+ /**
100
+ * Get a screenshot by ID
101
+ *
102
+ * @example
103
+ * ```typescript
104
+ * const screenshot = await screenshots.get({ id: 'screenshot-id' });
105
+ * if (screenshot.status === 'completed') {
106
+ * console.log(screenshot.imageUrl);
107
+ * }
108
+ * ```
109
+ */
110
+ async get(request) {
111
+ const params = new URLSearchParams();
112
+ if (request.environment) params.set("environment", request.environment);
113
+ if (request.projectId) params.set("projectId", request.projectId);
114
+ const query = params.toString();
115
+ const path = `/webdata/screenshots/${request.id}${query ? `?${query}` : ""}`;
116
+ const response = await this.http.get(path);
117
+ return this.convertDates(response);
118
+ }
119
+ /**
120
+ * List screenshots with pagination and filters
121
+ *
122
+ * @example
123
+ * ```typescript
124
+ * const { items, nextCursor } = await screenshots.list({
125
+ * status: 'completed',
126
+ * limit: 20,
127
+ * });
128
+ * ```
129
+ */
130
+ async list(request = {}) {
131
+ const params = new URLSearchParams();
132
+ if (request.environment) params.set("environment", request.environment);
133
+ if (request.projectId) params.set("projectId", request.projectId);
134
+ if (request.status) params.set("status", request.status);
135
+ if (request.url) params.set("url", request.url);
136
+ if (request.limit) params.set("limit", request.limit.toString());
137
+ if (request.cursor) params.set("cursor", request.cursor);
138
+ const query = params.toString();
139
+ const response = await this.http.get(
140
+ `/webdata/screenshots${query ? `?${query}` : ""}`
141
+ );
142
+ return {
143
+ ...response,
144
+ items: response.items.map((item) => this.convertDates(item))
145
+ };
146
+ }
147
+ /**
148
+ * Delete a screenshot
149
+ *
150
+ * @example
151
+ * ```typescript
152
+ * await screenshots.delete({ id: 'screenshot-id' });
153
+ * ```
154
+ */
155
+ async delete(request) {
156
+ const params = new URLSearchParams();
157
+ if (request.environment) params.set("environment", request.environment);
158
+ if (request.projectId) params.set("projectId", request.projectId);
159
+ const query = params.toString();
160
+ return this.http.delete(
161
+ `/webdata/screenshots/${request.id}${query ? `?${query}` : ""}`
162
+ );
163
+ }
164
+ /**
165
+ * Capture a screenshot and wait for completion
166
+ *
167
+ * @example
168
+ * ```typescript
169
+ * const screenshot = await screenshots.captureAndWait({
170
+ * url: 'https://example.com',
171
+ * format: 'png',
172
+ * });
173
+ * console.log(screenshot.imageUrl);
174
+ * ```
175
+ */
176
+ async captureAndWait(request, options = {}) {
177
+ const { pollInterval = 1e3, timeout = 6e4 } = options;
178
+ const startTime = Date.now();
179
+ const { id } = await this.capture(request);
180
+ while (Date.now() - startTime < timeout) {
181
+ const screenshot = await this.get({
182
+ id,
183
+ environment: request.environment,
184
+ projectId: request.projectId
185
+ });
186
+ if (screenshot.status === "completed" || screenshot.status === "failed") {
187
+ if (screenshot.status === "failed") {
188
+ throw new Error(screenshot.error || "Screenshot failed");
189
+ }
190
+ return screenshot;
191
+ }
192
+ await new Promise((resolve) => setTimeout(resolve, pollInterval));
193
+ }
194
+ throw new Error("Screenshot timed out");
195
+ }
196
+ // ==========================================================================
197
+ // BATCH JOBS
198
+ // ==========================================================================
199
+ /**
200
+ * Create a batch screenshot job for multiple URLs
201
+ *
202
+ * @example
203
+ * ```typescript
204
+ * const { id, totalUrls } = await screenshots.batch({
205
+ * urls: [
206
+ * 'https://example.com',
207
+ * 'https://example.org',
208
+ * ],
209
+ * config: { format: 'png', fullPage: true },
210
+ * });
211
+ *
212
+ * // Poll for completion
213
+ * const job = await screenshots.getBatchJob({ id });
214
+ * console.log(`Progress: ${job.processedUrls}/${job.totalUrls}`);
215
+ * ```
216
+ */
217
+ async batch(request) {
218
+ return this.http.post("/webdata/batch/screenshots", request);
219
+ }
220
+ /**
221
+ * Get a batch job by ID
222
+ */
223
+ async getBatchJob(request) {
224
+ const params = new URLSearchParams();
225
+ if (request.environment) params.set("environment", request.environment);
226
+ if (request.projectId) params.set("projectId", request.projectId);
227
+ const query = params.toString();
228
+ const path = `/webdata/batch/${request.id}${query ? `?${query}` : ""}`;
229
+ const response = await this.http.get(path);
230
+ return this.convertBatchJobDates(response);
231
+ }
232
+ /**
233
+ * List batch jobs with pagination and filters
234
+ */
235
+ async listBatchJobs(request = {}) {
236
+ const params = new URLSearchParams();
237
+ if (request.environment) params.set("environment", request.environment);
238
+ if (request.projectId) params.set("projectId", request.projectId);
239
+ if (request.status) params.set("status", request.status);
240
+ params.set("type", "screenshot");
241
+ if (request.limit) params.set("limit", request.limit.toString());
242
+ if (request.cursor) params.set("cursor", request.cursor);
243
+ const query = params.toString();
244
+ const response = await this.http.get(
245
+ `/webdata/batch${query ? `?${query}` : ""}`
246
+ );
247
+ return {
248
+ ...response,
249
+ items: response.items.map((item) => this.convertBatchJobDates(item))
250
+ };
251
+ }
252
+ /**
253
+ * Cancel a batch job
254
+ */
255
+ async cancelBatchJob(request) {
256
+ const params = new URLSearchParams();
257
+ if (request.environment) params.set("environment", request.environment);
258
+ if (request.projectId) params.set("projectId", request.projectId);
259
+ const query = params.toString();
260
+ return this.http.post(
261
+ `/webdata/batch/${request.id}/cancel${query ? `?${query}` : ""}`,
262
+ {}
263
+ );
264
+ }
265
+ /**
266
+ * Create a batch screenshot job and wait for completion
267
+ */
268
+ async batchAndWait(request, options = {}) {
269
+ const { pollInterval = 2e3, timeout = 3e5 } = options;
270
+ const startTime = Date.now();
271
+ const { id } = await this.batch(request);
272
+ while (Date.now() - startTime < timeout) {
273
+ const job = await this.getBatchJob({
274
+ id,
275
+ environment: request.environment,
276
+ projectId: request.projectId
277
+ });
278
+ if (job.status === "completed" || job.status === "failed" || job.status === "cancelled") {
279
+ return job;
280
+ }
281
+ await new Promise((resolve) => setTimeout(resolve, pollInterval));
282
+ }
283
+ throw new Error("Batch job timed out");
284
+ }
285
+ // ==========================================================================
286
+ // SCHEDULES
287
+ // ==========================================================================
288
+ /**
289
+ * Create a scheduled screenshot job
290
+ *
291
+ * @example
292
+ * ```typescript
293
+ * const { id } = await screenshots.createSchedule({
294
+ * name: 'Daily homepage screenshot',
295
+ * url: 'https://example.com',
296
+ * frequency: 'daily',
297
+ * config: { format: 'png', fullPage: true },
298
+ * });
299
+ * ```
300
+ */
301
+ async createSchedule(request) {
302
+ return this.http.post("/webdata/schedules", {
303
+ ...request,
304
+ type: "screenshot"
305
+ });
306
+ }
307
+ /**
308
+ * Update a schedule
309
+ */
310
+ async updateSchedule(request) {
311
+ const { id, environment, projectId, ...data } = request;
312
+ const params = new URLSearchParams();
313
+ if (environment) params.set("environment", environment);
314
+ if (projectId) params.set("projectId", projectId);
315
+ const query = params.toString();
316
+ return this.http.post(
317
+ `/webdata/schedules/${id}${query ? `?${query}` : ""}`,
318
+ data
319
+ );
320
+ }
321
+ /**
322
+ * Get a schedule by ID
323
+ */
324
+ async getSchedule(request) {
325
+ const params = new URLSearchParams();
326
+ if (request.environment) params.set("environment", request.environment);
327
+ if (request.projectId) params.set("projectId", request.projectId);
328
+ const query = params.toString();
329
+ const path = `/webdata/schedules/${request.id}${query ? `?${query}` : ""}`;
330
+ const response = await this.http.get(path);
331
+ return this.convertScheduleDates(response);
332
+ }
333
+ /**
334
+ * List schedules with pagination and filters
335
+ */
336
+ async listSchedules(request = {}) {
337
+ const params = new URLSearchParams();
338
+ if (request.environment) params.set("environment", request.environment);
339
+ if (request.projectId) params.set("projectId", request.projectId);
340
+ params.set("type", "screenshot");
341
+ if (request.isActive !== void 0) params.set("isActive", request.isActive.toString());
342
+ if (request.limit) params.set("limit", request.limit.toString());
343
+ if (request.cursor) params.set("cursor", request.cursor);
344
+ const query = params.toString();
345
+ const response = await this.http.get(
346
+ `/webdata/schedules${query ? `?${query}` : ""}`
347
+ );
348
+ return {
349
+ ...response,
350
+ items: response.items.map((item) => this.convertScheduleDates(item))
351
+ };
352
+ }
353
+ /**
354
+ * Delete a schedule
355
+ */
356
+ async deleteSchedule(request) {
357
+ const params = new URLSearchParams();
358
+ if (request.environment) params.set("environment", request.environment);
359
+ if (request.projectId) params.set("projectId", request.projectId);
360
+ const query = params.toString();
361
+ return this.http.delete(
362
+ `/webdata/schedules/${request.id}${query ? `?${query}` : ""}`
363
+ );
364
+ }
365
+ /**
366
+ * Toggle a schedule on or off
367
+ */
368
+ async toggleSchedule(request) {
369
+ const params = new URLSearchParams();
370
+ if (request.environment) params.set("environment", request.environment);
371
+ if (request.projectId) params.set("projectId", request.projectId);
372
+ const query = params.toString();
373
+ return this.http.post(
374
+ `/webdata/schedules/${request.id}/toggle${query ? `?${query}` : ""}`,
375
+ {}
376
+ );
377
+ }
378
+ // ==========================================================================
379
+ // HELPERS
380
+ // ==========================================================================
381
+ convertDates(screenshot) {
382
+ if (typeof screenshot.createdAt === "string") {
383
+ screenshot.createdAt = new Date(screenshot.createdAt);
384
+ }
385
+ if (screenshot.completedAt && typeof screenshot.completedAt === "string") {
386
+ screenshot.completedAt = new Date(screenshot.completedAt);
387
+ }
388
+ return screenshot;
389
+ }
390
+ convertBatchJobDates(job) {
391
+ if (typeof job.createdAt === "string") {
392
+ job.createdAt = new Date(job.createdAt);
393
+ }
394
+ if (job.startedAt && typeof job.startedAt === "string") {
395
+ job.startedAt = new Date(job.startedAt);
396
+ }
397
+ if (job.completedAt && typeof job.completedAt === "string") {
398
+ job.completedAt = new Date(job.completedAt);
399
+ }
400
+ return job;
401
+ }
402
+ convertScheduleDates(schedule) {
403
+ if (typeof schedule.createdAt === "string") {
404
+ schedule.createdAt = new Date(schedule.createdAt);
405
+ }
406
+ if (typeof schedule.updatedAt === "string") {
407
+ schedule.updatedAt = new Date(schedule.updatedAt);
408
+ }
409
+ if (schedule.lastRunAt && typeof schedule.lastRunAt === "string") {
410
+ schedule.lastRunAt = new Date(schedule.lastRunAt);
411
+ }
412
+ if (schedule.nextRunAt && typeof schedule.nextRunAt === "string") {
413
+ schedule.nextRunAt = new Date(schedule.nextRunAt);
414
+ }
415
+ return schedule;
416
+ }
417
+ };
418
+
419
+ export { Screenshots };
420
+ //# sourceMappingURL=index.mjs.map
421
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/lib/http-client.ts","../../src/screenshots/client.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * HTTP client for Stack0 API\n * Handles authentication, request/response formatting, and error handling\n */\n\nexport interface HttpClientConfig {\n apiKey: string;\n baseUrl?: string;\n}\n\nexport class HttpClient {\n private apiKey: string;\n private baseUrl: string;\n\n constructor(config: HttpClientConfig) {\n this.apiKey = config.apiKey;\n this.baseUrl = config.baseUrl || \"https://api.stack0.dev/v1\";\n }\n\n private getHeaders(): Record<string, string> {\n return {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${this.apiKey}`,\n };\n }\n\n async request<T>(method: string, path: string, body?: unknown): Promise<T> {\n const url = `${this.baseUrl}${path}`;\n\n try {\n const response = await fetch(url, {\n method,\n headers: this.getHeaders(),\n body: body ? JSON.stringify(body) : undefined,\n });\n\n if (!response.ok) {\n await this.handleErrorResponse(response);\n }\n\n const data = await response.json();\n return data as T;\n } catch (error) {\n if (error instanceof Error && \"statusCode\" in error) {\n throw error; // Re-throw our custom errors\n }\n throw this.createError(\"Network error\", error);\n }\n }\n\n private async handleErrorResponse(response: Response): Promise<never> {\n let errorBody: { message: string } | undefined;\n try {\n errorBody = (await response.json()) as { message: string };\n } catch {\n errorBody = { message: response.statusText };\n }\n\n const error = new Error(errorBody?.message || `HTTP ${response.status}`) as Error & {\n statusCode: number;\n code: string;\n response: unknown;\n };\n error.statusCode = response.status;\n error.code = (errorBody as unknown as { code: string } | undefined)?.code ?? \"\";\n error.response = errorBody;\n throw error;\n }\n\n private createError(message: string, cause?: unknown): Error {\n const error = new Error(message) as Error & { cause: unknown };\n error.cause = cause;\n return error;\n }\n\n async get<T>(path: string): Promise<T> {\n return this.request<T>(\"GET\", path);\n }\n\n async post<T>(path: string, body: unknown): Promise<T> {\n return this.request<T>(\"POST\", path, body);\n }\n\n async put<T>(path: string, body: unknown): Promise<T> {\n return this.request<T>(\"PUT\", path, body);\n }\n\n async delete<T>(path: string): Promise<T> {\n return this.request<T>(\"DELETE\", path);\n }\n\n async patch<T>(path: string, body: unknown): Promise<T> {\n return this.request<T>(\"PATCH\", path, body);\n }\n}\n","/**\n * Stack0 Screenshots Client\n * Capture high-quality screenshots of any webpage\n */\n\nimport { HttpClient, type HttpClientConfig } from \"../lib/http-client\";\nimport type {\n CreateBatchResponse,\n GetBatchJobRequest,\n ListBatchJobsRequest,\n CreateScheduleResponse,\n GetScheduleRequest,\n ListSchedulesRequest,\n} from \"../lib/shared-types\";\nimport type {\n Screenshot,\n CreateScreenshotRequest,\n CreateScreenshotResponse,\n GetScreenshotRequest,\n ListScreenshotsRequest,\n ListScreenshotsResponse,\n BatchScreenshotJob,\n CreateBatchScreenshotsRequest,\n ScreenshotBatchJobsResponse,\n ScreenshotSchedule,\n CreateScreenshotScheduleRequest,\n UpdateScreenshotScheduleRequest,\n ScreenshotSchedulesResponse,\n} from \"./types\";\n\nexport class Screenshots {\n private http: HttpClient;\n\n constructor(config: HttpClientConfig) {\n this.http = new HttpClient(config);\n }\n\n // ==========================================================================\n // SCREENSHOTS\n // ==========================================================================\n\n /**\n * Capture a screenshot of a URL\n *\n * @example\n * ```typescript\n * const { id, status } = await screenshots.capture({\n * url: 'https://example.com',\n * format: 'png',\n * fullPage: true,\n * deviceType: 'desktop',\n * });\n *\n * // Poll for completion\n * const screenshot = await screenshots.get({ id });\n * console.log(screenshot.imageUrl);\n * ```\n */\n async capture(request: CreateScreenshotRequest): Promise<CreateScreenshotResponse> {\n return this.http.post<CreateScreenshotResponse>(\"/webdata/screenshots\", request);\n }\n\n /**\n * Get a screenshot by ID\n *\n * @example\n * ```typescript\n * const screenshot = await screenshots.get({ id: 'screenshot-id' });\n * if (screenshot.status === 'completed') {\n * console.log(screenshot.imageUrl);\n * }\n * ```\n */\n async get(request: GetScreenshotRequest): Promise<Screenshot> {\n const params = new URLSearchParams();\n if (request.environment) params.set(\"environment\", request.environment);\n if (request.projectId) params.set(\"projectId\", request.projectId);\n\n const query = params.toString();\n const path = `/webdata/screenshots/${request.id}${query ? `?${query}` : \"\"}`;\n\n const response = await this.http.get<Screenshot>(path);\n return this.convertDates(response);\n }\n\n /**\n * List screenshots with pagination and filters\n *\n * @example\n * ```typescript\n * const { items, nextCursor } = await screenshots.list({\n * status: 'completed',\n * limit: 20,\n * });\n * ```\n */\n async list(request: ListScreenshotsRequest = {}): Promise<ListScreenshotsResponse> {\n const params = new URLSearchParams();\n\n if (request.environment) params.set(\"environment\", request.environment);\n if (request.projectId) params.set(\"projectId\", request.projectId);\n if (request.status) params.set(\"status\", request.status);\n if (request.url) params.set(\"url\", request.url);\n if (request.limit) params.set(\"limit\", request.limit.toString());\n if (request.cursor) params.set(\"cursor\", request.cursor);\n\n const query = params.toString();\n const response = await this.http.get<ListScreenshotsResponse>(\n `/webdata/screenshots${query ? `?${query}` : \"\"}`\n );\n\n return {\n ...response,\n items: response.items.map((item) => this.convertDates(item)),\n };\n }\n\n /**\n * Delete a screenshot\n *\n * @example\n * ```typescript\n * await screenshots.delete({ id: 'screenshot-id' });\n * ```\n */\n async delete(request: GetScreenshotRequest): Promise<{ success: boolean }> {\n const params = new URLSearchParams();\n if (request.environment) params.set(\"environment\", request.environment);\n if (request.projectId) params.set(\"projectId\", request.projectId);\n\n const query = params.toString();\n return this.http.delete<{ success: boolean }>(\n `/webdata/screenshots/${request.id}${query ? `?${query}` : \"\"}`\n );\n }\n\n /**\n * Capture a screenshot and wait for completion\n *\n * @example\n * ```typescript\n * const screenshot = await screenshots.captureAndWait({\n * url: 'https://example.com',\n * format: 'png',\n * });\n * console.log(screenshot.imageUrl);\n * ```\n */\n async captureAndWait(\n request: CreateScreenshotRequest,\n options: { pollInterval?: number; timeout?: number } = {}\n ): Promise<Screenshot> {\n const { pollInterval = 1000, timeout = 60000 } = options;\n const startTime = Date.now();\n\n const { id } = await this.capture(request);\n\n while (Date.now() - startTime < timeout) {\n const screenshot = await this.get({\n id,\n environment: request.environment,\n projectId: request.projectId,\n });\n\n if (screenshot.status === \"completed\" || screenshot.status === \"failed\") {\n if (screenshot.status === \"failed\") {\n throw new Error(screenshot.error || \"Screenshot failed\");\n }\n return screenshot;\n }\n\n await new Promise((resolve) => setTimeout(resolve, pollInterval));\n }\n\n throw new Error(\"Screenshot timed out\");\n }\n\n // ==========================================================================\n // BATCH JOBS\n // ==========================================================================\n\n /**\n * Create a batch screenshot job for multiple URLs\n *\n * @example\n * ```typescript\n * const { id, totalUrls } = await screenshots.batch({\n * urls: [\n * 'https://example.com',\n * 'https://example.org',\n * ],\n * config: { format: 'png', fullPage: true },\n * });\n *\n * // Poll for completion\n * const job = await screenshots.getBatchJob({ id });\n * console.log(`Progress: ${job.processedUrls}/${job.totalUrls}`);\n * ```\n */\n async batch(request: CreateBatchScreenshotsRequest): Promise<CreateBatchResponse> {\n return this.http.post<CreateBatchResponse>(\"/webdata/batch/screenshots\", request);\n }\n\n /**\n * Get a batch job by ID\n */\n async getBatchJob(request: GetBatchJobRequest): Promise<BatchScreenshotJob> {\n const params = new URLSearchParams();\n if (request.environment) params.set(\"environment\", request.environment);\n if (request.projectId) params.set(\"projectId\", request.projectId);\n\n const query = params.toString();\n const path = `/webdata/batch/${request.id}${query ? `?${query}` : \"\"}`;\n\n const response = await this.http.get<BatchScreenshotJob>(path);\n return this.convertBatchJobDates(response);\n }\n\n /**\n * List batch jobs with pagination and filters\n */\n async listBatchJobs(request: ListBatchJobsRequest = {}): Promise<ScreenshotBatchJobsResponse> {\n const params = new URLSearchParams();\n\n if (request.environment) params.set(\"environment\", request.environment);\n if (request.projectId) params.set(\"projectId\", request.projectId);\n if (request.status) params.set(\"status\", request.status);\n params.set(\"type\", \"screenshot\");\n if (request.limit) params.set(\"limit\", request.limit.toString());\n if (request.cursor) params.set(\"cursor\", request.cursor);\n\n const query = params.toString();\n const response = await this.http.get<ScreenshotBatchJobsResponse>(\n `/webdata/batch${query ? `?${query}` : \"\"}`\n );\n\n return {\n ...response,\n items: response.items.map((item) => this.convertBatchJobDates(item)),\n };\n }\n\n /**\n * Cancel a batch job\n */\n async cancelBatchJob(request: GetBatchJobRequest): Promise<{ success: boolean }> {\n const params = new URLSearchParams();\n if (request.environment) params.set(\"environment\", request.environment);\n if (request.projectId) params.set(\"projectId\", request.projectId);\n\n const query = params.toString();\n return this.http.post<{ success: boolean }>(\n `/webdata/batch/${request.id}/cancel${query ? `?${query}` : \"\"}`,\n {}\n );\n }\n\n /**\n * Create a batch screenshot job and wait for completion\n */\n async batchAndWait(\n request: CreateBatchScreenshotsRequest,\n options: { pollInterval?: number; timeout?: number } = {}\n ): Promise<BatchScreenshotJob> {\n const { pollInterval = 2000, timeout = 300000 } = options;\n const startTime = Date.now();\n\n const { id } = await this.batch(request);\n\n while (Date.now() - startTime < timeout) {\n const job = await this.getBatchJob({\n id,\n environment: request.environment,\n projectId: request.projectId,\n });\n\n if (job.status === \"completed\" || job.status === \"failed\" || job.status === \"cancelled\") {\n return job;\n }\n\n await new Promise((resolve) => setTimeout(resolve, pollInterval));\n }\n\n throw new Error(\"Batch job timed out\");\n }\n\n // ==========================================================================\n // SCHEDULES\n // ==========================================================================\n\n /**\n * Create a scheduled screenshot job\n *\n * @example\n * ```typescript\n * const { id } = await screenshots.createSchedule({\n * name: 'Daily homepage screenshot',\n * url: 'https://example.com',\n * frequency: 'daily',\n * config: { format: 'png', fullPage: true },\n * });\n * ```\n */\n async createSchedule(request: CreateScreenshotScheduleRequest): Promise<CreateScheduleResponse> {\n return this.http.post<CreateScheduleResponse>(\"/webdata/schedules\", {\n ...request,\n type: \"screenshot\",\n });\n }\n\n /**\n * Update a schedule\n */\n async updateSchedule(request: UpdateScreenshotScheduleRequest): Promise<{ success: boolean }> {\n const { id, environment, projectId, ...data } = request;\n\n const params = new URLSearchParams();\n if (environment) params.set(\"environment\", environment);\n if (projectId) params.set(\"projectId\", projectId);\n\n const query = params.toString();\n return this.http.post<{ success: boolean }>(\n `/webdata/schedules/${id}${query ? `?${query}` : \"\"}`,\n data\n );\n }\n\n /**\n * Get a schedule by ID\n */\n async getSchedule(request: GetScheduleRequest): Promise<ScreenshotSchedule> {\n const params = new URLSearchParams();\n if (request.environment) params.set(\"environment\", request.environment);\n if (request.projectId) params.set(\"projectId\", request.projectId);\n\n const query = params.toString();\n const path = `/webdata/schedules/${request.id}${query ? `?${query}` : \"\"}`;\n\n const response = await this.http.get<ScreenshotSchedule>(path);\n return this.convertScheduleDates(response);\n }\n\n /**\n * List schedules with pagination and filters\n */\n async listSchedules(request: ListSchedulesRequest = {}): Promise<ScreenshotSchedulesResponse> {\n const params = new URLSearchParams();\n\n if (request.environment) params.set(\"environment\", request.environment);\n if (request.projectId) params.set(\"projectId\", request.projectId);\n params.set(\"type\", \"screenshot\");\n if (request.isActive !== undefined) params.set(\"isActive\", request.isActive.toString());\n if (request.limit) params.set(\"limit\", request.limit.toString());\n if (request.cursor) params.set(\"cursor\", request.cursor);\n\n const query = params.toString();\n const response = await this.http.get<ScreenshotSchedulesResponse>(\n `/webdata/schedules${query ? `?${query}` : \"\"}`\n );\n\n return {\n ...response,\n items: response.items.map((item) => this.convertScheduleDates(item)),\n };\n }\n\n /**\n * Delete a schedule\n */\n async deleteSchedule(request: GetScheduleRequest): Promise<{ success: boolean }> {\n const params = new URLSearchParams();\n if (request.environment) params.set(\"environment\", request.environment);\n if (request.projectId) params.set(\"projectId\", request.projectId);\n\n const query = params.toString();\n return this.http.delete<{ success: boolean }>(\n `/webdata/schedules/${request.id}${query ? `?${query}` : \"\"}`\n );\n }\n\n /**\n * Toggle a schedule on or off\n */\n async toggleSchedule(request: GetScheduleRequest): Promise<{ isActive: boolean }> {\n const params = new URLSearchParams();\n if (request.environment) params.set(\"environment\", request.environment);\n if (request.projectId) params.set(\"projectId\", request.projectId);\n\n const query = params.toString();\n return this.http.post<{ isActive: boolean }>(\n `/webdata/schedules/${request.id}/toggle${query ? `?${query}` : \"\"}`,\n {}\n );\n }\n\n // ==========================================================================\n // HELPERS\n // ==========================================================================\n\n private convertDates(screenshot: Screenshot): Screenshot {\n if (typeof screenshot.createdAt === \"string\") {\n screenshot.createdAt = new Date(screenshot.createdAt);\n }\n if (screenshot.completedAt && typeof screenshot.completedAt === \"string\") {\n screenshot.completedAt = new Date(screenshot.completedAt);\n }\n return screenshot;\n }\n\n private convertBatchJobDates(job: BatchScreenshotJob): BatchScreenshotJob {\n if (typeof job.createdAt === \"string\") {\n job.createdAt = new Date(job.createdAt);\n }\n if (job.startedAt && typeof job.startedAt === \"string\") {\n job.startedAt = new Date(job.startedAt);\n }\n if (job.completedAt && typeof job.completedAt === \"string\") {\n job.completedAt = new Date(job.completedAt);\n }\n return job;\n }\n\n private convertScheduleDates(schedule: ScreenshotSchedule): ScreenshotSchedule {\n if (typeof schedule.createdAt === \"string\") {\n schedule.createdAt = new Date(schedule.createdAt);\n }\n if (typeof schedule.updatedAt === \"string\") {\n schedule.updatedAt = new Date(schedule.updatedAt);\n }\n if (schedule.lastRunAt && typeof schedule.lastRunAt === \"string\") {\n schedule.lastRunAt = new Date(schedule.lastRunAt);\n }\n if (schedule.nextRunAt && typeof schedule.nextRunAt === \"string\") {\n schedule.nextRunAt = new Date(schedule.nextRunAt);\n }\n return schedule;\n }\n}\n"]}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Shared types used across multiple SDK modules
3
+ */
4
+ type Environment = "sandbox" | "production";
5
+ type BatchJobStatus = "pending" | "processing" | "completed" | "failed" | "cancelled";
6
+ type ScheduleFrequency = "hourly" | "daily" | "weekly" | "monthly";
7
+ interface GetBatchJobRequest {
8
+ id: string;
9
+ environment?: Environment;
10
+ projectId?: string;
11
+ }
12
+ interface ListBatchJobsRequest {
13
+ environment?: Environment;
14
+ projectId?: string;
15
+ status?: BatchJobStatus;
16
+ limit?: number;
17
+ cursor?: string;
18
+ }
19
+ interface CreateBatchResponse {
20
+ id: string;
21
+ status: BatchJobStatus;
22
+ totalUrls: number;
23
+ }
24
+ interface GetScheduleRequest {
25
+ id: string;
26
+ environment?: Environment;
27
+ projectId?: string;
28
+ }
29
+ interface ListSchedulesRequest {
30
+ environment?: Environment;
31
+ projectId?: string;
32
+ isActive?: boolean;
33
+ limit?: number;
34
+ cursor?: string;
35
+ }
36
+ interface CreateScheduleResponse {
37
+ id: string;
38
+ }
39
+
40
+ export type { BatchJobStatus as B, CreateBatchResponse as C, Environment as E, GetBatchJobRequest as G, ListBatchJobsRequest as L, ScheduleFrequency as S, GetScheduleRequest as a, ListSchedulesRequest as b, CreateScheduleResponse as c };
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Shared types used across multiple SDK modules
3
+ */
4
+ type Environment = "sandbox" | "production";
5
+ type BatchJobStatus = "pending" | "processing" | "completed" | "failed" | "cancelled";
6
+ type ScheduleFrequency = "hourly" | "daily" | "weekly" | "monthly";
7
+ interface GetBatchJobRequest {
8
+ id: string;
9
+ environment?: Environment;
10
+ projectId?: string;
11
+ }
12
+ interface ListBatchJobsRequest {
13
+ environment?: Environment;
14
+ projectId?: string;
15
+ status?: BatchJobStatus;
16
+ limit?: number;
17
+ cursor?: string;
18
+ }
19
+ interface CreateBatchResponse {
20
+ id: string;
21
+ status: BatchJobStatus;
22
+ totalUrls: number;
23
+ }
24
+ interface GetScheduleRequest {
25
+ id: string;
26
+ environment?: Environment;
27
+ projectId?: string;
28
+ }
29
+ interface ListSchedulesRequest {
30
+ environment?: Environment;
31
+ projectId?: string;
32
+ isActive?: boolean;
33
+ limit?: number;
34
+ cursor?: string;
35
+ }
36
+ interface CreateScheduleResponse {
37
+ id: string;
38
+ }
39
+
40
+ export type { BatchJobStatus as B, CreateBatchResponse as C, Environment as E, GetBatchJobRequest as G, ListBatchJobsRequest as L, ScheduleFrequency as S, GetScheduleRequest as a, ListSchedulesRequest as b, CreateScheduleResponse as c };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stack0/sdk",
3
- "version": "0.2.8",
3
+ "version": "0.2.9",
4
4
  "description": "Official Stack0 SDK for Node.js",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
@@ -20,6 +20,21 @@
20
20
  "types": "./dist/cdn/index.d.ts",
21
21
  "require": "./dist/cdn/index.js",
22
22
  "import": "./dist/cdn/index.mjs"
23
+ },
24
+ "./screenshots": {
25
+ "types": "./dist/screenshots/index.d.ts",
26
+ "require": "./dist/screenshots/index.js",
27
+ "import": "./dist/screenshots/index.mjs"
28
+ },
29
+ "./extraction": {
30
+ "types": "./dist/extraction/index.d.ts",
31
+ "require": "./dist/extraction/index.js",
32
+ "import": "./dist/extraction/index.mjs"
33
+ },
34
+ "./webdata": {
35
+ "types": "./dist/webdata/index.d.ts",
36
+ "require": "./dist/webdata/index.js",
37
+ "import": "./dist/webdata/index.mjs"
23
38
  }
24
39
  },
25
40
  "files": [
@@ -34,6 +49,10 @@
34
49
  "cdn",
35
50
  "assets",
36
51
  "file-upload",
52
+ "screenshots",
53
+ "webpage-capture",
54
+ "ai-extraction",
55
+ "web-scraping",
37
56
  "api",
38
57
  "sdk"
39
58
  ],