@shivaedev/changesets 0.0.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/LICENSE +21 -0
  3. package/README.md +68 -1
  4. package/dist/applyRelease.d.ts +16 -0
  5. package/dist/applyRelease.d.ts.map +1 -0
  6. package/dist/applyRelease.js +55 -0
  7. package/dist/applyRelease.js.map +1 -0
  8. package/dist/check.d.ts +6 -0
  9. package/dist/check.d.ts.map +1 -0
  10. package/dist/check.js +69 -0
  11. package/dist/check.js.map +1 -0
  12. package/dist/cli.d.ts +3 -0
  13. package/dist/cli.d.ts.map +1 -0
  14. package/dist/cli.js +29 -0
  15. package/dist/cli.js.map +1 -0
  16. package/dist/collectChangelog.d.ts +3 -0
  17. package/dist/collectChangelog.d.ts.map +1 -0
  18. package/dist/collectChangelog.js +17 -0
  19. package/dist/collectChangelog.js.map +1 -0
  20. package/dist/config.d.ts +14 -0
  21. package/dist/config.d.ts.map +1 -0
  22. package/dist/config.js +4 -0
  23. package/dist/config.js.map +1 -0
  24. package/dist/error.d.ts +13 -0
  25. package/dist/error.d.ts.map +1 -0
  26. package/dist/error.js +15 -0
  27. package/dist/error.js.map +1 -0
  28. package/dist/model.d.ts +68 -0
  29. package/dist/model.d.ts.map +1 -0
  30. package/dist/model.js +22 -0
  31. package/dist/model.js.map +1 -0
  32. package/dist/parser.d.ts +8 -0
  33. package/dist/parser.d.ts.map +1 -0
  34. package/dist/parser.js +30 -0
  35. package/dist/parser.js.map +1 -0
  36. package/dist/planner.d.ts +20 -0
  37. package/dist/planner.d.ts.map +1 -0
  38. package/dist/planner.js +71 -0
  39. package/dist/planner.js.map +1 -0
  40. package/dist/readHistory.d.ts +27 -0
  41. package/dist/readHistory.d.ts.map +1 -0
  42. package/dist/readHistory.js +40 -0
  43. package/dist/readHistory.js.map +1 -0
  44. package/dist/sections.d.ts +9 -0
  45. package/dist/sections.d.ts.map +1 -0
  46. package/dist/sections.js +36 -0
  47. package/dist/sections.js.map +1 -0
  48. package/dist/workspace.d.ts +37 -0
  49. package/dist/workspace.d.ts.map +1 -0
  50. package/dist/workspace.js +87 -0
  51. package/dist/workspace.js.map +1 -0
  52. package/package.json +70 -4
  53. package/src/applyRelease.ts +64 -0
  54. package/src/check.ts +106 -0
  55. package/src/cli.ts +36 -0
  56. package/src/collectChangelog.ts +27 -0
  57. package/src/config.ts +16 -0
  58. package/src/error.ts +20 -0
  59. package/src/model.ts +38 -0
  60. package/src/parser.ts +33 -0
  61. package/src/planner.ts +73 -0
  62. package/src/readHistory.ts +41 -0
  63. package/src/sections.ts +40 -0
  64. package/src/workspace.ts +109 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"planner.d.ts","sourceRoot":"","sources":["../src/planner.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAChC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD,OAAO,KAAK,EAAQ,eAAe,EAAE,WAAW,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAK9F,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,eAAe,GAAG,SAAS,MAAM,EAAE,CAElF;AA+BD,wBAAgB,WAAW,CAAC,QAAQ,EAAE,SAAS,gBAAgB,EAAE,EAAE,OAAO,EAAE,SAAS,MAAM,EAAE,GAAG,WAAW,CAsB1G;AACD,wBAAgB,aAAa,CAAC,IAAI,EAAE,WAAW,GAAG,MAAM,CAIvD;AACD,eAAO,MAAM,WAAW;;;;;;;;;;;;6HAGtB,CAAC"}
