what-framework-cli 0.6.2 → 0.6.4

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 (2) hide show
  1. package/package.json +2 -2
  2. package/src/cli.js +61 -30
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "what-framework-cli",
3
- "version": "0.6.2",
3
+ "version": "0.6.4",
4
4
  "description": "What Framework CLI - Dev server, build, and deployment tools",
5
5
  "type": "module",
6
6
  "bin": {
@@ -22,7 +22,7 @@
22
22
  "author": "ZVN DEV (https://zvndev.com)",
23
23
  "license": "MIT",
24
24
  "dependencies": {
25
- "what-framework": "^0.6.2"
25
+ "what-framework": "^0.6.3"
26
26
  },
27
27
  "repository": {
28
28
  "type": "git",
package/src/cli.js CHANGED
@@ -6,15 +6,30 @@
6
6
  import { existsSync, readFileSync, mkdirSync, writeFileSync, readdirSync, statSync, copyFileSync, realpathSync } from 'fs';
7
7
  import { join, resolve, relative, extname, basename, normalize } from 'path';
8
8
  import { createServer } from 'http';
9
- import { fileURLToPath } from 'url';
9
+ import { fileURLToPath, pathToFileURL } from 'url';
10
10
  import { createHash } from 'crypto';
11
11
  import { gzipSync } from 'zlib';
12
12
 
13
- // Security: Prevent path traversal attacks
13
+ // Security: Prevent path traversal attacks while accepting URL paths like /main.js.
14
14
  function safePath(base, userPath) {
15
15
  try {
16
- // Reject paths that contain .. segments (path traversal attempt)
17
- const normalized = normalize(userPath);
16
+ if (typeof userPath !== 'string') return null;
17
+
18
+ let relativePath = userPath.startsWith('/') ? userPath.slice(1) : userPath;
19
+ try {
20
+ relativePath = decodeURIComponent(relativePath);
21
+ } catch {
22
+ return null;
23
+ }
24
+
25
+ if (relativePath.includes('\0')) return null;
26
+ relativePath = relativePath.replace(/\\/g, '/');
27
+
28
+ // Reject encoded absolute paths/double-leading-slash paths after decoding.
29
+ if (relativePath.startsWith('/')) return null;
30
+
31
+ // Reject paths that contain .. segments (path traversal attempt).
32
+ const normalized = normalize(relativePath || '.');
18
33
  if (normalized.startsWith('..') || normalized.includes('/..') || normalized.includes('\\..')) {
19
34
  return null;
20
35
  }
@@ -153,31 +168,6 @@ const __dirname = fileURLToPath(new URL('.', import.meta.url));
153
168
  const cwd = process.cwd();
154
169
 
155
170
  const args = process.argv.slice(2);
156
- const command = args[0];
157
-
158
- const commands = { dev, build, preview, generate, init };
159
-
160
- if (!command || !commands[command]) {
161
- console.log(`
162
- what - The closest framework to vanilla JS
163
-
164
- Usage: what <command>
165
-
166
- Commands:
167
- dev Start dev server with HMR
168
- build Production build
169
- preview Preview production build
170
- generate Static site generation
171
- init Create a new project
172
-
173
- Options:
174
- --port Dev server port (default: 3000)
175
- --host Dev server host (default: localhost)
176
- `);
177
- process.exit(0);
178
- }
179
-
180
- commands[command]();
181
171
 
182
172
  // --- Dev Server ---
183
173
 
@@ -537,7 +527,7 @@ function init() {
537
527
  generate: 'what generate',
538
528
  },
539
529
  dependencies: {
540
- 'what-framework': '^0.6.2',
530
+ 'what-framework': '^0.6.3',
541
531
  },
542
532
  }, null, 2));
543
533
 
@@ -945,3 +935,44 @@ function watchFiles(dir, onChange) {
945
935
  // Poll every 100ms for more responsive HMR
946
936
  setInterval(scan, 100);
947
937
  }
938
+
939
+ function printHelp() {
940
+ console.log(`
941
+ what - The closest framework to vanilla JS
942
+
943
+ Usage: what <command>
944
+
945
+ Commands:
946
+ dev Start dev server with HMR
947
+ build Production build
948
+ preview Preview production build
949
+ generate Static site generation
950
+ init Create a new project
951
+
952
+ Options:
953
+ --port Dev server port (default: 3000)
954
+ --host Dev server host (default: localhost)
955
+ `);
956
+ }
957
+
958
+ async function main() {
959
+ const command = args[0];
960
+ const commands = { dev, build, preview, generate, init };
961
+
962
+ if (!command || !commands[command]) {
963
+ printHelp();
964
+ return;
965
+ }
966
+
967
+ await commands[command]();
968
+ }
969
+
970
+ const isCliEntry = process.argv[1] && import.meta.url === pathToFileURL(realpathSync(process.argv[1])).href;
971
+ if (isCliEntry) {
972
+ main().catch((error) => {
973
+ console.error(error?.stack || error?.message || String(error));
974
+ process.exit(1);
975
+ });
976
+ }
977
+
978
+ export { safePath };