{"version":3,"sources":["../../../../src/lib/A-ServerStatic/A-ServerStatic.component.ts"],"names":[],"mappings":"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","file":"A-ServerStatic.component.mjs","sourcesContent":["import { A_Component, A_Concept, A_Feature, A_Inject } from \"@adaas/a-concept\"\nimport { A_Request } from \"@adaas/a-server/request/A-Request.entity\";\nimport { A_Response } from \"@adaas/a-server/response/A-Response.entity\";\nimport { A_StaticConfig, A_StaticAlias } from \"./A-ServerStatic.context\";\nimport { A_HttpServerFeatures } from \"@adaas/a-server/server/A-HttpServer.constants\";\nimport { A_HttpServerError } from \"@adaas/a-server/server/A-HttpServer.error\";\nimport { A_Logger } from \"@adaas/a-utils/a-logger\";\nimport { A_Polyfill } from \"@adaas/a-utils/a-polyfill\";\nimport { A_ServerRoute } from \"@adaas/a-server/route/A-ServerRoute.entity\";\n\nexport class A_StaticLoader extends A_Component {\n\n    private _fsPolyfill: any;\n    private _pathPolyfill: any;\n\n    @A_Concept.Load()\n    async load(\n        @A_Inject(A_Logger) logger: A_Logger,\n        @A_Inject(A_StaticConfig) config: A_StaticConfig,\n        @A_Inject(A_Polyfill) polyfill: A_Polyfill\n    ) {\n        // Initialize polyfills\n        this._fsPolyfill = await polyfill.fs();\n        this._pathPolyfill = await polyfill.path();\n\n        // Log configured aliases\n        const aliases = config.getEnabledAliases();\n        logger.info('cyan',\n\n            `Static aliases configured:`,\n            ...aliases.map(alias => `${alias.alias} -> ${alias.directory}`)\n        );\n    }\n\n\n    // =======================================================\n    // ================ Method Definition=====================\n    // =======================================================\n\n    @A_Feature.Extend({\n        before: /.*/\n    })\n    async [A_HttpServerFeatures.onRequest](\n        @A_Inject(A_Request) req: A_Request,\n        @A_Inject(A_Response) res: A_Response,\n        @A_Inject(A_Logger) logger: A_Logger,\n        @A_Inject(A_StaticConfig) config: A_StaticConfig,\n        @A_Inject(A_Polyfill) polyfill: A_Polyfill\n    ) {\n\n        if (req.method !== 'GET' && req.method !== 'HEAD') {\n            return; // Only handle GET and HEAD requests\n        }\n\n        const { method, url } = req;\n        const route = new A_ServerRoute(url, method);\n\n        // Check if this request matches any of our configured aliases\n        const alias = config.findMatchingAlias(route.path);\n        if (!alias) {\n            return; // No static config for this path\n        }\n\n        try {\n            // Ensure polyfills are available\n            const fs = this._fsPolyfill || await polyfill.fs();\n            const path = this._pathPolyfill || await polyfill.path();\n\n            const staticDir = path.resolve(process.cwd(), alias.directory);\n\n            // Validate static directory exists\n            if (!fs.existsSync(staticDir)) {\n                logger.log(\"red\", `Static directory ${staticDir} does not exist.`);\n                return;\n            }\n\n            // Get the file path relative to the alias\n            const relativePath = route.path.replace(alias.path, '');\n            const safePath = this.safeFilePath(staticDir, relativePath, req.headers?.host, path, fs);\n\n            await this.serveFile(safePath, res, logger, fs, path);\n\n            logger.log('green', `Successfully served: ${safePath}`);\n\n        } catch (error: any) {\n            throw new A_HttpServerError({\n                status: 500,\n                title: 'Static File Serving Error',\n                description: `Error serving static file for ${route.path}: ${error.message}`,\n                originalError: error\n            });\n        }\n    }\n\n    /**\n     * Add a custom static file alias through the config\n     * @param alias - The URL path alias (e.g., '/assets')\n     * @param directory - The local directory path\n     * @param path - Optional custom path (defaults to alias)\n     * @param config - Static config instance\n     * @param logger - Logger instance for logging\n     */\n    public addAlias(\n        alias: string,\n        directory: string,\n        config: A_StaticConfig,\n        logger?: A_Logger,\n        path?: string\n    ): void {\n        config.addAlias(alias, directory, path);\n\n        if (logger) {\n            logger.log('cyan', `Static alias added: ${alias} -> ${directory}`);\n        }\n    }\n\n    /**\n     * Remove a static file alias through the config\n     * @param aliasPath - The path of the alias to remove\n     * @param config - Static config instance\n     * @param logger - Logger instance for logging\n     */\n    public removeAlias(aliasPath: string, config: A_StaticConfig, logger?: A_Logger): boolean {\n        const removed = config.removeAlias(aliasPath);\n\n        if (removed && logger) {\n            logger.log('yellow', `Static alias removed: ${aliasPath}`);\n        }\n\n        return removed;\n    }\n\n    /**\n     * Get all configured aliases from config\n     * @param config - Static config instance\n     */\n    public getAliases(config: A_StaticConfig): A_StaticAlias[] {\n        return config.getAliases();\n    }\n\n    /**\n     * Enable or disable an alias\n     * @param aliasPath - The path of the alias\n     * @param enabled - Whether to enable or disable\n     * @param config - Static config instance\n     * @param logger - Logger instance for logging\n     */\n    public setAliasEnabled(\n        aliasPath: string,\n        enabled: boolean,\n        config: A_StaticConfig,\n        logger?: A_Logger\n    ): boolean {\n        const result = config.setAliasEnabled(aliasPath, enabled);\n\n        if (result && logger) {\n            logger.log('blue', `Static alias ${enabled ? 'enabled' : 'disabled'}: ${aliasPath}`);\n        }\n\n        return result;\n    }\n\n    protected getMimeType(ext: string): string {\n        const mimeTypes: Record<string, string> = {\n            // Text\n            \".html\": \"text/html\",\n            \".htm\": \"text/html\",\n            \".css\": \"text/css\",\n            \".txt\": \"text/plain\",\n            \".md\": \"text/markdown\",\n            \".xml\": \"application/xml\",\n\n            // JavaScript\n            \".js\": \"application/javascript\",\n            \".mjs\": \"application/javascript\",\n            \".jsx\": \"application/javascript\",\n            \".ts\": \"application/typescript\",\n            \".tsx\": \"application/typescript\",\n\n            // JSON\n            \".json\": \"application/json\",\n            \".jsonld\": \"application/ld+json\",\n\n            // Images\n            \".png\": \"image/png\",\n            \".jpg\": \"image/jpeg\",\n            \".jpeg\": \"image/jpeg\",\n            \".gif\": \"image/gif\",\n            \".svg\": \"image/svg+xml\",\n            \".ico\": \"image/x-icon\",\n            \".webp\": \"image/webp\",\n            \".bmp\": \"image/bmp\",\n            \".tiff\": \"image/tiff\",\n\n            // Fonts\n            \".woff\": \"font/woff\",\n            \".woff2\": \"font/woff2\",\n            \".ttf\": \"font/ttf\",\n            \".otf\": \"font/otf\",\n            \".eot\": \"application/vnd.ms-fontobject\",\n\n            // Audio/Video\n            \".mp3\": \"audio/mpeg\",\n            \".wav\": \"audio/wav\",\n            \".mp4\": \"video/mp4\",\n            \".webm\": \"video/webm\",\n            \".ogg\": \"application/ogg\",\n\n            // Archives\n            \".zip\": \"application/zip\",\n            \".tar\": \"application/x-tar\",\n            \".gz\": \"application/gzip\",\n\n            // Documents\n            \".pdf\": \"application/pdf\",\n            \".doc\": \"application/msword\",\n            \".docx\": \"application/vnd.openxmlformats-officedocument.wordprocessingml.document\",\n            \".xls\": \"application/vnd.ms-excel\",\n            \".xlsx\": \"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet\",\n        };\n\n        return mimeTypes[ext.toLowerCase()] || \"application/octet-stream\";\n    }\n\n\n    protected safeFilePath(staticDir: string, reqUrl: string, host: string = 'localhost', pathPolyfill: any, fsPolyfill: any): string {\n        const parsedUrl = new URL(reqUrl || \"/\", `http://${host}`);\n        let pathname = decodeURIComponent(parsedUrl.pathname);\n\n        // Prevent path traversal attacks\n        pathname = pathname.replace(/\\.\\.[\\/\\\\]/g, \"\");\n\n        let filePath = pathPolyfill.join(staticDir, pathname);\n\n        if (!fsPolyfill.existsSync(filePath)) {\n            throw new Error(`File not found: ${filePath}`);\n        }\n\n        return filePath;\n    }\n\n    protected serveFile(\n        filePath: string,\n        res: A_Response,\n        logger: A_Logger,\n        fsPolyfill: any,\n        pathPolyfill: any\n    ): Promise<void> {\n        return new Promise<void>((resolve, reject) => {\n            try {\n                if (fsPolyfill.existsSync(filePath)) {\n                    const ext = pathPolyfill.extname(filePath);\n                    const contentType = this.getMimeType(ext);\n\n                    // Set appropriate headers\n                    const headers: Record<string, string> = {\n                        \"Content-Type\": contentType,\n                        \"Cache-Control\": this.getCacheControl(ext),\n                        \"X-Content-Type-Options\": \"nosniff\"\n                    };\n\n                    res.writeHead(200, headers);\n\n                    const stream = fsPolyfill.createReadStream(filePath);\n\n                    if (stream && res.original) {\n                        stream.pipe(res.original);\n\n                        stream.on('end', () => {\n                            resolve();\n                        });\n\n                        stream.on(\"error\", (err: any) => {\n                            reject(new A_HttpServerError({\n                                status: 500,\n                                title: 'File Stream Error',\n                                description: `Error reading file stream for ${filePath}: ${err.message}`,\n                                originalError: err\n                            }));\n                        });\n                    } else {\n                        reject(new A_HttpServerError({\n                            status: 500,\n                            title: 'Response Stream Error',\n                            description: `Unable to pipe file stream for ${filePath}`,\n                        }));\n                    }\n                } else {\n                    reject(new A_HttpServerError({\n                        status: 404,\n                        title: 'File Not Found',\n                        description: `File not found: ${filePath}`,\n                    }));\n                }\n            } catch (error: any) {\n                logger.error(`Error serving file: ${error.message}`);\n                reject(new A_HttpServerError({\n                    status: 500,\n                    title: 'Internal Server Error',\n                    description: `Error serving file: ${error.message}`,\n                    originalError: error\n                }));\n            }\n        });\n    }\n\n    protected getCacheControl(ext: string): string {\n        // Different cache strategies for different file types\n        const staticAssets = ['.css', '.js', '.png', '.jpg', '.jpeg', '.gif', '.svg', '.ico', '.woff', '.woff2', '.ttf', '.otf'];\n        const dynamicContent = ['.html', '.htm'];\n\n        if (staticAssets.includes(ext.toLowerCase())) {\n            return \"public, max-age=31536000\"; // 1 year for static assets\n        } else if (dynamicContent.includes(ext.toLowerCase())) {\n            return \"public, max-age=3600\"; // 1 hour for HTML\n        } else {\n            return \"public, max-age=86400\"; // 1 day for other files\n        }\n    }\n\n}\n\n\n"]}