@@ -0,0 +1,71 @@
1
+ import { Effect } from "effect";
2
+ import { attempt, requireThat } from "#error.ts";
3
+ import { parseChangeset } from "#parser.ts";
4
+ import { readWorkspace } from "#workspace.ts";
5
+ const rank = { major: 2, minor: 1, patch: 0 };
6
+ export function publishedDependencies(manifest) {
7
+ return Object.keys({ ...manifest.dependencies, ...manifest.optionalDependencies, ...manifest.peerDependencies });
8
+ }
9
+ function nextVersion(name, version, bump) {
10
+ const match = /^(?<major>0|[1-9]\d*)\.(?<minor>0|[1-9]\d*)\.(?<patch>0|[1-9]\d*)$/u.exec(version);
11
+ requireThat(match !== null, `${name}: use a stable major.minor.patch version before planning a release; found ${version}.`);
12
+ const major = Number(match?.groups?.major);
13
+ const minor = Number(match?.groups?.minor);
14
+ const patch = Number(match?.groups?.patch);
15
+ requireThat(major !== 0 || bump !== "major", `${name}: major is not allowed on a 0.x package; use minor for breaking changes.`);
16
+ if (bump === "major") {
17
+ return `${major + 1}.0.0`;
18
+ }
19
+ return bump === "minor" ? `${major}.${minor + 1}.0` : `${major}.${minor}.${patch + 1}`;
20
+ }
21
+ function requestedBumps(packages, sources) {
22
+ const bumps = new Map();
23
+ for (const source of sources) {
24
+ for (const [name, bump] of Object.entries(parseChangeset(source).packages)) {
25
+ const pkg = packages.find((candidate) => candidate.manifest.name === name);
26
+ requireThat(pkg !== undefined, `${source.name}: unknown package ${name}; fix the name or include its directory in config.packages.`);
27
+ requireThat(!pkg?.manifest.private, `${source.name}: ${name} is private; remove it from release frontmatter.`);
28
+ if (pkg !== undefined) {
29
+ nextVersion(name, pkg.manifest.version, bump);
30
+ }
31
+ const previous = bumps.get(name);
32
+ if (previous === undefined || rank[bump] > rank[previous]) {
33
+ bumps.set(name, bump);
34
+ }
35
+ }
36
+ }
37
+ return bumps;
38
+ }
39
+ export function computePlan(packages, sources) {
40
+ const bumps = requestedBumps(packages, sources);
41
+ let changed = true;
42
+ while (changed) {
43
+ changed = false;
44
+ for (const { manifest } of packages) {
45
+ if (!(manifest.private || bumps.has(manifest.name)) && publishedDependencies(manifest).some((name) => bumps.has(name))) {
46
+ bumps.set(manifest.name, "patch");
47
+ changed = true;
48
+ }
49
+ }
50
+ }
51
+ const releases = [...bumps]
52
+ .sort(([left], [right]) => left.localeCompare(right))
53
+ .map(([name, bump]) => {
54
+ const pkg = packages.find((candidate) => candidate.manifest.name === name);
55
+ if (pkg === undefined) {
56
+ throw new Error(`Package ${name} disappeared while planning.`);
57
+ }
58
+ return { bump, directory: pkg.directory, from: pkg.manifest.version, name, to: nextVersion(name, pkg.manifest.version, bump) };
59
+ });
60
+ return { changesets: [...sources].sort((left, right) => left.name.localeCompare(right.name)), releases };
61
+ }
62
+ export function summarizePlan(plan) {
63
+ return plan.releases.length === 0
64
+ ? "No pending releases."
65
+ : plan.releases.map((release) => `${release.name}: ${release.from} -> ${release.to} (${release.bump})`).join("\n");
66
+ }
67
+ export const planRelease = Effect.fn("Changesets.planRelease")(function* (root, config = {}) {
68
+ const workspace = yield* readWorkspace(root, config);
69
+ return yield* attempt(() => computePlan(workspace.packages, workspace.changesets));
70
+ });
71
+ //# sourceMappingURL=planner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"planner.js","sourceRoot":"","sources":["../src/planner.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ import { Effect } from "effect";
2
+ import type { ChangesetConfig } from "#config.ts";
3
+ import { ChangesetError } from "#error.ts";
4
+ export declare const readHistory: (root: string, config: ChangesetConfig, reference?: string | undefined) => Effect.Effect<{
5
+ changesets: {
6
+ name: string;
7
+ text: string;
8
+ }[];
9
+ packages: import("#model.ts").WorkspacePackage[];
10
+ release: {
11
+ readonly date: string;
12
+ readonly plan: {
13
+ readonly changesets: readonly {
14
+ readonly name: string;
15
+ readonly text: string;
16
+ }[];
17
+ readonly releases: readonly {
18
+ readonly bump: "major" | "minor" | "patch";
19
+ readonly directory: string;
20
+ readonly from: string;
21
+ readonly name: string;
22
+ readonly to: string;
23
+ }[];
24
+ };
25
+ } | undefined;
26
+ }, ChangesetError, never>;
27
+ //# sourceMappingURL=readHistory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"readHistory.d.ts","sourceRoot":"","sources":["../src/readHistory.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,MAAM,EAAU,MAAM,QAAQ,CAAC;AACxC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAClD,OAAO,EAAW,cAAc,EAAE,MAAM,WAAW,CAAC;AAOpD,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;yBA4BtB,CAAC"}
@@ -0,0 +1,40 @@
1
+ import { execFileSync, spawnSync } from "node:child_process";
2
+ import { existsSync, readFileSync } from "node:fs";
3
+ import { posix } from "node:path";
4
+ import { Effect, Schema } from "effect";
5
+ import { attempt, ChangesetError } from "#error.ts";
6
+ import { ReleaseManifest } from "#model.ts";
7
+ import { decodePackage, isChangeset, packagePatterns } from "#workspace.ts";
8
+ function git(root, args) {
9
+ return execFileSync("git", ["-C", root, ...args], { encoding: "utf8", stdio: ["ignore", "pipe", "pipe"] });
10
+ }
11
+ export const readHistory = Effect.fn("Changesets.readHistory")(function* (root, config, reference) {
12
+ const base = yield* attempt(() => {
13
+ const mergeHead = git(root, ["rev-parse", "--path-format=absolute", "--git-path", "MERGE_HEAD"]).trim();
14
+ const heads = ["HEAD", ...(existsSync(mergeHead) ? readFileSync(mergeHead, "utf8").trim().split("\n") : [])];
15
+ for (const candidate of reference === undefined ? ["origin/main", "main"] : [reference]) {
16
+ const result = spawnSync("git", ["-C", root, "merge-base", candidate, ...heads], { encoding: "utf8" });
17
+ if (result.status === 0) {
18
+ return result.stdout.trim();
19
+ }
20
+ }
21
+ throw new ChangesetError({
22
+ message: `Cannot resolve changeset base ${reference ?? "origin/main or main"}; run git fetch origin main or pass an existing base-ref with full history.`,
23
+ });
24
+ });
25
+ return yield* attempt(() => {
26
+ const paths = git(root, ["ls-tree", "-r", "--name-only", base]).trim().split("\n");
27
+ function read(path, fallback) {
28
+ return paths.includes(path) ? git(root, ["show", `${base}:${path}`]) : fallback;
29
+ }
30
+ const packages = paths
31
+ .filter((path) => path.endsWith("/package.json") && packagePatterns(config).some((pattern) => posix.matchesGlob(posix.dirname(path), pattern)))
32
+ .map((path) => decodePackage(posix.dirname(path), read(path, ""), read(`${posix.dirname(path)}/CHANGELOG.md`, "# Changelog\n")));
33
+ const changesets = paths
34
+ .filter((path) => path.startsWith(".changeset/") && isChangeset(path.slice(".changeset/".length)))
35
+ .map((path) => ({ name: path.slice(".changeset/".length), text: read(path, "") }));
36
+ const text = read(".changeset/release.json", "");
37
+ return { changesets, packages, release: text === "" ? undefined : Schema.decodeUnknownSync(Schema.fromJsonString(ReleaseManifest))(text) };
38
+ });
39
+ });
40
+ //# sourceMappingURL=readHistory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"readHistory.js","sourceRoot":"","sources":["../src/readHistory.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ export declare const sections: readonly ["Added", "Changed", "Fixed", "Breaking"];
2
+ export type Section = (typeof sections)[number];
3
+ export interface Entry {
4
+ readonly section: Section;
5
+ readonly text: string;
6
+ }
7
+ export declare function parseBody(name: string, body: string): readonly Entry[];
8
+ export declare function renderEntries(entries: readonly Entry[]): string;
9
+ //# sourceMappingURL=sections.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sections.d.ts","sourceRoot":"","sources":["../src/sections.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,QAAQ,YAAI,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,UAAU,CAAU,CAAC;AAC3E,MAAM,MAAM,OAAO,GAAG,CAAC,OAAO,QAAQ,CAAC,CAAC,MAAM,CAAC,CAAC;AAChD,MAAM,WAAW,KAAK;IACrB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACtB;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,SAAS,KAAK,EAAE,CAqBtE;AAED,wBAAgB,aAAa,CAAC,OAAO,EAAE,SAAS,KAAK,EAAE,GAAG,MAAM,CAO/D"}
@@ -0,0 +1,36 @@
1
+ import { requireThat } from "#error.ts";
2
+ export const sections = ["Added", "Changed", "Fixed", "Breaking"];
3
+ export function parseBody(name, body) {
4
+ const entries = [];
5
+ let section;
6
+ for (const line of body.split("\n")) {
7
+ if (line.startsWith("### ")) {
8
+ section = sections.find((value) => line === `### ${value}`);
9
+ requireThat(section !== undefined, `${name}: use ### Added, ### Changed, ### Fixed or ### Breaking.`);
10
+ }
11
+ else if (line.startsWith("- ") && section !== undefined) {
12
+ requireThat(line.slice(2).trim() !== "", `${name}: write text after '- '.`);
13
+ entries.push({ section, text: line });
14
+ }
15
+ else if (line.trim() !== "") {
16
+ const previous = entries.at(-1);
17
+ if (previous === undefined || previous.section !== section || !/^\s+\S/u.test(line)) {
18
+ requireThat(false, `${name}: start each entry with '- ' under a ### section heading.`);
19
+ }
20
+ else {
21
+ entries[entries.length - 1] = { ...previous, text: `${previous.text}\n${line}` };
22
+ }
23
+ }
24
+ }
25
+ requireThat(entries.length > 0, `${name}: add at least one release-note entry under a ### section heading.`);
26
+ return entries;
27
+ }
28
+ export function renderEntries(entries) {
29
+ return sections
30
+ .flatMap((section) => {
31
+ const selected = entries.filter((entry) => entry.section === section);
32
+ return selected.length === 0 ? [] : [`### ${section}\n\n${selected.map((entry) => entry.text).join("\n")}\n`];
33
+ })
34
+ .join("\n");
35
+ }
36
+ //# sourceMappingURL=sections.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sections.js","sourceRoot":"","sources":["../src/sections.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAExC,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,UAAU,CAAU,CAAC;AAO3E,MAAM,UAAU,SAAS,CAAC,IAAY,EAAE,IAAY;IACnD,MAAM,OAAO,GAAY,EAAE,CAAC;IAC5B,IAAI,OAA4B,CAAC;IACjC,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QACrC,IAAI,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;YAC7B,OAAO,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,KAAK,OAAO,KAAK,EAAE,CAAC,CAAC;YAC5D,WAAW,CAAC,OAAO,KAAK,SAAS,EAAE,GAAG,IAAI,0DAA0D,CAAC,CAAC;QACvG,CAAC;aAAM,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;YAC3D,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,GAAG,IAAI,0BAA0B,CAAC,CAAC;YAC5E,OAAO,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;QACvC,CAAC;aAAM,IAAI,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;YAC/B,MAAM,QAAQ,GAAG,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;YAChC,IAAI,QAAQ,KAAK,SAAS,IAAI,QAAQ,CAAC,OAAO,KAAK,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;gBACrF,WAAW,CAAC,KAAK,EAAE,GAAG,IAAI,2DAA2D,CAAC,CAAC;YACxF,CAAC;iBAAM,CAAC;gBACP,OAAO,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,EAAE,GAAG,QAAQ,EAAE,IAAI,EAAE,GAAG,QAAQ,CAAC,IAAI,KAAK,IAAI,EAAE,EAAE,CAAC;YAClF,CAAC;QACF,CAAC;IACF,CAAC;IACD,WAAW,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,GAAG,IAAI,oEAAoE,CAAC,CAAC;IAC7G,OAAO,OAAO,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,OAAyB;IACtD,OAAO,QAAQ;SACb,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QACpB,MAAM,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,KAAK,OAAO,CAAC,CAAC;QACtE,OAAO,QAAQ,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO,OAAO,OAAO,QAAQ,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC/G,CAAC,CAAC;SACD,IAAI,CAAC,IAAI,CAAC,CAAC;AACd,CAAC"}
@@ -0,0 +1,37 @@
1
+ import { Effect, FileSystem } from "effect";
2
+ import type { ChangesetConfig } from "#config.ts";
3
+ import { ChangesetError } from "#error.ts";
4
+ import { type WorkspacePackage } from "#model.ts";
5
+ export declare function packagePatterns(config: ChangesetConfig): readonly string[];
6
+ export declare function decodePackage(directory: string, text: string, changelog: string): WorkspacePackage;
7
+ export declare const readOptional: (path: string, fallback: string) => Effect.Effect<string, import("effect/PlatformError").PlatformError, FileSystem.FileSystem>;
8
+ export declare const loadConfig: (root: string) => Effect.Effect<ChangesetConfig, ChangesetError | import("effect/PlatformError").PlatformError, FileSystem.FileSystem>;
9
+ export declare const readChangesets: (root: string) => Effect.Effect<{
10
+ readonly name: string;
11
+ readonly text: string;
12
+ }[], import("effect/PlatformError").PlatformError, FileSystem.FileSystem>;
13
+ export declare function isChangeset(name: string): boolean;
14
+ export declare const readWorkspace: (root: string, config: ChangesetConfig) => Effect.Effect<{
15
+ changesets: {
16
+ readonly name: string;
17
+ readonly text: string;
18
+ }[];
19
+ packages: WorkspacePackage[];
20
+ release: {
21
+ readonly date: string;
22
+ readonly plan: {
23
+ readonly changesets: readonly {
24
+ readonly name: string;
25
+ readonly text: string;
26
+ }[];
27
+ readonly releases: readonly {
28
+ readonly bump: "major" | "minor" | "patch";
29
+ readonly directory: string;
30
+ readonly from: string;
31
+ readonly name: string;
32
+ readonly to: string;
33
+ }[];
34
+ };
35
+ } | undefined;
36
+ }, ChangesetError | import("effect/PlatformError").PlatformError, FileSystem.FileSystem>;
37
+ //# sourceMappingURL=workspace.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspace.d.ts","sourceRoot":"","sources":["../src/workspace.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,EAAE,UAAU,EAAU,MAAM,QAAQ,CAAC;AACpD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAClD,OAAO,EAAW,cAAc,EAAe,MAAM,WAAW,CAAC;AACjE,OAAO,EAAiD,KAAK,gBAAgB,EAAE,MAAM,WAAW,CAAC;AACjG,wBAAgB,eAAe,CAAC,MAAM,EAAE,eAAe,GAAG,SAAS,MAAM,EAAE,CAE1E;AAED,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,gBAAgB,CAOlG;AACD,eAAO,MAAM,YAAY,gIAGvB,CAAC;AACH,eAAO,MAAM,UAAU,wIAgCrB,CAAC;AAeH,eAAO,MAAM,cAAc;;;yEAOzB,CAAC;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEjD;AACD,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;wFA4BxB,CAAC"}
@@ -0,0 +1,87 @@
1
+ var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExtension) || function (path, preserveJsx) {
2
+ if (typeof path === "string" && /^\.\.?\//.test(path)) {
3
+ return path.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function (m, tsx, d, ext, cm) {
4
+ return tsx ? preserveJsx ? ".jsx" : ".js" : d && (!ext || !cm) ? m : (d + ext + "." + cm.toLowerCase() + "js");
5
+ });
6
+ }
7
+ return path;
8
+ };
9
+ import { join } from "node:path";
10
+ import { pathToFileURL } from "node:url";
11
+ import { Effect, FileSystem, Schema } from "effect";
12
+ import { attempt, ChangesetError, requireThat } from "#error.ts";
13
+ import { PackageManifest, ReleaseManifest } from "#model.ts";
14
+ export function packagePatterns(config) {
15
+ return config.packages ?? ["packages/*", "examples/*"];
16
+ }
17
+ const Json = Schema.Record(Schema.String, Schema.Unknown);
18
+ export function decodePackage(directory, text, changelog) {
19
+ return {
20
+ changelog,
21
+ directory,
22
+ json: Schema.decodeUnknownSync(Schema.fromJsonString(Json))(text),
23
+ manifest: Schema.decodeUnknownSync(Schema.fromJsonString(PackageManifest))(text),
24
+ };
25
+ }
26
+ export const readOptional = Effect.fn("Changesets.readOptional")(function* (path, fallback) {
27
+ const fs = yield* FileSystem.FileSystem;
28
+ return (yield* fs.exists(path)) ? yield* fs.readFileString(path) : fallback;
29
+ });
30
+ export const loadConfig = Effect.fn("Changesets.loadConfig")(function* (root) {
31
+ const fs = yield* FileSystem.FileSystem;
32
+ const path = join(root, ".changeset/changesets.config.ts");
33
+ if (!(yield* fs.exists(path))) {
34
+ return {};
35
+ }
36
+ const module = yield* Effect.tryPromise({
37
+ catch: (cause) => new ChangesetError({
38
+ cause,
39
+ message: ".changeset/changesets.config.ts: export default defineConfig({ packages, hooks }); hooks must be typed Effect functions.",
40
+ }),
41
+ try: () => import(__rewriteRelativeImportExtension(pathToFileURL(path).href)),
42
+ });
43
+ yield* attempt(() => {
44
+ requireThat(typeof module.default === "object" && module.default !== null, ".changeset/changesets.config.ts: export a config object with defineConfig.");
45
+ requireThat(module.default.hooks === undefined || (Array.isArray(module.default.hooks) && module.default.hooks.every((hook) => typeof hook === "function")), ".changeset/changesets.config.ts: hooks must be Effect functions, not shell strings.");
46
+ requireThat(module.default.packages === undefined
47
+ || (Array.isArray(module.default.packages) && module.default.packages.every((pattern) => typeof pattern === "string")), ".changeset/changesets.config.ts: packages must be directory paths or parent/* patterns.");
48
+ });
49
+ return module.default;
50
+ });
51
+ const directories = Effect.fn("Changesets.directories")(function* (root, pattern) {
52
+ const fs = yield* FileSystem.FileSystem;
53
+ yield* attempt(() => requireThat(/^(?:[\w.-]+\/)*[\w.*-]+$/u.test(pattern) && !pattern.split("/").includes("..") && (!pattern.includes("*") || pattern.endsWith("/*")), `Invalid package pattern ${pattern}; use a relative directory or parent/*. `));
54
+ if (!pattern.endsWith("/*")) {
55
+ return [pattern];
56
+ }
57
+ const parent = pattern.slice(0, -2);
58
+ return (yield* fs.exists(join(root, parent))) ? (yield* fs.readDirectory(join(root, parent))).map((name) => `${parent}/${name}`) : [];
59
+ });
60
+ export const readChangesets = Effect.fn("Changesets.readChangesets")(function* (root) {
61
+ const fs = yield* FileSystem.FileSystem;
62
+ const directory = join(root, ".changeset");
63
+ const names = (yield* fs.exists(directory)) ? yield* fs.readDirectory(directory) : [];
64
+ return yield* Effect.forEach(names.filter(isChangeset).sort(), (name) => Effect.map(fs.readFileString(join(directory, name)), (text) => ({ name, text })));
65
+ });
66
+ export function isChangeset(name) {
67
+ return name !== "README.md" && /^[^/\\]+\.md$/u.test(name);
68
+ }
69
+ export const readWorkspace = Effect.fn("Changesets.readWorkspace")(function* (root, config) {
70
+ const fs = yield* FileSystem.FileSystem;
71
+ const paths = [...new Set((yield* Effect.forEach(packagePatterns(config), (pattern) => directories(root, pattern))).flat())].sort();
72
+ const packages = [];
73
+ for (const directory of paths) {
74
+ if (yield* fs.exists(join(root, directory, "package.json"))) {
75
+ const text = yield* fs.readFileString(join(root, directory, "package.json"));
76
+ const changelog = yield* readOptional(join(root, directory, "CHANGELOG.md"), "# Changelog\n");
77
+ packages.push(yield* attempt(() => decodePackage(directory, text, changelog)));
78
+ }
79
+ }
80
+ yield* attempt(() => requireThat(new Set(packages.map((pkg) => pkg.manifest.name)).size === packages.length, "Workspace package names must be unique; fix package.json names."));
81
+ const releaseText = yield* readOptional(join(root, ".changeset/release.json"), "");
82
+ const release = releaseText === ""
83
+ ? undefined
84
+ : yield* attempt(() => Schema.decodeUnknownSync(Schema.fromJsonString(ReleaseManifest))(releaseText)).pipe(Effect.mapError((cause) => new ChangesetError({ cause, message: ".changeset/release.json is invalid; restore the manifest generated by changesets apply." })));
85
+ return { changesets: yield* readChangesets(root), packages, release };
86
+ });
87
+ //# sourceMappingURL=workspace.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspace.js","sourceRoot":"","sources":["../src/workspace.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,10 +1,76 @@
1
1
  {
2
2
  "name": "@shivaedev/changesets",
3
- "version": "0.0.0",
4
- "description": "Placeholder for ShivaeDev's changesets release tool. Real releases start above 0.0.0.",
5
- "license": "MIT",
3
+ "version": "0.1.1",
4
+ "description": "Explicit changesets and reproducible workspace releases with Effect",
5
+ "homepage": "https://github.com/ShivaeDev/platform/tree/main/packages/changesets#readme",
6
+ "bugs": {
7
+ "url": "https://github.com/ShivaeDev/platform/issues"
8
+ },
6
9
  "repository": {
7
10
  "type": "git",
8
- "url": "git+https://github.com/ShivaeDev/platform.git"
11
+ "url": "git+https://github.com/ShivaeDev/platform.git",
12
+ "directory": "packages/changesets"
13
+ },
14
+ "license": "MIT",
15
+ "sideEffects": false,
16
+ "type": "module",
17
+ "imports": {
18
+ "#test/*": "./src/test-support/*",
19
+ "#*.ts": {
20
+ "source": "./src/*.ts",
21
+ "types": "./dist/*.d.ts",
22
+ "default": "./dist/*.js"
23
+ }
24
+ },
25
+ "exports": {
26
+ "./*.ts": {
27
+ "source": "./src/*.ts",
28
+ "types": "./dist/*.d.ts",
29
+ "default": "./dist/*.js"
30
+ },
31
+ "./package.json": "./package.json"
32
+ },
33
+ "bin": {
34
+ "changesets": "./dist/cli.js"
35
+ },
36
+ "files": [
37
+ "dist",
38
+ "src",
39
+ "!src/**/*.test.ts",
40
+ "!src/**/*.spec.ts",
41
+ "!src/**/test-support",
42
+ "CHANGELOG.md",
43
+ "README.md"
44
+ ],
45
+ "devDependencies": {
46
+ "@effect/platform-node": "4.0.4",
47
+ "@effect/platform-node-shared": "4.0.4",
48
+ "@effect/vitest": "4.0.4",
49
+ "@shivaedev/effect-test": "0.6.0",
50
+ "@shivaedev/quality": "0.26.0",
51
+ "@shivaedev/test-story": "0.8.0",
52
+ "@types/node": "24.19.2",
53
+ "effect": "4.0.4",
54
+ "happy-dom": "20.14.6",
55
+ "typescript": "7.0.2",
56
+ "vitest": "5.0.3"
57
+ },
58
+ "peerDependencies": {
59
+ "@effect/platform-node": "4.0.4",
60
+ "@effect/platform-node-shared": "4.0.4",
61
+ "effect": "4.0.4"
62
+ },
63
+ "engines": {
64
+ "node": ">=24"
65
+ },
66
+ "publishConfig": {
67
+ "access": "public",
68
+ "provenance": true
69
+ },
70
+ "scripts": {
71
+ "build": "node --eval \"import('node:fs').then(({ rmSync }) => rmSync('dist', { force: true, recursive: true }))\" && tsc --project tsconfig.build.json",
72
+ "ready": "pnpm typecheck && pnpm test && pnpm build",
73
+ "test": "vitest run",
74
+ "typecheck": "tsc --noEmit"
9
75
  }
10
76
  }
