源码快照 @ 2026-09-02 (source-only, 剔除非源码素材)
This commit is contained in:
@@ -0,0 +1,142 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* Refreshes den-api's COLD-START FALLBACK snapshot of published desktop
|
||||
* versions (ee/apps/den-api/src/generated/desktop-versions.ts).
|
||||
*
|
||||
* At runtime den-api discovers published versions from the GitHub Releases
|
||||
* API (src/desktop-releases.ts); this committed snapshot only serves
|
||||
* air-gapped deployments and the window before the first successful fetch.
|
||||
* It is no longer regenerated per release — refresh it occasionally via:
|
||||
* node scripts/release/generate-desktop-versions.mjs --version <latest>
|
||||
*/
|
||||
import { execFileSync } from "node:child_process";
|
||||
import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
||||
import { resolve } from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
|
||||
const root = resolve(fileURLToPath(new URL("../..", import.meta.url)));
|
||||
export const MIN_SUPPORTED_DESKTOP_VERSION = "0.17.0";
|
||||
export const GENERATED_DESKTOP_VERSIONS_PATH = resolve(
|
||||
root,
|
||||
"ee/apps/den-api/src/generated/desktop-versions.ts",
|
||||
);
|
||||
|
||||
function parseStableVersion(value) {
|
||||
const match = value.match(/^(\d+)\.(\d+)\.(\d+)$/);
|
||||
return match ? match.slice(1).map(Number) : null;
|
||||
}
|
||||
|
||||
function compareStableVersions(left, right) {
|
||||
const leftParts = parseStableVersion(left);
|
||||
const rightParts = parseStableVersion(right);
|
||||
if (!leftParts || !rightParts) return 0;
|
||||
|
||||
for (let index = 0; index < 3; index += 1) {
|
||||
const difference = leftParts[index] - rightParts[index];
|
||||
if (difference !== 0) return difference;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
export function buildPublishedDesktopVersions({ tags, currentVersion }) {
|
||||
if (!parseStableVersion(currentVersion)) {
|
||||
throw new Error(`Invalid current desktop version: ${currentVersion}`);
|
||||
}
|
||||
|
||||
const versions = tags.flatMap((tag) => {
|
||||
const trimmed = tag.trim();
|
||||
if (!trimmed.startsWith("v")) return [];
|
||||
const version = trimmed.slice(1);
|
||||
return parseStableVersion(version) ? [version] : [];
|
||||
});
|
||||
versions.push(currentVersion);
|
||||
|
||||
return [...new Set(versions)]
|
||||
.filter(
|
||||
(version) =>
|
||||
compareStableVersions(version, MIN_SUPPORTED_DESKTOP_VERSION) >= 0 &&
|
||||
compareStableVersions(version, currentVersion) <= 0,
|
||||
)
|
||||
.sort((left, right) => compareStableVersions(right, left));
|
||||
}
|
||||
|
||||
export function renderDesktopVersionsFile(versions) {
|
||||
return [
|
||||
`export const MIN_SUPPORTED_DESKTOP_VERSION = ${JSON.stringify(MIN_SUPPORTED_DESKTOP_VERSION)} as const;`,
|
||||
"",
|
||||
"export const PUBLISHED_DESKTOP_VERSIONS = [",
|
||||
...versions.map(
|
||||
(version, index) =>
|
||||
` ${JSON.stringify(version)}${index < versions.length - 1 ? "," : ""}`,
|
||||
),
|
||||
"] as const;",
|
||||
"",
|
||||
].join("\n");
|
||||
}
|
||||
|
||||
export function readGeneratedDesktopVersions(filePath = GENERATED_DESKTOP_VERSIONS_PATH) {
|
||||
const source = readFileSync(filePath, "utf8");
|
||||
const match = source.match(/PUBLISHED_DESKTOP_VERSIONS\s*=\s*(\[[\s\S]*?\])\s*as const/);
|
||||
if (!match) {
|
||||
throw new Error(`Published desktop versions missing from ${filePath}`);
|
||||
}
|
||||
const versions = [...match[1].matchAll(/"(\d+\.\d+\.\d+)"/g)].map(
|
||||
(versionMatch) => versionMatch[1],
|
||||
);
|
||||
if (versions.length === 0) {
|
||||
throw new Error(`Published desktop versions are invalid in ${filePath}`);
|
||||
}
|
||||
return versions;
|
||||
}
|
||||
|
||||
function readStableTags() {
|
||||
return execFileSync("git", ["tag", "--list", "v*"], {
|
||||
cwd: root,
|
||||
encoding: "utf8",
|
||||
}).split("\n");
|
||||
}
|
||||
|
||||
function main() {
|
||||
const args = process.argv.slice(2);
|
||||
const versionIndex = args.indexOf("--version");
|
||||
const currentVersion = versionIndex >= 0 ? args[versionIndex + 1] : null;
|
||||
if (!currentVersion) {
|
||||
throw new Error(
|
||||
"Pass --version X.Y.Z (package.json holds the 0.0.0-dev placeholder; versions live in git tags).",
|
||||
);
|
||||
}
|
||||
const dryRun = args.includes("--dry-run");
|
||||
const existingVersions = existsSync(GENERATED_DESKTOP_VERSIONS_PATH)
|
||||
? readGeneratedDesktopVersions()
|
||||
: [];
|
||||
const versions = buildPublishedDesktopVersions({
|
||||
tags: [
|
||||
...readStableTags(),
|
||||
...existingVersions.map((version) => `v${version}`),
|
||||
],
|
||||
currentVersion,
|
||||
});
|
||||
const output = renderDesktopVersionsFile(versions);
|
||||
|
||||
if (!dryRun) {
|
||||
writeFileSync(GENERATED_DESKTOP_VERSIONS_PATH, output);
|
||||
}
|
||||
|
||||
console.log(JSON.stringify({
|
||||
ok: true,
|
||||
dryRun,
|
||||
currentVersion,
|
||||
minimumVersion: MIN_SUPPORTED_DESKTOP_VERSION,
|
||||
versions,
|
||||
file: "ee/apps/den-api/src/generated/desktop-versions.ts",
|
||||
}, null, 2));
|
||||
}
|
||||
|
||||
if (process.argv[1] && resolve(process.argv[1]) === fileURLToPath(import.meta.url)) {
|
||||
try {
|
||||
main();
|
||||
} catch (error) {
|
||||
console.error(error instanceof Error ? error.message : String(error));
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user