clovie 0.1.29 → 0.1.33

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.
Files changed (41) hide show
  1. package/README.md +26 -25
  2. package/bin/cli.js +0 -10
  3. package/dist/{ExpressAdapter-DL0Y9BG2.js → ExpressAdapter-D6owl_CX.js} +16 -11
  4. package/dist/ExpressAdapter-D6owl_CX.js.map +1 -0
  5. package/dist/cjs/{ExpressAdapter-De7bTuZu.cjs → ExpressAdapter-Z_FtN3dq.cjs} +13 -8
  6. package/dist/cjs/ExpressAdapter-Z_FtN3dq.cjs.map +1 -0
  7. package/dist/cjs/createClovie-BziskasS.cjs +4260 -0
  8. package/dist/cjs/createClovie-BziskasS.cjs.map +1 -0
  9. package/dist/cjs/index.cjs +5 -4
  10. package/dist/cjs/index.cjs.map +1 -1
  11. package/dist/createClovie-x0YNcttr.js +4282 -0
  12. package/dist/createClovie-x0YNcttr.js.map +1 -0
  13. package/dist/index.d.ts +1 -1
  14. package/dist/index.js +13 -5
  15. package/dist/index.js.map +1 -1
  16. package/package.json +6 -5
  17. package/scripts/build-types.js +1 -1
  18. package/templates/server/AI_DEVELOPMENT_GUIDE.md +59 -439
  19. package/templates/server/README.md +21 -116
  20. package/templates/server/clovie.config.js +7 -98
  21. package/templates/server/views/about.html +2 -12
  22. package/templates/server/views/index.html +2 -2
  23. package/templates/static/AI_DEVELOPMENT_GUIDE.md +20 -77
  24. package/dist/ExpressAdapter-DL0Y9BG2.js.map +0 -1
  25. package/dist/LiveReload-CXR08AFg.js +0 -95
  26. package/dist/LiveReload-CXR08AFg.js.map +0 -1
  27. package/dist/Server-BR7ZqQBN.js +0 -531
  28. package/dist/Server-BR7ZqQBN.js.map +0 -1
  29. package/dist/cjs/ExpressAdapter-De7bTuZu.cjs.map +0 -1
  30. package/dist/cjs/LiveReload-TdgPIiCn.cjs +0 -75
  31. package/dist/cjs/LiveReload-TdgPIiCn.cjs.map +0 -1
  32. package/dist/cjs/Server-BVelCzau.cjs +0 -531
  33. package/dist/cjs/Server-BVelCzau.cjs.map +0 -1
  34. package/dist/cjs/createClovie-DdMTZ_dO.cjs +0 -6380
  35. package/dist/cjs/createClovie-DdMTZ_dO.cjs.map +0 -1
  36. package/dist/cjs/index-9MtAg70f.cjs +0 -461
  37. package/dist/cjs/index-9MtAg70f.cjs.map +0 -1
  38. package/dist/createClovie-LSdi1lXJ.js +0 -6396
  39. package/dist/createClovie-LSdi1lXJ.js.map +0 -1
  40. package/dist/index-CpXKm4Ga.js +0 -480
  41. package/dist/index-CpXKm4Ga.js.map +0 -1
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  > *"The Hollow Knight of Web Dev"* - Simple but deep, easy to start but room to grow.
4
4
 
5
- A powerful Node.js-based **static site generator** and **full-stack web framework** that bridges the gap between simple static sites and complex web applications. Built on the **@brickworks/engine** service architecture for maximum flexibility and maintainability.
5
+ A powerful Node.js-based **static site generator** and **full-stack web framework** that bridges the gap between simple static sites and complex web applications. Built on the **@jucie.io/engine** service architecture for maximum flexibility and maintainability.
6
6
 
7
7
  ## 🚀 Quick Start
8
8
 
@@ -24,13 +24,13 @@ npm run dev
24
24
  - **🎨 Template Agnostic**: Handlebars, Nunjucks, Pug, Mustache, or custom engines
