@savvy-web/changesets 0.4.2 → 0.5.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/README.md +16 -0
- package/cjs/changelog.cjs +131 -36
- package/cjs/changelog.d.cts +52 -3
- package/cjs/index.cjs +262 -42
- package/cjs/index.d.cts +1726 -175
- package/cjs/markdownlint.cjs +156 -2
- package/cjs/markdownlint.d.cts +127 -21
- package/cjs/remark.cjs +225 -9
- package/cjs/remark.d.cts +106 -37
- package/esm/160.js +45 -39
- package/esm/260.js +2 -1
- package/esm/273.js +2 -1
- package/esm/622.js +2 -2
- package/esm/{795.js → 725.js} +2 -5
- package/esm/855.js +5 -0
- package/esm/891.js +147 -0
- package/esm/bin/savvy-changesets.js +5 -3
- package/esm/changelog.d.ts +52 -3
- package/esm/index.d.ts +1726 -175
- package/esm/index.js +27 -5
- package/esm/markdownlint.d.ts +127 -21
- package/esm/markdownlint.js +152 -2
- package/esm/remark.d.ts +106 -37
- package/esm/remark.js +76 -3
- package/package.json +1 -1
- package/esm/689.js +0 -1
package/cjs/remark.d.cts
CHANGED
|
@@ -1,7 +1,54 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* \@savvy-web/changesets/remark
|
|
3
3
|
*
|
|
4
|
-
*
|
|
4
|
+
* Remark plugins for changeset validation and CHANGELOG transformation.
|
|
5
|
+
*
|
|
6
|
+
* This entry point re-exports all lint rules, transform plugins, and presets
|
|
7
|
+
* from a single import path. The exports are organized into three groups:
|
|
8
|
+
*
|
|
9
|
+
* **Lint rules** validate changeset markdown structure before changelog generation:
|
|
10
|
+
* - {@link HeadingHierarchyRule} (CSH001) -- heading depth and ordering
|
|
11
|
+
* - {@link RequiredSectionsRule} (CSH002) -- recognized section headings
|
|
12
|
+
* - {@link ContentStructureRule} (CSH003) -- non-empty sections, code fences, list items
|
|
13
|
+
* - {@link UncategorizedContentRule} (CSH004) -- content before the first heading
|
|
14
|
+
* - {@link DependencyTableFormatRule} (CSH005) -- dependency table schema compliance
|
|
15
|
+
*
|
|
16
|
+
* **Transform plugins** normalize and clean up generated CHANGELOG markdown:
|
|
17
|
+
* - {@link AggregateDependencyTablesPlugin} -- merge duplicate dependency sections
|
|
18
|
+
* - {@link MergeSectionsPlugin} -- merge duplicate h3 section headings
|
|
19
|
+
* - {@link ReorderSectionsPlugin} -- sort sections by category priority
|
|
20
|
+
* - {@link DeduplicateItemsPlugin} -- remove duplicate list items
|
|
21
|
+
* - {@link ContributorFootnotesPlugin} -- aggregate contributor attributions
|
|
22
|
+
* - {@link IssueLinkRefsPlugin} -- convert inline issue links to reference-style
|
|
23
|
+
* - {@link NormalizeFormatPlugin} -- remove empty sections and lists
|
|
24
|
+
*
|
|
25
|
+
* **Presets** bundle related rules or plugins for convenient consumption:
|
|
26
|
+
* - {@link SilkChangesetPreset} -- all five lint rules
|
|
27
|
+
* - {@link SilkChangesetTransformPreset} -- all seven transform plugins in execution order
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* ```typescript
|
|
31
|
+
* import {
|
|
32
|
+
* SilkChangesetPreset,
|
|
33
|
+
* SilkChangesetTransformPreset,
|
|
34
|
+
* } from "\@savvy-web/changesets/remark";
|
|
35
|
+
* import remarkParse from "remark-parse";
|
|
36
|
+
* import remarkStringify from "remark-stringify";
|
|
37
|
+
* import { unified } from "unified";
|
|
38
|
+
*
|
|
39
|
+
* // Lint a changeset file
|
|
40
|
+
* const linter = unified().use(remarkParse);
|
|
41
|
+
* for (const rule of SilkChangesetPreset) {
|
|
42
|
+
* linter.use(rule);
|
|
43
|
+
* }
|
|
44
|
+
*
|
|
45
|
+
* // Transform a CHANGELOG
|
|
46
|
+
* const transformer = unified().use(remarkParse);
|
|
47
|
+
* for (const plugin of SilkChangesetTransformPreset) {
|
|
48
|
+
* transformer.use(plugin);
|
|
49
|
+
* }
|
|
50
|
+
* transformer.use(remarkStringify);
|
|
51
|
+
* ```
|
|
5
52
|
*
|
|
6
53
|
* @packageDocumentation
|
|
7
54
|
*/
|
|
@@ -10,46 +57,24 @@ import { Plugin } from 'unified';
|
|
|
10
57
|
import { Plugin as Plugin_2 } from 'unified-lint-rule';
|
|
11
58
|
import { Root } from 'mdast';
|
|
12
59
|
|
|
60
|
+
export declare const AggregateDependencyTablesPlugin: Plugin<[], Root>;
|
|
61
|
+
|
|
13
62
|
export declare const ContentStructureRule: Plugin_2<Root, unknown>;
|
|
14
63
|
|
|
15
|
-
/**
|
|
16
|
-
* Extract inline contributor attributions and aggregate them into
|
|
17
|
-
* a summary paragraph at the end of each version block.
|
|
18
|
-
*/
|
|
19
64
|
export declare const ContributorFootnotesPlugin: Plugin<[], Root>;
|
|
20
65
|
|
|
21
|
-
/**
|
|
22
|
-
* Remove duplicate list items within each h3 section.
|
|
23
|
-
*
|
|
24
|
-
* Items are compared by their plain text content. If a list becomes
|
|
25
|
-
* empty after deduplication, it is removed from the tree.
|
|
26
|
-
*/
|
|
27
66
|
export declare const DeduplicateItemsPlugin: Plugin<[], Root>;
|
|
28
67
|
|
|
68
|
+
export declare const DependencyTableFormatRule: Plugin_2<Root, unknown>;
|
|
69
|
+
|
|
29
70
|
export declare const HeadingHierarchyRule: Plugin_2<Root, unknown>;
|
|
30
71
|
|
|
31
|
-
/**
|
|
32
|
-
* Convert inline issue links to reference-style links with definitions
|
|
33
|
-
* at the end of each version block.
|
|
34
|
-
*/
|
|
35
72
|
export declare const IssueLinkRefsPlugin: Plugin<[], Root>;
|
|
36
73
|
|
|
37
|
-
/**
|
|
38
|
-
* Merge duplicate h3 sections within each version block.
|
|
39
|
-
*
|
|
40
|
-
* Groups sections by heading text (case-insensitive via `fromHeading`),
|
|
41
|
-
* keeps the first occurrence, and splices content from duplicates into it.
|
|
42
|
-
*/
|
|
43
74
|
export declare const MergeSectionsPlugin: Plugin<[], Root>;
|
|
44
75
|
|
|
45
|
-
/**
|
|
46
|
-
* Remove empty sections and empty lists from the document.
|
|
47
|
-
*/
|
|
48
76
|
export declare const NormalizeFormatPlugin: Plugin<[], Root>;
|
|
49
77
|
|
|
50
|
-
/**
|
|
51
|
-
* Reorder h3 sections within each version block by category priority.
|
|
52
|
-
*/
|
|
53
78
|
export declare const ReorderSectionsPlugin: Plugin<[], Root>;
|
|
54
79
|
|
|
55
80
|
export declare const RequiredSectionsRule: Plugin_2<Root, unknown>;
|
|
@@ -57,37 +82,81 @@ export declare const RequiredSectionsRule: Plugin_2<Root, unknown>;
|
|
|
57
82
|
/**
|
|
58
83
|
* Preset combining all changeset lint rules for convenient consumption.
|
|
59
84
|
*
|
|
85
|
+
* @remarks
|
|
86
|
+
* Includes the following rules in order:
|
|
87
|
+
*
|
|
88
|
+
* 1. {@link HeadingHierarchyRule} (CSH001) -- no h1, no depth skips
|
|
89
|
+
* 2. {@link RequiredSectionsRule} (CSH002) -- h2 headings must match a known category
|
|
90
|
+
* 3. {@link ContentStructureRule} (CSH003) -- non-empty sections, code fence languages, non-empty list items
|
|
91
|
+
* 4. {@link UncategorizedContentRule} (CSH004) -- no content before the first h2 heading
|
|
92
|
+
* 5. {@link DependencyTableFormatRule} (CSH005) -- dependency table column/value validation
|
|
93
|
+
*
|
|
94
|
+
* Rule execution order is not significant for lint rules; all rules run
|
|
95
|
+
* independently over the same AST and report warnings to the virtual file.
|
|
96
|
+
*
|
|
60
97
|
* @example
|
|
61
98
|
* ```typescript
|
|
62
99
|
* import { SilkChangesetPreset } from "\@savvy-web/changesets/remark";
|
|
63
100
|
* import remarkParse from "remark-parse";
|
|
64
101
|
* import { unified } from "unified";
|
|
102
|
+
* import { read } from "to-vfile";
|
|
65
103
|
*
|
|
66
104
|
* const processor = unified().use(remarkParse);
|
|
67
105
|
* for (const rule of SilkChangesetPreset) {
|
|
68
106
|
* processor.use(rule);
|
|
69
107
|
* }
|
|
108
|
+
*
|
|
109
|
+
* const file = await read("changeset.md");
|
|
110
|
+
* const result = await processor.process(file);
|
|
111
|
+
* console.log(result.messages); // lint warnings
|
|
70
112
|
* ```
|
|
71
113
|
*
|
|
114
|
+
* @see {@link SilkChangesetTransformPreset} for the corresponding transform preset
|
|
115
|
+
*
|
|
72
116
|
* @public
|
|
73
117
|
*/
|
|
74
|
-
export declare const SilkChangesetPreset: readonly [Plugin_2<Root, unknown>, Plugin_2<Root, unknown>, Plugin_2<Root, unknown>, Plugin_2<Root, unknown>];
|
|
118
|
+
export declare const SilkChangesetPreset: readonly [Plugin_2<Root, unknown>, Plugin_2<Root, unknown>, Plugin_2<Root, unknown>, Plugin_2<Root, unknown>, Plugin_2<Root, unknown>];
|
|
75
119
|
|
|
76
120
|
/**
|
|
77
121
|
* Ordered array of all transform plugins in the correct execution order.
|
|
78
122
|
*
|
|
79
123
|
* @remarks
|
|
80
|
-
* Plugin ordering is significant
|
|
81
|
-
*
|
|
82
|
-
*
|
|
83
|
-
*
|
|
84
|
-
*
|
|
85
|
-
*
|
|
86
|
-
*
|
|
124
|
+
* Plugin ordering is significant -- each plugin may depend on the output of
|
|
125
|
+
* earlier plugins in the pipeline:
|
|
126
|
+
*
|
|
127
|
+
* 1. {@link AggregateDependencyTablesPlugin} -- merge duplicate dependency sections (must run first so downstream plugins see a single Dependencies section)
|
|
128
|
+
* 2. {@link MergeSectionsPlugin} -- merge duplicate h3 headings (must run before reorder so that priority is computed on consolidated sections)
|
|
129
|
+
* 3. {@link ReorderSectionsPlugin} -- sort sections by category priority (Breaking Changes first, Other last)
|
|
130
|
+
* 4. {@link DeduplicateItemsPlugin} -- remove duplicate list items within each section
|
|
131
|
+
* 5. {@link ContributorFootnotesPlugin} -- extract inline `Thanks \@user!` attributions and aggregate them into a summary paragraph per version block
|
|
132
|
+
* 6. {@link IssueLinkRefsPlugin} -- convert inline `[#N](url)` links to reference-style `[#N]` with definitions at the end of each version block
|
|
133
|
+
* 7. {@link NormalizeFormatPlugin} -- final cleanup removing empty sections and empty lists
|
|
134
|
+
*
|
|
135
|
+
* @example
|
|
136
|
+
* ```typescript
|
|
137
|
+
* import { SilkChangesetTransformPreset } from "\@savvy-web/changesets/remark";
|
|
138
|
+
* import remarkGfm from "remark-gfm";
|
|
139
|
+
* import remarkParse from "remark-parse";
|
|
140
|
+
* import remarkStringify from "remark-stringify";
|
|
141
|
+
* import { unified } from "unified";
|
|
142
|
+
* import { read } from "to-vfile";
|
|
143
|
+
*
|
|
144
|
+
* const processor = unified().use(remarkParse).use(remarkGfm);
|
|
145
|
+
* for (const plugin of SilkChangesetTransformPreset) {
|
|
146
|
+
* processor.use(plugin);
|
|
147
|
+
* }
|
|
148
|
+
* processor.use(remarkStringify);
|
|
149
|
+
*
|
|
150
|
+
* const file = await read("CHANGELOG.md");
|
|
151
|
+
* const result = await processor.process(file);
|
|
152
|
+
* console.log(String(result));
|
|
153
|
+
* ```
|
|
154
|
+
*
|
|
155
|
+
* @see {@link SilkChangesetPreset} for the corresponding lint preset
|
|
87
156
|
*
|
|
88
157
|
* @public
|
|
89
158
|
*/
|
|
90
|
-
export declare const SilkChangesetTransformPreset: readonly [Plugin<[], Root>, Plugin<[], Root>, Plugin<[], Root>, Plugin<[], Root>, Plugin<[], Root>, Plugin<[], Root>];
|
|
159
|
+
export declare const SilkChangesetTransformPreset: readonly [Plugin<[], Root>, Plugin<[], Root>, Plugin<[], Root>, Plugin<[], Root>, Plugin<[], Root>, Plugin<[], Root>, Plugin<[], Root>];
|
|
91
160
|
|
|
92
161
|
export declare const UncategorizedContentRule: Plugin_2<Root, unknown>;
|
|
93
162
|
|
package/esm/160.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { getInfo } from "@changesets/get-github-info";
|
|
2
|
-
import { Layer, unified, Schema, remark_stringify, Effect,
|
|
3
|
-
import {
|
|
2
|
+
import { Layer, unified, Schema, external_mdast_util_to_string_toString, remark_stringify, Effect, remark_gfm, Context } from "./855.js";
|
|
3
|
+
import { GitHubApiError, VersionFilesSchema, ConfigurationError, remark_parse } from "./725.js";
|
|
4
|
+
import { PositiveInteger, serializeDependencyTableToMarkdown } from "./891.js";
|
|
4
5
|
import { resolveCommitType, fromHeading } from "./60.js";
|
|
5
6
|
const REPO_PATTERN = /^[a-zA-Z0-9._-]+\/[a-zA-Z0-9._-]+$/;
|
|
6
7
|
const RepoSchema = Schema.String.pipe(Schema.pattern(REPO_PATTERN, {
|
|
@@ -87,44 +88,44 @@ const MarkdownLive = Layer.succeed(MarkdownService, {
|
|
|
87
88
|
parse: (content)=>Effect.sync(()=>parseMarkdown(content)),
|
|
88
89
|
stringify: (tree)=>Effect.sync(()=>stringifyMarkdown(tree))
|
|
89
90
|
});
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
91
|
+
const FIELD_MAP = [
|
|
92
|
+
[
|
|
93
|
+
"dependencies",
|
|
94
|
+
"dependency"
|
|
95
|
+
],
|
|
96
|
+
[
|
|
97
|
+
"devDependencies",
|
|
98
|
+
"devDependency"
|
|
99
|
+
],
|
|
100
|
+
[
|
|
101
|
+
"peerDependencies",
|
|
102
|
+
"peerDependency"
|
|
103
|
+
],
|
|
104
|
+
[
|
|
105
|
+
"optionalDependencies",
|
|
106
|
+
"optionalDependency"
|
|
107
|
+
]
|
|
108
|
+
];
|
|
109
|
+
function inferDependencyType(dep) {
|
|
110
|
+
const pkg = dep.packageJson;
|
|
111
|
+
for (const [field, type] of FIELD_MAP){
|
|
112
|
+
const section = pkg[field];
|
|
113
|
+
if ("object" == typeof section && null !== section && dep.name in section) return type;
|
|
114
|
+
}
|
|
115
|
+
return "dependency";
|
|
96
116
|
}
|
|
97
|
-
function getDependencyReleaseLine(
|
|
117
|
+
function getDependencyReleaseLine(_changesets, dependenciesUpdated, _options) {
|
|
98
118
|
return Effect.gen(function*() {
|
|
99
119
|
if (0 === dependenciesUpdated.length) return "";
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
commit,
|
|
108
|
-
repo: options.repo
|
|
109
|
-
}).pipe(Effect.map((info)=>info.links.commit), Effect.catchAll((error)=>{
|
|
110
|
-
apiFailures++;
|
|
111
|
-
logWarning(`Failed to fetch GitHub info for commit ${commit}:`, String(error));
|
|
112
|
-
return Effect.succeed(`[\`${commit.substring(0, 7)}\`](https://github.com/${options.repo}/commit/${commit})`);
|
|
120
|
+
yield* GitHubService;
|
|
121
|
+
const rows = dependenciesUpdated.map((dep)=>({
|
|
122
|
+
dependency: dep.name,
|
|
123
|
+
type: inferDependencyType(dep),
|
|
124
|
+
action: "updated",
|
|
125
|
+
from: dep.oldVersion,
|
|
126
|
+
to: dep.newVersion
|
|
113
127
|
}));
|
|
114
|
-
|
|
115
|
-
concurrency: 10
|
|
116
|
-
});
|
|
117
|
-
if (apiFailures > 0) {
|
|
118
|
-
const successRate = ((totalWithCommit - apiFailures) / totalWithCommit * 100).toFixed(1);
|
|
119
|
-
logWarning(`GitHub API calls completed with ${apiFailures}/${totalWithCommit} failures (${successRate}% success rate)`);
|
|
120
|
-
}
|
|
121
|
-
const validLinks = commitLinks.filter(Boolean);
|
|
122
|
-
const changesetLink = validLinks.length > 0 ? `- Updated dependencies [${validLinks.join(", ")}]:` : "- Updated dependencies:";
|
|
123
|
-
const updatedDependenciesList = dependenciesUpdated.map((dep)=>` - ${dep.name}@${dep.newVersion}`);
|
|
124
|
-
return [
|
|
125
|
-
changesetLink,
|
|
126
|
-
...updatedDependenciesList
|
|
127
|
-
].join("\n");
|
|
128
|
+
return serializeDependencyTableToMarkdown(rows);
|
|
128
129
|
});
|
|
129
130
|
}
|
|
130
131
|
const MARKDOWN_LINK_PATTERN = /\[([^\]]+)\]\(([^)]+)\)/;
|
|
@@ -132,8 +133,6 @@ function extractUrlFromMarkdown(linkOrUrl) {
|
|
|
132
133
|
const match = MARKDOWN_LINK_PATTERN.exec(linkOrUrl);
|
|
133
134
|
return match ? match[2] : linkOrUrl;
|
|
134
135
|
}
|
|
135
|
-
const NonEmptyString = Schema.String.pipe(Schema.minLength(1));
|
|
136
|
-
const PositiveInteger = Schema.Number.pipe(Schema.int(), Schema.positive());
|
|
137
136
|
function isValidUrl(value) {
|
|
138
137
|
try {
|
|
139
138
|
new URL(value);
|
|
@@ -202,6 +201,13 @@ function parseIssueReferences(commitMessage) {
|
|
|
202
201
|
refs: extractIssueNumbers(REFS_ISSUE_PATTERN, commitMessage)
|
|
203
202
|
};
|
|
204
203
|
}
|
|
204
|
+
function logWarning(message, ...args) {
|
|
205
|
+
if ("u" > typeof process && process.env.VITEST) return;
|
|
206
|
+
if ("u" > typeof process && "true" === process.env.GITHUB_ACTIONS) {
|
|
207
|
+
const text = args.length > 0 ? `${message} ${args.join(" ")}` : message;
|
|
208
|
+
console.warn(`::warning::${text}`);
|
|
209
|
+
} else console.warn(message, ...args);
|
|
210
|
+
}
|
|
205
211
|
function parseChangesetSections(summary) {
|
|
206
212
|
const tree = parseMarkdown(summary);
|
|
207
213
|
const h2Indices = [];
|
|
@@ -368,4 +374,4 @@ const changelogFunctions = {
|
|
|
368
374
|
};
|
|
369
375
|
const changelog = changelogFunctions;
|
|
370
376
|
export default changelog;
|
|
371
|
-
export { ChangesetOptionsSchema, GitHubInfoSchema, GitHubLive, GitHubService, GitHubServiceBase, IssueNumberSchema, MarkdownLive, MarkdownService, MarkdownServiceBase,
|
|
377
|
+
export { ChangesetOptionsSchema, GitHubInfoSchema, GitHubLive, GitHubService, GitHubServiceBase, IssueNumberSchema, MarkdownLive, MarkdownService, MarkdownServiceBase, RepoSchema, UrlOrMarkdownLinkSchema, UsernameSchema, makeGitHubTest };
|
package/esm/260.js
CHANGED
package/esm/273.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { existsSync, mkdirSync, readFileSync, readdirSync, writeFileSync } from "node:fs";
|
|
2
2
|
import { join, relative, resolve } from "node:path";
|
|
3
|
-
import {
|
|
3
|
+
import { remark_parse } from "./725.js";
|
|
4
|
+
import { unified, remark_stringify, remark_gfm } from "./855.js";
|
|
4
5
|
import { UncategorizedContentRule, MergeSectionsPlugin, DeduplicateItemsPlugin, IssueLinkRefsPlugin, ContentStructureRule, HeadingHierarchyRule, NormalizeFormatPlugin, ReorderSectionsPlugin, ContributorFootnotesPlugin, RequiredSectionsRule } from "./622.js";
|
|
5
6
|
function stripFrontmatter(content) {
|
|
6
7
|
return content.replace(/^---\n[\s\S]*?\n---\n?/, "");
|
package/esm/622.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { lintRule } from "unified-lint-rule";
|
|
2
2
|
import { SKIP, visit } from "unist-util-visit";
|
|
3
|
-
import { external_mdast_util_to_string_toString } from "./
|
|
3
|
+
import { external_mdast_util_to_string_toString } from "./855.js";
|
|
4
4
|
import { RULE_DOCS } from "./260.js";
|
|
5
5
|
import { isValidHeading, fromHeading, allHeadings } from "./60.js";
|
|
6
6
|
const ContentStructureRule = lintRule("remark-lint:changeset-content-structure", (tree, file)=>{
|
|
@@ -348,4 +348,4 @@ const ReorderSectionsPlugin = ()=>(tree)=>{
|
|
|
348
348
|
tree.children.splice(block.startIndex, blockLength, ...newChildren);
|
|
349
349
|
}
|
|
350
350
|
};
|
|
351
|
-
export { ContentStructureRule, ContributorFootnotesPlugin, DeduplicateItemsPlugin, HeadingHierarchyRule, IssueLinkRefsPlugin, MergeSectionsPlugin, NormalizeFormatPlugin, ReorderSectionsPlugin, RequiredSectionsRule, UncategorizedContentRule };
|
|
351
|
+
export { ContentStructureRule, ContributorFootnotesPlugin, DeduplicateItemsPlugin, HeadingHierarchyRule, IssueLinkRefsPlugin, MergeSectionsPlugin, NormalizeFormatPlugin, ReorderSectionsPlugin, RequiredSectionsRule, UncategorizedContentRule, getBlockSections, getHeadingText, getVersionBlocks, lintRule, visit };
|
package/esm/{795.js → 725.js}
RENAMED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Data, Schema } from "./855.js";
|
|
2
2
|
const ChangesetValidationErrorBase = Data.TaggedError("ChangesetValidationError");
|
|
3
3
|
class ChangesetValidationError extends ChangesetValidationErrorBase {
|
|
4
4
|
get message() {
|
|
@@ -49,8 +49,5 @@ const VersionFileConfigSchema = Schema.Struct({
|
|
|
49
49
|
paths: Schema.optional(Schema.Array(JsonPathSchema))
|
|
50
50
|
});
|
|
51
51
|
const VersionFilesSchema = Schema.Array(VersionFileConfigSchema);
|
|
52
|
-
export { default as remark_gfm } from "remark-gfm";
|
|
53
52
|
export { default as remark_parse } from "remark-parse";
|
|
54
|
-
export {
|
|
55
|
-
export { unified } from "unified";
|
|
56
|
-
export { ChangesetValidationError, ChangesetValidationErrorBase, ConfigurationError, ConfigurationErrorBase, Context, Data, Effect, GitHubApiError, GitHubApiErrorBase, JsonPathSchema, Layer, MarkdownParseError, MarkdownParseErrorBase, Schema, VersionFileConfigSchema, VersionFileError, VersionFileErrorBase, VersionFilesSchema };
|
|
53
|
+
export { ChangesetValidationError, ChangesetValidationErrorBase, ConfigurationError, ConfigurationErrorBase, GitHubApiError, GitHubApiErrorBase, JsonPathSchema, MarkdownParseError, MarkdownParseErrorBase, VersionFileConfigSchema, VersionFileError, VersionFileErrorBase, VersionFilesSchema };
|
package/esm/855.js
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { Context, Data, Effect, Layer, Schema } from "effect";
|
|
2
|
+
export { default as remark_gfm } from "remark-gfm";
|
|
3
|
+
export { default as remark_stringify } from "remark-stringify";
|
|
4
|
+
export { unified } from "unified";
|
|
5
|
+
export { toString as external_mdast_util_to_string_toString } from "mdast-util-to-string";
|
package/esm/891.js
ADDED
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import { external_mdast_util_to_string_toString, unified, Schema, remark_gfm, remark_stringify } from "./855.js";
|
|
2
|
+
const NonEmptyString = Schema.String.pipe(Schema.minLength(1));
|
|
3
|
+
const PositiveInteger = Schema.Number.pipe(Schema.int(), Schema.positive());
|
|
4
|
+
const DependencyActionSchema = Schema.Literal("added", "updated", "removed");
|
|
5
|
+
const DependencyTableTypeSchema = Schema.Literal("dependency", "devDependency", "peerDependency", "optionalDependency", "workspace", "config");
|
|
6
|
+
const VersionOrEmptySchema = Schema.String.pipe(Schema.pattern(/^(\u2014|[~^]?\d+\.\d+\.\d+(?:[-+.][\w.+-]*)?)$/));
|
|
7
|
+
const DependencyTableRowSchema = Schema.Struct({
|
|
8
|
+
dependency: NonEmptyString,
|
|
9
|
+
type: DependencyTableTypeSchema,
|
|
10
|
+
action: DependencyActionSchema,
|
|
11
|
+
from: VersionOrEmptySchema,
|
|
12
|
+
to: VersionOrEmptySchema
|
|
13
|
+
});
|
|
14
|
+
const DependencyTableSchema = Schema.Array(DependencyTableRowSchema).pipe(Schema.minItems(1));
|
|
15
|
+
const COLUMN_HEADERS = [
|
|
16
|
+
"Dependency",
|
|
17
|
+
"Type",
|
|
18
|
+
"Action",
|
|
19
|
+
"From",
|
|
20
|
+
"To"
|
|
21
|
+
];
|
|
22
|
+
const COLUMN_KEYS = [
|
|
23
|
+
"dependency",
|
|
24
|
+
"type",
|
|
25
|
+
"action",
|
|
26
|
+
"from",
|
|
27
|
+
"to"
|
|
28
|
+
];
|
|
29
|
+
const decode = Schema.decodeUnknownSync(DependencyTableRowSchema);
|
|
30
|
+
function parseDependencyTable(table) {
|
|
31
|
+
const rows = table.children;
|
|
32
|
+
if (rows.length < 2) throw new Error("Dependency table must have at least one data row");
|
|
33
|
+
const headerRow = rows[0];
|
|
34
|
+
const headers = headerRow.children.map((cell)=>external_mdast_util_to_string_toString(cell).trim().toLowerCase());
|
|
35
|
+
const expected = COLUMN_HEADERS.map((h)=>h.toLowerCase());
|
|
36
|
+
if (headers.length !== expected.length || !headers.every((h, i)=>h === expected[i])) throw new Error(`Table must have columns: ${COLUMN_HEADERS.join(", ")}. Got: ${headers.join(", ")}`);
|
|
37
|
+
const result = [];
|
|
38
|
+
for(let i = 1; i < rows.length; i++){
|
|
39
|
+
const cells = rows[i].children;
|
|
40
|
+
const raw = {};
|
|
41
|
+
for(let c = 0; c < COLUMN_KEYS.length; c++)raw[COLUMN_KEYS[c]] = external_mdast_util_to_string_toString(cells[c]).trim();
|
|
42
|
+
result.push(decode(raw));
|
|
43
|
+
}
|
|
44
|
+
return result;
|
|
45
|
+
}
|
|
46
|
+
function makeCell(text) {
|
|
47
|
+
return {
|
|
48
|
+
type: "tableCell",
|
|
49
|
+
children: [
|
|
50
|
+
{
|
|
51
|
+
type: "text",
|
|
52
|
+
value: text
|
|
53
|
+
}
|
|
54
|
+
]
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
function makeRow(texts) {
|
|
58
|
+
return {
|
|
59
|
+
type: "tableRow",
|
|
60
|
+
children: texts.map(makeCell)
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
function serializeDependencyTable(rows) {
|
|
64
|
+
const headerRow = makeRow([
|
|
65
|
+
...COLUMN_HEADERS
|
|
66
|
+
]);
|
|
67
|
+
const dataRows = rows.map((row)=>makeRow(COLUMN_KEYS.map((key)=>row[key])));
|
|
68
|
+
return {
|
|
69
|
+
type: "table",
|
|
70
|
+
children: [
|
|
71
|
+
headerRow,
|
|
72
|
+
...dataRows
|
|
73
|
+
]
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
function serializeDependencyTableToMarkdown(rows) {
|
|
77
|
+
const table = serializeDependencyTable(rows);
|
|
78
|
+
const tree = {
|
|
79
|
+
type: "root",
|
|
80
|
+
children: [
|
|
81
|
+
table
|
|
82
|
+
]
|
|
83
|
+
};
|
|
84
|
+
return unified().use(remark_gfm).use(remark_stringify).stringify(tree).trim();
|
|
85
|
+
}
|
|
86
|
+
const ACTION_ORDER = {
|
|
87
|
+
removed: 0,
|
|
88
|
+
updated: 1,
|
|
89
|
+
added: 2
|
|
90
|
+
};
|
|
91
|
+
function collapseDependencyRows(rows) {
|
|
92
|
+
const groups = new Map();
|
|
93
|
+
for (const row of rows){
|
|
94
|
+
const key = `${row.dependency}\0${row.type}`;
|
|
95
|
+
const existing = groups.get(key);
|
|
96
|
+
if (!existing) {
|
|
97
|
+
groups.set(key, {
|
|
98
|
+
...row
|
|
99
|
+
});
|
|
100
|
+
continue;
|
|
101
|
+
}
|
|
102
|
+
const merged = collapseTwo(existing, row);
|
|
103
|
+
if (null === merged) groups.delete(key);
|
|
104
|
+
else groups.set(key, merged);
|
|
105
|
+
}
|
|
106
|
+
return [
|
|
107
|
+
...groups.values()
|
|
108
|
+
];
|
|
109
|
+
}
|
|
110
|
+
function collapseTwo(first, second) {
|
|
111
|
+
const a = first.action;
|
|
112
|
+
const b = second.action;
|
|
113
|
+
if ("updated" === a && "updated" === b) return {
|
|
114
|
+
...first,
|
|
115
|
+
to: second.to
|
|
116
|
+
};
|
|
117
|
+
if ("added" === a && "updated" === b) return {
|
|
118
|
+
...first,
|
|
119
|
+
to: second.to
|
|
120
|
+
};
|
|
121
|
+
if ("added" === a && "removed" === b) return null;
|
|
122
|
+
if ("updated" === a && "removed" === b) return {
|
|
123
|
+
...first,
|
|
124
|
+
action: "removed",
|
|
125
|
+
to: "\u2014"
|
|
126
|
+
};
|
|
127
|
+
if ("removed" === a && "added" === b) return {
|
|
128
|
+
...first,
|
|
129
|
+
action: "updated",
|
|
130
|
+
to: second.to
|
|
131
|
+
};
|
|
132
|
+
return {
|
|
133
|
+
...second
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
function sortDependencyRows(rows) {
|
|
137
|
+
return [
|
|
138
|
+
...rows
|
|
139
|
+
].sort((a, b)=>{
|
|
140
|
+
const actionDiff = (ACTION_ORDER[a.action] ?? 99) - (ACTION_ORDER[b.action] ?? 99);
|
|
141
|
+
if (0 !== actionDiff) return actionDiff;
|
|
142
|
+
const typeDiff = a.type.localeCompare(b.type);
|
|
143
|
+
if (0 !== typeDiff) return typeDiff;
|
|
144
|
+
return a.dependency.localeCompare(b.dependency);
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
export { DependencyActionSchema, DependencyTableRowSchema, DependencyTableSchema, DependencyTableTypeSchema, NonEmptyString, PositiveInteger, VersionOrEmptySchema, collapseDependencyRows, parseDependencyTable, serializeDependencyTable, serializeDependencyTableToMarkdown, sortDependencyRows };
|
|
@@ -6,7 +6,8 @@ import { applyEdits, modify, parse } from "jsonc-parser";
|
|
|
6
6
|
import { findProjectRoot, getWorkspaceInfos } from "workspace-tools";
|
|
7
7
|
import { globSync } from "tinyglobby";
|
|
8
8
|
import { readFileSync, ChangelogTransformer, ChangesetLinter, resolve, existsSync, relative, mkdirSync, writeFileSync, join } from "../273.js";
|
|
9
|
-
import {
|
|
9
|
+
import { Effect, Schema, Data } from "../855.js";
|
|
10
|
+
import { VersionFileError, VersionFilesSchema } from "../725.js";
|
|
10
11
|
const dirArg = Args.directory({
|
|
11
12
|
name: "dir"
|
|
12
13
|
}).pipe(Args.withDefault(".changeset"));
|
|
@@ -49,7 +50,8 @@ const RULE_NAMES = [
|
|
|
49
50
|
"changeset-heading-hierarchy",
|
|
50
51
|
"changeset-required-sections",
|
|
51
52
|
"changeset-content-structure",
|
|
52
|
-
"changeset-uncategorized-content"
|
|
53
|
+
"changeset-uncategorized-content",
|
|
54
|
+
"changeset-dependency-table-format"
|
|
53
55
|
];
|
|
54
56
|
const DEFAULT_CONFIG = {
|
|
55
57
|
$schema: "https://unpkg.com/@changesets/config@3.1.1/schema.json",
|
|
@@ -785,7 +787,7 @@ const rootCommand = Command.make("savvy-changesets").pipe(Command.withSubcommand
|
|
|
785
787
|
]));
|
|
786
788
|
const cli = Command.run(rootCommand, {
|
|
787
789
|
name: "savvy-changesets",
|
|
788
|
-
version: "0.
|
|
790
|
+
version: "0.5.0"
|
|
789
791
|
});
|
|
790
792
|
function runCli() {
|
|
791
793
|
const main = Effect.suspend(()=>cli(process.argv)).pipe(Effect.provide(NodeContext.layer));
|
package/esm/changelog.d.ts
CHANGED
|
@@ -1,8 +1,22 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Changesets API changelog formatter
|
|
2
|
+
* Changesets API changelog formatter — `\@savvy-web/changesets/changelog`
|
|
3
3
|
*
|
|
4
|
-
* This module
|
|
5
|
-
*
|
|
4
|
+
* This module is the default export consumed by the Changesets CLI via the
|
|
5
|
+
* `changelog` field in `.changeset/config.json`. It implements the
|
|
6
|
+
* `ChangelogFunctions` interface from `\@changesets/types`, wiring the
|
|
7
|
+
* Effect-based formatting pipeline into the async API that Changesets expects.
|
|
8
|
+
*
|
|
9
|
+
* @remarks
|
|
10
|
+
* The module composes two Effect programs — {@link getReleaseLine} and
|
|
11
|
+
* {@link getDependencyReleaseLine} — and runs each through
|
|
12
|
+
* `Effect.runPromise` with a merged layer of {@link GitHubLive} (for commit
|
|
13
|
+
* metadata) and {@link MarkdownLive} (for mdast parsing). Options are
|
|
14
|
+
* validated at the boundary via `validateChangesetOptions` before being
|
|
15
|
+
* passed to the formatters.
|
|
16
|
+
*
|
|
17
|
+
* ### Configuration
|
|
18
|
+
*
|
|
19
|
+
* Add the following to your `.changeset/config.json`:
|
|
6
20
|
*
|
|
7
21
|
* ```json
|
|
8
22
|
* {
|
|
@@ -10,11 +24,46 @@
|
|
|
10
24
|
* }
|
|
11
25
|
* ```
|
|
12
26
|
*
|
|
27
|
+
* The `repo` option is **required** and must be in `owner/repo` format.
|
|
28
|
+
*
|
|
29
|
+
* ### Pipeline
|
|
30
|
+
*
|
|
31
|
+
* 1. **Options validation** — the raw `options` object from the Changesets
|
|
32
|
+
* config is decoded through `ChangesetOptionsSchema`.
|
|
33
|
+
* 2. **Release line formatting** — each changeset is formatted by
|
|
34
|
+
* `getReleaseLine`, which resolves GitHub metadata, parses sections,
|
|
35
|
+
* and produces structured markdown with commit links and attribution.
|
|
36
|
+
* 3. **Dependency table formatting** — bulk dependency updates are
|
|
37
|
+
* formatted by `getDependencyReleaseLine` into a markdown table.
|
|
38
|
+
*
|
|
39
|
+
* @example Configuring in `.changeset/config.json`
|
|
40
|
+
* ```json
|
|
41
|
+
* {
|
|
42
|
+
* "$schema": "https://unpkg.com/\@changesets/config\@3.1.1/schema.json",
|
|
43
|
+
* "changelog": ["\@savvy-web/changesets/changelog", { "repo": "savvy-web/my-package" }],
|
|
44
|
+
* "commit": false,
|
|
45
|
+
* "access": "public"
|
|
46
|
+
* }
|
|
47
|
+
* ```
|
|
48
|
+
*
|
|
49
|
+
* @see {@link getReleaseLine} in `./getReleaseLine.ts` for individual changeset formatting
|
|
50
|
+
* @see {@link getDependencyReleaseLine} in `./getDependencyReleaseLine.ts` for dependency table formatting
|
|
51
|
+
*
|
|
13
52
|
* @packageDocumentation
|
|
14
53
|
*/
|
|
15
54
|
|
|
16
55
|
import { ChangelogFunctions } from '@changesets/types';
|
|
17
56
|
|
|
57
|
+
/**
|
|
58
|
+
* Changesets API `ChangelogFunctions` implementation.
|
|
59
|
+
*
|
|
60
|
+
* This object satisfies the `ChangelogFunctions` contract from
|
|
61
|
+
* `\@changesets/types`. Each method validates options, runs the
|
|
62
|
+
* corresponding Effect program with the merged service layer, and
|
|
63
|
+
* returns a `Promise<string>`.
|
|
64
|
+
*
|
|
65
|
+
* @internal
|
|
66
|
+
*/
|
|
18
67
|
declare const changelogFunctions: ChangelogFunctions;
|
|
19
68
|
export default changelogFunctions;
|
|
20
69
|
|