@tdio/static-serve 0.0.4 → 0.0.5-dev.5

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
@@ -92,8 +92,10 @@ If `ROOT_DIR` is not specified, it defaults to the current directory (`./`).
92
92
  | Flag | Description | Default |
93
93
  |------|-------------|---------|
94
94
  | `--address` | The TCP address to listen on. | `:3000` |
95
+ | `--config` | Load options from a YAML config file. CLI scalar flags override config values; repeated `--proxy` and `--mount` flags append to config lists. | `""` |
96
+ | `--log-level` | Server log level. Supported values: `error`, `warn`, `info`, `debug`, `trace`. | `info` |
95
97
  | `--mount` | Mount specific directory to a virtual path (can be repeated). Format: `<physical_path>:<virtual_path>` or `src=<physical_path>,dst=<virtual_path>` | `""` |
96
- | `--proxy` | Proxy specific upstream to a virtual path (can be repeated). | `""` |
98
+ | `--proxy` | Proxy specific upstream to a virtual path (can be repeated), including `unix:///path.sock` upstreams. | `""` |
97
99
  | `--spa` | Enable SPA mode (redirects missing files to `/index.html`). | `false` |
98
100
  | `--logger-format` | Custom server logger format (Go template syntax). | `{{.Method}} {{.URL.Path}} {{.Status}} {{.RemoteAddr}} {{.UserAgent}}` |
99
101
  | `--tls-cert` | Path to TLS certificate file. Enables HTTPS (requires `--tls-key`). | `""` |
@@ -156,6 +158,8 @@ This is useful for:
156
158
 
157
159
  Example: `/api:http://localhost:8080`
158
160
 
161
+ Unix socket example: `/api:unix:///tmp/app.sock`
162
+
159
163
  _Note: This format automatically enables `change_origin` and `strip_prefix`._
160
164
 
161
165
  #### Advanced Format (Key-Value)
@@ -164,11 +168,72 @@ _Note: This format automatically enables `change_origin` and `strip_prefix`._
164
168
 
165
169
  Parameters:
166
170
  - `path`: The virtual path on the current server to match.
167
- - `url`: The upstream URL to forward requests to.
171
+ - `url`: The upstream URL to forward requests to. Supports `http://...`, `https://...`, and `unix:///path.sock` for HTTP over Unix domain sockets.
168
172
  - `change_origin`: Whether to rewrite the `Host` header to match the upstream URL. **Default: `true`**.
169
173
  - `strip_prefix`: Whether to strip the matched path prefix before forwarding the request. **Default: `true`**.
170
174
  - `method(s)`: pipe-separated list of HTTP methods to proxy. If specified, only these methods will be proxied. Others will pass through to local file serving or return 405. **Default: all methods**.
171
175
 
176
+ ### YAML Config
177
+
178
+ For larger setups, you can keep server options in YAML and load them with `--config`.
179
+
180
+ An example config template is included at `docs/static-serve.example.yaml`. It shows a fuller setup with SPA, proxy, mount, TLS, and CORS settings, but you will need to update the sample paths and upstreams for your environment before using it.
181
+
182
+ ```yaml
183
+ address: ":3001"
184
+ root_dir: "./"
185
+ spa: false
186
+ log_level: info
187
+
188
+ proxies:
189
+ - path: /
190
+ url: unix:///tmp/nextjs.sock
191
+ - path: /dify/console/api
192
+ url: http://192.168.0.57:5001/console/api
193
+ strip_prefix: true
194
+ - path: /dify/api
195
+ url: http://192.168.0.57:5001/api
196
+ strip_prefix: true
197
+
198
+ mounts:
199
+ - src: ./assets
200
+ dst: /static
201
+ ```
202
+
203
+ Run it with:
204
+
205
+ ```sh
206
+ static-serve --config ./static-serve.yaml
207
+ ```
208
+
209
+ CLI scalar flags override the YAML values:
210
+
211
+ ```sh
212
+ static-serve --config ./static-serve.yaml --address :4000 ./dist
213
+ ```
214
+
215
+ Repeated route flags append after the YAML lists:
216
+
217
+ ```sh
218
+ static-serve --config ./static-serve.yaml --proxy /:unix:///tmp/nextjs.sock --mount ./extra-assets:/extra
219
+ ```
220
+
221
+ Supported YAML fields mirror the existing CLI options:
222
+
223
+ - `address`
224
+ - `root_dir`
225
+ - `spa`
226
+ - `log_level`
227
+ - `logger_format`
228
+ - `tls_cert`
229
+ - `tls_key`
230
+ - `cors`
231
+ - `cors_allow_origins`
232
+ - `cors_allow_credentials`
233
+ - `cors_max_age`
234
+ - `proxies`
235
+ - `mounts`
236
+
172
237
  ### Examples
