@t8/serve 0.1.39 → 0.2.1
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 +20 -19
- package/dist/index.d.ts +6 -12
- package/dist/run.mjs +130 -40
- package/package.json +4 -3
- package/src/run.ts +26 -47
package/README.md
CHANGED
|
@@ -9,28 +9,29 @@ 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 notes
|
|
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 To switch to the SPA mode by handling all unmatched paths as "/".
|
|
22
27
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
28
|
+
--dirs --dirs assets public
|
|
29
|
+
To serve files from the listed subdirectories of <app_dir>.
|
|
30
|
+
By default, files are served from <app_dir>.
|
|
26
31
|
|
|
27
|
-
|
|
28
|
-
# - bundle './app/src/index.ts' to './app/dist/index.js'
|
|
29
|
-
# - serve files from './app' at 'localhost:3000' in the SPA mode
|
|
32
|
+
--watch To rebuild the bundled code if the source code changes.
|
|
30
33
|
|
|
31
|
-
|
|
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'
|
|
34
|
+
--minify To minify the bundled code.
|
|
34
35
|
```
|
|
35
36
|
|
|
36
37
|
<details>
|
|
@@ -39,7 +40,7 @@ npx @t8/serve 127.0.0.1:3000 app public dist -b
|
|
|
39
40
|
```
|
|
40
41
|
// package.json
|
|
41
42
|
"scripts": {
|
|
42
|
-
"play": "npx @t8/serve
|
|
43
|
+
"play": "npx @t8/serve playground -s -b"
|
|
43
44
|
}
|
|
44
45
|
```
|
|
45
46
|
|
|
@@ -76,7 +77,7 @@ webServer: {
|
|
|
76
77
|
```
|
|
77
78
|
// package.json
|
|
78
79
|
"scripts": {
|
|
79
|
-
"play": "npx @t8/serve
|
|
80
|
+
"play": "npx @t8/serve playground -s -b src/index.tsx"
|
|
80
81
|
}
|
|
81
82
|
```
|
|
82
83
|
|
|
@@ -127,7 +128,7 @@ webServer: {
|
|
|
127
128
|
{
|
|
128
129
|
"name": "app",
|
|
129
130
|
"scripts": {
|
|
130
|
-
"start": "npx @t8/serve
|
|
131
|
+
"start": "npx @t8/serve . -u 80 -b src/index.ts --watch"
|
|
131
132
|
}
|
|
132
133
|
}
|
|
133
134
|
```
|
package/dist/index.d.ts
CHANGED
|
@@ -22,8 +22,7 @@ type BundleConfig = {
|
|
|
22
22
|
};
|
|
23
23
|
|
|
24
24
|
type Config = {
|
|
25
|
-
/** Server URL. */
|
|
26
|
-
url?: string;
|
|
25
|
+
/** Server URL. */url?: string;
|
|
27
26
|
/**
|
|
28
27
|
* Server host.
|
|
29
28
|
*
|
|
@@ -35,8 +34,7 @@ type Config = {
|
|
|
35
34
|
*
|
|
36
35
|
* @defaultValue 3000
|
|
37
36
|
*/
|
|
38
|
-
port?: number;
|
|
39
|
-
/** Application path. */
|
|
37
|
+
port?: number; /** Application path. */
|
|
40
38
|
path?: string;
|
|
41
39
|
/**
|
|
42
40
|
* Public assets directories. If not provided, the application
|
|
@@ -47,12 +45,9 @@ type Config = {
|
|
|
47
45
|
* Enables single-page application (SPA) mode. If `true`, all
|
|
48
46
|
* unmatched URLs are served as "/".
|
|
49
47
|
*/
|
|
50
|
-
spa?: boolean;
|
|
51
|
-
/** Whether
|
|
52
|
-
|
|
53
|
-
/** Whether the bundle should be minified. */
|
|
54
|
-
minify?: boolean;
|
|
55
|
-
/** Whether to log to the console. */
|
|
48
|
+
spa?: boolean; /** Whether to rebuild whenever the bundled files change. */
|
|
49
|
+
watch?: boolean; /** Whether the bundle should be minified. */
|
|
50
|
+
minify?: boolean; /** Whether to log to the console. */
|
|
56
51
|
log?: boolean;
|
|
57
52
|
/**
|
|
58
53
|
* Bundle config.
|
|
@@ -62,8 +57,7 @@ type Config = {
|
|
|
62
57
|
* If `true`, it's equivalent to `{ input: "index.ts", output: "index.js" }`.
|
|
63
58
|
* If `string`, it's equivalent to `input` in `{ input, ouput: "index.js" }`.
|
|
64
59
|
*/
|
|
65
|
-
bundle?: boolean | string | BundleConfig | undefined;
|
|
66
|
-
/** Custom request handler. */
|
|
60
|
+
bundle?: boolean | string | BundleConfig | undefined; /** Custom request handler. */
|
|
67
61
|
onRequest?: (req?: IncomingMessage, res?: ServerResponse<IncomingMessage>) => void | Promise<void>;
|
|
68
62
|
};
|
|
69
63
|
|
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.1
|
|
3
|
+
"version": "0.2.1",
|
|
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();
|