@t8/serve 0.1.39 → 0.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 (4) hide show
  1. package/README.md +23 -19
  2. package/dist/run.mjs +130 -40
  3. package/package.json +4 -3
  4. package/src/run.ts +26 -47
package/README.md CHANGED
@@ -9,28 +9,32 @@ Use cases:
9
9
 
10
10
  ## CLI
11
11
 
12
- ```sh
13
- npx @t8/serve [url|port] [*] [app_dir] [...assets_dirs] [-b [bundle_input_path] [bundle_output_path] [bundle_output_dir]] [--watch] [--minify]
14
- # * = SPA mode: serve all unmatched paths as "/"
15
12
  ```
13
+ npx @t8/serve <app_dir> [...optional flags]
16
14
 
17
- Examples:
15
+ Flag Usage
18
16
 
19
- ```sh
20
- npx @t8/serve 3000 app
21
- # - serve files from './app' at 'localhost:3000'
17
+ --bundle, -b -b [input_path [[output_path] [output_dir]]]
18
+ Defaults:
19
+ - input_path: "index.ts" (relative to <app_dir>)
20
+ - ouput_path: "index.js" (relative to <app_dir>/<output_dir>)
21
+ - output_dir: "dist"
22
+
23
+ --url, -u -u [<host>:]<port>
24
+ Default: "localhost:3000"
25
+
26
+ --spa, -s -s
27
+ Enables the SPA mode by handling all unmatched paths as "/".
22
28
 
23
- npx @t8/serve 3000 * app -b
24
- # - bundle './app/index.ts' to './app/dist/index.js' [-b]
25
- # - serve files from './app' at 'localhost:3000' in the SPA mode [*] (handling all unmatched paths as "/")
29
+ --dirs --dirs assets public
30
+ To serve files from the listed subdirectories of <app_dir>.
31
+ By default, files are served from <app_dir>.
26
32
 
27
- npx @t8/serve 3000 * app -b src/index.ts
28
- # - bundle './app/src/index.ts' to './app/dist/index.js'
29
- # - serve files from './app' at 'localhost:3000' in the SPA mode
33
+ --watch --watch
34
+ To rebuild the bundled code if the source code changes.
30
35
 
31
- npx @t8/serve 127.0.0.1:3000 app public dist -b
32
- # - bundle './app/index.ts' to './app/dist/index.js'
33
- # - serve files from './app/public' and './app/dist' at '127.0.0.1:3000'
36
+ --minify --minify
37
+ To minify the bundled code.
34
38
  ```
35
39
 
36
40
  <details>
@@ -39,7 +43,7 @@ npx @t8/serve 127.0.0.1:3000 app public dist -b
39
43
  ```
40
44
  // package.json
41
45
  "scripts": {
42
- "play": "npx @t8/serve 3000 * playground -b"
46
+ "play": "npx @t8/serve playground -s -b"
43
47
  }
44
48
  ```
45
49
 
