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.
- package/machinery/ast.js +347 -0
- package/machinery/build.js +466 -0
- package/machinery/build3.js +159 -0
- package/machinery/bundleAssets.js +0 -0
- package/machinery/bundleJux.js +0 -0
- package/machinery/bundleVendors.js +0 -0
- package/machinery/compiler3.js +628 -0
- package/machinery/config.js +68 -0
- package/machinery/doc-generator.js +136 -0
- package/machinery/imports.js +155 -0
- package/machinery/server.js +166 -0
- package/machinery/ts-shim.js +46 -0
- package/machinery/validators/file-validator.js +123 -0
- package/machinery/watcher.js +171 -0
- package/package.json +3 -2
|
@@ -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.
|
|
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",
|