#!/usr/bin/env node import * as NodeRuntime from "@effect/platform-node/NodeRuntime";import * as NodeServices from "@effect/platform-node/NodeServices";import { Config, Console, Effect, FileSystem, Option, Path, Schema, SchemaGetter } from "effect";import { Argument, Command, Flag } from "effect/unstable/cli"; 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 PrettyJsonString = SchemaGetter.parseJson<string>().compose( SchemaGetter.stringifyJson({ space: 2 }),);const PackageJsonPrettyJson = Schema.fromJsonString(PackageJsonSchema).pipe( Schema.encode({ decode: PrettyJsonString, encode: PrettyJsonString, }),);const decodePackageJson = Schema.decodeUnknownEffect(PackageJsonPrettyJson);const encodePackageJson = Schema.encodeSync(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; } yield* fs.writeFileString(filePath, `${encodePackageJson({ ...packageJson, version })}\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, );}
#!/usr/bin/env node
import * as NodeRuntime from "@effect/platform-node/NodeRuntime";
import * as NodeServices from "@effect/platform-node/NodeServices";
import { Config, Console, Effect, FileSystem, Option, Path, Schema, SchemaGetter } from "effect";
import { Argument, Command, Flag } from "effect/unstable/cli";
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 PrettyJsonString = SchemaGetter.parseJson<string>().compose(
SchemaGetter.stringifyJson({ space: 2 }),
);
const PackageJsonPrettyJson = Schema.fromJsonString(PackageJsonSchema).pipe(
Schema.encode({
decode: PrettyJsonString,
encode: PrettyJsonString,
}),
);
const decodePackageJson = Schema.decodeUnknownEffect(PackageJsonPrettyJson);
const encodePackageJson = Schema.encodeSync(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;
}
yield* fs.writeFileString(filePath, `${encodePackageJson({ ...packageJson, version })}\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,
);
}