zero-query 0.2.5 → 0.2.8

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/cli.js CHANGED
@@ -3,8 +3,9 @@
3
3
  /**
4
4
  * zQuery CLI
5
5
  *
6
- * Zero-dependency command-line tool for building the zQuery library
7
- * and bundling zQuery-based applications into a single file.
6
+ * Zero-dependency command-line tool for building the zQuery library,
7
+ * bundling zQuery-based applications, and running a dev server with
8
+ * live-reload.
8
9
  *
9
10
  * Usage:
10
11
  * zquery build Build the zQuery library (dist/)
@@ -13,7 +14,9 @@
13
14
  * zquery bundle scripts/app.js Specify entry explicitly
14
15
  * zquery bundle -o build/ Custom output directory
15
16
  * zquery bundle --html other.html Use a specific HTML file instead of auto-detected
16
- * zquery bundle --watch Watch & rebuild on changes
17
+ *
18
+ * zquery dev [root] Start dev server with live-reload
19
+ * zquery dev --port 8080 Custom port (default: 3100)
17
20
  *
18
21
  * Smart defaults (no flags needed for typical projects):
19
22
  * - Entry is auto-detected from index.html's <script type="module" src="...">
@@ -24,6 +27,7 @@
24
27
  * Examples:
25
28
  * cd my-app && npx zero-query bundle # just works!
26
29
  * npx zero-query bundle path/to/scripts/app.js # works from anywhere
30
+ * cd my-app && npx zquery dev # dev server with live-reload
27
31
  */
28
32
 
29
33
  const fs = require('fs');
@@ -412,7 +416,6 @@ function bundleApp() {
412
416
  }
413
417
 
414
418
  const outPath = option('out', 'o', null);
415
- const watchMode = flag('watch', 'w');
416
419
 
417
420
  // Auto-detect index.html by walking up from the entry file, then check cwd
418
421
  let htmlFile = option('html', null, null);
@@ -595,26 +598,6 @@ function bundleApp() {
595
598
  }
596
599
 
597
600
  doBuild();
598
-
599
- // Watch mode
600
- if (watchMode) {
601
- const watchDirs = new Set();
602
- const files = walkImportGraph(entry);
603
- files.forEach(f => watchDirs.add(path.dirname(f)));
604
-
605
- console.log(' Watching for changes...\n');
606
- let debounceTimer;
607
- for (const dir of watchDirs) {
608
- fs.watch(dir, { recursive: true }, (_, filename) => {
609
- if (!filename || !filename.endsWith('.js')) return;
610
- clearTimeout(debounceTimer);
611
- debounceTimer = setTimeout(() => {
612
- console.log(` Changed: ${filename} — rebuilding...`);
613
- try { doBuild(); } catch (e) { console.error(` ✗ ${e.message}`); }
614
- }, 200);
615
- });
616
- }
617
- }
618
601
  }
619
602
 
