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, targetDirectory),
33 (override) =>
34 fs.copyFile(
35 path.join(repoRoot, override.sourceRelativePath),
36 path.join(repoRoot, override.targetRelativePath),
37 ),
38 { concurrency: "unbounded" },
39 );
40});
41
42export const applyWebBrandAssetsCommand = Command.make(
43 "apply-web-brand-assets",
44 {
45 brand: Argument.Literals("brand", WEB_ASSET_BRANDS).pipe(
46 Argument.withDescription("Asset brand to copy into the hosted web output directory."),
47 Argument.optional,
48 ),
49 channel: Flag.Literals("channel", WEB_ASSET_CHANNELS).pipe(
50 Flag.withDescription("Hosted release channel to map to a web asset brand."),
51 Flag.optional,
52 ),
53 targetDirectory: Argument.String("target-directory").pipe(
54 Argument.withDescription("Output directory that contains the hosted web build assets."),
55 Argument.optional,
56 ),
57 },
58 ({ brand, channel, targetDirectory }) =>
59 applyWebBrandAssets(
60 Option.getOrElse(brand, () =>
61 Option.match(channel, {
62 onNone: () => "production" as const,
63 onSome: resolveWebAssetBrandForChannel,
64 }),
65 ),
66 Option.getOrElse(targetDirectory, () => "apps/web/dist"),
67 ),
68).pipe(Command.withDescription("Copy web brand assets into a built hosted web app."));
69
70if (import.meta.main) {
71 Command.run(applyWebBrandAssetsCommand, { version: "0.0.0" }).pipe(
72 Effect.provide(NodeServices.layer),
73 NodeRuntime.runMain,
74 );
75}