@savvy-web/silk 1.3.10 → 2.0.0
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.
- package/changesets-changelog.cjs +39308 -96625
- package/changesets-changelog.d.cts +137 -36
- package/changesets-changelog.d.ts +137 -36
- package/changesets-markdownlint.cjs +39305 -96622
- package/changesets-markdownlint.d.cts +137 -36
- package/changesets-markdownlint.d.ts +137 -36
- package/package.json +12 -12
- package/packages/silk-effects/dist/dev/pkg/changesets/api/changelog.cjs +2 -2
- package/packages/silk-effects/dist/dev/pkg/changesets/api/changelog.js +2 -2
- package/packages/silk-effects/dist/dev/pkg/changesets/api/transformer.cjs +24 -30
- package/packages/silk-effects/dist/dev/pkg/changesets/api/transformer.js +24 -30
- package/packages/silk-effects/dist/dev/pkg/changesets/changelog/formatting.cjs +4 -10
- package/packages/silk-effects/dist/dev/pkg/changesets/changelog/formatting.js +4 -10
- package/packages/silk-effects/dist/dev/pkg/changesets/changelog/getDependencyReleaseLine.cjs +13 -9
- package/packages/silk-effects/dist/dev/pkg/changesets/changelog/getDependencyReleaseLine.js +13 -9
- package/packages/silk-effects/dist/dev/pkg/changesets/changelog/getReleaseLine.cjs +8 -8
- package/packages/silk-effects/dist/dev/pkg/changesets/changelog/getReleaseLine.js +8 -8
- package/packages/silk-effects/dist/dev/pkg/changesets/changelog/index.cjs +1 -1
- package/packages/silk-effects/dist/dev/pkg/changesets/changelog/index.js +1 -1
- package/packages/silk-effects/dist/dev/pkg/changesets/index.cjs +12 -2
- package/packages/silk-effects/dist/dev/pkg/changesets/index.js +9 -3
- package/packages/silk-effects/dist/dev/pkg/changesets/remark/plugins/deduplicate-items.cjs +11 -9
- package/packages/silk-effects/dist/dev/pkg/changesets/remark/plugins/deduplicate-items.js +11 -9
- package/packages/silk-effects/dist/dev/pkg/changesets/remark/plugins/maintenance-note.cjs +61 -0
- package/packages/silk-effects/dist/dev/pkg/changesets/remark/plugins/maintenance-note.js +61 -0
- package/packages/silk-effects/dist/dev/pkg/changesets/remark/presets.cjs +1 -1
- package/packages/silk-effects/dist/dev/pkg/changesets/remark/presets.js +1 -1
- package/packages/silk-effects/dist/dev/pkg/changesets/services/maintenance-reason.cjs +68 -0
- package/packages/silk-effects/dist/dev/pkg/changesets/services/maintenance-reason.js +66 -0
- package/packages/silk-effects/dist/dev/pkg/changesets/services/release-planner.cjs +105 -59
- package/packages/silk-effects/dist/dev/pkg/changesets/services/release-planner.js +104 -58
- package/packages/silk-effects/dist/dev/pkg/changesets/vendor/github-info.cjs +33 -11
- package/packages/silk-effects/dist/dev/pkg/changesets/vendor/github-info.js +33 -11
- package/packages/silk-effects/dist/dev/pkg/schemas/VersioningSchemas.cjs +1 -1
- package/packages/silk-effects/dist/dev/pkg/schemas/VersioningSchemas.js +1 -1
- package/tsconfig/node/dist/tsconfig.tsbuildinfo +1 -1
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
const require_errors = require('../errors.cjs');
|
|
2
2
|
const require_transformer = require('../api/transformer.cjs');
|
|
3
3
|
const require_config_inspector = require('./config-inspector.cjs');
|
|
4
|
+
const require_maintenance_reason = require('./maintenance-reason.cjs');
|
|
4
5
|
const require_version_files = require('../utils/version-files.cjs');
|
|
5
|
-
const require_changesets_config_esm = require('../../../../../../../node_modules/.pnpm/@changesets_config@3.1.4/node_modules/@changesets/config/dist/changesets-config.esm.cjs');
|
|
6
|
-
const require_changesets_apply_release_plan_esm = require('../../../../../../../node_modules/.pnpm/@changesets_apply-release-plan@7.1.1/node_modules/@changesets/apply-release-plan/dist/changesets-apply-release-plan.esm.cjs');
|
|
7
|
-
const require_changesets_get_release_plan_esm = require('../../../../../../../node_modules/.pnpm/@changesets_get-release-plan@4.0.16/node_modules/@changesets/get-release-plan/dist/changesets-get-release-plan.esm.cjs');
|
|
8
6
|
const require_manypkg_get_packages = require('../../../../../../../node_modules/.pnpm/@manypkg_get-packages@3.1.0/node_modules/@manypkg/get-packages/dist/manypkg-get-packages.cjs');
|
|
7
|
+
const require_index = require('../../../../../../../node_modules/.pnpm/@changesets_config@4.0.0-next.6/node_modules/@changesets/config/dist/index.cjs');
|
|
8
|
+
const require_index$1 = require('../../../../../../../node_modules/.pnpm/@changesets_apply-release-plan@8.0.0-next.7/node_modules/@changesets/apply-release-plan/dist/index.cjs');
|
|
9
|
+
const require_index$2 = require('../../../../../../../node_modules/.pnpm/@changesets_get-release-plan@5.0.0-next.7/node_modules/@changesets/get-release-plan/dist/index.cjs');
|
|
9
10
|
let effect = require("effect");
|
|
10
11
|
let _effect_platform = require("@effect/platform");
|
|
11
12
|
let node_path = require("node:path");
|
|
@@ -23,37 +24,21 @@ let node_path = require("node:path");
|
|
|
23
24
|
* (e.g. `getChangelogEntry`) is re-implemented.
|
|
24
25
|
*
|
|
25
26
|
*/
|
|
26
|
-
const
|
|
27
|
-
"yarn",
|
|
28
|
-
"bolt",
|
|
29
|
-
"pnpm",
|
|
30
|
-
"lerna",
|
|
31
|
-
"root"
|
|
32
|
-
]);
|
|
27
|
+
const errMsg = (e) => e instanceof Error ? e.message : String(e);
|
|
33
28
|
/**
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
* the engine never reads `tool` at runtime, only `root.dir`), and
|
|
39
|
-
* `rootDir`/`rootPackage` fold back into `root`.
|
|
29
|
+
* Read the changesets config, surfacing non-throwing `readConfig` errors as a
|
|
30
|
+
* thrown `Error` so callers inside `Effect.tryPromise` land on the existing
|
|
31
|
+
* `ReleasePlanError` mapping. Warnings are returned alongside the config so
|
|
32
|
+
* the caller can log them via the Effect runtime rather than console output.
|
|
40
33
|
*/
|
|
41
|
-
|
|
42
|
-
const
|
|
43
|
-
if (
|
|
34
|
+
async function loadConfig(root, packages) {
|
|
35
|
+
const configResult = await require_index.readConfig(root, packages);
|
|
36
|
+
if (configResult.config === void 0) throw new Error(`Invalid changeset config:\n${configResult.errors.join("\n")}`);
|
|
44
37
|
return {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
dir: rootPackage.dir,
|
|
48
|
-
packageJson: rootPackage.packageJson
|
|
49
|
-
},
|
|
50
|
-
packages: packages.map((p) => ({
|
|
51
|
-
dir: p.dir,
|
|
52
|
-
packageJson: p.packageJson
|
|
53
|
-
}))
|
|
38
|
+
config: configResult.config,
|
|
39
|
+
warnings: configResult.warnings
|
|
54
40
|
};
|
|
55
|
-
}
|
|
56
|
-
const errMsg = (e) => e instanceof Error ? e.message : String(e);
|
|
41
|
+
}
|
|
57
42
|
/**
|
|
58
43
|
* Base class for {@link ReleasePlanner}.
|
|
59
44
|
*
|
|
@@ -66,14 +51,14 @@ var ReleasePlanner = class extends ReleasePlannerBase {};
|
|
|
66
51
|
/** Build the service shape over a resolved {@link ConfigInspector} and {@link FileSystem.FileSystem}. */
|
|
67
52
|
function makeShape(inspector, fs) {
|
|
68
53
|
const plan = (root) => effect.Effect.tryPromise({
|
|
69
|
-
try: () =>
|
|
54
|
+
try: () => require_index$2.getReleasePlan(root),
|
|
70
55
|
catch: (e) => new require_errors.ReleasePlanError({
|
|
71
56
|
phase: "plan",
|
|
72
57
|
reason: errMsg(e)
|
|
73
58
|
})
|
|
74
59
|
});
|
|
75
60
|
const preview = (root) => previewEffect(root, fs);
|
|
76
|
-
const apply = (root, options) => applyEffect(root, options?.dryRun ?? false, inspector, fs);
|
|
61
|
+
const apply = (root, options) => applyEffect(root, options?.dryRun ?? false, options?.changelogModules, inspector, fs);
|
|
77
62
|
return {
|
|
78
63
|
plan,
|
|
79
64
|
preview,
|
|
@@ -113,6 +98,16 @@ function extractVersionBlock(changelog, version) {
|
|
|
113
98
|
}
|
|
114
99
|
return lines.slice(start, end).join("\n").trim();
|
|
115
100
|
}
|
|
101
|
+
/** Maintenance reasons for every changeset-less release in the plan, keyed by package name. */
|
|
102
|
+
function maintenanceReasons(plan, config) {
|
|
103
|
+
const reasons = /* @__PURE__ */ new Map();
|
|
104
|
+
for (const r of plan.releases) {
|
|
105
|
+
if (r.type === "none") continue;
|
|
106
|
+
const reason = require_maintenance_reason.deriveMaintenanceReason(r, plan, config);
|
|
107
|
+
if (reason) reasons.set(r.name, reason);
|
|
108
|
+
}
|
|
109
|
+
return reasons;
|
|
110
|
+
}
|
|
116
111
|
/**
|
|
117
112
|
* Render a non-destructive preview by redirecting every write into a
|
|
118
113
|
* scope-managed temp directory (cleaned up automatically when the scope
|
|
@@ -121,19 +116,26 @@ function extractVersionBlock(changelog, version) {
|
|
|
121
116
|
function previewEffect(root, fs) {
|
|
122
117
|
const program = effect.Effect.gen(function* () {
|
|
123
118
|
const [plan, packages] = yield* effect.Effect.tryPromise({
|
|
124
|
-
try: () => Promise.all([
|
|
119
|
+
try: () => Promise.all([require_index$2.getReleasePlan(root), require_manypkg_get_packages.getPackages(root)]),
|
|
125
120
|
catch: (e) => new require_errors.ReleasePlanError({
|
|
126
121
|
phase: "preview",
|
|
127
122
|
reason: errMsg(e)
|
|
128
123
|
})
|
|
129
124
|
});
|
|
130
|
-
|
|
131
|
-
|
|
125
|
+
if (!packages.rootPackage) return yield* effect.Effect.fail(new require_errors.ReleasePlanError({
|
|
126
|
+
phase: "preview",
|
|
127
|
+
reason: `Workspace root has no package.json: ${root}`
|
|
128
|
+
}));
|
|
129
|
+
const rootPackage = packages.rootPackage;
|
|
130
|
+
const { config, warnings } = yield* effect.Effect.tryPromise({
|
|
131
|
+
try: () => loadConfig(root, packages),
|
|
132
132
|
catch: (e) => new require_errors.ReleasePlanError({
|
|
133
133
|
phase: "preview",
|
|
134
134
|
reason: errMsg(e)
|
|
135
135
|
})
|
|
136
136
|
});
|
|
137
|
+
yield* effect.Effect.forEach(warnings, (w) => effect.Effect.logWarning(w));
|
|
138
|
+
const reasonByName = maintenanceReasons(plan, config);
|
|
137
139
|
const preMode = plan.preState ? plan.preState.mode : null;
|
|
138
140
|
const changesets = plan.changesets.map((cs) => ({
|
|
139
141
|
id: cs.id,
|
|
@@ -151,7 +153,7 @@ function previewEffect(root, fs) {
|
|
|
151
153
|
};
|
|
152
154
|
const tempRoot = yield* fs.makeTempDirectoryScoped({ prefix: "silk-preview-" });
|
|
153
155
|
const mapDir = (dir) => {
|
|
154
|
-
const rel = (0, node_path.relative)(packages.
|
|
156
|
+
const rel = (0, node_path.relative)(packages.rootDir, dir);
|
|
155
157
|
if (rel.startsWith("..") || (0, node_path.isAbsolute)(rel)) return effect.Effect.fail(new require_errors.ReleasePlanError({
|
|
156
158
|
phase: "preview",
|
|
157
159
|
reason: `Package directory is outside the workspace root: ${dir}`
|
|
@@ -161,13 +163,12 @@ function previewEffect(root, fs) {
|
|
|
161
163
|
const tempDirs = yield* effect.Effect.forEach(packages.packages, (p) => mapDir(p.dir));
|
|
162
164
|
const tempPackages = {
|
|
163
165
|
tool: packages.tool,
|
|
164
|
-
|
|
165
|
-
|
|
166
|
+
rootDir: tempRoot,
|
|
167
|
+
rootPackage: {
|
|
166
168
|
dir: tempRoot,
|
|
167
|
-
packageJson: structuredClone(
|
|
169
|
+
packageJson: structuredClone(rootPackage.packageJson)
|
|
168
170
|
},
|
|
169
171
|
packages: packages.packages.map((p, i) => ({
|
|
170
|
-
...p,
|
|
171
172
|
dir: tempDirs[i],
|
|
172
173
|
packageJson: structuredClone(p.packageJson)
|
|
173
174
|
}))
|
|
@@ -184,10 +185,10 @@ function previewEffect(root, fs) {
|
|
|
184
185
|
const realCl = (0, node_path.join)(p.dir, "CHANGELOG.md");
|
|
185
186
|
if (yield* fs.exists(realCl)) yield* fs.copyFile(realCl, (0, node_path.join)(tDir, "CHANGELOG.md"));
|
|
186
187
|
}
|
|
187
|
-
const rootCl = (0, node_path.join)(packages.
|
|
188
|
+
const rootCl = (0, node_path.join)(packages.rootDir, "CHANGELOG.md");
|
|
188
189
|
if (yield* fs.exists(rootCl)) yield* fs.copyFile(rootCl, (0, node_path.join)(tempRoot, "CHANGELOG.md"));
|
|
189
190
|
yield* effect.Effect.tryPromise({
|
|
190
|
-
try: () =>
|
|
191
|
+
try: () => require_index$1.applyReleasePlan(plan, tempPackages, config, void 0, root),
|
|
191
192
|
catch: (e) => new require_errors.ReleasePlanError({
|
|
192
193
|
phase: "preview",
|
|
193
194
|
reason: errMsg(e)
|
|
@@ -195,15 +196,19 @@ function previewEffect(root, fs) {
|
|
|
195
196
|
});
|
|
196
197
|
const dirByName = /* @__PURE__ */ new Map();
|
|
197
198
|
for (const p of tempPackages.packages) dirByName.set(p.packageJson.name, p.dir);
|
|
198
|
-
if (tempPackages.
|
|
199
|
+
if (tempPackages.rootPackage?.packageJson.name) dirByName.set(tempPackages.rootPackage.packageJson.name, tempRoot);
|
|
199
200
|
const releases = [];
|
|
200
201
|
for (const r of releasesToRender) {
|
|
201
202
|
const dir = dirByName.get(r.name);
|
|
202
203
|
if (!dir) continue;
|
|
203
204
|
const clPath = (0, node_path.join)(dir, "CHANGELOG.md");
|
|
204
205
|
if (!(yield* fs.exists(clPath))) continue;
|
|
206
|
+
const reason = reasonByName.get(r.name);
|
|
205
207
|
yield* effect.Effect.try({
|
|
206
|
-
try: () => require_transformer.ChangelogTransformer.transformFile(clPath
|
|
208
|
+
try: () => require_transformer.ChangelogTransformer.transformFile(clPath, reason ? { maintenance: {
|
|
209
|
+
version: r.newVersion,
|
|
210
|
+
reason
|
|
211
|
+
} } : void 0),
|
|
207
212
|
catch: (e) => new require_errors.ReleasePlanError({
|
|
208
213
|
phase: "preview",
|
|
209
214
|
reason: errMsg(e)
|
|
@@ -234,15 +239,17 @@ function previewEffect(root, fs) {
|
|
|
234
239
|
function diskVersion(workspaceDir, fallback, fs) {
|
|
235
240
|
return fs.readFileString((0, node_path.join)(workspaceDir, "package.json")).pipe(effect.Effect.flatMap((raw) => effect.Effect.try(() => JSON.parse(raw).version ?? fallback)), effect.Effect.orElseSucceed(() => fallback));
|
|
236
241
|
}
|
|
237
|
-
function applyEffect(root, dryRun, inspector, fs) {
|
|
242
|
+
function applyEffect(root, dryRun, changelogModules, inspector, fs) {
|
|
238
243
|
return effect.Effect.gen(function* () {
|
|
239
|
-
const { plan, packages, config } = yield* effect.Effect.tryPromise({
|
|
244
|
+
const { plan, packages, config, warnings } = yield* effect.Effect.tryPromise({
|
|
240
245
|
try: async () => {
|
|
241
|
-
const [plan, packages] = await Promise.all([
|
|
246
|
+
const [plan, packages] = await Promise.all([require_index$2.getReleasePlan(root), require_manypkg_get_packages.getPackages(root)]);
|
|
247
|
+
const { config, warnings } = await loadConfig(root, packages);
|
|
242
248
|
return {
|
|
243
249
|
plan,
|
|
244
250
|
packages,
|
|
245
|
-
config
|
|
251
|
+
config,
|
|
252
|
+
warnings
|
|
246
253
|
};
|
|
247
254
|
},
|
|
248
255
|
catch: (e) => new require_errors.ReleasePlanError({
|
|
@@ -250,6 +257,29 @@ function applyEffect(root, dryRun, inspector, fs) {
|
|
|
250
257
|
reason: errMsg(e)
|
|
251
258
|
})
|
|
252
259
|
});
|
|
260
|
+
yield* effect.Effect.forEach(warnings, (w) => effect.Effect.logWarning(w));
|
|
261
|
+
let engineConfig = config;
|
|
262
|
+
if (changelogModules) {
|
|
263
|
+
engineConfig = {
|
|
264
|
+
...config,
|
|
265
|
+
format: false
|
|
266
|
+
};
|
|
267
|
+
if (Array.isArray(config.changelog)) {
|
|
268
|
+
const configuredId = config.changelog[0];
|
|
269
|
+
const mapped = changelogModules[configuredId];
|
|
270
|
+
if (mapped === void 0) {
|
|
271
|
+
const supported = Object.keys(changelogModules).join(", ");
|
|
272
|
+
return yield* effect.Effect.fail(new require_errors.ReleasePlanError({
|
|
273
|
+
phase: "apply",
|
|
274
|
+
reason: `changelog id "${configuredId}" is not in changelogModules (supported: ${supported})`
|
|
275
|
+
}));
|
|
276
|
+
}
|
|
277
|
+
engineConfig = {
|
|
278
|
+
...engineConfig,
|
|
279
|
+
changelog: [mapped, config.changelog[1]]
|
|
280
|
+
};
|
|
281
|
+
}
|
|
282
|
+
}
|
|
253
283
|
const releases = plan.releases.filter((r) => r.type !== "none").map((r) => ({
|
|
254
284
|
name: r.name,
|
|
255
285
|
type: r.type,
|
|
@@ -257,17 +287,33 @@ function applyEffect(root, dryRun, inspector, fs) {
|
|
|
257
287
|
newVersion: r.newVersion
|
|
258
288
|
}));
|
|
259
289
|
let touchedFiles = [];
|
|
260
|
-
if (!dryRun)
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
290
|
+
if (!dryRun) {
|
|
291
|
+
const reasonByName = maintenanceReasons(plan, config);
|
|
292
|
+
const versionByPkgName = new Map(plan.releases.map((r) => [r.name, r.newVersion]));
|
|
293
|
+
const nameByDir = /* @__PURE__ */ new Map();
|
|
294
|
+
for (const p of packages.packages) nameByDir.set(p.dir, p.packageJson.name);
|
|
295
|
+
if (packages.rootPackage?.packageJson.name) nameByDir.set(packages.rootDir, packages.rootPackage.packageJson.name);
|
|
296
|
+
touchedFiles = yield* effect.Effect.tryPromise({
|
|
297
|
+
try: async () => {
|
|
298
|
+
const touched = await require_index$1.applyReleasePlan(plan, packages, engineConfig);
|
|
299
|
+
for (const f of touched) {
|
|
300
|
+
if (!f.endsWith("CHANGELOG.md")) continue;
|
|
301
|
+
const pkgName = nameByDir.get((0, node_path.dirname)(f));
|
|
302
|
+
const reason = pkgName ? reasonByName.get(pkgName) : void 0;
|
|
303
|
+
const newVersion = pkgName ? versionByPkgName.get(pkgName) : void 0;
|
|
304
|
+
require_transformer.ChangelogTransformer.transformFile(f, reason && newVersion ? { maintenance: {
|
|
305
|
+
version: newVersion,
|
|
306
|
+
reason
|
|
307
|
+
} } : void 0);
|
|
308
|
+
}
|
|
309
|
+
return touched;
|
|
310
|
+
},
|
|
311
|
+
catch: (e) => new require_errors.ReleasePlanError({
|
|
312
|
+
phase: "apply",
|
|
313
|
+
reason: errMsg(e)
|
|
314
|
+
})
|
|
315
|
+
});
|
|
316
|
+
}
|
|
271
317
|
const newVersionByName = new Map(plan.releases.map((r) => [r.name, r.newVersion]));
|
|
272
318
|
const inspected = yield* inspector.inspect(root).pipe(effect.Effect.catchAll((error) => effect.Effect.logWarning(`Skipping versionFiles update: ${errMsg(error)}`).pipe(effect.Effect.as(null))));
|
|
273
319
|
let versionFileUpdates = [];
|
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import { ReleasePlanError } from "../errors.js";
|
|
2
2
|
import { ChangelogTransformer } from "../api/transformer.js";
|
|
3
3
|
import { ConfigInspector } from "./config-inspector.js";
|
|
4
|
+
import { deriveMaintenanceReason } from "./maintenance-reason.js";
|
|
4
5
|
import { VersionFiles } from "../utils/version-files.js";
|
|
5
|
-
import { read } from "../../../../../../../node_modules/.pnpm/@changesets_config@3.1.4/node_modules/@changesets/config/dist/changesets-config.esm.js";
|
|
6
|
-
import applyReleasePlan from "../../../../../../../node_modules/.pnpm/@changesets_apply-release-plan@7.1.1/node_modules/@changesets/apply-release-plan/dist/changesets-apply-release-plan.esm.js";
|
|
7
|
-
import getReleasePlan from "../../../../../../../node_modules/.pnpm/@changesets_get-release-plan@4.0.16/node_modules/@changesets/get-release-plan/dist/changesets-get-release-plan.esm.js";
|
|
8
6
|
import { getPackages } from "../../../../../../../node_modules/.pnpm/@manypkg_get-packages@3.1.0/node_modules/@manypkg/get-packages/dist/manypkg-get-packages.js";
|
|
7
|
+
import { readConfig } from "../../../../../../../node_modules/.pnpm/@changesets_config@4.0.0-next.6/node_modules/@changesets/config/dist/index.js";
|
|
8
|
+
import { applyReleasePlan } from "../../../../../../../node_modules/.pnpm/@changesets_apply-release-plan@8.0.0-next.7/node_modules/@changesets/apply-release-plan/dist/index.js";
|
|
9
|
+
import { getReleasePlan } from "../../../../../../../node_modules/.pnpm/@changesets_get-release-plan@5.0.0-next.7/node_modules/@changesets/get-release-plan/dist/index.js";
|
|
9
10
|
import { Context, Effect, Layer } from "effect";
|
|
10
11
|
import { FileSystem } from "@effect/platform";
|
|
11
|
-
import { isAbsolute, join, relative } from "node:path";
|
|
12
|
+
import { dirname, isAbsolute, join, relative } from "node:path";
|
|
12
13
|
|
|
13
14
|
//#region ../silk-effects/dist/dev/pkg/changesets/services/release-planner.js
|
|
14
15
|
/**
|
|
@@ -23,37 +24,21 @@ import { isAbsolute, join, relative } from "node:path";
|
|
|
23
24
|
* (e.g. `getChangelogEntry`) is re-implemented.
|
|
24
25
|
*
|
|
25
26
|
*/
|
|
26
|
-
const
|
|
27
|
-
"yarn",
|
|
28
|
-
"bolt",
|
|
29
|
-
"pnpm",
|
|
30
|
-
"lerna",
|
|
31
|
-
"root"
|
|
32
|
-
]);
|
|
27
|
+
const errMsg = (e) => e instanceof Error ? e.message : String(e);
|
|
33
28
|
/**
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
* the engine never reads `tool` at runtime, only `root.dir`), and
|
|
39
|
-
* `rootDir`/`rootPackage` fold back into `root`.
|
|
29
|
+
* Read the changesets config, surfacing non-throwing `readConfig` errors as a
|
|
30
|
+
* thrown `Error` so callers inside `Effect.tryPromise` land on the existing
|
|
31
|
+
* `ReleasePlanError` mapping. Warnings are returned alongside the config so
|
|
32
|
+
* the caller can log them via the Effect runtime rather than console output.
|
|
40
33
|
*/
|
|
41
|
-
|
|
42
|
-
const
|
|
43
|
-
if (
|
|
34
|
+
async function loadConfig(root, packages) {
|
|
35
|
+
const configResult = await readConfig(root, packages);
|
|
36
|
+
if (configResult.config === void 0) throw new Error(`Invalid changeset config:\n${configResult.errors.join("\n")}`);
|
|
44
37
|
return {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
dir: rootPackage.dir,
|
|
48
|
-
packageJson: rootPackage.packageJson
|
|
49
|
-
},
|
|
50
|
-
packages: packages.map((p) => ({
|
|
51
|
-
dir: p.dir,
|
|
52
|
-
packageJson: p.packageJson
|
|
53
|
-
}))
|
|
38
|
+
config: configResult.config,
|
|
39
|
+
warnings: configResult.warnings
|
|
54
40
|
};
|
|
55
|
-
}
|
|
56
|
-
const errMsg = (e) => e instanceof Error ? e.message : String(e);
|
|
41
|
+
}
|
|
57
42
|
/**
|
|
58
43
|
* Base class for {@link ReleasePlanner}.
|
|
59
44
|
*
|
|
@@ -73,7 +58,7 @@ function makeShape(inspector, fs) {
|
|
|
73
58
|
})
|
|
74
59
|
});
|
|
75
60
|
const preview = (root) => previewEffect(root, fs);
|
|
76
|
-
const apply = (root, options) => applyEffect(root, options?.dryRun ?? false, inspector, fs);
|
|
61
|
+
const apply = (root, options) => applyEffect(root, options?.dryRun ?? false, options?.changelogModules, inspector, fs);
|
|
77
62
|
return {
|
|
78
63
|
plan,
|
|
79
64
|
preview,
|
|
@@ -113,6 +98,16 @@ function extractVersionBlock(changelog, version) {
|
|
|
113
98
|
}
|
|
114
99
|
return lines.slice(start, end).join("\n").trim();
|
|
115
100
|
}
|
|
101
|
+
/** Maintenance reasons for every changeset-less release in the plan, keyed by package name. */
|
|
102
|
+
function maintenanceReasons(plan, config) {
|
|
103
|
+
const reasons = /* @__PURE__ */ new Map();
|
|
104
|
+
for (const r of plan.releases) {
|
|
105
|
+
if (r.type === "none") continue;
|
|
106
|
+
const reason = deriveMaintenanceReason(r, plan, config);
|
|
107
|
+
if (reason) reasons.set(r.name, reason);
|
|
108
|
+
}
|
|
109
|
+
return reasons;
|
|
110
|
+
}
|
|
116
111
|
/**
|
|
117
112
|
* Render a non-destructive preview by redirecting every write into a
|
|
118
113
|
* scope-managed temp directory (cleaned up automatically when the scope
|
|
@@ -121,19 +116,26 @@ function extractVersionBlock(changelog, version) {
|
|
|
121
116
|
function previewEffect(root, fs) {
|
|
122
117
|
const program = Effect.gen(function* () {
|
|
123
118
|
const [plan, packages] = yield* Effect.tryPromise({
|
|
124
|
-
try: () => Promise.all([getReleasePlan(root),
|
|
119
|
+
try: () => Promise.all([getReleasePlan(root), getPackages(root)]),
|
|
125
120
|
catch: (e) => new ReleasePlanError({
|
|
126
121
|
phase: "preview",
|
|
127
122
|
reason: errMsg(e)
|
|
128
123
|
})
|
|
129
124
|
});
|
|
130
|
-
|
|
131
|
-
|
|
125
|
+
if (!packages.rootPackage) return yield* Effect.fail(new ReleasePlanError({
|
|
126
|
+
phase: "preview",
|
|
127
|
+
reason: `Workspace root has no package.json: ${root}`
|
|
128
|
+
}));
|
|
129
|
+
const rootPackage = packages.rootPackage;
|
|
130
|
+
const { config, warnings } = yield* Effect.tryPromise({
|
|
131
|
+
try: () => loadConfig(root, packages),
|
|
132
132
|
catch: (e) => new ReleasePlanError({
|
|
133
133
|
phase: "preview",
|
|
134
134
|
reason: errMsg(e)
|
|
135
135
|
})
|
|
136
136
|
});
|
|
137
|
+
yield* Effect.forEach(warnings, (w) => Effect.logWarning(w));
|
|
138
|
+
const reasonByName = maintenanceReasons(plan, config);
|
|
137
139
|
const preMode = plan.preState ? plan.preState.mode : null;
|
|
138
140
|
const changesets = plan.changesets.map((cs) => ({
|
|
139
141
|
id: cs.id,
|
|
@@ -151,7 +153,7 @@ function previewEffect(root, fs) {
|
|
|
151
153
|
};
|
|
152
154
|
const tempRoot = yield* fs.makeTempDirectoryScoped({ prefix: "silk-preview-" });
|
|
153
155
|
const mapDir = (dir) => {
|
|
154
|
-
const rel = relative(packages.
|
|
156
|
+
const rel = relative(packages.rootDir, dir);
|
|
155
157
|
if (rel.startsWith("..") || isAbsolute(rel)) return Effect.fail(new ReleasePlanError({
|
|
156
158
|
phase: "preview",
|
|
157
159
|
reason: `Package directory is outside the workspace root: ${dir}`
|
|
@@ -161,13 +163,12 @@ function previewEffect(root, fs) {
|
|
|
161
163
|
const tempDirs = yield* Effect.forEach(packages.packages, (p) => mapDir(p.dir));
|
|
162
164
|
const tempPackages = {
|
|
163
165
|
tool: packages.tool,
|
|
164
|
-
|
|
165
|
-
|
|
166
|
+
rootDir: tempRoot,
|
|
167
|
+
rootPackage: {
|
|
166
168
|
dir: tempRoot,
|
|
167
|
-
packageJson: structuredClone(
|
|
169
|
+
packageJson: structuredClone(rootPackage.packageJson)
|
|
168
170
|
},
|
|
169
171
|
packages: packages.packages.map((p, i) => ({
|
|
170
|
-
...p,
|
|
171
172
|
dir: tempDirs[i],
|
|
172
173
|
packageJson: structuredClone(p.packageJson)
|
|
173
174
|
}))
|
|
@@ -184,7 +185,7 @@ function previewEffect(root, fs) {
|
|
|
184
185
|
const realCl = join(p.dir, "CHANGELOG.md");
|
|
185
186
|
if (yield* fs.exists(realCl)) yield* fs.copyFile(realCl, join(tDir, "CHANGELOG.md"));
|
|
186
187
|
}
|
|
187
|
-
const rootCl = join(packages.
|
|
188
|
+
const rootCl = join(packages.rootDir, "CHANGELOG.md");
|
|
188
189
|
if (yield* fs.exists(rootCl)) yield* fs.copyFile(rootCl, join(tempRoot, "CHANGELOG.md"));
|
|
189
190
|
yield* Effect.tryPromise({
|
|
190
191
|
try: () => applyReleasePlan(plan, tempPackages, config, void 0, root),
|
|
@@ -195,15 +196,19 @@ function previewEffect(root, fs) {
|
|
|
195
196
|
});
|
|
196
197
|
const dirByName = /* @__PURE__ */ new Map();
|
|
197
198
|
for (const p of tempPackages.packages) dirByName.set(p.packageJson.name, p.dir);
|
|
198
|
-
if (tempPackages.
|
|
199
|
+
if (tempPackages.rootPackage?.packageJson.name) dirByName.set(tempPackages.rootPackage.packageJson.name, tempRoot);
|
|
199
200
|
const releases = [];
|
|
200
201
|
for (const r of releasesToRender) {
|
|
201
202
|
const dir = dirByName.get(r.name);
|
|
202
203
|
if (!dir) continue;
|
|
203
204
|
const clPath = join(dir, "CHANGELOG.md");
|
|
204
205
|
if (!(yield* fs.exists(clPath))) continue;
|
|
206
|
+
const reason = reasonByName.get(r.name);
|
|
205
207
|
yield* Effect.try({
|
|
206
|
-
try: () => ChangelogTransformer.transformFile(clPath
|
|
208
|
+
try: () => ChangelogTransformer.transformFile(clPath, reason ? { maintenance: {
|
|
209
|
+
version: r.newVersion,
|
|
210
|
+
reason
|
|
211
|
+
} } : void 0),
|
|
207
212
|
catch: (e) => new ReleasePlanError({
|
|
208
213
|
phase: "preview",
|
|
209
214
|
reason: errMsg(e)
|
|
@@ -234,15 +239,17 @@ function previewEffect(root, fs) {
|
|
|
234
239
|
function diskVersion(workspaceDir, fallback, fs) {
|
|
235
240
|
return fs.readFileString(join(workspaceDir, "package.json")).pipe(Effect.flatMap((raw) => Effect.try(() => JSON.parse(raw).version ?? fallback)), Effect.orElseSucceed(() => fallback));
|
|
236
241
|
}
|
|
237
|
-
function applyEffect(root, dryRun, inspector, fs) {
|
|
242
|
+
function applyEffect(root, dryRun, changelogModules, inspector, fs) {
|
|
238
243
|
return Effect.gen(function* () {
|
|
239
|
-
const { plan, packages, config } = yield* Effect.tryPromise({
|
|
244
|
+
const { plan, packages, config, warnings } = yield* Effect.tryPromise({
|
|
240
245
|
try: async () => {
|
|
241
|
-
const [plan, packages] = await Promise.all([getReleasePlan(root),
|
|
246
|
+
const [plan, packages] = await Promise.all([getReleasePlan(root), getPackages(root)]);
|
|
247
|
+
const { config, warnings } = await loadConfig(root, packages);
|
|
242
248
|
return {
|
|
243
249
|
plan,
|
|
244
250
|
packages,
|
|
245
|
-
config
|
|
251
|
+
config,
|
|
252
|
+
warnings
|
|
246
253
|
};
|
|
247
254
|
},
|
|
248
255
|
catch: (e) => new ReleasePlanError({
|
|
@@ -250,6 +257,29 @@ function applyEffect(root, dryRun, inspector, fs) {
|
|
|
250
257
|
reason: errMsg(e)
|
|
251
258
|
})
|
|
252
259
|
});
|
|
260
|
+
yield* Effect.forEach(warnings, (w) => Effect.logWarning(w));
|
|
261
|
+
let engineConfig = config;
|
|
262
|
+
if (changelogModules) {
|
|
263
|
+
engineConfig = {
|
|
264
|
+
...config,
|
|
265
|
+
format: false
|
|
266
|
+
};
|
|
267
|
+
if (Array.isArray(config.changelog)) {
|
|
268
|
+
const configuredId = config.changelog[0];
|
|
269
|
+
const mapped = changelogModules[configuredId];
|
|
270
|
+
if (mapped === void 0) {
|
|
271
|
+
const supported = Object.keys(changelogModules).join(", ");
|
|
272
|
+
return yield* Effect.fail(new ReleasePlanError({
|
|
273
|
+
phase: "apply",
|
|
274
|
+
reason: `changelog id "${configuredId}" is not in changelogModules (supported: ${supported})`
|
|
275
|
+
}));
|
|
276
|
+
}
|
|
277
|
+
engineConfig = {
|
|
278
|
+
...engineConfig,
|
|
279
|
+
changelog: [mapped, config.changelog[1]]
|
|
280
|
+
};
|
|
281
|
+
}
|
|
282
|
+
}
|
|
253
283
|
const releases = plan.releases.filter((r) => r.type !== "none").map((r) => ({
|
|
254
284
|
name: r.name,
|
|
255
285
|
type: r.type,
|
|
@@ -257,17 +287,33 @@ function applyEffect(root, dryRun, inspector, fs) {
|
|
|
257
287
|
newVersion: r.newVersion
|
|
258
288
|
}));
|
|
259
289
|
let touchedFiles = [];
|
|
260
|
-
if (!dryRun)
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
290
|
+
if (!dryRun) {
|
|
291
|
+
const reasonByName = maintenanceReasons(plan, config);
|
|
292
|
+
const versionByPkgName = new Map(plan.releases.map((r) => [r.name, r.newVersion]));
|
|
293
|
+
const nameByDir = /* @__PURE__ */ new Map();
|
|
294
|
+
for (const p of packages.packages) nameByDir.set(p.dir, p.packageJson.name);
|
|
295
|
+
if (packages.rootPackage?.packageJson.name) nameByDir.set(packages.rootDir, packages.rootPackage.packageJson.name);
|
|
296
|
+
touchedFiles = yield* Effect.tryPromise({
|
|
297
|
+
try: async () => {
|
|
298
|
+
const touched = await applyReleasePlan(plan, packages, engineConfig);
|
|
299
|
+
for (const f of touched) {
|
|
300
|
+
if (!f.endsWith("CHANGELOG.md")) continue;
|
|
301
|
+
const pkgName = nameByDir.get(dirname(f));
|
|
302
|
+
const reason = pkgName ? reasonByName.get(pkgName) : void 0;
|
|
303
|
+
const newVersion = pkgName ? versionByPkgName.get(pkgName) : void 0;
|
|
304
|
+
ChangelogTransformer.transformFile(f, reason && newVersion ? { maintenance: {
|
|
305
|
+
version: newVersion,
|
|
306
|
+
reason
|
|
307
|
+
} } : void 0);
|
|
308
|
+
}
|
|
309
|
+
return touched;
|
|
310
|
+
},
|
|
311
|
+
catch: (e) => new ReleasePlanError({
|
|
312
|
+
phase: "apply",
|
|
313
|
+
reason: errMsg(e)
|
|
314
|
+
})
|
|
315
|
+
});
|
|
316
|
+
}
|
|
271
317
|
const newVersionByName = new Map(plan.releases.map((r) => [r.name, r.newVersion]));
|
|
272
318
|
const inspected = yield* inspector.inspect(root).pipe(Effect.catchAll((error) => Effect.logWarning(`Skipping versionFiles update: ${errMsg(error)}`).pipe(Effect.as(null))));
|
|
273
319
|
let versionFileUpdates = [];
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const require_errors = require('../errors.cjs');
|
|
2
|
-
const
|
|
2
|
+
const require_index = require('../../../../../../../node_modules/.pnpm/@changesets_get-github-info@1.0.0-next.3/node_modules/@changesets/get-github-info/dist/index.cjs');
|
|
3
3
|
let effect = require("effect");
|
|
4
4
|
|
|
5
5
|
//#region ../silk-effects/dist/dev/pkg/changesets/vendor/github-info.js
|
|
@@ -9,8 +9,14 @@ let effect = require("effect");
|
|
|
9
9
|
* @remarks
|
|
10
10
|
* Bridges the `\@changesets/get-github-info` package (which returns
|
|
11
11
|
* promises) into the Effect ecosystem. The {@link getGitHubInfo}
|
|
12
|
-
* function wraps the upstream `
|
|
13
|
-
*
|
|
12
|
+
* function wraps the upstream `getCommitInfo()` call in `Effect.tryPromise`,
|
|
13
|
+
* adapting its structured `CommitInfo | undefined` return back to the
|
|
14
|
+
* legacy {@link GitHubCommitInfo} shape and mapping failures (including a
|
|
15
|
+
* `not found` result) to {@link GitHubApiError}.
|
|
16
|
+
*
|
|
17
|
+
* The upstream v1 package added a `.env` fallback: it reads
|
|
18
|
+
* `GITHUB_TOKEN` from `process.env` directly when no token is otherwise
|
|
19
|
+
* configured, so the caller does not need to plumb one through.
|
|
14
20
|
*
|
|
15
21
|
* The {@link GitHubCommitInfo} type is the only item from this module
|
|
16
22
|
* that is part of the public API (re-exported from the package root).
|
|
@@ -24,9 +30,13 @@ let effect = require("effect");
|
|
|
24
30
|
* Fetch GitHub info for a commit, wrapped in Effect.
|
|
25
31
|
*
|
|
26
32
|
* @remarks
|
|
27
|
-
* Calls the upstream `
|
|
28
|
-
* within `Effect.tryPromise
|
|
29
|
-
* to
|
|
33
|
+
* Calls the upstream `getCommitInfo()` from `\@changesets/get-github-info`
|
|
34
|
+
* within `Effect.tryPromise`, adapting its structured `CommitInfo`
|
|
35
|
+
* return to the legacy {@link GitHubCommitInfo} shape. An `undefined`
|
|
36
|
+
* result (commit or repo not found) is treated as a thrown error so it
|
|
37
|
+
* is mapped to the same {@link GitHubApiError} failure channel. Any
|
|
38
|
+
* thrown error is caught and mapped to a {@link GitHubApiError} with
|
|
39
|
+
* the operation set to `"getCommitInfo"`.
|
|
30
40
|
*
|
|
31
41
|
* Requires a `GITHUB_TOKEN` environment variable to be set for
|
|
32
42
|
* authenticated API access (the upstream library reads it directly).
|
|
@@ -39,13 +49,25 @@ let effect = require("effect");
|
|
|
39
49
|
*/
|
|
40
50
|
function getGitHubInfo(params) {
|
|
41
51
|
return effect.Effect.tryPromise({
|
|
42
|
-
try: () =>
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
52
|
+
try: async () => {
|
|
53
|
+
const info = await require_index.getCommitInfo({
|
|
54
|
+
commit: params.commit,
|
|
55
|
+
repo: params.repo
|
|
56
|
+
});
|
|
57
|
+
if (info === void 0) throw new Error(`commit ${params.commit} not found in ${params.repo}`);
|
|
58
|
+
return {
|
|
59
|
+
user: info.author?.login ?? null,
|
|
60
|
+
pull: info.pull?.number ?? null,
|
|
61
|
+
links: {
|
|
62
|
+
commit: info.commit.markdownLink,
|
|
63
|
+
pull: info.pull?.markdownLink ?? null,
|
|
64
|
+
user: info.author?.markdownLink ?? null
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
},
|
|
46
68
|
/* v8 ignore next 5 -- error mapping tested via GitHubService test layer */
|
|
47
69
|
catch: (error) => new require_errors.GitHubApiError({
|
|
48
|
-
operation: "
|
|
70
|
+
operation: "getCommitInfo",
|
|
49
71
|
reason: error instanceof Error ? error.message : String(error)
|
|
50
72
|
})
|
|
51
73
|
});
|