25
25
  - **📦 Asset Pipeline**: SCSS compilation, JavaScript bundling with esbuild
26
26
  - **🔄 Live Reload**: WebSocket-based live reload during development
27
- - **🗄️ Database Ready**: SQLite integration for server mode applications
28
27
  - **🛣️ Dynamic Routing**: Data-driven page generation and API endpoints
28
+ - **🧩 App Orchestration**: Build and serve external Vite/Webpack/Rollup/esbuild apps via kernel handlers
29
29
  - **🔧 Service Architecture**: Modular, extensible service-oriented design
30
30
 
31
31
  ## 🏗️ Architecture Overview
32
32
 
33
- Clovie uses a **service-oriented architecture** built on `@brickworks/engine`. All functionality is provided by services that extend `ServiceProvider`, orchestrated through dependency injection with reactive state management.
33
+ Clovie uses a **service-oriented architecture** built on `@jucie.io/engine`. All functionality is provided by services that extend `ServiceProvider`, orchestrated through dependency injection with reactive state management.
34
34
 
35
35
  ### Core Services
36
36
 
@@ -276,9 +276,6 @@ export default {
276
276
  }
277
277
  },
278
278
 
279
- // Database configuration (optional)
280
- dbPath: './data/app.db',
281
-
282
279
  // Express middleware (auto-selects Express adapter)
