clovie 0.1.17 → 0.1.19
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 +2 -1
- package/bin/cli.js +12 -12
- package/dist/{LiveReload-DVEZWHf3.js → LiveReload-BOp9YYKI.js} +2 -6
- package/dist/{LiveReload-DVEZWHf3.js.map → LiveReload-BOp9YYKI.js.map} +1 -1
- package/dist/{Server-D_nOQX0E.js → Server-KKipH7VZ.js} +2 -6
- package/dist/{Server-D_nOQX0E.js.map → Server-KKipH7VZ.js.map} +1 -1
- package/dist/cjs/{LiveReload-Be6N_lnM.cjs → LiveReload-CcJySo4Z.cjs} +3 -4
- package/dist/cjs/{LiveReload-Be6N_lnM.cjs.map → LiveReload-CcJySo4Z.cjs.map} +1 -1
- package/dist/cjs/{Server-CN4bVO2j.cjs → Server-C1NgJiAD.cjs} +3 -4
- package/dist/cjs/{Server-CN4bVO2j.cjs.map → Server-C1NgJiAD.cjs.map} +1 -1
- package/dist/cjs/{createClovie-CWEt0g2r.cjs → createClovie-CyH1Um6E.cjs} +6 -10
- package/dist/cjs/{createClovie-CWEt0g2r.cjs.map → createClovie-CyH1Um6E.cjs.map} +1 -1
- package/dist/cjs/{index-DLefxiwH.cjs → index-B5xnnUxX.cjs} +4 -4
- package/dist/cjs/{index-DLefxiwH.cjs.map → index-B5xnnUxX.cjs.map} +1 -1
- package/dist/cjs/index.cjs +2 -3
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/{createClovie-B0jNRKtG.js → createClovie-Ce8o-tW3.js} +4 -8
- package/dist/{createClovie-B0jNRKtG.js.map → createClovie-Ce8o-tW3.js.map} +1 -1
- package/dist/{index-CdqSf8xZ.js → index-CbN5E5ow.js} +2 -6
- package/dist/{index-CdqSf8xZ.js.map → index-CbN5E5ow.js.map} +1 -1
- package/dist/index.js +1 -5
- package/dist/index.js.map +1 -1
- package/package.json +2 -1
- package/scripts/build-types.js +247 -0
- package/scripts/killPort.js +138 -0
- package/scripts/publish.js +180 -0
- package/templates/server/README.md +139 -161
- package/templates/server/clovie.config.js +90 -72
- package/templates/server/package.json +4 -4
- package/templates/server/partials/footer.html +1 -1
- package/templates/server/partials/header.html +4 -4
- package/templates/server/views/about.html +7 -7
- package/templates/server/views/index.html +9 -9
- package/templates/server/views/profile.html +36 -0
- package/templates/static/README.md +54 -91
- package/templates/static/clovie.config.js +5 -2
- package/templates/static/package.json +4 -4
- package/templates/static/partials/footer.html +1 -1
- package/templates/static/partials/header.html +4 -3
- package/templates/static/views/about.html +5 -5
- package/templates/static/views/index.html +11 -11
- package/templates/default/README.md +0 -117
- package/templates/default/clovie.config.js +0 -28
- package/templates/default/package.json +0 -12
- package/templates/default/scripts/main.js +0 -1
- package/templates/default/styles/main.scss +0 -11
- package/templates/default/views/index.html +0 -12
package/README.md
CHANGED
|
@@ -465,7 +465,8 @@ Clovie includes powerful CLI tools for development and deployment:
|
|
|
465
465
|
|
|
466
466
|
```bash
|
|
467
467
|
# Project creation
|
|
468
|
-
clovie create <name>
|
|
468
|
+
clovie create <name> # Creates static site (default)
|
|
469
|
+
clovie create <name> --template server # Creates server application
|
|
469
470
|
|
|
470
471
|
# Development
|
|
471
472
|
clovie dev # Start development server with live reload
|
package/bin/cli.js
CHANGED
|
@@ -8,8 +8,8 @@ const __filename = fileURLToPath(import.meta.url);
|
|
|
8
8
|
const __dirname = dirname(__filename);
|
|
9
9
|
|
|
10
10
|
// Local - import from compiled dist for published package
|
|
11
|
-
|
|
12
|
-
import { createClovie } from "../dist/index.js";
|
|
11
|
+
import { createClovie } from "../lib/createClovie.js";
|
|
12
|
+
// import { createClovie } from "../dist/index.js";
|
|
13
13
|
import { killPort, checkPorts, killCommonPorts } from "../scripts/killPort.js";
|
|
14
14
|
|
|
15
15
|
// Check for kill command first (before any argument parsing)
|
|
@@ -109,13 +109,13 @@ if (process.argv.includes('create') && process.argv.length > 2) {
|
|
|
109
109
|
if (!projectName) {
|
|
110
110
|
console.error('Error: Please provide a project name');
|
|
111
111
|
console.error('Usage: clovie create <project-name> [--template <template-type>]');
|
|
112
|
-
console.error('Available templates: default,
|
|
112
|
+
console.error('Available templates: static (default), server');
|
|
113
113
|
process.exit(1);
|
|
114
114
|
}
|
|
115
115
|
|
|
116
116
|
// Parse arguments to get template option
|
|
117
117
|
const createArgs = process.argv.slice(createArgIndex + 2);
|
|
118
|
-
let templateType = '
|
|
118
|
+
let templateType = 'static'; // Default to static template
|
|
119
119
|
|
|
120
120
|
// Look for --template or -t flag
|
|
121
121
|
const templateIndex = createArgs.findIndex(arg => arg === '--template' || arg === '-t');
|
|
@@ -124,7 +124,7 @@ if (process.argv.includes('create') && process.argv.length > 2) {
|
|
|
124
124
|
}
|
|
125
125
|
|
|
126
126
|
// Validate template type
|
|
127
|
-
const validTemplates = ['
|
|
127
|
+
const validTemplates = ['static', 'server'];
|
|
128
128
|
if (!validTemplates.includes(templateType)) {
|
|
129
129
|
console.error(`Error: Invalid template type '${templateType}'`);
|
|
130
130
|
console.error(`Available templates: ${validTemplates.join(', ')}`);
|
|
@@ -173,7 +173,7 @@ if (process.argv.includes('create') && process.argv.length > 2) {
|
|
|
173
173
|
}
|
|
174
174
|
|
|
175
175
|
await copyDir(templateDir, projectPath);
|
|
176
|
-
console.log(`✅ Clovie
|
|
176
|
+
console.log(`✅ Clovie project created successfully!`);
|
|
177
177
|
console.log(`📁 Project location: ${projectPath}`);
|
|
178
178
|
console.log(`🎨 Template: ${templateType}`);
|
|
179
179
|
console.log('\nNext steps:');
|
|
@@ -184,13 +184,13 @@ if (process.argv.includes('create') && process.argv.length > 2) {
|
|
|
184
184
|
// Show template-specific next steps
|
|
185
185
|
if (templateType === 'server') {
|
|
186
186
|
console.log('\n🌐 Server template features:');
|
|
187
|
-
console.log(' • API endpoints
|
|
188
|
-
console.log(' • Dynamic
|
|
189
|
-
console.log(' •
|
|
190
|
-
console.log(' • Use "npm
|
|
187
|
+
console.log(' • API endpoints with collection-based database');
|
|
188
|
+
console.log(' • Dynamic routes with server-side rendering');
|
|
189
|
+
console.log(' • Native Node.js HTTP server (Express adapter available)');
|
|
190
|
+
console.log(' • Use "npm start" for production server');
|
|
191
191
|
} else if (templateType === 'static') {
|
|
192
|
-
console.log('\n📄 Static
|
|
193
|
-
console.log(' • SEO optimized pages');
|
|
192
|
+
console.log('\n📄 Static site features:');
|
|
193
|
+
console.log(' • SEO optimized pages with semantic HTML');
|
|
194
194
|
console.log(' • Modern responsive design');
|
|
195
195
|
console.log(' • Ready for JAMstack deployment');
|
|
196
196
|
console.log(' • Use "npm run build" to generate static files');
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Server } from "socket.io";
|
|
2
2
|
|
|
3
|
-
import { S as ServiceProvider, q as queueMacrotask } from "./createClovie-
|
|
3
|
+
import { S as ServiceProvider, q as queueMacrotask } from "./createClovie-Ce8o-tW3.js";
|
|
4
4
|
|
|
5
5
|
import "stream";
|
|
6
6
|
|
|
@@ -26,10 +26,6 @@ import "node:os";
|
|
|
26
26
|
|
|
27
27
|
import "node:tty";
|
|
28
28
|
|
|
29
|
-
import "node:path";
|
|
30
|
-
|
|
31
|
-
import "node:fs";
|
|
32
|
-
|
|
33
29
|
class LiveReload extends ServiceProvider {
|
|
34
30
|
static manifest={
|
|
35
31
|
name: "Clovie LiveReload",
|
|
@@ -96,4 +92,4 @@ class LiveReload extends ServiceProvider {
|
|
|
96
92
|
}
|
|
97
93
|
|
|
98
94
|
export { LiveReload };
|
|
99
|
-
//# sourceMappingURL=LiveReload-
|
|
95
|
+
//# sourceMappingURL=LiveReload-BOp9YYKI.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LiveReload-
|
|
1
|
+
{"version":3,"file":"LiveReload-BOp9YYKI.js","sources":["../lib/LiveReload.js"],"sourcesContent":["import { Server as SocketIOServer } from 'socket.io';\nimport { ServiceProvider } from '@brickworks/engine';\nimport { queueMacrotask } from './utils/tasks.js';\n\nexport class LiveReload extends ServiceProvider {\n static manifest = {\n name: 'Clovie LiveReload',\n namespace: 'liveReload',\n version: '1.0.0',\n };\n\n #io;\n #reloading = false;\n\n getter () {\n return {\n io: () => this.#io,\n }\n }\n\n actions() {\n return {\n initializeServer: async (server, opts) => {\n const log = this.useContext('log');\n if (opts.mode === 'development') {\n await this.#setupSocketIO(server, log);\n }\n },\n notifyReload: () => {\n if (this.#reloading) return;\n this.#reloading = true;\n \n queueMacrotask(() => {\n this.#reloading = false;\n if (this.#io) {\n this.#io.emit('reload')\n }\n });\n },\n injectLiveReloadScript: async (renderedContent, opts) => {\n const lastBodyIndex = renderedContent.lastIndexOf('</body>');\n if (lastBodyIndex !== -1) {\n const scriptConfig = { \n mode: opts.mode || 'development', \n port: opts.port || 3000 \n };\n \n try {\n // Import live reload script dynamically \n renderedContent = renderedContent.substring(0, lastBodyIndex) + \n this.#liveReloadScript(scriptConfig) + '\\n' + \n renderedContent.substring(lastBodyIndex);\n } catch (err) {\n console.warn('⚠️ Could not load live reload script:', err.message);\n }\n }\n return renderedContent;\n }\n }\n }\n\n async #setupSocketIO(server, log) {\n try {\n // Wait a bit for server to be fully initialized\n await new Promise(resolve => setTimeout(resolve, 100));\n\n log.debug('Setting up Socket.IO...');\n \n // Configure Socket.IO with proper CORS and options\n this.#io = new SocketIOServer(server, {\n cors: {\n origin: \"*\",\n methods: [\"GET\", \"POST\"]\n },\n transports: ['polling', 'websocket'],\n allowEIO3: true\n });\n\n this.#io.on('connection', (socket) => {\n log.debug(`Client connected: ${socket.id}`);\n \n socket.on('disconnect', (reason) => {\n log.debug(`Client disconnected: ${socket.id} - ${reason}`);\n });\n \n socket.on('error', (error) => {\n log.error('Socket error:', error);\n });\n });\n\n log.info('Socket.IO server ready');\n } catch (error) {\n log.error('Error setting up Socket.IO:', error);\n }\n }\n\n #liveReloadScript = (opts) => `<!-- Live Reload Script (Development Mode Only) -->\n<script src=\"https://cdn.socket.io/4.7.4/socket.io.min.js\"></script>\n<script>\n (function() {\n const opts = ${JSON.stringify(opts)};\n \n console.log('Initializing live reload with opts:', opts);\n \n // Configure Socket.IO client with proper options\n const socket = io({\n transports: ['polling', 'websocket'],\n timeout: 20000,\n forceNew: true\n });\n \n socket.on('reload', () => {\n console.log('Live reload triggered');\n window.location.reload();\n });\n \n socket.on('connect', () => {\n console.log('Connected to live reload server');\n });\n \n socket.on('disconnect', (reason) => {\n console.log('Disconnected from live reload server:', reason);\n });\n \n socket.on('connect_error', (error) => {\n console.error('Connection error:', error);\n console.log('Retrying connection in 3 seconds...');\n setTimeout(() => {\n socket.connect();\n }, 3000);\n });\n \n socket.on('error', (error) => {\n console.error('Socket error:', error);\n });\n \n // Add connection timeout\n setTimeout(() => {\n if (!socket.connected) {\n console.warn('Live reload connection timeout - server may not be running');\n }\n }, 5000);\n })();\n</script>`;\n}"],"names":["LiveReload","ServiceProvider","static","name","namespace","version","io","reloading","getter","this","actions","initializeServer","async","server","opts","log","useContext","mode","setupSocketIO","notifyReload","queueMacrotask","emit","injectLiveReloadScript","renderedContent","lastBodyIndex","lastIndexOf","scriptConfig","port","substring","liveReloadScript","err","console","warn","message","Promise","resolve","setTimeout","debug","SocketIOServer","cors","origin","methods","transports","allowEIO3","on","socket","id","reason","error","info","JSON","stringify"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAIO,MAAMA,mBAAmBC;IAC9BC,gBAAkB;QAChBC,MAAM;QACNC,WAAW;QACXC,SAAS;;IAGXC;IACAC,YAAa;IAEb,MAAAC;QACE,OAAO;YACLF,IAAI,MAAMG,MAAKH;;AAEnB;IAEA,OAAAI;QACE,OAAO;YACLC,kBAAkBC,OAAOC,QAAQC;gBAC/B,MAAMC,MAAMN,KAAKO,WAAW;gBACV,kBAAdF,KAAKG,cACDR,MAAKS,cAAeL,QAAQE;;YAGtCI,cAAc;gBACRV,MAAKF,cACTE,MAAKF,aAAa,GAElBa,eAAe;oBACbX,MAAKF,aAAa,GACdE,MAAKH,MACPG,MAAKH,GAAIe,KAAK;;;YAIpBC,wBAAwBV,OAAOW,iBAAiBT;gBAC9C,MAAMU,gBAAgBD,gBAAgBE,YAAY;gBAClD,KAAsB,MAAlBD,eAAsB;oBACxB,MAAME,eAAe;wBACnBT,MAAMH,KAAKG,QAAQ;wBACnBU,MAAMb,KAAKa,QAAQ;;oBAGrB;wBAEEJ,kBAAkBA,gBAAgBK,UAAU,GAAGJ,iBAC/Bf,MAAKoB,iBAAkBH,gBAAgB,OACvCH,gBAAgBK,UAAUJ;AAC5C,sBAAE,OAAOM;wBACPC,QAAQC,KAAK,0CAA0CF,IAAIG;AAC7D;AACF;gBACA,OAAOV;;;AAGb;IAEA,oBAAML,CAAeL,QAAQE;QAC3B;kBAEQ,IAAImB,QAAQC,WAAWC,WAAWD,SAAS,OAEjDpB,IAAIsB,MAAM;YAGV5B,MAAKH,KAAM,IAAIgC,OAAezB,QAAQ;gBACpC0B,MAAM;oBACJC,QAAQ;oBACRC,SAAS,EAAC,OAAO;;gBAEnBC,YAAY,EAAC,WAAW;gBACxBC,YAAW;gBAGblC,MAAKH,GAAIsC,GAAG,cAAeC;gBACzB9B,IAAIsB,MAAM,qBAAqBQ,OAAOC,OAEtCD,OAAOD,GAAG,cAAeG;oBACvBhC,IAAIsB,MAAM,wBAAwBQ,OAAOC,QAAQC;oBAGnDF,OAAOD,GAAG,SAAUI;oBAClBjC,IAAIiC,MAAM,iBAAiBA;;gBAI/BjC,IAAIkC,KAAK;AACX,UAAE,OAAOD;YACPjC,IAAIiC,MAAM,+BAA+BA;AAC3C;AACF;IAEAnB,kBAAqBf,QAAS,iLAIboC,KAAKC,UAAUrC;;;"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { c as compileRoute, a as chalk, S as ServiceProvider } from "./createClovie-
|
|
1
|
+
import { c as compileRoute, a as chalk, S as ServiceProvider } from "./createClovie-Ce8o-tW3.js";
|
|
2
2
|
|
|
3
3
|
import http from "node:http";
|
|
4
4
|
|
|
@@ -30,10 +30,6 @@ import "node:os";
|
|
|
30
30
|
|
|
31
31
|
import "node:tty";
|
|
32
32
|
|
|
33
|
-
import "node:path";
|
|
34
|
-
|
|
35
|
-
import "node:fs";
|
|
36
|
-
|
|
37
33
|
class Kernel {
|
|
38
34
|
#routes=[];
|
|
39
35
|
#hooks={
|
|
@@ -527,4 +523,4 @@ class Server extends ServiceProvider {
|
|
|
527
523
|
}
|
|
528
524
|
|
|
529
525
|
export { Server };
|
|
530
|
-
//# sourceMappingURL=Server-
|
|
526
|
+
//# sourceMappingURL=Server-KKipH7VZ.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Server-D_nOQX0E.js","sources":["../lib/Server/Kernel.js","../lib/Server/utils/httpParsing.js","../lib/Server/adapters/AdapterInterface.js","../lib/Server/adapters/HttpAdapter.js","../lib/Server/utils/serverReady.js","../lib/Server/Server.js"],"sourcesContent":["import { compileRoute } from './utils/routeMatch.js';\n\n/**\n * Kernel handles route registration and matching\n * Separates routing logic from HTTP protocol handling\n */\nexport class Kernel {\n #routes = []; // { method, path, match, handler, mode, revalidate, ... }\n #hooks = { \n onRequest: null, \n preHandler: null, \n onSend: null, \n onError: null \n };\n #staticFallback = null;\n\n constructor() { \n }\n\n /**\n * Register multiple routes at once\n * @param {Array} rawRoutes - Array of route objects\n */\n registerRoutes(rawRoutes) {\n for (const r of rawRoutes) {\n this.registerRoute(r);\n }\n }\n\n /**\n * Register a single route\n * @param {Object} route - Route object with method, path, handler, etc.\n */\n registerRoute(route) {\n const compiledRoute = {\n ...route,\n match: compileRoute(route.path)\n };\n this.#routes.push(compiledRoute);\n }\n\n /**\n * Configure hooks\n * @param {Object} hooks - Hook functions\n */\n hooks(h) { \n Object.assign(this.#hooks, h); \n }\n\n /**\n * Set static file fallback handler\n * @param {string} outputDir - Directory to serve static files from\n * @param {Function} handler - Static file handler function\n */\n setStaticFallback(outputDir, handler) {\n this.#staticFallback = { outputDir, handler };\n }\n\n /**\n * Handle a request through the routing system\n * @param {Object} ctx - Request context\n * @returns {Object} Response object\n */\n async handle(ctx) {\n let response;\n try {\n // onRequest can short-circuit\n const onReqOut = await this.#hooks.onRequest?.(ctx);\n if (onReqOut) { response = onReqOut; return response; }\n\n // route match …\n let matchParams = null;\n const route = this.#routes.find(r => {\n if (r.method !== ctx.req.method) return false;\n const m = r.match(ctx.req.path);\n if (m) { matchParams = m; return true; }\n return false;\n });\n\n if (!route) {\n if (this.#staticFallback) {\n const staticResponse = await this.#staticFallback.handler(ctx, this.#staticFallback.outputDir);\n response = (staticResponse && staticResponse.status !== 404)\n ? staticResponse\n : ctx.respond.text('Not Found', 404);\n } else {\n response = ctx.respond.text('Not Found', 404);\n }\n return response;\n }\n\n ctx.req.params = matchParams || {};\n\n // preHandler can short-circuit\n const preOut = await this.#hooks.preHandler?.(ctx, route);\n if (preOut) { response = preOut; return response; }\n\n // route handler\n response = await route.handler(ctx);\n\n } catch (err) {\n response = (await this.#hooks.onError?.(ctx, err))\n ?? ctx.respond.text('Internal Server Error', 500);\n } finally {\n await this.#hooks.onSend?.(ctx, response);\n }\n return response ?? ctx.respond.text('', 204);\n}\n\n\n /**\n * Get all registered routes\n * @returns {Array} Array of registered routes\n */\n getRoutes() {\n return this.#routes.map(route => ({\n method: route.method,\n path: route.path,\n params: route.params || [],\n compiled: true\n }));\n }\n}\n","/**\n * HTTP parsing utilities for request body and query parameters\n */\n\n/**\n * Parse request body based on content type\n * @param {Object} req - Node.js request object\n * @returns {Object|null} Parsed body object or null\n */\nexport async function parseBody(req) {\n return new Promise((resolve) => {\n if (req.method === 'GET' || req.method === 'HEAD') {\n resolve(null);\n return;\n }\n\n const contentType = req.headers['content-type'] || '';\n let body = '';\n\n req.on('data', chunk => {\n body += chunk.toString();\n });\n\n req.on('end', () => {\n try {\n if (contentType.includes('application/json')) {\n resolve(body ? JSON.parse(body) : {});\n } else if (contentType.includes('application/x-www-form-urlencoded')) {\n resolve(parseUrlEncoded(body));\n } else if (contentType.includes('multipart/form-data')) {\n // For now, just return the raw body for multipart\n // Could be enhanced with proper multipart parsing\n resolve({ raw: body });\n } else {\n resolve(body || null);\n }\n } catch (error) {\n resolve(null);\n }\n });\n\n req.on('error', () => {\n resolve(null);\n });\n });\n}\n\n/**\n * Parse URL-encoded form data\n * @param {string} data - URL-encoded string\n * @returns {Object} Parsed object\n */\nfunction parseUrlEncoded(data) {\n const result = {};\n const pairs = data.split('&');\n \n for (const pair of pairs) {\n const [key, value] = pair.split('=');\n if (key) {\n const decodedKey = decodeURIComponent(key);\n const decodedValue = value ? decodeURIComponent(value) : '';\n \n // Handle arrays (key[] or key[0])\n if (decodedKey.endsWith('[]')) {\n const arrayKey = decodedKey.slice(0, -2);\n if (!result[arrayKey]) result[arrayKey] = [];\n result[arrayKey].push(decodedValue);\n } else {\n result[decodedKey] = decodedValue;\n }\n }\n }\n \n return result;\n}\n\n/**\n * Parse query parameters from URLSearchParams\n * @param {URLSearchParams} searchParams - URL search parameters\n * @returns {Object} Parsed query object with support for arrays\n */\nexport function parseQuery(searchParams) {\n const result = {};\n \n for (const [key, value] of searchParams.entries()) {\n // Handle array parameters (key[] or key[0])\n if (key.endsWith('[]') || /\\[\\d*\\]$/.test(key)) {\n const arrayKey = key.replace(/\\[\\d*\\]$/, '').replace('[]', '');\n if (!result[arrayKey]) result[arrayKey] = [];\n result[arrayKey].push(value);\n } else {\n result[key] = value;\n }\n }\n \n return result;\n}\n","/**\n * Clovie Adapter Interface\n * \n * This defines the contract that all HTTP server adapters must implement.\n * The Clovie kernel uses this interface to delegate HTTP handling to\n * any compatible adapter (Express, Fastify, Node HTTP, etc.)\n */\nimport { parseQuery } from '../utils/httpParsing.js';\n\n/**\n * Adapter Interface - All adapters must implement this\n */\nexport class AdapterInterface {\n static create(name) {\n return new this(name);\n }\n\n constructor(name) {\n this.name = name;\n this.server = null;\n this.kernel = null;\n this.log = null;\n this.hooks = null;\n }\n\n /**\n * Initialize the adapter with kernel and context\n * @param {Object} kernel - Clovie kernel instance\n * @param {Object} log - Clovie logger\n */\n async initialize(kernel, log) {\n this.kernel = kernel;\n this.log = log;\n }\n\n /**\n * Start the HTTP server\n * @param {Object} options - Server options (port, host, etc.)\n * @returns {Promise<Object>} - Server instance\n */\n async start(options) {\n throw new Error(`start() must be implemented by ${this.name} adapter`);\n }\n\n /**\n * Stop the HTTP server\n * @returns {Promise<void>}\n */\n async stop() {\n throw new Error(`stop() must be implemented by ${this.name} adapter`);\n }\n\n /**\n * Get the underlying HTTP server instance\n * Used by services like LiveReload for Socket.IO integration\n * @returns {Object|null} - HTTP server instance\n */\n getHttpServer() {\n return this.server;\n }\n\n /**\n * Check if the server is currently running\n * @returns {boolean}\n */\n isRunning() {\n return this.server !== null;\n }\n\n /**\n * Handle a request through the adapter\n * @param {Object} req - HTTP request\n * @param {Object} res - HTTP response\n * @returns {Promise<void>}\n */\n async handleRequest(req, res) {\n throw new Error(`handleRequest() must be implemented by ${this.name} adapter`);\n }\n\n /**\n * Create standardized context object from request\n * @param {Object} req - HTTP request\n * @param {Object} res - HTTP response\n * @returns {Object} - Standardized context object\n */\n createContext(req, res) {\n const url = new URL(req.url || req.originalUrl, `http://${req.headers.host}`);\n\n return {\n req: {\n method: req.method,\n url: url.toString(),\n path: url.pathname,\n headers: Object.fromEntries(\n Object.entries(req.headers).map(([k, v]) => [k.toLowerCase(), v])\n ),\n query: req.query || parseQuery(url.searchParams),\n body: req.body || null,\n raw: { req, res },\n params: {}\n },\n res,\n respond: new RespondHelpers()\n };\n }\n\n /**\n * Send response using standardized response format\n * @param {Object} res - HTTP response\n * @param {Object} response - Response object from route handler\n * @param {boolean} isHead - Whether this is a HEAD request\n * @returns {Promise<void>}\n */\n async sendResponse(res, response, isHead = false) {\n // Default to 204 if no response object was returned\n const resp = response ?? { type: 'text', status: 204, headers: {}, body: '' };\n\n if (res.headersSent) return; // defensive guard\n\n // Set status and headers (normalize keys)\n res.statusCode = resp.status ?? 200;\n if (resp.headers) {\n for (const [k, v] of Object.entries(resp.headers)) {\n res.setHeader(k.toLowerCase(), v);\n }\n }\n\n // Respect HEAD requests: send headers only\n if (isHead) {\n return res.end();\n }\n\n switch (resp.type) {\n case 'json': {\n if (!res.getHeader('content-type')) {\n res.setHeader('content-type', 'application/json; charset=utf-8');\n }\n return res.end(JSON.stringify(resp.body));\n }\n\n case 'text': {\n if (!res.getHeader('content-type')) {\n res.setHeader('content-type', 'text/plain; charset=utf-8');\n }\n return res.end(resp.body ?? '');\n }\n\n case 'html': {\n if (!res.getHeader('content-type')) {\n res.setHeader('content-type', 'text/html; charset=utf-8');\n }\n return res.end(resp.body ?? '');\n }\n\n case 'file': {\n return await this.serveFile(res, resp.path);\n }\n\n case 'stream': {\n const b = resp.body;\n if (!b) return res.end();\n // Node stream\n if (typeof b.pipe === 'function') return b.pipe(res);\n // AsyncIterable\n if (Symbol.asyncIterator in Object(b)) {\n for await (const chunk of b) {\n if (!res.write(chunk)) {\n await new Promise(r => res.once('drain', r));\n }\n }\n return res.end();\n }\n // Fallback\n return res.end(b);\n }\n\n default:\n return res.end('');\n }\n }\n\n /**\n * Serve static files with proper MIME types and streaming\n * @param {Object} res - HTTP response\n * @param {string} filePath - Path to file to serve\n * @returns {Promise<void>}\n */\n async serveFile(res, filePath) {\n const fs = await import('node:fs');\n const fsp = await import('node:fs/promises');\n const path = await import('node:path');\n const { pipeline } = await import('node:stream');\n const { promisify } = await import('node:util');\n \n const pipelineAsync = promisify(pipeline);\n\n const MIME = {\n '.html': 'text/html; charset=utf-8',\n '.css': 'text/css; charset=utf-8',\n '.js': 'application/javascript; charset=utf-8',\n '.mjs': 'application/javascript; charset=utf-8',\n '.json': 'application/json; charset=utf-8',\n '.svg': 'image/svg+xml',\n '.png': 'image/png',\n '.jpg': 'image/jpeg',\n '.jpeg': 'image/jpeg',\n '.gif': 'image/gif',\n '.ico': 'image/x-icon',\n '.woff': 'font/woff',\n '.woff2': 'font/woff2',\n '.ttf': 'font/ttf',\n '.eot': 'application/vnd.ms-fontobject'\n };\n\n try {\n const st = await fsp.stat(filePath);\n if (!st.isFile()) {\n res.statusCode = 404;\n res.setHeader('content-type', 'text/plain; charset=utf-8');\n return res.end('Not Found');\n }\n\n const ext = path.extname(filePath).toLowerCase();\n if (!res.getHeader('content-type')) {\n res.setHeader('content-type', MIME[ext] ?? 'application/octet-stream');\n }\n res.setHeader('content-length', String(st.size));\n\n const rs = fs.createReadStream(filePath);\n rs.on('error', () => {\n if (!res.headersSent) res.statusCode = 404;\n res.end('Not Found');\n });\n await pipelineAsync(rs, res); // backpressure-aware piping\n } catch {\n if (!res.headersSent) {\n res.statusCode = 404;\n res.setHeader('content-type', 'text/plain; charset=utf-8');\n }\n res.end('Not Found');\n }\n }\n\n /**\n * Handle request errors consistently\n * @param {Object} res - HTTP response\n * @param {Error} error - Error that occurred\n * @returns {Promise<void>}\n */\n async handleError(res, error) {\n this.log?.error?.('Request handling error:', error);\n if (!res.headersSent) {\n res.statusCode = 500;\n res.setHeader('content-type', 'text/plain; charset=utf-8');\n res.end('Internal Server Error');\n }\n }\n}\n\n/**\n * Route object structure that adapters receive from Clovie kernel\n */\nexport class ClovieRoute {\n constructor(method, path, handler, options = {}) {\n this.method = method.toUpperCase();\n this.path = path;\n this.handler = handler;\n this.options = options;\n this.params = options.params || [];\n }\n}\n\n/**\n * Hook object structure for lifecycle management\n */\nexport class ClovieHooks {\n constructor() {\n this.onRequest = null;\n this.preHandler = null;\n this.onSend = null;\n this.onError = null;\n }\n}\n\n/**\n * Context object passed to route handlers\n */\nexport class ClovieContext {\n constructor(req, res, state, stable) {\n this.req = req;\n this.res = res;\n this.state = state;\n this.stable = stable;\n this.respond = new RespondHelpers();\n }\n}\n\n/**\n * Response helpers for route handlers\n */\nexport class RespondHelpers {\n json(data, status = 200, headers = {}) {\n return { type: 'json', status, headers, body: data };\n }\n\n text(data, status = 200, headers = {}) {\n return { type: 'text', status, headers, body: data };\n }\n\n html(data, status = 200, headers = {}) {\n return { type: 'html', status, headers, body: data };\n }\n\n file(path, status = 200, headers = {}) {\n return { type: 'file', status, headers, path };\n }\n\n stream(body, status = 200, headers = {}) {\n return { type: 'stream', status, headers, body };\n }\n\n redirect(location, status = 302, headers = {}) {\n return { type:'text', status, headers: { ...headers, location }, body: '' };\n }\n}\n","/**\n * HTTP Adapter for Node.js native HTTP server\n * Thin I/O shim: normalize req/res, call kernel, send response\n */\nimport http from 'node:http';\nimport { AdapterInterface } from './AdapterInterface.js';\nimport { parseBody } from '../utils/httpParsing.js';\n\nexport class HttpAdapter extends AdapterInterface {\n #connections = new Set();\n\n constructor() {\n super('http');\n }\n\n async initialize(kernel, services, log) {\n await super.initialize(kernel, services, log);\n }\n\n async start({ port = 3000, host = '0.0.0.0' } = {}) {\n this.server = http.createServer(async (req, res) => {\n try {\n // Parse body for HTTP adapter (Express handles this differently)\n if (!req.body) {\n req.body = await parseBody(req);\n }\n\n const ctx = this.createContext(req, res);\n const out = await this.kernel.handle(ctx);\n await this.sendResponse(res, out, req.method === 'HEAD');\n } catch (error) {\n await this.handleError(res, error);\n }\n });\n\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 await new Promise((resolve, reject) =>\n this.server.listen(port, host, err => (err ? reject(err) : resolve()))\n );\n\n this.log?.info?.(`HTTP Server listening on http://${host}:${port}`);\n return this.server;\n }\n\n async stop() {\n if (this.server) {\n // Destroy all active connections\n for (const conn of this.#connections) {\n conn.destroy();\n }\n this.#connections.clear();\n\n // Close the server\n await new Promise(resolve => this.server.close(() => resolve()));\n this.server = null;\n }\n }\n\n}\n","import chalk from 'chalk';\nimport { exec } from 'child_process';\nimport { promisify } from 'util';\n\nconst execAsync = promisify(exec);\n\n/**\n * Display a pretty server ready message with clickable URL\n * @param {object} options - Server options\n * @param {number} options.port - Server port\n * @param {string} options.host - Server host\n * @param {string} options.mode - Server mode (development/production)\n * @param {object} logger - Logger instance\n */\nexport async function displayServerReady({ port, host, mode }, logger) {\n const protocol = mode === 'development' ? 'http' : 'https';\n const url = `${protocol}://${host === '0.0.0.0' ? 'localhost' : host}:${port}`;\n \n // Create a nice banner\n const banner = [\n '',\n chalk.bold.blue('╔══════════════════════════════════════════════════════════════╗'),\n chalk.bold.blue('║') + chalk.bold.white(' 🚀 Clovie Server Ready! 🚀 ') + chalk.bold.blue('║'),\n chalk.bold.blue('╠══════════════════════════════════════════════════════════════╣'),\n chalk.bold.blue('║') + chalk.white(` Mode: ${chalk.green(mode.toUpperCase())} `) + chalk.bold.blue('║'),\n chalk.bold.blue('║') + chalk.white(` URL: ${chalk.cyan.underline(url)} `) + chalk.bold.blue('║'),\n chalk.bold.blue('║') + chalk.white(` Host: ${chalk.yellow(host)}:${chalk.yellow(port)} `) + chalk.bold.blue('║'),\n chalk.bold.blue('╚══════════════════════════════════════════════════════════════╝'),\n ''\n ];\n\n // Display the banner\n banner.forEach(line => logger.info(line));\n\n // Try to open browser automatically in development mode\n if (mode === 'development') {\n try {\n await openBrowser(url);\n logger.info(chalk.green('🌐 Browser opened automatically'));\n } catch (error) {\n logger.debug('Could not open browser automatically:', error.message);\n }\n }\n\n // Display helpful commands\n const commands = [\n '',\n chalk.gray('💡 Quick Commands:'),\n chalk.gray(` • Press ${chalk.yellow('Ctrl+C')} to stop the server`),\n chalk.gray(` • Visit ${chalk.cyan(url)} to view your site`),\n chalk.gray(` • Check the console for live reload updates`),\n ''\n ];\n\n commands.forEach(line => logger.info(line));\n}\n\n/**\n * Open browser with the given URL\n * @param {string} url - URL to open\n */\nasync function openBrowser(url) {\n const platform = process.platform;\n let command;\n\n switch (platform) {\n case 'darwin': // macOS\n command = `open \"${url}\"`;\n break;\n case 'win32': // Windows\n command = `start \"${url}\"`;\n break;\n default: // Linux and others\n command = `xdg-open \"${url}\"`;\n break;\n }\n\n try {\n await execAsync(command);\n } catch (error) {\n throw new Error(`Failed to open browser: ${error.message}`);\n }\n}","import { ServiceProvider } from '@brickworks/engine';\nimport { Kernel } from './Kernel.js';\nimport { HttpAdapter } from './adapters/HttpAdapter.js';\nimport { displayServerReady } from './utils/serverReady.js';\n\nexport class Server extends ServiceProvider {\n static manifest = {\n name: 'Clovie Server',\n namespace: 'server',\n version: '1.0.0'\n };\n\n #routes = [];\n #adapter = null;\n #hooks = {\n onRequest: null,\n preHandler: null,\n onSend: null,\n onError: null\n };\n\n actions(useContext) { \n return {\n // Add a route\n add: (method, path, handler, meta = {}) => {\n this.#routes.push({\n method: method.toUpperCase(),\n path,\n handler,\n meta\n });\n },\n\n // Set server adapter\n useAdapter: (adapter) => {\n this.#adapter = adapter;\n return this;\n },\n\n // Configure hooks\n hooks: (hooks) => {\n this.#hooks = { ...this.#hooks, ...hooks };\n return this;\n },\n\n // Start listening server\n listen: async (opts = {}) => {\n const relay = useContext('relay');\n const port = opts.port || opts || 3000;\n const host = opts.host || '0.0.0.0';\n const log = useContext('log');\n \n // Create kernel with services\n const kernel = new Kernel({\n state: useContext('state'),\n stable: useContext('stable'),\n // Add other services as needed for ISR/static/SSR\n });\n\n // Configure kernel hooks\n kernel.hooks(this.#hooks);\n\n // 1) Register app routes first\n kernel.registerRoutes(this.#routes);\n\n // 2) Add system routes (won't shadow user routes)\n kernel.registerRoutes([\n {\n method: 'GET',\n path: '/health',\n handler: (ctx) => ctx.respond.json({\n status: 'ok',\n timestamp: new Date().toISOString(),\n mode: opts.mode || 'production'\n })\n },\n {\n method: 'GET',\n path: '/api/info',\n handler: (ctx) => ctx.respond.json({\n name: 'Clovie',\n version: '1.0.0',\n mode: opts.mode || 'production',\n routes: this.#routes.length\n })\n }\n ]);\n\n // 3) Configure static file serving as 404 fallback\n if (opts.outputDir) {\n kernel.setStaticFallback(opts.outputDir, (ctx, outputDir) => {\n return this.#serveStaticFile(ctx, outputDir);\n });\n }\n\n // 4) Boot adapter\n this.#adapter = this.#adapter ?? HttpAdapter.create();\n await this.#adapter.initialize(kernel, log);\n \n // Start the server and return the instance\n const server = await this.#adapter.start({ port, host });\n \n // Check for LiveReload service and initialize it if available\n try {\n const liveReload = useContext('liveReload');\n log.debug(`LiveReload service found: ${!!liveReload}, mode: ${opts.mode}`);\n if (liveReload && opts.mode === 'development') {\n log.info('Initializing LiveReload...');\n await liveReload.initializeServer(server, opts);\n log.info('LiveReload initialized successfully');\n }\n } catch (error) {\n log.debug('LiveReload not available:', error.message);\n }\n \n // Display pretty server ready message\n const actualPort = server.address()?.port || port;\n await displayServerReady({ \n port: actualPort, \n host, \n mode: opts.mode || 'production' \n }, log);\n \n // Broadcast server ready event\n relay.broadcast('server:ready', server);\n return server;\n },\n\n // Get all routes\n getRoutes: () => this.#routes,\n\n // Stop the server\n stop: async () => {\n if (this.#adapter) {\n await this.#adapter.stop();\n }\n },\n\n // Check if server is running\n isRunning: () => this.#adapter && this.#adapter.isRunning(),\n\n // Get the underlying HTTP server (for Socket.IO integration)\n getHttpServer: () => {\n if (this.#adapter) {\n return this.#adapter.getHttpServer();\n }\n return null;\n }\n };\n }\n /**\n * Serve static files from the output directory\n * @private\n */\n async #serveStaticFile(context, outputDir) {\n const fs = await import('fs/promises');\n const path = await import('path');\n \n try {\n // Get the requested file path\n const requestPath = context.req.path === '/' ? '/index.html' : context.req.path;\n let filePath = path.join(outputDir, requestPath);\n let stats;\n \n try {\n // Try the path as-is first\n stats = await fs.stat(filePath);\n } catch (error) {\n // If it fails and has no extension, try adding .html\n const ext = path.extname(requestPath);\n if (!ext) {\n const htmlPath = path.join(outputDir, `${requestPath}.html`);\n try {\n stats = await fs.stat(htmlPath);\n filePath = htmlPath; // Use the .html version\n } catch (htmlError) {\n // Neither worked, return 404\n return context.respond.text('Not Found', 404);\n }\n } else {\n // Had an extension but file not found\n return context.respond.text('Not Found', 404);\n }\n }\n \n if (stats.isFile()) {\n // Determine content type\n const ext = path.extname(filePath);\n const contentType = this.#getContentType(ext);\n \n // Read and serve the file\n const content = await fs.readFile(filePath);\n \n // Serve with correct content type\n if (contentType === 'text/html') {\n return context.respond.html(content.toString(), 200);\n } else if (contentType === 'text/css') {\n return context.respond.text(content.toString(), 200, { 'Content-Type': 'text/css' });\n } else if (contentType === 'application/javascript') {\n return context.respond.text(content.toString(), 200, { 'Content-Type': 'application/javascript' });\n } else if (contentType.startsWith('text/')) {\n return context.respond.text(content.toString(), 200, { 'Content-Type': contentType });\n } else {\n // For binary files, send as file response\n return context.respond.file(filePath, 200, { 'Content-Type': contentType });\n }\n } else {\n return context.respond.text('Not Found', 404);\n }\n } catch (error) {\n return context.respond.text('Not Found', 404);\n }\n }\n\n /**\n * Get content type based on file extension\n * @private\n */\n #getContentType(ext) {\n const types = {\n '.html': 'text/html',\n '.css': 'text/css',\n '.js': 'application/javascript',\n '.json': 'application/json',\n '.png': 'image/png',\n '.jpg': 'image/jpeg',\n '.jpeg': 'image/jpeg',\n '.gif': 'image/gif',\n '.svg': 'image/svg+xml',\n '.ico': 'image/x-icon',\n '.woff': 'font/woff',\n '.woff2': 'font/woff2',\n '.ttf': 'font/ttf',\n '.eot': 'application/vnd.ms-fontobject'\n };\n \n return types[ext.toLowerCase()] || 'application/octet-stream';\n }\n}"],"names":["Kernel","routes","hooks","onRequest","preHandler","onSend","onError","staticFallback","constructor","registerRoutes","rawRoutes","r","this","registerRoute","route","compiledRoute","match","compileRoute","path","push","h","Object","assign","setStaticFallback","outputDir","handler","handle","ctx","response","onReqOut","matchParams","find","method","req","m","staticResponse","status","respond","text","params","preOut","err","getRoutes","map","compiled","async","parseBody","Promise","resolve","contentType","headers","body","on","chunk","toString","includes","JSON","parse","data","result","pairs","split","pair","key","value","decodedKey","decodeURIComponent","decodedValue","endsWith","arrayKey","slice","parseUrlEncoded","raw","error","parseQuery","searchParams","entries","test","replace","AdapterInterface","create","name","server","kernel","log","initialize","start","options","Error","stop","getHttpServer","isRunning","handleRequest","res","createContext","url","URL","originalUrl","host","pathname","fromEntries","k","v","toLowerCase","query","RespondHelpers","sendResponse","isHead","resp","type","headersSent","statusCode","setHeader","end","getHeader","stringify","serveFile","b","pipe","Symbol","asyncIterator","write","once","filePath","fs","import","fsp","pipeline","promisify","pipelineAsync","MIME","st","stat","isFile","ext","extname","String","size","rs","createReadStream","handleError","json","html","file","stream","redirect","location","HttpAdapter","connections","Set","super","services","port","http","createServer","out","conn","add","delete","reject","listen","info","destroy","clear","close","execAsync","exec","displayServerReady","mode","logger","chalk","bold","blue","white","green","toUpperCase","cyan","underline","yellow","forEach","line","command","process","platform","message","openBrowser","debug","gray","Server","ServiceProvider","static","namespace","version","adapter","actions","useContext","meta","useAdapter","opts","relay","state","stable","timestamp","Date","toISOString","length","serveStaticFile","liveReload","initializeServer","actualPort","address","broadcast","context","requestPath","stats","join","htmlPath","htmlError","getContentType","content","readFile","startsWith"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Server-KKipH7VZ.js","sources":["../lib/Server/Kernel.js","../lib/Server/utils/httpParsing.js","../lib/Server/adapters/AdapterInterface.js","../lib/Server/adapters/HttpAdapter.js","../lib/Server/utils/serverReady.js","../lib/Server/Server.js"],"sourcesContent":["import { compileRoute } from './utils/routeMatch.js';\n\n/**\n * Kernel handles route registration and matching\n * Separates routing logic from HTTP protocol handling\n */\nexport class Kernel {\n #routes = []; // { method, path, match, handler, mode, revalidate, ... }\n #hooks = { \n onRequest: null, \n preHandler: null, \n onSend: null, \n onError: null \n };\n #staticFallback = null;\n\n constructor() { \n }\n\n /**\n * Register multiple routes at once\n * @param {Array} rawRoutes - Array of route objects\n */\n registerRoutes(rawRoutes) {\n for (const r of rawRoutes) {\n this.registerRoute(r);\n }\n }\n\n /**\n * Register a single route\n * @param {Object} route - Route object with method, path, handler, etc.\n */\n registerRoute(route) {\n const compiledRoute = {\n ...route,\n match: compileRoute(route.path)\n };\n this.#routes.push(compiledRoute);\n }\n\n /**\n * Configure hooks\n * @param {Object} hooks - Hook functions\n */\n hooks(h) { \n Object.assign(this.#hooks, h); \n }\n\n /**\n * Set static file fallback handler\n * @param {string} outputDir - Directory to serve static files from\n * @param {Function} handler - Static file handler function\n */\n setStaticFallback(outputDir, handler) {\n this.#staticFallback = { outputDir, handler };\n }\n\n /**\n * Handle a request through the routing system\n * @param {Object} ctx - Request context\n * @returns {Object} Response object\n */\n async handle(ctx) {\n let response;\n try {\n // onRequest can short-circuit\n const onReqOut = await this.#hooks.onRequest?.(ctx);\n if (onReqOut) { response = onReqOut; return response; }\n\n // route match …\n let matchParams = null;\n const route = this.#routes.find(r => {\n if (r.method !== ctx.req.method) return false;\n const m = r.match(ctx.req.path);\n if (m) { matchParams = m; return true; }\n return false;\n });\n\n if (!route) {\n if (this.#staticFallback) {\n const staticResponse = await this.#staticFallback.handler(ctx, this.#staticFallback.outputDir);\n response = (staticResponse && staticResponse.status !== 404)\n ? staticResponse\n : ctx.respond.text('Not Found', 404);\n } else {\n response = ctx.respond.text('Not Found', 404);\n }\n return response;\n }\n\n ctx.req.params = matchParams || {};\n\n // preHandler can short-circuit\n const preOut = await this.#hooks.preHandler?.(ctx, route);\n if (preOut) { response = preOut; return response; }\n\n // route handler\n response = await route.handler(ctx);\n\n } catch (err) {\n response = (await this.#hooks.onError?.(ctx, err))\n ?? ctx.respond.text('Internal Server Error', 500);\n } finally {\n await this.#hooks.onSend?.(ctx, response);\n }\n return response ?? ctx.respond.text('', 204);\n}\n\n\n /**\n * Get all registered routes\n * @returns {Array} Array of registered routes\n */\n getRoutes() {\n return this.#routes.map(route => ({\n method: route.method,\n path: route.path,\n params: route.params || [],\n compiled: true\n }));\n }\n}\n","/**\n * HTTP parsing utilities for request body and query parameters\n */\n\n/**\n * Parse request body based on content type\n * @param {Object} req - Node.js request object\n * @returns {Object|null} Parsed body object or null\n */\nexport async function parseBody(req) {\n return new Promise((resolve) => {\n if (req.method === 'GET' || req.method === 'HEAD') {\n resolve(null);\n return;\n }\n\n const contentType = req.headers['content-type'] || '';\n let body = '';\n\n req.on('data', chunk => {\n body += chunk.toString();\n });\n\n req.on('end', () => {\n try {\n if (contentType.includes('application/json')) {\n resolve(body ? JSON.parse(body) : {});\n } else if (contentType.includes('application/x-www-form-urlencoded')) {\n resolve(parseUrlEncoded(body));\n } else if (contentType.includes('multipart/form-data')) {\n // For now, just return the raw body for multipart\n // Could be enhanced with proper multipart parsing\n resolve({ raw: body });\n } else {\n resolve(body || null);\n }\n } catch (error) {\n resolve(null);\n }\n });\n\n req.on('error', () => {\n resolve(null);\n });\n });\n}\n\n/**\n * Parse URL-encoded form data\n * @param {string} data - URL-encoded string\n * @returns {Object} Parsed object\n */\nfunction parseUrlEncoded(data) {\n const result = {};\n const pairs = data.split('&');\n \n for (const pair of pairs) {\n const [key, value] = pair.split('=');\n if (key) {\n const decodedKey = decodeURIComponent(key);\n const decodedValue = value ? decodeURIComponent(value) : '';\n \n // Handle arrays (key[] or key[0])\n if (decodedKey.endsWith('[]')) {\n const arrayKey = decodedKey.slice(0, -2);\n if (!result[arrayKey]) result[arrayKey] = [];\n result[arrayKey].push(decodedValue);\n } else {\n result[decodedKey] = decodedValue;\n }\n }\n }\n \n return result;\n}\n\n/**\n * Parse query parameters from URLSearchParams\n * @param {URLSearchParams} searchParams - URL search parameters\n * @returns {Object} Parsed query object with support for arrays\n */\nexport function parseQuery(searchParams) {\n const result = {};\n \n for (const [key, value] of searchParams.entries()) {\n // Handle array parameters (key[] or key[0])\n if (key.endsWith('[]') || /\\[\\d*\\]$/.test(key)) {\n const arrayKey = key.replace(/\\[\\d*\\]$/, '').replace('[]', '');\n if (!result[arrayKey]) result[arrayKey] = [];\n result[arrayKey].push(value);\n } else {\n result[key] = value;\n }\n }\n \n return result;\n}\n","/**\n * Clovie Adapter Interface\n * \n * This defines the contract that all HTTP server adapters must implement.\n * The Clovie kernel uses this interface to delegate HTTP handling to\n * any compatible adapter (Express, Fastify, Node HTTP, etc.)\n */\nimport { parseQuery } from '../utils/httpParsing.js';\n\n/**\n * Adapter Interface - All adapters must implement this\n */\nexport class AdapterInterface {\n static create(name) {\n return new this(name);\n }\n\n constructor(name) {\n this.name = name;\n this.server = null;\n this.kernel = null;\n this.log = null;\n this.hooks = null;\n }\n\n /**\n * Initialize the adapter with kernel and context\n * @param {Object} kernel - Clovie kernel instance\n * @param {Object} log - Clovie logger\n */\n async initialize(kernel, log) {\n this.kernel = kernel;\n this.log = log;\n }\n\n /**\n * Start the HTTP server\n * @param {Object} options - Server options (port, host, etc.)\n * @returns {Promise<Object>} - Server instance\n */\n async start(options) {\n throw new Error(`start() must be implemented by ${this.name} adapter`);\n }\n\n /**\n * Stop the HTTP server\n * @returns {Promise<void>}\n */\n async stop() {\n throw new Error(`stop() must be implemented by ${this.name} adapter`);\n }\n\n /**\n * Get the underlying HTTP server instance\n * Used by services like LiveReload for Socket.IO integration\n * @returns {Object|null} - HTTP server instance\n */\n getHttpServer() {\n return this.server;\n }\n\n /**\n * Check if the server is currently running\n * @returns {boolean}\n */\n isRunning() {\n return this.server !== null;\n }\n\n /**\n * Handle a request through the adapter\n * @param {Object} req - HTTP request\n * @param {Object} res - HTTP response\n * @returns {Promise<void>}\n */\n async handleRequest(req, res) {\n throw new Error(`handleRequest() must be implemented by ${this.name} adapter`);\n }\n\n /**\n * Create standardized context object from request\n * @param {Object} req - HTTP request\n * @param {Object} res - HTTP response\n * @returns {Object} - Standardized context object\n */\n createContext(req, res) {\n const url = new URL(req.url || req.originalUrl, `http://${req.headers.host}`);\n\n return {\n req: {\n method: req.method,\n url: url.toString(),\n path: url.pathname,\n headers: Object.fromEntries(\n Object.entries(req.headers).map(([k, v]) => [k.toLowerCase(), v])\n ),\n query: req.query || parseQuery(url.searchParams),\n body: req.body || null,\n raw: { req, res },\n params: {}\n },\n res,\n respond: new RespondHelpers()\n };\n }\n\n /**\n * Send response using standardized response format\n * @param {Object} res - HTTP response\n * @param {Object} response - Response object from route handler\n * @param {boolean} isHead - Whether this is a HEAD request\n * @returns {Promise<void>}\n */\n async sendResponse(res, response, isHead = false) {\n // Default to 204 if no response object was returned\n const resp = response ?? { type: 'text', status: 204, headers: {}, body: '' };\n\n if (res.headersSent) return; // defensive guard\n\n // Set status and headers (normalize keys)\n res.statusCode = resp.status ?? 200;\n if (resp.headers) {\n for (const [k, v] of Object.entries(resp.headers)) {\n res.setHeader(k.toLowerCase(), v);\n }\n }\n\n // Respect HEAD requests: send headers only\n if (isHead) {\n return res.end();\n }\n\n switch (resp.type) {\n case 'json': {\n if (!res.getHeader('content-type')) {\n res.setHeader('content-type', 'application/json; charset=utf-8');\n }\n return res.end(JSON.stringify(resp.body));\n }\n\n case 'text': {\n if (!res.getHeader('content-type')) {\n res.setHeader('content-type', 'text/plain; charset=utf-8');\n }\n return res.end(resp.body ?? '');\n }\n\n case 'html': {\n if (!res.getHeader('content-type')) {\n res.setHeader('content-type', 'text/html; charset=utf-8');\n }\n return res.end(resp.body ?? '');\n }\n\n case 'file': {\n return await this.serveFile(res, resp.path);\n }\n\n case 'stream': {\n const b = resp.body;\n if (!b) return res.end();\n // Node stream\n if (typeof b.pipe === 'function') return b.pipe(res);\n // AsyncIterable\n if (Symbol.asyncIterator in Object(b)) {\n for await (const chunk of b) {\n if (!res.write(chunk)) {\n await new Promise(r => res.once('drain', r));\n }\n }\n return res.end();\n }\n // Fallback\n return res.end(b);\n }\n\n default:\n return res.end('');\n }\n }\n\n /**\n * Serve static files with proper MIME types and streaming\n * @param {Object} res - HTTP response\n * @param {string} filePath - Path to file to serve\n * @returns {Promise<void>}\n */\n async serveFile(res, filePath) {\n const fs = await import('node:fs');\n const fsp = await import('node:fs/promises');\n const path = await import('node:path');\n const { pipeline } = await import('node:stream');\n const { promisify } = await import('node:util');\n \n const pipelineAsync = promisify(pipeline);\n\n const MIME = {\n '.html': 'text/html; charset=utf-8',\n '.css': 'text/css; charset=utf-8',\n '.js': 'application/javascript; charset=utf-8',\n '.mjs': 'application/javascript; charset=utf-8',\n '.json': 'application/json; charset=utf-8',\n '.svg': 'image/svg+xml',\n '.png': 'image/png',\n '.jpg': 'image/jpeg',\n '.jpeg': 'image/jpeg',\n '.gif': 'image/gif',\n '.ico': 'image/x-icon',\n '.woff': 'font/woff',\n '.woff2': 'font/woff2',\n '.ttf': 'font/ttf',\n '.eot': 'application/vnd.ms-fontobject'\n };\n\n try {\n const st = await fsp.stat(filePath);\n if (!st.isFile()) {\n res.statusCode = 404;\n res.setHeader('content-type', 'text/plain; charset=utf-8');\n return res.end('Not Found');\n }\n\n const ext = path.extname(filePath).toLowerCase();\n if (!res.getHeader('content-type')) {\n res.setHeader('content-type', MIME[ext] ?? 'application/octet-stream');\n }\n res.setHeader('content-length', String(st.size));\n\n const rs = fs.createReadStream(filePath);\n rs.on('error', () => {\n if (!res.headersSent) res.statusCode = 404;\n res.end('Not Found');\n });\n await pipelineAsync(rs, res); // backpressure-aware piping\n } catch {\n if (!res.headersSent) {\n res.statusCode = 404;\n res.setHeader('content-type', 'text/plain; charset=utf-8');\n }\n res.end('Not Found');\n }\n }\n\n /**\n * Handle request errors consistently\n * @param {Object} res - HTTP response\n * @param {Error} error - Error that occurred\n * @returns {Promise<void>}\n */\n async handleError(res, error) {\n this.log?.error?.('Request handling error:', error);\n if (!res.headersSent) {\n res.statusCode = 500;\n res.setHeader('content-type', 'text/plain; charset=utf-8');\n res.end('Internal Server Error');\n }\n }\n}\n\n/**\n * Route object structure that adapters receive from Clovie kernel\n */\nexport class ClovieRoute {\n constructor(method, path, handler, options = {}) {\n this.method = method.toUpperCase();\n this.path = path;\n this.handler = handler;\n this.options = options;\n this.params = options.params || [];\n }\n}\n\n/**\n * Hook object structure for lifecycle management\n */\nexport class ClovieHooks {\n constructor() {\n this.onRequest = null;\n this.preHandler = null;\n this.onSend = null;\n this.onError = null;\n }\n}\n\n/**\n * Context object passed to route handlers\n */\nexport class ClovieContext {\n constructor(req, res, state, stable) {\n this.req = req;\n this.res = res;\n this.state = state;\n this.stable = stable;\n this.respond = new RespondHelpers();\n }\n}\n\n/**\n * Response helpers for route handlers\n */\nexport class RespondHelpers {\n json(data, status = 200, headers = {}) {\n return { type: 'json', status, headers, body: data };\n }\n\n text(data, status = 200, headers = {}) {\n return { type: 'text', status, headers, body: data };\n }\n\n html(data, status = 200, headers = {}) {\n return { type: 'html', status, headers, body: data };\n }\n\n file(path, status = 200, headers = {}) {\n return { type: 'file', status, headers, path };\n }\n\n stream(body, status = 200, headers = {}) {\n return { type: 'stream', status, headers, body };\n }\n\n redirect(location, status = 302, headers = {}) {\n return { type:'text', status, headers: { ...headers, location }, body: '' };\n }\n}\n","/**\n * HTTP Adapter for Node.js native HTTP server\n * Thin I/O shim: normalize req/res, call kernel, send response\n */\nimport http from 'node:http';\nimport { AdapterInterface } from './AdapterInterface.js';\nimport { parseBody } from '../utils/httpParsing.js';\n\nexport class HttpAdapter extends AdapterInterface {\n #connections = new Set();\n\n constructor() {\n super('http');\n }\n\n async initialize(kernel, services, log) {\n await super.initialize(kernel, services, log);\n }\n\n async start({ port = 3000, host = '0.0.0.0' } = {}) {\n this.server = http.createServer(async (req, res) => {\n try {\n // Parse body for HTTP adapter (Express handles this differently)\n if (!req.body) {\n req.body = await parseBody(req);\n }\n\n const ctx = this.createContext(req, res);\n const out = await this.kernel.handle(ctx);\n await this.sendResponse(res, out, req.method === 'HEAD');\n } catch (error) {\n await this.handleError(res, error);\n }\n });\n\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 await new Promise((resolve, reject) =>\n this.server.listen(port, host, err => (err ? reject(err) : resolve()))\n );\n\n this.log?.info?.(`HTTP Server listening on http://${host}:${port}`);\n return this.server;\n }\n\n async stop() {\n if (this.server) {\n // Destroy all active connections\n for (const conn of this.#connections) {\n conn.destroy();\n }\n this.#connections.clear();\n\n // Close the server\n await new Promise(resolve => this.server.close(() => resolve()));\n this.server = null;\n }\n }\n\n}\n","import chalk from 'chalk';\nimport { exec } from 'child_process';\nimport { promisify } from 'util';\n\nconst execAsync = promisify(exec);\n\n/**\n * Display a pretty server ready message with clickable URL\n * @param {object} options - Server options\n * @param {number} options.port - Server port\n * @param {string} options.host - Server host\n * @param {string} options.mode - Server mode (development/production)\n * @param {object} logger - Logger instance\n */\nexport async function displayServerReady({ port, host, mode }, logger) {\n const protocol = mode === 'development' ? 'http' : 'https';\n const url = `${protocol}://${host === '0.0.0.0' ? 'localhost' : host}:${port}`;\n \n // Create a nice banner\n const banner = [\n '',\n chalk.bold.blue('╔══════════════════════════════════════════════════════════════╗'),\n chalk.bold.blue('║') + chalk.bold.white(' 🚀 Clovie Server Ready! 🚀 ') + chalk.bold.blue('║'),\n chalk.bold.blue('╠══════════════════════════════════════════════════════════════╣'),\n chalk.bold.blue('║') + chalk.white(` Mode: ${chalk.green(mode.toUpperCase())} `) + chalk.bold.blue('║'),\n chalk.bold.blue('║') + chalk.white(` URL: ${chalk.cyan.underline(url)} `) + chalk.bold.blue('║'),\n chalk.bold.blue('║') + chalk.white(` Host: ${chalk.yellow(host)}:${chalk.yellow(port)} `) + chalk.bold.blue('║'),\n chalk.bold.blue('╚══════════════════════════════════════════════════════════════╝'),\n ''\n ];\n\n // Display the banner\n banner.forEach(line => logger.info(line));\n\n // Try to open browser automatically in development mode\n if (mode === 'development') {\n try {\n await openBrowser(url);\n logger.info(chalk.green('🌐 Browser opened automatically'));\n } catch (error) {\n logger.debug('Could not open browser automatically:', error.message);\n }\n }\n\n // Display helpful commands\n const commands = [\n '',\n chalk.gray('💡 Quick Commands:'),\n chalk.gray(` • Press ${chalk.yellow('Ctrl+C')} to stop the server`),\n chalk.gray(` • Visit ${chalk.cyan(url)} to view your site`),\n chalk.gray(` • Check the console for live reload updates`),\n ''\n ];\n\n commands.forEach(line => logger.info(line));\n}\n\n/**\n * Open browser with the given URL\n * @param {string} url - URL to open\n */\nasync function openBrowser(url) {\n const platform = process.platform;\n let command;\n\n switch (platform) {\n case 'darwin': // macOS\n command = `open \"${url}\"`;\n break;\n case 'win32': // Windows\n command = `start \"${url}\"`;\n break;\n default: // Linux and others\n command = `xdg-open \"${url}\"`;\n break;\n }\n\n try {\n await execAsync(command);\n } catch (error) {\n throw new Error(`Failed to open browser: ${error.message}`);\n }\n}","import { ServiceProvider } from '@brickworks/engine';\nimport { Kernel } from './Kernel.js';\nimport { HttpAdapter } from './adapters/HttpAdapter.js';\nimport { displayServerReady } from './utils/serverReady.js';\n\nexport class Server extends ServiceProvider {\n static manifest = {\n name: 'Clovie Server',\n namespace: 'server',\n version: '1.0.0'\n };\n\n #routes = [];\n #adapter = null;\n #hooks = {\n onRequest: null,\n preHandler: null,\n onSend: null,\n onError: null\n };\n\n actions(useContext) { \n return {\n // Add a route\n add: (method, path, handler, meta = {}) => {\n this.#routes.push({\n method: method.toUpperCase(),\n path,\n handler,\n meta\n });\n },\n\n // Set server adapter\n useAdapter: (adapter) => {\n this.#adapter = adapter;\n return this;\n },\n\n // Configure hooks\n hooks: (hooks) => {\n this.#hooks = { ...this.#hooks, ...hooks };\n return this;\n },\n\n // Start listening server\n listen: async (opts = {}) => {\n const relay = useContext('relay');\n const port = opts.port || opts || 3000;\n const host = opts.host || '0.0.0.0';\n const log = useContext('log');\n \n // Create kernel with services\n const kernel = new Kernel({\n state: useContext('state'),\n stable: useContext('stable'),\n // Add other services as needed for ISR/static/SSR\n });\n\n // Configure kernel hooks\n kernel.hooks(this.#hooks);\n\n // 1) Register app routes first\n kernel.registerRoutes(this.#routes);\n\n // 2) Add system routes (won't shadow user routes)\n kernel.registerRoutes([\n {\n method: 'GET',\n path: '/health',\n handler: (ctx) => ctx.respond.json({\n status: 'ok',\n timestamp: new Date().toISOString(),\n mode: opts.mode || 'production'\n })\n },\n {\n method: 'GET',\n path: '/api/info',\n handler: (ctx) => ctx.respond.json({\n name: 'Clovie',\n version: '1.0.0',\n mode: opts.mode || 'production',\n routes: this.#routes.length\n })\n }\n ]);\n\n // 3) Configure static file serving as 404 fallback\n if (opts.outputDir) {\n kernel.setStaticFallback(opts.outputDir, (ctx, outputDir) => {\n return this.#serveStaticFile(ctx, outputDir);\n });\n }\n\n // 4) Boot adapter\n this.#adapter = this.#adapter ?? HttpAdapter.create();\n await this.#adapter.initialize(kernel, log);\n \n // Start the server and return the instance\n const server = await this.#adapter.start({ port, host });\n \n // Check for LiveReload service and initialize it if available\n try {\n const liveReload = useContext('liveReload');\n log.debug(`LiveReload service found: ${!!liveReload}, mode: ${opts.mode}`);\n if (liveReload && opts.mode === 'development') {\n log.info('Initializing LiveReload...');\n await liveReload.initializeServer(server, opts);\n log.info('LiveReload initialized successfully');\n }\n } catch (error) {\n log.debug('LiveReload not available:', error.message);\n }\n \n // Display pretty server ready message\n const actualPort = server.address()?.port || port;\n await displayServerReady({ \n port: actualPort, \n host, \n mode: opts.mode || 'production' \n }, log);\n \n // Broadcast server ready event\n relay.broadcast('server:ready', server);\n return server;\n },\n\n // Get all routes\n getRoutes: () => this.#routes,\n\n // Stop the server\n stop: async () => {\n if (this.#adapter) {\n await this.#adapter.stop();\n }\n },\n\n // Check if server is running\n isRunning: () => this.#adapter && this.#adapter.isRunning(),\n\n // Get the underlying HTTP server (for Socket.IO integration)\n getHttpServer: () => {\n if (this.#adapter) {\n return this.#adapter.getHttpServer();\n }\n return null;\n }\n };\n }\n /**\n * Serve static files from the output directory\n * @private\n */\n async #serveStaticFile(context, outputDir) {\n const fs = await import('fs/promises');\n const path = await import('path');\n \n try {\n // Get the requested file path\n const requestPath = context.req.path === '/' ? '/index.html' : context.req.path;\n let filePath = path.join(outputDir, requestPath);\n let stats;\n \n try {\n // Try the path as-is first\n stats = await fs.stat(filePath);\n } catch (error) {\n // If it fails and has no extension, try adding .html\n const ext = path.extname(requestPath);\n if (!ext) {\n const htmlPath = path.join(outputDir, `${requestPath}.html`);\n try {\n stats = await fs.stat(htmlPath);\n filePath = htmlPath; // Use the .html version\n } catch (htmlError) {\n // Neither worked, return 404\n return context.respond.text('Not Found', 404);\n }\n } else {\n // Had an extension but file not found\n return context.respond.text('Not Found', 404);\n }\n }\n \n if (stats.isFile()) {\n // Determine content type\n const ext = path.extname(filePath);\n const contentType = this.#getContentType(ext);\n \n // Read and serve the file\n const content = await fs.readFile(filePath);\n \n // Serve with correct content type\n if (contentType === 'text/html') {\n return context.respond.html(content.toString(), 200);\n } else if (contentType === 'text/css') {\n return context.respond.text(content.toString(), 200, { 'Content-Type': 'text/css' });\n } else if (contentType === 'application/javascript') {\n return context.respond.text(content.toString(), 200, { 'Content-Type': 'application/javascript' });\n } else if (contentType.startsWith('text/')) {\n return context.respond.text(content.toString(), 200, { 'Content-Type': contentType });\n } else {\n // For binary files, send as file response\n return context.respond.file(filePath, 200, { 'Content-Type': contentType });\n }\n } else {\n return context.respond.text('Not Found', 404);\n }\n } catch (error) {\n return context.respond.text('Not Found', 404);\n }\n }\n\n /**\n * Get content type based on file extension\n * @private\n */\n #getContentType(ext) {\n const types = {\n '.html': 'text/html',\n '.css': 'text/css',\n '.js': 'application/javascript',\n '.json': 'application/json',\n '.png': 'image/png',\n '.jpg': 'image/jpeg',\n '.jpeg': 'image/jpeg',\n '.gif': 'image/gif',\n '.svg': 'image/svg+xml',\n '.ico': 'image/x-icon',\n '.woff': 'font/woff',\n '.woff2': 'font/woff2',\n '.ttf': 'font/ttf',\n '.eot': 'application/vnd.ms-fontobject'\n };\n \n return types[ext.toLowerCase()] || 'application/octet-stream';\n }\n}"],"names":["Kernel","routes","hooks","onRequest","preHandler","onSend","onError","staticFallback","constructor","registerRoutes","rawRoutes","r","this","registerRoute","route","compiledRoute","match","compileRoute","path","push","h","Object","assign","setStaticFallback","outputDir","handler","handle","ctx","response","onReqOut","matchParams","find","method","req","m","staticResponse","status","respond","text","params","preOut","err","getRoutes","map","compiled","async","parseBody","Promise","resolve","contentType","headers","body","on","chunk","toString","includes","JSON","parse","data","result","pairs","split","pair","key","value","decodedKey","decodeURIComponent","decodedValue","endsWith","arrayKey","slice","parseUrlEncoded","raw","error","parseQuery","searchParams","entries","test","replace","AdapterInterface","create","name","server","kernel","log","initialize","start","options","Error","stop","getHttpServer","isRunning","handleRequest","res","createContext","url","URL","originalUrl","host","pathname","fromEntries","k","v","toLowerCase","query","RespondHelpers","sendResponse","isHead","resp","type","headersSent","statusCode","setHeader","end","getHeader","stringify","serveFile","b","pipe","Symbol","asyncIterator","write","once","filePath","fs","import","fsp","pipeline","promisify","pipelineAsync","MIME","st","stat","isFile","ext","extname","String","size","rs","createReadStream","handleError","json","html","file","stream","redirect","location","HttpAdapter","connections","Set","super","services","port","http","createServer","out","conn","add","delete","reject","listen","info","destroy","clear","close","execAsync","exec","displayServerReady","mode","logger","chalk","bold","blue","white","green","toUpperCase","cyan","underline","yellow","forEach","line","command","process","platform","message","openBrowser","debug","gray","Server","ServiceProvider","static","namespace","version","adapter","actions","useContext","meta","useAdapter","opts","relay","state","stable","timestamp","Date","toISOString","length","serveStaticFile","liveReload","initializeServer","actualPort","address","broadcast","context","requestPath","stats","join","htmlPath","htmlError","getContentType","content","readFile","startsWith"],"mappings":"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"}
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
var socket_io = require("socket.io"), createClovie = require("./createClovie-
|
|
3
|
+
var socket_io = require("socket.io"), createClovie = require("./createClovie-CyH1Um6E.cjs");
|
|
4
4
|
|
|
5
5
|
require("stream"), require("module"), require("path"), require("crypto"), require("fs"),
|
|
6
6
|
require("istextorbinary"), require("chokidar"), require("readline"), require("events"),
|
|
7
|
-
require("node:process"), require("node:os"), require("node:tty")
|
|
8
|
-
require("node:fs");
|
|
7
|
+
require("node:process"), require("node:os"), require("node:tty");
|
|
9
8
|
|
|
10
9
|
class LiveReload extends createClovie.ServiceProvider {
|
|
11
10
|
static manifest={
|
|
@@ -73,4 +72,4 @@ class LiveReload extends createClovie.ServiceProvider {
|
|
|
73
72
|
}
|
|
74
73
|
|
|
75
74
|
exports.LiveReload = LiveReload;
|
|
76
|
-
//# sourceMappingURL=LiveReload-
|
|
75
|
+
//# sourceMappingURL=LiveReload-CcJySo4Z.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LiveReload-
|
|
1
|
+
{"version":3,"file":"LiveReload-CcJySo4Z.cjs","sources":["../../lib/LiveReload.js"],"sourcesContent":["import { Server as SocketIOServer } from 'socket.io';\nimport { ServiceProvider } from '@brickworks/engine';\nimport { queueMacrotask } from './utils/tasks.js';\n\nexport class LiveReload extends ServiceProvider {\n static manifest = {\n name: 'Clovie LiveReload',\n namespace: 'liveReload',\n version: '1.0.0',\n };\n\n #io;\n #reloading = false;\n\n getter () {\n return {\n io: () => this.#io,\n }\n }\n\n actions() {\n return {\n initializeServer: async (server, opts) => {\n const log = this.useContext('log');\n if (opts.mode === 'development') {\n await this.#setupSocketIO(server, log);\n }\n },\n notifyReload: () => {\n if (this.#reloading) return;\n this.#reloading = true;\n \n queueMacrotask(() => {\n this.#reloading = false;\n if (this.#io) {\n this.#io.emit('reload')\n }\n });\n },\n injectLiveReloadScript: async (renderedContent, opts) => {\n const lastBodyIndex = renderedContent.lastIndexOf('</body>');\n if (lastBodyIndex !== -1) {\n const scriptConfig = { \n mode: opts.mode || 'development', \n port: opts.port || 3000 \n };\n \n try {\n // Import live reload script dynamically \n renderedContent = renderedContent.substring(0, lastBodyIndex) + \n this.#liveReloadScript(scriptConfig) + '\\n' + \n renderedContent.substring(lastBodyIndex);\n } catch (err) {\n console.warn('⚠️ Could not load live reload script:', err.message);\n }\n }\n return renderedContent;\n }\n }\n }\n\n async #setupSocketIO(server, log) {\n try {\n // Wait a bit for server to be fully initialized\n await new Promise(resolve => setTimeout(resolve, 100));\n\n log.debug('Setting up Socket.IO...');\n \n // Configure Socket.IO with proper CORS and options\n this.#io = new SocketIOServer(server, {\n cors: {\n origin: \"*\",\n methods: [\"GET\", \"POST\"]\n },\n transports: ['polling', 'websocket'],\n allowEIO3: true\n });\n\n this.#io.on('connection', (socket) => {\n log.debug(`Client connected: ${socket.id}`);\n \n socket.on('disconnect', (reason) => {\n log.debug(`Client disconnected: ${socket.id} - ${reason}`);\n });\n \n socket.on('error', (error) => {\n log.error('Socket error:', error);\n });\n });\n\n log.info('Socket.IO server ready');\n } catch (error) {\n log.error('Error setting up Socket.IO:', error);\n }\n }\n\n #liveReloadScript = (opts) => `<!-- Live Reload Script (Development Mode Only) -->\n<script src=\"https://cdn.socket.io/4.7.4/socket.io.min.js\"></script>\n<script>\n (function() {\n const opts = ${JSON.stringify(opts)};\n \n console.log('Initializing live reload with opts:', opts);\n \n // Configure Socket.IO client with proper options\n const socket = io({\n transports: ['polling', 'websocket'],\n timeout: 20000,\n forceNew: true\n });\n \n socket.on('reload', () => {\n console.log('Live reload triggered');\n window.location.reload();\n });\n \n socket.on('connect', () => {\n console.log('Connected to live reload server');\n });\n \n socket.on('disconnect', (reason) => {\n console.log('Disconnected from live reload server:', reason);\n });\n \n socket.on('connect_error', (error) => {\n console.error('Connection error:', error);\n console.log('Retrying connection in 3 seconds...');\n setTimeout(() => {\n socket.connect();\n }, 3000);\n });\n \n socket.on('error', (error) => {\n console.error('Socket error:', error);\n });\n \n // Add connection timeout\n setTimeout(() => {\n if (!socket.connected) {\n console.warn('Live reload connection timeout - server may not be running');\n }\n }, 5000);\n })();\n</script>`;\n}"],"names":["LiveReload","ServiceProvider","static","name","namespace","version","io","reloading","getter","this","actions","initializeServer","async","server","opts","log","useContext","mode","setupSocketIO","notifyReload","queueMacrotask","emit","injectLiveReloadScript","renderedContent","lastBodyIndex","lastIndexOf","scriptConfig","port","substring","liveReloadScript","err","console","warn","message","Promise","resolve","setTimeout","debug","SocketIOServer","cors","origin","methods","transports","allowEIO3","on","socket","id","reason","error","info","JSON","stringify"],"mappings":";;;;;;;;AAIO,MAAMA,mBAAmBC,aAAAA;IAC9BC,gBAAkB;QAChBC,MAAM;QACNC,WAAW;QACXC,SAAS;;IAGXC;IACAC,YAAa;IAEb,MAAAC;QACE,OAAO;YACLF,IAAI,MAAMG,MAAKH;;AAEnB;IAEA,OAAAI;QACE,OAAO;YACLC,kBAAkBC,OAAOC,QAAQC;gBAC/B,MAAMC,MAAMN,KAAKO,WAAW;gBACV,kBAAdF,KAAKG,cACDR,MAAKS,cAAeL,QAAQE;;YAGtCI,cAAc;gBACRV,MAAKF,cACTE,MAAKF,aAAa,GAElBa,aAAAA,eAAe;oBACbX,MAAKF,aAAa,GACdE,MAAKH,MACPG,MAAKH,GAAIe,KAAK;;;YAIpBC,wBAAwBV,OAAOW,iBAAiBT;gBAC9C,MAAMU,gBAAgBD,gBAAgBE,YAAY;gBAClD,KAAsB,MAAlBD,eAAsB;oBACxB,MAAME,eAAe;wBACnBT,MAAMH,KAAKG,QAAQ;wBACnBU,MAAMb,KAAKa,QAAQ;;oBAGrB;wBAEEJ,kBAAkBA,gBAAgBK,UAAU,GAAGJ,iBAC/Bf,MAAKoB,iBAAkBH,gBAAgB,OACvCH,gBAAgBK,UAAUJ;AAC5C,sBAAE,OAAOM;wBACPC,QAAQC,KAAK,0CAA0CF,IAAIG;AAC7D;AACF;gBACA,OAAOV;;;AAGb;IAEA,oBAAML,CAAeL,QAAQE;QAC3B;kBAEQ,IAAImB,QAAQC,WAAWC,WAAWD,SAAS,OAEjDpB,IAAIsB,MAAM;YAGV5B,MAAKH,KAAM,IAAIgC,UAAAA,OAAezB,QAAQ;gBACpC0B,MAAM;oBACJC,QAAQ;oBACRC,SAAS,EAAC,OAAO;;gBAEnBC,YAAY,EAAC,WAAW;gBACxBC,YAAW;gBAGblC,MAAKH,GAAIsC,GAAG,cAAeC;gBACzB9B,IAAIsB,MAAM,qBAAqBQ,OAAOC,OAEtCD,OAAOD,GAAG,cAAeG;oBACvBhC,IAAIsB,MAAM,wBAAwBQ,OAAOC,QAAQC;oBAGnDF,OAAOD,GAAG,SAAUI;oBAClBjC,IAAIiC,MAAM,iBAAiBA;;gBAI/BjC,IAAIkC,KAAK;AACX,UAAE,OAAOD;YACPjC,IAAIiC,MAAM,+BAA+BA;AAC3C;AACF;IAEAnB,kBAAqBf,QAAS,iLAIboC,KAAKC,UAAUrC;;;"}
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
var createClovie = require("./createClovie-
|
|
3
|
+
var createClovie = require("./createClovie-CyH1Um6E.cjs"), http = require("node:http"), child_process = require("child_process"), util = require("util");
|
|
4
4
|
|
|
5
5
|
require("stream"), require("module"), require("path"), require("crypto"), require("fs"),
|
|
6
6
|
require("istextorbinary"), require("chokidar"), require("readline"), require("events"),
|
|
7
|
-
require("node:process"), require("node:os"), require("node:tty")
|
|
8
|
-
require("node:fs");
|
|
7
|
+
require("node:process"), require("node:os"), require("node:tty");
|
|
9
8
|
|
|
10
9
|
class Kernel {
|
|
11
10
|
#routes=[];
|
|
@@ -500,4 +499,4 @@ class Server extends createClovie.ServiceProvider {
|
|
|
500
499
|
}
|
|
501
500
|
|
|
502
501
|
exports.Server = Server;
|
|
503
|
-
//# sourceMappingURL=Server-
|
|
502
|
+
//# sourceMappingURL=Server-C1NgJiAD.cjs.map
|