@@ -76,7 +80,7 @@ webServer: {
76
80
  ```
77
81
  // package.json
78
82
  "scripts": {
79
- "play": "npx @t8/serve 3000 * playground -b src/index.tsx"
83
+ "play": "npx @t8/serve playground -s -b src/index.tsx"
80
84
  }
81
85
  ```
82
86
 
@@ -127,7 +131,7 @@ webServer: {
127
131
  {
128
132
  "name": "app",
129
133
  "scripts": {
130
- "start": "npx @t8/serve 80 . -b src/index.ts --watch"
134
+ "start": "npx @t8/serve . -u 80 -b src/index.ts --watch"
131
135
  }
132
136
  }
133
137
  ```
package/dist/run.mjs CHANGED
@@ -1,4 +1,118 @@
1
1
  #!/usr/bin/env node
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __commonJS = (cb, mod) => function __require() {
9
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
10
+ };
11
+ var __copyProps = (to, from, except, desc) => {
12
+ if (from && typeof from === "object" || typeof from === "function") {
13
+ for (let key of __getOwnPropNames(from))
14
+ if (!__hasOwnProp.call(to, key) && key !== except)
15
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
+ }
17
+ return to;
18
+ };
19
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
20
+ // If the importer is in node compatibility mode or this is not an ESM
21
+ // file that has been converted to a CommonJS file using a Babel-
22
+ // compatible transform (i.e. "__esModule" has not been set), then set
23
+ // "default" to the CommonJS "module.exports" for node compatibility.
24
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
25
+ mod
26
+ ));
27
+
28
+ // node_modules/args-json/dist/index.cjs
29
+ var require_dist = __commonJS({
30
+ "node_modules/args-json/dist/index.cjs"(exports) {
31
+ function toCamelCase(x) {
32
+ let s = x.replace(/^[-_.\s~+]|[-_.\s~+]$/g, "");
33
+ if (!/[-_.\s~+]/.test(s)) return s.slice(0, 1).toLowerCase() + s.slice(1);
34
+ return s.toLowerCase().replace(/[-_.\s~+](\S)/g, (_, match) => match.toUpperCase());
35
+ }
36
+ function toKey(x) {
37
+ if (x) {
38
+ if (x.startsWith("--") && x.length > 2) return toCamelCase(x.slice(2));
39
+ if (x.startsWith("-") && x.length === 2) return toCamelCase(x.slice(1));
40
+ }
41
+ }
42
+ function split(x) {
43
+ let words = [], word = "";
44
+ let hasOpenSingleQuote = false;
45
+ let hasOpenDoubleQuote = false;
46
+ for (let i = 0; i < x.length; i++) {
47
+ let c = x[i];
48
+ if (/^\s/.test(c) && !hasOpenSingleQuote && !hasOpenDoubleQuote) {
49
+ if (word) words.push(word);
50
+ word = "";
51
+ continue;
52
+ }
53
+ if (c === "'" && x[i - 1] !== "\\") hasOpenSingleQuote = !hasOpenSingleQuote;
54
+ if (c === '"' && x[i - 1] !== "\\") hasOpenDoubleQuote = !hasOpenDoubleQuote;
55
+ word += c;
56
+ }
57
+ if (word) words.push(word);
58
+ return words;
59
+ }
60
+ function getDefaultInput() {
61
+ return typeof process === "undefined" ? [] : process.argv;
62
+ }
63
+ function parseArgs2(input, map) {
64
+ let normalizedInput;
65
+ let normalizedMap;
66
+ if (input === void 0) normalizedInput = getDefaultInput();
67
+ else if (typeof input === "string") normalizedInput = split(input);
68
+ else if (Array.isArray(input)) normalizedInput = input.map((x) => String(x));
69
+ else if (input !== null && typeof input === "object") {
70
+ normalizedInput = getDefaultInput();
71
+ normalizedMap = input;
72
+ } else normalizedInput = [];
73
+ normalizedInput = normalizedInput.flatMap((item) => {
74
+ let normalizedItem = item.trim();
75
+ let k = normalizedItem.indexOf("=");
76
+ if (k === -1) return normalizedItem;
77
+ return [normalizedItem.slice(0, k), normalizedItem.slice(k + 1)];
78
+ });
79
+ if (map) normalizedMap = map;
80
+ let key = "";
81
+ let parsedArgs = {};
82
+ for (let rawValue of normalizedInput) {
83
+ rawValue = rawValue.trim();
84
+ if (rawValue.startsWith('"') && rawValue.endsWith('"')) rawValue = rawValue.slice(1, -1);
85
+ else if (rawValue.startsWith("'") && rawValue.endsWith("'")) rawValue = rawValue.slice(1, -1);
86
+ let parsedKey = toKey(rawValue);
87
+ if (parsedKey !== void 0) {
88
+ let nextKey = normalizedMap?.[parsedKey] ?? parsedKey;
89
+ if (key && nextKey !== key && parsedArgs[key] === void 0) parsedArgs[key] = true;
90
+ key = nextKey;
91
+ continue;
92
+ }
93
+ let parsedValue;
94
+ if (rawValue) try {
95
+ parsedValue = JSON.parse(rawValue);
96
+ } catch {
97
+ parsedValue = rawValue;
98
+ }
99
+ else parsedValue = true;
100
+ let prevValue = parsedArgs[key];
101
+ let value;
102
+ if (prevValue === void 0) value = key === "" ? [parsedValue] : parsedValue;
103
+ else if (Array.isArray(prevValue)) value = [...prevValue, parsedValue];
104
+ else value = [prevValue, parsedValue];
105
+ parsedArgs[key] = value;
106
+ }
107
+ if (key && parsedArgs[key] === void 0) parsedArgs[key] = true;
108
+ return parsedArgs;
109
+ }
110
+ exports.parseArgs = parseArgs2;
111
+ }
112
+ });
113
+
114
+ // src/run.ts
115
+ var import_args_json = __toESM(require_dist(), 1);
2
116
 
3
117
  // src/serve.ts
4
118
  import { createReadStream } from "node:fs";
@@ -143,47 +257,23 @@ async function serve(config = {}) {
143
257
 
144
258
  // src/run.ts
145
259
  async function run() {
146
- let [url, ...args] = process.argv.slice(2);
147
- let spa = false;
148
- let watch = false;
149
- let minify = false;
150
- if (args[0] === "*") {
151
- spa = true;
152
- args.shift();
153
- }
154
- while (args.at(-1)?.startsWith("--")) {
155
- let arg = args.pop();
156
- switch (arg) {
157
- case "--watch":
158
- watch = true;
159
- break;
160
- case "--minify":
161
- minify = true;
162
- break;
163
- }
164
- }
165
- let bundleFlagIndex = args.indexOf("-b");
166
- let path = args[0];
167
- let dirs;
168
- let bundle2;
169
- if (bundleFlagIndex === -1) dirs = args.slice(1);
170
- else {
171
- dirs = args.slice(1, bundleFlagIndex);
172
- bundle2 = {
173
- input: args[bundleFlagIndex + 1] || void 0,
174
- output: args[bundleFlagIndex + 2] || void 0,
175
- dir: args[bundleFlagIndex + 3] || void 0
176
- };
177
- }
178
- await serve({
179
- url,
180
- path,
181
- dirs,
182
- spa,
260
+ let {
261
+ "": unkeyedArgs,
183
262
  bundle: bundle2,
184
- log: true,
185
- watch,
186
- minify
263
+ dirs,
264
+ ...args
265
+ } = (0, import_args_json.parseArgs)(process.argv.slice(2), {
266
+ b: "bundle",
267
+ u: "url",
268
+ s: "spa"
187
269
  });
270
+ let config = {
271
+ path: unkeyedArgs?.[0],
272
+ dirs: Array.isArray(dirs) ? dirs : dirs && [dirs],
273
+ bundle: Array.isArray(bundle2) ? { input: bundle2[0], output: bundle2[1], dir: bundle2[2] } : bundle2,
274
+ log: true,
275
+ ...args
276
+ };
277
+ await serve(config);
188
278
  }
189
279
  run();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@t8/serve",
3
- "version": "0.1.39",
3
+ "version": "0.2.0",
4
4
  "description": "Simple static file server + bundler, primarily for demo apps and tests, manual or automated",
5
5
  "keywords": [
6
6
  "node",
@@ -27,9 +27,10 @@
27
27
  "shape": "npx codeshape"
28
28
  },
29
29
  "devDependencies": {
30
- "@types/node": "^24.5.2"
30
+ "@types/node": "^25.0.3"
31
31
  },
32
32
  "dependencies": {
33
- "esbuild": "^0.27.1"
33
+ "args-json": "^1.2.10",
34
+ "esbuild": "^0.27.2"
34
35
  }
35
36
  }
package/src/run.ts CHANGED
@@ -1,57 +1,36 @@
1
1
  #!/usr/bin/env node
2
+ import { parseArgs } from "args-json";
2
3
  import type { Config } from "./Config.ts";
3
4
  import { serve } from "./serve.ts";
4
5
 
5
- async function run() {
6
- let [url, ...args] = process.argv.slice(2);
7
- let spa = false;
8
- let watch = false;
9
- let minify = false;
10
-
11
- if (args[0] === "*") {
12
- spa = true;
13
- args.shift();
14
- }
15
-
16
- while (args.at(-1)?.startsWith("--")) {
17
- let arg = args.pop();
18
-
19
- switch (arg) {
20
- case "--watch":
21
- watch = true;
22
- break;
23
- case "--minify":
24
- minify = true;
25
- break;
26
- }
27
- }
28
-
29
- let bundleFlagIndex = args.indexOf("-b");
30
- let path = args[0];
31
-
32
- let dirs: string[];
33
- let bundle: Config["bundle"];
34
-
35
- if (bundleFlagIndex === -1) dirs = args.slice(1);
36
- else {
37
- dirs = args.slice(1, bundleFlagIndex);
38
- bundle = {
39
- input: args[bundleFlagIndex + 1] || undefined,
40
- output: args[bundleFlagIndex + 2] || undefined,
41
- dir: args[bundleFlagIndex + 3] || undefined,
42
- };
43
- }
6
+ type CLIConfig = Omit<Config, "bundle" | "onRequest"> & {
7
+ ""?: string[];
8
+ bundle?: string | string[];
9
+ };
44
10
 
45
- await serve({
46
- url,
47
- path,
48
- dirs,
49
- spa,
11
+ async function run() {
12
+ let {
13
+ "": unkeyedArgs,
50
14
  bundle,
51
- log: true,
52
- watch,
53
- minify,
15
+ dirs,
16
+ ...args
17
+ } = parseArgs<CLIConfig>(process.argv.slice(2), {
18
+ b: "bundle",
19
+ u: "url",
20
+ s: "spa",
54
21
  });
22
+
23
+ let config: Config = {
24
+ path: unkeyedArgs?.[0],
25
+ dirs: Array.isArray(dirs) ? dirs : dirs && [dirs],
26
+ bundle: Array.isArray(bundle)
27
+ ? { input: bundle[0], output: bundle[1], dir: bundle[2] }
28
+ : bundle,
29
+ log: true,
30
+ ...args,
31
+ };
32
+
33
+ await serve(config);
55
34
  }
56
35
 
57
36
  run();