620
603
  /**
@@ -745,23 +728,400 @@ function rewriteHtml(projectRoot, htmlRelPath, bundleFile, includeLib, bundledFi
745
728
  }
746
729
 
747
730
 
731
+ // ---------------------------------------------------------------------------
732
+ // "dev" command — development server with live-reload
733
+ // ---------------------------------------------------------------------------
734
+
735
+ /**
736
+ * SSE live-reload client script injected into served HTML.
737
+ * Connects to /__zq_reload, reloads on 'reload' events,
738
+ * and hot-swaps CSS on 'css' events without a full reload.
739
+ */
740
+ const LIVE_RELOAD_SNIPPET = `<script>
741
+ (function(){
742
+ var es, timer;
743
+ function connect(){
744
+ es = new EventSource('/__zq_reload');
745
+ es.addEventListener('reload', function(){ location.reload(); });
746
+ es.addEventListener('css', function(e){
747
+ var sheets = document.querySelectorAll('link[rel="stylesheet"]');
748
+ sheets.forEach(function(l){
749
+ var href = l.getAttribute('href');
750
+ if(!href) return;
751
+ var sep = href.indexOf('?') >= 0 ? '&' : '?';
752
+ l.setAttribute('href', href.replace(/[?&]_zqr=\\d+/, '') + sep + '_zqr=' + Date.now());
753
+ });
754
+ });
755
+ es.onerror = function(){
756
+ es.close();
757
+ clearTimeout(timer);
758
+ timer = setTimeout(connect, 2000);
759
+ };
760
+ }
761
+ connect();
762
+ })();
763
+ </script>`;
764
+
765
+ function devServer() {
766
+ let zeroHttp;
767
+ try {
768
+ zeroHttp = require('zero-http');
769
+ } catch (_) {
770
+ console.error(`\n ✗ zero-http is required for the dev server.`);
771
+ console.error(` Install it: npm install zero-http --save-dev\n`);
772
+ process.exit(1);
773
+ }
774
+
775
+ const { createApp, static: serveStatic } = zeroHttp;
776
+
777
+ // Determine the project root to serve
778
+ let root = null;
779
+ for (let i = 1; i < args.length; i++) {
780
+ if (!args[i].startsWith('-') && args[i - 1] !== '-p' && args[i - 1] !== '--port') {
781
+ root = path.resolve(process.cwd(), args[i]);
782
+ break;
783
+ }
784
+ }
785
+ if (!root) {
786
+ // Auto-detect: look for index.html in cwd or common sub-dirs
787
+ const candidates = [
788
+ process.cwd(),
789
+ path.join(process.cwd(), 'public'),
790
+ path.join(process.cwd(), 'src'),
791
+ ];
792
+ for (const c of candidates) {
793
+ if (fs.existsSync(path.join(c, 'index.html'))) { root = c; break; }
794
+ }
795
+ if (!root) root = process.cwd();
796
+ }
797
+
798
+ const PORT = parseInt(option('port', 'p', '3100'));
799
+
800
+ // SSE clients for live-reload
801
+ const sseClients = new Set();
802
+
803
+ const app = createApp();
804
+
805
+ // SSE endpoint — clients connect here for reload notifications
806
+ app.get('/__zq_reload', (req, res) => {
807
+ const sse = res.sse({ keepAlive: 30000, keepAliveComment: 'ping' });
808
+ sseClients.add(sse);
809
+ sse.on('close', () => sseClients.delete(sse));
810
+ });
811
+
812
+ // Auto-resolve zquery.min.js — serve the freshest version regardless of
813
+ // what's on disk in the project. Priority:
814
+ // 1. Package dist/ (when running from the repo after `npm run build`)
815
+ // 2. node_modules/zero-query/dist/ (when installed as a dependency)
816
+ // 3. Fall through to static serving (vendor copy on disk)
817
+ // Registered as middleware so it runs BEFORE serveStatic.
818
+ app.use((req, res, next) => {
819
+ const basename = path.basename(req.url.split('?')[0]).toLowerCase();
820
+ if (basename !== 'zquery.min.js') return next();
821
+
822
+ const candidates = [
823
+ path.join(__dirname, 'dist', 'zquery.min.js'), // package repo
824
+ path.join(root, 'node_modules', 'zero-query', 'dist', 'zquery.min.js'), // npm dep
825
+ ];
826
+ for (const p of candidates) {
827
+ if (fs.existsSync(p)) {
828
+ res.set('Content-Type', 'application/javascript; charset=utf-8');
829
+ res.set('Cache-Control', 'no-cache');
830
+ res.send(fs.readFileSync(p, 'utf-8'));
831
+ return;
832
+ }
833
+ }
834
+ next(); // fall through to static / 404
835
+ });
836
+
837
+ // Static file serving
838
+ app.use(serveStatic(root, { index: false, dotfiles: 'ignore' }));
839
+
840
+ // SPA fallback — inject live-reload snippet into HTML
841
+ app.get('*', (req, res) => {
842
+ if (path.extname(req.url) && path.extname(req.url) !== '.html') {
843
+ res.status(404).send('Not Found');
844
+ return;
845
+ }
846
+ const indexPath = path.join(root, 'index.html');
847
+ if (!fs.existsSync(indexPath)) {
848
+ res.status(404).send('index.html not found');
849
+ return;
850
+ }
851
+ let html = fs.readFileSync(indexPath, 'utf-8');
852
+ // Inject live-reload snippet before </body> or at end
853
+ if (html.includes('</body>')) {
854
+ html = html.replace('</body>', LIVE_RELOAD_SNIPPET + '\n</body>');
855
+ } else {
856
+ html += LIVE_RELOAD_SNIPPET;
857
+ }
858
+ res.html(html);
859
+ });
860
+
861
+ // Broadcast a reload event to all connected SSE clients
862
+ function broadcast(eventType, data) {
863
+ for (const sse of sseClients) {
864
+ try { sse.event(eventType, data || ''); } catch (_) { sseClients.delete(sse); }
865
+ }
866
+ }
867
+
868
+ // File watcher — watch the project root for changes
869
+ const WATCH_EXTS = new Set(['.js', '.css', '.html', '.htm', '.json', '.svg']);
870
+ const IGNORE_DIRS = new Set(['node_modules', '.git', 'dist', '.cache']);
871
+ let debounceTimer;
872
+
873
+ function shouldWatch(filename) {
874
+ if (!filename) return false;
875
+ const ext = path.extname(filename).toLowerCase();
876
+ return WATCH_EXTS.has(ext);
877
+ }
878
+
879
+ function isIgnored(filepath) {
880
+ const parts = filepath.split(path.sep);
881
+ return parts.some(p => IGNORE_DIRS.has(p));
882
+ }
883
+
884
+ // Collect directories to watch (walk root, skip ignored)
885
+ function collectWatchDirs(dir) {
886
+ const dirs = [dir];
887
+ try {
888
+ const entries = fs.readdirSync(dir, { withFileTypes: true });
889
+ for (const entry of entries) {
890
+ if (!entry.isDirectory()) continue;
891
+ if (IGNORE_DIRS.has(entry.name)) continue;
892
+ const sub = path.join(dir, entry.name);
893
+ dirs.push(...collectWatchDirs(sub));
894
+ }
895
+ } catch (_) {}
896
+ return dirs;
897
+ }
898
+
899
+ const watchDirs = collectWatchDirs(root);
900
+ const watchers = [];
901
+
902
+ for (const dir of watchDirs) {
903
+ try {
904
+ const watcher = fs.watch(dir, (eventType, filename) => {
905
+ if (!shouldWatch(filename)) return;
906
+ const fullPath = path.join(dir, filename || '');
907
+ if (isIgnored(fullPath)) return;
908
+
909
+ clearTimeout(debounceTimer);
910
+ debounceTimer = setTimeout(() => {
911
+ const rel = path.relative(root, fullPath).replace(/\\/g, '/');
912
+ const ext = path.extname(filename).toLowerCase();
913
+ const now = new Date().toLocaleTimeString();
914
+
915
+ if (ext === '.css') {
916
+ console.log(` ${now} \x1b[35m css \x1b[0m ${rel}`);
917
+ broadcast('css', rel);
918
+ } else {
919
+ console.log(` ${now} \x1b[36m reload \x1b[0m ${rel}`);
920
+ broadcast('reload', rel);
921
+ }
922
+ }, 100);
923
+ });
924
+ watchers.push(watcher);
925
+ } catch (_) {}
926
+ }
927
+
928
+ app.listen(PORT, () => {
929
+ console.log(`\n \x1b[1mzQuery Dev Server\x1b[0m`);
930
+ console.log(` \x1b[2m${'─'.repeat(40)}\x1b[0m`);
931
+ console.log(` Local: \x1b[36mhttp://localhost:${PORT}/\x1b[0m`);
932
+ console.log(` Root: ${path.relative(process.cwd(), root) || '.'}`);
933
+ console.log(` Live Reload: \x1b[32menabled\x1b[0m (SSE)`);
934
+ console.log(` Watching: ${WATCH_EXTS.size} file types in ${watchDirs.length} director${watchDirs.length === 1 ? 'y' : 'ies'}`);
935
+ console.log(` \x1b[2m${'─'.repeat(40)}\x1b[0m`);
936
+ console.log(` Press Ctrl+C to stop\n`);
937
+ });
938
+
939
+ // Graceful shutdown
940
+ process.on('SIGINT', () => {
941
+ console.log('\n Shutting down...');
942
+ watchers.forEach(w => w.close());
943
+ for (const sse of sseClients) { try { sse.close(); } catch (_) {} }
944
+ app.close(() => process.exit(0));
945
+ setTimeout(() => process.exit(0), 1000);
946
+ });
947
+ }
948
+
949
+
950
+ // ---------------------------------------------------------------------------
951
+ // Create — scaffold a new zQuery project
952
+ // ---------------------------------------------------------------------------
953
+
954
+ function createProject() {
955
+ const target = args[1] ? path.resolve(args[1]) : process.cwd();
956
+ const name = path.basename(target);
957
+
958
+ // Guard: refuse to overwrite existing files
959
+ const conflicts = ['index.html', 'scripts'].filter(f =>
960
+ fs.existsSync(path.join(target, f))
961
+ );
962
+ if (conflicts.length) {
963
+ console.error(`\n ✗ Directory already contains: ${conflicts.join(', ')}`);
964
+ console.error(` Aborting to avoid overwriting existing files.\n`);
965
+ process.exit(1);
966
+ }
967
+
968
+ console.log(`\n zQuery — Create Project\n`);
969
+ console.log(` Scaffolding into ${target}\n`);
970
+
971
+ // ---- templates ----
972
+
973
+ const indexHTML = `<!DOCTYPE html>
974
+ <html lang="en">
975
+ <head>
976
+ <meta charset="UTF-8">
977
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
978
+ <title>${name}</title>
979
+ <link rel="stylesheet" href="styles/styles.css">
980
+ <script src="scripts/vendor/zQuery.min.js"></script>
981
+ <script type="module" src="scripts/app.js"></script>
982
+ </head>
983
+ <body>
984
+ <nav>
985
+ <a z-link="/">Home</a>
986
+ <a z-link="/about">About</a>
987
+ </nav>
988
+ <div id="app"></div>
989
+ </body>
990
+ </html>`;
991
+
992
+ const appJS = `// scripts/app.js — entry point
993
+ import './components/home.js';
994
+ import './components/about.js';
995
+ import { routes } from './routes.js';
996
+
997
+ $.router({ el: '#app', routes, fallback: 'not-found' });
998
+
999
+ $.ready(() => {
1000
+ console.log('zQuery v' + $.version + ' loaded');
1001
+ });`;
1002
+
1003
+ const routesJS = `// scripts/routes.js
1004
+ export const routes = [
1005
+ { path: '/', component: 'home-page' },
1006
+ { path: '/about', component: 'about-page' },
1007
+ ];`;
1008
+
1009
+ const homeJS = `// scripts/components/home.js
1010
+ $.component('home-page', {
1011
+ state: () => ({ count: 0 }),
1012
+
1013
+ increment() { this.state.count++; },
1014
+
1015
+ render() {
1016
+ return \`
1017
+ <h1>Home</h1>
1018
+ <p>Count: \${this.state.count}</p>
1019
+ <button @click="increment">+1</button>
1020
+ \`;
1021
+ }
1022
+ });`;
1023
+
1024
+ const aboutJS = `// scripts/components/about.js
1025
+ $.component('about-page', {
1026
+ render() {
1027
+ return \`
1028
+ <h1>About</h1>
1029
+ <p>Built with <strong>zQuery</strong> — a lightweight, zero-dependency frontend library.</p>
1030
+ \`;
1031
+ }
1032
+ });`;
1033
+
1034
+ const stylesCSS = `/* styles/styles.css */
1035
+ *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
1036
+
1037
+ body {
1038
+ font-family: system-ui, -apple-system, sans-serif;
1039
+ line-height: 1.6;
1040
+ color: #e6edf3;
1041
+ background: #0d1117;
1042
+ padding: 2rem;
1043
+ }
1044
+
1045
+ nav {
1046
+ display: flex;
1047
+ gap: 1rem;
1048
+ margin-bottom: 2rem;
1049
+ padding-bottom: 1rem;
1050
+ border-bottom: 1px solid #30363d;
1051
+ }
1052
+
1053
+ nav a {
1054
+ color: #58a6ff;
1055
+ text-decoration: none;
1056
+ font-weight: 500;
1057
+ }
1058
+
1059
+ nav a:hover { text-decoration: underline; }
1060
+
1061
+ h1 { margin-bottom: 0.5rem; }
1062
+
1063
+ button {
1064
+ margin-top: 0.75rem;
1065
+ padding: 0.5rem 1.25rem;
1066
+ background: #238636;
1067
+ color: #fff;
1068
+ border: none;
1069
+ border-radius: 6px;
1070
+ cursor: pointer;
1071
+ font-size: 0.95rem;
1072
+ }
1073
+
1074
+ button:hover { background: #2ea043; }`;
1075
+
1076
+ // ---- write files ----
1077
+
1078
+ const files = {
1079
+ 'index.html': indexHTML,
1080
+ 'scripts/app.js': appJS,
1081
+ 'scripts/routes.js': routesJS,
1082
+ 'scripts/components/home.js': homeJS,
1083
+ 'scripts/components/about.js': aboutJS,
1084
+ 'styles/styles.css': stylesCSS,
1085
+ };
1086
+
1087
+ for (const [rel, content] of Object.entries(files)) {
1088
+ const abs = path.join(target, rel);
1089
+ fs.mkdirSync(path.dirname(abs), { recursive: true });
1090
+ fs.writeFileSync(abs, content, 'utf-8');
1091
+ console.log(` ✓ ${rel}`);
1092
+ }
1093
+
1094
+ console.log(`
1095
+ Done! Next steps:
1096
+
1097
+ ${target !== process.cwd() ? `cd ${args[1]}\n ` : ''}npx zquery dev
1098
+ `);
1099
+ }
1100
+
1101
+
748
1102
  // ---------------------------------------------------------------------------