173
238
 
174
239
  **Serve current directory on port 8080:**
@@ -209,14 +274,21 @@ static-serve --mount "src=./config.json,dst=/api/config"
209
274
  ```
210
275
  Requests to `http://localhost:3000/api/users` will be forwarded to `http://localhost:8080/api/users` (if no local file exists).
211
276
 
212
- 3. **Method Filtering**: Only proxy POST and PUT requests to the upstream server.
277
+ 3. **Unix Socket Upstream**: Forward `/api` to an HTTP server listening on a Unix domain socket.
278
+ ```sh
279
+ static-serve --proxy "/api:unix:///tmp/app.sock"
280
+ static-serve --proxy "path=/api,url=unix:///tmp/app.sock"
281
+ ```
282
+ Requests to `http://localhost:3000/api/users` will be forwarded over the Unix socket to `/users` (if no local file exists).
283
+
284
+ 4. **Method Filtering**: Only proxy POST and PUT requests to the upstream server.
213
285
  ```sh
214
286
  static-serve --proxy "path=/api,url=http://localhost:8080,methods=POST|PUT"
215
287
  ```
216
288
  - `GET /api/users` → serves local `./api/users` or 404
217
289
  - `POST /api/users` → proxies to `http://localhost:8080/users` (if no local file exists)
218
290
 
219
- 4. **Local Override Pattern**: Override specific upstream assets with local versions.
291
+ 5. **Local Override Pattern**: Override specific upstream assets with local versions.
220
292
  ```sh
221
293
  # Create local override
222
294
  mkdir -p ./assets
@@ -228,6 +300,16 @@ static-serve --mount "src=./config.json,dst=/api/config"
228
300
  - `GET /assets/config.json` → serves local `./assets/config.json`
229
301
  - `GET /assets/other.js` → proxies to `http://cdn.example.com/assets/other.js`
230
302
 
303
+ 6. **Trace Proxy Requests**: Emit detailed per-request proxy logs such as `Proxying "GET ..."` only in trace mode.
304
+ ```sh
305
+ static-serve --log-level trace --proxy "/api:http://localhost:8080"
306
+ ```
307
+
308
+ 7. **Show Route Wiring Details**: Use debug mode to inspect mount and proxy registration without enabling full trace noise.
309
+ ```sh
310
+ static-serve --log-level debug --mount ./assets:/static --proxy "/api:http://localhost:8080"
311
+ ```
312
+
231
313
  **Serve over HTTPS:**
