zero-query 1.0.9 → 1.2.0
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/LICENSE +21 -21
- package/README.md +2 -0
- package/cli/args.js +33 -33
- package/cli/commands/build-api.js +443 -0
- package/cli/commands/build.js +254 -216
- package/cli/commands/bundle.js +1228 -1183
- package/cli/commands/create.js +137 -121
- package/cli/commands/dev/devtools/index.js +56 -56
- package/cli/commands/dev/devtools/js/components.js +49 -49
- package/cli/commands/dev/devtools/js/core.js +423 -423
- package/cli/commands/dev/devtools/js/elements.js +421 -421
- package/cli/commands/dev/devtools/js/network.js +166 -166
- package/cli/commands/dev/devtools/js/performance.js +73 -73
- package/cli/commands/dev/devtools/js/router.js +105 -105
- package/cli/commands/dev/devtools/js/source.js +132 -132
- package/cli/commands/dev/devtools/js/stats.js +35 -35
- package/cli/commands/dev/devtools/js/tabs.js +79 -79
- package/cli/commands/dev/devtools/panel.html +95 -95
- package/cli/commands/dev/devtools/styles.css +244 -244
- package/cli/commands/dev/index.js +107 -107
- package/cli/commands/dev/logger.js +75 -75
- package/cli/commands/dev/overlay.js +858 -858
- package/cli/commands/dev/server.js +220 -167
- package/cli/commands/dev/validator.js +94 -94
- package/cli/commands/dev/watcher.js +172 -172
- package/cli/help.js +114 -112
- package/cli/index.js +52 -52
- package/cli/scaffold/default/LICENSE +21 -21
- package/cli/scaffold/default/app/app.js +207 -207
- package/cli/scaffold/default/app/components/about.js +201 -201
- package/cli/scaffold/default/app/components/api-demo.js +143 -143
- package/cli/scaffold/default/app/components/contact-card.js +231 -231
- package/cli/scaffold/default/app/components/contacts/contacts.css +706 -706
- package/cli/scaffold/default/app/components/contacts/contacts.html +200 -200
- package/cli/scaffold/default/app/components/contacts/contacts.js +196 -196
- package/cli/scaffold/default/app/components/counter.js +127 -127
- package/cli/scaffold/default/app/components/home.js +249 -249
- package/cli/scaffold/default/app/components/not-found.js +16 -16
- package/cli/scaffold/default/app/components/playground/playground.css +115 -115
- package/cli/scaffold/default/app/components/playground/playground.html +161 -161
- package/cli/scaffold/default/app/components/playground/playground.js +116 -116
- package/cli/scaffold/default/app/components/todos.js +225 -225
- package/cli/scaffold/default/app/components/toolkit/toolkit.css +97 -97
- package/cli/scaffold/default/app/components/toolkit/toolkit.html +146 -146
- package/cli/scaffold/default/app/components/toolkit/toolkit.js +280 -280
- package/cli/scaffold/default/app/routes.js +15 -15
- package/cli/scaffold/default/app/store.js +101 -101
- package/cli/scaffold/default/global.css +552 -552
- package/cli/scaffold/default/index.html +99 -99
- package/cli/scaffold/minimal/app/app.js +85 -85
- package/cli/scaffold/minimal/app/components/about.js +68 -68
- package/cli/scaffold/minimal/app/components/counter.js +122 -122
- package/cli/scaffold/minimal/app/components/home.js +68 -68
- package/cli/scaffold/minimal/app/components/not-found.js +16 -16
- package/cli/scaffold/minimal/app/routes.js +9 -9
- package/cli/scaffold/minimal/app/store.js +36 -36
- package/cli/scaffold/minimal/global.css +300 -300
- package/cli/scaffold/minimal/index.html +44 -44
- package/cli/scaffold/ssr/app/app.js +41 -41
- package/cli/scaffold/ssr/app/components/about.js +55 -55
- package/cli/scaffold/ssr/app/components/blog/index.js +65 -65
- package/cli/scaffold/ssr/app/components/blog/post.js +86 -86
- package/cli/scaffold/ssr/app/components/home.js +37 -37
- package/cli/scaffold/ssr/app/components/not-found.js +15 -15
- package/cli/scaffold/ssr/app/routes.js +8 -8
- package/cli/scaffold/ssr/global.css +228 -228
- package/cli/scaffold/ssr/index.html +37 -37
- package/cli/scaffold/ssr/package.json +8 -8
- package/cli/scaffold/ssr/server/data/posts.js +144 -144
- package/cli/scaffold/ssr/server/index.js +213 -213
- package/cli/scaffold/webrtc/app/app.js +11 -0
- package/cli/scaffold/webrtc/app/components/video-room.js +295 -0
- package/cli/scaffold/webrtc/app/lib/room.js +252 -0
- package/cli/scaffold/webrtc/assets/.gitkeep +0 -0
- package/cli/scaffold/webrtc/global.css +250 -0
- package/cli/scaffold/webrtc/index.html +21 -0
- package/cli/utils.js +305 -287
- package/dist/API.md +7264 -0
- package/dist/zquery.dist.zip +0 -0
- package/dist/zquery.js +10313 -6252
- package/dist/zquery.min.js +8 -601
- package/index.d.ts +570 -365
- package/index.js +311 -232
- package/package.json +76 -69
- package/src/component.js +1709 -1454
- package/src/core.js +921 -921
- package/src/diff.js +497 -497
- package/src/errors.js +209 -209
- package/src/expression.js +922 -922
- package/src/http.js +242 -242
- package/src/package.json +1 -1
- package/src/reactive.js +255 -254
- package/src/router.js +843 -773
- package/src/ssr.js +418 -418
- package/src/store.js +318 -272
- package/src/utils.js +515 -515
- package/src/webrtc/e2ee.js +351 -0
- package/src/webrtc/errors.js +116 -0
- package/src/webrtc/ice.js +301 -0
- package/src/webrtc/index.js +131 -0
- package/src/webrtc/joinToken.js +119 -0
- package/src/webrtc/observe.js +172 -0
- package/src/webrtc/peer.js +351 -0
- package/src/webrtc/reactive.js +268 -0
- package/src/webrtc/room.js +625 -0
- package/src/webrtc/sdp.js +302 -0
- package/src/webrtc/sfu/index.js +43 -0
- package/src/webrtc/sfu/livekit.js +131 -0
- package/src/webrtc/sfu/mediasoup.js +150 -0
- package/src/webrtc/signaling.js +373 -0
- package/src/webrtc/turn.js +237 -0
- package/tests/_helpers/webrtcFakes.js +289 -0
- package/tests/audit.test.js +4158 -4158
- package/tests/cli.test.js +1136 -1023
- package/tests/compare.test.js +497 -0
- package/tests/component.test.js +3969 -3938
- package/tests/core.test.js +1910 -1910
- package/tests/dev-server.test.js +489 -0
- package/tests/diff.test.js +1416 -1416
- package/tests/docs.test.js +1664 -0
- package/tests/electron-features.test.js +864 -0
- package/tests/errors.test.js +619 -619
- package/tests/expression.test.js +1056 -1056
- package/tests/http.test.js +648 -648
- package/tests/reactive.test.js +819 -819
- package/tests/router.test.js +2327 -2327
- package/tests/ssr.test.js +870 -870
- package/tests/store.test.js +830 -830
- package/tests/test-minifier.js +153 -153
- package/tests/test-ssr.js +27 -27
- package/tests/utils.test.js +1377 -1377
- package/tests/webrtc/e2ee.test.js +283 -0
- package/tests/webrtc/ice.test.js +202 -0
- package/tests/webrtc/joinToken.test.js +89 -0
- package/tests/webrtc/observe.test.js +111 -0
- package/tests/webrtc/peer.test.js +373 -0
- package/tests/webrtc/reactive.test.js +235 -0
- package/tests/webrtc/room.test.js +406 -0
- package/tests/webrtc/sdp.test.js +151 -0
- package/tests/webrtc/sfu-livekit.test.js +119 -0
- package/tests/webrtc/sfu.test.js +160 -0
- package/tests/webrtc/signaling.test.js +251 -0
- package/tests/webrtc/turn.test.js +256 -0
- package/types/collection.d.ts +383 -383
- package/types/component.d.ts +186 -186
- package/types/errors.d.ts +135 -135
- package/types/http.d.ts +92 -92
- package/types/misc.d.ts +201 -201
- package/types/reactive.d.ts +98 -98
- package/types/router.d.ts +190 -190
- package/types/ssr.d.ts +102 -102
- package/types/store.d.ts +146 -145
- package/types/utils.d.ts +245 -245
- package/types/webrtc.d.ts +653 -0
|
@@ -1,172 +1,172 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* cli/commands/dev/watcher.js - File system watcher
|
|
3
|
-
*
|
|
4
|
-
* Recursively watches the project root for file changes, validates
|
|
5
|
-
* JS files for syntax errors, and broadcasts reload / CSS hot-swap /
|
|
6
|
-
* error events through the SSE pool.
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
'use strict';
|
|
10
|
-
|
|
11
|
-
const fs = require('fs');
|
|
12
|
-
const path = require('path');
|
|
13
|
-
|
|
14
|
-
const { validateJS } = require('./validator');
|
|
15
|
-
const { logCSS, logReload, logError } = require('./logger');
|
|
16
|
-
|
|
17
|
-
const IGNORE_DIRS = new Set(['node_modules', '.git', 'dist', '.cache']);
|
|
18
|
-
|
|
19
|
-
// ---------------------------------------------------------------------------
|
|
20
|
-
// Helpers
|
|
21
|
-
// ---------------------------------------------------------------------------
|
|
22
|
-
|
|
23
|
-
function shouldWatch(filename) {
|
|
24
|
-
return !!filename && !filename.startsWith('.');
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
function isIgnored(filepath) {
|
|
28
|
-
return filepath.split(path.sep).some(p => IGNORE_DIRS.has(p));
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Return the file's mtime as a millisecond timestamp, or 0 if unreadable.
|
|
33
|
-
* Used to ignore spurious fs.watch events (Windows fires on reads too).
|
|
34
|
-
*/
|
|
35
|
-
function mtime(filepath) {
|
|
36
|
-
try { return fs.statSync(filepath).mtimeMs; } catch { return 0; }
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
/** Recursively collect every directory under `dir` (excluding ignored). */
|
|
40
|
-
function collectWatchDirs(dir) {
|
|
41
|
-
const dirs = [dir];
|
|
42
|
-
try {
|
|
43
|
-
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
44
|
-
if (!entry.isDirectory() || IGNORE_DIRS.has(entry.name)) continue;
|
|
45
|
-
dirs.push(...collectWatchDirs(path.join(dir, entry.name)));
|
|
46
|
-
}
|
|
47
|
-
} catch { /* unreadable dir - skip */ }
|
|
48
|
-
return dirs;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
// ---------------------------------------------------------------------------
|
|
52
|
-
// Watcher factory
|
|
53
|
-
// ---------------------------------------------------------------------------
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* Start watching `root` for file changes.
|
|
57
|
-
*
|
|
58
|
-
* @param {object} opts
|
|
59
|
-
* @param {string} opts.root - absolute project root
|
|
60
|
-
* @param {SSEPool} opts.pool - SSE broadcast pool
|
|
61
|
-
* @returns {{ dirs: string[], destroy: Function }}
|
|
62
|
-
*/
|
|
63
|
-
function startWatcher({ root, pool, bundleMode, serveRoot }) {
|
|
64
|
-
const watchDirs = collectWatchDirs(root);
|
|
65
|
-
const watchers = [];
|
|
66
|
-
|
|
67
|
-
let debounceTimer;
|
|
68
|
-
let currentError = null; // track which file has an active error
|
|
69
|
-
let bundleTimer = null; // debounce for bundle rebuilds
|
|
70
|
-
|
|
71
|
-
// Track file mtimes so we only react to genuine writes.
|
|
72
|
-
// On Windows, fs.watch fires on reads/access too, which causes
|
|
73
|
-
// spurious reloads the first time the server serves a file.
|
|
74
|
-
// We seed the cache with current mtimes so the first real save
|
|
75
|
-
// (which changes the mtime) is always detected.
|
|
76
|
-
const mtimeCache = new Map();
|
|
77
|
-
for (const d of watchDirs) {
|
|
78
|
-
try {
|
|
79
|
-
for (const entry of fs.readdirSync(d, { withFileTypes: true })) {
|
|
80
|
-
if (entry.isFile()) {
|
|
81
|
-
const fp = path.join(d, entry.name);
|
|
82
|
-
const mt = mtime(fp);
|
|
83
|
-
if (mt) mtimeCache.set(fp, mt);
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
} catch { /* skip */ }
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
for (const dir of watchDirs) {
|
|
90
|
-
try {
|
|
91
|
-
const watcher = fs.watch(dir, (_, filename) => {
|
|
92
|
-
if (!shouldWatch(filename)) return;
|
|
93
|
-
const fullPath = path.join(dir, filename || '');
|
|
94
|
-
if (isIgnored(fullPath)) return;
|
|
95
|
-
|
|
96
|
-
clearTimeout(debounceTimer);
|
|
97
|
-
debounceTimer = setTimeout(() => {
|
|
98
|
-
// Skip if the file hasn't actually been modified
|
|
99
|
-
const mt = mtime(fullPath);
|
|
100
|
-
if (mt === 0) return; // deleted or unreadable
|
|
101
|
-
const prev = mtimeCache.get(fullPath);
|
|
102
|
-
mtimeCache.set(fullPath, mt);
|
|
103
|
-
if (prev !== undefined && mt === prev) return; // unchanged
|
|
104
|
-
|
|
105
|
-
const rel = path.relative(root, fullPath).replace(/\\/g, '/');
|
|
106
|
-
const ext = path.extname(filename).toLowerCase();
|
|
107
|
-
|
|
108
|
-
// ---- CSS hot-swap ----
|
|
109
|
-
if (ext === '.css') {
|
|
110
|
-
logCSS(rel);
|
|
111
|
-
pool.broadcast('css', rel);
|
|
112
|
-
return;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
// ---- JS syntax check ----
|
|
116
|
-
if (ext === '.js') {
|
|
117
|
-
const err = validateJS(fullPath, rel);
|
|
118
|
-
if (err) {
|
|
119
|
-
currentError = rel;
|
|
120
|
-
logError(err);
|
|
121
|
-
pool.broadcast('error:syntax', JSON.stringify(err));
|
|
122
|
-
return;
|
|
123
|
-
}
|
|
124
|
-
// File was fixed - clear previous overlay
|
|
125
|
-
if (currentError === rel) {
|
|
126
|
-
currentError = null;
|
|
127
|
-
pool.broadcast('error:clear', '');
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
// ---- Full reload ----
|
|
132
|
-
if (bundleMode) {
|
|
133
|
-
// Debounce bundle rebuilds (500ms) so rapid saves don't spam
|
|
134
|
-
clearTimeout(bundleTimer);
|
|
135
|
-
bundleTimer = setTimeout(() => {
|
|
136
|
-
try {
|
|
137
|
-
const bundleFn = require('../bundle');
|
|
138
|
-
const { args: cliArgs } = require('../../args');
|
|
139
|
-
const savedArgs = cliArgs.slice();
|
|
140
|
-
cliArgs.length = 0;
|
|
141
|
-
cliArgs.push('bundle');
|
|
142
|
-
const prevCwd = process.cwd();
|
|
143
|
-
process.chdir(root);
|
|
144
|
-
bundleFn();
|
|
145
|
-
process.chdir(prevCwd);
|
|
146
|
-
cliArgs.length = 0;
|
|
147
|
-
savedArgs.forEach(a => cliArgs.push(a));
|
|
148
|
-
logReload(rel + ' (rebuilt)');
|
|
149
|
-
pool.broadcast('reload', rel);
|
|
150
|
-
} catch (err) {
|
|
151
|
-
console.error(' Bundle rebuild failed:', err.message);
|
|
152
|
-
}
|
|
153
|
-
}, 500);
|
|
154
|
-
return;
|
|
155
|
-
}
|
|
156
|
-
logReload(rel);
|
|
157
|
-
pool.broadcast('reload', rel);
|
|
158
|
-
}, 100);
|
|
159
|
-
});
|
|
160
|
-
watchers.push(watcher);
|
|
161
|
-
} catch { /* dir became inaccessible - skip */ }
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
function destroy() {
|
|
165
|
-
clearTimeout(debounceTimer);
|
|
166
|
-
watchers.forEach(w => w.close());
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
return { dirs: watchDirs, destroy };
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
module.exports = { startWatcher, collectWatchDirs };
|
|
1
|
+
/**
|
|
2
|
+
* cli/commands/dev/watcher.js - File system watcher
|
|
3
|
+
*
|
|
4
|
+
* Recursively watches the project root for file changes, validates
|
|
5
|
+
* JS files for syntax errors, and broadcasts reload / CSS hot-swap /
|
|
6
|
+
* error events through the SSE pool.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
'use strict';
|
|
10
|
+
|
|
11
|
+
const fs = require('fs');
|
|
12
|
+
const path = require('path');
|
|
13
|
+
|
|
14
|
+
const { validateJS } = require('./validator');
|
|
15
|
+
const { logCSS, logReload, logError } = require('./logger');
|
|
16
|
+
|
|
17
|
+
const IGNORE_DIRS = new Set(['node_modules', '.git', 'dist', '.cache']);
|
|
18
|
+
|
|
19
|
+
// ---------------------------------------------------------------------------
|
|
20
|
+
// Helpers
|
|
21
|
+
// ---------------------------------------------------------------------------
|
|
22
|
+
|
|
23
|
+
function shouldWatch(filename) {
|
|
24
|
+
return !!filename && !filename.startsWith('.');
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function isIgnored(filepath) {
|
|
28
|
+
return filepath.split(path.sep).some(p => IGNORE_DIRS.has(p));
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Return the file's mtime as a millisecond timestamp, or 0 if unreadable.
|
|
33
|
+
* Used to ignore spurious fs.watch events (Windows fires on reads too).
|
|
34
|
+
*/
|
|
35
|
+
function mtime(filepath) {
|
|
36
|
+
try { return fs.statSync(filepath).mtimeMs; } catch { return 0; }
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/** Recursively collect every directory under `dir` (excluding ignored). */
|
|
40
|
+
function collectWatchDirs(dir) {
|
|
41
|
+
const dirs = [dir];
|
|
42
|
+
try {
|
|
43
|
+
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
44
|
+
if (!entry.isDirectory() || IGNORE_DIRS.has(entry.name)) continue;
|
|
45
|
+
dirs.push(...collectWatchDirs(path.join(dir, entry.name)));
|
|
46
|
+
}
|
|
47
|
+
} catch { /* unreadable dir - skip */ }
|
|
48
|
+
return dirs;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// ---------------------------------------------------------------------------
|
|
52
|
+
// Watcher factory
|
|
53
|
+
// ---------------------------------------------------------------------------
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Start watching `root` for file changes.
|
|
57
|
+
*
|
|
58
|
+
* @param {object} opts
|
|
59
|
+
* @param {string} opts.root - absolute project root
|
|
60
|
+
* @param {SSEPool} opts.pool - SSE broadcast pool
|
|
61
|
+
* @returns {{ dirs: string[], destroy: Function }}
|
|
62
|
+
*/
|
|
63
|
+
function startWatcher({ root, pool, bundleMode, serveRoot }) {
|
|
64
|
+
const watchDirs = collectWatchDirs(root);
|
|
65
|
+
const watchers = [];
|
|
66
|
+
|
|
67
|
+
let debounceTimer;
|
|
68
|
+
let currentError = null; // track which file has an active error
|
|
69
|
+
let bundleTimer = null; // debounce for bundle rebuilds
|
|
70
|
+
|
|
71
|
+
// Track file mtimes so we only react to genuine writes.
|
|
72
|
+
// On Windows, fs.watch fires on reads/access too, which causes
|
|
73
|
+
// spurious reloads the first time the server serves a file.
|
|
74
|
+
// We seed the cache with current mtimes so the first real save
|
|
75
|
+
// (which changes the mtime) is always detected.
|
|
76
|
+
const mtimeCache = new Map();
|
|
77
|
+
for (const d of watchDirs) {
|
|
78
|
+
try {
|
|
79
|
+
for (const entry of fs.readdirSync(d, { withFileTypes: true })) {
|
|
80
|
+
if (entry.isFile()) {
|
|
81
|
+
const fp = path.join(d, entry.name);
|
|
82
|
+
const mt = mtime(fp);
|
|
83
|
+
if (mt) mtimeCache.set(fp, mt);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
} catch { /* skip */ }
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
for (const dir of watchDirs) {
|
|
90
|
+
try {
|
|
91
|
+
const watcher = fs.watch(dir, (_, filename) => {
|
|
92
|
+
if (!shouldWatch(filename)) return;
|
|
93
|
+
const fullPath = path.join(dir, filename || '');
|
|
94
|
+
if (isIgnored(fullPath)) return;
|
|
95
|
+
|
|
96
|
+
clearTimeout(debounceTimer);
|
|
97
|
+
debounceTimer = setTimeout(() => {
|
|
98
|
+
// Skip if the file hasn't actually been modified
|
|
99
|
+
const mt = mtime(fullPath);
|
|
100
|
+
if (mt === 0) return; // deleted or unreadable
|
|
101
|
+
const prev = mtimeCache.get(fullPath);
|
|
102
|
+
mtimeCache.set(fullPath, mt);
|
|
103
|
+
if (prev !== undefined && mt === prev) return; // unchanged
|
|
104
|
+
|
|
105
|
+
const rel = path.relative(root, fullPath).replace(/\\/g, '/');
|
|
106
|
+
const ext = path.extname(filename).toLowerCase();
|
|
107
|
+
|
|
108
|
+
// ---- CSS hot-swap ----
|
|
109
|
+
if (ext === '.css') {
|
|
110
|
+
logCSS(rel);
|
|
111
|
+
pool.broadcast('css', rel);
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// ---- JS syntax check ----
|
|
116
|
+
if (ext === '.js') {
|
|
117
|
+
const err = validateJS(fullPath, rel);
|
|
118
|
+
if (err) {
|
|
119
|
+
currentError = rel;
|
|
120
|
+
logError(err);
|
|
121
|
+
pool.broadcast('error:syntax', JSON.stringify(err));
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
// File was fixed - clear previous overlay
|
|
125
|
+
if (currentError === rel) {
|
|
126
|
+
currentError = null;
|
|
127
|
+
pool.broadcast('error:clear', '');
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// ---- Full reload ----
|
|
132
|
+
if (bundleMode) {
|
|
133
|
+
// Debounce bundle rebuilds (500ms) so rapid saves don't spam
|
|
134
|
+
clearTimeout(bundleTimer);
|
|
135
|
+
bundleTimer = setTimeout(() => {
|
|
136
|
+
try {
|
|
137
|
+
const bundleFn = require('../bundle');
|
|
138
|
+
const { args: cliArgs } = require('../../args');
|
|
139
|
+
const savedArgs = cliArgs.slice();
|
|
140
|
+
cliArgs.length = 0;
|
|
141
|
+
cliArgs.push('bundle');
|
|
142
|
+
const prevCwd = process.cwd();
|
|
143
|
+
process.chdir(root);
|
|
144
|
+
bundleFn();
|
|
145
|
+
process.chdir(prevCwd);
|
|
146
|
+
cliArgs.length = 0;
|
|
147
|
+
savedArgs.forEach(a => cliArgs.push(a));
|
|
148
|
+
logReload(rel + ' (rebuilt)');
|
|
149
|
+
pool.broadcast('reload', rel);
|
|
150
|
+
} catch (err) {
|
|
151
|
+
console.error(' Bundle rebuild failed:', err.message);
|
|
152
|
+
}
|
|
153
|
+
}, 500);
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
logReload(rel);
|
|
157
|
+
pool.broadcast('reload', rel);
|
|
158
|
+
}, 100);
|
|
159
|
+
});
|
|
160
|
+
watchers.push(watcher);
|
|
161
|
+
} catch { /* dir became inaccessible - skip */ }
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
function destroy() {
|
|
165
|
+
clearTimeout(debounceTimer);
|
|
166
|
+
watchers.forEach(w => w.close());
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
return { dirs: watchDirs, destroy };
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
module.exports = { startWatcher, collectWatchDirs };
|
package/cli/help.js
CHANGED
|
@@ -1,112 +1,114 @@
|
|
|
1
|
-
// cli/help.js - show CLI usage information
|
|
2
|
-
|
|
3
|
-
function showHelp() {
|
|
4
|
-
console.log(`
|
|
5
|
-
zQuery CLI \u2014 create, dev, bundle & build
|
|
6
|
-
|
|
7
|
-
COMMANDS
|
|
8
|
-
|
|
9
|
-
create [dir] Scaffold a new zQuery project
|
|
10
|
-
Creates index.html, global.css, app/, assets/ in the target directory
|
|
11
|
-
(defaults to the current directory)
|
|
12
|
-
--minimal, -m Use the minimal template (home, counter, about)
|
|
13
|
-
instead of the full-featured default scaffold
|
|
14
|
-
--ssr, -s Use the SSR template - includes server/index.js
|
|
15
|
-
SSR HTTP server with shared component definitions,
|
|
16
|
-
blog with param routing, JSON API, and SEO metadata
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
--
|
|
22
|
-
|
|
23
|
-
--
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
--
|
|
35
|
-
--
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
•
|
|
50
|
-
•
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
•
|
|
76
|
-
|
|
77
|
-
•
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
1
|
+
// cli/help.js - show CLI usage information
|
|
2
|
+
|
|
3
|
+
function showHelp() {
|
|
4
|
+
console.log(`
|
|
5
|
+
zQuery CLI \u2014 create, dev, bundle & build
|
|
6
|
+
|
|
7
|
+
COMMANDS
|
|
8
|
+
|
|
9
|
+
create [dir] Scaffold a new zQuery project
|
|
10
|
+
Creates index.html, global.css, app/, assets/ in the target directory
|
|
11
|
+
(defaults to the current directory)
|
|
12
|
+
--minimal, -m Use the minimal template (home, counter, about)
|
|
13
|
+
instead of the full-featured default scaffold
|
|
14
|
+
--ssr, -s Use the SSR template - includes server/index.js
|
|
15
|
+
SSR HTTP server with shared component definitions,
|
|
16
|
+
blog with param routing, JSON API, and SEO metadata
|
|
17
|
+
--webrtc-demo, -w Use the WebRTC demo template - one-page video room
|
|
18
|
+
powered by $.webrtc.join() against a zero-server hub
|
|
19
|
+
|
|
20
|
+
dev [root] Start a dev server with live-reload
|
|
21
|
+
--port, -p <number> Port number (default: 3100)
|
|
22
|
+
--index, -i <file> Index HTML file (default: index.html)
|
|
23
|
+
--no-intercept Disable auto-resolution of zquery.min.js
|
|
24
|
+
(serve the on-disk vendor copy instead)
|
|
25
|
+
--bundle, -b Serve the bundled build (runs bundler first,
|
|
26
|
+
serves from dist/server/, auto-rebuilds on save)
|
|
27
|
+
|
|
28
|
+
Includes error overlay: syntax errors are
|
|
29
|
+
caught on save and shown as a full-screen
|
|
30
|
+
overlay in the browser. Runtime errors and
|
|
31
|
+
unhandled rejections are also captured.
|
|
32
|
+
|
|
33
|
+
bundle [dir|file] Bundle app ES modules into a single file
|
|
34
|
+
--out, -o <path> Output directory (default: dist/ next to HTML file)
|
|
35
|
+
--index, -i <file> Index HTML file (default: auto-detected)
|
|
36
|
+
--minimal, -m Only output HTML, bundled JS, and global CSS (skip static assets)
|
|
37
|
+
--global-css <path> Override global CSS input (default: first <link> in HTML)
|
|
38
|
+
|
|
39
|
+
build Build the zQuery library \u2192 dist/ --watch, -w Watch src/ and rebuild on changes (must be run from the project root where src/ lives)
|
|
40
|
+
|
|
41
|
+
SMART DEFAULTS
|
|
42
|
+
|
|
43
|
+
The bundler works with zero flags for typical projects:
|
|
44
|
+
\u2022 Entry is auto-detected with strict precedence:
|
|
45
|
+
1. index.html first, then other .html files
|
|
46
|
+
2. Within HTML: module script pointing to app.js, else first module script
|
|
47
|
+
3. JS scan: $.router( first (entry point), then $.mount( / $.store(
|
|
48
|
+
4. Convention fallbacks (app/app.js, scripts/app.js, app.js, etc.)
|
|
49
|
+
• Passing a directory auto-detects the entry; passing a file uses it directly
|
|
50
|
+
• zquery.min.js is always embedded (auto-built from source if not found)
|
|
51
|
+
• HTML file is auto-detected (any .html, not just index.html)
|
|
52
|
+
• Output goes to dist/server/ and dist/local/ next to the detected HTML file
|
|
53
|
+
|
|
54
|
+
OUTPUT
|
|
55
|
+
|
|
56
|
+
The bundler produces two self-contained sub-directories:
|
|
57
|
+
|
|
58
|
+
dist/server/ deploy to your web server
|
|
59
|
+
index.html has <base href="/"> for SPA deep routes
|
|
60
|
+
z-<entry>.<hash>.js readable bundle
|
|
61
|
+
z-<entry>.<hash>.min.js minified bundle
|
|
62
|
+
|
|
63
|
+
dist/local/ open from disk (file://)
|
|
64
|
+
index.html relative paths, no <base> tag
|
|
65
|
+
z-<entry>.<hash>.js same bundle
|
|
66
|
+
|
|
67
|
+
Previous hashed builds are automatically cleaned on each rebuild.
|
|
68
|
+
|
|
69
|
+
DEVELOPMENT
|
|
70
|
+
|
|
71
|
+
zquery dev start a dev server with live-reload (port 3100)
|
|
72
|
+
zquery dev --port 8080 custom port
|
|
73
|
+
|
|
74
|
+
The dev server includes a full-screen error overlay:
|
|
75
|
+
• JS files are syntax-checked on save - errors block reload
|
|
76
|
+
and show an overlay with exact file, line:column, and code frame
|
|
77
|
+
• Runtime errors and unhandled rejections are also captured
|
|
78
|
+
• The overlay auto-clears when the file is fixed and saved
|
|
79
|
+
• Press Esc or click × to dismiss manually
|
|
80
|
+
|
|
81
|
+
EXAMPLES
|
|
82
|
+
|
|
83
|
+
# Scaffold a new project and start developing
|
|
84
|
+
zquery create my-app && zquery dev my-app
|
|
85
|
+
|
|
86
|
+
# Start dev server with live-reload
|
|
87
|
+
zquery dev my-app
|
|
88
|
+
|
|
89
|
+
# Build the library only
|
|
90
|
+
zquery build
|
|
91
|
+
|
|
92
|
+
# Bundle an app from the project root
|
|
93
|
+
zquery bundle my-app/
|
|
94
|
+
|
|
95
|
+
# Pass a direct entry file (skip auto-detection)
|
|
96
|
+
zquery bundle my-app/app/main.js
|
|
97
|
+
|
|
98
|
+
# Custom output directory
|
|
99
|
+
zquery bundle my-app/ -o build/
|
|
100
|
+
|
|
101
|
+
# Minimal build (HTML + JS + global CSS, no static asset copying)
|
|
102
|
+
zquery bundle my-app/ --minimal
|
|
103
|
+
|
|
104
|
+
# Dev server with a custom index page
|
|
105
|
+
zquery dev my-app/ --index home.html
|
|
106
|
+
|
|
107
|
+
The bundler walks the ES module import graph starting from the entry
|
|
108
|
+
file, topologically sorts dependencies, strips import/export syntax,
|
|
109
|
+
and concatenates everything into a single IIFE with content-hashed
|
|
110
|
+
filenames for cache-busting. No dependencies needed \u2014 just Node.js.
|
|
111
|
+
`);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
module.exports = showHelp;
|