@happier-dev/relay-server 0.1.2 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/happier-server.mjs +92 -101
- package/node_modules/@happier-dev/release-runtime/dist/.tsbuildinfo +1 -0
- package/node_modules/@happier-dev/release-runtime/dist/_cjs/releaseRings.js +134 -0
- package/node_modules/@happier-dev/release-runtime/dist/assets.d.ts +22 -0
- package/node_modules/@happier-dev/release-runtime/dist/assets.d.ts.map +1 -0
- package/node_modules/@happier-dev/release-runtime/dist/assets.js +44 -0
- package/node_modules/@happier-dev/release-runtime/dist/assets.js.map +1 -0
- package/node_modules/@happier-dev/release-runtime/dist/checksums.d.ts +5 -0
- package/node_modules/@happier-dev/release-runtime/dist/checksums.d.ts.map +1 -0
- package/node_modules/@happier-dev/release-runtime/dist/checksums.js +21 -0
- package/node_modules/@happier-dev/release-runtime/dist/checksums.js.map +1 -0
- package/node_modules/@happier-dev/release-runtime/dist/extractPlan.d.ts +14 -0
- package/node_modules/@happier-dev/release-runtime/dist/extractPlan.d.ts.map +1 -0
- package/node_modules/@happier-dev/release-runtime/dist/extractPlan.js +48 -0
- package/node_modules/@happier-dev/release-runtime/dist/extractPlan.js.map +1 -0
- package/node_modules/@happier-dev/release-runtime/dist/github.d.ts +26 -0
- package/node_modules/@happier-dev/release-runtime/dist/github.d.ts.map +1 -0
- package/node_modules/@happier-dev/release-runtime/dist/github.js +141 -0
- package/node_modules/@happier-dev/release-runtime/dist/github.js.map +1 -0
- package/node_modules/@happier-dev/release-runtime/dist/http.d.ts +18 -0
- package/node_modules/@happier-dev/release-runtime/dist/http.d.ts.map +1 -0
- package/node_modules/@happier-dev/release-runtime/dist/http.js +112 -0
- package/node_modules/@happier-dev/release-runtime/dist/http.js.map +1 -0
- package/node_modules/@happier-dev/release-runtime/dist/index.d.ts +8 -0
- package/node_modules/@happier-dev/release-runtime/dist/index.d.ts.map +1 -0
- package/node_modules/@happier-dev/release-runtime/dist/index.js +8 -0
- package/node_modules/@happier-dev/release-runtime/dist/index.js.map +1 -0
- package/node_modules/@happier-dev/release-runtime/dist/minisign.d.ts +7 -0
- package/node_modules/@happier-dev/release-runtime/dist/minisign.d.ts.map +1 -0
- package/node_modules/@happier-dev/release-runtime/dist/minisign.js +92 -0
- package/node_modules/@happier-dev/release-runtime/dist/minisign.js.map +1 -0
- package/node_modules/@happier-dev/release-runtime/dist/releaseRings.cjs +134 -0
- package/node_modules/@happier-dev/release-runtime/dist/releaseRings.d.ts +27 -0
- package/node_modules/@happier-dev/release-runtime/dist/releaseRings.d.ts.map +1 -0
- package/node_modules/@happier-dev/release-runtime/dist/releaseRings.js +124 -0
- package/node_modules/@happier-dev/release-runtime/dist/releaseRings.js.map +1 -0
- package/node_modules/@happier-dev/release-runtime/dist/verifiedDownload.d.ts +26 -0
- package/node_modules/@happier-dev/release-runtime/dist/verifiedDownload.d.ts.map +1 -0
- package/node_modules/@happier-dev/release-runtime/dist/verifiedDownload.js +47 -0
- package/node_modules/@happier-dev/release-runtime/dist/verifiedDownload.js.map +1 -0
- package/node_modules/@happier-dev/release-runtime/package.json +43 -0
- package/package.json +10 -4
- package/src/checksums.mjs +1 -17
- package/src/checksums.test.mjs +1 -2
- package/src/minisign.mjs +1 -94
- package/src/minisign.verify.test.mjs +1 -2
- package/src/releaseAssets.mjs +30 -30
- package/src/releaseAssets.test.mjs +33 -1
- package/src/runnerConfig.mjs +69 -0
- package/src/runnerConfig.test.mjs +37 -0
- package/src/target.mjs +48 -0
- package/src/target.test.mjs +54 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"assets.d.ts","sourceRoot":"","sources":["../src/assets.ts"],"names":[],"mappings":"AAcA,wBAAgB,yBAAyB,CAAC,EACxC,MAAM,EACN,OAAO,EACP,EAAE,EACF,IAAI,EACJ,kBAAyB,GAC1B,EAAE;IACD,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B;;;cAEwC,MAAM;aAAO,MAAM;;;cAAnB,MAAM;aAAO,MAAM;;;cAAnB,MAAM;aAAO,MAAM;;EAoC3D"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
function normalizeAsset(asset) {
|
|
2
|
+
const name = String(asset?.name ?? '').trim();
|
|
3
|
+
const url = String(asset?.browser_download_url ?? asset?.url ?? '').trim();
|
|
4
|
+
return name && url ? { name, url } : null;
|
|
5
|
+
}
|
|
6
|
+
const VERSION_RE = '\\d+\\.\\d+\\.\\d+(?:-[0-9A-Za-z.-]+)?';
|
|
7
|
+
export function resolveReleaseAssetBundle({ assets, product, os, arch, preferZipOnWindows = true, }) {
|
|
8
|
+
const list = Array.isArray(assets) ? assets : [];
|
|
9
|
+
const byName = new Map();
|
|
10
|
+
for (const asset of list) {
|
|
11
|
+
const normalized = normalizeAsset(asset);
|
|
12
|
+
if (!normalized)
|
|
13
|
+
continue;
|
|
14
|
+
byName.set(normalized.name, normalized);
|
|
15
|
+
}
|
|
16
|
+
const checksumsRe = new RegExp(`^checksums-${product}-v(${VERSION_RE})\\.txt$`);
|
|
17
|
+
const checksumsName = [...byName.keys()].find((name) => checksumsRe.test(name)) ?? '';
|
|
18
|
+
if (!checksumsName) {
|
|
19
|
+
throw new Error(`[release-assets] missing checksums-${product}-v<version>.txt asset`);
|
|
20
|
+
}
|
|
21
|
+
const versionMatch = checksumsRe.exec(checksumsName);
|
|
22
|
+
const version = versionMatch?.[1] ?? '';
|
|
23
|
+
if (!version) {
|
|
24
|
+
throw new Error(`[release-assets] unable to derive version from checksums filename: ${checksumsName}`);
|
|
25
|
+
}
|
|
26
|
+
const checksumsSigName = `${checksumsName}.minisig`;
|
|
27
|
+
const base = `${product}-v${version}-${os}-${arch}`;
|
|
28
|
+
const zipName = `${base}.zip`;
|
|
29
|
+
const tgzName = `${base}.tar.gz`;
|
|
30
|
+
const archiveName = os.toLowerCase() === 'windows' && preferZipOnWindows && byName.has(zipName)
|
|
31
|
+
? zipName
|
|
32
|
+
: tgzName;
|
|
33
|
+
const checksums = byName.get(checksumsName) ?? null;
|
|
34
|
+
const checksumsSig = byName.get(checksumsSigName) ?? null;
|
|
35
|
+
const archive = byName.get(archiveName) ?? null;
|
|
36
|
+
if (!checksums)
|
|
37
|
+
throw new Error(`[release-assets] missing release asset: ${checksumsName}`);
|
|
38
|
+
if (!checksumsSig)
|
|
39
|
+
throw new Error(`[release-assets] missing release asset: ${checksumsSigName}`);
|
|
40
|
+
if (!archive)
|
|
41
|
+
throw new Error(`[release-assets] missing release asset: ${archiveName}`);
|
|
42
|
+
return { version, archive, checksums, checksumsSig };
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=assets.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"assets.js","sourceRoot":"","sources":["../src/assets.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"checksums.d.ts","sourceRoot":"","sources":["../src/checksums.ts"],"names":[],"mappings":"AAAA,wBAAgB,YAAY,CAAC,MAAM,EAAE,QAAQ,CAAC;IAAE,aAAa,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,GAAG,MAAM,CAgBlG"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export function lookupSha256(params) {
|
|
2
|
+
const target = String(params.filename ?? '').trim();
|
|
3
|
+
if (!target)
|
|
4
|
+
throw new Error('[checksums] filename is required');
|
|
5
|
+
const text = String(params.checksumsText ?? '');
|
|
6
|
+
const lines = text.split('\n');
|
|
7
|
+
for (const line of lines) {
|
|
8
|
+
const trimmed = line.trim();
|
|
9
|
+
if (!trimmed)
|
|
10
|
+
continue;
|
|
11
|
+
const m = /^([0-9a-fA-F]{8,})\s+(.+)$/.exec(trimmed);
|
|
12
|
+
if (!m)
|
|
13
|
+
continue;
|
|
14
|
+
const hash = m[1].toLowerCase();
|
|
15
|
+
const file = m[2].trim();
|
|
16
|
+
if (file === target)
|
|
17
|
+
return hash;
|
|
18
|
+
}
|
|
19
|
+
throw new Error(`[checksums] sha256 not found for ${target}`);
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=checksums.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"checksums.js","sourceRoot":"","sources":["../src/checksums.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,YAAY,CAAC,MAA6D;IACxF,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IACpD,IAAI,CAAC,MAAM;QAAE,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC;IAEjE,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,aAAa,IAAI,EAAE,CAAC,CAAC;IAChD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC/B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QAC5B,IAAI,CAAC,OAAO;YAAE,SAAS;QACvB,MAAM,CAAC,GAAG,4BAA4B,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACrD,IAAI,CAAC,CAAC;YAAE,SAAS;QACjB,MAAM,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;QAChC,MAAM,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QACzB,IAAI,IAAI,KAAK,MAAM;YAAE,OAAO,IAAI,CAAC;IACnC,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,oCAAoC,MAAM,EAAE,CAAC,CAAC;AAChE,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export type PlannedCommand = Readonly<{
|
|
2
|
+
cmd: string;
|
|
3
|
+
args: string[];
|
|
4
|
+
}>;
|
|
5
|
+
export declare function planArchiveExtraction(params: Readonly<{
|
|
6
|
+
archiveName: string;
|
|
7
|
+
archivePath: string;
|
|
8
|
+
destDir: string;
|
|
9
|
+
os: 'linux' | 'darwin' | 'windows';
|
|
10
|
+
}>): Readonly<{
|
|
11
|
+
requiredCommand: 'tar' | 'powershell';
|
|
12
|
+
command: PlannedCommand;
|
|
13
|
+
}>;
|
|
14
|
+
//# sourceMappingURL=extractPlan.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extractPlan.d.ts","sourceRoot":"","sources":["../src/extractPlan.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,cAAc,GAAG,QAAQ,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,CAAC;AAEvE,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,QAAQ,CAAC;IACrD,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,EAAE,EAAE,OAAO,GAAG,QAAQ,GAAG,SAAS,CAAC;CACpC,CAAC,GAAG,QAAQ,CAAC;IAAE,eAAe,EAAE,KAAK,GAAG,YAAY,CAAC;IAAC,OAAO,EAAE,cAAc,CAAA;CAAE,CAAC,CAgDhF"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
export function planArchiveExtraction(params) {
|
|
2
|
+
const name = String(params.archiveName ?? '').trim();
|
|
3
|
+
const archivePath = String(params.archivePath ?? '').trim();
|
|
4
|
+
const destDir = String(params.destDir ?? '').trim();
|
|
5
|
+
const os = String(params.os ?? '').trim().toLowerCase();
|
|
6
|
+
if (!name)
|
|
7
|
+
throw new Error('[extract] archiveName is required');
|
|
8
|
+
if (!archivePath)
|
|
9
|
+
throw new Error('[extract] archivePath is required');
|
|
10
|
+
if (!destDir)
|
|
11
|
+
throw new Error('[extract] destDir is required');
|
|
12
|
+
if (os !== 'linux' && os !== 'darwin' && os !== 'windows') {
|
|
13
|
+
throw new Error(`[extract] unsupported os: ${os}`);
|
|
14
|
+
}
|
|
15
|
+
if (name.toLowerCase().endsWith('.zip')) {
|
|
16
|
+
if (os !== 'windows') {
|
|
17
|
+
throw new Error(`[extract] .zip archives are supported only on windows (got ${os})`);
|
|
18
|
+
}
|
|
19
|
+
const command = `Expand-Archive -LiteralPath "${archivePath}" -DestinationPath "${destDir}" -Force`;
|
|
20
|
+
return {
|
|
21
|
+
requiredCommand: 'powershell',
|
|
22
|
+
command: {
|
|
23
|
+
cmd: 'powershell',
|
|
24
|
+
args: ['-NoProfile', '-Command', command],
|
|
25
|
+
},
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
if (name.toLowerCase().endsWith('.tar.gz')) {
|
|
29
|
+
return {
|
|
30
|
+
requiredCommand: 'tar',
|
|
31
|
+
command: {
|
|
32
|
+
cmd: 'tar',
|
|
33
|
+
args: ['-xzf', archivePath, '-C', destDir],
|
|
34
|
+
},
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
if (name.toLowerCase().endsWith('.tar.xz')) {
|
|
38
|
+
return {
|
|
39
|
+
requiredCommand: 'tar',
|
|
40
|
+
command: {
|
|
41
|
+
cmd: 'tar',
|
|
42
|
+
args: ['-xJf', archivePath, '-C', destDir],
|
|
43
|
+
},
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
throw new Error(`[extract] unsupported archive extension: ${name}`);
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=extractPlan.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extractPlan.js","sourceRoot":"","sources":["../src/extractPlan.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,qBAAqB,CAAC,MAKpC;IACA,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IACrD,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IAC5D,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IACpD,MAAM,EAAE,GAAG,MAAM,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAExD,IAAI,CAAC,IAAI;QAAE,MAAM,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAC;IAChE,IAAI,CAAC,WAAW;QAAE,MAAM,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAC;IACvE,IAAI,CAAC,OAAO;QAAE,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;IAC/D,IAAI,EAAE,KAAK,OAAO,IAAI,EAAE,KAAK,QAAQ,IAAI,EAAE,KAAK,SAAS,EAAE,CAAC;QAC1D,MAAM,IAAI,KAAK,CAAC,6BAA6B,EAAE,EAAE,CAAC,CAAC;IACrD,CAAC;IAED,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;QACxC,IAAI,EAAE,KAAK,SAAS,EAAE,CAAC;YACrB,MAAM,IAAI,KAAK,CAAC,8DAA8D,EAAE,GAAG,CAAC,CAAC;QACvF,CAAC;QACD,MAAM,OAAO,GAAG,gCAAgC,WAAW,uBAAuB,OAAO,UAAU,CAAC;QACpG,OAAO;YACL,eAAe,EAAE,YAAY;YAC7B,OAAO,EAAE;gBACP,GAAG,EAAE,YAAY;gBACjB,IAAI,EAAE,CAAC,YAAY,EAAE,UAAU,EAAE,OAAO,CAAC;aAC1C;SACF,CAAC;IACJ,CAAC;IAED,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;QAC3C,OAAO;YACL,eAAe,EAAE,KAAK;YACtB,OAAO,EAAE;gBACP,GAAG,EAAE,KAAK;gBACV,IAAI,EAAE,CAAC,MAAM,EAAE,WAAW,EAAE,IAAI,EAAE,OAAO,CAAC;aAC3C;SACF,CAAC;IACJ,CAAC;IAED,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;QAC3C,OAAO;YACL,eAAe,EAAE,KAAK;YACtB,OAAO,EAAE;gBACP,GAAG,EAAE,KAAK;gBACV,IAAI,EAAE,CAAC,MAAM,EAAE,WAAW,EAAE,IAAI,EAAE,OAAO,CAAC;aAC3C;SACF,CAAC;IACJ,CAAC;IAED,MAAM,IAAI,KAAK,CAAC,4CAA4C,IAAI,EAAE,CAAC,CAAC;AACtE,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
type FetchImpl = typeof fetch;
|
|
2
|
+
export declare function fetchGitHubReleaseByTag(params: Readonly<{
|
|
3
|
+
githubRepo: string;
|
|
4
|
+
tag: string;
|
|
5
|
+
userAgent?: string;
|
|
6
|
+
githubToken?: string;
|
|
7
|
+
fetchImpl?: FetchImpl;
|
|
8
|
+
}>): Promise<unknown>;
|
|
9
|
+
export declare function fetchGitHubLatestRelease(params: Readonly<{
|
|
10
|
+
githubRepo: string;
|
|
11
|
+
userAgent?: string;
|
|
12
|
+
githubToken?: string;
|
|
13
|
+
fetchImpl?: FetchImpl;
|
|
14
|
+
}>): Promise<unknown>;
|
|
15
|
+
export declare function fetchFirstGitHubReleaseByTags(params: Readonly<{
|
|
16
|
+
githubRepo: string;
|
|
17
|
+
tags: string[];
|
|
18
|
+
userAgent?: string;
|
|
19
|
+
githubToken?: string;
|
|
20
|
+
fetchImpl?: FetchImpl;
|
|
21
|
+
}>): Promise<Readonly<{
|
|
22
|
+
tag: string;
|
|
23
|
+
release: unknown;
|
|
24
|
+
}>>;
|
|
25
|
+
export {};
|
|
26
|
+
//# sourceMappingURL=github.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"github.d.ts","sourceRoot":"","sources":["../src/github.ts"],"names":[],"mappings":"AAEA,KAAK,SAAS,GAAG,OAAO,KAAK,CAAC;AAoD9B,wBAAsB,uBAAuB,CAAC,MAAM,EAAE,QAAQ,CAAC;IAC7D,UAAU,EAAE,MAAM,CAAC;IACnB,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,SAAS,CAAC;CACvB,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,CAgCpB;AAED,wBAAsB,wBAAwB,CAAC,MAAM,EAAE,QAAQ,CAAC;IAC9D,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,SAAS,CAAC;CACvB,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,CAgCpB;AAED,wBAAsB,6BAA6B,CAAC,MAAM,EAAE,QAAQ,CAAC;IACnE,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,SAAS,CAAC;CACvB,CAAC,GAAG,OAAO,CAAC,QAAQ,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAAC,CAAC,CA0BxD"}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import { requestJson } from './http.js';
|
|
2
|
+
function buildGitHubReleaseTagUrl(githubRepo, tag) {
|
|
3
|
+
const repo = String(githubRepo ?? '').trim();
|
|
4
|
+
const t = String(tag ?? '').trim();
|
|
5
|
+
if (!repo)
|
|
6
|
+
throw new Error('[github] githubRepo is required');
|
|
7
|
+
if (!t)
|
|
8
|
+
throw new Error('[github] tag is required');
|
|
9
|
+
return `https://api.github.com/repos/${repo}/releases/tags/${encodeURIComponent(t)}`;
|
|
10
|
+
}
|
|
11
|
+
function buildGitHubLatestReleaseUrl(githubRepo) {
|
|
12
|
+
const repo = String(githubRepo ?? '').trim();
|
|
13
|
+
if (!repo)
|
|
14
|
+
throw new Error('[github] githubRepo is required');
|
|
15
|
+
return `https://api.github.com/repos/${repo}/releases/latest`;
|
|
16
|
+
}
|
|
17
|
+
function createHttpError(message, status) {
|
|
18
|
+
const err = new Error(message);
|
|
19
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
20
|
+
err.status = status;
|
|
21
|
+
return err;
|
|
22
|
+
}
|
|
23
|
+
function readHttpStatus(error) {
|
|
24
|
+
const statusFromField = typeof error === 'object' && error != null && 'status' in error
|
|
25
|
+
? Number(
|
|
26
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
27
|
+
error.status)
|
|
28
|
+
: NaN;
|
|
29
|
+
if (Number.isInteger(statusFromField) && statusFromField >= 100 && statusFromField <= 599) {
|
|
30
|
+
return statusFromField;
|
|
31
|
+
}
|
|
32
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
33
|
+
const match = /\((\d{3})\)\s*$/.exec(message);
|
|
34
|
+
if (!match)
|
|
35
|
+
return null;
|
|
36
|
+
const statusFromMessage = Number(match[1]);
|
|
37
|
+
return Number.isInteger(statusFromMessage) ? statusFromMessage : null;
|
|
38
|
+
}
|
|
39
|
+
function normalizeGitHubRequestError(params) {
|
|
40
|
+
const status = readHttpStatus(params.error) ?? 500;
|
|
41
|
+
const message = params.error instanceof Error ? params.error.message : String(params.error);
|
|
42
|
+
return createHttpError(`${params.context}: ${message}`, status);
|
|
43
|
+
}
|
|
44
|
+
export async function fetchGitHubReleaseByTag(params) {
|
|
45
|
+
const userAgent = String(params.userAgent ?? '').trim() || 'happier-release-runtime';
|
|
46
|
+
const token = String(params.githubToken ?? '').trim();
|
|
47
|
+
const url = buildGitHubReleaseTagUrl(params.githubRepo, params.tag);
|
|
48
|
+
const headers = {
|
|
49
|
+
'user-agent': userAgent,
|
|
50
|
+
accept: 'application/vnd.github+json',
|
|
51
|
+
};
|
|
52
|
+
if (token)
|
|
53
|
+
headers.authorization = `Bearer ${token}`;
|
|
54
|
+
if (params.fetchImpl) {
|
|
55
|
+
try {
|
|
56
|
+
const response = await params.fetchImpl(url, { headers });
|
|
57
|
+
if (!response.ok) {
|
|
58
|
+
throw createHttpError(`[github] failed to resolve release tag ${params.tag} (${response.status})`, response.status);
|
|
59
|
+
}
|
|
60
|
+
return response.json();
|
|
61
|
+
}
|
|
62
|
+
catch (error) {
|
|
63
|
+
throw normalizeGitHubRequestError({
|
|
64
|
+
context: `[github] failed to resolve release tag ${params.tag}`,
|
|
65
|
+
error,
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
try {
|
|
70
|
+
return await requestJson({ url, headers });
|
|
71
|
+
}
|
|
72
|
+
catch (error) {
|
|
73
|
+
throw normalizeGitHubRequestError({
|
|
74
|
+
context: `[github] failed to resolve release tag ${params.tag}`,
|
|
75
|
+
error,
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
export async function fetchGitHubLatestRelease(params) {
|
|
80
|
+
const userAgent = String(params.userAgent ?? '').trim() || 'happier-release-runtime';
|
|
81
|
+
const token = String(params.githubToken ?? '').trim();
|
|
82
|
+
const url = buildGitHubLatestReleaseUrl(params.githubRepo);
|
|
83
|
+
const headers = {
|
|
84
|
+
'user-agent': userAgent,
|
|
85
|
+
accept: 'application/vnd.github+json',
|
|
86
|
+
};
|
|
87
|
+
if (token)
|
|
88
|
+
headers.authorization = `Bearer ${token}`;
|
|
89
|
+
if (params.fetchImpl) {
|
|
90
|
+
try {
|
|
91
|
+
const response = await params.fetchImpl(url, { headers });
|
|
92
|
+
if (!response.ok) {
|
|
93
|
+
throw createHttpError(`[github] failed to resolve latest release (${response.status})`, response.status);
|
|
94
|
+
}
|
|
95
|
+
return response.json();
|
|
96
|
+
}
|
|
97
|
+
catch (error) {
|
|
98
|
+
throw normalizeGitHubRequestError({
|
|
99
|
+
context: '[github] failed to resolve latest release',
|
|
100
|
+
error,
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
try {
|
|
105
|
+
return await requestJson({ url, headers });
|
|
106
|
+
}
|
|
107
|
+
catch (error) {
|
|
108
|
+
throw normalizeGitHubRequestError({
|
|
109
|
+
context: '[github] failed to resolve latest release',
|
|
110
|
+
error,
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
export async function fetchFirstGitHubReleaseByTags(params) {
|
|
115
|
+
const tags = Array.isArray(params.tags) ? params.tags : [];
|
|
116
|
+
for (const tag of tags) {
|
|
117
|
+
try {
|
|
118
|
+
// eslint-disable-next-line no-await-in-loop
|
|
119
|
+
const release = await fetchGitHubReleaseByTag({
|
|
120
|
+
githubRepo: params.githubRepo,
|
|
121
|
+
tag,
|
|
122
|
+
userAgent: params.userAgent,
|
|
123
|
+
githubToken: params.githubToken,
|
|
124
|
+
fetchImpl: params.fetchImpl,
|
|
125
|
+
});
|
|
126
|
+
return { tag, release };
|
|
127
|
+
}
|
|
128
|
+
catch (e) {
|
|
129
|
+
const status = typeof e === 'object' && e != null && 'status' in e
|
|
130
|
+
? Number(
|
|
131
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
132
|
+
e.status)
|
|
133
|
+
: NaN;
|
|
134
|
+
if (status === 404)
|
|
135
|
+
continue;
|
|
136
|
+
throw e;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
throw createHttpError('[github] no matching release tags found', 404);
|
|
140
|
+
}
|
|
141
|
+
//# sourceMappingURL=github.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"github.js","sourceRoot":"","sources":["../src/github.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
type HeaderMap = Readonly<Record<string, string>>;
|
|
2
|
+
export declare function requestBytes(params: Readonly<{
|
|
3
|
+
url: string;
|
|
4
|
+
headers?: HeaderMap;
|
|
5
|
+
timeoutMs?: number;
|
|
6
|
+
}>): Promise<Buffer>;
|
|
7
|
+
export declare function requestText(params: Readonly<{
|
|
8
|
+
url: string;
|
|
9
|
+
headers?: HeaderMap;
|
|
10
|
+
timeoutMs?: number;
|
|
11
|
+
}>): Promise<string>;
|
|
12
|
+
export declare function requestJson<T>(params: Readonly<{
|
|
13
|
+
url: string;
|
|
14
|
+
headers?: HeaderMap;
|
|
15
|
+
timeoutMs?: number;
|
|
16
|
+
}>): Promise<T>;
|
|
17
|
+
export {};
|
|
18
|
+
//# sourceMappingURL=http.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"AAMA,KAAK,SAAS,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;AAmHlD,wBAAsB,YAAY,CAAC,MAAM,EAAE,QAAQ,CAAC;IAClD,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CAWnB;AAED,wBAAsB,WAAW,CAAC,MAAM,EAAE,QAAQ,CAAC;IACjD,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CAGnB;AAED,wBAAsB,WAAW,CAAC,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC;IACpD,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAEd"}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { request as httpRequest } from 'node:http';
|
|
2
|
+
import { request as httpsRequest } from 'node:https';
|
|
3
|
+
const DEFAULT_TIMEOUT_MS = 30_000;
|
|
4
|
+
const MAX_REDIRECTS = 5;
|
|
5
|
+
const CROSS_ORIGIN_SENSITIVE_HEADERS = new Set(['authorization', 'proxy-authorization']);
|
|
6
|
+
function decodeDataUrl(url) {
|
|
7
|
+
const match = /^data:([^,]*?),(.*)$/s.exec(url);
|
|
8
|
+
if (!match) {
|
|
9
|
+
throw new Error(`[http] invalid data URL`);
|
|
10
|
+
}
|
|
11
|
+
const meta = match[1] ?? '';
|
|
12
|
+
const body = match[2] ?? '';
|
|
13
|
+
const isBase64 = meta.split(';').some((part) => part.trim().toLowerCase() === 'base64');
|
|
14
|
+
if (isBase64) {
|
|
15
|
+
return Buffer.from(body, 'base64');
|
|
16
|
+
}
|
|
17
|
+
return Buffer.from(decodeURIComponent(body), 'utf8');
|
|
18
|
+
}
|
|
19
|
+
function dropCrossOriginSensitiveHeaders(headers) {
|
|
20
|
+
if (!headers) {
|
|
21
|
+
return headers;
|
|
22
|
+
}
|
|
23
|
+
let nextHeaders = null;
|
|
24
|
+
for (const [key, value] of Object.entries(headers)) {
|
|
25
|
+
if (CROSS_ORIGIN_SENSITIVE_HEADERS.has(key.toLowerCase())) {
|
|
26
|
+
nextHeaders ??= { ...headers };
|
|
27
|
+
delete nextHeaders[key];
|
|
28
|
+
continue;
|
|
29
|
+
}
|
|
30
|
+
if (nextHeaders) {
|
|
31
|
+
nextHeaders[key] = value;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return nextHeaders ?? headers;
|
|
35
|
+
}
|
|
36
|
+
function resolveRedirectHeaders(params) {
|
|
37
|
+
const requestOrigin = new URL(params.requestUrl).origin;
|
|
38
|
+
const redirectOrigin = new URL(params.redirectUrl).origin;
|
|
39
|
+
if (requestOrigin === redirectOrigin) {
|
|
40
|
+
return params.headers;
|
|
41
|
+
}
|
|
42
|
+
return dropCrossOriginSensitiveHeaders(params.headers);
|
|
43
|
+
}
|
|
44
|
+
async function requestBufferWithNode(params) {
|
|
45
|
+
const redirectCount = params.redirectCount ?? 0;
|
|
46
|
+
if (redirectCount > MAX_REDIRECTS) {
|
|
47
|
+
throw new Error(`[http] too many redirects for ${params.url}`);
|
|
48
|
+
}
|
|
49
|
+
const requestImpl = params.url.startsWith('https:') ? httpsRequest : httpRequest;
|
|
50
|
+
return await new Promise((resolve, reject) => {
|
|
51
|
+
const req = requestImpl(params.url, {
|
|
52
|
+
method: 'GET',
|
|
53
|
+
headers: params.headers,
|
|
54
|
+
}, (res) => {
|
|
55
|
+
const statusCode = res.statusCode ?? 0;
|
|
56
|
+
const location = typeof res.headers.location === 'string' ? res.headers.location.trim() : '';
|
|
57
|
+
if (statusCode >= 300 && statusCode < 400 && location) {
|
|
58
|
+
const nextUrl = new URL(location, params.url).toString();
|
|
59
|
+
const nextHeaders = resolveRedirectHeaders({
|
|
60
|
+
requestUrl: params.url,
|
|
61
|
+
redirectUrl: nextUrl,
|
|
62
|
+
headers: params.headers,
|
|
63
|
+
});
|
|
64
|
+
res.resume();
|
|
65
|
+
void requestBufferWithNode({
|
|
66
|
+
url: nextUrl,
|
|
67
|
+
headers: nextHeaders,
|
|
68
|
+
redirectCount: redirectCount + 1,
|
|
69
|
+
timeoutMs: params.timeoutMs,
|
|
70
|
+
}).then(resolve, reject);
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
if (statusCode < 200 || statusCode >= 300) {
|
|
74
|
+
res.resume();
|
|
75
|
+
reject(new Error(`[http] request failed: ${params.url} (${statusCode})`));
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
const chunks = [];
|
|
79
|
+
res.on('data', (chunk) => {
|
|
80
|
+
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
|
|
81
|
+
});
|
|
82
|
+
res.on('end', () => resolve(Buffer.concat(chunks)));
|
|
83
|
+
res.on('error', reject);
|
|
84
|
+
});
|
|
85
|
+
req.setTimeout(params.timeoutMs ?? DEFAULT_TIMEOUT_MS, () => {
|
|
86
|
+
req.destroy(new Error(`[http] request timed out: ${params.url}`));
|
|
87
|
+
});
|
|
88
|
+
req.on('error', reject);
|
|
89
|
+
req.end();
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
export async function requestBytes(params) {
|
|
93
|
+
const url = String(params.url ?? '').trim();
|
|
94
|
+
if (!url)
|
|
95
|
+
throw new Error('[http] url is required');
|
|
96
|
+
if (url.startsWith('data:')) {
|
|
97
|
+
return decodeDataUrl(url);
|
|
98
|
+
}
|
|
99
|
+
return await requestBufferWithNode({
|
|
100
|
+
url,
|
|
101
|
+
headers: params.headers,
|
|
102
|
+
timeoutMs: params.timeoutMs,
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
export async function requestText(params) {
|
|
106
|
+
const bytes = await requestBytes(params);
|
|
107
|
+
return bytes.toString('utf8');
|
|
108
|
+
}
|
|
109
|
+
export async function requestJson(params) {
|
|
110
|
+
return JSON.parse(await requestText(params));
|
|
111
|
+
}
|
|
112
|
+
//# sourceMappingURL=http.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http.js","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export { DEFAULT_MINISIGN_PUBLIC_KEY, verifyMinisign } from './minisign.js';
|
|
2
|
+
export { lookupSha256 } from './checksums.js';
|
|
3
|
+
export { resolveReleaseAssetBundle } from './assets.js';
|
|
4
|
+
export { planArchiveExtraction } from './extractPlan.js';
|
|
5
|
+
export { downloadVerifiedReleaseAssetBundle } from './verifiedDownload.js';
|
|
6
|
+
export { fetchGitHubLatestRelease, fetchGitHubReleaseByTag, fetchFirstGitHubReleaseByTags } from './github.js';
|
|
7
|
+
export { PUBLIC_RELEASE_RING_IDS, RELEASE_RING_IDS, getReleaseRingCatalogEntry, getReleaseRingPublicLabel, isPublicReleaseRingId, listPublicReleaseRingCatalogEntries, listPublicReleaseRingLabels, listReleaseRingCatalogEntries, normalizePublicReleaseRingId, normalizeReleaseRingId, } from './releaseRings.js';
|
|
8
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,2BAA2B,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC5E,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,yBAAyB,EAAE,MAAM,aAAa,CAAC;AACxD,OAAO,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AACzD,OAAO,EAAE,kCAAkC,EAAE,MAAM,uBAAuB,CAAC;AAC3E,OAAO,EAAE,wBAAwB,EAAE,uBAAuB,EAAE,6BAA6B,EAAE,MAAM,aAAa,CAAC;AAC/G,OAAO,EACL,uBAAuB,EACvB,gBAAgB,EAChB,0BAA0B,EAC1B,yBAAyB,EACzB,qBAAqB,EACrB,mCAAmC,EACnC,2BAA2B,EAC3B,6BAA6B,EAC7B,4BAA4B,EAC5B,sBAAsB,GACvB,MAAM,mBAAmB,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export { DEFAULT_MINISIGN_PUBLIC_KEY, verifyMinisign } from './minisign.js';
|
|
2
|
+
export { lookupSha256 } from './checksums.js';
|
|
3
|
+
export { resolveReleaseAssetBundle } from './assets.js';
|
|
4
|
+
export { planArchiveExtraction } from './extractPlan.js';
|
|
5
|
+
export { downloadVerifiedReleaseAssetBundle } from './verifiedDownload.js';
|
|
6
|
+
export { fetchGitHubLatestRelease, fetchGitHubReleaseByTag, fetchFirstGitHubReleaseByTags } from './github.js';
|
|
7
|
+
export { PUBLIC_RELEASE_RING_IDS, RELEASE_RING_IDS, getReleaseRingCatalogEntry, getReleaseRingPublicLabel, isPublicReleaseRingId, listPublicReleaseRingCatalogEntries, listPublicReleaseRingLabels, listReleaseRingCatalogEntries, normalizePublicReleaseRingId, normalizeReleaseRingId, } from './releaseRings.js';
|
|
8
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,2BAA2B,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC5E,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,yBAAyB,EAAE,MAAM,aAAa,CAAC;AACxD,OAAO,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AACzD,OAAO,EAAE,kCAAkC,EAAE,MAAM,uBAAuB,CAAC;AAC3E,OAAO,EAAE,wBAAwB,EAAE,uBAAuB,EAAE,6BAA6B,EAAE,MAAM,aAAa,CAAC;AAC/G,OAAO,EACL,uBAAuB,EACvB,gBAAgB,EAChB,0BAA0B,EAC1B,yBAAyB,EACzB,qBAAqB,EACrB,mCAAmC,EACnC,2BAA2B,EAC3B,6BAA6B,EAC7B,4BAA4B,EAC5B,sBAAsB,GACvB,MAAM,mBAAmB,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export declare const DEFAULT_MINISIGN_PUBLIC_KEY = "untrusted comment: minisign public key 91AE28177BF6E43C\nRWQ85PZ7FyiukYbL3qv/bKnwgbT68wLVzotapeMFIb8n+c7pBQ7U8W2t\n";
|
|
2
|
+
export declare function verifyMinisign(params: Readonly<{
|
|
3
|
+
message: Buffer;
|
|
4
|
+
pubkeyFile: string;
|
|
5
|
+
sigFile: string;
|
|
6
|
+
}>): boolean;
|
|
7
|
+
//# sourceMappingURL=minisign.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"minisign.d.ts","sourceRoot":"","sources":["../src/minisign.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,2BAA2B,wHAEvC,CAAC;AAmEF,wBAAgB,cAAc,CAAC,MAAM,EAAE,QAAQ,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,GAAG,OAAO,CAiClH"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { createHash, createPublicKey, verify } from 'node:crypto';
|
|
2
|
+
const ED25519_SPKI_PREFIX = Buffer.from('302a300506032b6570032100', 'hex');
|
|
3
|
+
export const DEFAULT_MINISIGN_PUBLIC_KEY = `untrusted comment: minisign public key 91AE28177BF6E43C
|
|
4
|
+
RWQ85PZ7FyiukYbL3qv/bKnwgbT68wLVzotapeMFIb8n+c7pBQ7U8W2t
|
|
5
|
+
`;
|
|
6
|
+
function decodeBase64Line(line, expectedBytes) {
|
|
7
|
+
const bytes = Buffer.from(String(line ?? '').trim(), 'base64');
|
|
8
|
+
if (expectedBytes != null && bytes.length !== expectedBytes) {
|
|
9
|
+
throw new Error(`[minisign] expected ${expectedBytes} bytes, got ${bytes.length}`);
|
|
10
|
+
}
|
|
11
|
+
return bytes;
|
|
12
|
+
}
|
|
13
|
+
function parseMinisignPublicKeyFile(pubkeyFile) {
|
|
14
|
+
const lines = String(pubkeyFile ?? '')
|
|
15
|
+
.split('\n')
|
|
16
|
+
.map((l) => l.trim())
|
|
17
|
+
.filter(Boolean);
|
|
18
|
+
if (lines.length < 2)
|
|
19
|
+
throw new Error('[minisign] invalid public key file');
|
|
20
|
+
const payload = lines[lines.length - 1] ?? '';
|
|
21
|
+
const bytes = decodeBase64Line(payload, 42);
|
|
22
|
+
const signatureAlgorithm = bytes.subarray(0, 2);
|
|
23
|
+
const keyId = bytes.subarray(2, 10);
|
|
24
|
+
const rawPublicKey = bytes.subarray(10, 42);
|
|
25
|
+
return { signatureAlgorithm, keyId, rawPublicKey };
|
|
26
|
+
}
|
|
27
|
+
function parseMinisignSignatureFile(sigFile) {
|
|
28
|
+
const lines = String(sigFile ?? '').split('\n');
|
|
29
|
+
if (lines.length < 4)
|
|
30
|
+
throw new Error('[minisign] invalid signature file');
|
|
31
|
+
const untrustedPayload = String(lines[1] ?? '').trim();
|
|
32
|
+
const trustedComment = String(lines[2] ?? '');
|
|
33
|
+
const globalPayload = String(lines[3] ?? '').trim();
|
|
34
|
+
const untrustedBytes = decodeBase64Line(untrustedPayload, 74);
|
|
35
|
+
const signatureAlgorithm = untrustedBytes.subarray(0, 2);
|
|
36
|
+
const keyId = untrustedBytes.subarray(2, 10);
|
|
37
|
+
const signature = untrustedBytes.subarray(10, 74);
|
|
38
|
+
const globalSignature = decodeBase64Line(globalPayload, 64);
|
|
39
|
+
if (!trustedComment.startsWith('trusted comment: ')) {
|
|
40
|
+
throw new Error('[minisign] unexpected trusted comment format');
|
|
41
|
+
}
|
|
42
|
+
const trustedSuffix = Buffer.from(trustedComment.slice('trusted comment: '.length), 'utf-8');
|
|
43
|
+
return { signatureAlgorithm, keyId, signature, trustedSuffix, globalSignature };
|
|
44
|
+
}
|
|
45
|
+
function createEd25519PublicKey(rawPublicKey) {
|
|
46
|
+
if (!Buffer.isBuffer(rawPublicKey) || rawPublicKey.length !== 32) {
|
|
47
|
+
throw new Error('[minisign] invalid Ed25519 public key length');
|
|
48
|
+
}
|
|
49
|
+
const spki = Buffer.concat([ED25519_SPKI_PREFIX, rawPublicKey]);
|
|
50
|
+
return createPublicKey({ key: spki, format: 'der', type: 'spki' });
|
|
51
|
+
}
|
|
52
|
+
function bytesEqual(a, b) {
|
|
53
|
+
if (!a || !b)
|
|
54
|
+
return false;
|
|
55
|
+
if (a.length !== b.length)
|
|
56
|
+
return false;
|
|
57
|
+
return Buffer.compare(a, b) === 0;
|
|
58
|
+
}
|
|
59
|
+
export function verifyMinisign(params) {
|
|
60
|
+
try {
|
|
61
|
+
const bin = Buffer.isBuffer(params.message) ? params.message : Buffer.from(params.message ?? '');
|
|
62
|
+
const pubkey = parseMinisignPublicKeyFile(params.pubkeyFile);
|
|
63
|
+
const sig = parseMinisignSignatureFile(params.sigFile);
|
|
64
|
+
if (!bytesEqual(pubkey.signatureAlgorithm, Buffer.from('Ed'))) {
|
|
65
|
+
throw new Error('[minisign] incompatible public key signature algorithm');
|
|
66
|
+
}
|
|
67
|
+
if (!bytesEqual(pubkey.keyId, sig.keyId)) {
|
|
68
|
+
throw new Error('[minisign] incompatible key identifiers');
|
|
69
|
+
}
|
|
70
|
+
let prehashed = false;
|
|
71
|
+
if (bytesEqual(sig.signatureAlgorithm, Buffer.from('Ed'))) {
|
|
72
|
+
prehashed = false;
|
|
73
|
+
}
|
|
74
|
+
else if (bytesEqual(sig.signatureAlgorithm, Buffer.from('ED'))) {
|
|
75
|
+
prehashed = true;
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
throw new Error('[minisign] unsupported signature algorithm');
|
|
79
|
+
}
|
|
80
|
+
const publicKey = createEd25519PublicKey(pubkey.rawPublicKey);
|
|
81
|
+
const payload = prehashed ? createHash('blake2b512').update(bin).digest() : bin;
|
|
82
|
+
const okSig = verify(null, payload, publicKey, sig.signature);
|
|
83
|
+
if (!okSig)
|
|
84
|
+
return false;
|
|
85
|
+
const okGlobal = verify(null, Buffer.concat([sig.signature, sig.trustedSuffix]), publicKey, sig.globalSignature);
|
|
86
|
+
return okGlobal;
|
|
87
|
+
}
|
|
88
|
+
catch {
|
|
89
|
+
return false;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
//# sourceMappingURL=minisign.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"minisign.js","sourceRoot":"","sources":["../src/minisign.ts"],"names":[],"mappings":"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"}
|