232
314
  ```sh
233
315
  static-serve --tls-cert ./cert.pem --tls-key ./key.pem ./public
@@ -0,0 +1,190 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __create = Object.create;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getProtoOf = Object.getPrototypeOf;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __copyProps = (to, from, except, desc) => {
10
+ if (from && typeof from === "object" || typeof from === "function") {
11
+ for (let key of __getOwnPropNames(from))
12
+ if (!__hasOwnProp.call(to, key) && key !== except)
13
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
14
+ }
15
+ return to;
16
+ };
17
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
18
+ // If the importer is in node compatibility mode or this is not an ESM
19
+ // file that has been converted to a CommonJS file using a Babel-
20
+ // compatible transform (i.e. "__esModule" has not been set), then set
21
+ // "default" to the CommonJS "module.exports" for node compatibility.
22
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
23
+ mod
24
+ ));
25
+
26
+ // lib/npm/node-platform.ts
27
+ var fs = require("fs");
28
+ var os = require("os");
29
+ var path = require("path");
30
+ var STATIC_SERVE_BINARY_PATH = process.env.STATIC_SERVE_BINARY_PATH || STATIC_SERVE_BINARY_PATH;
31
+ var PACKAGE_PREFIX = "static-serve";
32
+ var PACKAGE_SCOPE = "@tdio";
33
+ var knownPackages = {
34
+ "darwin arm64 LE": `${PACKAGE_SCOPE}/${PACKAGE_PREFIX}-darwin-arm64`,
35
+ "darwin x64 LE": `${PACKAGE_SCOPE}/${PACKAGE_PREFIX}-darwin-x64`,
36
+ "linux arm64 LE": `${PACKAGE_SCOPE}/${PACKAGE_PREFIX}-linux-arm64`,
37
+ "linux x64 LE": `${PACKAGE_SCOPE}/${PACKAGE_PREFIX}-linux-x64`,
38
+ "win32 arm64 LE": `${PACKAGE_SCOPE}/${PACKAGE_PREFIX}-win32-arm64`,
39
+ "win32 x64 LE": `${PACKAGE_SCOPE}/${PACKAGE_PREFIX}-win32-x64`
40
+ };
41
+ function pkgAndSubpathForCurrentPlatform() {
42
+ const platformKey = `${process.platform} ${os.arch()} ${os.endianness()}`;
43
+ const pkg = knownPackages[platformKey];
44
+ if (!pkg) {
45
+ throw new Error(`Unsupported platform: ${platformKey}`);
46
+ }
47
+ const subpath = process.platform === "win32" ? "static-serve.exe" : "static-serve";
48
+ return { pkg, subpath };
49
+ }
50
+ function pkgForSomeOtherPlatform() {
51
+ const libMainJS = require.resolve("@tdio/static-serve");
52
+ const nodeModulesDirectory = path.dirname(path.dirname(path.dirname(libMainJS)));
53
+ if (path.basename(nodeModulesDirectory) === "node_modules") {
54
+ for (const platformKey in knownPackages) {
55
+ try {
56
+ const pkg = knownPackages[platformKey];
57
+ if (fs.existsSync(path.join(nodeModulesDirectory, pkg))) return pkg;
58
+ } catch {
59
+ }
60
+ }
61
+ }
62
+ return null;
63
+ }
64
+ function downloadedBinPath(pkg, subpath) {
65
+ const staticServeLibDir = path.dirname(require.resolve("@tdio/static-serve"));
66
+ return path.join(staticServeLibDir, `downloaded-${pkg.replace("/", "-")}-${path.basename(subpath)}`);
67
+ }
68
+ function generateBinPath() {
69
+ if (STATIC_SERVE_BINARY_PATH) {
70
+ if (fs.existsSync(STATIC_SERVE_BINARY_PATH)) {
71
+ return STATIC_SERVE_BINARY_PATH;
72
+ }
73
+ console.warn(`[static-serve] Ignoring bad configuration: STATIC_SERVE_BINARY_PATH=${STATIC_SERVE_BINARY_PATH}`);
74
+ }
75
+ const { pkg, subpath } = pkgAndSubpathForCurrentPlatform();
76
+ let binPath;
77
+ try {
78
+ binPath = require.resolve(`${pkg}/${subpath}`);
79
+ } catch (e) {
80
+ binPath = downloadedBinPath(pkg, subpath);
81
+ if (!fs.existsSync(binPath)) {
82
+ try {
83
+ require.resolve(pkg);
84
+ } catch {
85
+ const otherPkg = pkgForSomeOtherPlatform();
86
+ if (otherPkg) {
87
+ let suggestions = `
88
+ Specifically the "${otherPkg}" package is present but this platform
89
+ needs the "${pkg}" package instead. People often get into this
90
+ situation by installing static-serve on Windows or macOS and copying "node_modules"
91
+ into a Docker image that runs Linux, or by copying "node_modules" between
92
+ Windows and WSL environments.
93
+
94
+ If you are installing with npm, you can try not copying the "node_modules"
95
+ directory when you copy the files over, and running "npm ci" or "npm install"
96
+ on the destination platform after the copy. Or you could consider using yarn
97
+ instead of npm which has built-in support for installing a package on multiple
98
+ platforms simultaneously.
99
+
100
+ If you are installing with yarn, you can try listing both this platform and the
101
+ other platform in your ".yarnrc.yml" file using the "supportedArchitectures"
102
+ feature: https://yarnpkg.com/configuration/yarnrc/#supportedArchitectures
103
+ Keep in mind that this means multiple copies of static-serve will be present.
104
+ `;
105
+ const packageDarwin_x64 = `${PACKAGE_SCOPE}/${PACKAGE_PREFIX}-darwin-x64`;
106
+ const packageDarwin_arm64 = `${PACKAGE_SCOPE}/${PACKAGE_PREFIX}-darwin-arm64`;
107
+ if (pkg === packageDarwin_x64 && otherPkg === packageDarwin_arm64 || pkg === packageDarwin_arm64 && otherPkg === packageDarwin_x64) {
108
+ suggestions = `
109
+ Specifically the "${otherPkg}" package is present but this platform
110
+ needs the "${pkg}" package instead. People often get into this
111
+ situation by installing static-serve with npm running inside of Rosetta 2 and then
112
+ trying to use it with node running outside of Rosetta 2, or vice versa (Rosetta
113
+ 2 is Apple's on-the-fly x86_64-to-arm64 translation service).
114
+
115
+ If you are installing with npm, you can try ensuring that both npm and node are
116
+ not running under Rosetta 2 and then reinstalling static-serve. This likely involves
117
+ changing how you installed npm and/or node. For example, installing node with
118
+ the universal installer here should work: https://nodejs.org/en/download/. Or
119
+ you could consider using yarn instead of npm which has built-in support for
120
+ installing a package on multiple platforms simultaneously.
121
+
122
+ If you are installing with yarn, you can try listing both "arm64" and "x64"
123
+ in your ".yarnrc.yml" file using the "supportedArchitectures" feature:
124
+ https://yarnpkg.com/configuration/yarnrc/#supportedArchitectures
125
+ Keep in mind that this means multiple copies of static-serve will be present.
126
+ `;
127
+ }
128
+ throw new Error(`
129
+ You installed static-serve for another platform than the one you're currently using.
130
+ This won't work because static-serve is written with native code and needs to
131
+ install a platform-specific binary executable.
132
+ ${suggestions}
133
+ `);
134
+ }
135
+ throw new Error(`The package "${pkg}" could not be found, and is needed by static-serve.
136
+
137
+ If you are installing static-serve with npm, make sure that you don't specify the
138
+ "--no-optional" or "--omit=optional" flags. The "optionalDependencies" feature
139
+ of "package.json" is used by static-serve to install the correct binary executable
140
+ for your current platform.`);
141
+ }
142
+ throw e;
143
+ }
144
+ }
145
+ return binPath;
146
+ }
147
+
148
+ // lib/npm/cli.ts
149
+ var child_process = require("child_process");
150
+ var path2 = require("path");
151
+ var fs2 = require("fs");
152
+ var PACKAGE_PREFIX2 = "static-serve";
153
+ function getLocalBuildPath() {
154
+ const platform = process.platform;
155
+ const arch = process.arch;
156
+ const goOs = platform === "win32" ? "windows" : platform;
157
+ const goArch = arch === "x64" ? "amd64" : arch;
158
+ const binFile = platform === "win32" ? `${PACKAGE_PREFIX2}-${goOs}-${goArch}.exe` : `${PACKAGE_PREFIX2}-${goOs}-${goArch}`;
159
+ const searchPaths = [
160
+ path2.join(__dirname, "..", "..", "out", binFile),
161
+ // from lib/npm/
162
+ path2.join(__dirname, "..", "..", "..", "out", binFile)
163
+ // from npm/static-serve/bin/
164
+ ];
165
+ for (const p of searchPaths) {
166
+ if (fs2.existsSync(p)) {
167
+ return p;
168
+ }
169
+ }
170
+ return "";
171
+ }
172
+ var binaryPath;
173
+ try {
174
+ binaryPath = generateBinPath();
175
+ } catch (err) {
176
+ const localPath = getLocalBuildPath();
177
+ if (localPath) {
178
+ binaryPath = localPath;
179
+ } else {
180
+ console.error(`Failed to locate binary for ${process.platform}-${process.arch}.`);
181
+ console.error(`Error: ${err.message}`);
182
+ process.exit(1);
183
+ }
184
+ }
185
+ var child = child_process.spawn(binaryPath, process.argv.slice(2), {
186
+ stdio: "inherit"
187
+ });
188
+ child.on("exit", (code) => {
189
+ process.exit(code ?? 0);
190
+ });
package/install.js ADDED
@@ -0,0 +1,259 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __create = Object.create;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getProtoOf = Object.getPrototypeOf;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __copyProps = (to, from, except, desc) => {
10
+ if (from && typeof from === "object" || typeof from === "function") {
11
+ for (let key of __getOwnPropNames(from))
12
+ if (!__hasOwnProp.call(to, key) && key !== except)
13
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
14
+ }
15
+ return to;
16
+ };
17
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
18
+ // If the importer is in node compatibility mode or this is not an ESM
19
+ // file that has been converted to a CommonJS file using a Babel-
20
+ // compatible transform (i.e. "__esModule" has not been set), then set
21
+ // "default" to the CommonJS "module.exports" for node compatibility.
22
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
23
+ mod
24
+ ));
25
+
26
+ // lib/npm/node-platform.ts
27
+ var fs = require("fs");
28
+ var os = require("os");
29
+ var path = require("path");
30
+ var STATIC_SERVE_BINARY_PATH = process.env.STATIC_SERVE_BINARY_PATH || STATIC_SERVE_BINARY_PATH;
31
+ var isValidBinaryPath = (x) => !!x && fs.existsSync(x);
32
+ var PACKAGE_PREFIX = "static-serve";
33
+ var PACKAGE_SCOPE = "@tdio";
34
+ var knownPackages = {
35
+ "darwin arm64 LE": `${PACKAGE_SCOPE}/${PACKAGE_PREFIX}-darwin-arm64`,
36
+ "darwin x64 LE": `${PACKAGE_SCOPE}/${PACKAGE_PREFIX}-darwin-x64`,
37
+ "linux arm64 LE": `${PACKAGE_SCOPE}/${PACKAGE_PREFIX}-linux-arm64`,
38
+ "linux x64 LE": `${PACKAGE_SCOPE}/${PACKAGE_PREFIX}-linux-x64`,
39
+ "win32 arm64 LE": `${PACKAGE_SCOPE}/${PACKAGE_PREFIX}-win32-arm64`,
40
+ "win32 x64 LE": `${PACKAGE_SCOPE}/${PACKAGE_PREFIX}-win32-x64`
41
+ };
42
+ function pkgAndSubpathForCurrentPlatform() {
43
+ const platformKey = `${process.platform} ${os.arch()} ${os.endianness()}`;
44
+ const pkg = knownPackages[platformKey];
45
+ if (!pkg) {
46
+ throw new Error(`Unsupported platform: ${platformKey}`);
47
+ }
48
+ const subpath = process.platform === "win32" ? "static-serve.exe" : "static-serve";
49
+ return { pkg, subpath };
50
+ }
51
+ function downloadedBinPath(pkg, subpath) {
52
+ const staticServeLibDir = path.dirname(require.resolve("@tdio/static-serve"));
53
+ return path.join(staticServeLibDir, `downloaded-${pkg.replace("/", "-")}-${path.basename(subpath)}`);
54
+ }
55
+
56
+ // lib/npm/install.ts
57
+ var fs2 = require("fs");
58
+ var os2 = require("os");
59
+ var path2 = require("path");
60
+ var zlib = require("zlib");
61
+ var https = require("https");
62
+ var child_process = require("child_process");
63
+ var versionFromPackageJSON = require(path2.join(__dirname, "package.json")).version;
64
+ var toPath = path2.join(__dirname, "bin", "static-serve");
65
+ var isToPathJS = true;
66
+ function validateBinaryVersion(...command) {
67
+ command.push("-v");
68
+ let stdout;
69
+ try {
70
+ stdout = child_process.execFileSync(command.shift(), command, {
71
+ // Without this, this install script strangely crashes with the error
72
+ // "EACCES: permission denied, write" but only on Ubuntu Linux when node is
73
+ // installed from the Snap Store. This is not a problem when you download
74
+ // the official version of node. The problem appears to be that stderr
75
+ // (i.e. file descriptor 2) isn't writable?
76
+ stdio: "pipe"
77
+ }).toString().trim();
78
+ } catch (err) {
79
+ if (os2.platform() === "darwin" && /_SecTrustEvaluateWithError/.test(err + "")) {
80
+ let osVersion = "this version of macOS";
81
+ try {
82
+ osVersion = "macOS " + child_process.execFileSync("sw_vers", ["-productVersion"]).toString().trim();
83
+ } catch {
84
+ }
85
+ throw new Error(`The "static-serve" package cannot be installed because ${osVersion} is too outdated.
86
+
87
+ The Go compiler (which static-serve relies on) no longer supports ${osVersion},
88
+ which means the "static-serve" binary executable can't be run. You can either:
89
+
90
+ * Update your version of macOS to one that the Go compiler supports
91
+ * Build static-serve yourself using an older version of the Go compiler
92
+ `);
93
+ }
94
+ throw err;
95
+ }
96
+ const versionMatch = stdout.match(/version\s+([^\s,]+)/);
97
+ if (versionMatch && versionMatch[1] !== versionFromPackageJSON) {
98
+ throw new Error(`Expected ${JSON.stringify(versionFromPackageJSON)} but got ${JSON.stringify(versionMatch[1])}`);
99
+ }
100
+ }
101
+ function isYarn() {
102
+ const { npm_config_user_agent } = process.env;
103
+ if (npm_config_user_agent) {
104
+ return /\byarn\//.test(npm_config_user_agent);
105
+ }
106
+ return false;
107
+ }
108
+ function fetch(url) {
109
+ return new Promise((resolve, reject) => {
110
+ https.get(url, (res) => {
111
+ if ((res.statusCode === 301 || res.statusCode === 302) && res.headers.location)
112
+ return fetch(res.headers.location).then(resolve, reject);
113
+ if (res.statusCode !== 200)
114
+ return reject(new Error(`Server responded with ${res.statusCode}`));
115
+ let chunks = [];
116
+ res.on("data", (chunk) => chunks.push(chunk));
117
+ res.on("end", () => resolve(Buffer.concat(chunks)));
118
+ }).on("error", reject);
119
+ });
120
+ }
121
+ function extractFileFromTarGzip(buffer, subpath) {
122
+ try {
123
+ buffer = zlib.unzipSync(buffer);
124
+ } catch (err) {
125
+ throw new Error(`Invalid gzip data in archive: ${err && err.message || err}`);
126
+ }
127
+ let str = (i, n) => String.fromCharCode(...buffer.subarray(i, i + n)).replace(/\0.*$/, "");
128
+ let offset = 0;
129
+ subpath = `package/${subpath}`;
130
+ while (offset < buffer.length) {
131
+ let name = str(offset, 100);
132
+ let size = parseInt(str(offset + 124, 12), 8);
133
+ offset += 512;
134
+ if (!isNaN(size)) {
135
+ if (name === subpath) return buffer.subarray(offset, offset + size);
136
+ offset += size + 511 & ~511;
137
+ }
138
+ }
139
+ throw new Error(`Could not find ${JSON.stringify(subpath)} in archive`);
140
+ }
141
+ function installUsingNPM(pkg, subpath, binPath) {
142
+ const env = { ...process.env, npm_config_global: void 0 };
143
+ const staticServeLibDir = path2.dirname(require.resolve("@tdio/static-serve"));
144
+ const installDir = path2.join(staticServeLibDir, "npm-install");
145
+ fs2.mkdirSync(installDir, { recursive: true });
146
+ try {
147
+ fs2.writeFileSync(path2.join(installDir, "package.json"), "{}");
148
+ child_process.execSync(
149
+ `npm install --loglevel=error --prefer-offline --no-audit --progress=false ${pkg}@${versionFromPackageJSON}`,
150
+ { cwd: installDir, stdio: "pipe", env }
151
+ );
152
+ const installedBinPath = path2.join(installDir, "node_modules", pkg, subpath);
153
+ fs2.renameSync(installedBinPath, binPath);
154
+ } finally {
155
+ try {
156
+ removeRecursive(installDir);
157
+ } catch {
158
+ }
159
+ }
160
+ }
161
+ function removeRecursive(dir) {
162
+ for (const entry of fs2.readdirSync(dir)) {
163
+ const entryPath = path2.join(dir, entry);
164
+ let stats;
165
+ try {
166
+ stats = fs2.lstatSync(entryPath);
167
+ } catch {
168
+ continue;
169
+ }
170
+ if (stats.isDirectory()) removeRecursive(entryPath);
171
+ else fs2.unlinkSync(entryPath);
172
+ }
173
+ fs2.rmdirSync(dir);
174
+ }
175
+ function applyManualBinaryPathOverride(overridePath) {
176
+ const pathString = JSON.stringify(overridePath);
177
+ fs2.writeFileSync(toPath, `#!/usr/bin/env node
178
+ require('child_process').execFileSync(${pathString}, process.argv.slice(2), { stdio: 'inherit' });
179
+ `);
180
+ const libMain = path2.join(__dirname, "lib", "main.js");
181
+ const code = fs2.readFileSync(libMain, "utf8");
182
+ fs2.writeFileSync(libMain, `var STATIC_SERVE_BINARY_PATH = ${pathString};
183
+ ${code}`);
184
+ }
185
+ function maybeOptimizePackage(binPath) {
186
+ if (os2.platform() !== "win32" && !isYarn()) {
187
+ const tempPath = path2.join(__dirname, "bin-static-serve");
188
+ try {
189
+ fs2.linkSync(binPath, tempPath);
190
+ fs2.renameSync(tempPath, toPath);
191
+ isToPathJS = false;
192
+ fs2.unlinkSync(tempPath);
193
+ } catch {
194
+ }
195
+ }
196
+ }
197
+ async function downloadDirectlyFromNPM(pkg, subpath, binPath) {
198
+ const pkgName = pkg.replace("@tdio/", "");
199
+ const url = `https://registry.npmjs.org/${pkg}/-/${pkgName}-${versionFromPackageJSON}.tgz`;
200
+ console.error(`[static-serve] Trying to download ${JSON.stringify(url)}`);
201
+ try {
202
+ fs2.writeFileSync(binPath, extractFileFromTarGzip(await fetch(url), subpath));
203
+ fs2.chmodSync(binPath, 493);
204
+ } catch (e) {
205
+ console.error(`[static-serve] Failed to download ${JSON.stringify(url)}: ${e && e.message || e}`);
206
+ throw e;
207
+ }
208
+ }
209
+ async function checkAndPreparePackage() {
210
+ if (isValidBinaryPath(STATIC_SERVE_BINARY_PATH)) {
211
+ if (!fs2.existsSync(STATIC_SERVE_BINARY_PATH)) {
212
+ console.warn(`[static-serve] Ignoring bad configuration: STATIC_SERVE_BINARY_PATH=${STATIC_SERVE_BINARY_PATH}`);
213
+ } else {
214
+ applyManualBinaryPathOverride(STATIC_SERVE_BINARY_PATH);
215
+ return;
216
+ }
217
+ }
218
+ const { pkg, subpath } = pkgAndSubpathForCurrentPlatform();
219
+ let binPath;
220
+ let downloadedBinPathToCleanup;
221
+ try {
222
+ binPath = require.resolve(`${pkg}/${subpath}`);
223
+ } catch (e) {
224
+ console.error(`[static-serve] Failed to find package "${pkg}" on the file system
225
+
226
+ This can happen if you use the "--no-optional" flag. The "optionalDependencies"
227
+ package.json feature is used by static-serve to install the correct binary executable
228
+ for your current platform. This install script will now attempt to work around
229
+ this. If that fails, you need to remove the "--no-optional" flag to use static-serve.
230
+ `);
231
+ binPath = downloadedBinPath(pkg, subpath);
232
+ try {
233
+ console.error(`[static-serve] Trying to install package "${pkg}" using npm`);
234
+ installUsingNPM(pkg, subpath, binPath);
235
+ } catch (e2) {
236
+ console.error(`[static-serve] Failed to install package "${pkg}" using npm: ${e2 && e2.message || e2}`);
237
+ try {
238
+ await downloadDirectlyFromNPM(pkg, subpath, binPath);
239
+ downloadedBinPathToCleanup = binPath;
240
+ } catch (e3) {
241
+ throw new Error(`Failed to install package "${pkg}"`);
242
+ }
243
+ }
244
+ }
245
+ maybeOptimizePackage(binPath);
246
+ if (downloadedBinPathToCleanup && !isToPathJS) {
247
+ try {
248
+ fs2.unlinkSync(downloadedBinPathToCleanup);
249
+ } catch {
250
+ }
251
+ }
252
+ }
253
+ checkAndPreparePackage().then(() => {
254
+ if (isToPathJS) {
255
+ validateBinaryVersion(process.execPath, toPath);
256
+ } else {
257
+ validateBinaryVersion(toPath);
258
+ }
259
+ });
package/main.js ADDED
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // lib/npm/main.ts
21
+ var main_exports = {};
22
+ __export(main_exports, {
23
+ default: () => main_default
24
+ });
25
+ module.exports = __toCommonJS(main_exports);
26
+ var main_default = {};
package/package.json CHANGED
@@ -1,9 +1,10 @@
1
1
  {
2
2
  "name": "@tdio/static-serve",
3
- "version": "0.0.4",
3
+ "version": "0.0.5-dev.5",
4
4
  "description": "A simple, lightweight static file server written in Go, designed with features for modern web application serving",
5
+ "main": "main.js",
5
6
  "bin": {
6
- "static-serve": "./bin/cli.js"
7
+ "static-serve": "bin/static-serve"
7
8
  },
8
9
  "author": "allex <allex.wxn@gmail.com> (http://iallex.com/)",
9
10
  "repository": {
@@ -20,15 +21,22 @@
20
21
  "arm64"
21
22
  ],
22
23
  "files": [
23
- "bin/cli.js"
24
+ "bin",
25
+ "install.js"
24
26
  ],
25
27
  "license": "MIT",
28
+ "scripts": {
29
+ "postinstall": "node install.js"
30
+ },
26
31
  "optionalDependencies": {
27
- "@tdio/static-serve-darwin-x64": "0.0.4",
28
- "@tdio/static-serve-darwin-arm64": "0.0.4",
29
- "@tdio/static-serve-linux-x64": "0.0.4",
30
- "@tdio/static-serve-linux-arm64": "0.0.4",
31
- "@tdio/static-serve-win32-x64": "0.0.4",
32
- "@tdio/static-serve-win32-arm64": "0.0.4"
32
+ "@tdio/static-serve-darwin-x64": "0.0.5-dev.5",
33
+ "@tdio/static-serve-darwin-arm64": "0.0.5-dev.5",
34
+ "@tdio/static-serve-linux-x64": "0.0.5-dev.5",
35
+ "@tdio/static-serve-linux-arm64": "0.0.5-dev.5",
36
+ "@tdio/static-serve-win32-x64": "0.0.5-dev.5",
37
+ "@tdio/static-serve-win32-arm64": "0.0.5-dev.5"
38
+ },
39
+ "engines": {
40
+ "node": ">=18"
33
41
  }
34
42
  }
