1#!/usr/bin/env node
2
3import * as NodeRuntime from "@effect/platform-node/NodeRuntime";
4import * as NodeServices from "@effect/platform-node/NodeServices";
5import * as Effect from "effect/Effect";
6import * as FileSystem from "effect/FileSystem";
7import * as Option from "effect/Option";
8import * as Path from "effect/Path";
9import { Argument, Command, Flag } from "effect/cli";
10import {
11 resolveWebAssetBrandForChannel,
12 resolveWebIconOverrides,
13 WEB_ASSET_CHANNELS,
14 type WebAssetBrand,
15} from "./lib/brand-assets.ts";
16
17const WEB_ASSET_BRANDS = [
18 "development",
19 "nightly",
20 "production",
21] as const satisfies ReadonlyArray<WebAssetBrand>;
22
23export const applyWebBrandAssets = Effect.fn("applyWebBrandAssets")(function* (
24 brand: WebAssetBrand,
25 targetDirectory: string,
26) {
27 const fs = yield* FileSystem.FileSystem;
28 const path = yield* Path.Path;
29 const repoRoot = yield* path.fromFileUrl(new URL("..", import.meta.url));
30
31 yield* Effect.forEach(
32 resolveWebIconOverrides(brand, path.resolve(repoRoot, targetDirectory)),
33 (override) =>
34 fs.copyFile(path.join(repoRoot, override.sourceRelativePath), override.targetRelativePath),
35 { concurrency: "unbounded" },
36 );
37});
38
39export const applyWebBrandAssetsCommand = Command.make(
40 "apply-web-brand-assets",
41 {
42 brand: Argument.Literals("brand", WEB_ASSET_BRANDS).pipe(
43 Argument.withDescription("Asset brand to copy into the hosted web output directory."),
44 Argument.optional,
45 ),
46 channel: Flag.Literals("channel", WEB_ASSET_CHANNELS).pipe(
47 Flag.withDescription("Hosted release channel to map to a web asset brand."),
48 Flag.optional,
49 ),
50 targetDirectory: Argument.String("target-directory").pipe(
51 Argument.withDescription("Output directory that contains the hosted web build assets."),
52 Argument.optional,
53 ),
54 },
55 ({ brand, channel, targetDirectory }) =>
56 applyWebBrandAssets(
57 Option.getOrElse(brand, () =>
58 Option.match(channel, {
59 onNone: () => "production" as const,
60 onSome: resolveWebAssetBrandForChannel,
61 }),
62 ),
63 Option.getOrElse(targetDirectory, () => "apps/web/dist"),
64 ),
65).pipe(Command.withDescription("Copy web brand assets into a built hosted web app."));
66
67if (import.meta.main) {
68 Command.run(applyWebBrandAssetsCommand, { version: "0.0.0" }).pipe(
69 Effect.provide(NodeServices.layer),
70 NodeRuntime.runMain,
71 );
72}