@screenshotscout/cli 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +236 -0
- package/SECURITY.md +13 -0
- package/dist/capture-options.js +476 -0
- package/dist/capture-url.js +23 -0
- package/dist/capture.js +17 -0
- package/dist/cli-usage-error.js +8 -0
- package/dist/cli.js +96 -0
- package/dist/help.js +59 -0
- package/dist/index.js +3 -0
- package/dist/input.js +332 -0
- package/dist/result.js +51 -0
- package/dist/sdk.js +23 -0
- package/package.json +63 -0
|
@@ -0,0 +1,476 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The single runtime source of truth for translating capture-option names and
|
|
3
|
+
* CLI-owned value shapes. The mapped type makes a changed SDK CaptureOptions
|
|
4
|
+
* surface a compile-time failure until this descriptor is updated deliberately.
|
|
5
|
+
*/
|
|
6
|
+
export const CAPTURE_OPTION_DEFINITIONS = {
|
|
7
|
+
format: {
|
|
8
|
+
sdkName: "format",
|
|
9
|
+
apiName: "format",
|
|
10
|
+
cliName: "format",
|
|
11
|
+
kind: "string",
|
|
12
|
+
multiple: false,
|
|
13
|
+
},
|
|
14
|
+
responseType: {
|
|
15
|
+
sdkName: "responseType",
|
|
16
|
+
apiName: "response_type",
|
|
17
|
+
cliName: "response-type",
|
|
18
|
+
kind: "string",
|
|
19
|
+
multiple: false,
|
|
20
|
+
},
|
|
21
|
+
country: {
|
|
22
|
+
sdkName: "country",
|
|
23
|
+
apiName: "country",
|
|
24
|
+
cliName: "country",
|
|
25
|
+
kind: "string",
|
|
26
|
+
multiple: false,
|
|
27
|
+
},
|
|
28
|
+
proxy: {
|
|
29
|
+
sdkName: "proxy",
|
|
30
|
+
apiName: "proxy",
|
|
31
|
+
cliName: "proxy",
|
|
32
|
+
kind: "string",
|
|
33
|
+
multiple: false,
|
|
34
|
+
},
|
|
35
|
+
geolocationLatitude: {
|
|
36
|
+
sdkName: "geolocationLatitude",
|
|
37
|
+
apiName: "geolocation_latitude",
|
|
38
|
+
cliName: "geolocation-latitude",
|
|
39
|
+
kind: "number",
|
|
40
|
+
multiple: false,
|
|
41
|
+
},
|
|
42
|
+
geolocationLongitude: {
|
|
43
|
+
sdkName: "geolocationLongitude",
|
|
44
|
+
apiName: "geolocation_longitude",
|
|
45
|
+
cliName: "geolocation-longitude",
|
|
46
|
+
kind: "number",
|
|
47
|
+
multiple: false,
|
|
48
|
+
},
|
|
49
|
+
geolocationAccuracy: {
|
|
50
|
+
sdkName: "geolocationAccuracy",
|
|
51
|
+
apiName: "geolocation_accuracy",
|
|
52
|
+
cliName: "geolocation-accuracy",
|
|
53
|
+
kind: "number",
|
|
54
|
+
multiple: false,
|
|
55
|
+
},
|
|
56
|
+
cookies: {
|
|
57
|
+
sdkName: "cookies",
|
|
58
|
+
apiName: "cookies",
|
|
59
|
+
cliName: "cookies",
|
|
60
|
+
kind: "string",
|
|
61
|
+
multiple: true,
|
|
62
|
+
},
|
|
63
|
+
headers: {
|
|
64
|
+
sdkName: "headers",
|
|
65
|
+
apiName: "headers",
|
|
66
|
+
cliName: "headers",
|
|
67
|
+
kind: "string",
|
|
68
|
+
multiple: true,
|
|
69
|
+
},
|
|
70
|
+
timeout: {
|
|
71
|
+
sdkName: "timeout",
|
|
72
|
+
apiName: "timeout",
|
|
73
|
+
cliName: "timeout",
|
|
74
|
+
kind: "number",
|
|
75
|
+
multiple: false,
|
|
76
|
+
},
|
|
77
|
+
waitUntil: {
|
|
78
|
+
sdkName: "waitUntil",
|
|
79
|
+
apiName: "wait_until",
|
|
80
|
+
cliName: "wait-until",
|
|
81
|
+
kind: "string",
|
|
82
|
+
multiple: false,
|
|
83
|
+
},
|
|
84
|
+
navigationTimeout: {
|
|
85
|
+
sdkName: "navigationTimeout",
|
|
86
|
+
apiName: "navigation_timeout",
|
|
87
|
+
cliName: "navigation-timeout",
|
|
88
|
+
kind: "number",
|
|
89
|
+
multiple: false,
|
|
90
|
+
},
|
|
91
|
+
delay: {
|
|
92
|
+
sdkName: "delay",
|
|
93
|
+
apiName: "delay",
|
|
94
|
+
cliName: "delay",
|
|
95
|
+
kind: "number",
|
|
96
|
+
multiple: false,
|
|
97
|
+
},
|
|
98
|
+
device: {
|
|
99
|
+
sdkName: "device",
|
|
100
|
+
apiName: "device",
|
|
101
|
+
cliName: "device",
|
|
102
|
+
kind: "string",
|
|
103
|
+
multiple: false,
|
|
104
|
+
},
|
|
105
|
+
deviceViewportWidth: {
|
|
106
|
+
sdkName: "deviceViewportWidth",
|
|
107
|
+
apiName: "device_viewport_width",
|
|
108
|
+
cliName: "device-viewport-width",
|
|
109
|
+
kind: "number",
|
|
110
|
+
multiple: false,
|
|
111
|
+
},
|
|
112
|
+
deviceViewportHeight: {
|
|
113
|
+
sdkName: "deviceViewportHeight",
|
|
114
|
+
apiName: "device_viewport_height",
|
|
115
|
+
cliName: "device-viewport-height",
|
|
116
|
+
kind: "number",
|
|
117
|
+
multiple: false,
|
|
118
|
+
},
|
|
119
|
+
deviceScaleFactor: {
|
|
120
|
+
sdkName: "deviceScaleFactor",
|
|
121
|
+
apiName: "device_scale_factor",
|
|
122
|
+
cliName: "device-scale-factor",
|
|
123
|
+
kind: "number",
|
|
124
|
+
multiple: false,
|
|
125
|
+
},
|
|
126
|
+
deviceIsMobile: {
|
|
127
|
+
sdkName: "deviceIsMobile",
|
|
128
|
+
apiName: "device_is_mobile",
|
|
129
|
+
cliName: "device-is-mobile",
|
|
130
|
+
kind: "boolean",
|
|
131
|
+
multiple: false,
|
|
132
|
+
},
|
|
133
|
+
deviceHasTouch: {
|
|
134
|
+
sdkName: "deviceHasTouch",
|
|
135
|
+
apiName: "device_has_touch",
|
|
136
|
+
cliName: "device-has-touch",
|
|
137
|
+
kind: "boolean",
|
|
138
|
+
multiple: false,
|
|
139
|
+
},
|
|
140
|
+
deviceUserAgent: {
|
|
141
|
+
sdkName: "deviceUserAgent",
|
|
142
|
+
apiName: "device_user_agent",
|
|
143
|
+
cliName: "device-user-agent",
|
|
144
|
+
kind: "string",
|
|
145
|
+
multiple: false,
|
|
146
|
+
},
|
|
147
|
+
timezone: {
|
|
148
|
+
sdkName: "timezone",
|
|
149
|
+
apiName: "timezone",
|
|
150
|
+
cliName: "timezone",
|
|
151
|
+
kind: "string",
|
|
152
|
+
multiple: false,
|
|
153
|
+
},
|
|
154
|
+
mediaType: {
|
|
155
|
+
sdkName: "mediaType",
|
|
156
|
+
apiName: "media_type",
|
|
157
|
+
cliName: "media-type",
|
|
158
|
+
kind: "string",
|
|
159
|
+
multiple: false,
|
|
160
|
+
},
|
|
161
|
+
colorScheme: {
|
|
162
|
+
sdkName: "colorScheme",
|
|
163
|
+
apiName: "color_scheme",
|
|
164
|
+
cliName: "color-scheme",
|
|
165
|
+
kind: "string",
|
|
166
|
+
multiple: false,
|
|
167
|
+
},
|
|
168
|
+
reducedMotion: {
|
|
169
|
+
sdkName: "reducedMotion",
|
|
170
|
+
apiName: "reduced_motion",
|
|
171
|
+
cliName: "reduced-motion",
|
|
172
|
+
kind: "boolean",
|
|
173
|
+
multiple: false,
|
|
174
|
+
},
|
|
175
|
+
fullPage: {
|
|
176
|
+
sdkName: "fullPage",
|
|
177
|
+
apiName: "full_page",
|
|
178
|
+
cliName: "full-page",
|
|
179
|
+
kind: "boolean",
|
|
180
|
+
multiple: false,
|
|
181
|
+
},
|
|
182
|
+
fullPagePreScroll: {
|
|
183
|
+
sdkName: "fullPagePreScroll",
|
|
184
|
+
apiName: "full_page_pre_scroll",
|
|
185
|
+
cliName: "full-page-pre-scroll",
|
|
186
|
+
kind: "boolean",
|
|
187
|
+
multiple: false,
|
|
188
|
+
},
|
|
189
|
+
fullPagePreScrollStep: {
|
|
190
|
+
sdkName: "fullPagePreScrollStep",
|
|
191
|
+
apiName: "full_page_pre_scroll_step",
|
|
192
|
+
cliName: "full-page-pre-scroll-step",
|
|
193
|
+
kind: "number",
|
|
194
|
+
multiple: false,
|
|
195
|
+
},
|
|
196
|
+
fullPagePreScrollStepDelay: {
|
|
197
|
+
sdkName: "fullPagePreScrollStepDelay",
|
|
198
|
+
apiName: "full_page_pre_scroll_step_delay",
|
|
199
|
+
cliName: "full-page-pre-scroll-step-delay",
|
|
200
|
+
kind: "number",
|
|
201
|
+
multiple: false,
|
|
202
|
+
},
|
|
203
|
+
fullPageMaxHeight: {
|
|
204
|
+
sdkName: "fullPageMaxHeight",
|
|
205
|
+
apiName: "full_page_max_height",
|
|
206
|
+
cliName: "full-page-max-height",
|
|
207
|
+
kind: "number",
|
|
208
|
+
multiple: false,
|
|
209
|
+
},
|
|
210
|
+
blockCookieBanners: {
|
|
211
|
+
sdkName: "blockCookieBanners",
|
|
212
|
+
apiName: "block_cookie_banners",
|
|
213
|
+
cliName: "block-cookie-banners",
|
|
214
|
+
kind: "boolean",
|
|
215
|
+
multiple: false,
|
|
216
|
+
},
|
|
217
|
+
blockAds: {
|
|
218
|
+
sdkName: "blockAds",
|
|
219
|
+
apiName: "block_ads",
|
|
220
|
+
cliName: "block-ads",
|
|
221
|
+
kind: "boolean",
|
|
222
|
+
multiple: false,
|
|
223
|
+
},
|
|
224
|
+
blockChatWidgets: {
|
|
225
|
+
sdkName: "blockChatWidgets",
|
|
226
|
+
apiName: "block_chat_widgets",
|
|
227
|
+
cliName: "block-chat-widgets",
|
|
228
|
+
kind: "boolean",
|
|
229
|
+
multiple: false,
|
|
230
|
+
},
|
|
231
|
+
hideSelectors: {
|
|
232
|
+
sdkName: "hideSelectors",
|
|
233
|
+
apiName: "hide_selectors",
|
|
234
|
+
cliName: "hide-selectors",
|
|
235
|
+
kind: "string",
|
|
236
|
+
multiple: true,
|
|
237
|
+
},
|
|
238
|
+
clickSelectors: {
|
|
239
|
+
sdkName: "clickSelectors",
|
|
240
|
+
apiName: "click_selectors",
|
|
241
|
+
cliName: "click-selectors",
|
|
242
|
+
kind: "string",
|
|
243
|
+
multiple: true,
|
|
244
|
+
},
|
|
245
|
+
clickAllSelectors: {
|
|
246
|
+
sdkName: "clickAllSelectors",
|
|
247
|
+
apiName: "click_all_selectors",
|
|
248
|
+
cliName: "click-all-selectors",
|
|
249
|
+
kind: "string",
|
|
250
|
+
multiple: true,
|
|
251
|
+
},
|
|
252
|
+
injectCss: {
|
|
253
|
+
sdkName: "injectCss",
|
|
254
|
+
apiName: "inject_css",
|
|
255
|
+
cliName: "inject-css",
|
|
256
|
+
kind: "string",
|
|
257
|
+
multiple: true,
|
|
258
|
+
},
|
|
259
|
+
injectJs: {
|
|
260
|
+
sdkName: "injectJs",
|
|
261
|
+
apiName: "inject_js",
|
|
262
|
+
cliName: "inject-js",
|
|
263
|
+
kind: "string",
|
|
264
|
+
multiple: true,
|
|
265
|
+
},
|
|
266
|
+
bypassCsp: {
|
|
267
|
+
sdkName: "bypassCsp",
|
|
268
|
+
apiName: "bypass_csp",
|
|
269
|
+
cliName: "bypass-csp",
|
|
270
|
+
kind: "boolean",
|
|
271
|
+
multiple: false,
|
|
272
|
+
},
|
|
273
|
+
selector: {
|
|
274
|
+
sdkName: "selector",
|
|
275
|
+
apiName: "selector",
|
|
276
|
+
cliName: "selector",
|
|
277
|
+
kind: "string",
|
|
278
|
+
multiple: false,
|
|
279
|
+
},
|
|
280
|
+
clipX: {
|
|
281
|
+
sdkName: "clipX",
|
|
282
|
+
apiName: "clip_x",
|
|
283
|
+
cliName: "clip-x",
|
|
284
|
+
kind: "number",
|
|
285
|
+
multiple: false,
|
|
286
|
+
},
|
|
287
|
+
clipY: {
|
|
288
|
+
sdkName: "clipY",
|
|
289
|
+
apiName: "clip_y",
|
|
290
|
+
cliName: "clip-y",
|
|
291
|
+
kind: "number",
|
|
292
|
+
multiple: false,
|
|
293
|
+
},
|
|
294
|
+
clipWidth: {
|
|
295
|
+
sdkName: "clipWidth",
|
|
296
|
+
apiName: "clip_width",
|
|
297
|
+
cliName: "clip-width",
|
|
298
|
+
kind: "number",
|
|
299
|
+
multiple: false,
|
|
300
|
+
},
|
|
301
|
+
clipHeight: {
|
|
302
|
+
sdkName: "clipHeight",
|
|
303
|
+
apiName: "clip_height",
|
|
304
|
+
cliName: "clip-height",
|
|
305
|
+
kind: "number",
|
|
306
|
+
multiple: false,
|
|
307
|
+
},
|
|
308
|
+
imageWidth: {
|
|
309
|
+
sdkName: "imageWidth",
|
|
310
|
+
apiName: "image_width",
|
|
311
|
+
cliName: "image-width",
|
|
312
|
+
kind: "number",
|
|
313
|
+
multiple: false,
|
|
314
|
+
},
|
|
315
|
+
imageHeight: {
|
|
316
|
+
sdkName: "imageHeight",
|
|
317
|
+
apiName: "image_height",
|
|
318
|
+
cliName: "image-height",
|
|
319
|
+
kind: "number",
|
|
320
|
+
multiple: false,
|
|
321
|
+
},
|
|
322
|
+
imageMode: {
|
|
323
|
+
sdkName: "imageMode",
|
|
324
|
+
apiName: "image_mode",
|
|
325
|
+
cliName: "image-mode",
|
|
326
|
+
kind: "string",
|
|
327
|
+
multiple: false,
|
|
328
|
+
},
|
|
329
|
+
imageAnchor: {
|
|
330
|
+
sdkName: "imageAnchor",
|
|
331
|
+
apiName: "image_anchor",
|
|
332
|
+
cliName: "image-anchor",
|
|
333
|
+
kind: "string",
|
|
334
|
+
multiple: false,
|
|
335
|
+
},
|
|
336
|
+
imageAllowUpscale: {
|
|
337
|
+
sdkName: "imageAllowUpscale",
|
|
338
|
+
apiName: "image_allow_upscale",
|
|
339
|
+
cliName: "image-allow-upscale",
|
|
340
|
+
kind: "boolean",
|
|
341
|
+
multiple: false,
|
|
342
|
+
},
|
|
343
|
+
imageBackground: {
|
|
344
|
+
sdkName: "imageBackground",
|
|
345
|
+
apiName: "image_background",
|
|
346
|
+
cliName: "image-background",
|
|
347
|
+
kind: "string",
|
|
348
|
+
multiple: false,
|
|
349
|
+
},
|
|
350
|
+
imageQuality: {
|
|
351
|
+
sdkName: "imageQuality",
|
|
352
|
+
apiName: "image_quality",
|
|
353
|
+
cliName: "image-quality",
|
|
354
|
+
kind: "number",
|
|
355
|
+
multiple: false,
|
|
356
|
+
},
|
|
357
|
+
pdfPaperFormat: {
|
|
358
|
+
sdkName: "pdfPaperFormat",
|
|
359
|
+
apiName: "pdf_paper_format",
|
|
360
|
+
cliName: "pdf-paper-format",
|
|
361
|
+
kind: "string",
|
|
362
|
+
multiple: false,
|
|
363
|
+
},
|
|
364
|
+
pdfLandscape: {
|
|
365
|
+
sdkName: "pdfLandscape",
|
|
366
|
+
apiName: "pdf_landscape",
|
|
367
|
+
cliName: "pdf-landscape",
|
|
368
|
+
kind: "boolean",
|
|
369
|
+
multiple: false,
|
|
370
|
+
},
|
|
371
|
+
pdfPrintBackground: {
|
|
372
|
+
sdkName: "pdfPrintBackground",
|
|
373
|
+
apiName: "pdf_print_background",
|
|
374
|
+
cliName: "pdf-print-background",
|
|
375
|
+
kind: "boolean",
|
|
376
|
+
multiple: false,
|
|
377
|
+
},
|
|
378
|
+
pdfMargin: {
|
|
379
|
+
sdkName: "pdfMargin",
|
|
380
|
+
apiName: "pdf_margin",
|
|
381
|
+
cliName: "pdf-margin",
|
|
382
|
+
kind: "string",
|
|
383
|
+
multiple: false,
|
|
384
|
+
},
|
|
385
|
+
pdfMarginTop: {
|
|
386
|
+
sdkName: "pdfMarginTop",
|
|
387
|
+
apiName: "pdf_margin_top",
|
|
388
|
+
cliName: "pdf-margin-top",
|
|
389
|
+
kind: "string",
|
|
390
|
+
multiple: false,
|
|
391
|
+
},
|
|
392
|
+
pdfMarginRight: {
|
|
393
|
+
sdkName: "pdfMarginRight",
|
|
394
|
+
apiName: "pdf_margin_right",
|
|
395
|
+
cliName: "pdf-margin-right",
|
|
396
|
+
kind: "string",
|
|
397
|
+
multiple: false,
|
|
398
|
+
},
|
|
399
|
+
pdfMarginBottom: {
|
|
400
|
+
sdkName: "pdfMarginBottom",
|
|
401
|
+
apiName: "pdf_margin_bottom",
|
|
402
|
+
cliName: "pdf-margin-bottom",
|
|
403
|
+
kind: "string",
|
|
404
|
+
multiple: false,
|
|
405
|
+
},
|
|
406
|
+
pdfMarginLeft: {
|
|
407
|
+
sdkName: "pdfMarginLeft",
|
|
408
|
+
apiName: "pdf_margin_left",
|
|
409
|
+
cliName: "pdf-margin-left",
|
|
410
|
+
kind: "string",
|
|
411
|
+
multiple: false,
|
|
412
|
+
},
|
|
413
|
+
pdfScale: {
|
|
414
|
+
sdkName: "pdfScale",
|
|
415
|
+
apiName: "pdf_scale",
|
|
416
|
+
cliName: "pdf-scale",
|
|
417
|
+
kind: "number",
|
|
418
|
+
multiple: false,
|
|
419
|
+
},
|
|
420
|
+
cache: {
|
|
421
|
+
sdkName: "cache",
|
|
422
|
+
apiName: "cache",
|
|
423
|
+
cliName: "cache",
|
|
424
|
+
kind: "boolean",
|
|
425
|
+
multiple: false,
|
|
426
|
+
},
|
|
427
|
+
cacheTtl: {
|
|
428
|
+
sdkName: "cacheTtl",
|
|
429
|
+
apiName: "cache_ttl",
|
|
430
|
+
cliName: "cache-ttl",
|
|
431
|
+
kind: "number",
|
|
432
|
+
multiple: false,
|
|
433
|
+
},
|
|
434
|
+
cacheKey: {
|
|
435
|
+
sdkName: "cacheKey",
|
|
436
|
+
apiName: "cache_key",
|
|
437
|
+
cliName: "cache-key",
|
|
438
|
+
kind: "string",
|
|
439
|
+
multiple: false,
|
|
440
|
+
},
|
|
441
|
+
storageMode: {
|
|
442
|
+
sdkName: "storageMode",
|
|
443
|
+
apiName: "storage_mode",
|
|
444
|
+
cliName: "storage-mode",
|
|
445
|
+
kind: "string",
|
|
446
|
+
multiple: false,
|
|
447
|
+
},
|
|
448
|
+
storageEndpoint: {
|
|
449
|
+
sdkName: "storageEndpoint",
|
|
450
|
+
apiName: "storage_endpoint",
|
|
451
|
+
cliName: "storage-endpoint",
|
|
452
|
+
kind: "string",
|
|
453
|
+
multiple: false,
|
|
454
|
+
},
|
|
455
|
+
storageBucket: {
|
|
456
|
+
sdkName: "storageBucket",
|
|
457
|
+
apiName: "storage_bucket",
|
|
458
|
+
cliName: "storage-bucket",
|
|
459
|
+
kind: "string",
|
|
460
|
+
multiple: false,
|
|
461
|
+
},
|
|
462
|
+
storageRegion: {
|
|
463
|
+
sdkName: "storageRegion",
|
|
464
|
+
apiName: "storage_region",
|
|
465
|
+
cliName: "storage-region",
|
|
466
|
+
kind: "string",
|
|
467
|
+
multiple: false,
|
|
468
|
+
},
|
|
469
|
+
storageObjectKey: {
|
|
470
|
+
sdkName: "storageObjectKey",
|
|
471
|
+
apiName: "storage_object_key",
|
|
472
|
+
cliName: "storage-object-key",
|
|
473
|
+
kind: "string",
|
|
474
|
+
multiple: false,
|
|
475
|
+
},
|
|
476
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { parseCaptureUrlCommandInput } from "./input.js";
|
|
2
|
+
import { createScreenshotScoutClient, } from "./sdk.js";
|
|
3
|
+
/** Run one capture-url command as a direct input -> SDK -> output adapter. */
|
|
4
|
+
export async function runCaptureUrlCommand(args, dependencies = {}) {
|
|
5
|
+
const input = dependencies.inputReader === undefined
|
|
6
|
+
? await parseCaptureUrlCommandInput(args)
|
|
7
|
+
: await parseCaptureUrlCommandInput(args, dependencies.inputReader);
|
|
8
|
+
const client = dependencies.client ?? createScreenshotScoutClient();
|
|
9
|
+
const captureUrl = client.buildCaptureUrl(input.targetUrl, input.captureOptions);
|
|
10
|
+
await (dependencies.writeStandardOutput ?? writeStandardOutput)(`${captureUrl}\n`);
|
|
11
|
+
}
|
|
12
|
+
function writeStandardOutput(text) {
|
|
13
|
+
return new Promise((resolve, reject) => {
|
|
14
|
+
process.stdout.write(text, (error) => {
|
|
15
|
+
if (error === null || error === undefined) {
|
|
16
|
+
resolve();
|
|
17
|
+
}
|
|
18
|
+
else {
|
|
19
|
+
reject(error);
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
});
|
|
23
|
+
}
|
package/dist/capture.js
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { parseCaptureCommandInput } from "./input.js";
|
|
2
|
+
import { writeCaptureResult } from "./result.js";
|
|
3
|
+
import { captureWithScreenshotScoutClient, createScreenshotScoutClient, } from "./sdk.js";
|
|
4
|
+
/** Run one capture command as a direct input -> SDK -> result adapter. */
|
|
5
|
+
export async function runCaptureCommand(args, dependencies = {}) {
|
|
6
|
+
const input = dependencies.inputReader === undefined
|
|
7
|
+
? await parseCaptureCommandInput(args)
|
|
8
|
+
: await parseCaptureCommandInput(args, dependencies.inputReader);
|
|
9
|
+
const client = dependencies.client ?? createScreenshotScoutClient();
|
|
10
|
+
const response = await captureWithScreenshotScoutClient(client, input.targetUrl, input.captureOptions, input.method);
|
|
11
|
+
if (dependencies.resultIo === undefined) {
|
|
12
|
+
await writeCaptureResult(response, input.outputPath);
|
|
13
|
+
}
|
|
14
|
+
else {
|
|
15
|
+
await writeCaptureResult(response, input.outputPath, dependencies.resultIo);
|
|
16
|
+
}
|
|
17
|
+
}
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
import { ScreenshotScoutApiError } from "@screenshotscout/sdk";
|
|
3
|
+
import { runCaptureUrlCommand } from "./capture-url.js";
|
|
4
|
+
import { runCaptureCommand } from "./capture.js";
|
|
5
|
+
import { CliUsageError } from "./cli-usage-error.js";
|
|
6
|
+
import { captureCommandHelp, captureUrlCommandHelp, ROOT_HELP, } from "./help.js";
|
|
7
|
+
/** Strictly dispatch one root CLI invocation. Command failures propagate. */
|
|
8
|
+
export async function runCli(args, dependencies = {}) {
|
|
9
|
+
const writeStandardOutput = dependencies.writeStandardOutput ?? defaultWriteStandardOutput;
|
|
10
|
+
if (args.length === 0) {
|
|
11
|
+
throw new CliUsageError("A command is required.");
|
|
12
|
+
}
|
|
13
|
+
if (args.length === 1 && args[0] === "--help") {
|
|
14
|
+
await writeStandardOutput(ROOT_HELP);
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
if (args.length === 1 && args[0] === "--version") {
|
|
18
|
+
await writeStandardOutput(`${readPackageVersion()}\n`);
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
const command = args[0];
|
|
22
|
+
const commandArgs = args.slice(1);
|
|
23
|
+
if (command === "capture") {
|
|
24
|
+
if (commandArgs.length === 1 && commandArgs[0] === "--help") {
|
|
25
|
+
await writeStandardOutput(captureCommandHelp());
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
await (dependencies.runCapture ?? runCaptureCommand)(commandArgs);
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
if (command === "capture-url") {
|
|
32
|
+
if (commandArgs.length === 1 && commandArgs[0] === "--help") {
|
|
33
|
+
await writeStandardOutput(captureUrlCommandHelp());
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
await (dependencies.runCaptureUrl ?? runCaptureUrlCommand)(commandArgs);
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
throw new CliUsageError(`Unknown command '${command}'.`);
|
|
40
|
+
}
|
|
41
|
+
/** Run the executable behind one concise failure and exit-code boundary. */
|
|
42
|
+
export async function runCliExecutable(args, dependencies = {}) {
|
|
43
|
+
try {
|
|
44
|
+
await runCli(args, dependencies);
|
|
45
|
+
return 0;
|
|
46
|
+
}
|
|
47
|
+
catch (error) {
|
|
48
|
+
const exitCode = error instanceof CliUsageError ? 2 : 1;
|
|
49
|
+
try {
|
|
50
|
+
const writeStandardError = dependencies.writeStandardError ?? defaultWriteStandardError;
|
|
51
|
+
await writeStandardError(formatFailure(error));
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
// A failed failure-message write has no additional safe output channel.
|
|
55
|
+
}
|
|
56
|
+
return exitCode;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
/** Format only the approved human-readable message and API details. */
|
|
60
|
+
export function formatFailure(error) {
|
|
61
|
+
let output = `${error instanceof Error ? error.message : String(error)}\n`;
|
|
62
|
+
if (error instanceof ScreenshotScoutApiError &&
|
|
63
|
+
error.errors !== undefined &&
|
|
64
|
+
error.errors.length > 0) {
|
|
65
|
+
output += `${JSON.stringify(error.errors)}\n`;
|
|
66
|
+
}
|
|
67
|
+
return output;
|
|
68
|
+
}
|
|
69
|
+
function readPackageVersion() {
|
|
70
|
+
const packageJson = JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf8"));
|
|
71
|
+
if (packageJson === null ||
|
|
72
|
+
typeof packageJson !== "object" ||
|
|
73
|
+
!("version" in packageJson) ||
|
|
74
|
+
typeof packageJson.version !== "string") {
|
|
75
|
+
throw new Error("The CLI package version is unavailable.");
|
|
76
|
+
}
|
|
77
|
+
return packageJson.version;
|
|
78
|
+
}
|
|
79
|
+
function defaultWriteStandardOutput(text) {
|
|
80
|
+
return writeProcessStream(process.stdout, text);
|
|
81
|
+
}
|
|
82
|
+
function defaultWriteStandardError(text) {
|
|
83
|
+
return writeProcessStream(process.stderr, text);
|
|
84
|
+
}
|
|
85
|
+
function writeProcessStream(stream, text) {
|
|
86
|
+
return new Promise((resolve, reject) => {
|
|
87
|
+
stream.write(text, (error) => {
|
|
88
|
+
if (error === null || error === undefined) {
|
|
89
|
+
resolve();
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
reject(error);
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
});
|
|
96
|
+
}
|
package/dist/help.js
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { CAPTURE_OPTION_DEFINITIONS, } from "./capture-options.js";
|
|
2
|
+
export const ROOT_HELP = `Screenshot Scout CLI
|
|
3
|
+
|
|
4
|
+
Usage:
|
|
5
|
+
screenshotscout capture <url> [capture options] [CLI controls]
|
|
6
|
+
screenshotscout capture-url <url> [capture options]
|
|
7
|
+
screenshotscout --help
|
|
8
|
+
screenshotscout --version
|
|
9
|
+
|
|
10
|
+
Commands:
|
|
11
|
+
capture Capture one URL.
|
|
12
|
+
capture-url Build one capture URL locally.
|
|
13
|
+
|
|
14
|
+
Options:
|
|
15
|
+
--help Show root help.
|
|
16
|
+
--version Show the CLI version.
|
|
17
|
+
|
|
18
|
+
Run "screenshotscout <command> --help" for command options.
|
|
19
|
+
`;
|
|
20
|
+
const CAPTURE_OPTION_HELP = Object.values(CAPTURE_OPTION_DEFINITIONS)
|
|
21
|
+
.map(formatCaptureOption)
|
|
22
|
+
.join("\n");
|
|
23
|
+
export function captureCommandHelp() {
|
|
24
|
+
return `Usage:
|
|
25
|
+
screenshotscout capture <url> [capture options] [CLI controls]
|
|
26
|
+
|
|
27
|
+
CLI controls:
|
|
28
|
+
--options <path|-> Read a snake_case JSON options object from a file or standard input.
|
|
29
|
+
--method <get|post> Select the SDK capture request method.
|
|
30
|
+
-o, --output <path|-> Write the response to a file or standard output.
|
|
31
|
+
--help Show this help.
|
|
32
|
+
|
|
33
|
+
Capture options:
|
|
34
|
+
${CAPTURE_OPTION_HELP}
|
|
35
|
+
|
|
36
|
+
Boolean capture options accept a bare flag or an inline true/false value.
|
|
37
|
+
Repeatable capture options preserve order and duplicates.
|
|
38
|
+
`;
|
|
39
|
+
}
|
|
40
|
+
export function captureUrlCommandHelp() {
|
|
41
|
+
return `Usage:
|
|
42
|
+
screenshotscout capture-url <url> [capture options]
|
|
43
|
+
|
|
44
|
+
CLI controls:
|
|
45
|
+
--options <path|-> Read a snake_case JSON options object from a file or standard input.
|
|
46
|
+
--help Show this help.
|
|
47
|
+
|
|
48
|
+
Capture options:
|
|
49
|
+
${CAPTURE_OPTION_HELP}
|
|
50
|
+
|
|
51
|
+
Boolean capture options accept a bare flag or an inline true/false value.
|
|
52
|
+
Repeatable capture options preserve order and duplicates.
|
|
53
|
+
`;
|
|
54
|
+
}
|
|
55
|
+
function formatCaptureOption(definition) {
|
|
56
|
+
const valueShape = definition.kind === "boolean" ? "[=true|false]" : ` <${definition.kind}>`;
|
|
57
|
+
const repetition = definition.multiple ? " (repeatable)" : "";
|
|
58
|
+
return ` --${definition.cliName}${valueShape}${repetition}`;
|
|
59
|
+
}
|
package/dist/index.js
ADDED