@savvy-web/silk-effects 0.6.1 → 1.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/README.md +48 -17
- package/_virtual/_rolldown/runtime.js +18 -0
- package/changesets/api/categories.js +247 -0
- package/changesets/api/changelog.js +134 -0
- package/changesets/api/dependency-table.js +163 -0
- package/changesets/api/linter.js +168 -0
- package/changesets/api/transformer.js +140 -0
- package/changesets/categories/index.js +299 -0
- package/changesets/categories/types.js +66 -0
- package/changesets/changelog/formatting.js +119 -0
- package/changesets/changelog/getDependencyReleaseLine.js +114 -0
- package/changesets/changelog/getReleaseLine.js +122 -0
- package/changesets/changelog/index.js +99 -0
- package/changesets/constants.js +43 -0
- package/changesets/errors.js +305 -0
- package/changesets/index.js +146 -0
- package/changesets/markdownlint/index.js +29 -0
- package/changesets/markdownlint/rules/content-structure.js +98 -0
- package/changesets/markdownlint/rules/dependency-table-format.js +170 -0
- package/changesets/markdownlint/rules/heading-hierarchy.js +61 -0
- package/changesets/markdownlint/rules/required-sections.js +54 -0
- package/changesets/markdownlint/rules/uncategorized-content.js +54 -0
- package/changesets/markdownlint/rules/utils.js +30 -0
- package/changesets/remark/plugins/aggregate-dependency-tables.js +47 -0
- package/changesets/remark/plugins/contributor-footnotes.js +123 -0
- package/changesets/remark/plugins/deduplicate-items.js +30 -0
- package/changesets/remark/plugins/issue-link-refs.js +58 -0
- package/changesets/remark/plugins/merge-sections.js +43 -0
- package/changesets/remark/plugins/normalize-format.js +47 -0
- package/changesets/remark/plugins/reorder-sections.js +34 -0
- package/changesets/remark/presets.js +119 -0
- package/changesets/remark/rules/content-structure.js +22 -0
- package/changesets/remark/rules/dependency-table-format.js +40 -0
- package/changesets/remark/rules/heading-hierarchy.js +19 -0
- package/changesets/remark/rules/required-sections.js +17 -0
- package/changesets/remark/rules/uncategorized-content.js +31 -0
- package/changesets/schemas/changeset.js +146 -0
- package/changesets/schemas/dependency-table.js +189 -0
- package/changesets/schemas/git.js +69 -0
- package/changesets/schemas/github.js +175 -0
- package/changesets/schemas/options.js +182 -0
- package/changesets/schemas/package-scope.js +128 -0
- package/changesets/schemas/primitives.js +72 -0
- package/changesets/schemas/version-files.js +151 -0
- package/changesets/services/branch-analyzer.js +278 -0
- package/changesets/services/changelog.js +50 -0
- package/changesets/services/config-inspector.js +390 -0
- package/changesets/services/github.js +178 -0
- package/changesets/services/markdown.js +106 -0
- package/changesets/services/workspace-snapshot.js +182 -0
- package/changesets/utils/commit-parser.js +80 -0
- package/changesets/utils/dep-diff.js +77 -0
- package/changesets/utils/dependency-table.js +347 -0
- package/changesets/utils/issue-refs.js +101 -0
- package/changesets/utils/jsonpath.js +175 -0
- package/changesets/utils/logger.js +50 -0
- package/changesets/utils/markdown-link.js +57 -0
- package/changesets/utils/publishability.js +39 -0
- package/changesets/utils/remark-pipeline.js +79 -0
- package/changesets/utils/section-parser.js +94 -0
- package/changesets/utils/strip-frontmatter.js +46 -0
- package/changesets/utils/version-blocks.js +108 -0
- package/changesets/utils/version-files.js +336 -0
- package/changesets/utils/worktree-snapshot.js +142 -0
- package/changesets/vendor/github-info.js +55 -0
- package/commitlint/config/factory.js +69 -0
- package/commitlint/config/plugins.js +227 -0
- package/commitlint/config/rules.js +155 -0
- package/commitlint/config/schema.js +46 -0
- package/commitlint/detection/dco.js +53 -0
- package/commitlint/detection/scopes.js +45 -0
- package/commitlint/formatter/format.js +85 -0
- package/commitlint/formatter/messages.js +79 -0
- package/commitlint/hook/diagnostics/branch.js +36 -0
- package/commitlint/hook/diagnostics/cache.js +37 -0
- package/commitlint/hook/diagnostics/commitlint-config.js +36 -0
- package/commitlint/hook/diagnostics/open-issues.js +56 -0
- package/commitlint/hook/diagnostics/package-manager.js +51 -0
- package/commitlint/hook/diagnostics/signing.js +107 -0
- package/commitlint/hook/envelope.js +46 -0
- package/commitlint/hook/output.js +45 -0
- package/commitlint/hook/parse-bash-command.js +105 -0
- package/commitlint/hook/rules/closes-trailer.js +31 -0
- package/commitlint/hook/rules/forbidden-content.js +32 -0
- package/commitlint/hook/rules/plan-leakage.js +36 -0
- package/commitlint/hook/rules/signing-flag-conflict.js +25 -0
- package/commitlint/hook/rules/soft-wrap.js +37 -0
- package/commitlint/hook/rules/types.js +14 -0
- package/commitlint/hook/rules/verbosity.js +31 -0
- package/commitlint/hook/silence-logger.js +39 -0
- package/commitlint/index.js +146 -0
- package/commitlint/prompt/config.js +91 -0
- package/commitlint/prompt/emojis.js +74 -0
- package/commitlint/prompt/prompter.js +135 -0
- package/commitlint/static.js +73 -0
- package/errors/BiomeSyncError.js +21 -0
- package/errors/ChangesetConfigError.js +20 -0
- package/errors/ConfigNotFoundError.js +21 -0
- package/errors/SectionParseError.js +16 -0
- package/errors/SectionValidationError.js +16 -0
- package/errors/SectionWriteError.js +16 -0
- package/errors/TagFormatError.js +20 -0
- package/errors/ToolNotFoundError.js +11 -0
- package/errors/ToolResolutionError.js +11 -0
- package/errors/ToolVersionMismatchError.js +11 -0
- package/errors/VersioningDetectionError.js +20 -0
- package/errors/WorkspaceAnalysisError.js +21 -0
- package/index.d.ts +9743 -8380
- package/index.js +36 -6657
- package/lint/Handler.js +39 -0
- package/lint/cli/sections.js +65 -0
- package/lint/cli/templates/markdownlint.gen.js +183 -0
- package/lint/config/Preset.js +152 -0
- package/lint/config/createConfig.js +89 -0
- package/lint/handlers/Biome.js +179 -0
- package/lint/handlers/Markdown.js +139 -0
- package/lint/handlers/PackageJson.js +130 -0
- package/lint/handlers/PnpmWorkspace.js +141 -0
- package/lint/handlers/ShellScripts.js +58 -0
- package/lint/handlers/TypeScript.js +134 -0
- package/lint/handlers/Yaml.js +167 -0
- package/lint/index.js +52 -0
- package/lint/utils/Command.js +285 -0
- package/lint/utils/Filter.js +100 -0
- package/lint/utils/Workspace.js +86 -0
- package/package.json +52 -63
- package/schemas/CommentStyle.js +16 -0
- package/schemas/ResolvedTool.js +63 -0
- package/schemas/SavvySections.js +113 -0
- package/schemas/SectionBlock.js +70 -0
- package/schemas/SectionDefinition.js +121 -0
- package/schemas/SectionResults.js +12 -0
- package/schemas/TagStrategySchemas.js +18 -0
- package/schemas/ToolDefinition.js +39 -0
- package/schemas/ToolResults.js +14 -0
- package/schemas/VersioningSchemas.js +95 -0
- package/schemas/WorkspaceAnalysisSchemas.js +190 -0
- package/services/BiomeSchemaSync.js +133 -0
- package/services/ChangesetConfig.js +78 -0
- package/services/ChangesetConfigReader.js +106 -0
- package/services/ConfigDiscovery.js +71 -0
- package/services/ManagedSection.js +288 -0
- package/services/SilkPublishability.js +193 -0
- package/services/SilkWorkspaceAnalyzer.js +213 -0
- package/services/TagStrategy.js +54 -0
- package/services/ToolDiscovery.js +229 -0
- package/services/VersioningStrategy.js +67 -0
- package/tsdoc-metadata.json +11 -11
- package/turbo/digest.js +127 -0
- package/turbo/errors.js +48 -0
- package/turbo/index.js +32 -0
- package/turbo/schemas/DryRun.js +57 -0
- package/turbo/schemas/results.js +61 -0
- package/turbo/services/TurboInspector.js +100 -0
- package/utils/ToolCommand.js +40 -0
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { getVersionBlocks } from "../../utils/version-blocks.js";
|
|
2
|
+
import { toString } from "mdast-util-to-string";
|
|
3
|
+
|
|
4
|
+
//#region src/changesets/remark/plugins/normalize-format.ts
|
|
5
|
+
/**
|
|
6
|
+
* Check if a node is a heading at one of the given depths.
|
|
7
|
+
*
|
|
8
|
+
* @param node - The AST node to check
|
|
9
|
+
* @param depths - Allowed heading depths
|
|
10
|
+
* @returns `true` if the node is a heading at one of the specified depths
|
|
11
|
+
*
|
|
12
|
+
* @internal
|
|
13
|
+
*/
|
|
14
|
+
function isHeadingAtDepth(node, depths) {
|
|
15
|
+
return node.type === "heading" && depths.includes(node.depth);
|
|
16
|
+
}
|
|
17
|
+
const NormalizeFormatPlugin = () => {
|
|
18
|
+
return (tree) => {
|
|
19
|
+
const blocks = getVersionBlocks(tree);
|
|
20
|
+
const indicesToRemove = /* @__PURE__ */ new Set();
|
|
21
|
+
for (const block of blocks) for (let i = block.startIndex; i < block.endIndex; i++) {
|
|
22
|
+
const node = tree.children[i];
|
|
23
|
+
if (node.type === "list" && node.children.length === 0) {
|
|
24
|
+
indicesToRemove.add(i);
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
if (!isHeadingAtDepth(node, [3])) continue;
|
|
28
|
+
let hasContent = false;
|
|
29
|
+
for (let j = i + 1; j < block.endIndex; j++) {
|
|
30
|
+
const next = tree.children[j];
|
|
31
|
+
if (next.type === "paragraph" && toString(next).trim() === "") {
|
|
32
|
+
indicesToRemove.add(j);
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
if (isHeadingAtDepth(next, [2, 3])) break;
|
|
36
|
+
hasContent = true;
|
|
37
|
+
break;
|
|
38
|
+
}
|
|
39
|
+
if (!hasContent) indicesToRemove.add(i);
|
|
40
|
+
}
|
|
41
|
+
const sorted = [...indicesToRemove].sort((a, b) => b - a);
|
|
42
|
+
for (const idx of sorted) tree.children.splice(idx, 1);
|
|
43
|
+
};
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
//#endregion
|
|
47
|
+
export { NormalizeFormatPlugin };
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { fromHeading } from "../../categories/index.js";
|
|
2
|
+
import { getBlockSections, getHeadingText, getVersionBlocks } from "../../utils/version-blocks.js";
|
|
3
|
+
|
|
4
|
+
//#region src/changesets/remark/plugins/reorder-sections.ts
|
|
5
|
+
/**
|
|
6
|
+
* Default priority for unrecognized headings (sorts after all known categories).
|
|
7
|
+
*
|
|
8
|
+
* @internal
|
|
9
|
+
*/
|
|
10
|
+
const UNKNOWN_PRIORITY = 999;
|
|
11
|
+
const ReorderSectionsPlugin = () => {
|
|
12
|
+
return (tree) => {
|
|
13
|
+
const blocks = getVersionBlocks(tree);
|
|
14
|
+
for (let b = blocks.length - 1; b >= 0; b--) {
|
|
15
|
+
const block = blocks[b];
|
|
16
|
+
const sections = getBlockSections(tree, block);
|
|
17
|
+
if (sections.length <= 1) continue;
|
|
18
|
+
const preamble = [];
|
|
19
|
+
for (let i = block.startIndex; i < block.endIndex; i++) if (i < sections[0].headingIndex) preamble.push(tree.children[i]);
|
|
20
|
+
else break;
|
|
21
|
+
const sorted = [...sections].sort((a, b) => {
|
|
22
|
+
return (fromHeading(getHeadingText(a.heading))?.priority ?? UNKNOWN_PRIORITY) - (fromHeading(getHeadingText(b.heading))?.priority ?? UNKNOWN_PRIORITY);
|
|
23
|
+
});
|
|
24
|
+
if (sorted.every((s, i) => s.headingIndex === sections[i].headingIndex)) continue;
|
|
25
|
+
const newChildren = [...preamble];
|
|
26
|
+
for (const section of sorted) newChildren.push(section.heading, ...section.contentNodes);
|
|
27
|
+
const blockLength = block.endIndex - block.startIndex;
|
|
28
|
+
tree.children.splice(block.startIndex, blockLength, ...newChildren);
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
//#endregion
|
|
34
|
+
export { ReorderSectionsPlugin };
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { ContentStructureRule } from "./rules/content-structure.js";
|
|
2
|
+
import { HeadingHierarchyRule } from "./rules/heading-hierarchy.js";
|
|
3
|
+
import { RequiredSectionsRule } from "./rules/required-sections.js";
|
|
4
|
+
import { UncategorizedContentRule } from "./rules/uncategorized-content.js";
|
|
5
|
+
import { ContributorFootnotesPlugin } from "./plugins/contributor-footnotes.js";
|
|
6
|
+
import { DeduplicateItemsPlugin } from "./plugins/deduplicate-items.js";
|
|
7
|
+
import { IssueLinkRefsPlugin } from "./plugins/issue-link-refs.js";
|
|
8
|
+
import { MergeSectionsPlugin } from "./plugins/merge-sections.js";
|
|
9
|
+
import { NormalizeFormatPlugin } from "./plugins/normalize-format.js";
|
|
10
|
+
import { ReorderSectionsPlugin } from "./plugins/reorder-sections.js";
|
|
11
|
+
import { AggregateDependencyTablesPlugin } from "./plugins/aggregate-dependency-tables.js";
|
|
12
|
+
import { DependencyTableFormatRule } from "./rules/dependency-table-format.js";
|
|
13
|
+
|
|
14
|
+
//#region src/changesets/remark/presets.ts
|
|
15
|
+
/**
|
|
16
|
+
* Remark preset collections for changeset lint rules and transform plugins.
|
|
17
|
+
*
|
|
18
|
+
* @remarks
|
|
19
|
+
* Presets bundle related remark plugins into ordered arrays for convenient
|
|
20
|
+
* consumption. Each preset is a `readonly` tuple so that TypeScript can
|
|
21
|
+
* narrow element types. Iterate and `.use()` each entry with `unified()`.
|
|
22
|
+
*
|
|
23
|
+
* @see {@link SilkChangesetPreset} for lint rules
|
|
24
|
+
* @see {@link SilkChangesetTransformPreset} for transform plugins
|
|
25
|
+
*/
|
|
26
|
+
/**
|
|
27
|
+
* Preset combining all changeset lint rules for convenient consumption.
|
|
28
|
+
*
|
|
29
|
+
* @remarks
|
|
30
|
+
* Includes the following rules in order:
|
|
31
|
+
*
|
|
32
|
+
* 1. {@link HeadingHierarchyRule} (CSH001) -- no h1, no depth skips
|
|
33
|
+
* 2. {@link RequiredSectionsRule} (CSH002) -- h2 headings must match a known category
|
|
34
|
+
* 3. {@link ContentStructureRule} (CSH003) -- non-empty sections, code fence languages, non-empty list items
|
|
35
|
+
* 4. {@link UncategorizedContentRule} (CSH004) -- no content before the first h2 heading
|
|
36
|
+
* 5. {@link DependencyTableFormatRule} (CSH005) -- dependency table column/value validation
|
|
37
|
+
*
|
|
38
|
+
* Rule execution order is not significant for lint rules; all rules run
|
|
39
|
+
* independently over the same AST and report warnings to the virtual file.
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* ```typescript
|
|
43
|
+
* import { SilkChangesetPreset } from "\@savvy-web/changesets/remark";
|
|
44
|
+
* import remarkParse from "remark-parse";
|
|
45
|
+
* import { unified } from "unified";
|
|
46
|
+
* import { read } from "to-vfile";
|
|
47
|
+
*
|
|
48
|
+
* const processor = unified().use(remarkParse);
|
|
49
|
+
* for (const rule of SilkChangesetPreset) {
|
|
50
|
+
* processor.use(rule);
|
|
51
|
+
* }
|
|
52
|
+
*
|
|
53
|
+
* const file = await read("changeset.md");
|
|
54
|
+
* const result = await processor.process(file);
|
|
55
|
+
* console.log(result.messages); // lint warnings
|
|
56
|
+
* ```
|
|
57
|
+
*
|
|
58
|
+
* @see {@link SilkChangesetTransformPreset} for the corresponding transform preset
|
|
59
|
+
*
|
|
60
|
+
* @public
|
|
61
|
+
*/
|
|
62
|
+
const SilkChangesetPreset = [
|
|
63
|
+
HeadingHierarchyRule,
|
|
64
|
+
RequiredSectionsRule,
|
|
65
|
+
ContentStructureRule,
|
|
66
|
+
UncategorizedContentRule,
|
|
67
|
+
DependencyTableFormatRule
|
|
68
|
+
];
|
|
69
|
+
/**
|
|
70
|
+
* Ordered array of all transform plugins in the correct execution order.
|
|
71
|
+
*
|
|
72
|
+
* @remarks
|
|
73
|
+
* Plugin ordering is significant -- each plugin may depend on the output of
|
|
74
|
+
* earlier plugins in the pipeline:
|
|
75
|
+
*
|
|
76
|
+
* 1. {@link AggregateDependencyTablesPlugin} -- merge duplicate dependency sections (must run first so downstream plugins see a single Dependencies section)
|
|
77
|
+
* 2. {@link MergeSectionsPlugin} -- merge duplicate h3 headings (must run before reorder so that priority is computed on consolidated sections)
|
|
78
|
+
* 3. {@link ReorderSectionsPlugin} -- sort sections by category priority (Breaking Changes first, Other last)
|
|
79
|
+
* 4. {@link DeduplicateItemsPlugin} -- remove duplicate list items within each section
|
|
80
|
+
* 5. {@link ContributorFootnotesPlugin} -- extract inline `Thanks \@user!` attributions and aggregate them into a summary paragraph per version block
|
|
81
|
+
* 6. {@link IssueLinkRefsPlugin} -- convert inline `[#N](url)` links to reference-style `[#N]` with definitions at the end of each version block
|
|
82
|
+
* 7. {@link NormalizeFormatPlugin} -- final cleanup removing empty sections and empty lists
|
|
83
|
+
*
|
|
84
|
+
* @example
|
|
85
|
+
* ```typescript
|
|
86
|
+
* import { SilkChangesetTransformPreset } from "\@savvy-web/changesets/remark";
|
|
87
|
+
* import remarkGfm from "remark-gfm";
|
|
88
|
+
* import remarkParse from "remark-parse";
|
|
89
|
+
* import remarkStringify from "remark-stringify";
|
|
90
|
+
* import { unified } from "unified";
|
|
91
|
+
* import { read } from "to-vfile";
|
|
92
|
+
*
|
|
93
|
+
* const processor = unified().use(remarkParse).use(remarkGfm);
|
|
94
|
+
* for (const plugin of SilkChangesetTransformPreset) {
|
|
95
|
+
* processor.use(plugin);
|
|
96
|
+
* }
|
|
97
|
+
* processor.use(remarkStringify);
|
|
98
|
+
*
|
|
99
|
+
* const file = await read("CHANGELOG.md");
|
|
100
|
+
* const result = await processor.process(file);
|
|
101
|
+
* console.log(String(result));
|
|
102
|
+
* ```
|
|
103
|
+
*
|
|
104
|
+
* @see {@link SilkChangesetPreset} for the corresponding lint preset
|
|
105
|
+
*
|
|
106
|
+
* @public
|
|
107
|
+
*/
|
|
108
|
+
const SilkChangesetTransformPreset = [
|
|
109
|
+
AggregateDependencyTablesPlugin,
|
|
110
|
+
MergeSectionsPlugin,
|
|
111
|
+
ReorderSectionsPlugin,
|
|
112
|
+
DeduplicateItemsPlugin,
|
|
113
|
+
ContributorFootnotesPlugin,
|
|
114
|
+
IssueLinkRefsPlugin,
|
|
115
|
+
NormalizeFormatPlugin
|
|
116
|
+
];
|
|
117
|
+
|
|
118
|
+
//#endregion
|
|
119
|
+
export { SilkChangesetPreset, SilkChangesetTransformPreset };
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { RULE_DOCS } from "../../constants.js";
|
|
2
|
+
import { toString } from "mdast-util-to-string";
|
|
3
|
+
import { lintRule } from "unified-lint-rule";
|
|
4
|
+
import { visit } from "unist-util-visit";
|
|
5
|
+
|
|
6
|
+
//#region src/changesets/remark/rules/content-structure.ts
|
|
7
|
+
const ContentStructureRule = lintRule("remark-lint:changeset-content-structure", (tree, file) => {
|
|
8
|
+
visit(tree, "heading", (node, index, parent) => {
|
|
9
|
+
if (node.depth !== 2 || parent == null || index == null) return;
|
|
10
|
+
const next = parent.children[index + 1];
|
|
11
|
+
if (!next || next.type === "heading" && next.depth === 2) file.message(`Empty section: heading has no content before the next section or end of file. Add a list of changes (e.g., "- Added feature X") under this heading, or remove the empty heading. See: ${RULE_DOCS.CSH003}`, node);
|
|
12
|
+
});
|
|
13
|
+
visit(tree, "code", (node) => {
|
|
14
|
+
if (!node.lang) file.message(`Code block is missing a language identifier. Add a language after the opening fence (e.g., \`\`\`ts, \`\`\`json, \`\`\`bash). See: ${RULE_DOCS.CSH003}`, node);
|
|
15
|
+
});
|
|
16
|
+
visit(tree, "listItem", (node) => {
|
|
17
|
+
if (!toString(node).trim()) file.message(`Empty list item. Each list item must contain descriptive text (e.g., "- Fixed login timeout issue"). See: ${RULE_DOCS.CSH003}`, node);
|
|
18
|
+
});
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
//#endregion
|
|
22
|
+
export { ContentStructureRule };
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { parseDependencyTable } from "../../utils/dependency-table.js";
|
|
2
|
+
import { RULE_DOCS } from "../../constants.js";
|
|
3
|
+
import { toString } from "mdast-util-to-string";
|
|
4
|
+
import { lintRule } from "unified-lint-rule";
|
|
5
|
+
import { visit } from "unist-util-visit";
|
|
6
|
+
|
|
7
|
+
//#region src/changesets/remark/rules/dependency-table-format.ts
|
|
8
|
+
/** @internal */
|
|
9
|
+
const EM_DASH = "—";
|
|
10
|
+
const DependencyTableFormatRule = lintRule("remark-lint:changeset-dependency-table-format", (tree, file) => {
|
|
11
|
+
visit(tree, "heading", (node, index) => {
|
|
12
|
+
if (node.depth !== 2) return;
|
|
13
|
+
if (toString(node).toLowerCase() !== "dependencies") return;
|
|
14
|
+
if (index === void 0) return;
|
|
15
|
+
const content = [];
|
|
16
|
+
for (let i = index + 1; i < tree.children.length; i++) {
|
|
17
|
+
const child = tree.children[i];
|
|
18
|
+
if (child.type === "heading") break;
|
|
19
|
+
content.push(child);
|
|
20
|
+
}
|
|
21
|
+
const tables = content.filter((n) => n.type === "table");
|
|
22
|
+
if (tables.length === 0) {
|
|
23
|
+
file.message(`Dependencies section must contain a table, not a list or paragraph. See: ${RULE_DOCS.CSH005}`, node);
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
const table = tables[0];
|
|
27
|
+
try {
|
|
28
|
+
const rows = parseDependencyTable(table);
|
|
29
|
+
for (const row of rows) {
|
|
30
|
+
if (row.action === "added" && row.from !== EM_DASH) file.message(`'from' must be '\u2014' when action is 'added' (got '${row.from}'). See: ${RULE_DOCS.CSH005}`, table);
|
|
31
|
+
if (row.action === "removed" && row.to !== EM_DASH) file.message(`'to' must be '\u2014' when action is 'removed' (got '${row.to}'). See: ${RULE_DOCS.CSH005}`, table);
|
|
32
|
+
}
|
|
33
|
+
} catch (error) {
|
|
34
|
+
file.message(`${error instanceof Error ? error.message : String(error)}. See: ${RULE_DOCS.CSH005}`, table);
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
//#endregion
|
|
40
|
+
export { DependencyTableFormatRule };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { RULE_DOCS } from "../../constants.js";
|
|
2
|
+
import { lintRule } from "unified-lint-rule";
|
|
3
|
+
import { visit } from "unist-util-visit";
|
|
4
|
+
|
|
5
|
+
//#region src/changesets/remark/rules/heading-hierarchy.ts
|
|
6
|
+
const HeadingHierarchyRule = lintRule("remark-lint:changeset-heading-hierarchy", (tree, file) => {
|
|
7
|
+
let prevDepth = 0;
|
|
8
|
+
visit(tree, "heading", (node) => {
|
|
9
|
+
if (node.depth === 1) {
|
|
10
|
+
file.message(`h1 headings are not allowed in changeset files. Use h2 (##) for top-level sections like "## Features" or "## Bug Fixes". h1 is reserved for the version title generated by the changelog formatter. See: ${RULE_DOCS.CSH001}`, node);
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
if (prevDepth > 0 && node.depth > prevDepth + 1) file.message(`Heading level skipped: expected h${prevDepth + 1} or lower, found h${node.depth}. Headings must increase sequentially (h2 → h3 → h4). Add the missing intermediate level or reduce this heading's depth. See: ${RULE_DOCS.CSH001}`, node);
|
|
14
|
+
prevDepth = node.depth;
|
|
15
|
+
});
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
//#endregion
|
|
19
|
+
export { HeadingHierarchyRule };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { allHeadings, isValidHeading } from "../../categories/index.js";
|
|
2
|
+
import { RULE_DOCS } from "../../constants.js";
|
|
3
|
+
import { toString } from "mdast-util-to-string";
|
|
4
|
+
import { lintRule } from "unified-lint-rule";
|
|
5
|
+
import { visit } from "unist-util-visit";
|
|
6
|
+
|
|
7
|
+
//#region src/changesets/remark/rules/required-sections.ts
|
|
8
|
+
const RequiredSectionsRule = lintRule("remark-lint:changeset-required-sections", (tree, file) => {
|
|
9
|
+
visit(tree, "heading", (node) => {
|
|
10
|
+
if (node.depth !== 2) return;
|
|
11
|
+
const text = toString(node);
|
|
12
|
+
if (!isValidHeading(text)) file.message(`Unknown section "${text}". Valid h2 headings are: ${allHeadings().join(", ")}. Heading comparison is case-insensitive. See: ${RULE_DOCS.CSH002}`, node);
|
|
13
|
+
});
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
//#endregion
|
|
17
|
+
export { RequiredSectionsRule };
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { RULE_DOCS } from "../../constants.js";
|
|
2
|
+
import { lintRule } from "unified-lint-rule";
|
|
3
|
+
|
|
4
|
+
//#region src/changesets/remark/rules/uncategorized-content.ts
|
|
5
|
+
/**
|
|
6
|
+
* Node types to ignore when detecting uncategorized content (e.g., HTML comments).
|
|
7
|
+
*
|
|
8
|
+
* @internal
|
|
9
|
+
*/
|
|
10
|
+
const IGNORED_TYPES = new Set(["html"]);
|
|
11
|
+
/**
|
|
12
|
+
* Determine whether a node is substantive content (not a heading or ignored type).
|
|
13
|
+
*
|
|
14
|
+
* @param node - The AST node to check
|
|
15
|
+
* @returns `true` if the node is content that should be under a heading
|
|
16
|
+
*
|
|
17
|
+
* @internal
|
|
18
|
+
*/
|
|
19
|
+
function isContentNode(node) {
|
|
20
|
+
if (node.type === "heading") return false;
|
|
21
|
+
return !IGNORED_TYPES.has(node.type);
|
|
22
|
+
}
|
|
23
|
+
const UncategorizedContentRule = lintRule("remark-lint:changeset-uncategorized-content", (tree, file) => {
|
|
24
|
+
for (const node of tree.children) {
|
|
25
|
+
if (node.type === "heading" && node.depth === 2) break;
|
|
26
|
+
if (isContentNode(node)) file.message(`Content must be placed under a category heading (## heading). Move this content under an appropriate section like "## Features" or "## Bug Fixes". If it doesn't fit an existing category, use "## Other". See: ${RULE_DOCS.CSH004}`, node);
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
//#endregion
|
|
31
|
+
export { UncategorizedContentRule };
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import { NonEmptyString } from "./primitives.js";
|
|
2
|
+
import { CommitHashSchema } from "./git.js";
|
|
3
|
+
import { Schema } from "effect";
|
|
4
|
+
|
|
5
|
+
//#region src/changesets/schemas/changeset.ts
|
|
6
|
+
/**
|
|
7
|
+
* Effect schemas for changeset entries and dependency updates.
|
|
8
|
+
*
|
|
9
|
+
* @remarks
|
|
10
|
+
* These schemas define the canonical representation of changeset data
|
|
11
|
+
* consumed by the changelog formatter (Layer 2) and validated by the
|
|
12
|
+
* remark-lint pre-validation layer (Layer 1). They enforce constraints
|
|
13
|
+
* such as summary length limits and valid dependency types at system
|
|
14
|
+
* boundaries.
|
|
15
|
+
*
|
|
16
|
+
* @see {@link https://github.com/changesets/changesets | Changesets documentation}
|
|
17
|
+
* @see {@link https://effect.website/docs/schema/introduction | Effect Schema documentation}
|
|
18
|
+
*
|
|
19
|
+
* @packageDocumentation
|
|
20
|
+
*/
|
|
21
|
+
/**
|
|
22
|
+
* Schema for a changeset summary (1--1000 characters).
|
|
23
|
+
*
|
|
24
|
+
* @remarks
|
|
25
|
+
* Enforces that every changeset has a non-empty summary and caps length
|
|
26
|
+
* at 1000 characters. Longer descriptions should go in the changeset body,
|
|
27
|
+
* not the summary line. Validation messages guide users toward correct usage.
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* ```typescript
|
|
31
|
+
* import { Schema } from "effect";
|
|
32
|
+
* import { ChangesetSummarySchema } from "@savvy-web/changesets";
|
|
33
|
+
*
|
|
34
|
+
* // Succeeds — valid summary
|
|
35
|
+
* const summary = Schema.decodeUnknownSync(ChangesetSummarySchema)(
|
|
36
|
+
* "Fix authentication timeout in login flow"
|
|
37
|
+
* );
|
|
38
|
+
*
|
|
39
|
+
* // Throws ParseError — empty string
|
|
40
|
+
* Schema.decodeUnknownSync(ChangesetSummarySchema)("");
|
|
41
|
+
* ```
|
|
42
|
+
*
|
|
43
|
+
* @public
|
|
44
|
+
*/
|
|
45
|
+
const ChangesetSummarySchema = Schema.String.pipe(Schema.minLength(1, { message: () => "Changeset summary cannot be empty. Provide a 1-1000 character description of the change (e.g., \"Fix authentication timeout in login flow\")" }), Schema.maxLength(1e3, { message: () => "Changeset summary exceeds the 1000 character limit. Shorten the summary to at most 1000 characters — use the changeset body for additional details" }));
|
|
46
|
+
/**
|
|
47
|
+
* Schema for a changeset object.
|
|
48
|
+
*
|
|
49
|
+
* @remarks
|
|
50
|
+
* Represents a single changeset entry as consumed by the changelog formatter.
|
|
51
|
+
* The `summary` is the human-readable description, `id` is a unique identifier
|
|
52
|
+
* (typically the changeset filename without extension), and `commit` is the
|
|
53
|
+
* optional git SHA that introduced the changeset.
|
|
54
|
+
*
|
|
55
|
+
* @example
|
|
56
|
+
* ```typescript
|
|
57
|
+
* import { Schema } from "effect";
|
|
58
|
+
* import { ChangesetSchema } from "@savvy-web/changesets";
|
|
59
|
+
* import type { Changeset } from "@savvy-web/changesets";
|
|
60
|
+
*
|
|
61
|
+
* const changeset: Changeset = Schema.decodeUnknownSync(ChangesetSchema)({
|
|
62
|
+
* summary: "Add retry logic to API client",
|
|
63
|
+
* id: "brave-dogs-laugh",
|
|
64
|
+
* commit: "a1b2c3d",
|
|
65
|
+
* });
|
|
66
|
+
* ```
|
|
67
|
+
*
|
|
68
|
+
* @see {@link Changeset} for the inferred TypeScript type
|
|
69
|
+
* @see {@link ChangesetSummarySchema} for summary validation rules
|
|
70
|
+
* @see {@link CommitHashSchema} for commit hash format requirements
|
|
71
|
+
*
|
|
72
|
+
* @public
|
|
73
|
+
*/
|
|
74
|
+
const ChangesetSchema = Schema.Struct({
|
|
75
|
+
/** The changeset summary text. */
|
|
76
|
+
summary: ChangesetSummarySchema,
|
|
77
|
+
/** Unique changeset identifier. */
|
|
78
|
+
id: Schema.String,
|
|
79
|
+
/** Git commit hash associated with this changeset. */
|
|
80
|
+
commit: Schema.optional(CommitHashSchema)
|
|
81
|
+
});
|
|
82
|
+
/**
|
|
83
|
+
* Schema for npm dependency types.
|
|
84
|
+
*
|
|
85
|
+
* @remarks
|
|
86
|
+
* Represents the four standard `package.json` dependency fields using their
|
|
87
|
+
* plural key names as they appear in the manifest. For the singular,
|
|
88
|
+
* table-oriented variant that includes `workspace` and `config` types,
|
|
89
|
+
* see {@link DependencyTableTypeSchema}.
|
|
90
|
+
*
|
|
91
|
+
* @example
|
|
92
|
+
* ```typescript
|
|
93
|
+
* import { Schema } from "effect";
|
|
94
|
+
* import { DependencyTypeSchema } from "@savvy-web/changesets";
|
|
95
|
+
* import type { DependencyType } from "@savvy-web/changesets";
|
|
96
|
+
*
|
|
97
|
+
* const depType: DependencyType = Schema.decodeUnknownSync(DependencyTypeSchema)(
|
|
98
|
+
* "devDependencies"
|
|
99
|
+
* );
|
|
100
|
+
* ```
|
|
101
|
+
*
|
|
102
|
+
* @see {@link DependencyTableTypeSchema} for the extended singular-form variant
|
|
103
|
+
*
|
|
104
|
+
* @public
|
|
105
|
+
*/
|
|
106
|
+
const DependencyTypeSchema = Schema.Literal("dependencies", "devDependencies", "peerDependencies", "optionalDependencies");
|
|
107
|
+
/**
|
|
108
|
+
* Schema for a dependency update entry.
|
|
109
|
+
*
|
|
110
|
+
* @remarks
|
|
111
|
+
* Represents a single dependency version change as reported by
|
|
112
|
+
* the Changesets API. Captures the package name, which dependency
|
|
113
|
+
* field it belongs to, and the old and new version strings.
|
|
114
|
+
*
|
|
115
|
+
* @example
|
|
116
|
+
* ```typescript
|
|
117
|
+
* import { Schema } from "effect";
|
|
118
|
+
* import { DependencyUpdateSchema } from "@savvy-web/changesets";
|
|
119
|
+
* import type { DependencyUpdate } from "@savvy-web/changesets";
|
|
120
|
+
*
|
|
121
|
+
* const update: DependencyUpdate = Schema.decodeUnknownSync(DependencyUpdateSchema)({
|
|
122
|
+
* name: "effect",
|
|
123
|
+
* type: "dependencies",
|
|
124
|
+
* oldVersion: "3.18.0",
|
|
125
|
+
* newVersion: "3.19.1",
|
|
126
|
+
* });
|
|
127
|
+
* ```
|
|
128
|
+
*
|
|
129
|
+
* @see {@link DependencyUpdate} for the inferred TypeScript type
|
|
130
|
+
* @see {@link DependencyTableRowSchema} for the table-formatted variant
|
|
131
|
+
*
|
|
132
|
+
* @public
|
|
133
|
+
*/
|
|
134
|
+
const DependencyUpdateSchema = Schema.Struct({
|
|
135
|
+
/** Package name (must be non-empty). */
|
|
136
|
+
name: NonEmptyString.annotations({ message: () => "Package name cannot be empty" }),
|
|
137
|
+
/** npm dependency type. */
|
|
138
|
+
type: DependencyTypeSchema,
|
|
139
|
+
/** Previous version string. */
|
|
140
|
+
oldVersion: Schema.String,
|
|
141
|
+
/** New version string. */
|
|
142
|
+
newVersion: Schema.String
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
//#endregion
|
|
146
|
+
export { ChangesetSchema, ChangesetSummarySchema, DependencyTypeSchema, DependencyUpdateSchema };
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
import { NonEmptyString } from "./primitives.js";
|
|
2
|
+
import { Schema } from "effect";
|
|
3
|
+
|
|
4
|
+
//#region src/changesets/schemas/dependency-table.ts
|
|
5
|
+
/**
|
|
6
|
+
* Effect schemas for structured dependency table entries.
|
|
7
|
+
*
|
|
8
|
+
* @remarks
|
|
9
|
+
* These schemas define the canonical representation for dependency
|
|
10
|
+
* changes tracked as markdown tables in changeset files and CHANGELOGs.
|
|
11
|
+
* The table format provides a richer view than {@link DependencyUpdateSchema}
|
|
12
|
+
* by supporting singular dependency type names, workspace/config types,
|
|
13
|
+
* and explicit add/update/remove actions.
|
|
14
|
+
*
|
|
15
|
+
* A dependency table row looks like this in a CHANGELOG:
|
|
16
|
+
*
|
|
17
|
+
* | Dependency | Type | Action | From | To |
|
|
18
|
+
* |---|---|---|---|---|
|
|
19
|
+
* | effect | dependency | updated | 3.18.0 | 3.19.1 |
|
|
20
|
+
*
|
|
21
|
+
* @see {@link DependencyUpdateSchema} for the simpler Changesets API format
|
|
22
|
+
* @see {@link https://effect.website/docs/schema/introduction | Effect Schema documentation}
|
|
23
|
+
*
|
|
24
|
+
* @packageDocumentation
|
|
25
|
+
*/
|
|
26
|
+
/**
|
|
27
|
+
* Valid dependency table actions.
|
|
28
|
+
*
|
|
29
|
+
* @remarks
|
|
30
|
+
* Represents the three possible operations on a dependency: `"added"` for
|
|
31
|
+
* new dependencies, `"updated"` for version changes, and `"removed"` for
|
|
32
|
+
* deletions. Used in the "Action" column of dependency tables.
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* ```typescript
|
|
36
|
+
* import { Schema } from "effect";
|
|
37
|
+
* import { DependencyActionSchema } from "@savvy-web/changesets";
|
|
38
|
+
* import type { DependencyAction } from "@savvy-web/changesets";
|
|
39
|
+
*
|
|
40
|
+
* const action: DependencyAction = Schema.decodeUnknownSync(DependencyActionSchema)("updated");
|
|
41
|
+
* ```
|
|
42
|
+
*
|
|
43
|
+
* @public
|
|
44
|
+
*/
|
|
45
|
+
const DependencyActionSchema = Schema.Literal("added", "updated", "removed");
|
|
46
|
+
/**
|
|
47
|
+
* Extended dependency types for table format.
|
|
48
|
+
*
|
|
49
|
+
* @remarks
|
|
50
|
+
* Unlike {@link DependencyTypeSchema} (which uses plural npm field names like
|
|
51
|
+
* `"dependencies"`), this schema uses singular forms (`"dependency"`) and adds
|
|
52
|
+
* two additional types: `"workspace"` for monorepo workspace references and
|
|
53
|
+
* `"config"` for configuration toolchain updates (e.g., ESLint, TypeScript).
|
|
54
|
+
*
|
|
55
|
+
* @example
|
|
56
|
+
* ```typescript
|
|
57
|
+
* import { Schema } from "effect";
|
|
58
|
+
* import { DependencyTableTypeSchema } from "@savvy-web/changesets";
|
|
59
|
+
* import type { DependencyTableType } from "@savvy-web/changesets";
|
|
60
|
+
*
|
|
61
|
+
* const tableType: DependencyTableType = Schema.decodeUnknownSync(
|
|
62
|
+
* DependencyTableTypeSchema
|
|
63
|
+
* )("workspace");
|
|
64
|
+
* ```
|
|
65
|
+
*
|
|
66
|
+
* @see {@link DependencyTypeSchema} for the plural npm-field variant
|
|
67
|
+
*
|
|
68
|
+
* @public
|
|
69
|
+
*/
|
|
70
|
+
const DependencyTableTypeSchema = Schema.Literal("dependency", "devDependency", "peerDependency", "optionalDependency", "workspace", "config");
|
|
71
|
+
/**
|
|
72
|
+
* Version string or em dash (U+2014) sentinel for added/removed entries.
|
|
73
|
+
*
|
|
74
|
+
* @remarks
|
|
75
|
+
* Accepts either a semver-like version string (with optional `~` or `^`
|
|
76
|
+
* prefix and pre-release/build suffixes) or the em dash character `\u2014`
|
|
77
|
+
* which serves as a sentinel: the "From" column uses `\u2014` for newly
|
|
78
|
+
* added dependencies, and the "To" column uses it for removed ones.
|
|
79
|
+
*
|
|
80
|
+
* @example
|
|
81
|
+
* ```typescript
|
|
82
|
+
* import { Schema } from "effect";
|
|
83
|
+
* import { VersionOrEmptySchema } from "@savvy-web/changesets";
|
|
84
|
+
*
|
|
85
|
+
* // Succeeds — semver version
|
|
86
|
+
* Schema.decodeUnknownSync(VersionOrEmptySchema)("^3.19.1");
|
|
87
|
+
*
|
|
88
|
+
* // Succeeds — em dash sentinel for "no version"
|
|
89
|
+
* Schema.decodeUnknownSync(VersionOrEmptySchema)("\u2014");
|
|
90
|
+
*
|
|
91
|
+
* // Throws ParseError — arbitrary text
|
|
92
|
+
* Schema.decodeUnknownSync(VersionOrEmptySchema)("latest");
|
|
93
|
+
* ```
|
|
94
|
+
*
|
|
95
|
+
* @public
|
|
96
|
+
*/
|
|
97
|
+
const VersionOrEmptySchema = Schema.String.pipe(Schema.pattern(/^(\u2014|[~^]?\d+\.\d+\.\d+(?:[-+.][\w.+-]*)?)$/));
|
|
98
|
+
/**
|
|
99
|
+
* Schema for a single dependency table row.
|
|
100
|
+
*
|
|
101
|
+
* @remarks
|
|
102
|
+
* Represents one row of a dependency update table in a CHANGELOG.
|
|
103
|
+
* Each row captures the dependency name, its type, the change action,
|
|
104
|
+
* and the "from" and "to" version strings. For added dependencies the
|
|
105
|
+
* `from` field is an em dash; for removed dependencies the `to` field
|
|
106
|
+
* is an em dash.
|
|
107
|
+
*
|
|
108
|
+
* @example
|
|
109
|
+
* ```typescript
|
|
110
|
+
* import { Schema } from "effect";
|
|
111
|
+
* import { DependencyTableRowSchema } from "@savvy-web/changesets";
|
|
112
|
+
* import type { DependencyTableRow } from "@savvy-web/changesets";
|
|
113
|
+
*
|
|
114
|
+
* const row: DependencyTableRow = Schema.decodeUnknownSync(DependencyTableRowSchema)({
|
|
115
|
+
* dependency: "effect",
|
|
116
|
+
* type: "dependency",
|
|
117
|
+
* action: "updated",
|
|
118
|
+
* from: "3.18.0",
|
|
119
|
+
* to: "3.19.1",
|
|
120
|
+
* });
|
|
121
|
+
*
|
|
122
|
+
* // Newly added dependency — "from" is em dash
|
|
123
|
+
* const addedRow: DependencyTableRow = Schema.decodeUnknownSync(DependencyTableRowSchema)({
|
|
124
|
+
* dependency: "@effect/cli",
|
|
125
|
+
* type: "dependency",
|
|
126
|
+
* action: "added",
|
|
127
|
+
* from: "\u2014",
|
|
128
|
+
* to: "0.50.0",
|
|
129
|
+
* });
|
|
130
|
+
* ```
|
|
131
|
+
*
|
|
132
|
+
* @see {@link DependencyTableRow} for the inferred TypeScript type
|
|
133
|
+
* @see {@link DependencyTableSchema} for a non-empty array of rows
|
|
134
|
+
*
|
|
135
|
+
* @public
|
|
136
|
+
*/
|
|
137
|
+
const DependencyTableRowSchema = Schema.Struct({
|
|
138
|
+
/** Package or toolchain name. */
|
|
139
|
+
dependency: NonEmptyString,
|
|
140
|
+
/** Dependency type. */
|
|
141
|
+
type: DependencyTableTypeSchema,
|
|
142
|
+
/** Change action. */
|
|
143
|
+
action: DependencyActionSchema,
|
|
144
|
+
/** Previous version (em dash for added). */
|
|
145
|
+
from: VersionOrEmptySchema,
|
|
146
|
+
/** New version (em dash for removed). */
|
|
147
|
+
to: VersionOrEmptySchema
|
|
148
|
+
});
|
|
149
|
+
/**
|
|
150
|
+
* Schema for a dependency table (non-empty array of rows).
|
|
151
|
+
*
|
|
152
|
+
* @remarks
|
|
153
|
+
* Validates that the table contains at least one row. Used to represent
|
|
154
|
+
* the full dependency update table in a changeset or CHANGELOG entry.
|
|
155
|
+
*
|
|
156
|
+
* @example
|
|
157
|
+
* ```typescript
|
|
158
|
+
* import { Schema } from "effect";
|
|
159
|
+
* import { DependencyTableSchema } from "@savvy-web/changesets";
|
|
160
|
+
*
|
|
161
|
+
* const table = Schema.decodeUnknownSync(DependencyTableSchema)([
|
|
162
|
+
* {
|
|
163
|
+
* dependency: "effect",
|
|
164
|
+
* type: "dependency",
|
|
165
|
+
* action: "updated",
|
|
166
|
+
* from: "3.18.0",
|
|
167
|
+
* to: "3.19.1",
|
|
168
|
+
* },
|
|
169
|
+
* {
|
|
170
|
+
* dependency: "typescript",
|
|
171
|
+
* type: "config",
|
|
172
|
+
* action: "updated",
|
|
173
|
+
* from: "5.6.0",
|
|
174
|
+
* to: "5.7.2",
|
|
175
|
+
* },
|
|
176
|
+
* ]);
|
|
177
|
+
*
|
|
178
|
+
* // Throws ParseError — empty array
|
|
179
|
+
* Schema.decodeUnknownSync(DependencyTableSchema)([]);
|
|
180
|
+
* ```
|
|
181
|
+
*
|
|
182
|
+
* @see {@link DependencyTableRowSchema} for the individual row schema
|
|
183
|
+
*
|
|
184
|
+
* @public
|
|
185
|
+
*/
|
|
186
|
+
const DependencyTableSchema = Schema.Array(DependencyTableRowSchema).pipe(Schema.minItems(1));
|
|
187
|
+
|
|
188
|
+
//#endregion
|
|
189
|
+
export { DependencyActionSchema, DependencyTableRowSchema, DependencyTableSchema, DependencyTableTypeSchema, VersionOrEmptySchema };
|