@@ -39,67 +39,82 @@ const screenshotSchema = z.object({
3939 headers : z . record ( z . string ( ) , z . any ( ) ) . optional ( ) ,
4040 sleep : z . number ( ) . min ( 0 ) . max ( 60000 ) . default ( 3000 ) ,
4141 // Viewport options
42- viewport : z . object ( {
43- width : z . number ( ) . min ( 1 ) . max ( 3840 ) . default ( 1280 ) ,
44- height : z . number ( ) . min ( 1 ) . max ( 2160 ) . default ( 720 ) ,
45- } ) . optional ( ) ,
42+ viewport : z
43+ . object ( {
44+ width : z . number ( ) . min ( 1 ) . max ( 3840 ) . default ( 1280 ) ,
45+ height : z . number ( ) . min ( 1 ) . max ( 2160 ) . default ( 720 ) ,
46+ } )
47+ . optional ( ) ,
4648 // Screenshot options
4749 format : z . enum ( [ "png" , "jpeg" , "webp" ] ) . default ( "png" ) ,
4850 quality : z . number ( ) . min ( 0 ) . max ( 100 ) . default ( 90 ) ,
4951 fullPage : z . boolean ( ) . default ( false ) ,
50- clip : z . object ( {
51- x : z . number ( ) . min ( 0 ) ,
52- y : z . number ( ) . min ( 0 ) ,
53- width : z . number ( ) . min ( 1 ) ,
54- height : z . number ( ) . min ( 1 ) ,
55- } ) . optional ( ) ,
52+ clip : z
53+ . object ( {
54+ x : z . number ( ) . min ( 0 ) ,
55+ y : z . number ( ) . min ( 0 ) ,
56+ width : z . number ( ) . min ( 1 ) ,
57+ height : z . number ( ) . min ( 1 ) ,
58+ } )
59+ . optional ( ) ,
5660 // Browser context options
5761 userAgent : z . string ( ) . optional ( ) ,
5862 locale : z . string ( ) . optional ( ) ,
59- timezoneId : z . string ( ) . regex (
60- / ^ ( A f r i c a | A m e r i c a | A n t a r c t i c a | A r c t i c | A s i a | A t l a n t i c | A u s t r a l i a | E u r o p e | I n d i a n | P a c i f i c | U T C ) \/ [ A - Z a - z _ ] + $ / ,
61- "Must be a valid IANA timezone identifier (e.g., 'America/New_York', 'Europe/London', 'Asia/Tokyo')"
62- ) . optional ( ) ,
63- geolocation : z . object ( {
64- latitude : z . number ( ) . min ( - 90 ) . max ( 90 ) ,
65- longitude : z . number ( ) . min ( - 180 ) . max ( 180 ) ,
66- accuracy : z . number ( ) . min ( 0 ) . optional ( ) ,
67- } ) . optional ( ) ,
68- permissions : z . array ( z . enum ( [
69- "geolocation" ,
70- "camera" ,
71- "microphone" ,
72- "notifications" ,
73- "clipboard-read" ,
74- "clipboard-write" ,
75- "payment-handler" ,
76- "midi" ,
77- "usb" ,
78- "serial" ,
79- "bluetooth" ,
80- "persistent-storage" ,
81- "accelerometer" ,
82- "gyroscope" ,
83- "magnetometer" ,
84- "ambient-light-sensor" ,
85- "background-sync" ,
86- "background-fetch" ,
87- "idle-detection" ,
88- "periodic-background-sync" ,
89- "push" ,
90- "speaker-selection" ,
91- "storage-access" ,
92- "top-level-storage-access" ,
93- "window-management" ,
94- "local-fonts" ,
95- "display-capture" ,
96- "nfc" ,
97- "screen-wake-lock" ,
98- "web-share" ,
99- "xr-spatial-tracking"
100- ] ) ) . optional ( ) ,
63+ timezoneId : z
64+ . string ( )
65+ . regex (
66+ / ^ ( A f r i c a | A m e r i c a | A n t a r c t i c a | A r c t i c | A s i a | A t l a n t i c | A u s t r a l i a | E u r o p e | I n d i a n | P a c i f i c | U T C ) \/ [ A - Z a - z _ ] + $ / ,
67+ "Must be a valid IANA timezone identifier (e.g., 'America/New_York', 'Europe/London', 'Asia/Tokyo')" ,
68+ )
69+ . optional ( ) ,
70+ geolocation : z
71+ . object ( {
72+ latitude : z . number ( ) . min ( - 90 ) . max ( 90 ) ,
73+ longitude : z . number ( ) . min ( - 180 ) . max ( 180 ) ,
74+ accuracy : z . number ( ) . min ( 0 ) . optional ( ) ,
75+ } )
76+ . optional ( ) ,
77+ permissions : z
78+ . array (
79+ z . enum ( [
80+ "geolocation" ,
81+ "camera" ,
82+ "microphone" ,
83+ "notifications" ,
84+ "clipboard-read" ,
85+ "clipboard-write" ,
86+ "payment-handler" ,
87+ "midi" ,
88+ "usb" ,
89+ "serial" ,
90+ "bluetooth" ,
91+ "persistent-storage" ,
92+ "accelerometer" ,
93+ "gyroscope" ,
94+ "magnetometer" ,
95+ "ambient-light-sensor" ,
96+ "background-sync" ,
97+ "background-fetch" ,
98+ "idle-detection" ,
99+ "periodic-background-sync" ,
100+ "push" ,
101+ "speaker-selection" ,
102+ "storage-access" ,
103+ "top-level-storage-access" ,
104+ "window-management" ,
105+ "local-fonts" ,
106+ "display-capture" ,
107+ "nfc" ,
108+ "screen-wake-lock" ,
109+ "web-share" ,
110+ "xr-spatial-tracking" ,
111+ ] ) ,
112+ )
113+ . optional ( ) ,
101114 // Navigation options
102- waitUntil : z . enum ( [ "load" , "domcontentloaded" , "networkidle" , "commit" ] ) . default ( "domcontentloaded" ) ,
115+ waitUntil : z
116+ . enum ( [ "load" , "domcontentloaded" , "networkidle" , "commit" ] )
117+ . default ( "domcontentloaded" ) ,
103118 timeout : z . number ( ) . min ( 0 ) . max ( 120000 ) . default ( 30000 ) ,
104119 // Additional options
105120 deviceScaleFactor : z . number ( ) . min ( 0.1 ) . max ( 3 ) . default ( 1 ) ,
@@ -110,7 +125,7 @@ router.post(
110125 "/v1/screenshots" ,
111126 defineEventHandler ( async ( event ) => {
112127 const body = await readValidatedBody ( event , screenshotSchema . parse ) ;
113-
128+
114129 // Build context options
115130 const contextOptions = {
116131 ...defaultContext ,
@@ -197,53 +212,64 @@ const lighthouseSchema = z.object({
197212 headers : z . record ( z . string ( ) , z . any ( ) ) . optional ( ) ,
198213 userAgent : z . string ( ) . optional ( ) ,
199214 locale : z . string ( ) . optional ( ) ,
200- timezoneId : z . string ( ) . regex (
201- / ^ ( A f r i c a | A m e r i c a | A n t a r c t i c a | A r c t i c | A s i a | A t l a n t i c | A u s t r a l i a | E u r o p e | I n d i a n | P a c i f i c | U T C ) \/ [ A - Z a - z _ ] + $ / ,
202- "Must be a valid IANA timezone identifier (e.g., 'America/New_York', 'Europe/London', 'Asia/Tokyo')"
203- ) . optional ( ) ,
204- permissions : z . array ( z . enum ( [
205- "geolocation" ,
206- "camera" ,
207- "microphone" ,
208- "notifications" ,
209- "clipboard-read" ,
210- "clipboard-write" ,
211- "payment-handler" ,
212- "midi" ,
213- "usb" ,
214- "serial" ,
215- "bluetooth" ,
216- "persistent-storage" ,
217- "accelerometer" ,
218- "gyroscope" ,
219- "magnetometer" ,
220- "ambient-light-sensor" ,
221- "background-sync" ,
222- "background-fetch" ,
223- "idle-detection" ,
224- "periodic-background-sync" ,
225- "push" ,
226- "speaker-selection" ,
227- "storage-access" ,
228- "top-level-storage-access" ,
229- "window-management" ,
230- "local-fonts" ,
231- "display-capture" ,
232- "nfc" ,
233- "screen-wake-lock" ,
234- "web-share" ,
235- "xr-spatial-tracking"
236- ] ) ) . optional ( ) ,
215+ timezoneId : z
216+ . string ( )
217+ . regex (
218+ / ^ ( A f r i c a | A m e r i c a | A n t a r c t i c a | A r c t i c | A s i a | A t l a n t i c | A u s t r a l i a | E u r o p e | I n d i a n | P a c i f i c | U T C ) \/ [ A - Z a - z _ ] + $ / ,
219+ "Must be a valid IANA timezone identifier (e.g., 'America/New_York', 'Europe/London', 'Asia/Tokyo')" ,
220+ )
221+ . optional ( ) ,
222+ permissions : z
223+ . array (
224+ z . enum ( [
225+ "geolocation" ,
226+ "camera" ,
227+ "microphone" ,
228+ "notifications" ,
229+ "clipboard-read" ,
230+ "clipboard-write" ,
231+ "payment-handler" ,
232+ "midi" ,
233+ "usb" ,
234+ "serial" ,
235+ "bluetooth" ,
236+ "persistent-storage" ,
237+ "accelerometer" ,
238+ "gyroscope" ,
239+ "magnetometer" ,
240+ "ambient-light-sensor" ,
241+ "background-sync" ,
242+ "background-fetch" ,
243+ "idle-detection" ,
244+ "periodic-background-sync" ,
245+ "push" ,
246+ "speaker-selection" ,
247+ "storage-access" ,
248+ "top-level-storage-access" ,
249+ "window-management" ,
250+ "local-fonts" ,
251+ "display-capture" ,
252+ "nfc" ,
253+ "screen-wake-lock" ,
254+ "web-share" ,
255+ "xr-spatial-tracking" ,
256+ ] ) ,
257+ )
258+ . optional ( ) ,
237259 // Performance thresholds
238- thresholds : z . object ( {
239- performance : z . number ( ) . min ( 0 ) . max ( 100 ) . default ( 0 ) ,
240- accessibility : z . number ( ) . min ( 0 ) . max ( 100 ) . default ( 0 ) ,
241- "best-practices" : z . number ( ) . min ( 0 ) . max ( 100 ) . default ( 0 ) ,
242- seo : z . number ( ) . min ( 0 ) . max ( 100 ) . default ( 0 ) ,
243- pwa : z . number ( ) . min ( 0 ) . max ( 100 ) . default ( 0 ) ,
244- } ) . optional ( ) ,
260+ thresholds : z
261+ . object ( {
262+ performance : z . number ( ) . min ( 0 ) . max ( 100 ) . default ( 0 ) ,
263+ accessibility : z . number ( ) . min ( 0 ) . max ( 100 ) . default ( 0 ) ,
264+ "best-practices" : z . number ( ) . min ( 0 ) . max ( 100 ) . default ( 0 ) ,
265+ seo : z . number ( ) . min ( 0 ) . max ( 100 ) . default ( 0 ) ,
266+ pwa : z . number ( ) . min ( 0 ) . max ( 100 ) . default ( 0 ) ,
267+ } )
268+ . optional ( ) ,
245269 // Navigation options
246- waitUntil : z . enum ( [ "load" , "domcontentloaded" , "networkidle" , "commit" ] ) . default ( "domcontentloaded" ) ,
270+ waitUntil : z
271+ . enum ( [ "load" , "domcontentloaded" , "networkidle" , "commit" ] )
272+ . default ( "domcontentloaded" ) ,
247273 timeout : z . number ( ) . min ( 0 ) . max ( 120000 ) . default ( 30000 ) ,
248274} ) ;
249275const configs = {
@@ -254,7 +280,7 @@ router.post(
254280 "/v1/reports" ,
255281 defineEventHandler ( async ( event ) => {
256282 const body = await readValidatedBody ( event , lighthouseSchema . parse ) ;
257-
283+
258284 // Build context options
259285 const contextOptions = {
260286 ...defaultContext ,
@@ -687,9 +713,9 @@ router.get(
687713 } ) ;
688714
689715 await context . close ( ) ;
690-
716+
691717 // Set content type to HTML
692- event . node . res . setHeader ( ' Content-Type' , ' text/html' ) ;
718+ event . node . res . setHeader ( " Content-Type" , " text/html" ) ;
693719 return html ;
694720 } ) ,
695721) ;
0 commit comments