diff --git a/package.json b/package.json index 4b9492e3d..955bbbd5c 100644 --- a/package.json +++ b/package.json @@ -28,6 +28,7 @@ "copy:assets": "cpx \"models/**\" \"electron/models/\" && cpx \"docs/openapi/**\" \"electron/docs/openapi\"", "dev:electron": "yarn copy:assets && yarn workspace jan dev", "dev:web": "yarn workspace jan-web dev", + "dev:server": "yarn workspace @janhq/server dev", "dev": "concurrently --kill-others \"yarn dev:web\" \"wait-on http://localhost:3000 && yarn dev:electron\"", "test-local": "yarn lint && yarn build:test && yarn test", "dev:uikit": "yarn workspace @janhq/uikit install && yarn workspace @janhq/uikit dev", diff --git a/server/index.ts b/server/index.ts index 49d37a447..1df03c776 100644 --- a/server/index.ts +++ b/server/index.ts @@ -5,25 +5,62 @@ import path from "path"; import os from "os"; +// Load environment variables dotenv.config(); +// Define default settings const JAN_API_HOST = process.env.JAN_API_HOST || "127.0.0.1"; const JAN_API_PORT = Number.parseInt(process.env.JAN_API_PORT || "1337"); const serverLogPath = path.join(os.homedir(), "jan", "logs", "server.log"); +// Initialize server settings let server: any | undefined = undefined; +let hostSetting: string = JAN_API_HOST; +let portSetting: number = JAN_API_PORT; +let corsEnbaled: boolean = true; +let isVerbose: boolean = true; -export const startServer = async (schemaPath?: string, baseDir?: string) => { +/** + * Function to start the server + * @param host - The host address for the server + * @param port - The port number for the server + * @param isCorsEnabled - Flag to enable or disable CORS + * @param isVerboseEnabled - Flag to enable or disable verbose logging + * @param schemaPath - Path to the OpenAPI schema file + * @param baseDir - Base directory for the OpenAPI schema file + */ +export const startServer = async ( + host?: string, + port?: number, + isCorsEnabled?: boolean, + isVerboseEnabled?: boolean, + schemaPath?: string, + baseDir?: string +) => { + // Update server settings + isVerbose = isVerboseEnabled ?? true; + hostSetting = host ?? JAN_API_HOST; + portSetting = port ?? JAN_API_PORT; + corsEnbaled = isCorsEnabled ?? true; + + // Start the server try { - log(`[API]::Debug: Starting JAN API server...`, "server.log") + // Log server start + if (isVerbose) + log(`[API]::Debug: Starting JAN API server...`, "server.log"); + + // Initialize Fastify server with logging server = fastify({ logger: { level: "info", file: serverLogPath, }, }); - await server.register(require("@fastify/cors"), {}); + // Register CORS if enabled + if (corsEnbaled) await server.register(require("@fastify/cors"), {}); + + // Register Swagger for API documentation await server.register(require("@fastify/swagger"), { mode: "static", specification: { @@ -32,6 +69,7 @@ export const startServer = async (schemaPath?: string, baseDir?: string) => { }, }); + // Register Swagger UI await server.register(require("@fastify/swagger-ui"), { routePrefix: "/", baseDir: baseDir ?? path.join(__dirname, "../..", "./docs/openapi"), @@ -43,6 +81,8 @@ export const startServer = async (schemaPath?: string, baseDir?: string) => { transformSpecificationClone: true, }); + // Register static file serving for extensions + // TODO: Watch extension files changes and reload await server.register( (childContext: any, _: any, done: any) => { childContext.register(require("@fastify/static"), { @@ -56,25 +96,64 @@ export const startServer = async (schemaPath?: string, baseDir?: string) => { }, { prefix: "extensions" } ); + + // Register API routes await server.register(v1Router, { prefix: "/v1" }); + + // Start listening for requests await server .listen({ - port: JAN_API_PORT, - host: JAN_API_HOST, + port: hostSetting, + host: portSetting, }) .then(() => { - log(`[API]::Debug: JAN API listening at: http://${JAN_API_HOST}:${JAN_API_PORT}`); + // Log server listening + if (isVerbose) + log( + `[API]::Debug: JAN API listening at: http://${JAN_API_HOST}:${JAN_API_PORT}` + ); }); } catch (e) { - log(`[API]::Error: ${e}`); + // Log any errors + if (isVerbose) log(`[API]::Error: ${e}`); } }; +/** + * Function to stop the server + */ export const stopServer = async () => { try { - log(`[API]::Debug: Server stopped`, "server.log") + // Log server stop + if (isVerbose) log(`[API]::Debug: Server stopped`, "server.log"); + // Stop the server await server.close(); } catch (e) { - log(`[API]::Error: ${e}`); + // Log any errors + if (isVerbose) log(`[API]::Error: ${e}`); } }; + +/** + * Function to check if CORS is enabled + * @returns - True if CORS is enabled, false otherwise + */ +export const isCorsEnabled = () => corsEnbaled; + +/** + * Function to check if verbose logging is enabled + * @returns - True if verbose logging is enabled, false otherwise + */ +export const isVerboseEnabled = () => isVerbose; + +/** + * Function to get the host setting + * @returns - The current host setting + */ +export const getHost = () => hostSetting; + +/** + * Function to get the port setting + * @returns - The current port setting + */ +export const getPort = () => portSetting;