749
1103
  // Help
750
1104
  // ---------------------------------------------------------------------------
751
1105
 
752
1106
  function showHelp() {
753
1107
  console.log(`
754
- zQuery CLI — build & bundle tool
1108
+ zQuery CLI — create, dev, bundle & build
755
1109
 
756
1110
  COMMANDS
757
1111
 
758
- build Build the zQuery library dist/
759
- (must be run from the project root where src/ lives)
1112
+ create [dir] Scaffold a new zQuery project
1113
+ Creates index.html, scripts/, styles/ in the target directory
1114
+ (defaults to the current directory)
1115
+
1116
+ dev [root] Start a dev server with live-reload
1117
+ --port, -p <number> Port number (default: 3100)
760
1118
 
761
1119
  bundle [entry] Bundle app ES modules into a single file
762
1120
  --out, -o <path> Output directory (default: dist/ next to index.html)
763
1121
  --html <file> Use a specific HTML file (default: auto-detected)
764
- --watch, -w Watch source files and rebuild on changes
1122
+
1123
+ build Build the zQuery library → dist/
1124
+ (must be run from the project root where src/ lives)
765
1125
 
766
1126
  SMART DEFAULTS
767
1127
 
@@ -788,11 +1148,17 @@ function showHelp() {
788
1148
 
789
1149
  DEVELOPMENT
790
1150
 
791
- npm run serve start a local dev server (zero-http, SPA routing)
792
- npm run dev watch mode auto-rebuild bundle on source changes
1151
+ zquery dev start a dev server with live-reload (port 3100)
1152
+ zquery dev --port 8080 custom port
793
1153
 
794
1154
  EXAMPLES
795
1155
 
1156
+ # Scaffold a new project and start developing
1157
+ zquery create my-app && cd my-app && zquery dev
1158
+
1159
+ # Start dev server with live-reload
1160
+ cd my-app && zquery dev
1161
+
796
1162
  # Build the library only
797
1163
  zquery build
798
1164
 
@@ -805,9 +1171,6 @@ function showHelp() {
805
1171
  # Custom output directory
806
1172
  zquery bundle -o build/
807
1173
 
808
- # Watch mode
809
- zquery bundle --watch
810
-
811
1174
  The bundler walks the ES module import graph starting from the entry
812
1175
  file, topologically sorts dependencies, strips import/export syntax,
813
1176
  and concatenates everything into a single IIFE with content-hashed
@@ -822,11 +1185,15 @@ function showHelp() {
822
1185
 
823
1186
  if (!command || command === '--help' || command === '-h' || command === 'help') {
824
1187
  showHelp();
1188
+ } else if (command === 'create') {
1189
+ createProject();
825
1190
  } else if (command === 'build') {
826
1191
  console.log('\n zQuery Library Build\n');
827
1192
  buildLibrary();
828
1193
  } else if (command === 'bundle') {
829
1194
  bundleApp();
1195
+ } else if (command === 'dev') {
1196
+ devServer();
830
1197
  } else {
831
1198
  console.error(`\n Unknown command: ${command}\n Run "zquery --help" for usage.\n`);
832
1199
  process.exit(1);
Binary file
package/dist/zquery.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * zQuery (zeroQuery) v0.2.5
2
+ * zQuery (zeroQuery) v0.2.8
3
3
  * Lightweight Frontend Library
4
4
  * https://github.com/tonywied17/zero-query
5
5
  * (c) 2026 Anthony Wiedman — MIT License
@@ -2576,7 +2576,7 @@ $.session = session;
2576
2576
  $.bus = bus;
2577
2577
 
2578
2578
  // --- Meta ------------------------------------------------------------------
2579
- $.version = '0.2.5';
2579
+ $.version = '0.2.8';
2580
2580
  $.meta = {}; // populated at build time by CLI bundler
2581
2581
 
2582
2582
  $.noConflict = () => {
@@ -1,5 +1,5 @@
1
1
  /**
2
- * zQuery (zeroQuery) v0.2.5
2
+ * zQuery (zeroQuery) v0.2.8
3
3
  * Lightweight Frontend Library
4
4
  * https://github.com/tonywied17/zero-query
5
5
  * (c) 2026 Anthony Wiedman — MIT License
@@ -13,5 +13,5 @@ class Router { constructor(config = {}) { this._el = null; const isFile = typeof
13
13
  class Store { constructor(config = {}) { this._subscribers = new Map(); this._wildcards = new Set(); this._actions = config.actions || {}; this._getters = config.getters || {}; this._middleware = []; this._history = []; this._debug = config.debug || false; const initial = typeof config.state === 'function' ? config.state() : { ...(config.state || {}) }; this.state = reactive(initial, (key, value, old) => { const subs = this._subscribers.get(key); if (subs) subs.forEach(fn => fn(value, old, key)); this._wildcards.forEach(fn => fn(key, value, old)); }); this.getters = {}; for (const [name, fn] of Object.entries(this._getters)) { Object.defineProperty(this.getters, name, { get: () => fn(this.state.__raw || this.state), enumerable: true }); } } dispatch(name, ...args) { const action = this._actions[name]; if (!action) { console.warn(`zQuery Store: Unknown action "${name}"`); return; } for (const mw of this._middleware) { const result = mw(name, args, this.state); if (result === false) return; } if (this._debug) { console.log(`%c[Store] ${name}`, 'color: #4CAF50; font-weight: bold;', ...args); } const result = action(this.state, ...args); this._history.push({ action: name, args, timestamp: Date.now() }); return result; } subscribe(keyOrFn, fn) { if (typeof keyOrFn === 'function') { this._wildcards.add(keyOrFn); return () => this._wildcards.delete(keyOrFn); } if (!this._subscribers.has(keyOrFn)) { this._subscribers.set(keyOrFn, new Set()); } this._subscribers.get(keyOrFn).add(fn); return () => this._subscribers.get(keyOrFn)?.delete(fn); } snapshot() { return JSON.parse(JSON.stringify(this.state.__raw || this.state)); } replaceState(newState) { const raw = this.state.__raw || this.state; for (const key of Object.keys(raw)) { delete this.state[key]; } Object.assign(this.state, newState); } use(fn) { this._middleware.push(fn); return this; } get history() { return [...this._history]; } reset(initialState) { this.replaceState(initialState); this._history = []; }
14
14
  const _config = { baseURL: '', headers: { 'Content-Type': 'application/json' }, timeout: 30000,
15
15
  function debounce(fn, ms = 250) { let timer; const debounced = (...args) => { clearTimeout(timer); timer = setTimeout(() => fn(...args), ms); }; debounced.cancel = () => clearTimeout(timer); return debounced;
16
- function $(selector, context) { if (typeof selector === 'function') { query.ready(selector); return; } return query(selector, context);
16
+ function $(selector, context) { if (typeof selector === 'function') { query.ready(selector); return; } return query(selector, context);
17
17
  })(typeof window !== 'undefined' ? window : globalThis);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zero-query",
3
- "version": "0.2.5",
3
+ "version": "0.2.8",
4
4
  "description": "Lightweight modern frontend library — jQuery-like selectors, reactive components, SPA router, and state management with zero dependencies.",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
@@ -18,8 +18,7 @@
18
18
  ],
19
19
  "scripts": {
20
20
  "build": "node build.js",
21
- "dev": "npx zquery bundle examples/starter-app/scripts/app.js --watch",
22
- "serve": "node examples/starter-app/local-server.js",
21
+ "dev": "node cli.js dev examples/starter-app",
23
22
  "dev-lib": "node build.js --watch",
24
23
  "bundle": "node cli.js bundle",
25
24
  "bundle:app": "node cli.js bundle examples/starter-app/scripts/app.js"