@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.
- package/README.md +23 -19
- package/dist/run.mjs +130 -40
- package/package.json +4 -3
- 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
|
-
|
|
15
|
+
Flag Usage
|
|
18
16
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
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
|
-
|
|
24
|
-
|
|
25
|
-
|
|
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
|
-
|
|
28
|
-
|
|
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
|
-
|
|
32
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
147
|
-
|
|
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
|
-
|
|
185
|
-
|
|
186
|
-
|
|
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.
|
|
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": "^
|
|
30
|
+
"@types/node": "^25.0.3"
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"
|
|
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
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
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
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
dirs,
|
|
49
|
-
spa,
|
|
11
|
+
async function run() {
|
|
12
|
+
let {
|
|
13
|
+
"": unkeyedArgs,
|
|
50
14
|
bundle,
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
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();
|