1#!/usr/bin/env nix-shell
2/*
3#!nix-shell -i node --pure --packages cacert nodejs_latest
4*/
5import * as assert from "node:assert/strict";
6import * as fsPromises from "node:fs/promises";
7import * as path from "node:path";
8import * as process from "node:process";
9
10const __dirname = import.meta.dirname;
11const __filename = import.meta.filename;
12
13interface LatestInfo {
14 readonly url: string;
15 readonly sha256hash: string;
16 readonly windsurfVersion: string;
17 readonly productVersion: string;
18}
19
20const platforms = ["aarch64-darwin", "x86_64-darwin", "x86_64-linux"] as const;
21type Platform = (typeof platforms)[number];
22type InfoMap = Record<
23 Platform,
24 {
25 readonly version: string;
26 readonly vscodeVersion: string;
27 readonly url: string;
28 readonly sha256: string;
29 }
30>;
31
32async function getInfo(targetSystem: "darwin-arm64" | "darwin-x64" | "linux-x64") {
33 const url =
34 `https://windsurf-stable.codeium.com/api/update/${targetSystem}/stable/latest` as const;
35
36 const response = await fetch(url);
37 assert.ok(response.ok, `Failed to fetch ${url}`);
38
39 const latestInfo: LatestInfo = JSON.parse(await response.text());
40 assert.ok(latestInfo.sha256hash, "sha256hash is required");
41 assert.ok(latestInfo.url, "url is required");
42 assert.ok(latestInfo.windsurfVersion, "windsurfVersion is required");
43 assert.ok(latestInfo.productVersion, "productVersion is required");
44 return {
45 version: latestInfo.windsurfVersion,
46 vscodeVersion: latestInfo.productVersion,
47 url: latestInfo.url,
48 sha256: latestInfo.sha256hash,
49 };
50}
51
52async function main() {
53 const filePath = path.join(__dirname, "../info.json");
54 const oldInfo = JSON.parse(
55 await fsPromises.readFile(filePath, { encoding: "utf-8" }),
56 );
57
58 const info: InfoMap = {
59 "aarch64-darwin": await getInfo("darwin-arm64"),
60 "x86_64-darwin": await getInfo("darwin-x64"),
61 "x86_64-linux": await getInfo("linux-x64"),
62 };
63 if (JSON.stringify(oldInfo) === JSON.stringify(info)) {
64 console.log("[update] No updates found");
65 return;
66 }
67 for (const platform of platforms) {
68 console.log(
69 `[update] Updating Windsurf ${platform} ${oldInfo[platform].version} -> ${info[platform].version}`,
70 );
71 }
72 await fsPromises.writeFile(
73 filePath,
74 JSON.stringify(info, null, 2) + "\n",
75 "utf-8",
76 );
77 console.log("[update] Updating Windsurf complete");
78}
79
80if (process.argv[1] === __filename) {
81 main();
82}