283
280
  middleware: [
284
281
  express.json(),
@@ -401,28 +398,37 @@ curl http://localhost:3000/api/protected/data
401
398
  curl -H "Authorization: Bearer your-token" http://localhost:3000/api/protected/data
402
399
  ```
403
400
 
404
- ### 📊 Database Integration (Server Mode)
401
+ ### 🧩 App Orchestration
402
+
403
+ Clovie can manage multiple frontend apps alongside your core project using kernel-level handlers, so no Express-specific middleware is required. Define apps in `clovie.config.js`, and Clovie will:
405
404
 
406
- Clovie includes built-in SQLite database support for server applications:
405
+ - Detect the build tool (Vite, Webpack, Rollup, esbuild) or use the specified `buildTool`
406
+ - Run builds during `clovie build` and `clovie serve`
407
+ - Launch tool-specific dev middleware during `clovie dev`
408
+ - Mount bundles or dev servers at configurable mount paths (e.g., `/admin`, `/studio`)
407
409
 
408
410
  ```javascript
409
411
  export default {
410
412
  type: 'server',
411
- dbPath: './data/app.db', // SQLite database path
412
-
413
- // Database is available in API actions and routes
414
- api: [{
415
- path: '/api/posts',
416
- method: 'GET',
417
- action: async (state, event) => {
418
- // Access database through state.db
419
- const posts = await state.db.query('SELECT * FROM posts ORDER BY created_at DESC');
420
- return { posts };
413
+ apps: [
414
+ {
415
+ name: 'studio',
416
+ source: './apps/studio',
417
+ buildTool: 'vite',
418
+ buildOptions: {
419
+ watch: true,
420
+ build: { outDir: './apps/studio/dist' }
421
+ },
422
+ dev: {
423
+ mountPath: '/studio'
424
+ }
421
425
  }
422
- }]
426
+ ]
423
427
  };
424
428
  ```
425
429
 
430
+ See [Apps Integration](docs/CONFIGURATION.md#apps-integration) for full examples covering Webpack, Rollup, and esbuild setups.
431
+
426
432
  ### 🔄 Async Data Loading
427
433
 
428
434
  Load data dynamically at build time or runtime:
@@ -596,7 +602,7 @@ my-site/
596
602
  - Validate input data in API actions
597
603
  - Use middleware for authentication and request parsing
598
604
  - Handle errors gracefully in API endpoints
599
- - Implement proper database migrations and seeding
605
+ - Implement proper data migrations and seeding
600
606
 
601
607
  ### 🔧 Configuration Tips
602
608
 
@@ -683,11 +689,6 @@ clovie kill --check # Check port status
683
689
  - Check that template files have correct extensions
684
690
  - Ensure partial files are in the `partials` directory
685
691
 
686
- **Database Connection Issues (Server Mode)**
687
- - Check that `dbPath` in config points to a writable directory
688
- - Ensure SQLite is properly installed
689
- - Verify database initialization in your API actions
690
-
691
692
  **Live Reload Not Working**
692
693
  - Check that you're in development mode (`npm run dev`)
693
694
  - Verify WebSocket connection in browser dev tools
package/bin/cli.js CHANGED
@@ -361,16 +361,6 @@ function setupGracefulShutdown(clovie) {
361
361
  }, 5000); // 5 second timeout
362
362
 
363
363
  try {
364
- // Close database if it exists and is initialized
365
- const database = clovie.database;
366
- if (database && database.isInitialized && database.isInitialized()) {
367
- console.log('💾 Closing database...');
368
- if (typeof database.checkpoint === 'function') {
369
- await database.checkpoint();
370
- console.log('✅ Database written successfully');
371
- }
372
- }
373
-
374
364
  // Stop server if it's running
375
365
  const server = clovie.server;
376
366
  if (server && server.isRunning && server.isRunning()) {
@@ -1,10 +1,4 @@
1
- import { A as AdapterInterface } from "./Server-BR7ZqQBN.js";
2
-
3
- import "./createClovie-LSdi1lXJ.js";
4
-
5
- import "stream";
6
-
7
- import "module";
1
+ import { A as AdapterInterface } from "./createClovie-x0YNcttr.js";
8
2
 
9
3
  import "path";
10
4
 
@@ -26,12 +20,18 @@ import "node:os";
26
20
 
27
21
  import "node:tty";
28
22
 
29
- import "node:http";
23
+ import "fs/promises";
30
24
 
31
25
  import "child_process";
32
26
 
27
+ import "url";
28
+
29
+ import "node:http";
30
+
33
31
  import "util";
34
32
 
33
+ import "socket.io";
34
+
35
35
  class ExpressAdapter extends AdapterInterface {
36
36
  #connections=new Set;
37
37
  constructor(express = null) {
@@ -54,10 +54,15 @@ class ExpressAdapter extends AdapterInterface {
54
54
  throw new Error(`Failed to apply middleware[${index}]: ${error.message}`);
55
55
  }
56
56
  }
57
- this.app.all("*", async (req, res) => {
57
+ }
58
+ registerKernelHandler() {
59
+ this.app && this.app.all("*", async (req, res) => {
58
60
  await this.handleRequest(req, res);
59
61
  });
60
62
  }
63
+ getExpressApp() {
64
+ return this.app;
65
+ }
61
66
  async start({port: port = 3e3, host: host = "0.0.0.0"} = {}) {
62
67
  return new Promise((resolve, reject) => {
63
68
  this.server = this.app.listen(port, host, err => {
@@ -81,7 +86,7 @@ class ExpressAdapter extends AdapterInterface {
81
86
  }
82
87
  }
83
88
  async handleRequest(req, res) {
84
- try {
89
+ if (!res.headersSent) try {
85
90
  const ctx = this.createContext(req, res), response = await this.kernel.handle(ctx);
86
91
  await this.sendResponse(res, response, "HEAD" === req.method);
87
92
  } catch (error) {
@@ -97,4 +102,4 @@ class ExpressAdapter extends AdapterInterface {
97
102
  }
98
103
 
99
104
  export { ExpressAdapter };
100
- //# sourceMappingURL=ExpressAdapter-DL0Y9BG2.js.map
105
+ //# sourceMappingURL=ExpressAdapter-D6owl_CX.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ExpressAdapter-D6owl_CX.js","sources":["../lib/Server/adapters/ExpressAdapter.js"],"sourcesContent":["/**\n * Express adapter for Clovie with full middleware support\n */\nimport { AdapterInterface } from './AdapterInterface.js';\n\nexport class ExpressAdapter extends AdapterInterface {\n #connections = new Set();\n\n constructor(express = null) {\n super('express');\n this.express = express;\n this.app = null;\n }\n\n async initialize(kernel, opts = {}, log = null) {\n await super.initialize(kernel, opts, log);\n \n // Import Express\n if (!this.express) {\n try {\n this.express = await import('express');\n this.express = this.express.default;\n } catch (error) {\n throw new Error('Express not installed. Run: npm install express');\n }\n }\n\n // Create Express app\n this.app = this.express();\n\n // Apply default middleware (can be overridden by user middleware)\n if (!opts.middleware || !this.#hasBodyParser(opts.middleware)) {\n this.app.use(this.express.json());\n this.app.use(this.express.urlencoded({ extended: true }));\n }\n\n // Apply user-defined middleware\n if (opts.middleware && Array.isArray(opts.middleware)) {\n this.log?.info(`Applying ${opts.middleware.length} middleware functions`);\n \n for (const [index, middleware] of opts.middleware.entries()) {\n try {\n this.app.use(middleware);\n this.log?.debug(`Applied middleware ${index + 1}/${opts.middleware.length}`);\n } catch (error) {\n throw new Error(`Failed to apply middleware[${index}]: ${error.message}`);\n }\n }\n }\n\n // Additional middleware will be mounted by the server before kernel handler registration\n }\n\n registerKernelHandler() {\n if (!this.app) {\n return;\n }\n\n this.app.all('*', async (req, res) => {\n await this.handleRequest(req, res);\n });\n }\n\n getExpressApp() {\n return this.app;\n }\n\n async start({ port = 3000, host = '0.0.0.0' } = {}) {\n return new Promise((resolve, reject) => {\n this.server = this.app.listen(port, host, (err) => {\n if (err) {\n reject(err);\n } else {\n // Track connections for clean shutdown\n this.server.on('connection', (conn) => {\n this.#connections.add(conn);\n conn.on('close', () => {\n this.#connections.delete(conn);\n });\n });\n\n this.log?.info(`Express Server with middleware listening on http://${host}:${port}`);\n resolve(this.server);\n }\n });\n });\n }\n\n async stop() {\n if (this.server?.close) {\n // Destroy all active connections\n for (const conn of this.#connections) {\n conn.destroy();\n }\n this.#connections.clear();\n\n return new Promise((resolve) => {\n this.server.close(() => {\n this.log?.info('Express Server stopped');\n resolve();\n });\n });\n }\n }\n\n async handleRequest(req, res) {\n if (res.headersSent) return;\n try {\n // Create context from Express request\n const ctx = this.createContext(req, res);\n \n // Delegate to kernel for route matching and handling\n const response = await this.kernel.handle(ctx);\n \n // Send response using shared method\n await this.sendResponse(res, response, req.method === 'HEAD');\n\n } catch (error) {\n await this.handleError(res, error);\n }\n }\n\n /**\n * Check if middleware array contains body parser\n * @private\n */\n #hasBodyParser(middlewareArray) {\n return middlewareArray.some(mw => {\n // Check for common body parser middleware names\n const name = mw.name?.toLowerCase() || mw.toString().toLowerCase();\n return name.includes('json') || name.includes('urlencoded') || name.includes('bodyparser');\n });\n }\n}\n"],"names":["ExpressAdapter","AdapterInterface","connections","Set","constructor","express","super","this","app","initialize","kernel","opts","log","import","default","error","Error","middleware","hasBodyParser","use","json","urlencoded","extended","Array","isArray","info","length","index","entries","debug","message","registerKernelHandler","all","async","req","res","handleRequest","getExpressApp","start","port","host","Promise","resolve","reject","server","listen","err","on","conn","add","delete","stop","close","destroy","clear","headersSent","ctx","createContext","response","handle","sendResponse","method","handleError","middlewareArray","some","mw","name","toLowerCase","toString","includes"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAKO,MAAMA,uBAAuBC;IAClCC,aAAe,IAAIC;IAEnB,WAAAC,CAAYC,UAAU;QACpBC,MAAM,YACNC,KAAKF,UAAUA,SACfE,KAAKC,MAAM;AACb;IAEA,gBAAMC,CAAWC,QAAQC,OAAO,CAAA,GAAIC,MAAM;QAIxC,UAHMN,MAAMG,WAAWC,QAAQC,MAAMC,OAGhCL,KAAKF,SACR;YACEE,KAAKF,gBAAgBQ,OAAO,YAC5BN,KAAKF,UAAUE,KAAKF,QAAQS;AAC9B,UAAE,OAAOC;YACP,MAAM,IAAIC,MAAM;AAClB;QAaF,IATAT,KAAKC,MAAMD,KAAKF,WAGXM,KAAKM,cAAeV,MAAKW,cAAeP,KAAKM,gBAChDV,KAAKC,IAAIW,IAAIZ,KAAKF,QAAQe;QAC1Bb,KAAKC,IAAIW,IAAIZ,KAAKF,QAAQgB,WAAW;YAAEC,WAAU;cAI/CX,KAAKM,cAAcM,MAAMC,QAAQb,KAAKM,aAAa;YACrDV,KAAKK,KAAKa,KAAK,YAAYd,KAAKM,WAAWS;YAE3C,KAAK,OAAOC,OAAOV,eAAeN,KAAKM,WAAWW,WAChD;gBACErB,KAAKC,IAAIW,IAAIF,aACbV,KAAKK,KAAKiB,MAAM,sBAAsBF,QAAQ,KAAKhB,KAAKM,WAAWS;AACrE,cAAE,OAAOX;gBACP,MAAM,IAAIC,MAAM,8BAA8BW,WAAWZ,MAAMe;AACjE;AAEJ;AAGF;IAEA,qBAAAC;QACOxB,KAAKC,OAIVD,KAAKC,IAAIwB,IAAI,KAAKC,OAAOC,KAAKC;kBACtB5B,KAAK6B,cAAcF,KAAKC;;AAElC;IAEA,aAAAE;QACE,OAAO9B,KAAKC;AACd;IAEA,WAAM8B,EAAMC,MAAEA,OAAO,KAAIC,MAAEA,OAAO,aAAc;QAC9C,OAAO,IAAIC,QAAQ,CAACC,SAASC;YAC3BpC,KAAKqC,SAASrC,KAAKC,IAAIqC,OAAON,MAAMC,MAAOM;gBACrCA,MACFH,OAAOG,QAGPvC,KAAKqC,OAAOG,GAAG,cAAeC;oBAC5BzC,MAAKL,YAAa+C,IAAID,OACtBA,KAAKD,GAAG,SAAS;wBACfxC,MAAKL,YAAagD,OAAOF;;oBAI7BzC,KAAKK,KAAKa,KAAK,sDAAsDe,QAAQD;gBAC7EG,QAAQnC,KAAKqC;;;AAIrB;IAEA,UAAMO;QACJ,IAAI5C,KAAKqC,QAAQQ,OAAO;YAEtB,KAAK,MAAMJ,QAAQzC,MAAKL,aACtB8C,KAAKK;YAIP,OAFA9C,MAAKL,YAAaoD,SAEX,IAAIb,QAASC;gBAClBnC,KAAKqC,OAAOQ,MAAM;oBAChB7C,KAAKK,KAAKa,KAAK,2BACfiB;;;AAGN;AACF;IAEA,mBAAMN,CAAcF,KAAKC;QACvB,KAAIA,IAAIoB,aACR;YAEE,MAAMC,MAAMjD,KAAKkD,cAAcvB,KAAKC,MAG9BuB,iBAAiBnD,KAAKG,OAAOiD,OAAOH;kBAGpCjD,KAAKqD,aAAazB,KAAKuB,UAAyB,WAAfxB,IAAI2B;AAE7C,UAAE,OAAO9C;kBACDR,KAAKuD,YAAY3B,KAAKpB;AAC9B;AACF;IAMA,cAAAG,CAAe6C;QACb,OAAOA,gBAAgBC,KAAKC;YAE1B,MAAMC,OAAOD,GAAGC,MAAMC,iBAAiBF,GAAGG,WAAWD;YACrD,OAAOD,KAAKG,SAAS,WAAWH,KAAKG,SAAS,iBAAiBH,KAAKG,SAAS;;AAEjF;;;"}
@@ -1,13 +1,13 @@
1
1
  "use strict";
2
2
 
3
- var Server = require("./Server-BVelCzau.cjs");
3
+ var createClovie = require("./createClovie-BziskasS.cjs");
4
4
 
5
- require("./createClovie-DdMTZ_dO.cjs"), require("stream"), require("module"), require("path"),
6
- require("crypto"), require("fs"), require("istextorbinary"), require("chokidar"),
5
+ require("path"), require("crypto"), require("fs"), require("istextorbinary"), require("chokidar"),
7
6
  require("readline"), require("events"), require("node:process"), require("node:os"),
8
- require("node:tty"), require("node:http"), require("child_process"), require("util");
7
+ require("node:tty"), require("fs/promises"), require("child_process"), require("url"),
8
+ require("node:http"), require("util"), require("socket.io");
9
9
 
10
- class ExpressAdapter extends Server.AdapterInterface {
10
+ class ExpressAdapter extends createClovie.AdapterInterface {
11
11
  #connections=new Set;
12
12
  constructor(express = null) {
13
13
  super("express"), this.express = express, this.app = null;
@@ -29,10 +29,15 @@ class ExpressAdapter extends Server.AdapterInterface {
29
29
  throw new Error(`Failed to apply middleware[${index}]: ${error.message}`);
30
30
  }
31
31
  }
32
- this.app.all("*", async (req, res) => {
32
+ }
33
+ registerKernelHandler() {
34
+ this.app && this.app.all("*", async (req, res) => {
33
35
  await this.handleRequest(req, res);
34
36
  });
35
37
  }
38
+ getExpressApp() {
39
+ return this.app;
40
+ }
36
41
  async start({port: port = 3e3, host: host = "0.0.0.0"} = {}) {
37
42
  return new Promise((resolve, reject) => {
38
43
  this.server = this.app.listen(port, host, err => {
@@ -56,7 +61,7 @@ class ExpressAdapter extends Server.AdapterInterface {
56
61
  }
57
62
  }
58
63
  async handleRequest(req, res) {
59
- try {
64
+ if (!res.headersSent) try {
60
65
  const ctx = this.createContext(req, res), response = await this.kernel.handle(ctx);
61
66
  await this.sendResponse(res, response, "HEAD" === req.method);
62
67
  } catch (error) {
@@ -72,4 +77,4 @@ class ExpressAdapter extends Server.AdapterInterface {
72
77
  }
73
78
 
74
79
  exports.ExpressAdapter = ExpressAdapter;
75
- //# sourceMappingURL=ExpressAdapter-De7bTuZu.cjs.map
80
+ //# sourceMappingURL=ExpressAdapter-Z_FtN3dq.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ExpressAdapter-Z_FtN3dq.cjs","sources":["../../lib/Server/adapters/ExpressAdapter.js"],"sourcesContent":["/**\n * Express adapter for Clovie with full middleware support\n */\nimport { AdapterInterface } from './AdapterInterface.js';\n\nexport class ExpressAdapter extends AdapterInterface {\n #connections = new Set();\n\n constructor(express = null) {\n super('express');\n this.express = express;\n this.app = null;\n }\n\n async initialize(kernel, opts = {}, log = null) {\n await super.initialize(kernel, opts, log);\n \n // Import Express\n if (!this.express) {\n try {\n this.express = await import('express');\n this.express = this.express.default;\n } catch (error) {\n throw new Error('Express not installed. Run: npm install express');\n }\n }\n\n // Create Express app\n this.app = this.express();\n\n // Apply default middleware (can be overridden by user middleware)\n if (!opts.middleware || !this.#hasBodyParser(opts.middleware)) {\n this.app.use(this.express.json());\n this.app.use(this.express.urlencoded({ extended: true }));\n }\n\n // Apply user-defined middleware\n if (opts.middleware && Array.isArray(opts.middleware)) {\n this.log?.info(`Applying ${opts.middleware.length} middleware functions`);\n \n for (const [index, middleware] of opts.middleware.entries()) {\n try {\n this.app.use(middleware);\n this.log?.debug(`Applied middleware ${index + 1}/${opts.middleware.length}`);\n } catch (error) {\n throw new Error(`Failed to apply middleware[${index}]: ${error.message}`);\n }\n }\n }\n\n // Additional middleware will be mounted by the server before kernel handler registration\n }\n\n registerKernelHandler() {\n if (!this.app) {\n return;\n }\n\n this.app.all('*', async (req, res) => {\n await this.handleRequest(req, res);\n });\n }\n\n getExpressApp() {\n return this.app;\n }\n\n async start({ port = 3000, host = '0.0.0.0' } = {}) {\n return new Promise((resolve, reject) => {\n this.server = this.app.listen(port, host, (err) => {\n if (err) {\n reject(err);\n } else {\n // Track connections for clean shutdown\n this.server.on('connection', (conn) => {\n this.#connections.add(conn);\n conn.on('close', () => {\n this.#connections.delete(conn);\n });\n });\n\n this.log?.info(`Express Server with middleware listening on http://${host}:${port}`);\n resolve(this.server);\n }\n });\n });\n }\n\n async stop() {\n if (this.server?.close) {\n // Destroy all active connections\n for (const conn of this.#connections) {\n conn.destroy();\n }\n this.#connections.clear();\n\n return new Promise((resolve) => {\n this.server.close(() => {\n this.log?.info('Express Server stopped');\n resolve();\n });\n });\n }\n }\n\n async handleRequest(req, res) {\n if (res.headersSent) return;\n try {\n // Create context from Express request\n const ctx = this.createContext(req, res);\n \n // Delegate to kernel for route matching and handling\n const response = await this.kernel.handle(ctx);\n \n // Send response using shared method\n await this.sendResponse(res, response, req.method === 'HEAD');\n\n } catch (error) {\n await this.handleError(res, error);\n }\n }\n\n /**\n * Check if middleware array contains body parser\n * @private\n */\n #hasBodyParser(middlewareArray) {\n return middlewareArray.some(mw => {\n // Check for common body parser middleware names\n const name = mw.name?.toLowerCase() || mw.toString().toLowerCase();\n return name.includes('json') || name.includes('urlencoded') || name.includes('bodyparser');\n });\n }\n}\n"],"names":["ExpressAdapter","AdapterInterface","connections","Set","constructor","express","super","this","app","initialize","kernel","opts","log","import","default","error","Error","middleware","hasBodyParser","use","json","urlencoded","extended","Array","isArray","info","length","index","entries","debug","message","registerKernelHandler","all","async","req","res","handleRequest","getExpressApp","start","port","host","Promise","resolve","reject","server","listen","err","on","conn","add","delete","stop","close","destroy","clear","headersSent","ctx","createContext","response","handle","sendResponse","method","handleError","middlewareArray","some","mw","name","toLowerCase","toString","includes"],"mappings":";;;;;;;;;AAKO,MAAMA,uBAAuBC,aAAAA;IAClCC,aAAe,IAAIC;IAEnB,WAAAC,CAAYC,UAAU;QACpBC,MAAM,YACNC,KAAKF,UAAUA,SACfE,KAAKC,MAAM;AACb;IAEA,gBAAMC,CAAWC,QAAQC,OAAO,CAAA,GAAIC,MAAM;QAIxC,UAHMN,MAAMG,WAAWC,QAAQC,MAAMC,OAGhCL,KAAKF,SACR;YACEE,KAAKF,gBAAgBQ,OAAO,YAC5BN,KAAKF,UAAUE,KAAKF,QAAQS;AAC9B,UAAE,OAAOC;YACP,MAAM,IAAIC,MAAM;AAClB;QAaF,IATAT,KAAKC,MAAMD,KAAKF,WAGXM,KAAKM,cAAeV,MAAKW,cAAeP,KAAKM,gBAChDV,KAAKC,IAAIW,IAAIZ,KAAKF,QAAQe;QAC1Bb,KAAKC,IAAIW,IAAIZ,KAAKF,QAAQgB,WAAW;YAAEC,WAAU;cAI/CX,KAAKM,cAAcM,MAAMC,QAAQb,KAAKM,aAAa;YACrDV,KAAKK,KAAKa,KAAK,YAAYd,KAAKM,WAAWS;YAE3C,KAAK,OAAOC,OAAOV,eAAeN,KAAKM,WAAWW,WAChD;gBACErB,KAAKC,IAAIW,IAAIF,aACbV,KAAKK,KAAKiB,MAAM,sBAAsBF,QAAQ,KAAKhB,KAAKM,WAAWS;AACrE,cAAE,OAAOX;gBACP,MAAM,IAAIC,MAAM,8BAA8BW,WAAWZ,MAAMe;AACjE;AAEJ;AAGF;IAEA,qBAAAC;QACOxB,KAAKC,OAIVD,KAAKC,IAAIwB,IAAI,KAAKC,OAAOC,KAAKC;kBACtB5B,KAAK6B,cAAcF,KAAKC;;AAElC;IAEA,aAAAE;QACE,OAAO9B,KAAKC;AACd;IAEA,WAAM8B,EAAMC,MAAEA,OAAO,KAAIC,MAAEA,OAAO,aAAc;QAC9C,OAAO,IAAIC,QAAQ,CAACC,SAASC;YAC3BpC,KAAKqC,SAASrC,KAAKC,IAAIqC,OAAON,MAAMC,MAAOM;gBACrCA,MACFH,OAAOG,QAGPvC,KAAKqC,OAAOG,GAAG,cAAeC;oBAC5BzC,MAAKL,YAAa+C,IAAID,OACtBA,KAAKD,GAAG,SAAS;wBACfxC,MAAKL,YAAagD,OAAOF;;oBAI7BzC,KAAKK,KAAKa,KAAK,sDAAsDe,QAAQD;gBAC7EG,QAAQnC,KAAKqC;;;AAIrB;IAEA,UAAMO;QACJ,IAAI5C,KAAKqC,QAAQQ,OAAO;YAEtB,KAAK,MAAMJ,QAAQzC,MAAKL,aACtB8C,KAAKK;YAIP,OAFA9C,MAAKL,YAAaoD,SAEX,IAAIb,QAASC;gBAClBnC,KAAKqC,OAAOQ,MAAM;oBAChB7C,KAAKK,KAAKa,KAAK,2BACfiB;;;AAGN;AACF;IAEA,mBAAMN,CAAcF,KAAKC;QACvB,KAAIA,IAAIoB,aACR;YAEE,MAAMC,MAAMjD,KAAKkD,cAAcvB,KAAKC,MAG9BuB,iBAAiBnD,KAAKG,OAAOiD,OAAOH;kBAGpCjD,KAAKqD,aAAazB,KAAKuB,UAAyB,WAAfxB,IAAI2B;AAE7C,UAAE,OAAO9C;kBACDR,KAAKuD,YAAY3B,KAAKpB;AAC9B;AACF;IAMA,cAAAG,CAAe6C;QACb,OAAOA,gBAAgBC,KAAKC;YAE1B,MAAMC,OAAOD,GAAGC,MAAMC,iBAAiBF,GAAGG,WAAWD;YACrD,OAAOD,KAAKG,SAAS,WAAWH,KAAKG,SAAS,iBAAiBH,KAAKG,SAAS;;AAEjF;;;"}