Skip to content

Commit ca2a5f4

Browse files
committed
feat(download): fetch version at build time and enable Windows downloads
- Move version fetching from client-side to build time (server-side) - Enable Windows platform downloads - Update all download links to use build-time version from GitHub releases - Improve platform-specific asset matching in getDownloadUrlForPlatform - Add getLatestVersion() function for build-time version retrieval
1 parent 4717c7c commit ca2a5f4

File tree

8 files changed

+229
-73
lines changed

8 files changed

+229
-73
lines changed

app/download/components/download-page-client.tsx

Lines changed: 10 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
'use client'
22

3-
import { formatReleaseDate, formatVersion, getLatestRelease, type GitHubRelease } from '@/lib/github';
3+
import { formatReleaseDate, formatVersion, type GitHubRelease } from '@/lib/github';
44
import AppleIcon from "@/public/svgs/brands/apple.svg";
55
import DockerIcon from "@/public/svgs/brands/docker.svg";
66
import LinuxIcon from "@/public/svgs/brands/linux.svg";
@@ -11,7 +11,11 @@ import PlatformSelector from './platform-selector';
1111
import PlatformFactory from './platforms/platform-factory';
1212
import { type PlatformInfoData } from './platforms/platform-info';
1313

14-
export default function DownloadPageClient() {// 使用 download 命名空间
14+
interface DownloadPageClientProps {
15+
release: GitHubRelease | null;
16+
}
17+
18+
export default function DownloadPageClient({ release }: DownloadPageClientProps) {// 使用 download 命名空间
1519

1620
// 平台配置 - 直接使用 useMemo,不依赖 t 函数
1721
const platforms = useMemo((): PlatformInfoData[] => [
@@ -41,8 +45,7 @@ export default function DownloadPageClient() {// 使用 download 命名空间
4145
name: 'Windows',
4246
icon: <WindowsIcon className="w-full h-full aspect-square" />,
4347
description: 'Windows 10/11 with native binary support',
44-
available: false,
45-
comingSoon: true,
48+
available: true,
4649
},
4750
], []);
4851

@@ -51,8 +54,6 @@ export default function DownloadPageClient() {// 使用 download 命名空间
5154
// State management
5255
const [selectedPlatform, setSelectedPlatform] = useState<PlatformInfoData | null>(null);
5356
const [isInitialized, setIsInitialized] = useState(false);
54-
const [release, setRelease] = useState<GitHubRelease | null>(null);
55-
const [isLoadingRelease, setIsLoadingRelease] = useState(true);
5657

5758
// Initialize selected platform - 只在组件挂载时执行一次
5859
useEffect(() => {
@@ -88,22 +89,6 @@ export default function DownloadPageClient() {// 使用 download 命名空间
8889
}
8990
}, [platforms, availablePlatforms, isInitialized]);
9091

91-
// Get latest version information
92-
useEffect(() => {
93-
const fetchLatestRelease = async () => {
94-
try {
95-
const latestRelease = await getLatestRelease();
96-
setRelease(latestRelease);
97-
} catch (error) {
98-
console.error('Failed to fetch latest release:', error);
99-
} finally {
100-
setIsLoadingRelease(false);
101-
}
102-
};
103-
104-
fetchLatestRelease();
105-
}, []);
106-
10792
// Handle platform selection change
10893
const handlePlatformChange = (platform: PlatformInfoData) => {
10994
setSelectedPlatform(platform);
@@ -144,15 +129,9 @@ export default function DownloadPageClient() {// 使用 download 命名空间
144129
{/* 版本信息 */}
145130
<div className="flex items-center space-x-2">
146131
<span className="text-sm font-medium text-foreground">
147-
{isLoadingRelease ? (
148-
'Loading latest version...'
149-
) : release ? (
150-
formatVersion(release.tag_name)
151-
) : (
152-
'v1.0.0'
153-
)}
132+
{release ? formatVersion(release.tag_name) : 'v1.0.0'}
154133
</span>
155-
{!isLoadingRelease && (
134+
{release && (
156135
<span className="inline-flex items-center space-x-1 px-2 py-1 bg-green-100 dark:bg-green-900/30 text-green-700 dark:text-green-300 text-xs rounded-full">
157136
<div className="w-1 h-1 bg-green-500 rounded-full"></div>
158137
<span>{'Latest'}</span>
@@ -190,7 +169,7 @@ export default function DownloadPageClient() {// 使用 download 命名空间
190169
{selectedPlatform && (
191170
<section className="py-16 bg-muted/30">
192171
<div className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
193-
<PlatformFactory platform={selectedPlatform} />
172+
<PlatformFactory platform={selectedPlatform} release={release} />
194173
</div>
195174
</section>
196175
)}

app/download/components/platforms/docker-download-section.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,15 @@ import CodeBlock from "../code-block";
77
import Note from "../common/note";
88
import PlatformHeader from "../common/platform-header";
99
import { type PlatformInfoData } from "./platform-info";
10+
import { type GitHubRelease } from '@/lib/github';
1011

1112
interface DockerDownloadSectionProps {
1213
platform: PlatformInfoData;
14+
release: GitHubRelease | null;
1315
className?: string;
1416
}
1517

16-
export default function DockerDownloadSection({ platform, className }: DockerDownloadSectionProps) {return (
18+
export default function DockerDownloadSection({ platform, release, className }: DockerDownloadSectionProps) {return (
1719
<div className={cn("space-y-8", className)}>
1820
{/* Platform Header */}
1921
<PlatformHeader platform={platform} />

app/download/components/platforms/linux-download-section.tsx

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,40 @@ import CodeBlock from "../code-block";
66
import Note from "../common/note";
77
import PlatformHeader from "../common/platform-header";
88
import { type PlatformInfoData } from "./platform-info";
9+
import { getDownloadUrlForPlatform, type GitHubRelease } from '@/lib/github';
910

1011
interface LinuxDownloadSectionProps {
1112
platform: PlatformInfoData;
13+
release: GitHubRelease | null;
1214
className?: string;
1315
}
1416

15-
export default function LinuxDownloadSection({ platform, className }: LinuxDownloadSectionProps) {return (
17+
export default function LinuxDownloadSection({ platform, release, className }: LinuxDownloadSectionProps) {
18+
// Get download URLs from release assets or use fallback
19+
const x86_64Url = release
20+
? getDownloadUrlForPlatform(release, 'linux', 'x86_64')
21+
: null;
22+
23+
const aarch64Url = release
24+
? getDownloadUrlForPlatform(release, 'linux', 'aarch64')
25+
: null;
26+
27+
const fallbackX86_64Url = 'https://github.com/rustfs/rustfs/releases/latest';
28+
const fallbackAarch64Url = 'https://github.com/rustfs/rustfs/releases/latest';
29+
30+
const finalX86_64Url = x86_64Url || fallbackX86_64Url;
31+
const finalAarch64Url = aarch64Url || fallbackAarch64Url;
32+
33+
// Extract filename from URL for code block
34+
const getFilenameFromUrl = (url: string, arch: string) => {
35+
if (url.includes('github.com')) {
36+
return `rustfs-linux-${arch}-musl.zip`;
37+
}
38+
const match = url.match(/([^\/]+\.zip)/);
39+
return match ? match[1] : `rustfs-linux-${arch}-musl.zip`;
40+
};
41+
42+
return (
1643
<div className={cn("space-y-8", className)}>
1744
{/* Platform Header */}
1845
<PlatformHeader platform={platform} />
@@ -40,7 +67,7 @@ export default function LinuxDownloadSection({ platform, className }: LinuxDownl
4067
</p>
4168
</div>
4269
<a
43-
href="https://dl.rustfs.com/artifacts/rustfs/release/rustfs-linux-x86_64-musl-latest.zip"
70+
href={finalX86_64Url}
4471
target="_blank"
4572
rel="noopener noreferrer"
4673
className="inline-flex items-center space-x-2 px-4 py-2 bg-primary text-primary-foreground rounded-lg hover:bg-primary/90 transition-colors">
@@ -51,8 +78,8 @@ export default function LinuxDownloadSection({ platform, className }: LinuxDownl
5178

5279
<CodeBlock
5380
code={[
54-
"curl -O https://dl.rustfs.com/artifacts/rustfs/release/rustfs-linux-x86_64-musl-latest.zip",
55-
"unzip rustfs-linux-x86_64-musl-latest.zip",
81+
`curl -O ${finalX86_64Url}`,
82+
`unzip ${getFilenameFromUrl(finalX86_64Url, 'x86_64')}`,
5683
"./rustfs --version",
5784
]}
5885
title={'Installation Commands'}
@@ -73,7 +100,7 @@ export default function LinuxDownloadSection({ platform, className }: LinuxDownl
73100
</p>
74101
</div>
75102
<a
76-
href="https://dl.rustfs.com/artifacts/rustfs/release/rustfs-linux-aarch64-musl-latest.zip"
103+
href={finalAarch64Url}
77104
target="_blank"
78105
rel="noopener noreferrer"
79106
className="inline-flex items-center space-x-2 px-4 py-2 bg-primary text-primary-foreground rounded-lg hover:bg-primary/90 transition-colors">
@@ -84,8 +111,8 @@ export default function LinuxDownloadSection({ platform, className }: LinuxDownl
84111

85112
<CodeBlock
86113
code={[
87-
"curl -O https://dl.rustfs.com/artifacts/rustfs/release/rustfs-linux-aarch64-musl-latest.zip",
88-
"unzip rustfs-linux-aarch64-musl-latest.zip",
114+
`curl -O ${finalAarch64Url}`,
115+
`unzip ${getFilenameFromUrl(finalAarch64Url, 'aarch64')}`,
89116
"./rustfs --version",
90117
]}
91118
title={'Installation Commands'}

app/download/components/platforms/macos-download-section.tsx

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,40 @@ import CodeBlock from "../code-block";
77
import Note from "../common/note";
88
import PlatformHeader from "../common/platform-header";
99
import { type PlatformInfoData } from "./platform-info";
10+
import { getDownloadUrlForPlatform, type GitHubRelease } from '@/lib/github';
1011

1112
interface MacOSDownloadSectionProps {
1213
platform: PlatformInfoData;
14+
release: GitHubRelease | null;
1315
className?: string;
1416
}
1517

16-
export default function MacOSDownloadSection({ platform, className }: MacOSDownloadSectionProps) {return (
18+
export default function MacOSDownloadSection({ platform, release, className }: MacOSDownloadSectionProps) {
19+
// Get download URLs from release assets or use fallback
20+
const aarch64Url = release
21+
? getDownloadUrlForPlatform(release, 'macos', 'aarch64')
22+
: null;
23+
24+
const x86_64Url = release
25+
? getDownloadUrlForPlatform(release, 'macos', 'x86_64')
26+
: null;
27+
28+
const fallbackAarch64Url = 'https://github.com/rustfs/rustfs/releases/latest';
29+
const fallbackX86_64Url = 'https://github.com/rustfs/rustfs/releases/latest';
30+
31+
const finalAarch64Url = aarch64Url || fallbackAarch64Url;
32+
const finalX86_64Url = x86_64Url || fallbackX86_64Url;
33+
34+
// Extract filename from URL for code block
35+
const getFilenameFromUrl = (url: string, arch: string) => {
36+
if (url.includes('github.com')) {
37+
return `rustfs-macos-${arch}.zip`;
38+
}
39+
const match = url.match(/([^\/]+\.zip)/);
40+
return match ? match[1] : `rustfs-macos-${arch}.zip`;
41+
};
42+
43+
return (
1744
<div className={cn("space-y-8", className)}>
1845
{/* Platform Header */}
1946
<PlatformHeader platform={platform} />
@@ -48,7 +75,7 @@ export default function MacOSDownloadSection({ platform, className }: MacOSDownl
4875
</p>
4976
</div>
5077
<a
51-
href="https://dl.rustfs.com/artifacts/rustfs/release/rustfs-macos-aarch64-latest.zip"
78+
href={finalAarch64Url}
5279
target="_blank"
5380
rel="noopener noreferrer"
5481
className="inline-flex items-center space-x-2 px-4 py-2 bg-primary text-primary-foreground rounded-lg hover:bg-primary/90 transition-colors">
@@ -59,8 +86,8 @@ export default function MacOSDownloadSection({ platform, className }: MacOSDownl
5986

6087
<CodeBlock
6188
code={[
62-
"curl --progress-bar -O https://dl.rustfs.com/artifacts/rustfs/release/rustfs-macos-aarch64-latest.zip",
63-
"unzip rustfs-macos-aarch64-latest.zip",
89+
`curl --progress-bar -O ${finalAarch64Url}`,
90+
`unzip ${getFilenameFromUrl(finalAarch64Url, 'aarch64')}`,
6491
"chmod +x rustfs",
6592
"./rustfs --version",
6693
]}
@@ -87,7 +114,7 @@ export default function MacOSDownloadSection({ platform, className }: MacOSDownl
87114
</p>
88115
</div>
89116
<a
90-
href="https://dl.rustfs.com/artifacts/rustfs/release/rustfs-macos-x86_64-latest.zip"
117+
href={finalX86_64Url}
91118
target="_blank"
92119
rel="noopener noreferrer"
93120
className="inline-flex items-center space-x-2 px-4 py-2 bg-primary text-primary-foreground rounded-lg hover:bg-primary/90 transition-colors">
@@ -98,8 +125,8 @@ export default function MacOSDownloadSection({ platform, className }: MacOSDownl
98125

99126
<CodeBlock
100127
code={[
101-
"curl --progress-bar -O https://dl.rustfs.com/artifacts/rustfs/release/rustfs-macos-x86_64-latest.zip",
102-
"unzip rustfs-macos-x86_64-latest.zip",
128+
`curl --progress-bar -O ${finalX86_64Url}`,
129+
`unzip ${getFilenameFromUrl(finalX86_64Url, 'x86_64')}`,
103130
"chmod +x rustfs",
104131
"./rustfs --version",
105132
]}

app/download/components/platforms/platform-factory.tsx

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,21 +5,23 @@ import LinuxDownloadSection from "./linux-download-section";
55
import MacOSDownloadSection from "./macos-download-section";
66
import { type PlatformInfoData } from "./platform-info";
77
import WindowsDownloadSection from "./windows-download-section";
8+
import { type GitHubRelease } from '@/lib/github';
89

910
interface PlatformFactoryProps {
1011
platform: PlatformInfoData;
12+
release: GitHubRelease | null;
1113
className?: string;
1214
}
1315

14-
export default function PlatformFactory({ platform, className }: PlatformFactoryProps) {switch (platform.id) {
16+
export default function PlatformFactory({ platform, release, className }: PlatformFactoryProps) {switch (platform.id) {
1517
case 'linux':
16-
return <LinuxDownloadSection platform={platform} className={className} />;
18+
return <LinuxDownloadSection platform={platform} release={release} className={className} />;
1719
case 'docker':
18-
return <DockerDownloadSection platform={platform} className={className} />;
20+
return <DockerDownloadSection platform={platform} release={release} className={className} />;
1921
case 'macos':
20-
return <MacOSDownloadSection platform={platform} className={className} />;
22+
return <MacOSDownloadSection platform={platform} release={release} className={className} />;
2123
case 'windows':
22-
return <WindowsDownloadSection platform={platform} className={className} />;
24+
return <WindowsDownloadSection platform={platform} release={release} className={className} />;
2325
default:
2426
// Fallback for unknown platforms
2527
return (

0 commit comments

Comments
 (0)