jam 0.8.1 → 0.9.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 +49 -47
- package/bin/jam.js +166 -15
- package/package.json +32 -13
- package/types/index.d.ts +1 -0
- package/types/jam/index.d.ts +96 -0
- package/lib/platform.js +0 -72
- package/lib/resolve-binary.js +0 -30
- package/lib/resolve-optional-package.js +0 -43
package/README.md
CHANGED
|
@@ -1,60 +1,62 @@
|
|
|
1
1
|
# jam
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
## Install
|
|
6
|
-
|
|
7
|
-
```sh
|
|
8
|
-
npm install -g jam
|
|
9
|
-
jam --help
|
|
10
|
-
```
|
|
3
|
+
`jam` is an application server for isolated JavaScript. It runs JavaScript (and TypeScript) per request with isolated execution contexts, inspired by the PHP-FPM model.
|
|
11
4
|
|
|
12
5
|
## Usage
|
|
13
6
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
```ts
|
|
17
|
-
export default {
|
|
18
|
-
fetch(request: Request): Response {
|
|
19
|
-
return new Response("Hello from Jam");
|
|
20
|
-
}
|
|
21
|
-
};
|
|
22
|
-
```
|
|
23
|
-
|
|
24
|
-
Start Jam, pointing it at the scripts folder:
|
|
25
|
-
|
|
26
|
-
```sh
|
|
27
|
-
jam ./scripts
|
|
7
|
+
```bash
|
|
8
|
+
jam [flags] [scripts-dir]
|
|
28
9
|
```
|
|
29
10
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
```
|
|
33
|
-
|
|
11
|
+
Run `jam --help` for all options:
|
|
12
|
+
|
|
13
|
+
```text
|
|
14
|
+
Options:
|
|
15
|
+
--port <port> TCP port to listen on.
|
|
16
|
+
--host <host> Host or IP address to bind the TCP server to.
|
|
17
|
+
--unix <path> Unix socket path to listen on instead of TCP.
|
|
18
|
+
--php Enable PHP-style globals such as $_GET, $_POST, and $_SERVER.
|
|
19
|
+
--public <dir> Directory for static files (checked before script routes).
|
|
20
|
+
--access-log Enable per-request access log output.
|
|
21
|
+
--config <path> Path to jamconfig.json (default: ./jamconfig.json).
|
|
22
|
+
--env <KEY=VALUE> Set an env var for scripts; include multiple times.
|
|
23
|
+
--log <path|-> Log destination ('-' for stdout, otherwise a file path).
|
|
24
|
+
--log-level <error|warning|info|debug> Minimum log level to emit (default: info).
|
|
25
|
+
--tls-cert <path> Path to TLS certificate PEM file.
|
|
26
|
+
--tls-key <path> Path to TLS private key PEM file.
|
|
27
|
+
--timeout-ms <ms> Maximum script execution time in milliseconds.
|
|
28
|
+
--request-max-body-bytes <bytes> Maximum allowed request body size in bytes.
|
|
29
|
+
--request-max-header-bytes <bytes> Maximum allowed request header size in bytes.
|
|
30
|
+
--workers <count> Worker pool size (0 uses automatic sizing).
|
|
31
|
+
--worker-memory-mb <mb> Per-worker memory limit in MB.
|
|
32
|
+
--worker-max-requests <count> Recycle a worker after this many requests.
|
|
33
|
+
--mode <value> Runtime mode string (commonly production or development).
|
|
34
|
+
--error-page-404 <path> Path to a custom 404 error page.
|
|
35
|
+
--error-page-500 <path> Path to a custom 500 error page.
|
|
36
|
+
--help Print this help message and exit.
|
|
37
|
+
--version Print version and exit.
|
|
38
|
+
|
|
39
|
+
Examples:
|
|
40
|
+
jam
|
|
41
|
+
jam --port 3000
|
|
42
|
+
jam ./app
|
|
43
|
+
jam --php --public ./public ./app
|
|
34
44
|
```
|
|
35
45
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
To learn more, see [the documentation](https://github.com/mjackson/jam/tree/main/docs).
|
|
41
|
-
|
|
42
|
-
## How platform binaries are downloaded
|
|
43
|
-
|
|
44
|
-
The `jam` package uses platform-specific optional dependencies. During install, npm picks the matching package for your OS/CPU target:
|
|
45
|
-
|
|
46
|
-
- [`jam-darwin-arm64`](https://www.npmjs.com/package/jam-darwin-arm64)
|
|
47
|
-
- [`jam-darwin-x64`](https://www.npmjs.com/package/jam-darwin-x64)
|
|
48
|
-
- [`jam-linux-x64`](https://www.npmjs.com/package/jam-linux-x64)
|
|
49
|
-
- [`jam-linux-arm64`](https://www.npmjs.com/package/jam-linux-arm64)
|
|
50
|
-
|
|
51
|
-
Current support is macOS (`darwin`) and Linux glibc builds. Linux musl and Windows targets are not published yet.
|
|
46
|
+
Warning and error messages are written to stderr, while info/debug messages are written to stdout when logging to stdout.
|
|
47
|
+
When stderr is an interactive terminal, warning output is yellow and error output is red.
|
|
48
|
+
Set `NO_COLOR` in the environment to force no colors.
|
|
52
49
|
|
|
53
|
-
##
|
|
50
|
+
## Development
|
|
54
51
|
|
|
55
|
-
|
|
56
|
-
- `JAM_BINARY_PATH=<path>`: run a specific local binary instead of the optional dependency binary.
|
|
52
|
+
`jam` has two entry points with different roles:
|
|
57
53
|
|
|
58
|
-
|
|
54
|
+
- `bin/jam.js`: Node-facing dispatch shim for the npm package.
|
|
55
|
+
- This is what `npx jam` and `npm/yarn/pnpm` bin resolution executes.
|
|
56
|
+
- It picks the correct platform package (`jam-darwin-arm64`, `jam-darwin-x64`, `jam-linux-arm64`, `jam-linux-x64`), installs it if needed, and forwards execution to its binary.
|
|
57
|
+
- `src/entry.ts`: Bun runtime CLI entrypoint.
|
|
58
|
+
- This is what gets compiled into each platform binary.
|
|
59
|
+
- It should remain minimal and primarily call into `main` from `src/main.ts`.
|
|
60
|
+
- CI and release scripts build it for each target.
|
|
59
61
|
|
|
60
|
-
|
|
62
|
+
The fallback path used in `bin/jam.js` (`../src/entry.ts`) is for local development when running from a checked out repo and the platform package binary is unavailable.
|
package/bin/jam.js
CHANGED
|
@@ -1,29 +1,180 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
"use strict";
|
|
3
2
|
|
|
4
|
-
|
|
3
|
+
// This is the user-facing Node entrypoint for the npm `jam` package.
|
|
4
|
+
// `npx jam` and the package binary in `package.json` resolve here first.
|
|
5
|
+
//
|
|
6
|
+
// It exists because the published `jam` package is a tiny bootstrap layer:
|
|
7
|
+
// it detects the host platform, resolves the corresponding platform package
|
|
8
|
+
// (`jam-darwin-arm64`, `jam-darwin-x64`, `jam-linux-arm64`, `jam-linux-x64`),
|
|
9
|
+
// and executes the native Jam binary shipped by that package.
|
|
10
|
+
//
|
|
11
|
+
// If the platform package is not installed yet, this shim tries to install it
|
|
12
|
+
// on demand via `npm install <platform-package>@<version> --no-save`.
|
|
13
|
+
// If Bun is available in a local repo checkout and no platform package is
|
|
14
|
+
// present, it falls back to running `src/main.ts` directly for development.
|
|
15
|
+
//
|
|
16
|
+
// `src/entry.ts` is the Bun source entrypoint used by platform package builds;
|
|
17
|
+
// this file (`jam.js`) is the runtime dispatcher that selects and runs them.
|
|
5
18
|
|
|
6
|
-
|
|
19
|
+
import fs from "node:fs";
|
|
20
|
+
import path from "node:path";
|
|
21
|
+
import { spawnSync } from "node:child_process";
|
|
22
|
+
import { createRequire } from "node:module";
|
|
23
|
+
import { fileURLToPath } from "node:url";
|
|
24
|
+
|
|
25
|
+
let require = createRequire(import.meta.url);
|
|
26
|
+
let THIS_FILE = fileURLToPath(import.meta.url);
|
|
27
|
+
let THIS_DIR = path.dirname(THIS_FILE);
|
|
28
|
+
let PACKAGE_DIR = path.resolve(THIS_DIR, "..");
|
|
29
|
+
let PACKAGE_JSON = path.join(PACKAGE_DIR, "package.json");
|
|
30
|
+
|
|
31
|
+
function resolvePlatformPackageName() {
|
|
32
|
+
let key = `${process.platform}-${process.arch}`;
|
|
33
|
+
|
|
34
|
+
if (key === "darwin-arm64") {
|
|
35
|
+
return "jam-darwin-arm64";
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (key === "darwin-x64") {
|
|
39
|
+
return "jam-darwin-x64";
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (key === "linux-arm64") {
|
|
43
|
+
return "jam-linux-arm64";
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (key === "linux-x64") {
|
|
47
|
+
return "jam-linux-x64";
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return "";
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function runProcess(command, args, options) {
|
|
54
|
+
let result = spawnSync(command, args, {
|
|
55
|
+
stdio: "inherit",
|
|
56
|
+
...options
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
if (result.error) {
|
|
60
|
+
throw result.error;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (typeof result.status === "number") {
|
|
64
|
+
return result.status;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return 1;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function resolvePlatformBinary(packageName) {
|
|
71
|
+
let packageJsonPath = require.resolve(`${packageName}/package.json`);
|
|
72
|
+
return path.join(path.dirname(packageJsonPath), "bin", "jam");
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function getMainPackageVersion() {
|
|
76
|
+
let packageJson = JSON.parse(fs.readFileSync(PACKAGE_JSON, "utf8"));
|
|
77
|
+
return packageJson.version;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function installPlatformPackage(packageName) {
|
|
81
|
+
let version = getMainPackageVersion();
|
|
82
|
+
let packageSpec = `${packageName}@${version}`;
|
|
83
|
+
|
|
84
|
+
let npmHasInstall = false;
|
|
85
|
+
let npmVersionResult = spawnSync("npm", ["--version"], {
|
|
86
|
+
stdio: "ignore"
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
if (
|
|
90
|
+
typeof npmVersionResult.status === "number" &&
|
|
91
|
+
npmVersionResult.status === 0
|
|
92
|
+
) {
|
|
93
|
+
npmHasInstall = true;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
if (!npmHasInstall) {
|
|
97
|
+
throw new Error(
|
|
98
|
+
"npm is required to install the platform package automatically."
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
let result = runProcess(
|
|
103
|
+
"npm",
|
|
104
|
+
["install", packageSpec, "--no-save", "--no-audit", "--no-fund"],
|
|
105
|
+
{
|
|
106
|
+
cwd: PACKAGE_DIR
|
|
107
|
+
}
|
|
108
|
+
);
|
|
109
|
+
|
|
110
|
+
if (result !== 0) {
|
|
111
|
+
throw new Error(`npm install failed for ${packageSpec} (status: ${result}).`);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function runPlatformBinary(packageName, args) {
|
|
116
|
+
let binaryPath = resolvePlatformBinary(packageName);
|
|
117
|
+
return runProcess(binaryPath, args);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function maybeRunDevFallback(args) {
|
|
121
|
+
let sourceEntrypoint = path.resolve(THIS_DIR, "../src/entry.ts");
|
|
122
|
+
if (!fs.existsSync(sourceEntrypoint)) {
|
|
123
|
+
return false;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
runProcess("bun", [sourceEntrypoint, ...args]);
|
|
127
|
+
return true;
|
|
128
|
+
}
|
|
7
129
|
|
|
8
130
|
function main() {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
131
|
+
let packageName = resolvePlatformPackageName();
|
|
132
|
+
|
|
133
|
+
if (!packageName) {
|
|
134
|
+
process.stderr.write(
|
|
135
|
+
`[jam] Unsupported platform: ${process.platform}-${process.arch}. ` +
|
|
136
|
+
"Supported platforms: darwin-arm64, darwin-x64, linux-arm64, linux-x64.\n"
|
|
137
|
+
);
|
|
138
|
+
process.exit(1);
|
|
139
|
+
}
|
|
14
140
|
|
|
15
|
-
|
|
141
|
+
let args = process.argv.slice(2);
|
|
16
142
|
|
|
17
|
-
|
|
18
|
-
|
|
143
|
+
try {
|
|
144
|
+
let exitCode = runPlatformBinary(packageName, args);
|
|
145
|
+
process.exit(exitCode);
|
|
146
|
+
} catch (error) {
|
|
147
|
+
let installError = null;
|
|
148
|
+
if (
|
|
149
|
+
error instanceof Error &&
|
|
150
|
+
error.message.includes("Could not resolve") &&
|
|
151
|
+
error.message.includes(`${packageName}/package.json`)
|
|
152
|
+
) {
|
|
153
|
+
try {
|
|
154
|
+
process.stderr.write(
|
|
155
|
+
`[jam] Installing platform package ${packageName}...\n`
|
|
156
|
+
);
|
|
157
|
+
installPlatformPackage(packageName);
|
|
158
|
+
let exitCode = runPlatformBinary(packageName, args);
|
|
159
|
+
process.exit(exitCode);
|
|
160
|
+
} catch (secondError) {
|
|
161
|
+
installError = secondError;
|
|
162
|
+
}
|
|
19
163
|
}
|
|
20
164
|
|
|
21
|
-
if (
|
|
22
|
-
process.kill(process.pid, result.signal);
|
|
165
|
+
if (installError === null && maybeRunDevFallback(args)) {
|
|
23
166
|
return;
|
|
24
167
|
}
|
|
25
|
-
|
|
26
|
-
|
|
168
|
+
|
|
169
|
+
let message = installError instanceof Error
|
|
170
|
+
? installError.message
|
|
171
|
+
: error instanceof Error
|
|
172
|
+
? error.message
|
|
173
|
+
: String(error);
|
|
174
|
+
process.stderr.write(
|
|
175
|
+
`[jam] Could not find platform binary package ${packageName}. ` +
|
|
176
|
+
`Try reinstalling dependencies. (${message})\n`
|
|
177
|
+
);
|
|
27
178
|
process.exit(1);
|
|
28
179
|
}
|
|
29
180
|
}
|
package/package.json
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "jam",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"description": "An application server for isolated JavaScript",
|
|
5
5
|
"license": "MIT",
|
|
6
|
-
"type": "
|
|
6
|
+
"type": "module",
|
|
7
|
+
"types": "types/index.d.ts",
|
|
7
8
|
"repository": {
|
|
8
9
|
"type": "git",
|
|
9
10
|
"url": "git+https://github.com/mjackson/jam.git",
|
|
@@ -16,21 +17,39 @@
|
|
|
16
17
|
"bin": {
|
|
17
18
|
"jam": "bin/jam.js"
|
|
18
19
|
},
|
|
19
|
-
"optionalDependencies": {
|
|
20
|
-
"jam-darwin-arm64": "0.8.1",
|
|
21
|
-
"jam-darwin-x64": "0.8.1",
|
|
22
|
-
"jam-linux-x64": "0.8.1",
|
|
23
|
-
"jam-linux-arm64": "0.8.1"
|
|
24
|
-
},
|
|
25
20
|
"files": [
|
|
26
|
-
"bin",
|
|
27
|
-
"
|
|
28
|
-
"
|
|
21
|
+
"bin/jam.js",
|
|
22
|
+
"README.md",
|
|
23
|
+
"types/**"
|
|
29
24
|
],
|
|
25
|
+
"publishConfig": {
|
|
26
|
+
"executableFiles": [
|
|
27
|
+
"bin/jam.js"
|
|
28
|
+
]
|
|
29
|
+
},
|
|
30
|
+
"optionalDependencies": {
|
|
31
|
+
"jam-darwin-arm64": "0.9.0",
|
|
32
|
+
"jam-darwin-x64": "0.9.0",
|
|
33
|
+
"jam-linux-arm64": "0.9.0",
|
|
34
|
+
"jam-linux-x64": "0.9.0"
|
|
35
|
+
},
|
|
36
|
+
"dependencies": {
|
|
37
|
+
"@jridgewell/trace-mapping": "^0.3.31",
|
|
38
|
+
"typescript": "^5.6.3"
|
|
39
|
+
},
|
|
40
|
+
"devDependencies": {
|
|
41
|
+
"@types/node": "^22.15.31",
|
|
42
|
+
"bun-types": "^1.2.8"
|
|
43
|
+
},
|
|
30
44
|
"engines": {
|
|
31
|
-
"
|
|
45
|
+
"bun": ">=1.2"
|
|
32
46
|
},
|
|
33
47
|
"scripts": {
|
|
34
|
-
"
|
|
48
|
+
"lint": "eslint .",
|
|
49
|
+
"typecheck": "tsc -p tsconfig.json",
|
|
50
|
+
"test": "bun run test:unit && bun run test:integration",
|
|
51
|
+
"test:unit": "bun test ./src/**/*.test.ts",
|
|
52
|
+
"test:integration": "bun test ./test/*.test.ts",
|
|
53
|
+
"build:bin": "bun build ./src/entry.ts --compile --outfile ./dist/jam"
|
|
35
54
|
}
|
|
36
55
|
}
|
package/types/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
/// <reference path="./jam/index.d.ts" />
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
declare module "jam:template" {
|
|
2
|
+
export interface RenderTemplateResult {
|
|
3
|
+
body: string;
|
|
4
|
+
status: number;
|
|
5
|
+
headers: Headers;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export class TemplateRuntimeError extends Error {
|
|
9
|
+
templatePath: string;
|
|
10
|
+
constructor(templatePath: string, message: string);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export class TemplateCompileError extends Error {
|
|
14
|
+
constructor(templatePath: string, message: string);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export class TemplateSyntaxError extends Error {
|
|
18
|
+
line: number;
|
|
19
|
+
column: number;
|
|
20
|
+
constructor(templatePath: string, message: string, line: number, column: number);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export class TemplateCompiler {
|
|
24
|
+
constructor(maxEntries?: number);
|
|
25
|
+
renderTemplate(
|
|
26
|
+
templatePath: string,
|
|
27
|
+
scriptRoot: string,
|
|
28
|
+
runtimeContext: Record<string, unknown>,
|
|
29
|
+
request: Request
|
|
30
|
+
): Promise<RenderTemplateResult>;
|
|
31
|
+
getCacheSize(): number;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function renderTemplate(
|
|
35
|
+
templatePath: string,
|
|
36
|
+
scriptRoot: string,
|
|
37
|
+
runtimeContext: Record<string, unknown>,
|
|
38
|
+
request: Request
|
|
39
|
+
): Promise<RenderTemplateResult>;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
declare module "jam:test" {
|
|
43
|
+
export class AssertionError extends Error {
|
|
44
|
+
actual: unknown;
|
|
45
|
+
expected: unknown;
|
|
46
|
+
operator: string;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export namespace assert {
|
|
50
|
+
function ok(value: unknown, message?: string): asserts value;
|
|
51
|
+
function equal(actual: unknown, expected: unknown, message?: string): void;
|
|
52
|
+
function deepEqual(actual: unknown, expected: unknown, message?: string): void;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export interface SpyCall {
|
|
56
|
+
args: unknown[];
|
|
57
|
+
thisValue: unknown;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export interface Spy {
|
|
61
|
+
calls: SpyCall[];
|
|
62
|
+
restore(): void;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export function mock(
|
|
66
|
+
target: object,
|
|
67
|
+
methodName: string,
|
|
68
|
+
implementation: (...args: unknown[]) => unknown
|
|
69
|
+
): () => void;
|
|
70
|
+
|
|
71
|
+
export function spyOn(target: object, methodName: string): Spy;
|
|
72
|
+
|
|
73
|
+
export function restoreAll(): void;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
declare type JamPhpFile = {
|
|
77
|
+
name: string;
|
|
78
|
+
type: string;
|
|
79
|
+
tmp_name: string;
|
|
80
|
+
error: number;
|
|
81
|
+
size: number;
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
declare type JamPhpFiles = Record<string, JamPhpFile | JamPhpFile[]>;
|
|
85
|
+
|
|
86
|
+
declare type JamPhpServer = {
|
|
87
|
+
REQUEST_METHOD?: string;
|
|
88
|
+
REQUEST_URI?: string;
|
|
89
|
+
[key: string]: string | undefined;
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
declare const $_GET: Record<string, string> | null;
|
|
93
|
+
declare const $_POST: Record<string, string> | null;
|
|
94
|
+
declare const $_SERVER: JamPhpServer | null;
|
|
95
|
+
declare const $_FILES: JamPhpFiles | null;
|
|
96
|
+
declare const $_ENV: Record<string, string> | null;
|
package/lib/platform.js
DELETED
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
function parseNodeLibcFromReport(report) {
|
|
4
|
-
if (!report || !report.header) return null;
|
|
5
|
-
if (report.header.glibcVersionRuntime) return "glibc";
|
|
6
|
-
|
|
7
|
-
let reportText = JSON.stringify(report).toLowerCase();
|
|
8
|
-
if (reportText.includes("musl")) return "musl";
|
|
9
|
-
return null;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
function detectLibc(runtime) {
|
|
13
|
-
if (runtime.platform !== "linux") return null;
|
|
14
|
-
|
|
15
|
-
let forced = runtime.env.JAM_LIBC;
|
|
16
|
-
if (forced === "glibc" || forced === "musl") return forced;
|
|
17
|
-
|
|
18
|
-
let fromReport = parseNodeLibcFromReport(runtime.report);
|
|
19
|
-
if (fromReport) return fromReport;
|
|
20
|
-
|
|
21
|
-
return "glibc";
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
function resolveTarget(platform, arch, libc) {
|
|
25
|
-
if (platform === "darwin" && arch === "arm64") return "darwin-arm64";
|
|
26
|
-
if (platform === "darwin" && arch === "x64") return "darwin-x64";
|
|
27
|
-
|
|
28
|
-
if (platform === "linux" && arch === "x64" && libc === "glibc") return "linux-x64";
|
|
29
|
-
if (platform === "linux" && arch === "arm64" && libc === "glibc") return "linux-arm64";
|
|
30
|
-
if (platform === "linux" && libc === "musl") {
|
|
31
|
-
throw new Error(
|
|
32
|
-
`Linux musl is not supported yet: platform=${platform} arch=${arch} libc=${libc}`
|
|
33
|
-
);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
throw new Error(
|
|
37
|
-
`Unsupported platform for Jam npm package: platform=${platform} arch=${arch} libc=${libc || "n/a"}`
|
|
38
|
-
);
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
function binaryFileName(platform) {
|
|
42
|
-
return platform === "win32" ? "jam.exe" : "jam";
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
function getRuntimeDescriptor(overrides) {
|
|
46
|
-
let platform = overrides?.platform ?? process.platform;
|
|
47
|
-
let arch = overrides?.arch ?? process.arch;
|
|
48
|
-
let report =
|
|
49
|
-
overrides?.report ??
|
|
50
|
-
(process.report && typeof process.report.getReport === "function"
|
|
51
|
-
? process.report.getReport()
|
|
52
|
-
: null);
|
|
53
|
-
let env = overrides?.env ?? process.env;
|
|
54
|
-
|
|
55
|
-
let libc = detectLibc({ platform, env, report });
|
|
56
|
-
let target = resolveTarget(platform, arch, libc);
|
|
57
|
-
|
|
58
|
-
return {
|
|
59
|
-
arch,
|
|
60
|
-
libc,
|
|
61
|
-
platform,
|
|
62
|
-
target,
|
|
63
|
-
binaryName: binaryFileName(platform),
|
|
64
|
-
};
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
module.exports = {
|
|
68
|
-
binaryFileName,
|
|
69
|
-
detectLibc,
|
|
70
|
-
getRuntimeDescriptor,
|
|
71
|
-
resolveTarget,
|
|
72
|
-
};
|
package/lib/resolve-binary.js
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
let {
|
|
4
|
-
packageNameForTarget,
|
|
5
|
-
resolveOptionalPackageBinaryPath,
|
|
6
|
-
} = require("./resolve-optional-package");
|
|
7
|
-
let { getRuntimeDescriptor } = require("./platform");
|
|
8
|
-
|
|
9
|
-
function resolveBinaryPath() {
|
|
10
|
-
let fromEnv = process.env.JAM_BINARY_PATH;
|
|
11
|
-
if (fromEnv) return fromEnv;
|
|
12
|
-
|
|
13
|
-
let descriptor = getRuntimeDescriptor();
|
|
14
|
-
let optionalPath = resolveOptionalPackageBinaryPath(descriptor);
|
|
15
|
-
if (optionalPath) return optionalPath;
|
|
16
|
-
|
|
17
|
-
let packageName = packageNameForTarget(descriptor.target);
|
|
18
|
-
|
|
19
|
-
if (!packageName) {
|
|
20
|
-
throw new Error(`No optional dependency package is configured for ${descriptor.target}.`);
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
throw new Error(
|
|
24
|
-
`Jam optional dependency package not installed for ${descriptor.target}: ${packageName}. Try reinstalling with optional dependencies enabled.`
|
|
25
|
-
);
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
module.exports = {
|
|
29
|
-
resolveBinaryPath,
|
|
30
|
-
};
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
let fs = require("node:fs");
|
|
4
|
-
let path = require("node:path");
|
|
5
|
-
|
|
6
|
-
let TARGET_TO_PACKAGE = {
|
|
7
|
-
"darwin-arm64": "jam-darwin-arm64",
|
|
8
|
-
"darwin-x64": "jam-darwin-x64",
|
|
9
|
-
"linux-x64": "jam-linux-x64",
|
|
10
|
-
"linux-arm64": "jam-linux-arm64",
|
|
11
|
-
};
|
|
12
|
-
|
|
13
|
-
function packageNameForTarget(target) {
|
|
14
|
-
return TARGET_TO_PACKAGE[target] || null;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
function packageRootFromName(packageName) {
|
|
18
|
-
try {
|
|
19
|
-
let packageJsonPath = require.resolve(`${packageName}/package.json`, {
|
|
20
|
-
paths: [path.join(__dirname, "..")],
|
|
21
|
-
});
|
|
22
|
-
return path.dirname(packageJsonPath);
|
|
23
|
-
} catch {
|
|
24
|
-
return null;
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
function resolveOptionalPackageBinaryPath(runtimeDescriptor) {
|
|
29
|
-
let packageName = packageNameForTarget(runtimeDescriptor.target);
|
|
30
|
-
if (!packageName) return null;
|
|
31
|
-
|
|
32
|
-
let packageRoot = packageRootFromName(packageName);
|
|
33
|
-
if (!packageRoot) return null;
|
|
34
|
-
|
|
35
|
-
let binaryPath = path.join(packageRoot, "bin", runtimeDescriptor.binaryName);
|
|
36
|
-
if (!fs.existsSync(binaryPath)) return null;
|
|
37
|
-
return binaryPath;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
module.exports = {
|
|
41
|
-
packageNameForTarget,
|
|
42
|
-
resolveOptionalPackageBinaryPath,
|
|
43
|
-
};
|