1import * as NodeServices from "@effect/platform-node/NodeServices";
2import { assert, describe, it } from "@effect/vitest";
3import * as Effect from "effect/Effect";
4import * as FileSystem from "effect/FileSystem";
5import * as Path from "effect/Path";
6import { Command } from "effect/cli";
7
8import {
9 mergePlatformUpdateManifests,
10 mergeUpdateManifestsCommand,
11 parsePlatformUpdateManifest,
12 serializePlatformUpdateManifest,
13} from "./merge-update-manifests.ts";
14
15const runCli = Command.runWith(mergeUpdateManifestsCommand, { version: "0.0.0" });
16
17describe("merge-update-manifests", () => {
18 it("merges arm64 and x64 macOS update manifests into one multi-arch manifest", () => {
19 const arm64 = parsePlatformUpdateManifest(
20 "mac",
21 `version: 0.0.4
22files:
23 - url: T3-Code-0.0.4-arm64.zip
24 sha512: arm64zip
25 size: 125621344
26 - url: T3-Code-0.0.4-arm64.dmg
27 sha512: arm64dmg
28 size: 131754935
29path: T3-Code-0.0.4-arm64.zip
30sha512: arm64zip
31releaseDate: '2026-03-07T10:32:14.587Z'
32`,
33 "latest-mac.yml",
34 );
35
36 const x64 = parsePlatformUpdateManifest(
37 "mac",
38 `version: 0.0.4
39files:
40 - url: T3-Code-0.0.4-x64.zip
41 sha512: x64zip
42 size: 132000112
43 - url: T3-Code-0.0.4-x64.dmg
44 sha512: x64dmg
45 size: 138148807
46path: T3-Code-0.0.4-x64.zip
47sha512: x64zip
48releaseDate: '2026-03-07T10:36:07.540Z'
49`,
50 "latest-mac-x64.yml",
51 );
52
53 const merged = mergePlatformUpdateManifests("mac", arm64, x64);
54
55 assert.equal(merged.version, "0.0.4");
56 assert.equal(merged.releaseDate, "2026-03-07T10:36:07.540Z");
57 assert.deepStrictEqual(
58 merged.files.map((file) => file.url),
59 [
60 "T3-Code-0.0.4-arm64.zip",
61 "T3-Code-0.0.4-arm64.dmg",
62 "T3-Code-0.0.4-x64.zip",
63 "T3-Code-0.0.4-x64.dmg",
64 ],
65 );
66
67 const serialized = serializePlatformUpdateManifest("mac", merged);
68 assert.ok(!serialized.includes("path:"));
69 assert.equal((serialized.match(/- url:/g) ?? []).length, 4);
70 });
71
72 it("rejects mismatched manifest versions", () => {
73 const primary = parsePlatformUpdateManifest(
74 "win",
75 `version: 0.0.4
76files:
77 - url: T3-Code-0.0.4-arm64.exe
78 sha512: arm64exe
79 size: 1
80releaseDate: '2026-03-07T10:32:14.587Z'
81`,
82 "latest-win-arm64.yml",
83 );
84
85 const secondary = parsePlatformUpdateManifest(
86 "win",
87 `version: 0.0.5
88files:
89 - url: T3-Code-0.0.5-x64.exe
90 sha512: x64exe
91 size: 1
92releaseDate: '2026-03-07T10:36:07.540Z'
93`,
94 "latest-win-x64.yml",
95 );
96
97 assert.throws(
98 () => mergePlatformUpdateManifests("win", primary, secondary),
99 /different versions/,
100 );
101 });
102
103 it("preserves quoted scalars as strings", () => {
104 const manifest = parsePlatformUpdateManifest(
105 "mac",
106 `version: '1.0'
107files:
108 - url: T3-Code-1.0-x64.zip
109 sha512: zipsha
110 size: 1
111releaseName: 'true'
112minimumSystemVersion: '13.0'
113stagingPercentage: 50
114releaseDate: '2026-03-07T10:36:07.540Z'
115`,
116 "latest-mac.yml",
117 );
118
119 assert.equal(manifest.version, "1.0");
120 assert.equal(manifest.extras.releaseName, "true");
121 assert.equal(manifest.extras.minimumSystemVersion, "13.0");
122 assert.equal(manifest.extras.stagingPercentage, 50);
123 });
124
125 it("round-trips numeric-looking versions as strings", () => {
126 const original = parsePlatformUpdateManifest(
127 "win",
128 `version: '1.0'
129files:
130 - url: T3-Code-1.0-x64.exe
131 sha512: exesha
132 size: 1
133releaseDate: '2026-03-07T10:36:07.540Z'
134`,
135 "latest-win-x64.yml",
136 );
137
138 const serialized = serializePlatformUpdateManifest("win", original);
139 assert.ok(serialized.includes("version: '1.0'"));
140
141 const reparsed = parsePlatformUpdateManifest("win", serialized, "latest-win-x64.yml");
142 assert.equal(reparsed.version, "1.0");
143 });
144});
145
146it.layer(NodeServices.layer)("merge-update-manifests cli", (it) => {
147 const arm64MacManifest = `version: 0.0.4
148files:
149 - url: T3-Code-0.0.4-arm64.zip
150 sha512: arm64zip
151 size: 125621344
152 - url: T3-Code-0.0.4-arm64.dmg
153 sha512: arm64dmg
154 size: 131754935
155path: T3-Code-0.0.4-arm64.zip
156sha512: arm64zip
157releaseDate: '2026-03-07T10:32:14.587Z'
158`;
159
160 const x64MacManifest = `version: 0.0.4
161files:
162 - url: T3-Code-0.0.4-x64.zip
163 sha512: x64zip
164 size: 132000112
165 - url: T3-Code-0.0.4-x64.dmg
166 sha512: x64dmg
167 size: 138148807
168path: T3-Code-0.0.4-x64.zip
169sha512: x64zip
170releaseDate: '2026-03-07T10:36:07.540Z'
171`;
172
173 it.effect("writes the merged manifest back to the primary path by default", () =>
174 Effect.gen(function* () {
175 const fs = yield* FileSystem.FileSystem;
176 const path = yield* Path.Path;
177 const baseDir = yield* fs.makeTempDirectoryScoped({
178 prefix: "merge-update-manifests-cli-",
179 });
180 const primaryPath = path.join(baseDir, "latest-mac.yml");
181 const secondaryPath = path.join(baseDir, "latest-mac-x64.yml");
182
183 yield* fs.writeFileString(primaryPath, arm64MacManifest);
184 yield* fs.writeFileString(secondaryPath, x64MacManifest);
185
186 yield* runCli(["--platform", "mac", primaryPath, secondaryPath]);
187
188 const merged = yield* fs.readFileString(primaryPath);
189 assert.ok(merged.includes("T3-Code-0.0.4-arm64.zip"));
190 assert.ok(merged.includes("T3-Code-0.0.4-x64.zip"));
191 assert.ok(!merged.includes("path:"));
192 }),
193 );
194});