返回 DeepSeek-Reasonix
releases.ts
根目录 / site / src / data / releases.ts
1 import source from '../../../release-notes/releases.json';
2 import { readFileSync } from 'node:fs';
3 import { resolve } from 'node:path';
4
5 export type LocalizedText = { en: string; zh: string };
6 export type ReleaseTarget = 'desktop' | 'cli' | 'site' | 'service';
7
8 export type ReleaseItem = {
9 title: LocalizedText;
10 body: LocalizedText;
11 refs?: number[];
12 targets?: ReleaseTarget[];
13 };
14
15 export type ReleaseHighlight = ReleaseItem & {
16 kind: 'new' | 'improved' | 'fixed' | 'security';
17 };
18
19 export type ReleaseGuide = ReleaseItem & { href: string };
20 export type ReleaseUpgrade = ReleaseItem & { level: 'info' | 'warning' };
21
22 export type ReleaseRecord = {
23 version: string;
24 targetingVersion?: 1;
25 releaseId?: string;
26 baseVersion?: string;
27 date: string;
28 channel: 'stable' | 'prerelease';
29 status?: 'reviewed' | 'published';
30 candidateSha?: string;
31 previousRelease?: string;
32 builds?: { cli: string; desktop: string; npm: string };
33 title: LocalizedText;
34 summary: LocalizedText;
35 surfaces: string[];
36 guides: ReleaseGuide[];
37 highlights: ReleaseHighlight[];
38 changes: { new: ReleaseItem[]; improved: ReleaseItem[]; fixed: ReleaseItem[] };
39 upgrade: ReleaseUpgrade[];
40 risks: ReleaseItem[];
41 contributors: string[];
42 links: { github: string; compare: string; download: string };
43 };
44
45 export const releaseCatalog = source as { schemaVersion: number; releases: ReleaseRecord[] };
46 export const allReleases = releaseCatalog.releases;
47
48 let publishedIds = new Set<string>();
49 try {
50 const generated = JSON.parse(
51 readFileSync(resolve(process.cwd(), '.generated/publications.json'), 'utf8'),
52 ) as { publications?: string[] };
53 publishedIds = new Set(generated.publications ?? []);
54 } catch {
55 // Before prebuild, preserve legacy entries and fail closed for reviewed
56 // releases that require a successful all-surface publication marker.
57 }
58
59 export const publishedReleases = allReleases.filter(
60 (release) => !release.status || release.status === 'published' || publishedIds.has(release.version),
61 );
62 // Public navigation contains official releases only. Historical prereleases
63 // remain addressable by their exact version URL for compatibility.
64 export const releases = publishedReleases.filter((release) => release.channel === 'stable');
65 export const stableReleases = releases;
66 export const previewReleases = publishedReleases.filter((release) => release.channel === 'prerelease');
67 export const latestStableRelease = stableReleases[0];
68 export const latestPreviewRelease = previewReleases[0];
69 export const latestRelease = latestStableRelease;
70
71 export function releasePath(version: string): string {
72 return `/changelog/v${version}/`;
73 }
74
75 export function releaseContentItems(release: ReleaseRecord): ReleaseItem[] {
76 return [
77 ...release.highlights,
78 ...release.changes.new,
79 ...release.changes.improved,
80 ...release.changes.fixed,
81 ...release.upgrade,
82 ...release.risks,
83 ];
84 }
85
86 export function releaseTargetCount(release: ReleaseRecord, target: ReleaseTarget): number {
87 return releaseContentItems(release).filter((item) => item.targets?.includes(target)).length;
88 }
89
89 lines TYPESCRIPT