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.
Files changed (154) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +2 -0
  3. package/cli/args.js +33 -33
  4. package/cli/commands/build-api.js +443 -0
  5. package/cli/commands/build.js +254 -216
  6. package/cli/commands/bundle.js +1228 -1183
  7. package/cli/commands/create.js +137 -121
  8. package/cli/commands/dev/devtools/index.js +56 -56
  9. package/cli/commands/dev/devtools/js/components.js +49 -49
  10. package/cli/commands/dev/devtools/js/core.js +423 -423
  11. package/cli/commands/dev/devtools/js/elements.js +421 -421
  12. package/cli/commands/dev/devtools/js/network.js +166 -166
  13. package/cli/commands/dev/devtools/js/performance.js +73 -73
  14. package/cli/commands/dev/devtools/js/router.js +105 -105
  15. package/cli/commands/dev/devtools/js/source.js +132 -132
  16. package/cli/commands/dev/devtools/js/stats.js +35 -35
  17. package/cli/commands/dev/devtools/js/tabs.js +79 -79
  18. package/cli/commands/dev/devtools/panel.html +95 -95
  19. package/cli/commands/dev/devtools/styles.css +244 -244
  20. package/cli/commands/dev/index.js +107 -107
  21. package/cli/commands/dev/logger.js +75 -75
  22. package/cli/commands/dev/overlay.js +858 -858
  23. package/cli/commands/dev/server.js +220 -167
  24. package/cli/commands/dev/validator.js +94 -94
  25. package/cli/commands/dev/watcher.js +172 -172
  26. package/cli/help.js +114 -112
  27. package/cli/index.js +52 -52
  28. package/cli/scaffold/default/LICENSE +21 -21
  29. package/cli/scaffold/default/app/app.js +207 -207
  30. package/cli/scaffold/default/app/components/about.js +201 -201
  31. package/cli/scaffold/default/app/components/api-demo.js +143 -143
  32. package/cli/scaffold/default/app/components/contact-card.js +231 -231
  33. package/cli/scaffold/default/app/components/contacts/contacts.css +706 -706
  34. package/cli/scaffold/default/app/components/contacts/contacts.html +200 -200
  35. package/cli/scaffold/default/app/components/contacts/contacts.js +196 -196
  36. package/cli/scaffold/default/app/components/counter.js +127 -127
  37. package/cli/scaffold/default/app/components/home.js +249 -249
  38. package/cli/scaffold/default/app/components/not-found.js +16 -16
  39. package/cli/scaffold/default/app/components/playground/playground.css +115 -115
  40. package/cli/scaffold/default/app/components/playground/playground.html +161 -161
  41. package/cli/scaffold/default/app/components/playground/playground.js +116 -116
  42. package/cli/scaffold/default/app/components/todos.js +225 -225
  43. package/cli/scaffold/default/app/components/toolkit/toolkit.css +97 -97
  44. package/cli/scaffold/default/app/components/toolkit/toolkit.html +146 -146
  45. package/cli/scaffold/default/app/components/toolkit/toolkit.js +280 -280
  46. package/cli/scaffold/default/app/routes.js +15 -15
  47. package/cli/scaffold/default/app/store.js +101 -101
  48. package/cli/scaffold/default/global.css +552 -552
  49. package/cli/scaffold/default/index.html +99 -99
  50. package/cli/scaffold/minimal/app/app.js +85 -85
  51. package/cli/scaffold/minimal/app/components/about.js +68 -68
  52. package/cli/scaffold/minimal/app/components/counter.js +122 -122
  53. package/cli/scaffold/minimal/app/components/home.js +68 -68
  54. package/cli/scaffold/minimal/app/components/not-found.js +16 -16
  55. package/cli/scaffold/minimal/app/routes.js +9 -9
  56. package/cli/scaffold/minimal/app/store.js +36 -36
  57. package/cli/scaffold/minimal/global.css +300 -300
  58. package/cli/scaffold/minimal/index.html +44 -44
  59. package/cli/scaffold/ssr/app/app.js +41 -41
  60. package/cli/scaffold/ssr/app/components/about.js +55 -55
  61. package/cli/scaffold/ssr/app/components/blog/index.js +65 -65
  62. package/cli/scaffold/ssr/app/components/blog/post.js +86 -86
  63. package/cli/scaffold/ssr/app/components/home.js +37 -37
  64. package/cli/scaffold/ssr/app/components/not-found.js +15 -15
  65. package/cli/scaffold/ssr/app/routes.js +8 -8
  66. package/cli/scaffold/ssr/global.css +228 -228
  67. package/cli/scaffold/ssr/index.html +37 -37
  68. package/cli/scaffold/ssr/package.json +8 -8
  69. package/cli/scaffold/ssr/server/data/posts.js +144 -144
  70. package/cli/scaffold/ssr/server/index.js +213 -213
  71. package/cli/scaffold/webrtc/app/app.js +11 -0
  72. package/cli/scaffold/webrtc/app/components/video-room.js +295 -0
  73. package/cli/scaffold/webrtc/app/lib/room.js +252 -0
  74. package/cli/scaffold/webrtc/assets/.gitkeep +0 -0
  75. package/cli/scaffold/webrtc/global.css +250 -0
  76. package/cli/scaffold/webrtc/index.html +21 -0
  77. package/cli/utils.js +305 -287
  78. package/dist/API.md +7264 -0
  79. package/dist/zquery.dist.zip +0 -0
  80. package/dist/zquery.js +10313 -6252
  81. package/dist/zquery.min.js +8 -601
  82. package/index.d.ts +570 -365
  83. package/index.js +311 -232
  84. package/package.json +76 -69
  85. package/src/component.js +1709 -1454
  86. package/src/core.js +921 -921
  87. package/src/diff.js +497 -497
  88. package/src/errors.js +209 -209
  89. package/src/expression.js +922 -922
  90. package/src/http.js +242 -242
  91. package/src/package.json +1 -1
  92. package/src/reactive.js +255 -254
  93. package/src/router.js +843 -773
  94. package/src/ssr.js +418 -418
  95. package/src/store.js +318 -272
  96. package/src/utils.js +515 -515
  97. package/src/webrtc/e2ee.js +351 -0
  98. package/src/webrtc/errors.js +116 -0
  99. package/src/webrtc/ice.js +301 -0
  100. package/src/webrtc/index.js +131 -0
  101. package/src/webrtc/joinToken.js +119 -0
  102. package/src/webrtc/observe.js +172 -0
  103. package/src/webrtc/peer.js +351 -0
  104. package/src/webrtc/reactive.js +268 -0
  105. package/src/webrtc/room.js +625 -0
  106. package/src/webrtc/sdp.js +302 -0
  107. package/src/webrtc/sfu/index.js +43 -0
  108. package/src/webrtc/sfu/livekit.js +131 -0
  109. package/src/webrtc/sfu/mediasoup.js +150 -0
  110. package/src/webrtc/signaling.js +373 -0
  111. package/src/webrtc/turn.js +237 -0
  112. package/tests/_helpers/webrtcFakes.js +289 -0
  113. package/tests/audit.test.js +4158 -4158
  114. package/tests/cli.test.js +1136 -1023
  115. package/tests/compare.test.js +497 -0
  116. package/tests/component.test.js +3969 -3938
  117. package/tests/core.test.js +1910 -1910
  118. package/tests/dev-server.test.js +489 -0
  119. package/tests/diff.test.js +1416 -1416
  120. package/tests/docs.test.js +1664 -0
  121. package/tests/electron-features.test.js +864 -0
  122. package/tests/errors.test.js +619 -619
  123. package/tests/expression.test.js +1056 -1056
  124. package/tests/http.test.js +648 -648
  125. package/tests/reactive.test.js +819 -819
  126. package/tests/router.test.js +2327 -2327
  127. package/tests/ssr.test.js +870 -870
  128. package/tests/store.test.js +830 -830
  129. package/tests/test-minifier.js +153 -153
  130. package/tests/test-ssr.js +27 -27
  131. package/tests/utils.test.js +1377 -1377
  132. package/tests/webrtc/e2ee.test.js +283 -0
  133. package/tests/webrtc/ice.test.js +202 -0
  134. package/tests/webrtc/joinToken.test.js +89 -0
  135. package/tests/webrtc/observe.test.js +111 -0
  136. package/tests/webrtc/peer.test.js +373 -0
  137. package/tests/webrtc/reactive.test.js +235 -0
  138. package/tests/webrtc/room.test.js +406 -0
  139. package/tests/webrtc/sdp.test.js +151 -0
  140. package/tests/webrtc/sfu-livekit.test.js +119 -0
  141. package/tests/webrtc/sfu.test.js +160 -0
  142. package/tests/webrtc/signaling.test.js +251 -0
  143. package/tests/webrtc/turn.test.js +256 -0
  144. package/types/collection.d.ts +383 -383
  145. package/types/component.d.ts +186 -186
  146. package/types/errors.d.ts +135 -135
  147. package/types/http.d.ts +92 -92
  148. package/types/misc.d.ts +201 -201
  149. package/types/reactive.d.ts +98 -98
  150. package/types/router.d.ts +190 -190
  151. package/types/ssr.d.ts +102 -102
  152. package/types/store.d.ts +146 -145
  153. package/types/utils.d.ts +245 -245
  154. 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
