88 convertWebResponseToLambdaEvent ,
99} from '@foladayo/lambda-adapter-kit' ;
1010import { getRequest } from '@sveltejs/kit/node' ;
11+ import { readFileSync } from 'node:fs' ;
12+ import { fileURLToPath } from 'node:url' ;
13+ import { dirname , join , extname } from 'node:path' ;
1114
1215/* global ENV_PREFIX */
1316
@@ -16,6 +19,9 @@ const server = new Server(manifest);
1619const body_size_limit = Number . parseInt ( env ( 'BODY_SIZE_LIMIT' , 'BODY_SIZE_LIMIT' ) ) ;
1720const binaryMediaTypes = BINARY_MEDIA_TYPES ;
1821
22+ // Get the directory of this handler file
23+ const __dirname = dirname ( fileURLToPath ( import . meta. url ) ) ;
24+
1925await server . init ( {
2026 env : process . env ,
2127} ) ;
@@ -83,6 +89,53 @@ function isALBEvent(event) {
8389 return event . requestContext && 'elb' in event . requestContext ;
8490}
8591
92+ /**
93+ * Serve static files from the bundled client directory
94+ * @param {string } path - The requested path
95+ * @returns {Promise<Response|null> } - Response for static file or null if not found
96+ */
97+ async function tryServeStaticFile ( path ) {
98+ // Handle client assets (JS, CSS, etc.)
99+ if ( path . startsWith ( '/_app/' ) || path . startsWith ( '/favicon.ico' ) ) {
100+ try {
101+ const filePath = join ( __dirname , 'client' , path ) ;
102+ const content = readFileSync ( filePath ) ;
103+
104+ // Determine content type
105+ const ext = extname ( path ) . toLowerCase ( ) ;
106+ const contentType = {
107+ '.js' : 'application/javascript' ,
108+ '.css' : 'text/css' ,
109+ '.ico' : 'image/x-icon' ,
110+ '.png' : 'image/png' ,
111+ '.jpg' : 'image/jpeg' ,
112+ '.jpeg' : 'image/jpeg' ,
113+ '.gif' : 'image/gif' ,
114+ '.svg' : 'image/svg+xml' ,
115+ '.woff' : 'font/woff' ,
116+ '.woff2' : 'font/woff2' ,
117+ '.ttf' : 'font/ttf' ,
118+ '.eot' : 'application/vnd.ms-fontobject'
119+ } [ ext ] || 'application/octet-stream' ;
120+
121+ return new Response ( content , {
122+ status : 200 ,
123+ headers : {
124+ 'Content-Type' : contentType ,
125+ 'Cache-Control' : path . includes ( '/immutable/' )
126+ ? 'public, max-age=31536000, immutable'
127+ : 'public, max-age=3600'
128+ }
129+ } ) ;
130+ } catch ( error ) {
131+ // File not found or error reading
132+ return null ;
133+ }
134+ }
135+
136+ return null ;
137+ }
138+
86139/**
87140 * AWS Lambda handler with hybrid architecture
88141 * @param {any } event - Lambda Function URL, API Gateway, or ALB event
@@ -93,6 +146,15 @@ export const handler = async (event, context) => {
93146 try {
94147 // 🔥 Use our superior event conversion (handles all Lambda event types)
95148 const webRequest = convertLambdaEventToWebRequest ( event ) ;
149+
150+ // Try to serve static files first
151+ const staticFileResponse = await tryServeStaticFile ( new URL ( webRequest . url ) . pathname ) ;
152+ if ( staticFileResponse ) {
153+ return await convertWebResponseToLambdaEvent ( staticFileResponse , {
154+ binaryMediaTypes,
155+ multiValueHeaders : isALBEvent ( event ) ,
156+ } ) ;
157+ }
96158
97159 // Convert to Node.js request format for SvelteKit
98160 const nodeRequest = convertWebRequestToNodeRequest ( webRequest , event ) ;
0 commit comments