package/bin/cli.js DELETED
@@ -1,51 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- const { spawn } = require('child_process');
4
- const path = require('path');
5
- const fs = require('fs');
6
-
7
- const PACKAGE_PREFIX = 'static-serve'; // Must match build-npm.js
8
- const PACKAGE_SCOPE = '@tdio'; // Must match build-npm.js
9
-
10
- // Map generic 'x64' to Node's arch if needed, but usually they match.
11
- // Node: x64, arm64, ia32, etc.
12
- const platform = process.platform;
13
- const arch = process.arch;
14
-
15
- const targetPackage = `${PACKAGE_SCOPE}/${PACKAGE_PREFIX}-${platform}-${arch}`
16
-
17
- let binaryPath;
18
-
19
- try {
20
- // Resolve the package.json of the platform-specific package
21
- // This throws if the package is not installed
22
- const pkgJsonPath = require.resolve(`${targetPackage}/package.json`);
23
- const pkgDir = path.dirname(pkgJsonPath);
24
-
25
- // Binary name is predictable: static-serve on Unix, static-serve.exe on Windows
26
- const binFile = platform === 'win32' ? `${PACKAGE_PREFIX}.exe` : PACKAGE_PREFIX;
27
- binaryPath = path.join(pkgDir, binFile);
28
-
29
- } catch (err) {
30
- // Fallback: Check if we are running from the source repo/local build
31
- // Useful for development
32
- const localBuildPath = path.join(__dirname, '..', 'out', `${PACKAGE_PREFIX}-${platform === 'win32' ? 'windows' : platform}-${arch === 'x64' ? 'amd64' : arch}${platform === 'win32' ? '.exe' : ''}`);
33
-
34
- if (fs.existsSync(localBuildPath)) {
35
- binaryPath = localBuildPath;
36
- } else {
37
- console.error(`Failed to locate binary for ${platform}-${arch}.`);
38
- console.error(`Tried package: ${targetPackage}`);
39
- console.error(`Error: ${err.message}`);
40
- process.exit(1);
41
- }
42
- }
43
-
44
- const child = spawn(binaryPath, process.argv.slice(2), {
45
- stdio: 'inherit'
46
- });
47
-
48
- child.on('exit', (code) => {
49
- process.exit(code);
50
- });
51
-