- dev [root] Start a dev server with live-reload
19
- --port, -p <number> Port number (default: 3100)
20
- --index, -i <file> Index HTML file (default: index.html)
21
- --no-intercept Disable auto-resolution of zquery.min.js
22
- (serve the on-disk vendor copy instead)
23
- --bundle, -b Serve the bundled build (runs bundler first,
24
- serves from dist/server/, auto-rebuilds on save)
25
-
26
- Includes error overlay: syntax errors are
27
- caught on save and shown as a full-screen
28
- overlay in the browser. Runtime errors and
29
- unhandled rejections are also captured.
30
-
31
- bundle [dir|file] Bundle app ES modules into a single file
32
- --out, -o <path> Output directory (default: dist/ next to HTML file)
33
- --index, -i <file> Index HTML file (default: auto-detected)
34
- --minimal, -m Only output HTML, bundled JS, and global CSS (skip static assets)
35
- --global-css <path> Override global CSS input (default: first <link> in HTML)
36
-
37
- 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)
38
-
39
- SMART DEFAULTS
40
-
41
- The bundler works with zero flags for typical projects:
42
- \u2022 Entry is auto-detected with strict precedence:
43
- 1. index.html first, then other .html files
44
- 2. Within HTML: module script pointing to app.js, else first module script
45
- 3. JS scan: $.router( first (entry point), then $.mount( / $.store(
46
- 4. Convention fallbacks (app/app.js, scripts/app.js, app.js, etc.)
47
- Passing a directory auto-detects the entry; passing a file uses it directly
48
- • zquery.min.js is always embedded (auto-built from source if not found)
49
- HTML file is auto-detected (any .html, not just index.html)
50
- Output goes to dist/server/ and dist/local/ next to the detected HTML file
51
-
52
- OUTPUT
53
-
54
- The bundler produces two self-contained sub-directories:
55
-
56
- dist/server/ deploy to your web server
57
- index.html has <base href="/"> for SPA deep routes
58
- z-<entry>.<hash>.js readable bundle
59
- z-<entry>.<hash>.min.js minified bundle
60
-
61
- dist/local/ open from disk (file://)
62
- index.html relative paths, no <base> tag
63
- z-<entry>.<hash>.js same bundle
64
-
65
- Previous hashed builds are automatically cleaned on each rebuild.
66
-
67
- DEVELOPMENT
68
-
69
- zquery dev start a dev server with live-reload (port 3100)
70
- zquery dev --port 8080 custom port
71
-
72
- The dev server includes a full-screen error overlay:
73
- • JS files are syntax-checked on save - errors block reload
74
- and show an overlay with exact file, line:column, and code frame
75
- Runtime errors and unhandled rejections are also captured
76
- The overlay auto-clears when the file is fixed and saved
77
- Press Esc or click × to dismiss manually
78
-
79
- EXAMPLES
80
-
81
- # Scaffold a new project and start developing
82
- zquery create my-app && zquery dev my-app
83
-
84
- # Start dev server with live-reload
85
- zquery dev my-app
86
-
87
- # Build the library only
88
- zquery build
89
-
90
- # Bundle an app from the project root
91
- zquery bundle my-app/
92
-
93
- # Pass a direct entry file (skip auto-detection)
94
- zquery bundle my-app/app/main.js
95
-
96
- # Custom output directory
97
- zquery bundle my-app/ -o build/
98
-
99
- # Minimal build (HTML + JS + global CSS, no static asset copying)
100
- zquery bundle my-app/ --minimal
101
-
102
- # Dev server with a custom index page
103
- zquery dev my-app/ --index home.html
104
-
105
- The bundler walks the ES module import graph starting from the entry
106
- file, topologically sorts dependencies, strips import/export syntax,
107
- and concatenates everything into a single IIFE with content-hashed
108
- filenames for cache-busting. No dependencies needed \u2014 just Node.js.
109
- `);
110
- }
111
-
112
- module.exports = showHelp;
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;