@torba/java 1.0.7
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 +63 -0
- package/dist/index.cjs +225 -0
- package/dist/index.d.cts +107 -0
- package/dist/index.d.cts.map +1 -0
- package/dist/index.d.mts +107 -0
- package/dist/index.d.mts.map +1 -0
- package/dist/index.mjs +223 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +28 -0
package/README.md
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# @torba/java
|
|
2
|
+
|
|
3
|
+
OpenJDK runtime support for torba — auto-installs an [Eclipse Temurin](https://adoptium.net) JDK and exposes `${java_home}` and `${java_bin}` as standardized vars so loader templates can reference a portable Java binary.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```sh
|
|
8
|
+
npm install @torba/java
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
import { resolveJava } from '@torba/java';
|
|
15
|
+
import { resolveLwjgl3ify } from '@torba/lwjgl3ify';
|
|
16
|
+
|
|
17
|
+
const lw = await resolveLwjgl3ify({ version: '3.0.16' });
|
|
18
|
+
const jav = await resolveJava({ version: '21' });
|
|
19
|
+
|
|
20
|
+
return {
|
|
21
|
+
manifest: {
|
|
22
|
+
artifacts: [lw.artifacts, jav.artifacts],
|
|
23
|
+
vars: { ...lw.vars, ...jav.vars },
|
|
24
|
+
launch: lw.launch, // launch.command is `${java_bin}` already
|
|
25
|
+
},
|
|
26
|
+
};
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### Version input
|
|
30
|
+
|
|
31
|
+
- **Major** — `'21'`, `'17'` — resolves to the latest GA release for that major.
|
|
32
|
+
- **Full version** — `'21.0.11+10'` — exact Adoptium release name (`jdk-` prefix and `-LTS` suffix are tolerated).
|
|
33
|
+
|
|
34
|
+
### Options
|
|
35
|
+
|
|
36
|
+
```ts
|
|
37
|
+
resolveJava({
|
|
38
|
+
version: string,
|
|
39
|
+
vendor?: 'openjdk', // only OpenJDK (Temurin) is supported today
|
|
40
|
+
platforms?: JavaPlatform[], // override the default OS/arch matrix
|
|
41
|
+
apiBase?: string, // override the Adoptium API base URL
|
|
42
|
+
});
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## How it works
|
|
46
|
+
|
|
47
|
+
1. Resolves the requested `version` against `https://api.adoptium.net/v3/`. Major versions hit `/feature_releases/<n>/ga` (latest GA); full versions hit `/release_name/eclipse/jdk-<v>` (exact).
|
|
48
|
+
2. Queries each platform (linux/osx/windows × x86_64+aarch64) in parallel; soft-skips combinations that don't ship a binary.
|
|
49
|
+
3. Emits one `Artifact` per platform pointing at the GitHub-hosted release asset, with sha256 from the API and OS+arch rules so only the matching binary downloads at install time.
|
|
50
|
+
4. Each artifact has an `extract: dump` rule pointing at `${root}/runtimes/jdk-<major>/`, so the JDK lands at `${root}/runtimes/jdk-<major>/jdk-<full>/`.
|
|
51
|
+
5. Sets `java_home` (per OS — macOS gets the `/Contents/Home` suffix) and `java_bin` (`${java_home}/bin/java` on POSIX, `${java_home}/bin/java.exe` on Windows).
|
|
52
|
+
|
|
53
|
+
`@torba/installer` extracts both `.zip` (Windows) and `.tar.gz` / `.tgz` (Linux/macOS) archives, preserving the executable bit on tar entries so `bin/java` stays runnable without a chmod step.
|
|
54
|
+
|
|
55
|
+
## Standard `${java_home}` and `${java_bin}` vars
|
|
56
|
+
|
|
57
|
+
Every torba template returned by `@torba/minecraft` (and by any loader built on it) now sets `launch.command = '${java_bin}'`, with `java_bin` defaulting to the literal `'java'` (PATH lookup). When you spread `@torba/java`'s vars over the loader's, the var resolves to the auto-installed JDK instead — without any change to the launch command.
|
|
58
|
+
|
|
59
|
+
## Notes
|
|
60
|
+
|
|
61
|
+
- **Vendor**: only `openjdk` (Eclipse Temurin) is supported. Adding Liberica, Zulu, GraalVM is a matter of plugging in another resolver.
|
|
62
|
+
- **macOS app bundles**: macOS Temurin tarballs ship as `.app` bundles with `Contents/MacOS/_CodeSignature/...`. `${java_home}` includes the `/Contents/Home` suffix automatically.
|
|
63
|
+
- **Disk usage**: each JDK is ~200 MB compressed, ~500 MB extracted. The archive is left in `${root}/runtimes/jdk-<major>/.cache/` after install — delete the `.cache` folder to reclaim space.
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
+
let _torba_core = require("@torba/core");
|
|
3
|
+
|
|
4
|
+
//#region lib/resolver.ts
|
|
5
|
+
/**
|
|
6
|
+
* Resolver for OpenJDK builds from the Eclipse Adoptium (Temurin) distribution.
|
|
7
|
+
*
|
|
8
|
+
* Adoptium publishes a public asset API at `https://api.adoptium.net/v3/`.
|
|
9
|
+
* We use two endpoints depending on the version input shape:
|
|
10
|
+
*
|
|
11
|
+
* - Major-only (`'21'`, `'17'`) → `/feature_releases/<major>/ga` (latest GA)
|
|
12
|
+
* - Full version (`'21.0.11+10'`) → `/release_name/<vendor>/jdk-<v>` (exact)
|
|
13
|
+
*
|
|
14
|
+
* Each platform (os × arch) is queried separately with `image_type=jdk` and
|
|
15
|
+
* `jvm_impl=hotspot`. Releases that don't ship a binary for a given platform
|
|
16
|
+
* are soft-skipped — the resulting `JavaRelease` only contains the platforms
|
|
17
|
+
* with a real binary.
|
|
18
|
+
*/
|
|
19
|
+
const ADOPTIUM_BASE = "https://api.adoptium.net/v3";
|
|
20
|
+
const VENDOR = "eclipse";
|
|
21
|
+
const DEFAULT_PLATFORMS = [
|
|
22
|
+
{
|
|
23
|
+
os: "linux",
|
|
24
|
+
arch: "x86_64",
|
|
25
|
+
adoptiumOs: "linux",
|
|
26
|
+
adoptiumArch: "x64",
|
|
27
|
+
homeSuffix: ""
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
os: "linux",
|
|
31
|
+
arch: "aarch64",
|
|
32
|
+
adoptiumOs: "linux",
|
|
33
|
+
adoptiumArch: "aarch64",
|
|
34
|
+
homeSuffix: ""
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
os: "osx",
|
|
38
|
+
arch: "x86_64",
|
|
39
|
+
adoptiumOs: "mac",
|
|
40
|
+
adoptiumArch: "x64",
|
|
41
|
+
homeSuffix: "/Contents/Home"
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
os: "osx",
|
|
45
|
+
arch: "aarch64",
|
|
46
|
+
adoptiumOs: "mac",
|
|
47
|
+
adoptiumArch: "aarch64",
|
|
48
|
+
homeSuffix: "/Contents/Home"
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
os: "windows",
|
|
52
|
+
arch: "x86_64",
|
|
53
|
+
adoptiumOs: "windows",
|
|
54
|
+
adoptiumArch: "x64",
|
|
55
|
+
homeSuffix: ""
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
os: "windows",
|
|
59
|
+
arch: "aarch64",
|
|
60
|
+
adoptiumOs: "windows",
|
|
61
|
+
adoptiumArch: "aarch64",
|
|
62
|
+
homeSuffix: ""
|
|
63
|
+
}
|
|
64
|
+
];
|
|
65
|
+
function normalizeInput(input) {
|
|
66
|
+
let v = input.trim();
|
|
67
|
+
if (v.startsWith("jdk-")) v = v.slice(4);
|
|
68
|
+
v = v.replace(/-LTS$/, "");
|
|
69
|
+
if (/^\d+$/.test(v)) return {
|
|
70
|
+
kind: "major",
|
|
71
|
+
raw: v
|
|
72
|
+
};
|
|
73
|
+
return {
|
|
74
|
+
kind: "full",
|
|
75
|
+
raw: v
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
function commonQuery(platform) {
|
|
79
|
+
return new URLSearchParams({
|
|
80
|
+
image_type: "jdk",
|
|
81
|
+
architecture: platform.adoptiumArch,
|
|
82
|
+
os: platform.adoptiumOs,
|
|
83
|
+
jvm_impl: "hotspot",
|
|
84
|
+
heap_size: "normal",
|
|
85
|
+
vendor: VENDOR
|
|
86
|
+
}).toString();
|
|
87
|
+
}
|
|
88
|
+
async function fetchPlatform(apiBase, platform, version) {
|
|
89
|
+
const res = await (0, _torba_core.fetchWithRetry)(`${apiBase}${version.kind === "major" ? `/assets/feature_releases/${version.raw}/ga?${commonQuery(platform)}&page_size=1&sort_order=DESC` : `/assets/release_name/${VENDOR}/${encodeURIComponent(`jdk-${version.raw}`)}?${commonQuery(platform)}`}`, { headers: { Accept: "application/json" } });
|
|
90
|
+
if (res.status === 404) return null;
|
|
91
|
+
if (!res.ok) throw new Error(`Adoptium API ${res.status} ${res.statusText} for ${platform.adoptiumOs}/${platform.adoptiumArch}`);
|
|
92
|
+
const body = await res.json();
|
|
93
|
+
const release = Array.isArray(body) ? body[0] : body;
|
|
94
|
+
if (!release || !release.binaries || release.binaries.length === 0) return null;
|
|
95
|
+
const binary = release.binaries.find((b) => b.architecture === platform.adoptiumArch && b.os === platform.adoptiumOs && b.image_type === "jdk");
|
|
96
|
+
if (!binary) return null;
|
|
97
|
+
return {
|
|
98
|
+
release,
|
|
99
|
+
binary
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Resolve an OpenJDK release across all requested platforms. Returns a
|
|
104
|
+
* single `JavaRelease` with one entry per platform that has a binary
|
|
105
|
+
* available — platforms that don't ship a build for this release are
|
|
106
|
+
* silently dropped from `binaries`, so callers don't have to handle the
|
|
107
|
+
* "linux x64 exists, windows aarch64 doesn't" case explicitly.
|
|
108
|
+
*/
|
|
109
|
+
async function resolveOpenjdk(version, options = {}) {
|
|
110
|
+
const apiBase = options.apiBase ?? ADOPTIUM_BASE;
|
|
111
|
+
const platforms = options.platforms ?? DEFAULT_PLATFORMS;
|
|
112
|
+
const parsed = normalizeInput(version);
|
|
113
|
+
const matched = (await Promise.all(platforms.map(async (p) => {
|
|
114
|
+
const found = await fetchPlatform(apiBase, p, parsed);
|
|
115
|
+
return found ? {
|
|
116
|
+
platform: p,
|
|
117
|
+
...found
|
|
118
|
+
} : null;
|
|
119
|
+
}))).filter((x) => x !== null);
|
|
120
|
+
if (matched.length === 0) throw new Error(`No OpenJDK binaries found for version '${version}' across requested platforms.`);
|
|
121
|
+
const nameCounts = /* @__PURE__ */ new Map();
|
|
122
|
+
for (const m of matched) nameCounts.set(m.release.release_name, (nameCounts.get(m.release.release_name) ?? 0) + 1);
|
|
123
|
+
const releaseName = [...nameCounts.entries()].sort((a, b) => b[1] - a[1] || (a[0] < b[0] ? 1 : -1))[0][0];
|
|
124
|
+
const consistent = matched.filter((m) => m.release.release_name === releaseName);
|
|
125
|
+
const binaries = consistent.map((m) => ({
|
|
126
|
+
platform: m.platform,
|
|
127
|
+
filename: m.binary.package.name,
|
|
128
|
+
url: m.binary.package.link,
|
|
129
|
+
size: m.binary.package.size,
|
|
130
|
+
sha256: m.binary.package.checksum
|
|
131
|
+
}));
|
|
132
|
+
return {
|
|
133
|
+
releaseName,
|
|
134
|
+
extractDir: releaseName,
|
|
135
|
+
major: consistent[0].release.version_data.major,
|
|
136
|
+
binaries
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
//#endregion
|
|
141
|
+
//#region lib/template.ts
|
|
142
|
+
function osArchRuleset(os, arch) {
|
|
143
|
+
return [{
|
|
144
|
+
action: "allow",
|
|
145
|
+
os: { name: os }
|
|
146
|
+
}, {
|
|
147
|
+
action: "allow",
|
|
148
|
+
os: { arch }
|
|
149
|
+
}];
|
|
150
|
+
}
|
|
151
|
+
function osRuleset(os) {
|
|
152
|
+
return [{
|
|
153
|
+
action: "allow",
|
|
154
|
+
os: { name: os }
|
|
155
|
+
}];
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Build a torba template fragment that auto-installs an OpenJDK runtime
|
|
159
|
+
* (Eclipse Temurin) and exposes `${java_home}` + `${java_bin}` vars.
|
|
160
|
+
*
|
|
161
|
+
* Each platform's archive is emitted as its own `Artifact` with an
|
|
162
|
+
* OS+arch rule, so only the matching binary downloads at install time.
|
|
163
|
+
* The archive is extracted into `${root}/runtimes/jdk-<major>/`, with
|
|
164
|
+
* the Adoptium release directory as the immediate child (e.g.
|
|
165
|
+
* `jdk-21.0.11+10/`). On macOS, `${java_home}` includes the
|
|
166
|
+
* `/Contents/Home` suffix that Mac JDK bundles use.
|
|
167
|
+
*
|
|
168
|
+
* Spread the result into your loader's vars + artifacts:
|
|
169
|
+
*
|
|
170
|
+
* ```ts
|
|
171
|
+
* const jav = await resolveJava({ version: '21' });
|
|
172
|
+
* return {
|
|
173
|
+
* artifacts: [lw.artifacts, jav.artifacts],
|
|
174
|
+
* vars: { ...lw.vars, ...jav.vars },
|
|
175
|
+
* command: lw.command, // command.command is `${java_bin}` already
|
|
176
|
+
* };
|
|
177
|
+
* ```
|
|
178
|
+
*/
|
|
179
|
+
async function resolveJava(options) {
|
|
180
|
+
if (options.vendor && options.vendor !== "openjdk") throw new Error(`@torba/java: vendor '${options.vendor}' is not yet supported (only 'openjdk').`);
|
|
181
|
+
const release = await resolveOpenjdk(options.version, {
|
|
182
|
+
platforms: options.platforms,
|
|
183
|
+
apiBase: options.apiBase
|
|
184
|
+
});
|
|
185
|
+
const javaRoot = `\${root}/runtimes/jdk-${release.major}`;
|
|
186
|
+
const archiveDir = `${javaRoot}/.cache`;
|
|
187
|
+
const extractInto = javaRoot;
|
|
188
|
+
const artifacts = release.binaries.map((b) => ({
|
|
189
|
+
path: `${archiveDir}/${b.filename}`,
|
|
190
|
+
source: (0, _torba_core.sourceUrl)(b.url),
|
|
191
|
+
size: b.size,
|
|
192
|
+
rules: osArchRuleset(b.platform.os, b.platform.arch),
|
|
193
|
+
integrity: { sha256: b.sha256 },
|
|
194
|
+
extract: [(0, _torba_core.extractDump)(extractInto, { excludes: [] })]
|
|
195
|
+
}));
|
|
196
|
+
const seenOses = new Set(release.binaries.map((b) => b.platform.os));
|
|
197
|
+
const javaHomeArms = [];
|
|
198
|
+
const javaBinArms = [];
|
|
199
|
+
for (const os of seenOses) {
|
|
200
|
+
const platform = release.binaries.find((b) => b.platform.os === os).platform;
|
|
201
|
+
const home = `${javaRoot}/${release.extractDir}${platform.homeSuffix}`;
|
|
202
|
+
javaHomeArms.push({
|
|
203
|
+
value: home,
|
|
204
|
+
rules: osRuleset(os)
|
|
205
|
+
});
|
|
206
|
+
const exe = os === "windows" ? "java.exe" : "java";
|
|
207
|
+
javaBinArms.push({
|
|
208
|
+
value: `\${java_home}/bin/${exe}`,
|
|
209
|
+
rules: osRuleset(os)
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
return {
|
|
213
|
+
artifacts,
|
|
214
|
+
vars: {
|
|
215
|
+
java_home: javaHomeArms,
|
|
216
|
+
java_bin: javaBinArms
|
|
217
|
+
},
|
|
218
|
+
release
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
//#endregion
|
|
223
|
+
exports.DEFAULT_PLATFORMS = DEFAULT_PLATFORMS;
|
|
224
|
+
exports.resolveJava = resolveJava;
|
|
225
|
+
exports.resolveOpenjdk = resolveOpenjdk;
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { Artifact, ValDefs } from "@torba/core";
|
|
2
|
+
import { OsArch, OsName } from "@torba/rules";
|
|
3
|
+
|
|
4
|
+
//#region lib/resolver.d.ts
|
|
5
|
+
/** Adoptium-side platform descriptor + how it maps onto torba's OS/arch enums. */
|
|
6
|
+
interface JavaPlatform {
|
|
7
|
+
/** torba OS name. */
|
|
8
|
+
readonly os: OsName;
|
|
9
|
+
/** torba arch. `x86_64` is Adoptium's `x64`. */
|
|
10
|
+
readonly arch: OsArch;
|
|
11
|
+
/** Adoptium API `os` value (`linux`, `mac`, `windows`). */
|
|
12
|
+
readonly adoptiumOs: 'linux' | 'mac' | 'windows';
|
|
13
|
+
/** Adoptium API `architecture` value. */
|
|
14
|
+
readonly adoptiumArch: 'x64' | 'aarch64';
|
|
15
|
+
/**
|
|
16
|
+
* Path appended to the extracted top-level directory to reach JAVA_HOME.
|
|
17
|
+
* Empty on Linux/Windows; `/Contents/Home` on macOS bundles.
|
|
18
|
+
*/
|
|
19
|
+
readonly homeSuffix: string;
|
|
20
|
+
}
|
|
21
|
+
declare const DEFAULT_PLATFORMS: readonly JavaPlatform[];
|
|
22
|
+
/** A resolved binary for one (os, arch) platform. */
|
|
23
|
+
interface JavaBinary {
|
|
24
|
+
readonly platform: JavaPlatform;
|
|
25
|
+
/** Asset filename, e.g. `OpenJDK21U-jdk_x64_linux_hotspot_21.0.11_10.tar.gz`. */
|
|
26
|
+
readonly filename: string;
|
|
27
|
+
/** Direct download URL (GitHub release asset). */
|
|
28
|
+
readonly url: string;
|
|
29
|
+
/** Asset size in bytes. */
|
|
30
|
+
readonly size: number;
|
|
31
|
+
/** sha256 of the asset (hex). */
|
|
32
|
+
readonly sha256: string;
|
|
33
|
+
}
|
|
34
|
+
interface JavaRelease {
|
|
35
|
+
/** Adoptium release name, e.g. `jdk-21.0.11+10`. */
|
|
36
|
+
readonly releaseName: string;
|
|
37
|
+
/** Top-level directory after extraction (matches `releaseName`). */
|
|
38
|
+
readonly extractDir: string;
|
|
39
|
+
/** Major version, e.g. `21`. */
|
|
40
|
+
readonly major: number;
|
|
41
|
+
/** Per-platform binaries that exist for this release. */
|
|
42
|
+
readonly binaries: JavaBinary[];
|
|
43
|
+
}
|
|
44
|
+
interface ResolveOpenjdkOptions {
|
|
45
|
+
/** Override the platform set. Default: linux/mac/windows × x64+aarch64. */
|
|
46
|
+
platforms?: readonly JavaPlatform[];
|
|
47
|
+
/** Optional override for the Adoptium API base URL. */
|
|
48
|
+
apiBase?: string;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Resolve an OpenJDK release across all requested platforms. Returns a
|
|
52
|
+
* single `JavaRelease` with one entry per platform that has a binary
|
|
53
|
+
* available — platforms that don't ship a build for this release are
|
|
54
|
+
* silently dropped from `binaries`, so callers don't have to handle the
|
|
55
|
+
* "linux x64 exists, windows aarch64 doesn't" case explicitly.
|
|
56
|
+
*/
|
|
57
|
+
declare function resolveOpenjdk(version: string, options?: ResolveOpenjdkOptions): Promise<JavaRelease>;
|
|
58
|
+
//#endregion
|
|
59
|
+
//#region lib/template.d.ts
|
|
60
|
+
interface JavaOptions {
|
|
61
|
+
/**
|
|
62
|
+
* OpenJDK version. Accepts:
|
|
63
|
+
* - Major: `'21'` — resolves to the latest GA for that major.
|
|
64
|
+
* - Full version: `'21.0.11+10'` — exact Adoptium release name (`jdk-…` prefix and `-LTS` suffix are tolerated).
|
|
65
|
+
*/
|
|
66
|
+
version: string;
|
|
67
|
+
/** Distribution to fetch from. Only `'openjdk'` (Eclipse Temurin) is supported today. */
|
|
68
|
+
vendor?: 'openjdk';
|
|
69
|
+
/** Override the platform set. Default covers linux/osx/windows × x86_64+aarch64. */
|
|
70
|
+
platforms?: readonly JavaPlatform[];
|
|
71
|
+
/** Optional override for the Adoptium API base URL. */
|
|
72
|
+
apiBase?: string;
|
|
73
|
+
}
|
|
74
|
+
interface JavaTemplate {
|
|
75
|
+
/** Per-platform JDK archives, scoped by OS+arch rules and extracted on first install. */
|
|
76
|
+
artifacts: Artifact[];
|
|
77
|
+
/** `java_home` and `java_bin` per OS — spread into your loader's vars. */
|
|
78
|
+
vars: ValDefs;
|
|
79
|
+
/** Resolved release metadata. */
|
|
80
|
+
release: JavaRelease;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Build a torba template fragment that auto-installs an OpenJDK runtime
|
|
84
|
+
* (Eclipse Temurin) and exposes `${java_home}` + `${java_bin}` vars.
|
|
85
|
+
*
|
|
86
|
+
* Each platform's archive is emitted as its own `Artifact` with an
|
|
87
|
+
* OS+arch rule, so only the matching binary downloads at install time.
|
|
88
|
+
* The archive is extracted into `${root}/runtimes/jdk-<major>/`, with
|
|
89
|
+
* the Adoptium release directory as the immediate child (e.g.
|
|
90
|
+
* `jdk-21.0.11+10/`). On macOS, `${java_home}` includes the
|
|
91
|
+
* `/Contents/Home` suffix that Mac JDK bundles use.
|
|
92
|
+
*
|
|
93
|
+
* Spread the result into your loader's vars + artifacts:
|
|
94
|
+
*
|
|
95
|
+
* ```ts
|
|
96
|
+
* const jav = await resolveJava({ version: '21' });
|
|
97
|
+
* return {
|
|
98
|
+
* artifacts: [lw.artifacts, jav.artifacts],
|
|
99
|
+
* vars: { ...lw.vars, ...jav.vars },
|
|
100
|
+
* command: lw.command, // command.command is `${java_bin}` already
|
|
101
|
+
* };
|
|
102
|
+
* ```
|
|
103
|
+
*/
|
|
104
|
+
declare function resolveJava(options: JavaOptions): Promise<JavaTemplate>;
|
|
105
|
+
//#endregion
|
|
106
|
+
export { DEFAULT_PLATFORMS, type JavaBinary, type JavaOptions, type JavaPlatform, type JavaRelease, type JavaTemplate, type ResolveOpenjdkOptions, resolveJava, resolveOpenjdk };
|
|
107
|
+
//# sourceMappingURL=index.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.cts","names":[],"sources":["../lib/resolver.ts","../lib/template.ts"],"mappings":";;;;;UAqBiB,YAAA;;WAEN,EAAA,EAAI,MAAA;EAFc;EAAA,SAIlB,IAAA,EAAM,MAAA;EAAM;EAAA,SAEZ,UAAA;EAJI;EAAA,SAMJ,YAAA;EAJM;;;;EAAA,SASN,UAAA;AAAA;AAAA,cAGE,iBAAA,WAA4B,YAAA;;UA8CxB,UAAA;EAAA,SACN,QAAA,EAAU,YAAA;EA/CgC;EAAA,SAiD1C,QAAA;EAHgB;EAAA,SAKhB,GAAA;EAJsB;EAAA,SAMtB,IAAA;EANU;EAAA,SAQV,MAAA;AAAA;AAAA,UAGM,WAAA;EAHN;EAAA,SAKA,WAAA;EALM;EAAA,SAON,UAAA;EAJiB;EAAA,SAMjB,KAAA;EAEoB;EAAA,SAApB,QAAA,EAAU,UAAA;AAAA;AAAA,UAGJ,qBAAA;EAHN;EAKT,SAAA,YAAqB,YAAA;EALQ;EAO7B,OAAA;AAAA;;;;;;;;iBAwFoB,cAAA,CACpB,OAAA,UACA,OAAA,GAAS,qBAAA,GACR,OAAA,CAAQ,WAAA;;;UC1LM,WAAA;;ADMjB;;;;ECAE,OAAA;EDEa;ECAb,MAAA;EDEe;ECAf,SAAA,YAAqB,YAAA;EDIZ;ECFT,OAAA;AAAA;AAAA,UAGe,YAAA;EDOJ;ECLX,SAAA,EAAW,QAAA;;EAEX,IAAA,EAAM,OAAA;EDG6C;ECDnD,OAAA,EAAS,WAAA;AAAA;;;;;;;;;;;AD2DX;;;;;;;;;;;AAWA;iBClCsB,WAAA,CAAY,OAAA,EAAS,WAAA,GAAc,OAAA,CAAQ,YAAA"}
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { Artifact, ValDefs } from "@torba/core";
|
|
2
|
+
import { OsArch, OsName } from "@torba/rules";
|
|
3
|
+
|
|
4
|
+
//#region lib/resolver.d.ts
|
|
5
|
+
/** Adoptium-side platform descriptor + how it maps onto torba's OS/arch enums. */
|
|
6
|
+
interface JavaPlatform {
|
|
7
|
+
/** torba OS name. */
|
|
8
|
+
readonly os: OsName;
|
|
9
|
+
/** torba arch. `x86_64` is Adoptium's `x64`. */
|
|
10
|
+
readonly arch: OsArch;
|
|
11
|
+
/** Adoptium API `os` value (`linux`, `mac`, `windows`). */
|
|
12
|
+
readonly adoptiumOs: 'linux' | 'mac' | 'windows';
|
|
13
|
+
/** Adoptium API `architecture` value. */
|
|
14
|
+
readonly adoptiumArch: 'x64' | 'aarch64';
|
|
15
|
+
/**
|
|
16
|
+
* Path appended to the extracted top-level directory to reach JAVA_HOME.
|
|
17
|
+
* Empty on Linux/Windows; `/Contents/Home` on macOS bundles.
|
|
18
|
+
*/
|
|
19
|
+
readonly homeSuffix: string;
|
|
20
|
+
}
|
|
21
|
+
declare const DEFAULT_PLATFORMS: readonly JavaPlatform[];
|
|
22
|
+
/** A resolved binary for one (os, arch) platform. */
|
|
23
|
+
interface JavaBinary {
|
|
24
|
+
readonly platform: JavaPlatform;
|
|
25
|
+
/** Asset filename, e.g. `OpenJDK21U-jdk_x64_linux_hotspot_21.0.11_10.tar.gz`. */
|
|
26
|
+
readonly filename: string;
|
|
27
|
+
/** Direct download URL (GitHub release asset). */
|
|
28
|
+
readonly url: string;
|
|
29
|
+
/** Asset size in bytes. */
|
|
30
|
+
readonly size: number;
|
|
31
|
+
/** sha256 of the asset (hex). */
|
|
32
|
+
readonly sha256: string;
|
|
33
|
+
}
|
|
34
|
+
interface JavaRelease {
|
|
35
|
+
/** Adoptium release name, e.g. `jdk-21.0.11+10`. */
|
|
36
|
+
readonly releaseName: string;
|
|
37
|
+
/** Top-level directory after extraction (matches `releaseName`). */
|
|
38
|
+
readonly extractDir: string;
|
|
39
|
+
/** Major version, e.g. `21`. */
|
|
40
|
+
readonly major: number;
|
|
41
|
+
/** Per-platform binaries that exist for this release. */
|
|
42
|
+
readonly binaries: JavaBinary[];
|
|
43
|
+
}
|
|
44
|
+
interface ResolveOpenjdkOptions {
|
|
45
|
+
/** Override the platform set. Default: linux/mac/windows × x64+aarch64. */
|
|
46
|
+
platforms?: readonly JavaPlatform[];
|
|
47
|
+
/** Optional override for the Adoptium API base URL. */
|
|
48
|
+
apiBase?: string;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Resolve an OpenJDK release across all requested platforms. Returns a
|
|
52
|
+
* single `JavaRelease` with one entry per platform that has a binary
|
|
53
|
+
* available — platforms that don't ship a build for this release are
|
|
54
|
+
* silently dropped from `binaries`, so callers don't have to handle the
|
|
55
|
+
* "linux x64 exists, windows aarch64 doesn't" case explicitly.
|
|
56
|
+
*/
|
|
57
|
+
declare function resolveOpenjdk(version: string, options?: ResolveOpenjdkOptions): Promise<JavaRelease>;
|
|
58
|
+
//#endregion
|
|
59
|
+
//#region lib/template.d.ts
|
|
60
|
+
interface JavaOptions {
|
|
61
|
+
/**
|
|
62
|
+
* OpenJDK version. Accepts:
|
|
63
|
+
* - Major: `'21'` — resolves to the latest GA for that major.
|
|
64
|
+
* - Full version: `'21.0.11+10'` — exact Adoptium release name (`jdk-…` prefix and `-LTS` suffix are tolerated).
|
|
65
|
+
*/
|
|
66
|
+
version: string;
|
|
67
|
+
/** Distribution to fetch from. Only `'openjdk'` (Eclipse Temurin) is supported today. */
|
|
68
|
+
vendor?: 'openjdk';
|
|
69
|
+
/** Override the platform set. Default covers linux/osx/windows × x86_64+aarch64. */
|
|
70
|
+
platforms?: readonly JavaPlatform[];
|
|
71
|
+
/** Optional override for the Adoptium API base URL. */
|
|
72
|
+
apiBase?: string;
|
|
73
|
+
}
|
|
74
|
+
interface JavaTemplate {
|
|
75
|
+
/** Per-platform JDK archives, scoped by OS+arch rules and extracted on first install. */
|
|
76
|
+
artifacts: Artifact[];
|
|
77
|
+
/** `java_home` and `java_bin` per OS — spread into your loader's vars. */
|
|
78
|
+
vars: ValDefs;
|
|
79
|
+
/** Resolved release metadata. */
|
|
80
|
+
release: JavaRelease;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Build a torba template fragment that auto-installs an OpenJDK runtime
|
|
84
|
+
* (Eclipse Temurin) and exposes `${java_home}` + `${java_bin}` vars.
|
|
85
|
+
*
|
|
86
|
+
* Each platform's archive is emitted as its own `Artifact` with an
|
|
87
|
+
* OS+arch rule, so only the matching binary downloads at install time.
|
|
88
|
+
* The archive is extracted into `${root}/runtimes/jdk-<major>/`, with
|
|
89
|
+
* the Adoptium release directory as the immediate child (e.g.
|
|
90
|
+
* `jdk-21.0.11+10/`). On macOS, `${java_home}` includes the
|
|
91
|
+
* `/Contents/Home` suffix that Mac JDK bundles use.
|
|
92
|
+
*
|
|
93
|
+
* Spread the result into your loader's vars + artifacts:
|
|
94
|
+
*
|
|
95
|
+
* ```ts
|
|
96
|
+
* const jav = await resolveJava({ version: '21' });
|
|
97
|
+
* return {
|
|
98
|
+
* artifacts: [lw.artifacts, jav.artifacts],
|
|
99
|
+
* vars: { ...lw.vars, ...jav.vars },
|
|
100
|
+
* command: lw.command, // command.command is `${java_bin}` already
|
|
101
|
+
* };
|
|
102
|
+
* ```
|
|
103
|
+
*/
|
|
104
|
+
declare function resolveJava(options: JavaOptions): Promise<JavaTemplate>;
|
|
105
|
+
//#endregion
|
|
106
|
+
export { DEFAULT_PLATFORMS, type JavaBinary, type JavaOptions, type JavaPlatform, type JavaRelease, type JavaTemplate, type ResolveOpenjdkOptions, resolveJava, resolveOpenjdk };
|
|
107
|
+
//# sourceMappingURL=index.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../lib/resolver.ts","../lib/template.ts"],"mappings":";;;;;UAqBiB,YAAA;;WAEN,EAAA,EAAI,MAAA;EAFc;EAAA,SAIlB,IAAA,EAAM,MAAA;EAAM;EAAA,SAEZ,UAAA;EAJI;EAAA,SAMJ,YAAA;EAJM;;;;EAAA,SASN,UAAA;AAAA;AAAA,cAGE,iBAAA,WAA4B,YAAA;;UA8CxB,UAAA;EAAA,SACN,QAAA,EAAU,YAAA;EA/CgC;EAAA,SAiD1C,QAAA;EAHgB;EAAA,SAKhB,GAAA;EAJsB;EAAA,SAMtB,IAAA;EANU;EAAA,SAQV,MAAA;AAAA;AAAA,UAGM,WAAA;EAHN;EAAA,SAKA,WAAA;EALM;EAAA,SAON,UAAA;EAJiB;EAAA,SAMjB,KAAA;EAEoB;EAAA,SAApB,QAAA,EAAU,UAAA;AAAA;AAAA,UAGJ,qBAAA;EAHN;EAKT,SAAA,YAAqB,YAAA;EALQ;EAO7B,OAAA;AAAA;;;;;;;;iBAwFoB,cAAA,CACpB,OAAA,UACA,OAAA,GAAS,qBAAA,GACR,OAAA,CAAQ,WAAA;;;UC1LM,WAAA;;ADMjB;;;;ECAE,OAAA;EDEa;ECAb,MAAA;EDEe;ECAf,SAAA,YAAqB,YAAA;EDIZ;ECFT,OAAA;AAAA;AAAA,UAGe,YAAA;EDOJ;ECLX,SAAA,EAAW,QAAA;;EAEX,IAAA,EAAM,OAAA;EDG6C;ECDnD,OAAA,EAAS,WAAA;AAAA;;;;;;;;;;;AD2DX;;;;;;;;;;;AAWA;iBClCsB,WAAA,CAAY,OAAA,EAAS,WAAA,GAAc,OAAA,CAAQ,YAAA"}
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
import { extractDump, fetchWithRetry, sourceUrl } from "@torba/core";
|
|
2
|
+
|
|
3
|
+
//#region lib/resolver.ts
|
|
4
|
+
/**
|
|
5
|
+
* Resolver for OpenJDK builds from the Eclipse Adoptium (Temurin) distribution.
|
|
6
|
+
*
|
|
7
|
+
* Adoptium publishes a public asset API at `https://api.adoptium.net/v3/`.
|
|
8
|
+
* We use two endpoints depending on the version input shape:
|
|
9
|
+
*
|
|
10
|
+
* - Major-only (`'21'`, `'17'`) → `/feature_releases/<major>/ga` (latest GA)
|
|
11
|
+
* - Full version (`'21.0.11+10'`) → `/release_name/<vendor>/jdk-<v>` (exact)
|
|
12
|
+
*
|
|
13
|
+
* Each platform (os × arch) is queried separately with `image_type=jdk` and
|
|
14
|
+
* `jvm_impl=hotspot`. Releases that don't ship a binary for a given platform
|
|
15
|
+
* are soft-skipped — the resulting `JavaRelease` only contains the platforms
|
|
16
|
+
* with a real binary.
|
|
17
|
+
*/
|
|
18
|
+
const ADOPTIUM_BASE = "https://api.adoptium.net/v3";
|
|
19
|
+
const VENDOR = "eclipse";
|
|
20
|
+
const DEFAULT_PLATFORMS = [
|
|
21
|
+
{
|
|
22
|
+
os: "linux",
|
|
23
|
+
arch: "x86_64",
|
|
24
|
+
adoptiumOs: "linux",
|
|
25
|
+
adoptiumArch: "x64",
|
|
26
|
+
homeSuffix: ""
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
os: "linux",
|
|
30
|
+
arch: "aarch64",
|
|
31
|
+
adoptiumOs: "linux",
|
|
32
|
+
adoptiumArch: "aarch64",
|
|
33
|
+
homeSuffix: ""
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
os: "osx",
|
|
37
|
+
arch: "x86_64",
|
|
38
|
+
adoptiumOs: "mac",
|
|
39
|
+
adoptiumArch: "x64",
|
|
40
|
+
homeSuffix: "/Contents/Home"
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
os: "osx",
|
|
44
|
+
arch: "aarch64",
|
|
45
|
+
adoptiumOs: "mac",
|
|
46
|
+
adoptiumArch: "aarch64",
|
|
47
|
+
homeSuffix: "/Contents/Home"
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
os: "windows",
|
|
51
|
+
arch: "x86_64",
|
|
52
|
+
adoptiumOs: "windows",
|
|
53
|
+
adoptiumArch: "x64",
|
|
54
|
+
homeSuffix: ""
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
os: "windows",
|
|
58
|
+
arch: "aarch64",
|
|
59
|
+
adoptiumOs: "windows",
|
|
60
|
+
adoptiumArch: "aarch64",
|
|
61
|
+
homeSuffix: ""
|
|
62
|
+
}
|
|
63
|
+
];
|
|
64
|
+
function normalizeInput(input) {
|
|
65
|
+
let v = input.trim();
|
|
66
|
+
if (v.startsWith("jdk-")) v = v.slice(4);
|
|
67
|
+
v = v.replace(/-LTS$/, "");
|
|
68
|
+
if (/^\d+$/.test(v)) return {
|
|
69
|
+
kind: "major",
|
|
70
|
+
raw: v
|
|
71
|
+
};
|
|
72
|
+
return {
|
|
73
|
+
kind: "full",
|
|
74
|
+
raw: v
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
function commonQuery(platform) {
|
|
78
|
+
return new URLSearchParams({
|
|
79
|
+
image_type: "jdk",
|
|
80
|
+
architecture: platform.adoptiumArch,
|
|
81
|
+
os: platform.adoptiumOs,
|
|
82
|
+
jvm_impl: "hotspot",
|
|
83
|
+
heap_size: "normal",
|
|
84
|
+
vendor: VENDOR
|
|
85
|
+
}).toString();
|
|
86
|
+
}
|
|
87
|
+
async function fetchPlatform(apiBase, platform, version) {
|
|
88
|
+
const res = await fetchWithRetry(`${apiBase}${version.kind === "major" ? `/assets/feature_releases/${version.raw}/ga?${commonQuery(platform)}&page_size=1&sort_order=DESC` : `/assets/release_name/${VENDOR}/${encodeURIComponent(`jdk-${version.raw}`)}?${commonQuery(platform)}`}`, { headers: { Accept: "application/json" } });
|
|
89
|
+
if (res.status === 404) return null;
|
|
90
|
+
if (!res.ok) throw new Error(`Adoptium API ${res.status} ${res.statusText} for ${platform.adoptiumOs}/${platform.adoptiumArch}`);
|
|
91
|
+
const body = await res.json();
|
|
92
|
+
const release = Array.isArray(body) ? body[0] : body;
|
|
93
|
+
if (!release || !release.binaries || release.binaries.length === 0) return null;
|
|
94
|
+
const binary = release.binaries.find((b) => b.architecture === platform.adoptiumArch && b.os === platform.adoptiumOs && b.image_type === "jdk");
|
|
95
|
+
if (!binary) return null;
|
|
96
|
+
return {
|
|
97
|
+
release,
|
|
98
|
+
binary
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Resolve an OpenJDK release across all requested platforms. Returns a
|
|
103
|
+
* single `JavaRelease` with one entry per platform that has a binary
|
|
104
|
+
* available — platforms that don't ship a build for this release are
|
|
105
|
+
* silently dropped from `binaries`, so callers don't have to handle the
|
|
106
|
+
* "linux x64 exists, windows aarch64 doesn't" case explicitly.
|
|
107
|
+
*/
|
|
108
|
+
async function resolveOpenjdk(version, options = {}) {
|
|
109
|
+
const apiBase = options.apiBase ?? ADOPTIUM_BASE;
|
|
110
|
+
const platforms = options.platforms ?? DEFAULT_PLATFORMS;
|
|
111
|
+
const parsed = normalizeInput(version);
|
|
112
|
+
const matched = (await Promise.all(platforms.map(async (p) => {
|
|
113
|
+
const found = await fetchPlatform(apiBase, p, parsed);
|
|
114
|
+
return found ? {
|
|
115
|
+
platform: p,
|
|
116
|
+
...found
|
|
117
|
+
} : null;
|
|
118
|
+
}))).filter((x) => x !== null);
|
|
119
|
+
if (matched.length === 0) throw new Error(`No OpenJDK binaries found for version '${version}' across requested platforms.`);
|
|
120
|
+
const nameCounts = /* @__PURE__ */ new Map();
|
|
121
|
+
for (const m of matched) nameCounts.set(m.release.release_name, (nameCounts.get(m.release.release_name) ?? 0) + 1);
|
|
122
|
+
const releaseName = [...nameCounts.entries()].sort((a, b) => b[1] - a[1] || (a[0] < b[0] ? 1 : -1))[0][0];
|
|
123
|
+
const consistent = matched.filter((m) => m.release.release_name === releaseName);
|
|
124
|
+
const binaries = consistent.map((m) => ({
|
|
125
|
+
platform: m.platform,
|
|
126
|
+
filename: m.binary.package.name,
|
|
127
|
+
url: m.binary.package.link,
|
|
128
|
+
size: m.binary.package.size,
|
|
129
|
+
sha256: m.binary.package.checksum
|
|
130
|
+
}));
|
|
131
|
+
return {
|
|
132
|
+
releaseName,
|
|
133
|
+
extractDir: releaseName,
|
|
134
|
+
major: consistent[0].release.version_data.major,
|
|
135
|
+
binaries
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
//#endregion
|
|
140
|
+
//#region lib/template.ts
|
|
141
|
+
function osArchRuleset(os, arch) {
|
|
142
|
+
return [{
|
|
143
|
+
action: "allow",
|
|
144
|
+
os: { name: os }
|
|
145
|
+
}, {
|
|
146
|
+
action: "allow",
|
|
147
|
+
os: { arch }
|
|
148
|
+
}];
|
|
149
|
+
}
|
|
150
|
+
function osRuleset(os) {
|
|
151
|
+
return [{
|
|
152
|
+
action: "allow",
|
|
153
|
+
os: { name: os }
|
|
154
|
+
}];
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Build a torba template fragment that auto-installs an OpenJDK runtime
|
|
158
|
+
* (Eclipse Temurin) and exposes `${java_home}` + `${java_bin}` vars.
|
|
159
|
+
*
|
|
160
|
+
* Each platform's archive is emitted as its own `Artifact` with an
|
|
161
|
+
* OS+arch rule, so only the matching binary downloads at install time.
|
|
162
|
+
* The archive is extracted into `${root}/runtimes/jdk-<major>/`, with
|
|
163
|
+
* the Adoptium release directory as the immediate child (e.g.
|
|
164
|
+
* `jdk-21.0.11+10/`). On macOS, `${java_home}` includes the
|
|
165
|
+
* `/Contents/Home` suffix that Mac JDK bundles use.
|
|
166
|
+
*
|
|
167
|
+
* Spread the result into your loader's vars + artifacts:
|
|
168
|
+
*
|
|
169
|
+
* ```ts
|
|
170
|
+
* const jav = await resolveJava({ version: '21' });
|
|
171
|
+
* return {
|
|
172
|
+
* artifacts: [lw.artifacts, jav.artifacts],
|
|
173
|
+
* vars: { ...lw.vars, ...jav.vars },
|
|
174
|
+
* command: lw.command, // command.command is `${java_bin}` already
|
|
175
|
+
* };
|
|
176
|
+
* ```
|
|
177
|
+
*/
|
|
178
|
+
async function resolveJava(options) {
|
|
179
|
+
if (options.vendor && options.vendor !== "openjdk") throw new Error(`@torba/java: vendor '${options.vendor}' is not yet supported (only 'openjdk').`);
|
|
180
|
+
const release = await resolveOpenjdk(options.version, {
|
|
181
|
+
platforms: options.platforms,
|
|
182
|
+
apiBase: options.apiBase
|
|
183
|
+
});
|
|
184
|
+
const javaRoot = `\${root}/runtimes/jdk-${release.major}`;
|
|
185
|
+
const archiveDir = `${javaRoot}/.cache`;
|
|
186
|
+
const extractInto = javaRoot;
|
|
187
|
+
const artifacts = release.binaries.map((b) => ({
|
|
188
|
+
path: `${archiveDir}/${b.filename}`,
|
|
189
|
+
source: sourceUrl(b.url),
|
|
190
|
+
size: b.size,
|
|
191
|
+
rules: osArchRuleset(b.platform.os, b.platform.arch),
|
|
192
|
+
integrity: { sha256: b.sha256 },
|
|
193
|
+
extract: [extractDump(extractInto, { excludes: [] })]
|
|
194
|
+
}));
|
|
195
|
+
const seenOses = new Set(release.binaries.map((b) => b.platform.os));
|
|
196
|
+
const javaHomeArms = [];
|
|
197
|
+
const javaBinArms = [];
|
|
198
|
+
for (const os of seenOses) {
|
|
199
|
+
const platform = release.binaries.find((b) => b.platform.os === os).platform;
|
|
200
|
+
const home = `${javaRoot}/${release.extractDir}${platform.homeSuffix}`;
|
|
201
|
+
javaHomeArms.push({
|
|
202
|
+
value: home,
|
|
203
|
+
rules: osRuleset(os)
|
|
204
|
+
});
|
|
205
|
+
const exe = os === "windows" ? "java.exe" : "java";
|
|
206
|
+
javaBinArms.push({
|
|
207
|
+
value: `\${java_home}/bin/${exe}`,
|
|
208
|
+
rules: osRuleset(os)
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
return {
|
|
212
|
+
artifacts,
|
|
213
|
+
vars: {
|
|
214
|
+
java_home: javaHomeArms,
|
|
215
|
+
java_bin: javaBinArms
|
|
216
|
+
},
|
|
217
|
+
release
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
//#endregion
|
|
222
|
+
export { DEFAULT_PLATFORMS, resolveJava, resolveOpenjdk };
|
|
223
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../lib/resolver.ts","../lib/template.ts"],"sourcesContent":["/**\n * Resolver for OpenJDK builds from the Eclipse Adoptium (Temurin) distribution.\n *\n * Adoptium publishes a public asset API at `https://api.adoptium.net/v3/`.\n * We use two endpoints depending on the version input shape:\n *\n * - Major-only (`'21'`, `'17'`) → `/feature_releases/<major>/ga` (latest GA)\n * - Full version (`'21.0.11+10'`) → `/release_name/<vendor>/jdk-<v>` (exact)\n *\n * Each platform (os × arch) is queried separately with `image_type=jdk` and\n * `jvm_impl=hotspot`. Releases that don't ship a binary for a given platform\n * are soft-skipped — the resulting `JavaRelease` only contains the platforms\n * with a real binary.\n */\nimport { fetchWithRetry } from '@torba/core';\nimport type { OsName, OsArch } from '@torba/rules';\n\nconst ADOPTIUM_BASE = 'https://api.adoptium.net/v3';\nconst VENDOR = 'eclipse';\n\n/** Adoptium-side platform descriptor + how it maps onto torba's OS/arch enums. */\nexport interface JavaPlatform {\n /** torba OS name. */\n readonly os: OsName;\n /** torba arch. `x86_64` is Adoptium's `x64`. */\n readonly arch: OsArch;\n /** Adoptium API `os` value (`linux`, `mac`, `windows`). */\n readonly adoptiumOs: 'linux' | 'mac' | 'windows';\n /** Adoptium API `architecture` value. */\n readonly adoptiumArch: 'x64' | 'aarch64';\n /**\n * Path appended to the extracted top-level directory to reach JAVA_HOME.\n * Empty on Linux/Windows; `/Contents/Home` on macOS bundles.\n */\n readonly homeSuffix: string;\n}\n\nexport const DEFAULT_PLATFORMS: readonly JavaPlatform[] = [\n {\n os: 'linux',\n arch: 'x86_64',\n adoptiumOs: 'linux',\n adoptiumArch: 'x64',\n homeSuffix: '',\n },\n {\n os: 'linux',\n arch: 'aarch64',\n adoptiumOs: 'linux',\n adoptiumArch: 'aarch64',\n homeSuffix: '',\n },\n {\n os: 'osx',\n arch: 'x86_64',\n adoptiumOs: 'mac',\n adoptiumArch: 'x64',\n homeSuffix: '/Contents/Home',\n },\n {\n os: 'osx',\n arch: 'aarch64',\n adoptiumOs: 'mac',\n adoptiumArch: 'aarch64',\n homeSuffix: '/Contents/Home',\n },\n {\n os: 'windows',\n arch: 'x86_64',\n adoptiumOs: 'windows',\n adoptiumArch: 'x64',\n homeSuffix: '',\n },\n {\n os: 'windows',\n arch: 'aarch64',\n adoptiumOs: 'windows',\n adoptiumArch: 'aarch64',\n homeSuffix: '',\n },\n];\n\n/** A resolved binary for one (os, arch) platform. */\nexport interface JavaBinary {\n readonly platform: JavaPlatform;\n /** Asset filename, e.g. `OpenJDK21U-jdk_x64_linux_hotspot_21.0.11_10.tar.gz`. */\n readonly filename: string;\n /** Direct download URL (GitHub release asset). */\n readonly url: string;\n /** Asset size in bytes. */\n readonly size: number;\n /** sha256 of the asset (hex). */\n readonly sha256: string;\n}\n\nexport interface JavaRelease {\n /** Adoptium release name, e.g. `jdk-21.0.11+10`. */\n readonly releaseName: string;\n /** Top-level directory after extraction (matches `releaseName`). */\n readonly extractDir: string;\n /** Major version, e.g. `21`. */\n readonly major: number;\n /** Per-platform binaries that exist for this release. */\n readonly binaries: JavaBinary[];\n}\n\nexport interface ResolveOpenjdkOptions {\n /** Override the platform set. Default: linux/mac/windows × x64+aarch64. */\n platforms?: readonly JavaPlatform[];\n /** Optional override for the Adoptium API base URL. */\n apiBase?: string;\n}\n\ninterface AdoptiumPackage {\n checksum: string;\n link: string;\n name: string;\n size: number;\n}\n\ninterface AdoptiumBinary {\n architecture: string;\n os: string;\n image_type: string;\n jvm_impl: string;\n package: AdoptiumPackage;\n}\n\ninterface AdoptiumRelease {\n release_name: string;\n binaries: AdoptiumBinary[];\n version_data: { major: number };\n}\n\nfunction normalizeInput(input: string): {\n kind: 'major' | 'full';\n raw: string;\n} {\n let v = input.trim();\n if (v.startsWith('jdk-')) v = v.slice(4);\n v = v.replace(/-LTS$/, '');\n if (/^\\d+$/.test(v)) return { kind: 'major', raw: v };\n return { kind: 'full', raw: v };\n}\n\nfunction commonQuery(platform: JavaPlatform): string {\n const params = new URLSearchParams({\n image_type: 'jdk',\n architecture: platform.adoptiumArch,\n os: platform.adoptiumOs,\n jvm_impl: 'hotspot',\n heap_size: 'normal',\n vendor: VENDOR,\n });\n return params.toString();\n}\n\nasync function fetchPlatform(\n apiBase: string,\n platform: JavaPlatform,\n version: { kind: 'major' | 'full'; raw: string },\n): Promise<{ release: AdoptiumRelease; binary: AdoptiumBinary } | null> {\n const path =\n version.kind === 'major'\n ? `/assets/feature_releases/${version.raw}/ga?${commonQuery(platform)}&page_size=1&sort_order=DESC`\n : `/assets/release_name/${VENDOR}/${encodeURIComponent(`jdk-${version.raw}`)}?${commonQuery(platform)}`;\n\n const url = `${apiBase}${path}`;\n const res = await fetchWithRetry(url, {\n headers: { Accept: 'application/json' },\n });\n if (res.status === 404) return null;\n if (!res.ok) {\n throw new Error(\n `Adoptium API ${res.status} ${res.statusText} for ${platform.adoptiumOs}/${platform.adoptiumArch}`,\n );\n }\n const body = (await res.json()) as AdoptiumRelease | AdoptiumRelease[];\n const release = Array.isArray(body) ? body[0] : body;\n if (!release || !release.binaries || release.binaries.length === 0)\n return null;\n const binary = release.binaries.find(\n (b) =>\n b.architecture === platform.adoptiumArch &&\n b.os === platform.adoptiumOs &&\n b.image_type === 'jdk',\n );\n if (!binary) return null;\n return { release, binary };\n}\n\n/**\n * Resolve an OpenJDK release across all requested platforms. Returns a\n * single `JavaRelease` with one entry per platform that has a binary\n * available — platforms that don't ship a build for this release are\n * silently dropped from `binaries`, so callers don't have to handle the\n * \"linux x64 exists, windows aarch64 doesn't\" case explicitly.\n */\nexport async function resolveOpenjdk(\n version: string,\n options: ResolveOpenjdkOptions = {},\n): Promise<JavaRelease> {\n const apiBase = options.apiBase ?? ADOPTIUM_BASE;\n const platforms = options.platforms ?? DEFAULT_PLATFORMS;\n const parsed = normalizeInput(version);\n\n const fetched = await Promise.all(\n platforms.map(async (p) => {\n const found = await fetchPlatform(apiBase, p, parsed);\n return found ? { platform: p, ...found } : null;\n }),\n );\n\n const matched = fetched.filter((x): x is NonNullable<typeof x> => x !== null);\n if (matched.length === 0) {\n throw new Error(\n `No OpenJDK binaries found for version '${version}' across requested platforms.`,\n );\n }\n\n // All platforms should agree on release_name when querying a specific\n // release_name; for major queries each platform may resolve to a\n // different latest GA — we anchor to the most-common release_name to\n // keep the bundle coherent (and skip mismatched binaries).\n const nameCounts = new Map<string, number>();\n for (const m of matched) {\n nameCounts.set(\n m.release.release_name,\n (nameCounts.get(m.release.release_name) ?? 0) + 1,\n );\n }\n const releaseName = [...nameCounts.entries()].sort(\n (a, b) => b[1] - a[1] || (a[0] < b[0] ? 1 : -1),\n )[0]![0];\n\n const consistent = matched.filter(\n (m) => m.release.release_name === releaseName,\n );\n\n const binaries: JavaBinary[] = consistent.map((m) => ({\n platform: m.platform,\n filename: m.binary.package.name,\n url: m.binary.package.link,\n size: m.binary.package.size,\n sha256: m.binary.package.checksum,\n }));\n\n return {\n releaseName,\n extractDir: releaseName,\n major: consistent[0]!.release.version_data.major,\n binaries,\n };\n}\n","import {\n type Artifact,\n type ValDefs,\n type ConditionalVal,\n sourceUrl,\n extractDump,\n} from '@torba/core';\nimport type { OsName, OsArch, Ruleset } from '@torba/rules';\nimport {\n resolveOpenjdk,\n type JavaPlatform,\n type JavaRelease,\n type ResolveOpenjdkOptions,\n} from './resolver';\n\nexport interface JavaOptions {\n /**\n * OpenJDK version. Accepts:\n * - Major: `'21'` — resolves to the latest GA for that major.\n * - Full version: `'21.0.11+10'` — exact Adoptium release name (`jdk-…` prefix and `-LTS` suffix are tolerated).\n */\n version: string;\n /** Distribution to fetch from. Only `'openjdk'` (Eclipse Temurin) is supported today. */\n vendor?: 'openjdk';\n /** Override the platform set. Default covers linux/osx/windows × x86_64+aarch64. */\n platforms?: readonly JavaPlatform[];\n /** Optional override for the Adoptium API base URL. */\n apiBase?: string;\n}\n\nexport interface JavaTemplate {\n /** Per-platform JDK archives, scoped by OS+arch rules and extracted on first install. */\n artifacts: Artifact[];\n /** `java_home` and `java_bin` per OS — spread into your loader's vars. */\n vars: ValDefs;\n /** Resolved release metadata. */\n release: JavaRelease;\n}\n\nfunction osArchRuleset(os: OsName, arch: OsArch): Ruleset {\n return [\n { action: 'allow', os: { name: os } },\n { action: 'allow', os: { arch } },\n ];\n}\n\nfunction osRuleset(os: OsName): Ruleset {\n return [{ action: 'allow', os: { name: os } }];\n}\n\n/**\n * Build a torba template fragment that auto-installs an OpenJDK runtime\n * (Eclipse Temurin) and exposes `${java_home}` + `${java_bin}` vars.\n *\n * Each platform's archive is emitted as its own `Artifact` with an\n * OS+arch rule, so only the matching binary downloads at install time.\n * The archive is extracted into `${root}/runtimes/jdk-<major>/`, with\n * the Adoptium release directory as the immediate child (e.g.\n * `jdk-21.0.11+10/`). On macOS, `${java_home}` includes the\n * `/Contents/Home` suffix that Mac JDK bundles use.\n *\n * Spread the result into your loader's vars + artifacts:\n *\n * ```ts\n * const jav = await resolveJava({ version: '21' });\n * return {\n * artifacts: [lw.artifacts, jav.artifacts],\n * vars: { ...lw.vars, ...jav.vars },\n * command: lw.command, // command.command is `${java_bin}` already\n * };\n * ```\n */\nexport async function resolveJava(options: JavaOptions): Promise<JavaTemplate> {\n if (options.vendor && options.vendor !== 'openjdk') {\n throw new Error(\n `@torba/java: vendor '${options.vendor}' is not yet supported (only 'openjdk').`,\n );\n }\n const release = await resolveOpenjdk(options.version, {\n platforms: options.platforms,\n apiBase: options.apiBase,\n } satisfies ResolveOpenjdkOptions);\n\n const javaRoot = `\\${root}/runtimes/jdk-${release.major}`;\n const archiveDir = `${javaRoot}/.cache`;\n const extractInto = javaRoot;\n\n const artifacts: Artifact[] = release.binaries.map((b) => ({\n path: `${archiveDir}/${b.filename}`,\n source: sourceUrl(b.url),\n size: b.size,\n rules: osArchRuleset(b.platform.os, b.platform.arch),\n integrity: { sha256: b.sha256 },\n extract: [extractDump(extractInto, { excludes: [] })],\n }));\n\n // `java_home` only varies by OS (Linux/Windows have no suffix; macOS\n // bundles add `/Contents/Home`). Both x86_64 and aarch64 archives\n // extract to the same top-level directory, so we don't need to split\n // by arch here.\n const seenOses = new Set(release.binaries.map((b) => b.platform.os));\n const javaHomeArms: ConditionalVal[] = [];\n const javaBinArms: ConditionalVal[] = [];\n for (const os of seenOses) {\n const platform = release.binaries.find(\n (b) => b.platform.os === os,\n )!.platform;\n const home = `${javaRoot}/${release.extractDir}${platform.homeSuffix}`;\n javaHomeArms.push({ value: home, rules: osRuleset(os) });\n const exe = os === 'windows' ? 'java.exe' : 'java';\n javaBinArms.push({\n value: `\\${java_home}/bin/${exe}`,\n rules: osRuleset(os),\n });\n }\n\n const vars: ValDefs = {\n java_home: javaHomeArms,\n java_bin: javaBinArms,\n };\n\n return { artifacts, vars, release };\n}\n"],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@torba/java",
|
|
3
|
+
"version": "1.0.7",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
|
+
"exports": {
|
|
7
|
+
".": {
|
|
8
|
+
"import": "./dist/index.mjs",
|
|
9
|
+
"require": "./dist/index.cjs"
|
|
10
|
+
}
|
|
11
|
+
},
|
|
12
|
+
"scripts": {
|
|
13
|
+
"build": "tsdown lib/index.ts --format esm,cjs --dts --clean"
|
|
14
|
+
},
|
|
15
|
+
"dependencies": {
|
|
16
|
+
"@torba/core": "^1.0.7",
|
|
17
|
+
"@torba/rules": "^1.0.7"
|
|
18
|
+
},
|
|
19
|
+
"peerDependencies": {
|
|
20
|
+
"zod": "^4.0.0"
|
|
21
|
+
},
|
|
22
|
+
"devDependencies": {
|
|
23
|
+
"tsdown": "*"
|
|
24
|
+
},
|
|
25
|
+
"files": [
|
|
26
|
+
"dist"
|
|
27
|
+
]
|
|
28
|
+
}
|