clovie 0.1.11 → 0.1.13

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/bin/cli.js CHANGED
@@ -131,14 +131,13 @@ const options = commandLineArgs(optionDefinitions, { argv });
131
131
 
132
132
 
133
133
 
134
- // Handle watch command
134
+ // Handle legacy command mappings
135
135
  if (mainOptions.command === 'watch') {
136
- options.watch = true;
136
+ mainOptions.command = 'dev'; // Map watch to dev
137
137
  }
138
138
 
139
- // Handle server command
140
139
  if (mainOptions.command === 'server') {
141
- options.server = true;
140
+ mainOptions.command = 'serve'; // Map server to serve
142
141
  }
143
142
 
144
143
  // Config path
@@ -147,136 +146,106 @@ const configPath = path.resolve(process.cwd(), options.config);
147
146
  // Main function
148
147
  async function main() {
149
148
  try {
150
- // Config file - use default if not found
151
- let config;
152
- try {
153
- const configModule = await import(configPath);
154
- config = configModule.default || configModule;
155
- } catch (err) {
156
- if (err.code === 'ERR_MODULE_NOT_FOUND') {
157
- // Use default config if clovie.config.js not found
158
- const defaultConfigModule = await import('../config/clovie.config.js');
159
- config = defaultConfigModule.default;
160
- console.log('šŸ“ Using default Clovie configuration');
161
- } else {
162
- throw err;
163
- }
164
- }
149
+ const command = mainOptions.command || 'dev'; // Default to dev
150
+ console.log(`šŸš€ Starting Clovie ${command}...`);
151
+
152
+ // Step 1: Load config file (with fallback to default)
153
+ const config = await loadConfig(options.config);
154
+
155
+ // Step 2: Determine mode based on command
156
+ const mode = determineMode(command, config);
157
+
158
+ // Step 3: Create Clovie instance with explicit mode
159
+ console.log('āš™ļø Creating Clovie instance...');
160
+ const clovie = await createClovie({
161
+ ...config,
162
+ configPath: configPath,
163
+ mode: mode
164
+ });
165
+
166
+ // Step 4: Execute specific command
167
+ await executeCommand(clovie, command, options);
165
168
 
166
- // Override config type if server command is used
167
- if (options.server) {
168
- config.type = 'server';
169
+ } catch (err) {
170
+ console.error('āŒ Error:', err.message || err);
171
+ process.exit(1);
172
+ }
173
+ }
174
+
175
+ // Load configuration with fallback
176
+ async function loadConfig(configPath) {
177
+ try {
178
+ const configModule = await import(configPath);
179
+ const config = configModule.default || configModule;
180
+ console.log(`šŸ“ Using config: ${options.config}`);
181
+ return config;
182
+ } catch (err) {
183
+ if (err.code === 'ERR_MODULE_NOT_FOUND') {
184
+ // Use default config if clovie.config.js not found
185
+ const defaultConfigModule = await import('../config/clovie.config.js');
186
+ const config = defaultConfigModule.default;
187
+ console.log('šŸ“ Using default Clovie configuration');
188
+ return config;
189
+ } else {
190
+ throw err;
169
191
  }
192
+ }
193
+ }
170
194
 
171
- // New Clovie instance
172
- const clovie = await createClovie(config);
195
+ // Determine mode based on command and config
196
+ function determineMode(command, config) {
197
+ // If config explicitly sets mode, use it unless overridden by command
198
+ if (config.mode && !['build', 'serve', 'dev', 'watch'].includes(command)) {
199
+ return config.mode;
200
+ }
201
+
202
+ // Command-based mode determination
203
+ switch (command) {
204
+ case 'build':
205
+ return 'production';
206
+ case 'serve':
207
+ return 'production';
208
+ case 'dev':
209
+ case 'watch':
210
+ return 'development';
211
+ default:
212
+ return 'development';
213
+ }
214
+ }
173
215
 
174
- if (options.server) {
175
- // Server mode - run as Express server
176
- console.log('🌐 Starting server mode...');
177
-
178
- // Load data into state first
179
- if (config.data) {
180
- console.log('šŸ“Š Loading data into state...');
181
- let loadedData = {};
182
- if (typeof config.data === 'function') {
183
- loadedData = await config.data();
184
- } else if (typeof config.data === 'object') {
185
- loadedData = config.data;
186
- }
187
- clovie.state.load(loadedData);
188
- console.log(` Loaded ${Object.keys(loadedData).length} data sources into state`);
189
- }
190
-
191
- // Start server
192
- clovie.server.start();
193
-
194
- // Keep the process running
195
- process.on('SIGINT', () => {
196
- console.log('\nšŸ›‘ Stopping server...');
197
- clovie.server.stop();
198
- process.exit(0);
199
- });
200
-
201
- } else if (options.watch) {
202
- // Development mode with file watching
203
- console.log('šŸ—ļø Initial build...');
204
- await clovie.build.static();
205
- console.log('āœ… Initial build completed\n');
206
-
207
- // Start development server
208
- clovie.server.start();
209
-
210
- // Set up file watching
211
- console.log('šŸ‘€ Setting up file watching...');
212
-
213
- // Debug: Check if config service is available
214
- console.log(' Debug: config service available:', !!clovie.config);
215
- console.log(' Debug: getWatchPaths available:', !!clovie.config?.getWatchPaths);
216
-
217
- // Use discovered config paths from Config service
218
- let watchPaths;
219
- try {
220
- watchPaths = clovie.config.getWatchPaths();
221
- } catch (error) {
222
- console.error(' Error getting watch paths:', error.message);
223
- // Fallback to manual discovery for debugging
224
- const discoveredConfig = clovie.config.get();
225
- watchPaths = [
226
- discoveredConfig?.views,
227
- discoveredConfig?.partials,
228
- discoveredConfig?.styles,
229
- discoveredConfig?.scripts,
230
- discoveredConfig?.assets
231
- ].filter(Boolean);
232
- console.log(' Using fallback watch paths:', watchPaths);
233
- }
234
-
235
- console.log(` Watching ${watchPaths.length} directories:`, watchPaths);
236
-
237
- // Set up file watchers with change handler
238
- const watchers = clovie.file.watch(watchPaths, {}, {
239
- onChange: async (filePath) => {
240
- console.log('šŸ”„ Triggering rebuild...');
241
-
242
- try {
243
- const result = await clovie.build.static();
244
- console.log(`āœ… Rebuild completed in ${result.buildTime}ms`);
245
-
246
- // Notify live reload
247
- if (clovie.server && clovie.server.notifyReload) {
248
- clovie.server.notifyReload();
249
- }
250
- } catch (error) {
251
- console.error('āŒ Rebuild failed:', error.message);
252
- }
253
- }
254
- });
216
+ // Execute the specific command
217
+ async function executeCommand(clovie, command, options) {
218
+ switch (command) {
219
+ case 'build':
220
+ console.log('šŸ”Ø Building project...');
221
+ await clovie.run.build();
222
+ console.log('āœ… Build completed successfully');
223
+ process.exit(0);
255
224
 
256
- console.log(`🌐 Development server running at http://localhost:${config.port || 3000}`);
257
- console.log('šŸ‘€ Watching for file changes...');
258
- console.log('Press Ctrl+C to stop the server\n');
225
+ case 'serve':
226
+ console.log('🌐 Starting production server...');
227
+ await clovie.run.serve();
228
+ // Keep process alive for server
229
+ break;
259
230
 
260
- // Keep the process running
261
- process.on('SIGINT', () => {
262
- console.log('\nšŸ›‘ Stopping development server...');
263
- if (clovie.file.isWatching()) {
264
- clovie.file.stopWatching();
265
- }
266
- process.exit(0);
267
- });
231
+ case 'dev':
232
+ case 'watch':
233
+ console.log('šŸš€ Starting development server...');
234
+ await clovie.run.dev();
235
+ // Keep process alive for dev server
236
+ break;
268
237
 
269
- } else {
270
- // Build mode
271
- const result = await clovie.build.static();
272
- console.log(`āœ… Build completed in ${result.buildTime}ms`);
273
- console.log(`šŸ“ Generated ${result.filesGenerated} files`);
274
- process.exit(0);
275
- }
276
- } catch (err) {
277
- console.error(err);
278
- process.exit(1);
238
+ default:
239
+ console.error(`āŒ Unknown command: ${command}`);
240
+ console.error('Available commands: build, serve, dev, watch');
241
+ process.exit(1);
279
242
  }
243
+
244
+ // Setup graceful shutdown for long-running processes
245
+ process.on('SIGINT', () => {
246
+ console.log('\nšŸ›‘ Shutting down...');
247
+ process.exit(0);
248
+ });
280
249
  }
281
250
 
282
251
  // Run main function
@@ -0,0 +1,95 @@
1
+ import { Server } from "socket.io";
2
+
3
+ import { S as ServiceProvider, q as queueMacrotask } from "./createClovie-1_zYoNTN.js";
4
+
5
+ import "stream";
6
+
7
+ import "module";
8
+
9
+ import "path";
10
+
11
+ import "crypto";
12
+
13
+ import "fs";
14
+
15
+ import "istextorbinary";
16
+
17
+ import "chokidar";
18
+
19
+ import "readline";
20
+
21
+ import "events";
22
+
23
+ import "node:process";
24
+
25
+ import "node:os";
26
+
27
+ import "node:tty";
28
+
29
+ class LiveReload extends ServiceProvider {
30
+ static manifest={
31
+ name: "Clovie LiveReload",
32
+ namespace: "liveReload",
33
+ version: "1.0.0"
34
+ };
35
+ #io;
36
+ #reloading=!1;
37
+ getter() {
38
+ return {
39
+ io: () => this.#io
40
+ };
41
+ }
42
+ actions() {
43
+ return {
44
+ initializeServer: async server => {
45
+ const log = this.useContext("log");
46
+ "development" === this.config?.mode && await this.#setupSocketIO(server, log);
47
+ },
48
+ notifyReload: () => {
49
+ this.#reloading || (this.#reloading = !0, queueMacrotask(() => {
50
+ this.#reloading = !1, this.#io.emit("reload");
51
+ }));
52
+ },
53
+ injectLiveReloadScript: async (renderedContent, config) => {
54
+ const lastBodyIndex = renderedContent.lastIndexOf("</body>");
55
+ if (-1 !== lastBodyIndex) {
56
+ const scriptConfig = {
57
+ mode: config.mode || "development",
58
+ port: config.port || 3e3
59
+ };
60
+ try {
61
+ renderedContent = renderedContent.substring(0, lastBodyIndex) + this.#liveReloadScript(scriptConfig) + "\n" + renderedContent.substring(lastBodyIndex);
62
+ } catch (err) {
63
+ console.warn("āš ļø Could not load live reload script:", err.message);
64
+ }
65
+ }
66
+ return renderedContent;
67
+ }
68
+ };
69
+ }
70
+ async #setupSocketIO(server, log) {
71
+ try {
72
+ await new Promise(resolve => setTimeout(resolve, 100)), log.debug("Setting up Socket.IO..."),
73
+ this.#io = new Server(server, {
74
+ cors: {
75
+ origin: "*",
76
+ methods: [ "GET", "POST" ]
77
+ },
78
+ transports: [ "polling", "websocket" ],
79
+ allowEIO3: !0
80
+ }), this.#io.on("connection", socket => {
81
+ log.debug(`Client connected: ${socket.id}`), socket.on("disconnect", reason => {
82
+ log.debug(`Client disconnected: ${socket.id} - ${reason}`);
83
+ }), socket.on("error", error => {
84
+ log.error("Socket error:", error);
85
+ });
86
+ }), log.info("Socket.IO server ready");
87
+ } catch (error) {
88
+ log.error("Error setting up Socket.IO:", error);
89
+ }
90
+ }
91
+ #liveReloadScript=config => `\x3c!-- Live Reload Script (Development Mode Only) --\x3e\n<script src="https://cdn.socket.io/4.7.4/socket.io.min.js"><\/script>\n<script>\n (function() {\n const config = ${JSON.stringify(config)};\n \n console.log('Initializing live reload with config:', config);\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>`;
92
+ }
93
+
94
+ export { LiveReload };
95
+ //# sourceMappingURL=LiveReload-CGbacq3U.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LiveReload-CGbacq3U.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) => {\n const log = this.useContext('log');\n if (this.config?.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 this.#io.emit('reload')\n });\n },\n injectLiveReloadScript: async (renderedContent, config) => {\n const lastBodyIndex = renderedContent.lastIndexOf('</body>');\n if (lastBodyIndex !== -1) {\n const scriptConfig = { \n mode: config.mode || 'development', \n port: config.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 = (config) => `<!-- 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 config = ${JSON.stringify(config)};\n \n console.log('Initializing live reload with config:', config);\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","log","useContext","config","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,MAAOC;gBACvB,MAAMC,MAAML,KAAKM,WAAW;gBACF,kBAAtBN,KAAKO,QAAQC,cACTR,MAAKS,cAAeL,QAAQC;;YAGtCK,cAAc;gBACRV,MAAKF,cACTE,MAAKF,aAAa,GAElBa,eAAe;oBACbX,MAAKF,aAAa,GAClBE,MAAKH,GAAIe,KAAK;;;YAGlBC,wBAAwBV,OAAOW,iBAAiBP;gBAC9C,MAAMQ,gBAAgBD,gBAAgBE,YAAY;gBAClD,KAAsB,MAAlBD,eAAsB;oBACxB,MAAME,eAAe;wBACnBT,MAAMD,OAAOC,QAAQ;wBACrBU,MAAMX,OAAOW,QAAQ;;oBAGvB;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,QAAQC;QAC3B;kBAEQ,IAAIoB,QAAQC,WAAWC,WAAWD,SAAS,OAEjDrB,IAAIuB,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;gBACzB/B,IAAIuB,MAAM,qBAAqBQ,OAAOC,OAEtCD,OAAOD,GAAG,cAAeG;oBACvBjC,IAAIuB,MAAM,wBAAwBQ,OAAOC,QAAQC;oBAGnDF,OAAOD,GAAG,SAAUI;oBAClBlC,IAAIkC,MAAM,iBAAiBA;;gBAI/BlC,IAAImC,KAAK;AACX,UAAE,OAAOD;YACPlC,IAAIkC,MAAM,+BAA+BA;AAC3C;AACF;IAEAnB,kBAAqBb,UAAW,mLAIbkC,KAAKC,UAAUnC;;;"}