@@ -0,0 +1,64 @@
1
+ import { join } from "node:path";
2
+ import { Clock, Effect, FileSystem } from "effect";
3
+ import { collectChangelog } from "#collectChangelog.ts";
4
+ import type { ChangesetConfig } from "#config.ts";
5
+ import { attempt, requireThat } from "#error.ts";
6
+ import type { ReleasePlan, WorkspacePackage } from "#model.ts";
7
+ import { computePlan } from "#planner.ts";
8
+ import { readWorkspace } from "#workspace.ts";
9
+
10
+ function updatedPackage(pkg: WorkspacePackage, plan: ReleasePlan, version: string) {
11
+ const json: Record<string, unknown> = { ...pkg.json, version };
12
+ for (const key of ["dependencies", "optionalDependencies", "peerDependencies"] as const) {
13
+ const dependencies = pkg.manifest[key];
14
+ if (dependencies !== undefined) {
15
+ json[key] = Object.fromEntries(
16
+ Object.entries(dependencies).map(([name, range]) => {
17
+ const target = plan.releases.find((release) => release.name === name);
18
+ if (target === undefined || ["workspace:*", "workspace:^", "workspace:~"].includes(range)) {
19
+ return [name, range];
20
+ }
21
+ const match = /^(?<prefix>(?:workspace:)?[~^]?)\d+\.\d+\.\d+$/u.exec(range);
22
+ requireThat(
23
+ match !== null,
24
+ `${pkg.manifest.name}: replace ${name}'s ${range} range with an exact version, ^version, ~version or workspace:* before applying a release.`,
25
+ );
26
+ const prefix = match?.groups?.prefix ?? "";
27
+ return [name, `${prefix}${target.to}`];
28
+ }),
29
+ );
30
+ }
31
+ }
32
+ return `${JSON.stringify(json, null, "\t")}\n`;
33
+ }
34
+ export const applyRelease = Effect.fn("Changesets.applyRelease")(function* (root: string, config: ChangesetConfig = {}) {
35
+ const fs = yield* FileSystem.FileSystem;
36
+ const workspace = yield* readWorkspace(root, config);
37
+ const plan = yield* attempt(() => computePlan(workspace.packages, workspace.changesets));
38
+ if (plan.releases.length === 0) {
39
+ return plan;
40
+ }
41
+ const date = new Date(yield* Clock.currentTimeMillis).toISOString().slice(0, 10);
42
+ const writes = yield* attempt(() =>
43
+ plan.releases.flatMap((release) => {
44
+ const pkg = workspace.packages.find((candidate) => candidate.manifest.name === release.name);
45
+ if (pkg === undefined) {
46
+ throw new Error(`Package ${release.name} disappeared while applying.`);
47
+ }
48
+ return [
49
+ { path: join(root, release.directory, "package.json"), text: updatedPackage(pkg, plan, release.to) },
50
+ { path: join(root, release.directory, "CHANGELOG.md"), text: collectChangelog(pkg.changelog, release, plan, date) },
51
+ ];
52
+ }),
53
+ );
54
+ const manifest = { date, plan };
55
+ for (const write of writes) {
56
+ yield* fs.writeFileString(write.path, write.text);
57
+ }
58
+ yield* fs.writeFileString(join(root, ".changeset/release.json"), `${JSON.stringify(manifest, null, "\t")}\n`);
59
+ yield* Effect.forEach(plan.changesets, (source) => fs.remove(join(root, ".changeset", source.name)));
60
+ for (const hook of config.hooks ?? []) {
61
+ yield* hook({ plan, root });
62
+ }
63
+ return plan;
64
+ });
package/src/check.ts ADDED
@@ -0,0 +1,106 @@
1
+ import { Effect } from "effect";
2
+ import { collectChangelog } from "#collectChangelog.ts";
3
+ import type { ChangesetConfig } from "#config.ts";
4
+ import { attempt, requireThat } from "#error.ts";
5
+ import type { Source, Workspace } from "#model.ts";
6
+ import { computePlan } from "#planner.ts";
7
+ import { readHistory } from "#readHistory.ts";
8
+ import { isChangeset, readWorkspace } from "#workspace.ts";
9
+
10
+ function same(left: unknown, right: unknown): boolean {
11
+ return JSON.stringify(left) === JSON.stringify(right);
12
+ }
13
+
14
+ function validateInputs(before: readonly Source[], pending: readonly Source[], consumed: readonly Source[]): void {
15
+ requireThat(
16
+ new Set(consumed.map((source) => source.name)).size === consumed.length && consumed.every((source) => isChangeset(source.name)),
17
+ "Release manifest changeset names must be unique .md filenames; restore the manifest generated by changesets apply.",
18
+ );
19
+ for (const source of consumed) {
20
+ requireThat(
21
+ !pending.some((item) => item.name === source.name),
22
+ `${source.name}: consumed changesets must be deleted; remove .changeset/${source.name}.`,
23
+ );
24
+ const previous = before.find((item) => item.name === source.name);
25
+ requireThat(
26
+ previous === undefined || previous.text === source.text,
27
+ `${source.name}: release inputs changed; restore the original changeset text and rerun changesets apply.`,
28
+ );
29
+ }
30
+ for (const source of before) {
31
+ const preserved = [...pending, ...consumed].find((item) => item.name === source.name);
32
+ requireThat(
33
+ preserved?.text === source.text,
34
+ `${source.name}: keep pending changesets unchanged or consume them unchanged in .changeset/release.json; add a new file for later changes.`,
35
+ );
36
+ }
37
+ }
38
+
39
+ export function validateDiff(before: Workspace, after: Workspace): void {
40
+ for (const old of before.packages) {
41
+ requireThat(
42
+ after.packages.some((pkg) => pkg.manifest.name === old.manifest.name),
43
+ `${old.manifest.name}: restore the package and its released history before checking releases.`,
44
+ );
45
+ }
46
+ const bumped = after.packages.filter((pkg) => {
47
+ const old = before.packages.find((candidate) => candidate.manifest.name === pkg.manifest.name);
48
+ const firstRelease = after.release?.plan.releases.find((candidate) => candidate.name === pkg.manifest.name);
49
+ return old === undefined
50
+ ? firstRelease !== undefined && firstRelease.from !== pkg.manifest.version
51
+ : old.manifest.version !== pkg.manifest.version;
52
+ });
53
+ if (bumped.length === 0) {
54
+ requireThat(same(before.release, after.release), ".changeset/release.json changes only with a release; restore it and run changesets apply.");
55
+ validateInputs(before.changesets, after.changesets, []);
56
+ for (const pkg of after.packages) {
57
+ const old = before.packages.find((candidate) => candidate.manifest.name === pkg.manifest.name);
58
+ requireThat(
59
+ old === undefined || old.changelog === pkg.changelog,
60
+ `${pkg.manifest.name}: CHANGELOG.md changes require a version bump; add .changeset/<name>.md and run changesets apply.`,
61
+ );
62
+ }
63
+ return;
64
+ }
65
+ const manifest = after.release;
66
+ requireThat(
67
+ manifest !== undefined && !same(before.release, manifest),
68
+ "A release needs .changeset/release.json; restore versions and run changesets apply.",
69
+ );
70
+ if (manifest === undefined) {
71
+ return;
72
+ }
73
+ validateInputs(before.changesets, after.changesets, manifest.plan.changesets);
74
+ const packages = after.packages.map((pkg) => {
75
+ const old = before.packages.find((candidate) => candidate.manifest.name === pkg.manifest.name);
76
+ const version =
77
+ old?.manifest.version ?? manifest.plan.releases.find((candidate) => candidate.name === pkg.manifest.name)?.from ?? pkg.manifest.version;
78
+ return { ...pkg, manifest: { ...pkg.manifest, version } };
79
+ });
80
+ const plan = computePlan(packages, manifest.plan.changesets);
81
+ requireThat(
82
+ plan.releases.length > 0 && same(plan, manifest.plan),
83
+ "Release manifest does not match the changeset plan; restore versions and rerun changesets apply, including published dependents.",
84
+ );
85
+ for (const pkg of after.packages) {
86
+ const old = before.packages.find((candidate) => candidate.manifest.name === pkg.manifest.name);
87
+ const release = plan.releases.find((candidate) => candidate.name === pkg.manifest.name);
88
+ requireThat(
89
+ pkg.manifest.version === (release?.to ?? old?.manifest.version ?? pkg.manifest.version),
90
+ `${pkg.manifest.name}: version differs from the release plan; restore versions and rerun changesets apply.`,
91
+ );
92
+ const expected =
93
+ release === undefined ? (old?.changelog ?? pkg.changelog) : collectChangelog(old?.changelog ?? "# Changelog\n", release, plan, manifest.date);
94
+ requireThat(
95
+ pkg.changelog === expected,
96
+ `${pkg.manifest.name}: release notes differ from changesets apply; restore released history and regenerate the release from unchanged inputs.`,
97
+ );
98
+ }
99
+ }
100
+
101
+ export const checkRepository = Effect.fn("Changesets.checkRepository")(function* (root: string, config: ChangesetConfig = {}, reference?: string) {
102
+ const after = yield* readWorkspace(root, config);
103
+ yield* attempt(() => computePlan(after.packages, after.changesets));
104
+ const before = yield* readHistory(root, config, reference);
105
+ yield* attempt(() => validateDiff(before, after));
106
+ });