@savvy-web/changesets 0.1.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.
- package/README.md +14 -36
- package/cjs/changelog.cjs +670 -0
- package/cjs/index.cjs +1302 -0
- package/cjs/markdownlint.cjs +312 -0
- package/cjs/remark.cjs +559 -0
- package/{bin → esm/bin}/savvy-changesets.js +143 -17
- package/esm/changelog.d.ts +21 -0
- package/esm/index.d.ts +795 -0
- package/esm/markdownlint.d.ts +61 -0
- package/esm/remark.d.ts +92 -0
- package/package.json +21 -27
- /package/{changelog.d.ts → cjs/changelog.d.cts} +0 -0
- /package/{index.d.ts → cjs/index.d.cts} +0 -0
- /package/{markdownlint.d.ts → cjs/markdownlint.d.cts} +0 -0
- /package/{remark.d.ts → cjs/remark.d.cts} +0 -0
- /package/{160.js → esm/160.js} +0 -0
- /package/{234.js → esm/234.js} +0 -0
- /package/{245.js → esm/245.js} +0 -0
- /package/{273.js → esm/273.js} +0 -0
- /package/{60.js → esm/60.js} +0 -0
- /package/{689.js → esm/689.js} +0 -0
- /package/{changelog.js → esm/changelog.js} +0 -0
- /package/{index.js → esm/index.js} +0 -0
- /package/{markdownlint.js → esm/markdownlint.js} +0 -0
- /package/{remark.js → esm/remark.js} +0 -0
|
@@ -37,7 +37,12 @@ const checkCommand = Command.make("check", {
|
|
|
37
37
|
}, ({ dir })=>runCheck(dir)).pipe(Command.withDescription("Full changeset validation with summary"));
|
|
38
38
|
const CUSTOM_RULES_ENTRY = "@savvy-web/changesets/markdownlint";
|
|
39
39
|
const CHANGELOG_ENTRY = "@savvy-web/changesets/changelog";
|
|
40
|
-
const
|
|
40
|
+
const MARKDOWNLINT_CONFIG_PATHS = [
|
|
41
|
+
"lib/configs/.markdownlint-cli2.jsonc",
|
|
42
|
+
"lib/configs/.markdownlint-cli2.json",
|
|
43
|
+
".markdownlint-cli2.jsonc",
|
|
44
|
+
".markdownlint-cli2.json"
|
|
45
|
+
];
|
|
41
46
|
const RULE_NAMES = [
|
|
42
47
|
"changeset-heading-hierarchy",
|
|
43
48
|
"changeset-required-sections",
|
|
@@ -70,6 +75,7 @@ class InitError extends InitErrorBase {
|
|
|
70
75
|
const forceOption = Options.boolean("force").pipe(Options.withAlias("f"), Options.withDescription("Overwrite existing config files"), Options.withDefault(false));
|
|
71
76
|
const quietOption = Options.boolean("quiet").pipe(Options.withAlias("q"), Options.withDescription("Silence warnings, always exit 0"), Options.withDefault(false));
|
|
72
77
|
const markdownlintOption = Options.boolean("markdownlint").pipe(Options.withDescription("Register rules in base markdownlint config"), Options.withDefault(true));
|
|
78
|
+
const checkOption = Options.boolean("check").pipe(Options.withDescription("Check configuration without writing (for postinstall scripts)"), Options.withDefault(false));
|
|
73
79
|
function detectGitHubRepo(cwd) {
|
|
74
80
|
try {
|
|
75
81
|
const url = execSync("git remote get-url origin", {
|
|
@@ -89,6 +95,10 @@ function stripJsoncComments(text) {
|
|
|
89
95
|
function resolveWorkspaceRoot(cwd) {
|
|
90
96
|
return findProjectRoot(cwd) ?? cwd;
|
|
91
97
|
}
|
|
98
|
+
function findMarkdownlintConfig(root) {
|
|
99
|
+
for (const configPath of MARKDOWNLINT_CONFIG_PATHS)if (existsSync(join(root, configPath))) return configPath;
|
|
100
|
+
return null;
|
|
101
|
+
}
|
|
92
102
|
function ensureChangesetDir(root) {
|
|
93
103
|
return Effect["try"]({
|
|
94
104
|
try: ()=>{
|
|
@@ -140,19 +150,20 @@ function handleConfig(changesetDir, repoSlug, force) {
|
|
|
140
150
|
function handleBaseMarkdownlint(root) {
|
|
141
151
|
return Effect["try"]({
|
|
142
152
|
try: ()=>{
|
|
143
|
-
const
|
|
144
|
-
if (!
|
|
145
|
-
const
|
|
153
|
+
const foundPath = findMarkdownlintConfig(root);
|
|
154
|
+
if (!foundPath) return `Warning: no markdownlint config found (checked ${MARKDOWNLINT_CONFIG_PATHS.join(", ")})`;
|
|
155
|
+
const fullPath = join(root, foundPath);
|
|
156
|
+
const raw = readFileSync(fullPath, "utf-8");
|
|
146
157
|
const parsed = JSON.parse(stripJsoncComments(raw));
|
|
147
158
|
if (!Array.isArray(parsed.customRules)) parsed.customRules = [];
|
|
148
159
|
if (!parsed.customRules.includes(CUSTOM_RULES_ENTRY)) parsed.customRules.push(CUSTOM_RULES_ENTRY);
|
|
149
160
|
if ("object" != typeof parsed.config || null === parsed.config) parsed.config = {};
|
|
150
161
|
for (const rule of RULE_NAMES)if (!(rule in parsed.config)) parsed.config[rule] = false;
|
|
151
|
-
writeFileSync(
|
|
152
|
-
return
|
|
162
|
+
writeFileSync(fullPath, `${JSON.stringify(parsed, null, "\t")}\n`);
|
|
163
|
+
return `Updated ${foundPath}`;
|
|
153
164
|
},
|
|
154
165
|
catch: (error)=>new InitError({
|
|
155
|
-
step: "
|
|
166
|
+
step: "markdownlint config",
|
|
156
167
|
reason: error instanceof Error ? error.message : String(error)
|
|
157
168
|
})
|
|
158
169
|
});
|
|
@@ -161,10 +172,10 @@ function handleChangesetMarkdownlint(changesetDir, root, force) {
|
|
|
161
172
|
return Effect["try"]({
|
|
162
173
|
try: ()=>{
|
|
163
174
|
const mdlintPath = join(changesetDir, ".markdownlint.json");
|
|
164
|
-
const
|
|
175
|
+
const baseConfig = findMarkdownlintConfig(root);
|
|
165
176
|
if (force || !existsSync(mdlintPath)) {
|
|
166
177
|
const mdlintConfig = {};
|
|
167
|
-
if (
|
|
178
|
+
if (baseConfig) mdlintConfig.extends = `../${baseConfig}`;
|
|
168
179
|
mdlintConfig.default = false;
|
|
169
180
|
mdlintConfig.MD041 = false;
|
|
170
181
|
for (const rule of RULE_NAMES)mdlintConfig[rule] = true;
|
|
@@ -182,15 +193,131 @@ function handleChangesetMarkdownlint(changesetDir, root, force) {
|
|
|
182
193
|
})
|
|
183
194
|
});
|
|
184
195
|
}
|
|
196
|
+
function checkChangesetDir(root) {
|
|
197
|
+
const dir = join(root, ".changeset");
|
|
198
|
+
if (!existsSync(dir)) return [
|
|
199
|
+
{
|
|
200
|
+
file: ".changeset/",
|
|
201
|
+
message: "directory does not exist"
|
|
202
|
+
}
|
|
203
|
+
];
|
|
204
|
+
return [];
|
|
205
|
+
}
|
|
206
|
+
function checkConfig(changesetDir, repoSlug) {
|
|
207
|
+
const configPath = join(changesetDir, "config.json");
|
|
208
|
+
if (!existsSync(configPath)) return [
|
|
209
|
+
{
|
|
210
|
+
file: ".changeset/config.json",
|
|
211
|
+
message: "file does not exist"
|
|
212
|
+
}
|
|
213
|
+
];
|
|
214
|
+
try {
|
|
215
|
+
const config = JSON.parse(readFileSync(configPath, "utf-8"));
|
|
216
|
+
const issues = [];
|
|
217
|
+
const changelog = config.changelog;
|
|
218
|
+
const entry = Array.isArray(changelog) ? changelog[0] : changelog;
|
|
219
|
+
const repo = Array.isArray(changelog) ? changelog[1]?.repo : void 0;
|
|
220
|
+
if (entry !== CHANGELOG_ENTRY) issues.push({
|
|
221
|
+
file: ".changeset/config.json",
|
|
222
|
+
message: `changelog formatter is "${entry}", expected "${CHANGELOG_ENTRY}"`
|
|
223
|
+
});
|
|
224
|
+
else if (repo !== repoSlug) issues.push({
|
|
225
|
+
file: ".changeset/config.json",
|
|
226
|
+
message: `changelog repo is "${repo ?? "(not set)"}", expected "${repoSlug}"`
|
|
227
|
+
});
|
|
228
|
+
return issues;
|
|
229
|
+
} catch {
|
|
230
|
+
return [
|
|
231
|
+
{
|
|
232
|
+
file: ".changeset/config.json",
|
|
233
|
+
message: "could not parse file"
|
|
234
|
+
}
|
|
235
|
+
];
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
function checkBaseMarkdownlint(root) {
|
|
239
|
+
const foundPath = findMarkdownlintConfig(root);
|
|
240
|
+
if (!foundPath) return [
|
|
241
|
+
{
|
|
242
|
+
file: "markdownlint config",
|
|
243
|
+
message: `not found (checked ${MARKDOWNLINT_CONFIG_PATHS.join(", ")})`
|
|
244
|
+
}
|
|
245
|
+
];
|
|
246
|
+
try {
|
|
247
|
+
const raw = readFileSync(join(root, foundPath), "utf-8");
|
|
248
|
+
const parsed = JSON.parse(stripJsoncComments(raw));
|
|
249
|
+
const issues = [];
|
|
250
|
+
if (!Array.isArray(parsed.customRules) || !parsed.customRules.includes(CUSTOM_RULES_ENTRY)) issues.push({
|
|
251
|
+
file: foundPath,
|
|
252
|
+
message: `customRules does not include ${CUSTOM_RULES_ENTRY}`
|
|
253
|
+
});
|
|
254
|
+
const config = parsed.config;
|
|
255
|
+
if ("object" != typeof config || null === config) issues.push({
|
|
256
|
+
file: foundPath,
|
|
257
|
+
message: "config section is missing"
|
|
258
|
+
});
|
|
259
|
+
else for (const rule of RULE_NAMES)if (!(rule in config)) issues.push({
|
|
260
|
+
file: foundPath,
|
|
261
|
+
message: `rule "${rule}" is not configured`
|
|
262
|
+
});
|
|
263
|
+
return issues;
|
|
264
|
+
} catch {
|
|
265
|
+
return [
|
|
266
|
+
{
|
|
267
|
+
file: foundPath,
|
|
268
|
+
message: "could not parse file"
|
|
269
|
+
}
|
|
270
|
+
];
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
function checkChangesetMarkdownlint(changesetDir) {
|
|
274
|
+
const mdlintPath = join(changesetDir, ".markdownlint.json");
|
|
275
|
+
if (!existsSync(mdlintPath)) return [
|
|
276
|
+
{
|
|
277
|
+
file: ".changeset/.markdownlint.json",
|
|
278
|
+
message: "file does not exist"
|
|
279
|
+
}
|
|
280
|
+
];
|
|
281
|
+
try {
|
|
282
|
+
const existing = JSON.parse(readFileSync(mdlintPath, "utf-8"));
|
|
283
|
+
const issues = [];
|
|
284
|
+
for (const rule of RULE_NAMES)if (true !== existing[rule]) issues.push({
|
|
285
|
+
file: ".changeset/.markdownlint.json",
|
|
286
|
+
message: `rule "${rule}" is not enabled`
|
|
287
|
+
});
|
|
288
|
+
return issues;
|
|
289
|
+
} catch {
|
|
290
|
+
return [
|
|
291
|
+
{
|
|
292
|
+
file: ".changeset/.markdownlint.json",
|
|
293
|
+
message: "could not parse file"
|
|
294
|
+
}
|
|
295
|
+
];
|
|
296
|
+
}
|
|
297
|
+
}
|
|
185
298
|
const initCommand = Command.make("init", {
|
|
186
299
|
force: forceOption,
|
|
187
300
|
quiet: quietOption,
|
|
188
|
-
markdownlint: markdownlintOption
|
|
189
|
-
|
|
301
|
+
markdownlint: markdownlintOption,
|
|
302
|
+
check: checkOption
|
|
303
|
+
}, ({ force, quiet, markdownlint, check })=>Effect.gen(function*() {
|
|
190
304
|
const root = resolveWorkspaceRoot(process.cwd());
|
|
191
305
|
const repo = detectGitHubRepo(root);
|
|
192
306
|
if (!repo && !quiet) yield* Effect.log("Warning: could not detect GitHub repo from git remote, using placeholder");
|
|
193
307
|
const repoSlug = repo ?? "owner/repo";
|
|
308
|
+
if (check) {
|
|
309
|
+
const changesetDir = join(root, ".changeset");
|
|
310
|
+
const issues = [
|
|
311
|
+
...checkChangesetDir(root),
|
|
312
|
+
...checkConfig(changesetDir, repoSlug),
|
|
313
|
+
...markdownlint ? checkBaseMarkdownlint(root) : [],
|
|
314
|
+
...checkChangesetMarkdownlint(changesetDir)
|
|
315
|
+
];
|
|
316
|
+
if (0 === issues.length) return void (yield* Effect.log("All @savvy-web/changesets config files are up to date."));
|
|
317
|
+
for (const issue of issues)yield* Effect.logWarning(`${issue.file}: ${issue.message}`);
|
|
318
|
+
yield* Effect.logWarning('Run "savvy-changesets init --force" to fix.');
|
|
319
|
+
return;
|
|
320
|
+
}
|
|
194
321
|
const changesetDir = yield* ensureChangesetDir(root);
|
|
195
322
|
yield* Effect.log("Ensured .changeset/ directory");
|
|
196
323
|
const errors = [];
|
|
@@ -199,9 +326,8 @@ const initCommand = Command.make("init", {
|
|
|
199
326
|
else errors.push(configResult.left);
|
|
200
327
|
if (markdownlint) {
|
|
201
328
|
const baseResult = yield* handleBaseMarkdownlint(root).pipe(Effect.either);
|
|
202
|
-
if ("Right" === baseResult._tag)
|
|
203
|
-
|
|
204
|
-
} else errors.push(baseResult.left);
|
|
329
|
+
if ("Right" === baseResult._tag) yield* Effect.log(baseResult.right);
|
|
330
|
+
else errors.push(baseResult.left);
|
|
205
331
|
}
|
|
206
332
|
const mdlintResult = yield* handleChangesetMarkdownlint(changesetDir, root, force).pipe(Effect.either);
|
|
207
333
|
if ("Right" === mdlintResult._tag) yield* Effect.log(mdlintResult.right);
|
|
@@ -239,7 +365,7 @@ const fileArg = Args.file({
|
|
|
239
365
|
name: "file"
|
|
240
366
|
}).pipe(Args.withDefault("CHANGELOG.md"));
|
|
241
367
|
const dryRunOption = Options.boolean("dry-run").pipe(Options.withAlias("n"), Options.withDescription("Print transformed output instead of writing"), Options.withDefault(false));
|
|
242
|
-
const
|
|
368
|
+
const transform_checkOption = Options.boolean("check").pipe(Options.withAlias("c"), Options.withDescription("Exit 1 if file would change (for CI)"), Options.withDefault(false));
|
|
243
369
|
function runTransform(file, dryRun, check) {
|
|
244
370
|
return Effect.gen(function*() {
|
|
245
371
|
const resolved = resolve(file);
|
|
@@ -260,7 +386,7 @@ function runTransform(file, dryRun, check) {
|
|
|
260
386
|
const transformCommand = Command.make("transform", {
|
|
261
387
|
file: fileArg,
|
|
262
388
|
dryRun: dryRunOption,
|
|
263
|
-
check:
|
|
389
|
+
check: transform_checkOption
|
|
264
390
|
}, ({ file, dryRun, check })=>runTransform(file, dryRun, check)).pipe(Command.withDescription("Post-process CHANGELOG.md"));
|
|
265
391
|
class Workspace {
|
|
266
392
|
static detectPackageManager(cwd = process.cwd()) {
|
|
@@ -366,7 +492,7 @@ const rootCommand = Command.make("savvy-changesets").pipe(Command.withSubcommand
|
|
|
366
492
|
]));
|
|
367
493
|
const cli = Command.run(rootCommand, {
|
|
368
494
|
name: "savvy-changesets",
|
|
369
|
-
version: "0.1.
|
|
495
|
+
version: "0.1.1"
|
|
370
496
|
});
|
|
371
497
|
function runCli() {
|
|
372
498
|
const main = Effect.suspend(()=>cli(process.argv)).pipe(Effect.provide(NodeContext.layer));
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Changesets API changelog formatter.
|
|
3
|
+
*
|
|
4
|
+
* This module exports the `ChangelogFunctions` required by the Changesets API.
|
|
5
|
+
* Configure in `.changeset/config.json`:
|
|
6
|
+
*
|
|
7
|
+
* ```json
|
|
8
|
+
* {
|
|
9
|
+
* "changelog": ["\@savvy-web/changesets/changelog", { "repo": "savvy-web/package-name" }]
|
|
10
|
+
* }
|
|
11
|
+
* ```
|
|
12
|
+
*
|
|
13
|
+
* @packageDocumentation
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import { ChangelogFunctions } from '@changesets/types';
|
|
17
|
+
|
|
18
|
+
declare const changelogFunctions: ChangelogFunctions;
|
|
19
|
+
export default changelogFunctions;
|
|
20
|
+
|
|
21
|
+
export { }
|