#!/usr/bin/env node import * as NodeRuntime from "@effect/platform-node/NodeRuntime"; import * as NodeServices from "@effect/platform-node/NodeServices"; import * as Effect from "effect/Effect"; import * as FileSystem from "effect/FileSystem"; import * as Option from "effect/Option"; import * as Path from "effect/Path"; import * as Schema from "effect/Schema"; import { Argument, Command, Flag } from "effect/unstable/cli"; import { mergeUpdateManifests, parseUpdateManifest, serializeUpdateManifest, type UpdateManifest, } from "./lib/update-manifest.ts"; const UpdateManifestPlatform = Schema.Literals(["mac", "win"]); export type UpdateManifestPlatform = typeof UpdateManifestPlatform.Type; function getPlatformLabel(platform: UpdateManifestPlatform): string { return platform === "mac" ? "macOS" : "Windows"; } export function parsePlatformUpdateManifest( platform: UpdateManifestPlatform, raw: string, sourcePath: string, ): UpdateManifest { return parseUpdateManifest(raw, sourcePath, getPlatformLabel(platform)); } export function mergePlatformUpdateManifests( platform: UpdateManifestPlatform, primary: UpdateManifest, secondary: UpdateManifest, ): UpdateManifest { return mergeUpdateManifests(primary, secondary, getPlatformLabel(platform)); } export function serializePlatformUpdateManifest( platform: UpdateManifestPlatform, manifest: UpdateManifest, ): string { return serializeUpdateManifest(manifest, { platformLabel: getPlatformLabel(platform), }); } export const mergeUpdateManifestFiles = Effect.fn("mergeUpdateManifestFiles")(function* ( platform: UpdateManifestPlatform, primaryPathArg: string, secondaryPathArg: string, outputPathArg: string | undefined, ) { const fs = yield* FileSystem.FileSystem; const path = yield* Path.Path; const primaryPath = path.resolve(primaryPathArg); const secondaryPath = path.resolve(secondaryPathArg); const outputPath = path.resolve(outputPathArg ?? primaryPathArg); const primaryManifest = parsePlatformUpdateManifest( platform, yield* fs.readFileString(primaryPath), primaryPath, ); const secondaryManifest = parsePlatformUpdateManifest( platform, yield* fs.readFileString(secondaryPath), secondaryPath, ); const merged = mergePlatformUpdateManifests(platform, primaryManifest, secondaryManifest); yield* fs.writeFileString(outputPath, serializePlatformUpdateManifest(platform, merged)); }); export const mergeUpdateManifestsCommand = Command.make( "merge-update-manifests", { platform: Flag.choice("platform", UpdateManifestPlatform.literals).pipe( Flag.withDescription("Update manifest platform."), ), primaryPath: Argument.string("primary-path").pipe( Argument.withDescription("Primary update manifest path. Defaults to the output path."), ), secondaryPath: Argument.string("secondary-path").pipe( Argument.withDescription( "Secondary update manifest path to merge into the primary manifest.", ), ), outputPath: Argument.string("output-path").pipe( Argument.withDescription("Optional output path for the merged manifest."), Argument.optional, ), }, ({ platform, primaryPath, secondaryPath, outputPath }) => mergeUpdateManifestFiles( platform, primaryPath, secondaryPath, Option.getOrUndefined(outputPath), ), ).pipe(Command.withDescription("Merge two Electron updater manifests into a multi-arch manifest.")); if (import.meta.main) { Command.run(mergeUpdateManifestsCommand, { version: "0.0.0" }).pipe( Effect.provide(NodeServices.layer), NodeRuntime.runMain, ); }