94 lines · 3.4 KB · TypeScript
RawDownload
#!/usr/bin/env node import * as NodeRuntime from "@effect/platform-node/NodeRuntime";import * as NodeServices from "@effect/platform-node/NodeServices";import * as Config from "effect/Config";import * as Console from "effect/Console";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 { fromJsonStringPretty } from "@t3tools/shared/schemaJson"; export const releasePackageFiles = [  "apps/server/package.json",  "apps/desktop/package.json",  "apps/web/package.json",  "packages/contracts/package.json",] as const; interface UpdateReleasePackageVersionsOptions {  readonly rootDir?: string | undefined;} const PackageJsonSchema = Schema.Record(Schema.String, Schema.Unknown);const PackageJsonPrettyJson = fromJsonStringPretty(PackageJsonSchema);const decodePackageJson = Schema.decodeUnknownEffect(PackageJsonPrettyJson);const encodePackageJson = Schema.encodeEffect(PackageJsonPrettyJson); export const updateReleasePackageVersions = Effect.fn("updateReleasePackageVersions")(function* (  version: string,  options: UpdateReleasePackageVersionsOptions = {},) {  const fs = yield* FileSystem.FileSystem;  const path = yield* Path.Path;  const rootDir = path.resolve(options.rootDir ?? process.cwd());  let changed = false;   for (const relativePath of releasePackageFiles) {    const filePath = path.join(rootDir, relativePath);    const packageJson = yield* fs.readFileString(filePath).pipe(Effect.flatMap(decodePackageJson));    if (packageJson.version === version) {      continue;    }     const packageJsonString = yield* encodePackageJson({ ...packageJson, version });    yield* fs.writeFileString(filePath, `${packageJsonString}\n`);    changed = true;  }   return { changed };}); const writeGithubOutput = Effect.fn("writeGithubOutput")(function* (changed: boolean) {  const fs = yield* FileSystem.FileSystem;  const githubOutputPath = yield* Config.nonEmptyString("GITHUB_OUTPUT");  yield* fs.writeFileString(githubOutputPath, `changed=${changed}\n`, { flag: "a" });}); export const updateReleasePackageVersionsCommand = Command.make(  "update-release-package-versions",  {    version: Argument.string("version").pipe(      Argument.withDescription("Release version to write into each releasable package.json."),    ),    root: Flag.string("root").pipe(      Flag.withDescription("Workspace root used to resolve the release package manifests."),      Flag.optional,    ),    githubOutput: Flag.boolean("github-output").pipe(      Flag.withDescription("Append changed=<boolean> to GITHUB_OUTPUT."),      Flag.withDefault(false),    ),  },  ({ version, root, githubOutput }) =>    updateReleasePackageVersions(version, {      rootDir: Option.getOrUndefined(root),    }).pipe(      Effect.tap(({ changed }) =>        changed          ? Effect.void          : Console.log("All package.json versions already match release version."),      ),      Effect.tap(({ changed }) => (githubOutput ? writeGithubOutput(changed) : Effect.void)),    ),).pipe(Command.withDescription("Update release package versions across the workspace.")); if (import.meta.main) {  Command.run(updateReleasePackageVersionsCommand, { version: "0.0.0" }).pipe(    Effect.provide(NodeServices.layer),    NodeRuntime.runMain,  );}