zero-query 0.2.7 → 0.2.9

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/README.md CHANGED
@@ -33,11 +33,28 @@
33
33
 
34
34
  ## Quick Start
35
35
 
36
- The preferred way to use zQuery is with the **pre-built browser bundle** (`zQuery.min.js`) paired with standard **ES module** `<script type="module">` tags for your app code. No npm install, no bundler, no transpiler — just grab the library and start writing components.
36
+ ### Recommended: CLI Dev Server
37
37
 
38
- ### 1. Get the Library
38
+ The fastest way to develop with zQuery is via the built-in **CLI dev server** with **live-reload**. It serves your ES modules as-is and automatically resolves the library — no manual downloads required.
39
39
 
40
- Download `dist/zQuery.min.js` from the [GitHub releases](https://github.com/tonywied17/zero-query/releases/tag/RELEASE), or clone and build:
40
+ ```bash
41
+ # Install (per-project or globally)
42
+ npm install zero-query --save-dev # or: npm install zero-query -g
43
+ ```
44
+
45
+ Scaffold a new project and start the server:
46
+
47
+ ```bash
48
+ npx zquery create my-app
49
+ cd my-app
50
+ npx zquery dev
51
+ ```
52
+
53
+ The `create` command generates a ready-to-run project with `index.html`, a router, two components, and styles. The dev server watches for file changes, hot-swaps CSS in-place, full-reloads on JS/HTML changes, and handles SPA fallback routing.
54
+
55
+ ### Alternative: Manual Setup (No npm)
56
+
57
+ If you prefer **zero tooling**, download `dist/zQuery.min.js` from the [GitHub releases](https://github.com/tonywied17/zero-query/releases/tag/RELEASE) and drop it into `scripts/vendor/`. Then open `index.html` directly in a browser — no Node.js required.
41
58
 
42
59
  ```bash
43
60
  git clone https://github.com/tonywied17/zero-query.git
@@ -46,7 +63,7 @@ node build.js
46
63
  # → dist/zQuery.min.js (~45 KB)
47
64
  ```
48
65
 
49
- ### 2. Include in HTML
66
+ ### Include in HTML
50
67
 
51
68
  ```html
52
69
  <!DOCTYPE html>
@@ -68,7 +85,7 @@ node build.js
68
85
  </html>
69
86
  ```
70
87
 
71
- ### 3. Boot Your App
88
+ ### Boot Your App
72
89
 
73
90
  ```js
74
91
  // scripts/app.js
@@ -79,7 +96,7 @@ import { routes } from './routes.js';
79
96
  $.router({ el: '#app', routes, fallback: 'not-found' });
80
97
  ```
81
98
 
82
- ### 4. Define a Component
99
+ ### Define a Component
83
100
 
84
101
  ```js
85
102
  // scripts/components/home.js
@@ -96,7 +113,7 @@ $.component('home-page', {
96
113
  });
97
114
  ```
98
115
 
99
- That's it — a fully working SPA with zero build tools.
116
+ That's it — a fully working SPA with the dev server's live-reload.
100
117
 
101
118
  ---
102
119
 
@@ -107,7 +124,7 @@ my-app/
107
124
  index.html
108
125
  scripts/
109
126
  vendor/
110
- zQuery.min.js
127
+ zQuery.min.js ← only needed for manual setup; dev server auto-resolves
111
128
  app.js
112
129
  routes.js
113
130
  store.js
@@ -123,40 +140,6 @@ my-app/
123
140
 
124
141
  ---
125
142
 
126
- ## Development Server
127
-
128
- The CLI includes a built-in dev server with **live-reload** powered by [zero-http](https://github.com/tonywied17/zero-http). Install once:
129
-
130
- ```bash
131
- # Per-project (recommended)
132
- npm install zero-query --save-dev
133
-
134
- # Or install globally to use zquery anywhere without npx
135
- npm install zero-query -g
136
- ```
137
-
138
- Then start the server:
139
-
140
- ```bash
141
- # Start dev server (default port 3100)
142
- npx zquery dev
143
-
144
- # Custom port
145
- npx zquery dev --port 8080
146
-
147
- # Serve a specific project folder
148
- npx zquery dev path/to/my-app
149
- ```
150
-
151
- - **No build step** — the server serves your ES modules as-is.
152
- - **CSS hot-swap** — `.css` changes reload in-place without a full refresh.
153
- - **Full reload** — `.js`, `.html`, `.json`, and `.svg` changes trigger a page refresh.
154
- - **SPA fallback** — non-file requests serve `index.html` so deep routes work.
155
-
156
- The server injects a tiny SSE (Server-Sent Events) client into the HTTP response at runtime. Your source files are never modified.
157
-
158
- ---
159
-
160
143
  ## CLI Bundler
161
144
 
162
145
  The CLI can compile your entire app — ES modules, the library, external templates, and assets — into a **single bundled file**.
@@ -252,6 +235,7 @@ location / {
252
235
 
253
236
  | CLI Command | Description |
254
237
  | --- | --- |
238
+ | `zquery create [dir]` | Scaffold a new project (index.html, scripts, styles) |
255
239
  | `zquery dev [root]` | Dev server with live-reload (port 3100) |
256
240
  | `zquery bundle [entry]` | Bundle app into a single IIFE file |
257
241
  | `zquery build` | Build the zQuery library (`dist/zQuery.min.js`) |
package/cli.js CHANGED
@@ -947,25 +947,181 @@ function devServer() {
947
947
  }
948
948
 
949
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
+
950
1102
  // ---------------------------------------------------------------------------
951
1103
  // Help
952
1104
  // ---------------------------------------------------------------------------
953
1105
 
954
1106
  function showHelp() {
955
1107
  console.log(`
956
- zQuery CLI — build, bundle & dev tool
1108
+ zQuery CLI — create, dev, bundle & build
957
1109
 
958
1110
  COMMANDS
959
1111
 
960
- build Build the zQuery library dist/
961
- (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)
962
1118
 
963
1119
  bundle [entry] Bundle app ES modules into a single file
964
1120
  --out, -o <path> Output directory (default: dist/ next to index.html)
965
1121
  --html <file> Use a specific HTML file (default: auto-detected)
966
1122
 
967
- dev [root] Start a dev server with live-reload
968
- --port, -p <number> Port number (default: 3100)
1123
+ build Build the zQuery library dist/
1124
+ (must be run from the project root where src/ lives)
969
1125
 
970
1126
  SMART DEFAULTS
971
1127
 
@@ -997,6 +1153,9 @@ function showHelp() {
997
1153
 
998
1154
  EXAMPLES
999
1155
 
1156
+ # Scaffold a new project and start developing
1157
+ zquery create my-app && cd my-app && zquery dev
1158
+
1000
1159
  # Start dev server with live-reload
1001
1160
  cd my-app && zquery dev
1002
1161
 
@@ -1026,6 +1185,8 @@ function showHelp() {
1026
1185
 
1027
1186
  if (!command || command === '--help' || command === '-h' || command === 'help') {
1028
1187
  showHelp();
1188
+ } else if (command === 'create') {
1189
+ createProject();
1029
1190
  } else if (command === 'build') {
1030
1191
  console.log('\n zQuery Library Build\n');
1031
1192
  buildLibrary();
Binary file
package/dist/zquery.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * zQuery (zeroQuery) v0.2.7
2
+ * zQuery (zeroQuery) v0.2.9
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.7';
2579
+ $.version = '0.2.9';
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.7
2
+ * zQuery (zeroQuery) v0.2.9
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.7",
3
+ "version": "0.2.9",
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",
@@ -50,7 +50,7 @@
50
50
  "publishConfig": {
51
51
  "access": "public"
52
52
  },
53
- "devDependencies": {
53
+ "dependencies": {
54
54
  "zero-http": "^0.2.3"
55
55
  }
56
56
  }