juxscript 1.1.0 → 1.1.2

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.
@@ -0,0 +1,171 @@
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+ import {
4
+ copyLibToOutput,
5
+ bundleJuxFilesToRouter,
6
+ generateIndexHtml
7
+ } from './compiler.js';
8
+
9
+ let isRebuilding = false;
10
+ let rebuildQueued = false;
11
+
12
+ /**
13
+ * Find all .jux files in a directory
14
+ */
15
+ function findJuxFiles(dir, fileList = []) {
16
+ if (!fs.existsSync(dir)) return fileList;
17
+
18
+ const files = fs.readdirSync(dir);
19
+
20
+ files.forEach(file => {
21
+ const filePath = path.join(dir, file);
22
+ const stat = fs.statSync(filePath);
23
+
24
+ if (stat.isDirectory()) {
25
+ if (file !== 'node_modules' && file !== 'jux-dist' && file !== '.git' && file !== 'server') {
26
+ findJuxFiles(filePath, fileList);
27
+ }
28
+ } else if (file.endsWith('.jux')) {
29
+ fileList.push(filePath);
30
+ }
31
+ });
32
+
33
+ return fileList;
34
+ }
35
+
36
+ /**
37
+ * Full rebuild of the entire bundle
38
+ */
39
+ async function fullRebuild(juxSource, distDir) {
40
+ const startTime = performance.now(); // āœ… Start timing
41
+ console.log('\nšŸ”„ Rebuilding bundle...');
42
+
43
+ try {
44
+ // Find all .jux files
45
+ const projectJuxFiles = findJuxFiles(juxSource);
46
+ console.log(` Found ${projectJuxFiles.length} .jux file(s)`);
47
+
48
+ // āœ… Time the bundling step
49
+ const bundleStartTime = performance.now();
50
+
51
+ // Bundle all files
52
+ const mainJsFilename = await bundleJuxFilesToRouter(juxSource, distDir, {
53
+ routePrefix: ''
54
+ });
55
+
56
+ const bundleTime = performance.now() - bundleStartTime;
57
+
58
+ // āœ… Time the route generation step
59
+ const routeStartTime = performance.now();
60
+
61
+ // Generate routes for index.html
62
+ const routes = projectJuxFiles.map(juxFile => {
63
+ const relativePath = path.relative(juxSource, juxFile);
64
+ const parsedPath = path.parse(relativePath);
65
+
66
+ const rawFunctionName = parsedPath.dir
67
+ ? `${parsedPath.dir.replace(/\//g, '_')}_${parsedPath.name}`
68
+ : parsedPath.name;
69
+
70
+ const functionName = rawFunctionName
71
+ .replace(/[-_]/g, ' ')
72
+ .split(' ')
73
+ .map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
74
+ .join('');
75
+
76
+ const routePath = '/' + (parsedPath.dir ? `${parsedPath.dir}/` : '') + parsedPath.name;
77
+
78
+ return {
79
+ path: routePath.replace(/\/+/g, '/'),
80
+ functionName
81
+ };
82
+ });
83
+
84
+ // Generate index.html
85
+ generateIndexHtml(distDir, routes, mainJsFilename);
86
+
87
+ const routeTime = performance.now() - routeStartTime;
88
+ const totalTime = performance.now() - startTime;
89
+
90
+ // āœ… Pretty-print timing breakdown
91
+ console.log(`\nā±ļø Rebuild Performance:`);
92
+ console.log(` Bundle generation: ${bundleTime.toFixed(0)}ms`);
93
+ console.log(` Route/index.html: ${routeTime.toFixed(0)}ms`);
94
+ console.log(` ━━━━━━━━━━━━━━━━━━━━━━━━━━━━`);
95
+ console.log(` Total rebuild: ${totalTime.toFixed(0)}ms`);
96
+
97
+ // āœ… Color-coded performance indicator
98
+ if (totalTime < 100) {
99
+ console.log(` āœ… Lightning fast! ⚔`);
100
+ } else if (totalTime < 500) {
101
+ console.log(` āœ… Fast rebuild`);
102
+ } else if (totalTime < 1000) {
103
+ console.log(` āš ļø Moderate speed`);
104
+ } else {
105
+ console.log(` 🐌 Slow rebuild (consider optimizing)`);
106
+ }
107
+
108
+ console.log(`āœ… Bundle rebuilt: ${mainJsFilename}\n`);
109
+ return true;
110
+
111
+ } catch (err) {
112
+ const failTime = performance.now() - startTime;
113
+ console.error(`āŒ Rebuild failed after ${failTime.toFixed(0)}ms:`, err.message);
114
+ return false;
115
+ }
116
+ }
117
+
118
+ /**
119
+ * Start watching for file changes and rebuild on change
120
+ */
121
+ export function startWatcher(juxSource, distDir, wsClients) {
122
+ console.log(`šŸ‘€ Watching: ${juxSource}`);
123
+
124
+ const watcher = fs.watch(juxSource, { recursive: true }, async (eventType, filename) => {
125
+ // Ignore non-.jux files and certain patterns
126
+ if (!filename ||
127
+ !filename.endsWith('.jux') ||
128
+ filename.includes('node_modules') ||
129
+ filename.includes('jux-dist') ||
130
+ filename.startsWith('.')) {
131
+ return;
132
+ }
133
+
134
+ // Debounce: If already rebuilding, queue another rebuild
135
+ if (isRebuilding) {
136
+ rebuildQueued = true;
137
+ return;
138
+ }
139
+
140
+ isRebuilding = true;
141
+ console.log(`\nšŸ“ File changed: ${filename}`);
142
+
143
+ // Rebuild the entire bundle
144
+ const success = await fullRebuild(juxSource, distDir);
145
+
146
+ isRebuilding = false;
147
+
148
+ // Notify all WebSocket clients to reload
149
+ if (success && wsClients && wsClients.length > 0) {
150
+ console.log(`šŸ”Œ Notifying ${wsClients.length} client(s) to reload`);
151
+
152
+ // āœ… Add small delay to ensure file is fully written
153
+ setTimeout(() => {
154
+ wsClients.forEach(client => {
155
+ if (client.readyState === 1) { // OPEN
156
+ client.send(JSON.stringify({ type: 'reload' }));
157
+ }
158
+ });
159
+ }, 100);
160
+ }
161
+
162
+ // Process queued rebuild if needed
163
+ if (rebuildQueued) {
164
+ rebuildQueued = false;
165
+ console.log('šŸ”„ Processing queued rebuild...');
166
+ setTimeout(() => watcher.emit('change', 'change', filename), 500);
167
+ }
168
+ });
169
+
170
+ return watcher;
171
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "juxscript",
3
- "version": "1.1.00",
3
+ "version": "1.1.2",
4
4
  "type": "module",
5
5
  "description": "A JavaScript UX authorship platform",
6
6
  "main": "index.js",
@@ -19,8 +19,9 @@
19
19
  "./package.json": "./package.json"
20
20
  },
21
21
  "files": [
22
- "lib",
23
22
  "bin",
23
+ "lib",
24
+ "machinery",
24
25
  "index.js",
25
26
  "index.d.ts",
26
27
  "juxconfig.example.js",