@cruxjs/app 0.0.2 → 0.0.3
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/README.md +1 -1
- package/dist/index.cjs +2 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
</div>
|
|
9
9
|
|
|
10
10
|
<div align="center">
|
|
11
|
-
<img src="https://img.shields.io/badge/v-0.0.
|
|
11
|
+
<img src="https://img.shields.io/badge/v-0.0.3-black"/>
|
|
12
12
|
<img src="https://img.shields.io/badge/🔥-@cruxjs-black"/>
|
|
13
13
|
<br>
|
|
14
14
|
<img src="https://img.shields.io/github/issues/cruxjs-org/app?style=flat" alt="Github Repo Issues" />
|
package/dist/index.cjs
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
'use strict';var base=require('@cruxjs/base'),server=require('@minejs/server'),db=require('@minejs/db'),i18n=require('@minejs/i18n');async function
|
|
2
|
-
exports.createApp=
|
|
1
|
+
'use strict';var base=require('@cruxjs/base'),server=require('@minejs/server'),db=require('@minejs/db'),i18n=require('@minejs/i18n');async function k(t,r){if(!t.client)return null;r.info("Building client...");try{let e=await Bun.build({entrypoints:[t.client.entry],outdir:t.client.output,target:t.client.target||"browser",minify:t.client.minify??!t.debug,sourcemap:t.client.sourcemap??t.debug?"inline":"none",external:t.client.external||[]});if(!e.success)throw new Error("Build failed");let s=e.outputs.map(i=>i.path);return r.success(`Client built \u2192 ${s.join(", ")}`),{success:!0,outputs:s}}catch(e){throw r.error("Failed to build client",e),e}}async function F(t,r){if(!t.ui)return null;r.info(`Building UI from package: ${t.ui.package}...`);try{if(await Bun.spawn(["bun","add",t.ui.package],{stdio:["ignore","pipe","pipe"]}).exited!==0)throw new Error(`Failed to install UI package: ${t.ui.package}`);return r.info(`UI package installed: ${t.ui.package}`),r.success(`UI built \u2192 ${t.ui.output}`),{success:!0,output:t.ui.output}}catch(e){throw r.error("Failed to build UI",e),e}}async function H(t,r){if(!t.style)return null;r.info(`Building styles from: ${t.style.entry}...`);try{if(!(await Bun.build({entrypoints:[t.style.entry],outdir:t.style.output,minify:t.style.minify??!t.debug,sourcemap:t.style.sourcemap??t.debug?"inline":"none"})).success)throw new Error("Style build failed");return r.success(`Styles built \u2192 ${t.style.output}`),{success:!0,output:t.style.output}}catch(e){throw r.error("Failed to build styles",e),e}}async function P(t,r,e){let s=new Map;if(!t.database&&r.length===0)return e.info("No database config, skipping setup"),s;let i=t.database?Array.isArray(t.database)?t.database:[t.database]:[];e.info("Setting up databases...");for(let o of i){let c=o.name||"default",l=new db.DB(o.connection);if(o.schema)try{let u=await import(o.schema),d=u.default||u.schema;if(Array.isArray(d))for(let a of d)l.defineSchema(a);}catch(u){throw e.error(`Failed to load schema: ${o.schema}`,u),u}for(let u of r)l.defineSchema(u);s.set(c,l),e.success(`Database '${c}' ready`);}if(s.size===0&&r.length>0){let o=new db.DB(":memory:");for(let c of r)o.defineSchema(c);s.set("default",o),e.success("Database 'default' ready (in-memory for plugins)");}return s}async function T(t,r){if(t.i18n){r.info("Setting up i18n...");try{await i18n.setupAuto({defaultLanguage:t.i18n.defaultLanguage,supportedLanguages:t.i18n.supportedLanguages,basePath:t.i18n.basePath,fileExtension:t.i18n.fileExtension||"json"}),r.success(`i18n ready \u2192 ${t.i18n.supportedLanguages.join(", ")}`);}catch(e){throw r.error("Failed to setup i18n",e),e}}}async function U(t,r){if(!t.api)return [];r.info(`Loading routes from ${t.api.directory}...`);let e=[];try{let s=await j(t.api.directory);for(let i of s)try{let o=await import(i),c=o.default||o.routes;Array.isArray(c)&&e.push(...c);}catch(o){r.error(`Failed to load routes from ${i}`,o);}return r.success(`Routes loaded \u2192 ${e.length} routes`),e}catch(s){return r.error("Failed to scan route directory",s),[]}}async function j(t){let r=[];try{let e=await Array.fromAsync(new Bun.Glob("**/*.{ts,js}").scan(t));for(let s of e)r.push(`${t}/${s}`);}catch{}return r}function Q(t,r){let e=r?.onConfig?r.onConfig(t):t,s=new base.Logger(e.debug),i=new base.PluginRegistry(s),o=new base.ResourceMerger(s),c=new Map,l=new Map,u=null,d=null,a={config:e,databases:c,plugins:[]},b={config:e,server:null,databases:c,plugins:[],middlewares:l,start:async()=>{},stop:async()=>{},restart:async()=>{},getContext:()=>a,getMiddleware:n=>l.get(n)};async function S(){if(!e.plugins||e.plugins.length===0){s.info("No plugins to register");return}s.phase("REGISTER");for(let p of e.plugins)await i.register(p,b);a.plugins=i.getAll(),i.collectMiddlewares().forEach((p,y)=>l.set(y,p));}async function C(){s.phase("AWAKE");try{d=await k(e,s),a.clientBuild=d;let n=await F(e,s);a.uiBuild=n;let p=await H(e,s);a.styleBuild=p;let y=i.collectSchemas(),g=await P(e,y,s);c.clear(),g.forEach((h,m)=>c.set(m,h)),await T(e,s),await i.callHook("onAwake",a),await r?.onAwake?.(a);}catch(n){throw await r?.onError?.(a,"AWAKE",n),n}}async function L(){s.phase("START");try{let n=await U(e,s),p=i.collectRoutes(),g=[...e.routes||[],...n],h=o.mergeRoutes(g,p),m=e.static?Array.isArray(e.static)?e.static:[e.static]:[],v=i.collectStatic(),A=o.mergeStatic(m,v);s.info("Creating server...");let E;for(let f of a.plugins){let w=f;if(w.__spaErrorHandler){E=w.__spaErrorHandler,console.log(`[CruxJS] \u2713 Error handler collected from: ${f.name}`);break}}u=server.server({port:e.server?.port||3e3,hostname:e.server?.host||"localhost",logging:e.server?.logging,routes:h,static:A.length>0?A:void 0,security:e.security,middlewares:e.middlewares,i18n:e.i18n?{defaultLanguage:e.i18n.defaultLanguage,supportedLanguages:e.i18n.supportedLanguages}:void 0,onError:E}),c.forEach((f,w)=>{u.db.set(w,f);}),a.server=u,b.server=u,s.success(`Server created \u2192 ${e.server?.host||"localhost"}:${e.server?.port||3e3}`),await i.callHook("onStart",a),await r?.onStart?.(a);}catch(n){throw await r?.onError?.(a,"START",n),n}}async function $(){s.phase("READY");try{await u.start(),s.success(`Server running on http://${e.server?.host||"localhost"}:${e.server?.port||3e3}`),await i.callHook("onReady",a),await r?.onReady?.(a);}catch(n){throw await r?.onError?.(a,"READY",n),n}}return {config:e,server:u,databases:c,plugins:a.plugins,middlewares:l,async start(){await S(),await C(),await L(),await $();},async stop(){s.info("Stopping server...");try{u&&await u.stop(),c.forEach((n,p)=>{n.close(),s.info(`Database '${p}' closed`);}),await i.callHook("onShutdown",a),await r?.onFinish?.(a),s.success("Server stopped");}catch(n){throw s.error("Failed to stop server",n),n}},async restart(){await this.stop(),await this.start();},getContext(){return a},getMiddleware(n){return l.get(n)}}}
|
|
2
|
+
exports.createApp=Q;Object.keys(base).forEach(function(k){if(k!=='default'&&!Object.prototype.hasOwnProperty.call(exports,k))Object.defineProperty(exports,k,{enumerable:true,get:function(){return base[k]}})});//# sourceMappingURL=index.cjs.map
|
|
3
3
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"names":["buildClient","config","logger","result","outputs","err","setupDatabases","additionalSchemas","databases","dbConfigs","dbConfig","name","db","DB","schemaModule","schema","table","setupI18n","setupAuto","loadRoutes","routes","files","scanDirectory","file","module","exported","dir","entries","entry","createApp","userConfig","hooks","Logger","pluginRegistry","PluginRegistry","resourceMerger","ResourceMerger","middlewares","serverInstance","clientBuild","ctx","partialApp","phaseRegister","plugin","mw","phaseAwake","pluginSchemas","dbs","phaseStart","userApiRoutes","pluginRoutes","allUserRoutes","mergedRoutes","userStatic","pluginStatic","mergedStatic","errorHandler","pluginWithHandler","createServer","phaseReady"],"mappings":"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","file":"index.cjs","sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any */\r\n// src/index.ts\r\n//\r\n// Made with ❤️ by Maysara.\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ PACK ════════════════════════════════════════╗\r\n\r\n import { AppConfig, LifecycleContext, LifecycleHooks, AppInstance, RouteDefinition, AppMiddleware, Logger, PluginRegistry, ResourceMerger } from '@cruxjs/base';\r\n import { server as createServer } from '@minejs/server';\r\n import { DB } from '@minejs/db';\r\n import { setupAuto } from '@minejs/i18n';\r\n import type { TableSchema } from '@minejs/db';\r\n\r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ CORE ════════════════════════════════════════╗\r\n\r\n /**\r\n * Builds the client bundle using Bun's bundler\r\n * \r\n * @param {AppConfig} config - The application configuration containing client build settings\r\n * @param {Logger} logger - Logger instance for logging build progress and errors\r\n * @returns {Promise<{success: boolean, outputs: string[]} | null>} Build result with output paths, or null if no client config\r\n * @throws {Error} If the build process fails\r\n * \r\n * @example\r\n * const result = await buildClient(config, logger);\r\n * if (result?.success) {\r\n * console.log('Built to:', result.outputs);\r\n * }\r\n */\r\n async function buildClient(config: AppConfig, logger: Logger) {\r\n if (!config.client) return null;\r\n\r\n logger.info('Building client...');\r\n\r\n try {\r\n const result = await Bun.build({\r\n entrypoints: [config.client.entry],\r\n outdir: config.client.output,\r\n target: config.client.target || 'browser',\r\n minify: config.client.minify ?? !config.debug,\r\n sourcemap: config.client.sourcemap ?? config.debug ? 'inline' : 'none',\r\n external: config.client.external || []\r\n });\r\n\r\n if (!result.success) throw new Error('Build failed');\r\n\r\n const outputs = result.outputs.map(o => o.path);\r\n logger.success(`Client built → ${outputs.join(', ')}`);\r\n\r\n return { success: true, outputs };\r\n } catch (err) {\r\n logger.error('Failed to build client', err as Error);\r\n throw err;\r\n }\r\n }\r\n\r\n /**\r\n * Initializes and configures database connections\r\n * \r\n * Handles:\r\n * - Multiple database instances (primary, cache, etc.)\r\n * - User-defined schemas from config\r\n * - Plugin schemas from plugins\r\n * - In-memory databases for plugin-only scenarios\r\n * \r\n * @param {AppConfig} config - Application configuration with database settings\r\n * @param {TableSchema[]} additionalSchemas - Database schemas provided by plugins\r\n * @param {Logger} logger - Logger instance for logging setup progress\r\n * @returns {Promise<Map<string, DB>>} Map of database instances by name\r\n * @throws {Error} If schema loading or database initialization fails\r\n * \r\n * @example\r\n * const databases = await setupDatabases(config, pluginSchemas, logger);\r\n * const db = databases.get('primary');\r\n * const result = db.query('SELECT * FROM users');\r\n */\r\n async function setupDatabases(\r\n config: AppConfig,\r\n additionalSchemas: TableSchema[],\r\n logger: Logger\r\n ) {\r\n const databases = new Map<string, DB>();\r\n\r\n if (!config.database && additionalSchemas.length === 0) {\r\n logger.info('No database config, skipping setup');\r\n return databases;\r\n }\r\n\r\n const dbConfigs = config.database\r\n ? Array.isArray(config.database)\r\n ? config.database\r\n : [config.database]\r\n : [];\r\n\r\n logger.info('Setting up databases...');\r\n\r\n for (const dbConfig of dbConfigs) {\r\n const name = dbConfig.name || 'default';\r\n const db = new DB(dbConfig.connection);\r\n\r\n // Load user schema\r\n if (dbConfig.schema) {\r\n try {\r\n const schemaModule = await import(dbConfig.schema);\r\n const schema = schemaModule.default || schemaModule.schema;\r\n\r\n if (Array.isArray(schema)) {\r\n for (const table of schema) {\r\n db.defineSchema(table);\r\n }\r\n }\r\n } catch (err) {\r\n logger.error(`Failed to load schema: ${dbConfig.schema}`, err as Error);\r\n throw err;\r\n }\r\n }\r\n\r\n // Load plugin schemas for this database\r\n for (const schema of additionalSchemas) {\r\n db.defineSchema(schema);\r\n }\r\n\r\n databases.set(name, db);\r\n logger.success(`Database '${name}' ready`);\r\n }\r\n\r\n // If no user database but plugins need one, create default\r\n if (databases.size === 0 && additionalSchemas.length > 0) {\r\n const db = new DB(':memory:');\r\n\r\n for (const schema of additionalSchemas) {\r\n db.defineSchema(schema);\r\n }\r\n\r\n databases.set('default', db);\r\n logger.success(`Database 'default' ready (in-memory for plugins)`);\r\n }\r\n\r\n return databases;\r\n }\r\n\r\n /**\r\n * Initializes internationalization (i18n) support\r\n * \r\n * Loads language files and configures the i18n system based on:\r\n * - Default language\r\n * - Supported languages\r\n * - Base path for translation files\r\n * - File extension (json, cjson, etc.)\r\n * \r\n * @param {AppConfig} config - Application configuration with i18n settings\r\n * @param {Logger} logger - Logger instance for logging setup progress\r\n * @returns {Promise<void>}\r\n * @throws {Error} If i18n setup or language file loading fails\r\n * \r\n * @example\r\n * await setupI18n({\r\n * i18n: {\r\n * defaultLanguage: 'en',\r\n * supportedLanguages: ['en', 'ar'],\r\n * basePath: './src/i18n'\r\n * }\r\n * }, logger);\r\n */\r\n async function setupI18n(config: AppConfig, logger: Logger) {\r\n if (!config.i18n) return;\r\n\r\n logger.info('Setting up i18n...');\r\n\r\n try {\r\n await setupAuto({\r\n defaultLanguage: config.i18n.defaultLanguage,\r\n supportedLanguages: config.i18n.supportedLanguages,\r\n basePath: config.i18n.basePath,\r\n fileExtension: config.i18n.fileExtension || 'json'\r\n });\r\n\r\n logger.success(`i18n ready → ${config.i18n.supportedLanguages.join(', ')}`);\r\n } catch (err) {\r\n logger.error('Failed to setup i18n', err as Error);\r\n throw err;\r\n }\r\n }\r\n\r\n /**\r\n * Dynamically loads route definitions from API directory\r\n * \r\n * Scans the specified directory for route files and imports them.\r\n * Each route file should export either:\r\n * - `routes` property with RouteDefinition array\r\n * - Default export with RouteDefinition array\r\n * \r\n * @param {AppConfig} config - Application configuration with api.directory\r\n * @param {Logger} logger - Logger instance for logging scan progress\r\n * @returns {Promise<RouteDefinition[]>} Array of loaded route definitions\r\n * \r\n * @example\r\n * const routes = await loadRoutes({\r\n * api: { directory: './src/server/api' }\r\n * }, logger);\r\n * console.log(`Loaded ${routes.length} routes`);\r\n */\r\n async function loadRoutes(config: AppConfig, logger: Logger): Promise<RouteDefinition[]> {\r\n if (!config.api) return [];\r\n\r\n logger.info(`Loading routes from ${config.api.directory}...`);\r\n\r\n const routes: RouteDefinition[] = [];\r\n\r\n try {\r\n const files = await scanDirectory(config.api.directory);\r\n\r\n for (const file of files) {\r\n try {\r\n const module = await import(file);\r\n const exported = module.default || module.routes;\r\n\r\n if (Array.isArray(exported)) {\r\n routes.push(...exported);\r\n }\r\n } catch (err) {\r\n logger.error(`Failed to load routes from ${file}`, err as Error);\r\n }\r\n }\r\n\r\n logger.success(`Routes loaded → ${routes.length} routes`);\r\n return routes;\r\n } catch (err) {\r\n logger.error('Failed to scan route directory', err as Error);\r\n return [];\r\n }\r\n }\r\n\r\n /**\r\n * Scans a directory for TypeScript/JavaScript files\r\n * \r\n * Uses Bun's Glob API to recursively find all .ts and .js files in a directory.\r\n * Gracefully handles non-existent directories (returns empty array).\r\n * \r\n * @param {string} dir - Directory path to scan\r\n * @returns {Promise<string[]>} Array of absolute file paths found\r\n * \r\n * @example\r\n * const files = await scanDirectory('./src/server/api');\r\n * // Returns: ['./src/server/api/users.ts', './src/server/api/posts.ts']\r\n */\r\n async function scanDirectory(dir: string): Promise<string[]> {\r\n const files: string[] = [];\r\n\r\n try {\r\n const entries = await Array.fromAsync(\r\n new Bun.Glob('**/*.{ts,js}').scan(dir)\r\n );\r\n\r\n for (const entry of entries) {\r\n files.push(`${dir}/${entry}`);\r\n }\r\n } catch {\r\n // Directory doesn't exist\r\n }\r\n\r\n return files;\r\n }\r\n\r\n /**\r\n * Creates a CruxJS application instance with full lifecycle management\r\n * \r\n * This is the main entry point for building a CruxJS application. It:\r\n * 1. Registers plugins (Phase 0)\r\n * 2. Builds client, initializes databases, setups i18n (Phase 1: AWAKE)\r\n * 3. Creates server, merges routes and middleware (Phase 2: START)\r\n * 4. Starts the server and enables request handling (Phase 3: READY)\r\n * \r\n * Phases execute sequentially when `app.start()` is called.\r\n * \r\n * @param {AppConfig} userConfig - Application configuration object\r\n * @param {LifecycleHooks} [hooks] - Optional lifecycle event handlers\r\n * @returns {AppInstance} Application instance with control methods\r\n * \r\n * @throws {Error} Will throw if any lifecycle phase fails (unless caught in onError hook)\r\n * \r\n * @example\r\n * // Basic usage\r\n * const app = createApp({\r\n * debug: true,\r\n * server: { port: 3000 },\r\n * api: { directory: './src/api' },\r\n * plugins: [spaPlugin]\r\n * });\r\n * await app.start();\r\n * \r\n * @example\r\n * // With lifecycle hooks\r\n * const app = createApp(config, {\r\n * onAwake: async (ctx) => {\r\n * console.log('⏰ App awoken, databases ready');\r\n * },\r\n * onReady: async (ctx) => {\r\n * console.log('✅ Server ready:', ctx.server.getURL());\r\n * },\r\n * onError: async (ctx, phase, error) => {\r\n * console.error(`Error in ${phase}:`, error.message);\r\n * }\r\n * });\r\n * \r\n * @example\r\n * // With cleanup\r\n * const app = createApp(config);\r\n * await app.start();\r\n * // ... server is running\r\n * await app.stop(); // Cleanup\r\n */\r\n export function createApp(\r\n userConfig: AppConfig,\r\n hooks?: LifecycleHooks\r\n ): AppInstance {\r\n // Apply config hook\r\n const config: AppConfig = hooks?.onConfig\r\n ? hooks.onConfig(userConfig) as AppConfig\r\n : userConfig;\r\n\r\n const logger = new Logger(config.debug);\r\n const pluginRegistry = new PluginRegistry(logger);\r\n const resourceMerger = new ResourceMerger(logger);\r\n\r\n const databases = new Map<string, DB>();\r\n const middlewares = new Map<string, AppMiddleware>();\r\n let serverInstance: any = null;\r\n let clientBuild: any = null;\r\n\r\n const ctx: LifecycleContext = {\r\n config,\r\n databases,\r\n plugins: []\r\n };\r\n\r\n // Create partial app instance for plugin registration\r\n const partialApp: AppInstance = {\r\n config,\r\n server: null,\r\n databases,\r\n plugins: [],\r\n middlewares,\r\n start: async () => { },\r\n stop: async () => { },\r\n restart: async () => { },\r\n getContext: () => ctx,\r\n getMiddleware: (name: string) => middlewares.get(name)\r\n };\r\n\r\n // ─────────────────────────────────────────────────────────\r\n // Phase 0: Plugin Registration\r\n // ─────────────────────────────────────────────────────────\r\n\r\n async function phaseRegister() {\r\n if (!config.plugins || config.plugins.length === 0) {\r\n logger.info('No plugins to register');\r\n return;\r\n }\r\n\r\n logger.phase('REGISTER');\r\n\r\n for (const plugin of config.plugins) {\r\n await pluginRegistry.register(plugin, partialApp);\r\n }\r\n\r\n ctx.plugins = pluginRegistry.getAll();\r\n\r\n // Collect plugin middlewares\r\n const pluginMiddlewares = pluginRegistry.collectMiddlewares();\r\n pluginMiddlewares.forEach((mw, name) => middlewares.set(name, mw));\r\n }\r\n\r\n // ─────────────────────────────────────────────────────────\r\n // Phase 1: AWAKE\r\n // ─────────────────────────────────────────────────────────\r\n\r\n async function phaseAwake() {\r\n logger.phase('AWAKE');\r\n\r\n try {\r\n // Build client\r\n clientBuild = await buildClient(config, logger);\r\n ctx.clientBuild = clientBuild;\r\n\r\n // Collect plugin schemas\r\n const pluginSchemas = pluginRegistry.collectSchemas();\r\n\r\n // Setup databases\r\n const dbs = await setupDatabases(config, pluginSchemas, logger);\r\n databases.clear();\r\n dbs.forEach((db, name) => databases.set(name, db));\r\n\r\n // Setup i18n\r\n await setupI18n(config, logger);\r\n\r\n // Call plugin hooks\r\n await pluginRegistry.callHook('onAwake', ctx);\r\n\r\n // Call user hook\r\n await hooks?.onAwake?.(ctx);\r\n } catch (err) {\r\n await hooks?.onError?.(ctx, 'AWAKE', err as Error);\r\n throw err;\r\n }\r\n }\r\n\r\n // ─────────────────────────────────────────────────────────\r\n // Phase 2: START\r\n // ─────────────────────────────────────────────────────────\r\n\r\n async function phaseStart() {\r\n logger.phase('START');\r\n\r\n try {\r\n // Load user routes\r\n const userApiRoutes = await loadRoutes(config, logger);\r\n\r\n // Collect plugin routes\r\n const pluginRoutes = pluginRegistry.collectRoutes();\r\n\r\n // Merge user routes + plugin routes\r\n const userRoutes = config.routes || [];\r\n const allUserRoutes = [...userRoutes, ...userApiRoutes];\r\n const mergedRoutes = resourceMerger.mergeRoutes(allUserRoutes, pluginRoutes);\r\n\r\n // Collect static configs\r\n const userStatic = config.static\r\n ? Array.isArray(config.static)\r\n ? config.static\r\n : [config.static]\r\n : [];\r\n const pluginStatic = pluginRegistry.collectStatic();\r\n const mergedStatic = resourceMerger.mergeStatic(userStatic, pluginStatic);\r\n\r\n logger.info('Creating server...');\r\n\r\n // Collect error handlers from plugins (especially SPA plugin)\r\n let errorHandler: ((statusCode: number, path: string) => Response) | undefined;\r\n for (const plugin of ctx.plugins) {\r\n const pluginWithHandler = plugin as any;\r\n if (pluginWithHandler.__spaErrorHandler) {\r\n errorHandler = pluginWithHandler.__spaErrorHandler;\r\n console.log(`[CruxJS] ✓ Error handler collected from: ${plugin.name}`);\r\n break; // Use first error handler found\r\n }\r\n }\r\n\r\n // Create server\r\n serverInstance = createServer({\r\n port: config.server?.port || 3000,\r\n hostname: config.server?.host || 'localhost',\r\n logging: config.server?.logging,\r\n routes: mergedRoutes,\r\n static: mergedStatic.length > 0 ? mergedStatic : undefined,\r\n security: config.security,\r\n middlewares: config.middlewares,\r\n i18n: config.i18n\r\n ? {\r\n defaultLanguage: config.i18n.defaultLanguage,\r\n supportedLanguages: config.i18n.supportedLanguages\r\n }\r\n : undefined,\r\n onError: errorHandler\r\n });\r\n\r\n // Inject databases\r\n databases.forEach((db, name) => {\r\n serverInstance.db.set(name, db);\r\n });\r\n\r\n ctx.server = serverInstance;\r\n partialApp.server = serverInstance;\r\n\r\n logger.success(\r\n `Server created → ${config.server?.host || 'localhost'}:${config.server?.port || 3000}`\r\n );\r\n\r\n // Call plugin hooks\r\n await pluginRegistry.callHook('onStart', ctx);\r\n\r\n // Call user hook\r\n await hooks?.onStart?.(ctx);\r\n } catch (err) {\r\n await hooks?.onError?.(ctx, 'START', err as Error);\r\n throw err;\r\n }\r\n }\r\n\r\n // ─────────────────────────────────────────────────────────\r\n // Phase 3: READY\r\n // ─────────────────────────────────────────────────────────\r\n\r\n async function phaseReady() {\r\n logger.phase('READY');\r\n\r\n try {\r\n await serverInstance.start();\r\n\r\n logger.success(\r\n `Server running on http://${config.server?.host || 'localhost'}:${config.server?.port || 3000}`\r\n );\r\n\r\n // Call plugin hooks\r\n await pluginRegistry.callHook('onReady', ctx);\r\n\r\n // Call user hook\r\n await hooks?.onReady?.(ctx);\r\n } catch (err) {\r\n await hooks?.onError?.(ctx, 'READY', err as Error);\r\n throw err;\r\n }\r\n }\r\n\r\n // ─────────────────────────────────────────────────────────\r\n // App Instance\r\n // ─────────────────────────────────────────────────────────\r\n\r\n return {\r\n config,\r\n server: serverInstance,\r\n databases,\r\n plugins: ctx.plugins,\r\n middlewares,\r\n\r\n async start() {\r\n await phaseRegister();\r\n await phaseAwake();\r\n await phaseStart();\r\n await phaseReady();\r\n },\r\n\r\n async stop() {\r\n logger.info('Stopping server...');\r\n\r\n try {\r\n if (serverInstance) {\r\n await serverInstance.stop();\r\n }\r\n\r\n databases.forEach((db, name) => {\r\n db.close();\r\n logger.info(`Database '${name}' closed`);\r\n });\r\n\r\n // Call plugin hooks\r\n await pluginRegistry.callHook('onShutdown', ctx);\r\n\r\n await hooks?.onFinish?.(ctx);\r\n\r\n logger.success('Server stopped');\r\n } catch (err) {\r\n logger.error('Failed to stop server', err as Error);\r\n throw err;\r\n }\r\n },\r\n\r\n async restart() {\r\n await this.stop();\r\n await this.start();\r\n },\r\n\r\n getContext() {\r\n return ctx;\r\n },\r\n\r\n getMiddleware(name: string) {\r\n return middlewares.get(name);\r\n }\r\n };\r\n }\r\n\r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ ════ ════════════════════════════════════════╗\r\n\r\n export * from '@cruxjs/base';\r\n\r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"names":["buildClient","config","logger","result","outputs","o","err","buildUI","buildStyles","setupDatabases","additionalSchemas","databases","dbConfigs","dbConfig","name","db","DB","schemaModule","schema","table","setupI18n","setupAuto","loadRoutes","routes","files","scanDirectory","file","module","exported","dir","entries","entry","createApp","userConfig","hooks","Logger","pluginRegistry","PluginRegistry","resourceMerger","ResourceMerger","middlewares","serverInstance","clientBuild","ctx","partialApp","phaseRegister","plugin","mw","phaseAwake","uiBuild","styleBuild","pluginSchemas","dbs","phaseStart","userApiRoutes","pluginRoutes","allUserRoutes","mergedRoutes","userStatic","pluginStatic","mergedStatic","errorHandler","pluginWithHandler","createServer","phaseReady"],"mappings":"qIAmCI,eAAeA,CAAAA,CAAYC,CAAAA,CAAmBC,EAAgB,CAC1D,GAAI,CAACD,CAAAA,CAAO,OAAQ,OAAO,IAAA,CAE3BC,CAAAA,CAAO,IAAA,CAAK,oBAAoB,CAAA,CAEhC,GAAI,CACA,IAAMC,CAAAA,CAAS,MAAM,GAAA,CAAI,KAAA,CAAM,CAC3B,WAAA,CAAa,CAACF,CAAAA,CAAO,MAAA,CAAO,KAAK,CAAA,CACjC,MAAA,CAAQA,CAAAA,CAAO,MAAA,CAAO,OACtB,MAAA,CAAQA,CAAAA,CAAO,MAAA,CAAO,MAAA,EAAU,UAChC,MAAA,CAAQA,CAAAA,CAAO,MAAA,CAAO,MAAA,EAAU,CAACA,CAAAA,CAAO,KAAA,CACxC,SAAA,CAAWA,CAAAA,CAAO,OAAO,SAAA,EAAaA,CAAAA,CAAO,KAAA,CAAQ,QAAA,CAAW,OAChE,QAAA,CAAUA,CAAAA,CAAO,MAAA,CAAO,QAAA,EAAY,EACxC,CAAC,CAAA,CAED,GAAI,CAACE,CAAAA,CAAO,OAAA,CAAS,MAAM,IAAI,KAAA,CAAM,cAAc,CAAA,CAEnD,IAAMC,EAAUD,CAAAA,CAAO,OAAA,CAAQ,GAAA,CAAIE,CAAAA,EAAKA,EAAE,IAAI,CAAA,CAC9C,OAAAH,CAAAA,CAAO,QAAQ,CAAA,oBAAA,EAAkBE,CAAAA,CAAQ,IAAA,CAAK,IAAI,CAAC,CAAA,CAAE,CAAA,CAE9C,CAAE,OAAA,CAAS,GAAM,OAAA,CAAAA,CAAQ,CACpC,CAAA,MAASE,CAAAA,CAAK,CACV,MAAAJ,CAAAA,CAAO,MAAM,wBAAA,CAA0BI,CAAY,CAAA,CAC7CA,CACV,CACJ,CAqBA,eAAeC,CAAAA,CAAQN,CAAAA,CAAmBC,EAAgB,CACtD,GAAI,CAACD,CAAAA,CAAO,GAAI,OAAO,IAAA,CAEvBC,CAAAA,CAAO,IAAA,CAAK,6BAA6BD,CAAAA,CAAO,EAAA,CAAG,OAAO,CAAA,GAAA,CAAK,EAE/D,GAAI,CAQA,GAFsB,MAJC,IAAI,KAAA,CAAM,CAAC,KAAA,CAAO,KAAA,CAAOA,CAAAA,CAAO,EAAA,CAAG,OAAO,CAAA,CAAG,CAChE,KAAA,CAAO,CAAC,QAAA,CAAU,MAAA,CAAQ,MAAM,CACpC,CAAC,CAAA,CAE0C,MAAA,GAErB,EAClB,MAAM,IAAI,KAAA,CAAM,CAAA,8BAAA,EAAiCA,EAAO,EAAA,CAAG,OAAO,CAAA,CAAE,CAAA,CAGxE,OAAAC,CAAAA,CAAO,IAAA,CAAK,CAAA,sBAAA,EAAyBD,CAAAA,CAAO,GAAG,OAAO,CAAA,CAAE,CAAA,CAQxDC,CAAAA,CAAO,QAAQ,CAAA,gBAAA,EAAcD,CAAAA,CAAO,EAAA,CAAG,MAAM,CAAA,CAAE,CAAA,CAExC,CAAE,OAAA,CAAS,GAAM,MAAA,CAAQA,CAAAA,CAAO,EAAA,CAAG,MAAO,CACrD,CAAA,MAASK,CAAAA,CAAK,CACV,MAAAJ,EAAO,KAAA,CAAM,oBAAA,CAAsBI,CAAY,CAAA,CACzCA,CACV,CACJ,CAsBA,eAAeE,CAAAA,CAAYP,EAAmBC,CAAAA,CAAgB,CAC1D,GAAI,CAACD,EAAO,KAAA,CAAO,OAAO,IAAA,CAE1BC,CAAAA,CAAO,KAAK,CAAA,sBAAA,EAAyBD,CAAAA,CAAO,KAAA,CAAM,KAAK,CAAA,GAAA,CAAK,CAAA,CAE5D,GAAI,CASA,GAAI,CAAA,CAPW,MAAM,GAAA,CAAI,KAAA,CAAM,CAC3B,WAAA,CAAa,CAACA,CAAAA,CAAO,KAAA,CAAM,KAAK,CAAA,CAChC,MAAA,CAAQA,CAAAA,CAAO,KAAA,CAAM,OACrB,MAAA,CAAQA,CAAAA,CAAO,KAAA,CAAM,MAAA,EAAU,CAACA,CAAAA,CAAO,KAAA,CACvC,SAAA,CAAWA,CAAAA,CAAO,MAAM,SAAA,EAAaA,CAAAA,CAAO,KAAA,CAAQ,QAAA,CAAW,MACnE,CAAC,CAAA,EAEW,OAAA,CACR,MAAM,IAAI,KAAA,CAAM,oBAAoB,CAAA,CAGxC,OAAAC,CAAAA,CAAO,OAAA,CAAQ,CAAA,oBAAA,EAAkBD,CAAAA,CAAO,MAAM,MAAM,CAAA,CAAE,CAAA,CAE/C,CAAE,QAAS,CAAA,CAAA,CAAM,MAAA,CAAQA,CAAAA,CAAO,KAAA,CAAM,MAAO,CACxD,CAAA,MAASK,CAAAA,CAAK,CACV,MAAAJ,CAAAA,CAAO,KAAA,CAAM,wBAAA,CAA0BI,CAAY,EAC7CA,CACV,CACJ,CAsBA,eAAeG,EACXR,CAAAA,CACAS,CAAAA,CACAR,CAAAA,CACF,CACE,IAAMS,CAAAA,CAAY,IAAI,GAAA,CAEtB,GAAI,CAACV,CAAAA,CAAO,QAAA,EAAYS,CAAAA,CAAkB,SAAW,CAAA,CACjD,OAAAR,CAAAA,CAAO,IAAA,CAAK,oCAAoC,CAAA,CACzCS,CAAAA,CAGX,IAAMC,CAAAA,CAAYX,EAAO,QAAA,CACnB,KAAA,CAAM,OAAA,CAAQA,CAAAA,CAAO,QAAQ,CAAA,CACzBA,CAAAA,CAAO,QAAA,CACP,CAACA,EAAO,QAAQ,CAAA,CACpB,EAAC,CAEPC,EAAO,IAAA,CAAK,yBAAyB,CAAA,CAErC,IAAA,IAAWW,CAAAA,IAAYD,CAAAA,CAAW,CAC9B,IAAME,EAAOD,CAAAA,CAAS,IAAA,EAAQ,SAAA,CACxBE,CAAAA,CAAK,IAAIC,KAAAA,CAAGH,CAAAA,CAAS,UAAU,CAAA,CAGrC,GAAIA,CAAAA,CAAS,MAAA,CACT,GAAI,CACA,IAAMI,CAAAA,CAAe,MAAM,OAAOJ,CAAAA,CAAS,QACrCK,CAAAA,CAASD,CAAAA,CAAa,OAAA,EAAWA,CAAAA,CAAa,OAEpD,GAAI,KAAA,CAAM,OAAA,CAAQC,CAAM,EACpB,IAAA,IAAWC,CAAAA,IAASD,CAAAA,CAChBH,CAAAA,CAAG,YAAA,CAAaI,CAAK,EAGjC,CAAA,MAASb,EAAK,CACV,MAAAJ,CAAAA,CAAO,KAAA,CAAM,0BAA0BW,CAAAA,CAAS,MAAM,CAAA,CAAA,CAAIP,CAAY,EAChEA,CACV,CAIJ,IAAA,IAAWY,CAAAA,IAAUR,EACjBK,CAAAA,CAAG,YAAA,CAAaG,CAAM,CAAA,CAG1BP,EAAU,GAAA,CAAIG,CAAAA,CAAMC,CAAE,CAAA,CACtBb,EAAO,OAAA,CAAQ,CAAA,UAAA,EAAaY,CAAI,CAAA,OAAA,CAAS,EAC7C,CAGA,GAAIH,CAAAA,CAAU,IAAA,GAAS,CAAA,EAAKD,CAAAA,CAAkB,MAAA,CAAS,CAAA,CAAG,CACtD,IAAMK,CAAAA,CAAK,IAAIC,KAAAA,CAAG,UAAU,CAAA,CAE5B,IAAA,IAAWE,CAAAA,IAAUR,CAAAA,CACjBK,EAAG,YAAA,CAAaG,CAAM,CAAA,CAG1BP,CAAAA,CAAU,IAAI,SAAA,CAAWI,CAAE,CAAA,CAC3Bb,CAAAA,CAAO,QAAQ,kDAAkD,EACrE,CAEA,OAAOS,CACX,CAyBA,eAAeS,CAAAA,CAAUnB,CAAAA,CAAmBC,EAAgB,CACxD,GAAKD,CAAAA,CAAO,IAAA,CAEZ,CAAAC,CAAAA,CAAO,IAAA,CAAK,oBAAoB,EAEhC,GAAI,CACA,MAAMmB,cAAAA,CAAU,CACZ,eAAA,CAAiBpB,CAAAA,CAAO,IAAA,CAAK,eAAA,CAC7B,mBAAoBA,CAAAA,CAAO,IAAA,CAAK,kBAAA,CAChC,QAAA,CAAUA,EAAO,IAAA,CAAK,QAAA,CACtB,aAAA,CAAeA,CAAAA,CAAO,KAAK,aAAA,EAAiB,MAChD,CAAC,CAAA,CAEDC,EAAO,OAAA,CAAQ,CAAA,kBAAA,EAAgBD,CAAAA,CAAO,IAAA,CAAK,mBAAmB,IAAA,CAAK,IAAI,CAAC,CAAA,CAAE,EAC9E,CAAA,MAASK,CAAAA,CAAK,CACV,MAAAJ,CAAAA,CAAO,KAAA,CAAM,sBAAA,CAAwBI,CAAY,EAC3CA,CACV,CAAA,CACJ,CAoBA,eAAegB,EAAWrB,CAAAA,CAAmBC,CAAAA,CAA4C,CACrF,GAAI,CAACD,CAAAA,CAAO,GAAA,CAAK,OAAO,GAExBC,CAAAA,CAAO,IAAA,CAAK,CAAA,oBAAA,EAAuBD,CAAAA,CAAO,IAAI,SAAS,CAAA,GAAA,CAAK,CAAA,CAE5D,IAAMsB,EAA4B,EAAC,CAEnC,GAAI,CACA,IAAMC,CAAAA,CAAQ,MAAMC,CAAAA,CAAcxB,EAAO,GAAA,CAAI,SAAS,CAAA,CAEtD,IAAA,IAAWyB,KAAQF,CAAAA,CACf,GAAI,CACA,IAAMG,EAAS,MAAM,OAAOD,CAAAA,CAAAA,CACtBE,CAAAA,CAAWD,EAAO,OAAA,EAAWA,CAAAA,CAAO,MAAA,CAEtC,KAAA,CAAM,QAAQC,CAAQ,CAAA,EACtBL,CAAAA,CAAO,IAAA,CAAK,GAAGK,CAAQ,EAE/B,CAAA,MAAStB,CAAAA,CAAK,CACVJ,CAAAA,CAAO,KAAA,CAAM,CAAA,2BAAA,EAA8BwB,CAAI,CAAA,CAAA,CAAIpB,CAAY,EACnE,CAGJ,OAAAJ,CAAAA,CAAO,OAAA,CAAQ,CAAA,qBAAA,EAAmBqB,CAAAA,CAAO,MAAM,CAAA,OAAA,CAAS,CAAA,CACjDA,CACX,CAAA,MAASjB,EAAK,CACV,OAAAJ,CAAAA,CAAO,KAAA,CAAM,iCAAkCI,CAAY,CAAA,CACpD,EACX,CACJ,CAeA,eAAemB,CAAAA,CAAcI,CAAAA,CAAgC,CACzD,IAAML,CAAAA,CAAkB,EAAC,CAEzB,GAAI,CACA,IAAMM,CAAAA,CAAU,MAAM,KAAA,CAAM,SAAA,CACxB,IAAI,GAAA,CAAI,KAAK,cAAc,CAAA,CAAE,IAAA,CAAKD,CAAG,CACzC,CAAA,CAEA,IAAA,IAAWE,CAAAA,IAASD,CAAAA,CAChBN,EAAM,IAAA,CAAK,CAAA,EAAGK,CAAG,CAAA,CAAA,EAAIE,CAAK,CAAA,CAAE,EAEpC,CAAA,KAAQ,CAER,CAEA,OAAOP,CACX,CAkDO,SAASQ,EACZC,CAAAA,CACAC,CAAAA,CACW,CAEX,IAAMjC,EAAoBiC,CAAAA,EAAO,QAAA,CAC3BA,CAAAA,CAAM,QAAA,CAASD,CAAU,CAAA,CACzBA,CAAAA,CAEA/B,CAAAA,CAAS,IAAIiC,WAAAA,CAAOlC,CAAAA,CAAO,KAAK,CAAA,CAChCmC,EAAiB,IAAIC,mBAAAA,CAAenC,CAAM,CAAA,CAC1CoC,EAAiB,IAAIC,mBAAAA,CAAerC,CAAM,CAAA,CAE1CS,EAAY,IAAI,GAAA,CAChB6B,CAAAA,CAAc,IAAI,IACpBC,CAAAA,CAAsB,IAAA,CACtBC,CAAAA,CAAmB,IAAA,CAEjBC,EAAwB,CAC1B,MAAA,CAAA1C,CAAAA,CACA,SAAA,CAAAU,EACA,OAAA,CAAS,EACb,CAAA,CAGMiC,CAAAA,CAA0B,CAC5B,MAAA,CAAA3C,CAAAA,CACA,OAAQ,IAAA,CACR,SAAA,CAAAU,CAAAA,CACA,OAAA,CAAS,EAAC,CACV,WAAA,CAAA6B,CAAAA,CACA,KAAA,CAAO,SAAY,CAAE,CAAA,CACrB,IAAA,CAAM,SAAY,CAAE,CAAA,CACpB,OAAA,CAAS,SAAY,CAAE,EACvB,UAAA,CAAY,IAAMG,CAAAA,CAClB,aAAA,CAAgB7B,GAAiB0B,CAAAA,CAAY,GAAA,CAAI1B,CAAI,CACzD,EAMA,eAAe+B,CAAAA,EAAgB,CAC3B,GAAI,CAAC5C,CAAAA,CAAO,OAAA,EAAWA,CAAAA,CAAO,QAAQ,MAAA,GAAW,CAAA,CAAG,CAChDC,CAAAA,CAAO,KAAK,wBAAwB,CAAA,CACpC,MACJ,CAEAA,EAAO,KAAA,CAAM,UAAU,CAAA,CAEvB,IAAA,IAAW4C,KAAU7C,CAAAA,CAAO,OAAA,CACxB,MAAMmC,CAAAA,CAAe,SAASU,CAAAA,CAAQF,CAAU,CAAA,CAGpDD,CAAAA,CAAI,QAAUP,CAAAA,CAAe,MAAA,EAAO,CAGVA,CAAAA,CAAe,oBAAmB,CAC1C,OAAA,CAAQ,CAACW,CAAAA,CAAIjC,CAAAA,GAAS0B,CAAAA,CAAY,GAAA,CAAI1B,CAAAA,CAAMiC,CAAE,CAAC,EACrE,CAMA,eAAeC,GAAa,CACxB9C,CAAAA,CAAO,KAAA,CAAM,OAAO,EAEpB,GAAI,CAEAwC,CAAAA,CAAc,MAAM1C,EAAYC,CAAAA,CAAQC,CAAM,CAAA,CAC9CyC,CAAAA,CAAI,YAAcD,CAAAA,CAGlB,IAAMO,CAAAA,CAAU,MAAM1C,EAAQN,CAAAA,CAAQC,CAAM,CAAA,CAC5CyC,CAAAA,CAAI,QAAUM,CAAAA,CAGd,IAAMC,CAAAA,CAAa,MAAM1C,CAAAA,CAAYP,CAAAA,CAAQC,CAAM,CAAA,CACnDyC,EAAI,UAAA,CAAaO,CAAAA,CAGjB,IAAMC,CAAAA,CAAgBf,EAAe,cAAA,EAAe,CAG9CgB,CAAAA,CAAM,MAAM3C,EAAeR,CAAAA,CAAQkD,CAAAA,CAAejD,CAAM,CAAA,CAC9DS,EAAU,KAAA,EAAM,CAChByC,CAAAA,CAAI,OAAA,CAAQ,CAACrC,CAAAA,CAAID,CAAAA,GAASH,CAAAA,CAAU,GAAA,CAAIG,EAAMC,CAAE,CAAC,CAAA,CAGjD,MAAMK,EAAUnB,CAAAA,CAAQC,CAAM,CAAA,CAG9B,MAAMkC,CAAAA,CAAe,QAAA,CAAS,SAAA,CAAWO,CAAG,EAG5C,MAAMT,CAAAA,EAAO,OAAA,GAAUS,CAAG,EAC9B,CAAA,MAASrC,CAAAA,CAAK,CACV,MAAA,MAAM4B,GAAO,OAAA,GAAUS,CAAAA,CAAK,OAAA,CAASrC,CAAY,EAC3CA,CACV,CACJ,CAMA,eAAe+C,GAAa,CACxBnD,CAAAA,CAAO,KAAA,CAAM,OAAO,EAEpB,GAAI,CAEA,IAAMoD,CAAAA,CAAgB,MAAMhC,CAAAA,CAAWrB,CAAAA,CAAQC,CAAM,CAAA,CAG/CqD,CAAAA,CAAenB,CAAAA,CAAe,aAAA,EAAc,CAI5CoB,EAAgB,CAAC,GADJvD,CAAAA,CAAO,MAAA,EAAU,EAAC,CACC,GAAGqD,CAAa,CAAA,CAChDG,EAAenB,CAAAA,CAAe,WAAA,CAAYkB,CAAAA,CAAeD,CAAY,EAGrEG,CAAAA,CAAazD,CAAAA,CAAO,MAAA,CACpB,KAAA,CAAM,QAAQA,CAAAA,CAAO,MAAM,CAAA,CACvBA,CAAAA,CAAO,OACP,CAACA,CAAAA,CAAO,MAAM,CAAA,CAClB,EAAC,CACD0D,CAAAA,CAAevB,CAAAA,CAAe,aAAA,EAAc,CAC5CwB,CAAAA,CAAetB,CAAAA,CAAe,WAAA,CAAYoB,EAAYC,CAAY,CAAA,CAExEzD,CAAAA,CAAO,IAAA,CAAK,oBAAoB,CAAA,CAGhC,IAAI2D,CAAAA,CACJ,IAAA,IAAWf,KAAUH,CAAAA,CAAI,OAAA,CAAS,CAC9B,IAAMmB,EAAoBhB,CAAAA,CAC1B,GAAIgB,CAAAA,CAAkB,iBAAA,CAAmB,CACrCD,CAAAA,CAAeC,CAAAA,CAAkB,iBAAA,CACjC,OAAA,CAAQ,IAAI,CAAA,8CAAA,EAA4ChB,CAAAA,CAAO,IAAI,CAAA,CAAE,EACrE,KACJ,CACJ,CAGAL,CAAAA,CAAiBsB,aAAAA,CAAa,CAC1B,IAAA,CAAM9D,CAAAA,CAAO,QAAQ,IAAA,EAAQ,GAAA,CAC7B,QAAA,CAAUA,CAAAA,CAAO,QAAQ,IAAA,EAAQ,WAAA,CACjC,OAAA,CAASA,CAAAA,CAAO,QAAQ,OAAA,CACxB,MAAA,CAAQwD,CAAAA,CACR,MAAA,CAAQG,EAAa,MAAA,CAAS,CAAA,CAAIA,CAAAA,CAAe,KAAA,CAAA,CACjD,SAAU3D,CAAAA,CAAO,QAAA,CACjB,WAAA,CAAaA,CAAAA,CAAO,YACpB,IAAA,CAAMA,CAAAA,CAAO,IAAA,CACP,CACE,gBAAiBA,CAAAA,CAAO,IAAA,CAAK,eAAA,CAC7B,kBAAA,CAAoBA,CAAAA,CAAO,IAAA,CAAK,kBACpC,CAAA,CACE,OACN,OAAA,CAAS4D,CACb,CAAC,CAAA,CAGDlD,EAAU,OAAA,CAAQ,CAACI,CAAAA,CAAID,CAAAA,GAAS,CAC5B2B,CAAAA,CAAe,EAAA,CAAG,GAAA,CAAI3B,CAAAA,CAAMC,CAAE,EAClC,CAAC,CAAA,CAED4B,CAAAA,CAAI,OAASF,CAAAA,CACbG,CAAAA,CAAW,MAAA,CAASH,CAAAA,CAEpBvC,EAAO,OAAA,CACH,CAAA,sBAAA,EAAoBD,CAAAA,CAAO,MAAA,EAAQ,MAAQ,WAAW,CAAA,CAAA,EAAIA,CAAAA,CAAO,MAAA,EAAQ,IAAA,EAAQ,GAAI,CAAA,CACzF,CAAA,CAGA,MAAMmC,CAAAA,CAAe,QAAA,CAAS,SAAA,CAAWO,CAAG,EAG5C,MAAMT,CAAAA,EAAO,OAAA,GAAUS,CAAG,EAC9B,CAAA,MAASrC,CAAAA,CAAK,CACV,MAAA,MAAM4B,GAAO,OAAA,GAAUS,CAAAA,CAAK,OAAA,CAASrC,CAAY,EAC3CA,CACV,CACJ,CAMA,eAAe0D,GAAa,CACxB9D,CAAAA,CAAO,KAAA,CAAM,OAAO,EAEpB,GAAI,CACA,MAAMuC,CAAAA,CAAe,KAAA,EAAM,CAE3BvC,CAAAA,CAAO,OAAA,CACH,4BAA4BD,CAAAA,CAAO,MAAA,EAAQ,IAAA,EAAQ,WAAW,IAAIA,CAAAA,CAAO,MAAA,EAAQ,IAAA,EAAQ,GAAI,EACjG,CAAA,CAGA,MAAMmC,CAAAA,CAAe,QAAA,CAAS,UAAWO,CAAG,CAAA,CAG5C,MAAMT,CAAAA,EAAO,UAAUS,CAAG,EAC9B,CAAA,MAASrC,CAAAA,CAAK,CACV,MAAA,MAAM4B,CAAAA,EAAO,OAAA,GAAUS,CAAAA,CAAK,QAASrC,CAAY,CAAA,CAC3CA,CACV,CACJ,CAMA,OAAO,CACH,MAAA,CAAAL,EACA,MAAA,CAAQwC,CAAAA,CACR,SAAA,CAAA9B,CAAAA,CACA,QAASgC,CAAAA,CAAI,OAAA,CACb,WAAA,CAAAH,CAAAA,CAEA,MAAM,KAAA,EAAQ,CACV,MAAMK,CAAAA,GACN,MAAMG,CAAAA,EAAW,CACjB,MAAMK,GAAW,CACjB,MAAMW,CAAAA,GACV,EAEA,MAAM,IAAA,EAAO,CACT9D,CAAAA,CAAO,KAAK,oBAAoB,CAAA,CAEhC,GAAI,CACIuC,CAAAA,EACA,MAAMA,CAAAA,CAAe,IAAA,GAGzB9B,CAAAA,CAAU,OAAA,CAAQ,CAACI,CAAAA,CAAID,IAAS,CAC5BC,CAAAA,CAAG,KAAA,EAAM,CACTb,EAAO,IAAA,CAAK,CAAA,UAAA,EAAaY,CAAI,CAAA,QAAA,CAAU,EAC3C,CAAC,CAAA,CAGD,MAAMsB,CAAAA,CAAe,SAAS,YAAA,CAAcO,CAAG,CAAA,CAE/C,MAAMT,GAAO,QAAA,GAAWS,CAAG,CAAA,CAE3BzC,CAAAA,CAAO,QAAQ,gBAAgB,EACnC,CAAA,MAASI,CAAAA,CAAK,CACV,MAAAJ,CAAAA,CAAO,KAAA,CAAM,uBAAA,CAAyBI,CAAY,CAAA,CAC5CA,CACV,CACJ,CAAA,CAEA,MAAM,OAAA,EAAU,CACZ,MAAM,IAAA,CAAK,MAAK,CAChB,MAAM,IAAA,CAAK,KAAA,GACf,CAAA,CAEA,UAAA,EAAa,CACT,OAAOqC,CACX,CAAA,CAEA,aAAA,CAAc7B,CAAAA,CAAc,CACxB,OAAO0B,CAAAA,CAAY,GAAA,CAAI1B,CAAI,CAC/B,CACJ,CACJ","file":"index.cjs","sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any */\r\n// src/index.ts\r\n//\r\n// Made with ❤️ by Maysara.\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ PACK ════════════════════════════════════════╗\r\n\r\n import { AppConfig, LifecycleContext, LifecycleHooks, AppInstance, RouteDefinition, AppMiddleware, Logger, PluginRegistry, ResourceMerger } from '@cruxjs/base';\r\n import { server as createServer } from '@minejs/server';\r\n import { DB } from '@minejs/db';\r\n import { setupAuto } from '@minejs/i18n';\r\n import type { TableSchema } from '@minejs/db';\r\n\r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ CORE ════════════════════════════════════════╗\r\n\r\n /**\r\n * Builds the client bundle using Bun's bundler\r\n *\r\n * @param {AppConfig} config - The application configuration containing client build settings\r\n * @param {Logger} logger - Logger instance for logging build progress and errors\r\n * @returns {Promise<{success: boolean, outputs: string[]} | null>} Build result with output paths, or null if no client config\r\n * @throws {Error} If the build process fails\r\n *\r\n * @example\r\n * const result = await buildClient(config, logger);\r\n * if (result?.success) {\r\n * console.log('Built to:', result.outputs);\r\n * }\r\n */\r\n async function buildClient(config: AppConfig, logger: Logger) {\r\n if (!config.client) return null;\r\n\r\n logger.info('Building client...');\r\n\r\n try {\r\n const result = await Bun.build({\r\n entrypoints: [config.client.entry],\r\n outdir: config.client.output,\r\n target: config.client.target || 'browser',\r\n minify: config.client.minify ?? !config.debug,\r\n sourcemap: config.client.sourcemap ?? config.debug ? 'inline' : 'none',\r\n external: config.client.external || []\r\n });\r\n\r\n if (!result.success) throw new Error('Build failed');\r\n\r\n const outputs = result.outputs.map(o => o.path);\r\n logger.success(`Client built → ${outputs.join(', ')}`);\r\n\r\n return { success: true, outputs };\r\n } catch (err) {\r\n logger.error('Failed to build client', err as Error);\r\n throw err;\r\n }\r\n }\r\n\r\n /**\r\n * Builds and installs UI library if specified in config\r\n *\r\n * Handles:\r\n * - Installing the specified UI package from npm\r\n * - Copying minified UI assets to the configured output path\r\n * - Supports packages like @mineui/core\r\n *\r\n * @param {AppConfig} config - The application configuration containing ui settings\r\n * @param {Logger} logger - Logger instance for logging build progress and errors\r\n * @returns {Promise<{success: boolean, output: string} | null>} Build result with output path, or null if no ui config\r\n * @throws {Error} If the build process fails\r\n *\r\n * @example\r\n * const result = await buildUI(config, logger);\r\n * if (result?.success) {\r\n * console.log('UI built to:', result.output);\r\n * }\r\n */\r\n async function buildUI(config: AppConfig, logger: Logger) {\r\n if (!config.ui) return null;\r\n\r\n logger.info(`Building UI from package: ${config.ui.package}...`);\r\n\r\n try {\r\n // Install the UI package\r\n const installProcess = Bun.spawn(['bun', 'add', config.ui.package], {\r\n stdio: ['ignore', 'pipe', 'pipe']\r\n });\r\n\r\n const installResult = await installProcess.exited;\r\n\r\n if (installResult !== 0) {\r\n throw new Error(`Failed to install UI package: ${config.ui.package}`);\r\n }\r\n\r\n logger.info(`UI package installed: ${config.ui.package}`);\r\n\r\n // TODO: Copy minified assets to output directory\r\n // This would typically involve:\r\n // 1. Finding the package in node_modules\r\n // 2. Locating dist/minified CSS files\r\n // 3. Copying to config.ui.output path\r\n\r\n logger.success(`UI built → ${config.ui.output}`);\r\n\r\n return { success: true, output: config.ui.output };\r\n } catch (err) {\r\n logger.error('Failed to build UI', err as Error);\r\n throw err;\r\n }\r\n }\r\n\r\n /**\r\n * Builds SCSS/CSS styles using a bundler\r\n *\r\n * Handles:\r\n * - Compiling SCSS to CSS\r\n * - Minifying CSS if configured\r\n * - Generating source maps if configured\r\n * - Outputting to specified directory\r\n *\r\n * @param {AppConfig} config - The application configuration containing style settings\r\n * @param {Logger} logger - Logger instance for logging build progress and errors\r\n * @returns {Promise<{success: boolean, output: string} | null>} Build result with output path, or null if no style config\r\n * @throws {Error} If the build process fails\r\n *\r\n * @example\r\n * const result = await buildStyles(config, logger);\r\n * if (result?.success) {\r\n * console.log('Styles built to:', result.output);\r\n * }\r\n */\r\n async function buildStyles(config: AppConfig, logger: Logger) {\r\n if (!config.style) return null;\r\n\r\n logger.info(`Building styles from: ${config.style.entry}...`);\r\n\r\n try {\r\n // Use Bun's built-in bundler to handle SCSS/CSS\r\n const result = await Bun.build({\r\n entrypoints: [config.style.entry],\r\n outdir: config.style.output,\r\n minify: config.style.minify ?? !config.debug,\r\n sourcemap: config.style.sourcemap ?? config.debug ? 'inline' : 'none'\r\n });\r\n\r\n if (!result.success) {\r\n throw new Error('Style build failed');\r\n }\r\n\r\n logger.success(`Styles built → ${config.style.output}`);\r\n\r\n return { success: true, output: config.style.output };\r\n } catch (err) {\r\n logger.error('Failed to build styles', err as Error);\r\n throw err;\r\n }\r\n }\r\n\r\n /**\r\n * Initializes and configures database connections\r\n *\r\n * Handles:\r\n * - Multiple database instances (primary, cache, etc.)\r\n * - User-defined schemas from config\r\n * - Plugin schemas from plugins\r\n * - In-memory databases for plugin-only scenarios\r\n *\r\n * @param {AppConfig} config - Application configuration with database settings\r\n * @param {TableSchema[]} additionalSchemas - Database schemas provided by plugins\r\n * @param {Logger} logger - Logger instance for logging setup progress\r\n * @returns {Promise<Map<string, DB>>} Map of database instances by name\r\n * @throws {Error} If schema loading or database initialization fails\r\n *\r\n * @example\r\n * const databases = await setupDatabases(config, pluginSchemas, logger);\r\n * const db = databases.get('primary');\r\n * const result = db.query('SELECT * FROM users');\r\n */\r\n async function setupDatabases(\r\n config: AppConfig,\r\n additionalSchemas: TableSchema[],\r\n logger: Logger\r\n ) {\r\n const databases = new Map<string, DB>();\r\n\r\n if (!config.database && additionalSchemas.length === 0) {\r\n logger.info('No database config, skipping setup');\r\n return databases;\r\n }\r\n\r\n const dbConfigs = config.database\r\n ? Array.isArray(config.database)\r\n ? config.database\r\n : [config.database]\r\n : [];\r\n\r\n logger.info('Setting up databases...');\r\n\r\n for (const dbConfig of dbConfigs) {\r\n const name = dbConfig.name || 'default';\r\n const db = new DB(dbConfig.connection);\r\n\r\n // Load user schema\r\n if (dbConfig.schema) {\r\n try {\r\n const schemaModule = await import(dbConfig.schema);\r\n const schema = schemaModule.default || schemaModule.schema;\r\n\r\n if (Array.isArray(schema)) {\r\n for (const table of schema) {\r\n db.defineSchema(table);\r\n }\r\n }\r\n } catch (err) {\r\n logger.error(`Failed to load schema: ${dbConfig.schema}`, err as Error);\r\n throw err;\r\n }\r\n }\r\n\r\n // Load plugin schemas for this database\r\n for (const schema of additionalSchemas) {\r\n db.defineSchema(schema);\r\n }\r\n\r\n databases.set(name, db);\r\n logger.success(`Database '${name}' ready`);\r\n }\r\n\r\n // If no user database but plugins need one, create default\r\n if (databases.size === 0 && additionalSchemas.length > 0) {\r\n const db = new DB(':memory:');\r\n\r\n for (const schema of additionalSchemas) {\r\n db.defineSchema(schema);\r\n }\r\n\r\n databases.set('default', db);\r\n logger.success(`Database 'default' ready (in-memory for plugins)`);\r\n }\r\n\r\n return databases;\r\n }\r\n\r\n /**\r\n * Initializes internationalization (i18n) support\r\n *\r\n * Loads language files and configures the i18n system based on:\r\n * - Default language\r\n * - Supported languages\r\n * - Base path for translation files\r\n * - File extension (json, cjson, etc.)\r\n *\r\n * @param {AppConfig} config - Application configuration with i18n settings\r\n * @param {Logger} logger - Logger instance for logging setup progress\r\n * @returns {Promise<void>}\r\n * @throws {Error} If i18n setup or language file loading fails\r\n *\r\n * @example\r\n * await setupI18n({\r\n * i18n: {\r\n * defaultLanguage: 'en',\r\n * supportedLanguages: ['en', 'ar'],\r\n * basePath: './src/i18n'\r\n * }\r\n * }, logger);\r\n */\r\n async function setupI18n(config: AppConfig, logger: Logger) {\r\n if (!config.i18n) return;\r\n\r\n logger.info('Setting up i18n...');\r\n\r\n try {\r\n await setupAuto({\r\n defaultLanguage: config.i18n.defaultLanguage,\r\n supportedLanguages: config.i18n.supportedLanguages,\r\n basePath: config.i18n.basePath,\r\n fileExtension: config.i18n.fileExtension || 'json'\r\n });\r\n\r\n logger.success(`i18n ready → ${config.i18n.supportedLanguages.join(', ')}`);\r\n } catch (err) {\r\n logger.error('Failed to setup i18n', err as Error);\r\n throw err;\r\n }\r\n }\r\n\r\n /**\r\n * Dynamically loads route definitions from API directory\r\n *\r\n * Scans the specified directory for route files and imports them.\r\n * Each route file should export either:\r\n * - `routes` property with RouteDefinition array\r\n * - Default export with RouteDefinition array\r\n *\r\n * @param {AppConfig} config - Application configuration with api.directory\r\n * @param {Logger} logger - Logger instance for logging scan progress\r\n * @returns {Promise<RouteDefinition[]>} Array of loaded route definitions\r\n *\r\n * @example\r\n * const routes = await loadRoutes({\r\n * api: { directory: './src/server/api' }\r\n * }, logger);\r\n * console.log(`Loaded ${routes.length} routes`);\r\n */\r\n async function loadRoutes(config: AppConfig, logger: Logger): Promise<RouteDefinition[]> {\r\n if (!config.api) return [];\r\n\r\n logger.info(`Loading routes from ${config.api.directory}...`);\r\n\r\n const routes: RouteDefinition[] = [];\r\n\r\n try {\r\n const files = await scanDirectory(config.api.directory);\r\n\r\n for (const file of files) {\r\n try {\r\n const module = await import(file);\r\n const exported = module.default || module.routes;\r\n\r\n if (Array.isArray(exported)) {\r\n routes.push(...exported);\r\n }\r\n } catch (err) {\r\n logger.error(`Failed to load routes from ${file}`, err as Error);\r\n }\r\n }\r\n\r\n logger.success(`Routes loaded → ${routes.length} routes`);\r\n return routes;\r\n } catch (err) {\r\n logger.error('Failed to scan route directory', err as Error);\r\n return [];\r\n }\r\n }\r\n\r\n /**\r\n * Scans a directory for TypeScript/JavaScript files\r\n *\r\n * Uses Bun's Glob API to recursively find all .ts and .js files in a directory.\r\n * Gracefully handles non-existent directories (returns empty array).\r\n *\r\n * @param {string} dir - Directory path to scan\r\n * @returns {Promise<string[]>} Array of absolute file paths found\r\n *\r\n * @example\r\n * const files = await scanDirectory('./src/server/api');\r\n * // Returns: ['./src/server/api/users.ts', './src/server/api/posts.ts']\r\n */\r\n async function scanDirectory(dir: string): Promise<string[]> {\r\n const files: string[] = [];\r\n\r\n try {\r\n const entries = await Array.fromAsync(\r\n new Bun.Glob('**/*.{ts,js}').scan(dir)\r\n );\r\n\r\n for (const entry of entries) {\r\n files.push(`${dir}/${entry}`);\r\n }\r\n } catch {\r\n // Directory doesn't exist\r\n }\r\n\r\n return files;\r\n }\r\n\r\n /**\r\n * Creates a CruxJS application instance with full lifecycle management\r\n *\r\n * This is the main entry point for building a CruxJS application. It:\r\n * 1. Registers plugins (Phase 0)\r\n * 2. Builds client, initializes databases, setups i18n (Phase 1: AWAKE)\r\n * 3. Creates server, merges routes and middleware (Phase 2: START)\r\n * 4. Starts the server and enables request handling (Phase 3: READY)\r\n *\r\n * Phases execute sequentially when `app.start()` is called.\r\n *\r\n * @param {AppConfig} userConfig - Application configuration object\r\n * @param {LifecycleHooks} [hooks] - Optional lifecycle event handlers\r\n * @returns {AppInstance} Application instance with control methods\r\n *\r\n * @throws {Error} Will throw if any lifecycle phase fails (unless caught in onError hook)\r\n *\r\n * @example\r\n * // Basic usage\r\n * const app = createApp({\r\n * debug: true,\r\n * server: { port: 3000 },\r\n * api: { directory: './src/api' },\r\n * plugins: [spaPlugin]\r\n * });\r\n * await app.start();\r\n *\r\n * @example\r\n * // With lifecycle hooks\r\n * const app = createApp(config, {\r\n * onAwake: async (ctx) => {\r\n * console.log('⏰ App awoken, databases ready');\r\n * },\r\n * onReady: async (ctx) => {\r\n * console.log('✅ Server ready:', ctx.server.getURL());\r\n * },\r\n * onError: async (ctx, phase, error) => {\r\n * console.error(`Error in ${phase}:`, error.message);\r\n * }\r\n * });\r\n *\r\n * @example\r\n * // With cleanup\r\n * const app = createApp(config);\r\n * await app.start();\r\n * // ... server is running\r\n * await app.stop(); // Cleanup\r\n */\r\n export function createApp(\r\n userConfig: AppConfig,\r\n hooks?: LifecycleHooks\r\n ): AppInstance {\r\n // Apply config hook\r\n const config: AppConfig = hooks?.onConfig\r\n ? hooks.onConfig(userConfig) as AppConfig\r\n : userConfig;\r\n\r\n const logger = new Logger(config.debug);\r\n const pluginRegistry = new PluginRegistry(logger);\r\n const resourceMerger = new ResourceMerger(logger);\r\n\r\n const databases = new Map<string, DB>();\r\n const middlewares = new Map<string, AppMiddleware>();\r\n let serverInstance: any = null;\r\n let clientBuild: any = null;\r\n\r\n const ctx: LifecycleContext = {\r\n config,\r\n databases,\r\n plugins: []\r\n };\r\n\r\n // Create partial app instance for plugin registration\r\n const partialApp: AppInstance = {\r\n config,\r\n server: null,\r\n databases,\r\n plugins: [],\r\n middlewares,\r\n start: async () => { },\r\n stop: async () => { },\r\n restart: async () => { },\r\n getContext: () => ctx,\r\n getMiddleware: (name: string) => middlewares.get(name)\r\n };\r\n\r\n // ─────────────────────────────────────────────────────────\r\n // Phase 0: Plugin Registration\r\n // ─────────────────────────────────────────────────────────\r\n\r\n async function phaseRegister() {\r\n if (!config.plugins || config.plugins.length === 0) {\r\n logger.info('No plugins to register');\r\n return;\r\n }\r\n\r\n logger.phase('REGISTER');\r\n\r\n for (const plugin of config.plugins) {\r\n await pluginRegistry.register(plugin, partialApp);\r\n }\r\n\r\n ctx.plugins = pluginRegistry.getAll();\r\n\r\n // Collect plugin middlewares\r\n const pluginMiddlewares = pluginRegistry.collectMiddlewares();\r\n pluginMiddlewares.forEach((mw, name) => middlewares.set(name, mw));\r\n }\r\n\r\n // ─────────────────────────────────────────────────────────\r\n // Phase 1: AWAKE\r\n // ─────────────────────────────────────────────────────────\r\n\r\n async function phaseAwake() {\r\n logger.phase('AWAKE');\r\n\r\n try {\r\n // Build client\r\n clientBuild = await buildClient(config, logger);\r\n ctx.clientBuild = clientBuild;\r\n\r\n // Build UI library if configured\r\n const uiBuild = await buildUI(config, logger);\r\n ctx.uiBuild = uiBuild;\r\n\r\n // Build styles if configured\r\n const styleBuild = await buildStyles(config, logger);\r\n ctx.styleBuild = styleBuild;\r\n\r\n // Collect plugin schemas\r\n const pluginSchemas = pluginRegistry.collectSchemas();\r\n\r\n // Setup databases\r\n const dbs = await setupDatabases(config, pluginSchemas, logger);\r\n databases.clear();\r\n dbs.forEach((db, name) => databases.set(name, db));\r\n\r\n // Setup i18n\r\n await setupI18n(config, logger);\r\n\r\n // Call plugin hooks\r\n await pluginRegistry.callHook('onAwake', ctx);\r\n\r\n // Call user hook\r\n await hooks?.onAwake?.(ctx);\r\n } catch (err) {\r\n await hooks?.onError?.(ctx, 'AWAKE', err as Error);\r\n throw err;\r\n }\r\n }\r\n\r\n // ─────────────────────────────────────────────────────────\r\n // Phase 2: START\r\n // ─────────────────────────────────────────────────────────\r\n\r\n async function phaseStart() {\r\n logger.phase('START');\r\n\r\n try {\r\n // Load user routes\r\n const userApiRoutes = await loadRoutes(config, logger);\r\n\r\n // Collect plugin routes\r\n const pluginRoutes = pluginRegistry.collectRoutes();\r\n\r\n // Merge user routes + plugin routes\r\n const userRoutes = config.routes || [];\r\n const allUserRoutes = [...userRoutes, ...userApiRoutes];\r\n const mergedRoutes = resourceMerger.mergeRoutes(allUserRoutes, pluginRoutes);\r\n\r\n // Collect static configs\r\n const userStatic = config.static\r\n ? Array.isArray(config.static)\r\n ? config.static\r\n : [config.static]\r\n : [];\r\n const pluginStatic = pluginRegistry.collectStatic();\r\n const mergedStatic = resourceMerger.mergeStatic(userStatic, pluginStatic);\r\n\r\n logger.info('Creating server...');\r\n\r\n // Collect error handlers from plugins (especially SPA plugin)\r\n let errorHandler: ((statusCode: number, path: string) => Response) | undefined;\r\n for (const plugin of ctx.plugins) {\r\n const pluginWithHandler = plugin as any;\r\n if (pluginWithHandler.__spaErrorHandler) {\r\n errorHandler = pluginWithHandler.__spaErrorHandler;\r\n console.log(`[CruxJS] ✓ Error handler collected from: ${plugin.name}`);\r\n break; // Use first error handler found\r\n }\r\n }\r\n\r\n // Create server\r\n serverInstance = createServer({\r\n port: config.server?.port || 3000,\r\n hostname: config.server?.host || 'localhost',\r\n logging: config.server?.logging,\r\n routes: mergedRoutes,\r\n static: mergedStatic.length > 0 ? mergedStatic : undefined,\r\n security: config.security,\r\n middlewares: config.middlewares,\r\n i18n: config.i18n\r\n ? {\r\n defaultLanguage: config.i18n.defaultLanguage,\r\n supportedLanguages: config.i18n.supportedLanguages\r\n }\r\n : undefined,\r\n onError: errorHandler\r\n });\r\n\r\n // Inject databases\r\n databases.forEach((db, name) => {\r\n serverInstance.db.set(name, db);\r\n });\r\n\r\n ctx.server = serverInstance;\r\n partialApp.server = serverInstance;\r\n\r\n logger.success(\r\n `Server created → ${config.server?.host || 'localhost'}:${config.server?.port || 3000}`\r\n );\r\n\r\n // Call plugin hooks\r\n await pluginRegistry.callHook('onStart', ctx);\r\n\r\n // Call user hook\r\n await hooks?.onStart?.(ctx);\r\n } catch (err) {\r\n await hooks?.onError?.(ctx, 'START', err as Error);\r\n throw err;\r\n }\r\n }\r\n\r\n // ─────────────────────────────────────────────────────────\r\n // Phase 3: READY\r\n // ─────────────────────────────────────────────────────────\r\n\r\n async function phaseReady() {\r\n logger.phase('READY');\r\n\r\n try {\r\n await serverInstance.start();\r\n\r\n logger.success(\r\n `Server running on http://${config.server?.host || 'localhost'}:${config.server?.port || 3000}`\r\n );\r\n\r\n // Call plugin hooks\r\n await pluginRegistry.callHook('onReady', ctx);\r\n\r\n // Call user hook\r\n await hooks?.onReady?.(ctx);\r\n } catch (err) {\r\n await hooks?.onError?.(ctx, 'READY', err as Error);\r\n throw err;\r\n }\r\n }\r\n\r\n // ─────────────────────────────────────────────────────────\r\n // App Instance\r\n // ─────────────────────────────────────────────────────────\r\n\r\n return {\r\n config,\r\n server: serverInstance,\r\n databases,\r\n plugins: ctx.plugins,\r\n middlewares,\r\n\r\n async start() {\r\n await phaseRegister();\r\n await phaseAwake();\r\n await phaseStart();\r\n await phaseReady();\r\n },\r\n\r\n async stop() {\r\n logger.info('Stopping server...');\r\n\r\n try {\r\n if (serverInstance) {\r\n await serverInstance.stop();\r\n }\r\n\r\n databases.forEach((db, name) => {\r\n db.close();\r\n logger.info(`Database '${name}' closed`);\r\n });\r\n\r\n // Call plugin hooks\r\n await pluginRegistry.callHook('onShutdown', ctx);\r\n\r\n await hooks?.onFinish?.(ctx);\r\n\r\n logger.success('Server stopped');\r\n } catch (err) {\r\n logger.error('Failed to stop server', err as Error);\r\n throw err;\r\n }\r\n },\r\n\r\n async restart() {\r\n await this.stop();\r\n await this.start();\r\n },\r\n\r\n getContext() {\r\n return ctx;\r\n },\r\n\r\n getMiddleware(name: string) {\r\n return middlewares.get(name);\r\n }\r\n };\r\n }\r\n\r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ ════ ════════════════════════════════════════╗\r\n\r\n export * from '@cruxjs/base';\r\n\r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝"]}
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import {Logger,PluginRegistry,ResourceMerger}from'@cruxjs/base';export*from'@cruxjs/base';import {server}from'@minejs/server';import {DB}from'@minejs/db';import {setupAuto}from'@minejs/i18n';async function
|
|
2
|
-
export{
|
|
1
|
+
import {Logger,PluginRegistry,ResourceMerger}from'@cruxjs/base';export*from'@cruxjs/base';import {server}from'@minejs/server';import {DB}from'@minejs/db';import {setupAuto}from'@minejs/i18n';async function k(t,r){if(!t.client)return null;r.info("Building client...");try{let e=await Bun.build({entrypoints:[t.client.entry],outdir:t.client.output,target:t.client.target||"browser",minify:t.client.minify??!t.debug,sourcemap:t.client.sourcemap??t.debug?"inline":"none",external:t.client.external||[]});if(!e.success)throw new Error("Build failed");let s=e.outputs.map(i=>i.path);return r.success(`Client built \u2192 ${s.join(", ")}`),{success:!0,outputs:s}}catch(e){throw r.error("Failed to build client",e),e}}async function F(t,r){if(!t.ui)return null;r.info(`Building UI from package: ${t.ui.package}...`);try{if(await Bun.spawn(["bun","add",t.ui.package],{stdio:["ignore","pipe","pipe"]}).exited!==0)throw new Error(`Failed to install UI package: ${t.ui.package}`);return r.info(`UI package installed: ${t.ui.package}`),r.success(`UI built \u2192 ${t.ui.output}`),{success:!0,output:t.ui.output}}catch(e){throw r.error("Failed to build UI",e),e}}async function H(t,r){if(!t.style)return null;r.info(`Building styles from: ${t.style.entry}...`);try{if(!(await Bun.build({entrypoints:[t.style.entry],outdir:t.style.output,minify:t.style.minify??!t.debug,sourcemap:t.style.sourcemap??t.debug?"inline":"none"})).success)throw new Error("Style build failed");return r.success(`Styles built \u2192 ${t.style.output}`),{success:!0,output:t.style.output}}catch(e){throw r.error("Failed to build styles",e),e}}async function P(t,r,e){let s=new Map;if(!t.database&&r.length===0)return e.info("No database config, skipping setup"),s;let i=t.database?Array.isArray(t.database)?t.database:[t.database]:[];e.info("Setting up databases...");for(let o of i){let c=o.name||"default",l=new DB(o.connection);if(o.schema)try{let u=await import(o.schema),d=u.default||u.schema;if(Array.isArray(d))for(let a of d)l.defineSchema(a);}catch(u){throw e.error(`Failed to load schema: ${o.schema}`,u),u}for(let u of r)l.defineSchema(u);s.set(c,l),e.success(`Database '${c}' ready`);}if(s.size===0&&r.length>0){let o=new DB(":memory:");for(let c of r)o.defineSchema(c);s.set("default",o),e.success("Database 'default' ready (in-memory for plugins)");}return s}async function T(t,r){if(t.i18n){r.info("Setting up i18n...");try{await setupAuto({defaultLanguage:t.i18n.defaultLanguage,supportedLanguages:t.i18n.supportedLanguages,basePath:t.i18n.basePath,fileExtension:t.i18n.fileExtension||"json"}),r.success(`i18n ready \u2192 ${t.i18n.supportedLanguages.join(", ")}`);}catch(e){throw r.error("Failed to setup i18n",e),e}}}async function U(t,r){if(!t.api)return [];r.info(`Loading routes from ${t.api.directory}...`);let e=[];try{let s=await j(t.api.directory);for(let i of s)try{let o=await import(i),c=o.default||o.routes;Array.isArray(c)&&e.push(...c);}catch(o){r.error(`Failed to load routes from ${i}`,o);}return r.success(`Routes loaded \u2192 ${e.length} routes`),e}catch(s){return r.error("Failed to scan route directory",s),[]}}async function j(t){let r=[];try{let e=await Array.fromAsync(new Bun.Glob("**/*.{ts,js}").scan(t));for(let s of e)r.push(`${t}/${s}`);}catch{}return r}function Q(t,r){let e=r?.onConfig?r.onConfig(t):t,s=new Logger(e.debug),i=new PluginRegistry(s),o=new ResourceMerger(s),c=new Map,l=new Map,u=null,d=null,a={config:e,databases:c,plugins:[]},b={config:e,server:null,databases:c,plugins:[],middlewares:l,start:async()=>{},stop:async()=>{},restart:async()=>{},getContext:()=>a,getMiddleware:n=>l.get(n)};async function S(){if(!e.plugins||e.plugins.length===0){s.info("No plugins to register");return}s.phase("REGISTER");for(let p of e.plugins)await i.register(p,b);a.plugins=i.getAll(),i.collectMiddlewares().forEach((p,y)=>l.set(y,p));}async function C(){s.phase("AWAKE");try{d=await k(e,s),a.clientBuild=d;let n=await F(e,s);a.uiBuild=n;let p=await H(e,s);a.styleBuild=p;let y=i.collectSchemas(),g=await P(e,y,s);c.clear(),g.forEach((h,m)=>c.set(m,h)),await T(e,s),await i.callHook("onAwake",a),await r?.onAwake?.(a);}catch(n){throw await r?.onError?.(a,"AWAKE",n),n}}async function L(){s.phase("START");try{let n=await U(e,s),p=i.collectRoutes(),g=[...e.routes||[],...n],h=o.mergeRoutes(g,p),m=e.static?Array.isArray(e.static)?e.static:[e.static]:[],v=i.collectStatic(),A=o.mergeStatic(m,v);s.info("Creating server...");let E;for(let f of a.plugins){let w=f;if(w.__spaErrorHandler){E=w.__spaErrorHandler,console.log(`[CruxJS] \u2713 Error handler collected from: ${f.name}`);break}}u=server({port:e.server?.port||3e3,hostname:e.server?.host||"localhost",logging:e.server?.logging,routes:h,static:A.length>0?A:void 0,security:e.security,middlewares:e.middlewares,i18n:e.i18n?{defaultLanguage:e.i18n.defaultLanguage,supportedLanguages:e.i18n.supportedLanguages}:void 0,onError:E}),c.forEach((f,w)=>{u.db.set(w,f);}),a.server=u,b.server=u,s.success(`Server created \u2192 ${e.server?.host||"localhost"}:${e.server?.port||3e3}`),await i.callHook("onStart",a),await r?.onStart?.(a);}catch(n){throw await r?.onError?.(a,"START",n),n}}async function $(){s.phase("READY");try{await u.start(),s.success(`Server running on http://${e.server?.host||"localhost"}:${e.server?.port||3e3}`),await i.callHook("onReady",a),await r?.onReady?.(a);}catch(n){throw await r?.onError?.(a,"READY",n),n}}return {config:e,server:u,databases:c,plugins:a.plugins,middlewares:l,async start(){await S(),await C(),await L(),await $();},async stop(){s.info("Stopping server...");try{u&&await u.stop(),c.forEach((n,p)=>{n.close(),s.info(`Database '${p}' closed`);}),await i.callHook("onShutdown",a),await r?.onFinish?.(a),s.success("Server stopped");}catch(n){throw s.error("Failed to stop server",n),n}},async restart(){await this.stop(),await this.start();},getContext(){return a},getMiddleware(n){return l.get(n)}}}
|
|
2
|
+
export{Q as createApp};//# sourceMappingURL=index.js.map
|
|
3
3
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"names":["buildClient","config","logger","result","outputs","err","setupDatabases","additionalSchemas","databases","dbConfigs","dbConfig","name","db","DB","schemaModule","schema","table","setupI18n","setupAuto","loadRoutes","routes","files","scanDirectory","file","module","exported","dir","entries","entry","createApp","userConfig","hooks","Logger","pluginRegistry","PluginRegistry","resourceMerger","ResourceMerger","middlewares","serverInstance","clientBuild","ctx","partialApp","phaseRegister","plugin","mw","phaseAwake","pluginSchemas","dbs","phaseStart","userApiRoutes","pluginRoutes","allUserRoutes","mergedRoutes","userStatic","pluginStatic","mergedStatic","errorHandler","pluginWithHandler","createServer","phaseReady"],"mappings":"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","file":"index.js","sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any */\r\n// src/index.ts\r\n//\r\n// Made with ❤️ by Maysara.\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ PACK ════════════════════════════════════════╗\r\n\r\n import { AppConfig, LifecycleContext, LifecycleHooks, AppInstance, RouteDefinition, AppMiddleware, Logger, PluginRegistry, ResourceMerger } from '@cruxjs/base';\r\n import { server as createServer } from '@minejs/server';\r\n import { DB } from '@minejs/db';\r\n import { setupAuto } from '@minejs/i18n';\r\n import type { TableSchema } from '@minejs/db';\r\n\r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ CORE ════════════════════════════════════════╗\r\n\r\n /**\r\n * Builds the client bundle using Bun's bundler\r\n * \r\n * @param {AppConfig} config - The application configuration containing client build settings\r\n * @param {Logger} logger - Logger instance for logging build progress and errors\r\n * @returns {Promise<{success: boolean, outputs: string[]} | null>} Build result with output paths, or null if no client config\r\n * @throws {Error} If the build process fails\r\n * \r\n * @example\r\n * const result = await buildClient(config, logger);\r\n * if (result?.success) {\r\n * console.log('Built to:', result.outputs);\r\n * }\r\n */\r\n async function buildClient(config: AppConfig, logger: Logger) {\r\n if (!config.client) return null;\r\n\r\n logger.info('Building client...');\r\n\r\n try {\r\n const result = await Bun.build({\r\n entrypoints: [config.client.entry],\r\n outdir: config.client.output,\r\n target: config.client.target || 'browser',\r\n minify: config.client.minify ?? !config.debug,\r\n sourcemap: config.client.sourcemap ?? config.debug ? 'inline' : 'none',\r\n external: config.client.external || []\r\n });\r\n\r\n if (!result.success) throw new Error('Build failed');\r\n\r\n const outputs = result.outputs.map(o => o.path);\r\n logger.success(`Client built → ${outputs.join(', ')}`);\r\n\r\n return { success: true, outputs };\r\n } catch (err) {\r\n logger.error('Failed to build client', err as Error);\r\n throw err;\r\n }\r\n }\r\n\r\n /**\r\n * Initializes and configures database connections\r\n * \r\n * Handles:\r\n * - Multiple database instances (primary, cache, etc.)\r\n * - User-defined schemas from config\r\n * - Plugin schemas from plugins\r\n * - In-memory databases for plugin-only scenarios\r\n * \r\n * @param {AppConfig} config - Application configuration with database settings\r\n * @param {TableSchema[]} additionalSchemas - Database schemas provided by plugins\r\n * @param {Logger} logger - Logger instance for logging setup progress\r\n * @returns {Promise<Map<string, DB>>} Map of database instances by name\r\n * @throws {Error} If schema loading or database initialization fails\r\n * \r\n * @example\r\n * const databases = await setupDatabases(config, pluginSchemas, logger);\r\n * const db = databases.get('primary');\r\n * const result = db.query('SELECT * FROM users');\r\n */\r\n async function setupDatabases(\r\n config: AppConfig,\r\n additionalSchemas: TableSchema[],\r\n logger: Logger\r\n ) {\r\n const databases = new Map<string, DB>();\r\n\r\n if (!config.database && additionalSchemas.length === 0) {\r\n logger.info('No database config, skipping setup');\r\n return databases;\r\n }\r\n\r\n const dbConfigs = config.database\r\n ? Array.isArray(config.database)\r\n ? config.database\r\n : [config.database]\r\n : [];\r\n\r\n logger.info('Setting up databases...');\r\n\r\n for (const dbConfig of dbConfigs) {\r\n const name = dbConfig.name || 'default';\r\n const db = new DB(dbConfig.connection);\r\n\r\n // Load user schema\r\n if (dbConfig.schema) {\r\n try {\r\n const schemaModule = await import(dbConfig.schema);\r\n const schema = schemaModule.default || schemaModule.schema;\r\n\r\n if (Array.isArray(schema)) {\r\n for (const table of schema) {\r\n db.defineSchema(table);\r\n }\r\n }\r\n } catch (err) {\r\n logger.error(`Failed to load schema: ${dbConfig.schema}`, err as Error);\r\n throw err;\r\n }\r\n }\r\n\r\n // Load plugin schemas for this database\r\n for (const schema of additionalSchemas) {\r\n db.defineSchema(schema);\r\n }\r\n\r\n databases.set(name, db);\r\n logger.success(`Database '${name}' ready`);\r\n }\r\n\r\n // If no user database but plugins need one, create default\r\n if (databases.size === 0 && additionalSchemas.length > 0) {\r\n const db = new DB(':memory:');\r\n\r\n for (const schema of additionalSchemas) {\r\n db.defineSchema(schema);\r\n }\r\n\r\n databases.set('default', db);\r\n logger.success(`Database 'default' ready (in-memory for plugins)`);\r\n }\r\n\r\n return databases;\r\n }\r\n\r\n /**\r\n * Initializes internationalization (i18n) support\r\n * \r\n * Loads language files and configures the i18n system based on:\r\n * - Default language\r\n * - Supported languages\r\n * - Base path for translation files\r\n * - File extension (json, cjson, etc.)\r\n * \r\n * @param {AppConfig} config - Application configuration with i18n settings\r\n * @param {Logger} logger - Logger instance for logging setup progress\r\n * @returns {Promise<void>}\r\n * @throws {Error} If i18n setup or language file loading fails\r\n * \r\n * @example\r\n * await setupI18n({\r\n * i18n: {\r\n * defaultLanguage: 'en',\r\n * supportedLanguages: ['en', 'ar'],\r\n * basePath: './src/i18n'\r\n * }\r\n * }, logger);\r\n */\r\n async function setupI18n(config: AppConfig, logger: Logger) {\r\n if (!config.i18n) return;\r\n\r\n logger.info('Setting up i18n...');\r\n\r\n try {\r\n await setupAuto({\r\n defaultLanguage: config.i18n.defaultLanguage,\r\n supportedLanguages: config.i18n.supportedLanguages,\r\n basePath: config.i18n.basePath,\r\n fileExtension: config.i18n.fileExtension || 'json'\r\n });\r\n\r\n logger.success(`i18n ready → ${config.i18n.supportedLanguages.join(', ')}`);\r\n } catch (err) {\r\n logger.error('Failed to setup i18n', err as Error);\r\n throw err;\r\n }\r\n }\r\n\r\n /**\r\n * Dynamically loads route definitions from API directory\r\n * \r\n * Scans the specified directory for route files and imports them.\r\n * Each route file should export either:\r\n * - `routes` property with RouteDefinition array\r\n * - Default export with RouteDefinition array\r\n * \r\n * @param {AppConfig} config - Application configuration with api.directory\r\n * @param {Logger} logger - Logger instance for logging scan progress\r\n * @returns {Promise<RouteDefinition[]>} Array of loaded route definitions\r\n * \r\n * @example\r\n * const routes = await loadRoutes({\r\n * api: { directory: './src/server/api' }\r\n * }, logger);\r\n * console.log(`Loaded ${routes.length} routes`);\r\n */\r\n async function loadRoutes(config: AppConfig, logger: Logger): Promise<RouteDefinition[]> {\r\n if (!config.api) return [];\r\n\r\n logger.info(`Loading routes from ${config.api.directory}...`);\r\n\r\n const routes: RouteDefinition[] = [];\r\n\r\n try {\r\n const files = await scanDirectory(config.api.directory);\r\n\r\n for (const file of files) {\r\n try {\r\n const module = await import(file);\r\n const exported = module.default || module.routes;\r\n\r\n if (Array.isArray(exported)) {\r\n routes.push(...exported);\r\n }\r\n } catch (err) {\r\n logger.error(`Failed to load routes from ${file}`, err as Error);\r\n }\r\n }\r\n\r\n logger.success(`Routes loaded → ${routes.length} routes`);\r\n return routes;\r\n } catch (err) {\r\n logger.error('Failed to scan route directory', err as Error);\r\n return [];\r\n }\r\n }\r\n\r\n /**\r\n * Scans a directory for TypeScript/JavaScript files\r\n * \r\n * Uses Bun's Glob API to recursively find all .ts and .js files in a directory.\r\n * Gracefully handles non-existent directories (returns empty array).\r\n * \r\n * @param {string} dir - Directory path to scan\r\n * @returns {Promise<string[]>} Array of absolute file paths found\r\n * \r\n * @example\r\n * const files = await scanDirectory('./src/server/api');\r\n * // Returns: ['./src/server/api/users.ts', './src/server/api/posts.ts']\r\n */\r\n async function scanDirectory(dir: string): Promise<string[]> {\r\n const files: string[] = [];\r\n\r\n try {\r\n const entries = await Array.fromAsync(\r\n new Bun.Glob('**/*.{ts,js}').scan(dir)\r\n );\r\n\r\n for (const entry of entries) {\r\n files.push(`${dir}/${entry}`);\r\n }\r\n } catch {\r\n // Directory doesn't exist\r\n }\r\n\r\n return files;\r\n }\r\n\r\n /**\r\n * Creates a CruxJS application instance with full lifecycle management\r\n * \r\n * This is the main entry point for building a CruxJS application. It:\r\n * 1. Registers plugins (Phase 0)\r\n * 2. Builds client, initializes databases, setups i18n (Phase 1: AWAKE)\r\n * 3. Creates server, merges routes and middleware (Phase 2: START)\r\n * 4. Starts the server and enables request handling (Phase 3: READY)\r\n * \r\n * Phases execute sequentially when `app.start()` is called.\r\n * \r\n * @param {AppConfig} userConfig - Application configuration object\r\n * @param {LifecycleHooks} [hooks] - Optional lifecycle event handlers\r\n * @returns {AppInstance} Application instance with control methods\r\n * \r\n * @throws {Error} Will throw if any lifecycle phase fails (unless caught in onError hook)\r\n * \r\n * @example\r\n * // Basic usage\r\n * const app = createApp({\r\n * debug: true,\r\n * server: { port: 3000 },\r\n * api: { directory: './src/api' },\r\n * plugins: [spaPlugin]\r\n * });\r\n * await app.start();\r\n * \r\n * @example\r\n * // With lifecycle hooks\r\n * const app = createApp(config, {\r\n * onAwake: async (ctx) => {\r\n * console.log('⏰ App awoken, databases ready');\r\n * },\r\n * onReady: async (ctx) => {\r\n * console.log('✅ Server ready:', ctx.server.getURL());\r\n * },\r\n * onError: async (ctx, phase, error) => {\r\n * console.error(`Error in ${phase}:`, error.message);\r\n * }\r\n * });\r\n * \r\n * @example\r\n * // With cleanup\r\n * const app = createApp(config);\r\n * await app.start();\r\n * // ... server is running\r\n * await app.stop(); // Cleanup\r\n */\r\n export function createApp(\r\n userConfig: AppConfig,\r\n hooks?: LifecycleHooks\r\n ): AppInstance {\r\n // Apply config hook\r\n const config: AppConfig = hooks?.onConfig\r\n ? hooks.onConfig(userConfig) as AppConfig\r\n : userConfig;\r\n\r\n const logger = new Logger(config.debug);\r\n const pluginRegistry = new PluginRegistry(logger);\r\n const resourceMerger = new ResourceMerger(logger);\r\n\r\n const databases = new Map<string, DB>();\r\n const middlewares = new Map<string, AppMiddleware>();\r\n let serverInstance: any = null;\r\n let clientBuild: any = null;\r\n\r\n const ctx: LifecycleContext = {\r\n config,\r\n databases,\r\n plugins: []\r\n };\r\n\r\n // Create partial app instance for plugin registration\r\n const partialApp: AppInstance = {\r\n config,\r\n server: null,\r\n databases,\r\n plugins: [],\r\n middlewares,\r\n start: async () => { },\r\n stop: async () => { },\r\n restart: async () => { },\r\n getContext: () => ctx,\r\n getMiddleware: (name: string) => middlewares.get(name)\r\n };\r\n\r\n // ─────────────────────────────────────────────────────────\r\n // Phase 0: Plugin Registration\r\n // ─────────────────────────────────────────────────────────\r\n\r\n async function phaseRegister() {\r\n if (!config.plugins || config.plugins.length === 0) {\r\n logger.info('No plugins to register');\r\n return;\r\n }\r\n\r\n logger.phase('REGISTER');\r\n\r\n for (const plugin of config.plugins) {\r\n await pluginRegistry.register(plugin, partialApp);\r\n }\r\n\r\n ctx.plugins = pluginRegistry.getAll();\r\n\r\n // Collect plugin middlewares\r\n const pluginMiddlewares = pluginRegistry.collectMiddlewares();\r\n pluginMiddlewares.forEach((mw, name) => middlewares.set(name, mw));\r\n }\r\n\r\n // ─────────────────────────────────────────────────────────\r\n // Phase 1: AWAKE\r\n // ─────────────────────────────────────────────────────────\r\n\r\n async function phaseAwake() {\r\n logger.phase('AWAKE');\r\n\r\n try {\r\n // Build client\r\n clientBuild = await buildClient(config, logger);\r\n ctx.clientBuild = clientBuild;\r\n\r\n // Collect plugin schemas\r\n const pluginSchemas = pluginRegistry.collectSchemas();\r\n\r\n // Setup databases\r\n const dbs = await setupDatabases(config, pluginSchemas, logger);\r\n databases.clear();\r\n dbs.forEach((db, name) => databases.set(name, db));\r\n\r\n // Setup i18n\r\n await setupI18n(config, logger);\r\n\r\n // Call plugin hooks\r\n await pluginRegistry.callHook('onAwake', ctx);\r\n\r\n // Call user hook\r\n await hooks?.onAwake?.(ctx);\r\n } catch (err) {\r\n await hooks?.onError?.(ctx, 'AWAKE', err as Error);\r\n throw err;\r\n }\r\n }\r\n\r\n // ─────────────────────────────────────────────────────────\r\n // Phase 2: START\r\n // ─────────────────────────────────────────────────────────\r\n\r\n async function phaseStart() {\r\n logger.phase('START');\r\n\r\n try {\r\n // Load user routes\r\n const userApiRoutes = await loadRoutes(config, logger);\r\n\r\n // Collect plugin routes\r\n const pluginRoutes = pluginRegistry.collectRoutes();\r\n\r\n // Merge user routes + plugin routes\r\n const userRoutes = config.routes || [];\r\n const allUserRoutes = [...userRoutes, ...userApiRoutes];\r\n const mergedRoutes = resourceMerger.mergeRoutes(allUserRoutes, pluginRoutes);\r\n\r\n // Collect static configs\r\n const userStatic = config.static\r\n ? Array.isArray(config.static)\r\n ? config.static\r\n : [config.static]\r\n : [];\r\n const pluginStatic = pluginRegistry.collectStatic();\r\n const mergedStatic = resourceMerger.mergeStatic(userStatic, pluginStatic);\r\n\r\n logger.info('Creating server...');\r\n\r\n // Collect error handlers from plugins (especially SPA plugin)\r\n let errorHandler: ((statusCode: number, path: string) => Response) | undefined;\r\n for (const plugin of ctx.plugins) {\r\n const pluginWithHandler = plugin as any;\r\n if (pluginWithHandler.__spaErrorHandler) {\r\n errorHandler = pluginWithHandler.__spaErrorHandler;\r\n console.log(`[CruxJS] ✓ Error handler collected from: ${plugin.name}`);\r\n break; // Use first error handler found\r\n }\r\n }\r\n\r\n // Create server\r\n serverInstance = createServer({\r\n port: config.server?.port || 3000,\r\n hostname: config.server?.host || 'localhost',\r\n logging: config.server?.logging,\r\n routes: mergedRoutes,\r\n static: mergedStatic.length > 0 ? mergedStatic : undefined,\r\n security: config.security,\r\n middlewares: config.middlewares,\r\n i18n: config.i18n\r\n ? {\r\n defaultLanguage: config.i18n.defaultLanguage,\r\n supportedLanguages: config.i18n.supportedLanguages\r\n }\r\n : undefined,\r\n onError: errorHandler\r\n });\r\n\r\n // Inject databases\r\n databases.forEach((db, name) => {\r\n serverInstance.db.set(name, db);\r\n });\r\n\r\n ctx.server = serverInstance;\r\n partialApp.server = serverInstance;\r\n\r\n logger.success(\r\n `Server created → ${config.server?.host || 'localhost'}:${config.server?.port || 3000}`\r\n );\r\n\r\n // Call plugin hooks\r\n await pluginRegistry.callHook('onStart', ctx);\r\n\r\n // Call user hook\r\n await hooks?.onStart?.(ctx);\r\n } catch (err) {\r\n await hooks?.onError?.(ctx, 'START', err as Error);\r\n throw err;\r\n }\r\n }\r\n\r\n // ─────────────────────────────────────────────────────────\r\n // Phase 3: READY\r\n // ─────────────────────────────────────────────────────────\r\n\r\n async function phaseReady() {\r\n logger.phase('READY');\r\n\r\n try {\r\n await serverInstance.start();\r\n\r\n logger.success(\r\n `Server running on http://${config.server?.host || 'localhost'}:${config.server?.port || 3000}`\r\n );\r\n\r\n // Call plugin hooks\r\n await pluginRegistry.callHook('onReady', ctx);\r\n\r\n // Call user hook\r\n await hooks?.onReady?.(ctx);\r\n } catch (err) {\r\n await hooks?.onError?.(ctx, 'READY', err as Error);\r\n throw err;\r\n }\r\n }\r\n\r\n // ─────────────────────────────────────────────────────────\r\n // App Instance\r\n // ─────────────────────────────────────────────────────────\r\n\r\n return {\r\n config,\r\n server: serverInstance,\r\n databases,\r\n plugins: ctx.plugins,\r\n middlewares,\r\n\r\n async start() {\r\n await phaseRegister();\r\n await phaseAwake();\r\n await phaseStart();\r\n await phaseReady();\r\n },\r\n\r\n async stop() {\r\n logger.info('Stopping server...');\r\n\r\n try {\r\n if (serverInstance) {\r\n await serverInstance.stop();\r\n }\r\n\r\n databases.forEach((db, name) => {\r\n db.close();\r\n logger.info(`Database '${name}' closed`);\r\n });\r\n\r\n // Call plugin hooks\r\n await pluginRegistry.callHook('onShutdown', ctx);\r\n\r\n await hooks?.onFinish?.(ctx);\r\n\r\n logger.success('Server stopped');\r\n } catch (err) {\r\n logger.error('Failed to stop server', err as Error);\r\n throw err;\r\n }\r\n },\r\n\r\n async restart() {\r\n await this.stop();\r\n await this.start();\r\n },\r\n\r\n getContext() {\r\n return ctx;\r\n },\r\n\r\n getMiddleware(name: string) {\r\n return middlewares.get(name);\r\n }\r\n };\r\n }\r\n\r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ ════ ════════════════════════════════════════╗\r\n\r\n export * from '@cruxjs/base';\r\n\r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"names":["buildClient","config","logger","result","outputs","o","err","buildUI","buildStyles","setupDatabases","additionalSchemas","databases","dbConfigs","dbConfig","name","db","DB","schemaModule","schema","table","setupI18n","setupAuto","loadRoutes","routes","files","scanDirectory","file","module","exported","dir","entries","entry","createApp","userConfig","hooks","Logger","pluginRegistry","PluginRegistry","resourceMerger","ResourceMerger","middlewares","serverInstance","clientBuild","ctx","partialApp","phaseRegister","plugin","mw","phaseAwake","uiBuild","styleBuild","pluginSchemas","dbs","phaseStart","userApiRoutes","pluginRoutes","allUserRoutes","mergedRoutes","userStatic","pluginStatic","mergedStatic","errorHandler","pluginWithHandler","createServer","phaseReady"],"mappings":"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","file":"index.js","sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any */\r\n// src/index.ts\r\n//\r\n// Made with ❤️ by Maysara.\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ PACK ════════════════════════════════════════╗\r\n\r\n import { AppConfig, LifecycleContext, LifecycleHooks, AppInstance, RouteDefinition, AppMiddleware, Logger, PluginRegistry, ResourceMerger } from '@cruxjs/base';\r\n import { server as createServer } from '@minejs/server';\r\n import { DB } from '@minejs/db';\r\n import { setupAuto } from '@minejs/i18n';\r\n import type { TableSchema } from '@minejs/db';\r\n\r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ CORE ════════════════════════════════════════╗\r\n\r\n /**\r\n * Builds the client bundle using Bun's bundler\r\n *\r\n * @param {AppConfig} config - The application configuration containing client build settings\r\n * @param {Logger} logger - Logger instance for logging build progress and errors\r\n * @returns {Promise<{success: boolean, outputs: string[]} | null>} Build result with output paths, or null if no client config\r\n * @throws {Error} If the build process fails\r\n *\r\n * @example\r\n * const result = await buildClient(config, logger);\r\n * if (result?.success) {\r\n * console.log('Built to:', result.outputs);\r\n * }\r\n */\r\n async function buildClient(config: AppConfig, logger: Logger) {\r\n if (!config.client) return null;\r\n\r\n logger.info('Building client...');\r\n\r\n try {\r\n const result = await Bun.build({\r\n entrypoints: [config.client.entry],\r\n outdir: config.client.output,\r\n target: config.client.target || 'browser',\r\n minify: config.client.minify ?? !config.debug,\r\n sourcemap: config.client.sourcemap ?? config.debug ? 'inline' : 'none',\r\n external: config.client.external || []\r\n });\r\n\r\n if (!result.success) throw new Error('Build failed');\r\n\r\n const outputs = result.outputs.map(o => o.path);\r\n logger.success(`Client built → ${outputs.join(', ')}`);\r\n\r\n return { success: true, outputs };\r\n } catch (err) {\r\n logger.error('Failed to build client', err as Error);\r\n throw err;\r\n }\r\n }\r\n\r\n /**\r\n * Builds and installs UI library if specified in config\r\n *\r\n * Handles:\r\n * - Installing the specified UI package from npm\r\n * - Copying minified UI assets to the configured output path\r\n * - Supports packages like @mineui/core\r\n *\r\n * @param {AppConfig} config - The application configuration containing ui settings\r\n * @param {Logger} logger - Logger instance for logging build progress and errors\r\n * @returns {Promise<{success: boolean, output: string} | null>} Build result with output path, or null if no ui config\r\n * @throws {Error} If the build process fails\r\n *\r\n * @example\r\n * const result = await buildUI(config, logger);\r\n * if (result?.success) {\r\n * console.log('UI built to:', result.output);\r\n * }\r\n */\r\n async function buildUI(config: AppConfig, logger: Logger) {\r\n if (!config.ui) return null;\r\n\r\n logger.info(`Building UI from package: ${config.ui.package}...`);\r\n\r\n try {\r\n // Install the UI package\r\n const installProcess = Bun.spawn(['bun', 'add', config.ui.package], {\r\n stdio: ['ignore', 'pipe', 'pipe']\r\n });\r\n\r\n const installResult = await installProcess.exited;\r\n\r\n if (installResult !== 0) {\r\n throw new Error(`Failed to install UI package: ${config.ui.package}`);\r\n }\r\n\r\n logger.info(`UI package installed: ${config.ui.package}`);\r\n\r\n // TODO: Copy minified assets to output directory\r\n // This would typically involve:\r\n // 1. Finding the package in node_modules\r\n // 2. Locating dist/minified CSS files\r\n // 3. Copying to config.ui.output path\r\n\r\n logger.success(`UI built → ${config.ui.output}`);\r\n\r\n return { success: true, output: config.ui.output };\r\n } catch (err) {\r\n logger.error('Failed to build UI', err as Error);\r\n throw err;\r\n }\r\n }\r\n\r\n /**\r\n * Builds SCSS/CSS styles using a bundler\r\n *\r\n * Handles:\r\n * - Compiling SCSS to CSS\r\n * - Minifying CSS if configured\r\n * - Generating source maps if configured\r\n * - Outputting to specified directory\r\n *\r\n * @param {AppConfig} config - The application configuration containing style settings\r\n * @param {Logger} logger - Logger instance for logging build progress and errors\r\n * @returns {Promise<{success: boolean, output: string} | null>} Build result with output path, or null if no style config\r\n * @throws {Error} If the build process fails\r\n *\r\n * @example\r\n * const result = await buildStyles(config, logger);\r\n * if (result?.success) {\r\n * console.log('Styles built to:', result.output);\r\n * }\r\n */\r\n async function buildStyles(config: AppConfig, logger: Logger) {\r\n if (!config.style) return null;\r\n\r\n logger.info(`Building styles from: ${config.style.entry}...`);\r\n\r\n try {\r\n // Use Bun's built-in bundler to handle SCSS/CSS\r\n const result = await Bun.build({\r\n entrypoints: [config.style.entry],\r\n outdir: config.style.output,\r\n minify: config.style.minify ?? !config.debug,\r\n sourcemap: config.style.sourcemap ?? config.debug ? 'inline' : 'none'\r\n });\r\n\r\n if (!result.success) {\r\n throw new Error('Style build failed');\r\n }\r\n\r\n logger.success(`Styles built → ${config.style.output}`);\r\n\r\n return { success: true, output: config.style.output };\r\n } catch (err) {\r\n logger.error('Failed to build styles', err as Error);\r\n throw err;\r\n }\r\n }\r\n\r\n /**\r\n * Initializes and configures database connections\r\n *\r\n * Handles:\r\n * - Multiple database instances (primary, cache, etc.)\r\n * - User-defined schemas from config\r\n * - Plugin schemas from plugins\r\n * - In-memory databases for plugin-only scenarios\r\n *\r\n * @param {AppConfig} config - Application configuration with database settings\r\n * @param {TableSchema[]} additionalSchemas - Database schemas provided by plugins\r\n * @param {Logger} logger - Logger instance for logging setup progress\r\n * @returns {Promise<Map<string, DB>>} Map of database instances by name\r\n * @throws {Error} If schema loading or database initialization fails\r\n *\r\n * @example\r\n * const databases = await setupDatabases(config, pluginSchemas, logger);\r\n * const db = databases.get('primary');\r\n * const result = db.query('SELECT * FROM users');\r\n */\r\n async function setupDatabases(\r\n config: AppConfig,\r\n additionalSchemas: TableSchema[],\r\n logger: Logger\r\n ) {\r\n const databases = new Map<string, DB>();\r\n\r\n if (!config.database && additionalSchemas.length === 0) {\r\n logger.info('No database config, skipping setup');\r\n return databases;\r\n }\r\n\r\n const dbConfigs = config.database\r\n ? Array.isArray(config.database)\r\n ? config.database\r\n : [config.database]\r\n : [];\r\n\r\n logger.info('Setting up databases...');\r\n\r\n for (const dbConfig of dbConfigs) {\r\n const name = dbConfig.name || 'default';\r\n const db = new DB(dbConfig.connection);\r\n\r\n // Load user schema\r\n if (dbConfig.schema) {\r\n try {\r\n const schemaModule = await import(dbConfig.schema);\r\n const schema = schemaModule.default || schemaModule.schema;\r\n\r\n if (Array.isArray(schema)) {\r\n for (const table of schema) {\r\n db.defineSchema(table);\r\n }\r\n }\r\n } catch (err) {\r\n logger.error(`Failed to load schema: ${dbConfig.schema}`, err as Error);\r\n throw err;\r\n }\r\n }\r\n\r\n // Load plugin schemas for this database\r\n for (const schema of additionalSchemas) {\r\n db.defineSchema(schema);\r\n }\r\n\r\n databases.set(name, db);\r\n logger.success(`Database '${name}' ready`);\r\n }\r\n\r\n // If no user database but plugins need one, create default\r\n if (databases.size === 0 && additionalSchemas.length > 0) {\r\n const db = new DB(':memory:');\r\n\r\n for (const schema of additionalSchemas) {\r\n db.defineSchema(schema);\r\n }\r\n\r\n databases.set('default', db);\r\n logger.success(`Database 'default' ready (in-memory for plugins)`);\r\n }\r\n\r\n return databases;\r\n }\r\n\r\n /**\r\n * Initializes internationalization (i18n) support\r\n *\r\n * Loads language files and configures the i18n system based on:\r\n * - Default language\r\n * - Supported languages\r\n * - Base path for translation files\r\n * - File extension (json, cjson, etc.)\r\n *\r\n * @param {AppConfig} config - Application configuration with i18n settings\r\n * @param {Logger} logger - Logger instance for logging setup progress\r\n * @returns {Promise<void>}\r\n * @throws {Error} If i18n setup or language file loading fails\r\n *\r\n * @example\r\n * await setupI18n({\r\n * i18n: {\r\n * defaultLanguage: 'en',\r\n * supportedLanguages: ['en', 'ar'],\r\n * basePath: './src/i18n'\r\n * }\r\n * }, logger);\r\n */\r\n async function setupI18n(config: AppConfig, logger: Logger) {\r\n if (!config.i18n) return;\r\n\r\n logger.info('Setting up i18n...');\r\n\r\n try {\r\n await setupAuto({\r\n defaultLanguage: config.i18n.defaultLanguage,\r\n supportedLanguages: config.i18n.supportedLanguages,\r\n basePath: config.i18n.basePath,\r\n fileExtension: config.i18n.fileExtension || 'json'\r\n });\r\n\r\n logger.success(`i18n ready → ${config.i18n.supportedLanguages.join(', ')}`);\r\n } catch (err) {\r\n logger.error('Failed to setup i18n', err as Error);\r\n throw err;\r\n }\r\n }\r\n\r\n /**\r\n * Dynamically loads route definitions from API directory\r\n *\r\n * Scans the specified directory for route files and imports them.\r\n * Each route file should export either:\r\n * - `routes` property with RouteDefinition array\r\n * - Default export with RouteDefinition array\r\n *\r\n * @param {AppConfig} config - Application configuration with api.directory\r\n * @param {Logger} logger - Logger instance for logging scan progress\r\n * @returns {Promise<RouteDefinition[]>} Array of loaded route definitions\r\n *\r\n * @example\r\n * const routes = await loadRoutes({\r\n * api: { directory: './src/server/api' }\r\n * }, logger);\r\n * console.log(`Loaded ${routes.length} routes`);\r\n */\r\n async function loadRoutes(config: AppConfig, logger: Logger): Promise<RouteDefinition[]> {\r\n if (!config.api) return [];\r\n\r\n logger.info(`Loading routes from ${config.api.directory}...`);\r\n\r\n const routes: RouteDefinition[] = [];\r\n\r\n try {\r\n const files = await scanDirectory(config.api.directory);\r\n\r\n for (const file of files) {\r\n try {\r\n const module = await import(file);\r\n const exported = module.default || module.routes;\r\n\r\n if (Array.isArray(exported)) {\r\n routes.push(...exported);\r\n }\r\n } catch (err) {\r\n logger.error(`Failed to load routes from ${file}`, err as Error);\r\n }\r\n }\r\n\r\n logger.success(`Routes loaded → ${routes.length} routes`);\r\n return routes;\r\n } catch (err) {\r\n logger.error('Failed to scan route directory', err as Error);\r\n return [];\r\n }\r\n }\r\n\r\n /**\r\n * Scans a directory for TypeScript/JavaScript files\r\n *\r\n * Uses Bun's Glob API to recursively find all .ts and .js files in a directory.\r\n * Gracefully handles non-existent directories (returns empty array).\r\n *\r\n * @param {string} dir - Directory path to scan\r\n * @returns {Promise<string[]>} Array of absolute file paths found\r\n *\r\n * @example\r\n * const files = await scanDirectory('./src/server/api');\r\n * // Returns: ['./src/server/api/users.ts', './src/server/api/posts.ts']\r\n */\r\n async function scanDirectory(dir: string): Promise<string[]> {\r\n const files: string[] = [];\r\n\r\n try {\r\n const entries = await Array.fromAsync(\r\n new Bun.Glob('**/*.{ts,js}').scan(dir)\r\n );\r\n\r\n for (const entry of entries) {\r\n files.push(`${dir}/${entry}`);\r\n }\r\n } catch {\r\n // Directory doesn't exist\r\n }\r\n\r\n return files;\r\n }\r\n\r\n /**\r\n * Creates a CruxJS application instance with full lifecycle management\r\n *\r\n * This is the main entry point for building a CruxJS application. It:\r\n * 1. Registers plugins (Phase 0)\r\n * 2. Builds client, initializes databases, setups i18n (Phase 1: AWAKE)\r\n * 3. Creates server, merges routes and middleware (Phase 2: START)\r\n * 4. Starts the server and enables request handling (Phase 3: READY)\r\n *\r\n * Phases execute sequentially when `app.start()` is called.\r\n *\r\n * @param {AppConfig} userConfig - Application configuration object\r\n * @param {LifecycleHooks} [hooks] - Optional lifecycle event handlers\r\n * @returns {AppInstance} Application instance with control methods\r\n *\r\n * @throws {Error} Will throw if any lifecycle phase fails (unless caught in onError hook)\r\n *\r\n * @example\r\n * // Basic usage\r\n * const app = createApp({\r\n * debug: true,\r\n * server: { port: 3000 },\r\n * api: { directory: './src/api' },\r\n * plugins: [spaPlugin]\r\n * });\r\n * await app.start();\r\n *\r\n * @example\r\n * // With lifecycle hooks\r\n * const app = createApp(config, {\r\n * onAwake: async (ctx) => {\r\n * console.log('⏰ App awoken, databases ready');\r\n * },\r\n * onReady: async (ctx) => {\r\n * console.log('✅ Server ready:', ctx.server.getURL());\r\n * },\r\n * onError: async (ctx, phase, error) => {\r\n * console.error(`Error in ${phase}:`, error.message);\r\n * }\r\n * });\r\n *\r\n * @example\r\n * // With cleanup\r\n * const app = createApp(config);\r\n * await app.start();\r\n * // ... server is running\r\n * await app.stop(); // Cleanup\r\n */\r\n export function createApp(\r\n userConfig: AppConfig,\r\n hooks?: LifecycleHooks\r\n ): AppInstance {\r\n // Apply config hook\r\n const config: AppConfig = hooks?.onConfig\r\n ? hooks.onConfig(userConfig) as AppConfig\r\n : userConfig;\r\n\r\n const logger = new Logger(config.debug);\r\n const pluginRegistry = new PluginRegistry(logger);\r\n const resourceMerger = new ResourceMerger(logger);\r\n\r\n const databases = new Map<string, DB>();\r\n const middlewares = new Map<string, AppMiddleware>();\r\n let serverInstance: any = null;\r\n let clientBuild: any = null;\r\n\r\n const ctx: LifecycleContext = {\r\n config,\r\n databases,\r\n plugins: []\r\n };\r\n\r\n // Create partial app instance for plugin registration\r\n const partialApp: AppInstance = {\r\n config,\r\n server: null,\r\n databases,\r\n plugins: [],\r\n middlewares,\r\n start: async () => { },\r\n stop: async () => { },\r\n restart: async () => { },\r\n getContext: () => ctx,\r\n getMiddleware: (name: string) => middlewares.get(name)\r\n };\r\n\r\n // ─────────────────────────────────────────────────────────\r\n // Phase 0: Plugin Registration\r\n // ─────────────────────────────────────────────────────────\r\n\r\n async function phaseRegister() {\r\n if (!config.plugins || config.plugins.length === 0) {\r\n logger.info('No plugins to register');\r\n return;\r\n }\r\n\r\n logger.phase('REGISTER');\r\n\r\n for (const plugin of config.plugins) {\r\n await pluginRegistry.register(plugin, partialApp);\r\n }\r\n\r\n ctx.plugins = pluginRegistry.getAll();\r\n\r\n // Collect plugin middlewares\r\n const pluginMiddlewares = pluginRegistry.collectMiddlewares();\r\n pluginMiddlewares.forEach((mw, name) => middlewares.set(name, mw));\r\n }\r\n\r\n // ─────────────────────────────────────────────────────────\r\n // Phase 1: AWAKE\r\n // ─────────────────────────────────────────────────────────\r\n\r\n async function phaseAwake() {\r\n logger.phase('AWAKE');\r\n\r\n try {\r\n // Build client\r\n clientBuild = await buildClient(config, logger);\r\n ctx.clientBuild = clientBuild;\r\n\r\n // Build UI library if configured\r\n const uiBuild = await buildUI(config, logger);\r\n ctx.uiBuild = uiBuild;\r\n\r\n // Build styles if configured\r\n const styleBuild = await buildStyles(config, logger);\r\n ctx.styleBuild = styleBuild;\r\n\r\n // Collect plugin schemas\r\n const pluginSchemas = pluginRegistry.collectSchemas();\r\n\r\n // Setup databases\r\n const dbs = await setupDatabases(config, pluginSchemas, logger);\r\n databases.clear();\r\n dbs.forEach((db, name) => databases.set(name, db));\r\n\r\n // Setup i18n\r\n await setupI18n(config, logger);\r\n\r\n // Call plugin hooks\r\n await pluginRegistry.callHook('onAwake', ctx);\r\n\r\n // Call user hook\r\n await hooks?.onAwake?.(ctx);\r\n } catch (err) {\r\n await hooks?.onError?.(ctx, 'AWAKE', err as Error);\r\n throw err;\r\n }\r\n }\r\n\r\n // ─────────────────────────────────────────────────────────\r\n // Phase 2: START\r\n // ─────────────────────────────────────────────────────────\r\n\r\n async function phaseStart() {\r\n logger.phase('START');\r\n\r\n try {\r\n // Load user routes\r\n const userApiRoutes = await loadRoutes(config, logger);\r\n\r\n // Collect plugin routes\r\n const pluginRoutes = pluginRegistry.collectRoutes();\r\n\r\n // Merge user routes + plugin routes\r\n const userRoutes = config.routes || [];\r\n const allUserRoutes = [...userRoutes, ...userApiRoutes];\r\n const mergedRoutes = resourceMerger.mergeRoutes(allUserRoutes, pluginRoutes);\r\n\r\n // Collect static configs\r\n const userStatic = config.static\r\n ? Array.isArray(config.static)\r\n ? config.static\r\n : [config.static]\r\n : [];\r\n const pluginStatic = pluginRegistry.collectStatic();\r\n const mergedStatic = resourceMerger.mergeStatic(userStatic, pluginStatic);\r\n\r\n logger.info('Creating server...');\r\n\r\n // Collect error handlers from plugins (especially SPA plugin)\r\n let errorHandler: ((statusCode: number, path: string) => Response) | undefined;\r\n for (const plugin of ctx.plugins) {\r\n const pluginWithHandler = plugin as any;\r\n if (pluginWithHandler.__spaErrorHandler) {\r\n errorHandler = pluginWithHandler.__spaErrorHandler;\r\n console.log(`[CruxJS] ✓ Error handler collected from: ${plugin.name}`);\r\n break; // Use first error handler found\r\n }\r\n }\r\n\r\n // Create server\r\n serverInstance = createServer({\r\n port: config.server?.port || 3000,\r\n hostname: config.server?.host || 'localhost',\r\n logging: config.server?.logging,\r\n routes: mergedRoutes,\r\n static: mergedStatic.length > 0 ? mergedStatic : undefined,\r\n security: config.security,\r\n middlewares: config.middlewares,\r\n i18n: config.i18n\r\n ? {\r\n defaultLanguage: config.i18n.defaultLanguage,\r\n supportedLanguages: config.i18n.supportedLanguages\r\n }\r\n : undefined,\r\n onError: errorHandler\r\n });\r\n\r\n // Inject databases\r\n databases.forEach((db, name) => {\r\n serverInstance.db.set(name, db);\r\n });\r\n\r\n ctx.server = serverInstance;\r\n partialApp.server = serverInstance;\r\n\r\n logger.success(\r\n `Server created → ${config.server?.host || 'localhost'}:${config.server?.port || 3000}`\r\n );\r\n\r\n // Call plugin hooks\r\n await pluginRegistry.callHook('onStart', ctx);\r\n\r\n // Call user hook\r\n await hooks?.onStart?.(ctx);\r\n } catch (err) {\r\n await hooks?.onError?.(ctx, 'START', err as Error);\r\n throw err;\r\n }\r\n }\r\n\r\n // ─────────────────────────────────────────────────────────\r\n // Phase 3: READY\r\n // ─────────────────────────────────────────────────────────\r\n\r\n async function phaseReady() {\r\n logger.phase('READY');\r\n\r\n try {\r\n await serverInstance.start();\r\n\r\n logger.success(\r\n `Server running on http://${config.server?.host || 'localhost'}:${config.server?.port || 3000}`\r\n );\r\n\r\n // Call plugin hooks\r\n await pluginRegistry.callHook('onReady', ctx);\r\n\r\n // Call user hook\r\n await hooks?.onReady?.(ctx);\r\n } catch (err) {\r\n await hooks?.onError?.(ctx, 'READY', err as Error);\r\n throw err;\r\n }\r\n }\r\n\r\n // ─────────────────────────────────────────────────────────\r\n // App Instance\r\n // ─────────────────────────────────────────────────────────\r\n\r\n return {\r\n config,\r\n server: serverInstance,\r\n databases,\r\n plugins: ctx.plugins,\r\n middlewares,\r\n\r\n async start() {\r\n await phaseRegister();\r\n await phaseAwake();\r\n await phaseStart();\r\n await phaseReady();\r\n },\r\n\r\n async stop() {\r\n logger.info('Stopping server...');\r\n\r\n try {\r\n if (serverInstance) {\r\n await serverInstance.stop();\r\n }\r\n\r\n databases.forEach((db, name) => {\r\n db.close();\r\n logger.info(`Database '${name}' closed`);\r\n });\r\n\r\n // Call plugin hooks\r\n await pluginRegistry.callHook('onShutdown', ctx);\r\n\r\n await hooks?.onFinish?.(ctx);\r\n\r\n logger.success('Server stopped');\r\n } catch (err) {\r\n logger.error('Failed to stop server', err as Error);\r\n throw err;\r\n }\r\n },\r\n\r\n async restart() {\r\n await this.stop();\r\n await this.start();\r\n },\r\n\r\n getContext() {\r\n return ctx;\r\n },\r\n\r\n getMiddleware(name: string) {\r\n return middlewares.get(name);\r\n }\r\n };\r\n }\r\n\r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ ════ ════════════════════════════════════════╗\r\n\r\n export * from '@cruxjs/base';\r\n\r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cruxjs/app",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.3",
|
|
4
4
|
"description": "Full-stack framework orchestrator for building modern web applications. Zero configuration. Plugin-based architecture.",
|
|
5
5
|
"keywords": ["cruxjs", "app"],
|
|
6
6
|
"license": "MIT",
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"bun": "^1.3.3"
|
|
41
41
|
},
|
|
42
42
|
"dependencies": {
|
|
43
|
-
"@cruxjs/base": "^0.0.
|
|
43
|
+
"@cruxjs/base": "^0.0.5",
|
|
44
44
|
"@minejs/db": "^0.0.3",
|
|
45
45
|
"@minejs/i18n": "^0.0.3",
|
|
46
46
|
"@minejs/server": "^0.0.5"
|