| ... | ... | @@ -1,7 +1,6 @@ |
| 1 | 1 | #!/usr/bin/env node |
| 2 | 2 | import * as NodeRuntime from "@effect/platform-node/NodeRuntime"; |
| 3 | 3 | import * as NodeServices from "@effect/platform-node/NodeServices"; |
| 4 | | import * as Data from "effect/Data"; |
| 5 | 4 | import * as Effect from "effect/Effect"; |
| 6 | 5 | import * as FileSystem from "effect/FileSystem"; |
| 7 | 6 | import * as Logger from "effect/Logger"; |
| ... | ... | @@ -20,6 +19,14 @@ import { fromJsonStringPretty } from "@t3tools/shared/schemaJson"; |
| 20 | 19 | import { fromYaml } from "@t3tools/shared/schemaYaml"; |
| 21 | 20 | import { resolveSpawnCommand } from "@t3tools/shared/shell"; |
| 22 | 21 | import serverPackageJson from "../package.json" with { type: "json" }; |
| 22 | import { |
| 23 | ServerCliBuildAssetMissingError, |
| 24 | ServerCliCommandExitError, |
| 25 | ServerCliDevelopmentIconSourceMissingError, |
| 26 | ServerCliDevelopmentIconTargetMissingError, |
| 27 | ServerCliPublishIconSourceMissingError, |
| 28 | ServerCliPublishIconTargetMissingError, |
| 29 | } from "./cliErrors.ts"; |
| 23 | 30 | |
| 24 | 31 | interface PackageJson { |
| 25 | 32 | name: string; |
| ... | ... | @@ -47,11 +54,6 @@ const WorkspaceConfig = Schema.Struct({ |
| 47 | 54 | type WorkspaceConfig = typeof WorkspaceConfig.Type; |
| 48 | 55 | const decodeWorkspaceConfig = Schema.decodeEffect(fromYaml(WorkspaceConfig)); |
| 49 | 56 | |
| 50 | | class CliError extends Data.TaggedError("CliError")<{ |
| 51 | | readonly message: string; |
| 52 | | readonly cause?: unknown; |
| 53 | | }> {} |
| 54 | | |
| 55 | 57 | const RepoRoot = Effect.service(Path.Path).pipe( |
| 56 | 58 | Effect.flatMap((path) => path.fromFileUrl(new URL("../../..", import.meta.url))), |
| 57 | 59 | ); |
| ... | ... | @@ -64,14 +66,17 @@ const readWorkspaceConfig = Effect.fn("readWorkspaceConfig")(function* () { |
| 64 | 66 | return yield* decodeWorkspaceConfig(workspaceYaml); |
| 65 | 67 | }); |
| 66 | 68 | |
| 67 | | const runCommand = Effect.fn("runCommand")(function* (command: ChildProcess.Command) { |
| 69 | const runCommand = Effect.fn("runCommand")(function* (command: ChildProcess.StandardCommand) { |
| 68 | 70 | const spawner = yield* ChildProcessSpawner.ChildProcessSpawner; |
| 69 | 71 | const child = yield* spawner.spawn(command); |
| 70 | 72 | const exitCode = yield* child.exitCode; |
| 71 | 73 | |
| 72 | 74 | if (exitCode !== 0) { |
| 73 | | return yield* new CliError({ |
| 74 | | message: `Command exited with non-zero exit code (${exitCode})`, |
| 75 | return yield* new ServerCliCommandExitError({ |
| 76 | command: command.command, |
| 77 | args: command.args, |
| 78 | cwd: command.options.cwd, |
| 79 | exitCode, |
| 75 | 80 | }); |
| 76 | 81 | } |
| 77 | 82 | }); |
| ... | ... | @@ -95,14 +100,10 @@ const applyPublishIconOverrides = Effect.fn("applyPublishIconOverrides")(functio |
| 95 | 100 | const backupPath = `${targetPath}.publish-bak`; |
| 96 | 101 | |
| 97 | 102 | if (!(yield* fs.exists(sourcePath))) { |
| 98 | | return yield* new CliError({ |
| 99 | | message: `Missing publish icon source: ${sourcePath}`, |
| 100 | | }); |
| 103 | return yield* new ServerCliPublishIconSourceMissingError({ sourcePath }); |
| 101 | 104 | } |
| 102 | 105 | if (!(yield* fs.exists(targetPath))) { |
| 103 | | return yield* new CliError({ |
| 104 | | message: `Missing publish icon target: ${targetPath}. Run the build subcommand first.`, |
| 105 | | }); |
| 106 | return yield* new ServerCliPublishIconTargetMissingError({ targetPath }); |
| 106 | 107 | } |
| 107 | 108 | |
| 108 | 109 | yield* fs.copyFile(targetPath, backupPath); |
| ... | ... | @@ -138,14 +139,10 @@ const applyDevelopmentIconOverrides = Effect.fn("applyDevelopmentIconOverrides") |
| 138 | 139 | const targetPath = path.join(serverDir, override.targetRelativePath); |
| 139 | 140 | |
| 140 | 141 | if (!(yield* fs.exists(sourcePath))) { |
| 141 | | return yield* new CliError({ |
| 142 | | message: `Missing development icon source: ${sourcePath}`, |
| 143 | | }); |
| 142 | return yield* new ServerCliDevelopmentIconSourceMissingError({ sourcePath }); |
| 144 | 143 | } |
| 145 | 144 | if (!(yield* fs.exists(targetPath))) { |
| 146 | | return yield* new CliError({ |
| 147 | | message: `Missing development icon target: ${targetPath}. Build web first.`, |
| 148 | | }); |
| 145 | return yield* new ServerCliDevelopmentIconTargetMissingError({ targetPath }); |
| 149 | 146 | } |
| 150 | 147 | |
| 151 | 148 | yield* fs.copyFile(sourcePath, targetPath); |
| ... | ... | @@ -245,9 +242,7 @@ const publishCmd = Command.make( |
| 245 | 242 | for (const relPath of ["dist/bin.mjs", "dist/client/index.html"]) { |
| 246 | 243 | const abs = path.join(serverDir, relPath); |
| 247 | 244 | if (!(yield* fs.exists(abs))) { |
| 248 | | return yield* new CliError({ |
| 249 | | message: `Missing build asset: ${abs}. Run the build subcommand first.`, |
| 250 | | }); |
| 245 | return yield* new ServerCliBuildAssetMissingError({ assetPath: abs }); |
| 251 | 246 | } |
| 252 | 247 | } |
| 253 | 248 | |