@codluv/versionguard 0.1.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/LICENSE +21 -0
- package/README.md +357 -0
- package/dist/calver.d.ts +245 -0
- package/dist/calver.d.ts.map +1 -0
- package/dist/changelog.d.ts +83 -0
- package/dist/changelog.d.ts.map +1 -0
- package/dist/chunks/index-DPBYoIRi.js +1568 -0
- package/dist/chunks/index-DPBYoIRi.js.map +1 -0
- package/dist/cli.d.ts +60 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +312 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +95 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/feedback/index.d.ts +141 -0
- package/dist/feedback/index.d.ts.map +1 -0
- package/dist/fix/index.d.ts +140 -0
- package/dist/fix/index.d.ts.map +1 -0
- package/dist/hooks.d.ts +98 -0
- package/dist/hooks.d.ts.map +1 -0
- package/dist/index.d.ts +123 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +37 -0
- package/dist/index.js.map +1 -0
- package/dist/project.d.ts +144 -0
- package/dist/project.d.ts.map +1 -0
- package/dist/semver.d.ts +191 -0
- package/dist/semver.d.ts.map +1 -0
- package/dist/sync.d.ts +71 -0
- package/dist/sync.d.ts.map +1 -0
- package/dist/tag/index.d.ts +180 -0
- package/dist/tag/index.d.ts.map +1 -0
- package/dist/types.d.ts +510 -0
- package/dist/types.d.ts.map +1 -0
- package/package.json +90 -0
package/dist/cli.js
ADDED
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import * as path from "node:path";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
import chalk from "chalk";
|
|
5
|
+
import { Command } from "commander";
|
|
6
|
+
import { i as initConfig, g as getConfig, a as getPackageVersion, b as getVersionFeedback, v as validate, h as handlePostTag, c as getSyncFeedback, d as getChangelogFeedback, e as doctor, f as fixAll, j as fixSyncIssues, s as suggestNextVersion, k as setPackageVersion, l as createTag, m as installHooks, u as uninstallHooks, n as areHooksInstalled } from "./chunks/index-DPBYoIRi.js";
|
|
7
|
+
const styles = {
|
|
8
|
+
error: chalk.red,
|
|
9
|
+
warning: chalk.yellow,
|
|
10
|
+
success: chalk.green,
|
|
11
|
+
info: chalk.blue,
|
|
12
|
+
dim: chalk.gray,
|
|
13
|
+
bold: chalk.bold
|
|
14
|
+
};
|
|
15
|
+
function createProgram() {
|
|
16
|
+
const program = new Command();
|
|
17
|
+
program.name("versionguard").description("Strict versioning enforcement for SemVer and CalVer").version("0.1.0");
|
|
18
|
+
program.command("init").description("Initialize VersionGuard configuration").option("-c, --cwd <path>", "Working directory", process.cwd()).action((options) => {
|
|
19
|
+
try {
|
|
20
|
+
const configPath = initConfig(options.cwd);
|
|
21
|
+
console.log(styles.success(`✓ Created ${path.relative(options.cwd, configPath)}`));
|
|
22
|
+
console.log("");
|
|
23
|
+
console.log(styles.info("Next steps:"));
|
|
24
|
+
console.log(" 1. Edit .versionguard.yml to set your versioning type");
|
|
25
|
+
console.log(" 2. Run: npx versionguard hooks install");
|
|
26
|
+
console.log(" 3. Run: npx versionguard check");
|
|
27
|
+
} catch (error) {
|
|
28
|
+
console.error(styles.error(`✗ ${error.message}`));
|
|
29
|
+
process.exit(1);
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
program.command("check").description("Check the current version with actionable feedback").option("-c, --cwd <path>", "Working directory", process.cwd()).option("--prev <version>", "Previous version for comparison").action((options) => {
|
|
33
|
+
try {
|
|
34
|
+
const config = getConfig(options.cwd);
|
|
35
|
+
const version = getPackageVersion(options.cwd);
|
|
36
|
+
const result = getVersionFeedback(version, config, options.prev);
|
|
37
|
+
console.log(styles.bold(`Current version: ${version}`));
|
|
38
|
+
console.log(styles.dim(`Versioning type: ${config.versioning.type}`));
|
|
39
|
+
console.log("");
|
|
40
|
+
if (result.valid) {
|
|
41
|
+
console.log(styles.success("✓ Version is valid"));
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
console.log(styles.error("✗ Version has issues:"));
|
|
45
|
+
console.log("");
|
|
46
|
+
for (const error of result.errors) {
|
|
47
|
+
console.log(styles.error(` ✗ ${error.message}`));
|
|
48
|
+
}
|
|
49
|
+
if (result.suggestions.length > 0) {
|
|
50
|
+
console.log("");
|
|
51
|
+
console.log(styles.info("How to fix:"));
|
|
52
|
+
for (const suggestion of result.suggestions) {
|
|
53
|
+
console.log(` → ${suggestion.message}`);
|
|
54
|
+
if (suggestion.fix) {
|
|
55
|
+
console.log(styles.dim(` Run: ${suggestion.fix}`));
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
process.exit(1);
|
|
60
|
+
} catch (error) {
|
|
61
|
+
console.error(styles.error(`✗ ${error.message}`));
|
|
62
|
+
process.exit(1);
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
program.command("validate").description("Run full validation with smart feedback").option("-c, --cwd <path>", "Working directory", process.cwd()).option("--hook <name>", "Running as git hook").option("--json", "Print machine-readable JSON output").action((options) => {
|
|
66
|
+
try {
|
|
67
|
+
const config = getConfig(options.cwd);
|
|
68
|
+
const version = getPackageVersion(options.cwd);
|
|
69
|
+
const result = validate(config, options.cwd);
|
|
70
|
+
let postTagResult;
|
|
71
|
+
if (options.hook === "post-tag") {
|
|
72
|
+
postTagResult = handlePostTag(config, options.cwd);
|
|
73
|
+
}
|
|
74
|
+
if (options.json) {
|
|
75
|
+
console.log(
|
|
76
|
+
JSON.stringify(
|
|
77
|
+
{
|
|
78
|
+
...result,
|
|
79
|
+
hook: options.hook ?? null,
|
|
80
|
+
postTag: postTagResult ?? null
|
|
81
|
+
},
|
|
82
|
+
null,
|
|
83
|
+
2
|
|
84
|
+
)
|
|
85
|
+
);
|
|
86
|
+
if (!result.valid || postTagResult && !postTagResult.success) {
|
|
87
|
+
process.exit(1);
|
|
88
|
+
}
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
console.log(styles.bold(`Validating version ${version}...`));
|
|
92
|
+
console.log("");
|
|
93
|
+
if (!result.syncValid) {
|
|
94
|
+
console.log(styles.error("Sync Issues:"));
|
|
95
|
+
for (const error of result.errors.filter((item) => item.includes("mismatch"))) {
|
|
96
|
+
const parts = error.match(
|
|
97
|
+
/Version mismatch in (.+):(\d+) - found "(.+?)" but expected "(.+?)"/
|
|
98
|
+
);
|
|
99
|
+
if (!parts) {
|
|
100
|
+
continue;
|
|
101
|
+
}
|
|
102
|
+
const suggestions = getSyncFeedback(parts[1], parts[3], parts[4]);
|
|
103
|
+
console.log(styles.error(` ✗ ${parts[1]} has wrong version`));
|
|
104
|
+
console.log(styles.dim(` Found: "${parts[3]}" Expected: "${parts[4]}"`));
|
|
105
|
+
if (suggestions[0]?.fix) {
|
|
106
|
+
console.log(styles.info(` Fix: ${suggestions[0].fix}`));
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
console.log("");
|
|
110
|
+
}
|
|
111
|
+
if (config.changelog.enabled && !result.changelogValid) {
|
|
112
|
+
console.log(styles.error("Changelog Issues:"));
|
|
113
|
+
for (const error of result.errors.filter(
|
|
114
|
+
(item) => item.toLowerCase().includes("changelog")
|
|
115
|
+
)) {
|
|
116
|
+
console.log(styles.error(` ✗ ${error}`));
|
|
117
|
+
}
|
|
118
|
+
const suggestions = getChangelogFeedback(false, version);
|
|
119
|
+
if (suggestions[0]?.fix) {
|
|
120
|
+
console.log(styles.info(`Fix: ${suggestions[0].fix}`));
|
|
121
|
+
}
|
|
122
|
+
console.log("");
|
|
123
|
+
}
|
|
124
|
+
if (postTagResult) {
|
|
125
|
+
if (!postTagResult.success) {
|
|
126
|
+
console.log(styles.error(`✗ ${postTagResult.message}`));
|
|
127
|
+
process.exit(1);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
if (!result.valid) {
|
|
131
|
+
console.log(styles.error("✗ Validation failed"));
|
|
132
|
+
process.exit(1);
|
|
133
|
+
}
|
|
134
|
+
console.log(styles.success("✓ All validations passed"));
|
|
135
|
+
} catch (error) {
|
|
136
|
+
console.error(styles.error(`✗ ${error.message}`));
|
|
137
|
+
process.exit(1);
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
program.command("doctor").description("Report repository readiness in one pass").option("-c, --cwd <path>", "Working directory", process.cwd()).option("--json", "Print machine-readable JSON output").action((options) => {
|
|
141
|
+
try {
|
|
142
|
+
const config = getConfig(options.cwd);
|
|
143
|
+
const report = doctor(config, options.cwd);
|
|
144
|
+
if (options.json) {
|
|
145
|
+
console.log(JSON.stringify(report, null, 2));
|
|
146
|
+
if (!report.ready) {
|
|
147
|
+
process.exit(1);
|
|
148
|
+
}
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
console.log(styles.bold("VersionGuard Doctor"));
|
|
152
|
+
console.log(` Version: ${report.version || "(missing)"}`);
|
|
153
|
+
console.log(` Version valid: ${report.versionValid ? "yes" : "no"}`);
|
|
154
|
+
console.log(` Files in sync: ${report.syncValid ? "yes" : "no"}`);
|
|
155
|
+
console.log(` Changelog ready: ${report.changelogValid ? "yes" : "no"}`);
|
|
156
|
+
console.log(` Git repository: ${report.gitRepository ? "yes" : "no"}`);
|
|
157
|
+
console.log(
|
|
158
|
+
` Hooks installed: ${report.gitRepository ? report.hooksInstalled ? "yes" : "no" : "n/a"}`
|
|
159
|
+
);
|
|
160
|
+
console.log(
|
|
161
|
+
` Worktree clean: ${report.gitRepository ? report.worktreeClean ? "yes" : "no" : "n/a"}`
|
|
162
|
+
);
|
|
163
|
+
if (!report.ready) {
|
|
164
|
+
console.log("");
|
|
165
|
+
console.log(styles.error("Issues:"));
|
|
166
|
+
for (const error of report.errors) {
|
|
167
|
+
console.log(styles.error(` ✗ ${error}`));
|
|
168
|
+
}
|
|
169
|
+
process.exit(1);
|
|
170
|
+
}
|
|
171
|
+
console.log("");
|
|
172
|
+
console.log(styles.success("✓ Repository is ready"));
|
|
173
|
+
} catch (error) {
|
|
174
|
+
console.error(styles.error(`✗ ${error.message}`));
|
|
175
|
+
process.exit(1);
|
|
176
|
+
}
|
|
177
|
+
});
|
|
178
|
+
program.command("fix").description("Auto-fix detected issues").option("-c, --cwd <path>", "Working directory", process.cwd()).action((options) => {
|
|
179
|
+
try {
|
|
180
|
+
const config = getConfig(options.cwd);
|
|
181
|
+
const version = getPackageVersion(options.cwd);
|
|
182
|
+
const results = fixAll(config, version, options.cwd);
|
|
183
|
+
console.log(styles.bold(`Fixing issues for version ${version}...`));
|
|
184
|
+
console.log("");
|
|
185
|
+
for (const result of results) {
|
|
186
|
+
const printer = result.fixed ? styles.success : styles.dim;
|
|
187
|
+
console.log(printer(`${result.fixed ? "✓" : "•"} ${result.message}`));
|
|
188
|
+
}
|
|
189
|
+
} catch (error) {
|
|
190
|
+
console.error(styles.error(`✗ ${error.message}`));
|
|
191
|
+
process.exit(1);
|
|
192
|
+
}
|
|
193
|
+
});
|
|
194
|
+
program.command("sync").description("Sync version to all configured files").option("-c, --cwd <path>", "Working directory", process.cwd()).action((options) => {
|
|
195
|
+
try {
|
|
196
|
+
const config = getConfig(options.cwd);
|
|
197
|
+
const version = getPackageVersion(options.cwd);
|
|
198
|
+
const results = fixSyncIssues(config, options.cwd);
|
|
199
|
+
console.log(styles.bold(`Syncing version ${version}...`));
|
|
200
|
+
for (const result of results) {
|
|
201
|
+
const printer = result.fixed ? styles.success : styles.dim;
|
|
202
|
+
console.log(printer(`${result.fixed ? "✓" : "•"} ${result.message}`));
|
|
203
|
+
}
|
|
204
|
+
} catch (error) {
|
|
205
|
+
console.error(styles.error(`✗ ${error.message}`));
|
|
206
|
+
process.exit(1);
|
|
207
|
+
}
|
|
208
|
+
});
|
|
209
|
+
program.command("bump").description("Suggest and optionally apply the next version").option("-c, --cwd <path>", "Working directory", process.cwd()).option("-t, --type <type>", "Bump type (major, minor, patch, auto)").option("--apply", "Apply the first suggested version").action(
|
|
210
|
+
(options) => {
|
|
211
|
+
try {
|
|
212
|
+
const config = getConfig(options.cwd);
|
|
213
|
+
const currentVersion = getPackageVersion(options.cwd);
|
|
214
|
+
const suggestions = suggestNextVersion(currentVersion, config, options.type);
|
|
215
|
+
console.log(styles.bold(`Current version: ${currentVersion}`));
|
|
216
|
+
console.log("");
|
|
217
|
+
for (const [index, suggestion] of suggestions.entries()) {
|
|
218
|
+
console.log(` ${index + 1}. ${styles.bold(suggestion.version)}`);
|
|
219
|
+
console.log(` ${styles.dim(suggestion.reason)}`);
|
|
220
|
+
}
|
|
221
|
+
if (options.apply) {
|
|
222
|
+
const nextVersion = suggestions[0]?.version;
|
|
223
|
+
if (!nextVersion) {
|
|
224
|
+
throw new Error("No version suggestion available");
|
|
225
|
+
}
|
|
226
|
+
setPackageVersion(nextVersion, options.cwd);
|
|
227
|
+
fixAll(config, nextVersion, options.cwd);
|
|
228
|
+
console.log(styles.success(`✓ Updated to ${nextVersion}`));
|
|
229
|
+
}
|
|
230
|
+
} catch (error) {
|
|
231
|
+
console.error(styles.error(`✗ ${error.message}`));
|
|
232
|
+
process.exit(1);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
);
|
|
236
|
+
program.command("tag").description("Create a git tag with automation").argument("[version]", "Version to tag (defaults to package.json version)").option("-c, --cwd <path>", "Working directory", process.cwd()).option("-m, --message <msg>", "Tag message").option("--no-fix", "Skip auto-fixing files before tagging").action(
|
|
237
|
+
(version, options) => {
|
|
238
|
+
try {
|
|
239
|
+
const config = getConfig(options.cwd);
|
|
240
|
+
const tagVersion = version || getPackageVersion(options.cwd);
|
|
241
|
+
const result = createTag(
|
|
242
|
+
tagVersion,
|
|
243
|
+
options.message,
|
|
244
|
+
options.fix !== false,
|
|
245
|
+
config,
|
|
246
|
+
options.cwd
|
|
247
|
+
);
|
|
248
|
+
if (!result.success) {
|
|
249
|
+
console.log(styles.error(`✗ ${result.message}`));
|
|
250
|
+
process.exit(1);
|
|
251
|
+
}
|
|
252
|
+
console.log(styles.success(`✓ ${result.message}`));
|
|
253
|
+
for (const action of result.actions) {
|
|
254
|
+
console.log(` • ${action}`);
|
|
255
|
+
}
|
|
256
|
+
} catch (error) {
|
|
257
|
+
console.error(styles.error(`✗ ${error.message}`));
|
|
258
|
+
process.exit(1);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
);
|
|
262
|
+
const hooksCommand = program.command("hooks").description("Manage git hooks");
|
|
263
|
+
hooksCommand.command("install").description("Install git hooks").option("-c, --cwd <path>", "Working directory", process.cwd()).action((options) => {
|
|
264
|
+
try {
|
|
265
|
+
const config = getConfig(options.cwd);
|
|
266
|
+
installHooks(config.git, options.cwd);
|
|
267
|
+
console.log(styles.success("✓ Git hooks installed"));
|
|
268
|
+
} catch (error) {
|
|
269
|
+
console.error(styles.error(`✗ ${error.message}`));
|
|
270
|
+
process.exit(1);
|
|
271
|
+
}
|
|
272
|
+
});
|
|
273
|
+
hooksCommand.command("uninstall").description("Uninstall git hooks").option("-c, --cwd <path>", "Working directory", process.cwd()).action((options) => {
|
|
274
|
+
try {
|
|
275
|
+
uninstallHooks(options.cwd);
|
|
276
|
+
console.log(styles.success("✓ Git hooks uninstalled"));
|
|
277
|
+
} catch (error) {
|
|
278
|
+
console.error(styles.error(`✗ ${error.message}`));
|
|
279
|
+
process.exit(1);
|
|
280
|
+
}
|
|
281
|
+
});
|
|
282
|
+
hooksCommand.command("status").description("Check if hooks are installed").option("-c, --cwd <path>", "Working directory", process.cwd()).action((options) => {
|
|
283
|
+
try {
|
|
284
|
+
if (areHooksInstalled(options.cwd)) {
|
|
285
|
+
console.log(styles.success("✓ VersionGuard hooks are installed"));
|
|
286
|
+
return;
|
|
287
|
+
}
|
|
288
|
+
console.log(styles.warning("✗ VersionGuard hooks are not installed"));
|
|
289
|
+
process.exit(1);
|
|
290
|
+
} catch (error) {
|
|
291
|
+
console.error(styles.error(`✗ ${error.message}`));
|
|
292
|
+
process.exit(1);
|
|
293
|
+
}
|
|
294
|
+
});
|
|
295
|
+
return program;
|
|
296
|
+
}
|
|
297
|
+
async function runCli(argv = process.argv) {
|
|
298
|
+
await createProgram().parseAsync(argv);
|
|
299
|
+
}
|
|
300
|
+
function shouldRunCli(argv = process.argv, metaUrl = import.meta.url) {
|
|
301
|
+
const entryPath = argv[1] ? path.resolve(argv[1]) : null;
|
|
302
|
+
return entryPath === fileURLToPath(metaUrl);
|
|
303
|
+
}
|
|
304
|
+
if (shouldRunCli()) {
|
|
305
|
+
void runCli();
|
|
306
|
+
}
|
|
307
|
+
export {
|
|
308
|
+
createProgram,
|
|
309
|
+
runCli,
|
|
310
|
+
shouldRunCli
|
|
311
|
+
};
|
|
312
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\nimport * as path from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nimport chalk from 'chalk';\nimport { Command } from 'commander';\n\nimport * as feedback from './feedback';\nimport * as fix from './fix';\nimport * as versionguard from './index';\nimport * as project from './project';\nimport * as tag from './tag';\n\nconst styles = {\n error: chalk.red,\n warning: chalk.yellow,\n success: chalk.green,\n info: chalk.blue,\n dim: chalk.gray,\n bold: chalk.bold,\n};\n\n/**\n * Creates the VersionGuard CLI program definition.\n *\n * @public\n * @since 0.1.0\n * @remarks\n * This function wires all commands, options, and handlers onto a fresh Commander\n * program instance without parsing arguments yet.\n *\n * @returns A configured Commander program for the VersionGuard CLI.\n *\n * @example\n * ```typescript\n * const program = createProgram();\n * console.log(program.name());\n * ```\n */\nexport function createProgram(): Command {\n const program = new Command();\n\n program\n .name('versionguard')\n .description('Strict versioning enforcement for SemVer and CalVer')\n .version('0.1.0');\n\n program\n .command('init')\n .description('Initialize VersionGuard configuration')\n .option('-c, --cwd <path>', 'Working directory', process.cwd())\n .action((options: { cwd: string }) => {\n try {\n const configPath = versionguard.initConfig(options.cwd);\n console.log(styles.success(`✓ Created ${path.relative(options.cwd, configPath)}`));\n console.log('');\n console.log(styles.info('Next steps:'));\n console.log(' 1. Edit .versionguard.yml to set your versioning type');\n console.log(' 2. Run: npx versionguard hooks install');\n console.log(' 3. Run: npx versionguard check');\n } catch (error) {\n console.error(styles.error(`✗ ${(error as Error).message}`));\n process.exit(1);\n }\n });\n\n program\n .command('check')\n .description('Check the current version with actionable feedback')\n .option('-c, --cwd <path>', 'Working directory', process.cwd())\n .option('--prev <version>', 'Previous version for comparison')\n .action((options: { cwd: string; prev?: string }) => {\n try {\n const config = versionguard.getConfig(options.cwd);\n const version = versionguard.getPackageVersion(options.cwd);\n const result = feedback.getVersionFeedback(version, config, options.prev);\n\n console.log(styles.bold(`Current version: ${version}`));\n console.log(styles.dim(`Versioning type: ${config.versioning.type}`));\n console.log('');\n\n if (result.valid) {\n console.log(styles.success('✓ Version is valid'));\n return;\n }\n\n console.log(styles.error('✗ Version has issues:'));\n console.log('');\n for (const error of result.errors) {\n console.log(styles.error(` ✗ ${error.message}`));\n }\n if (result.suggestions.length > 0) {\n console.log('');\n console.log(styles.info('How to fix:'));\n for (const suggestion of result.suggestions) {\n console.log(` → ${suggestion.message}`);\n if (suggestion.fix) {\n console.log(styles.dim(` Run: ${suggestion.fix}`));\n }\n }\n }\n process.exit(1);\n } catch (error) {\n console.error(styles.error(`✗ ${(error as Error).message}`));\n process.exit(1);\n }\n });\n\n program\n .command('validate')\n .description('Run full validation with smart feedback')\n .option('-c, --cwd <path>', 'Working directory', process.cwd())\n .option('--hook <name>', 'Running as git hook')\n .option('--json', 'Print machine-readable JSON output')\n .action((options: { cwd: string; hook?: string; json?: boolean }) => {\n try {\n const config = versionguard.getConfig(options.cwd);\n const version = versionguard.getPackageVersion(options.cwd);\n const result = versionguard.validate(config, options.cwd);\n\n let postTagResult: { success: boolean; message: string; actions: string[] } | undefined;\n\n if (options.hook === 'post-tag') {\n postTagResult = tag.handlePostTag(config, options.cwd);\n }\n\n if (options.json) {\n console.log(\n JSON.stringify(\n {\n ...result,\n hook: options.hook ?? null,\n postTag: postTagResult ?? null,\n },\n null,\n 2,\n ),\n );\n\n if (!result.valid || (postTagResult && !postTagResult.success)) {\n process.exit(1);\n }\n\n return;\n }\n\n console.log(styles.bold(`Validating version ${version}...`));\n console.log('');\n\n if (!result.syncValid) {\n console.log(styles.error('Sync Issues:'));\n for (const error of result.errors.filter((item) => item.includes('mismatch'))) {\n const parts = error.match(\n /Version mismatch in (.+):(\\d+) - found \"(.+?)\" but expected \"(.+?)\"/,\n );\n if (!parts) {\n continue;\n }\n const suggestions = feedback.getSyncFeedback(parts[1], parts[3], parts[4]);\n console.log(styles.error(` ✗ ${parts[1]} has wrong version`));\n console.log(styles.dim(` Found: \"${parts[3]}\" Expected: \"${parts[4]}\"`));\n if (suggestions[0]?.fix) {\n console.log(styles.info(` Fix: ${suggestions[0].fix}`));\n }\n }\n console.log('');\n }\n\n if (config.changelog.enabled && !result.changelogValid) {\n console.log(styles.error('Changelog Issues:'));\n for (const error of result.errors.filter((item) =>\n item.toLowerCase().includes('changelog'),\n )) {\n console.log(styles.error(` ✗ ${error}`));\n }\n const suggestions = feedback.getChangelogFeedback(false, version);\n if (suggestions[0]?.fix) {\n console.log(styles.info(`Fix: ${suggestions[0].fix}`));\n }\n console.log('');\n }\n\n if (postTagResult) {\n if (!postTagResult.success) {\n console.log(styles.error(`✗ ${postTagResult.message}`));\n process.exit(1);\n }\n }\n\n if (!result.valid) {\n console.log(styles.error('✗ Validation failed'));\n process.exit(1);\n }\n\n console.log(styles.success('✓ All validations passed'));\n } catch (error) {\n console.error(styles.error(`✗ ${(error as Error).message}`));\n process.exit(1);\n }\n });\n\n program\n .command('doctor')\n .description('Report repository readiness in one pass')\n .option('-c, --cwd <path>', 'Working directory', process.cwd())\n .option('--json', 'Print machine-readable JSON output')\n .action((options: { cwd: string; json?: boolean }) => {\n try {\n const config = versionguard.getConfig(options.cwd);\n const report = versionguard.doctor(config, options.cwd);\n\n if (options.json) {\n console.log(JSON.stringify(report, null, 2));\n if (!report.ready) {\n process.exit(1);\n }\n return;\n }\n\n console.log(styles.bold('VersionGuard Doctor'));\n console.log(` Version: ${report.version || '(missing)'}`);\n console.log(` Version valid: ${report.versionValid ? 'yes' : 'no'}`);\n console.log(` Files in sync: ${report.syncValid ? 'yes' : 'no'}`);\n console.log(` Changelog ready: ${report.changelogValid ? 'yes' : 'no'}`);\n console.log(` Git repository: ${report.gitRepository ? 'yes' : 'no'}`);\n console.log(\n ` Hooks installed: ${report.gitRepository ? (report.hooksInstalled ? 'yes' : 'no') : 'n/a'}`,\n );\n console.log(\n ` Worktree clean: ${report.gitRepository ? (report.worktreeClean ? 'yes' : 'no') : 'n/a'}`,\n );\n\n if (!report.ready) {\n console.log('');\n console.log(styles.error('Issues:'));\n for (const error of report.errors) {\n console.log(styles.error(` ✗ ${error}`));\n }\n process.exit(1);\n }\n\n console.log('');\n console.log(styles.success('✓ Repository is ready'));\n } catch (error) {\n console.error(styles.error(`✗ ${(error as Error).message}`));\n process.exit(1);\n }\n });\n\n program\n .command('fix')\n .description('Auto-fix detected issues')\n .option('-c, --cwd <path>', 'Working directory', process.cwd())\n .action((options: { cwd: string }) => {\n try {\n const config = versionguard.getConfig(options.cwd);\n const version = versionguard.getPackageVersion(options.cwd);\n const results = fix.fixAll(config, version, options.cwd);\n\n console.log(styles.bold(`Fixing issues for version ${version}...`));\n console.log('');\n\n for (const result of results) {\n const printer = result.fixed ? styles.success : styles.dim;\n console.log(printer(`${result.fixed ? '✓' : '•'} ${result.message}`));\n }\n } catch (error) {\n console.error(styles.error(`✗ ${(error as Error).message}`));\n process.exit(1);\n }\n });\n\n program\n .command('sync')\n .description('Sync version to all configured files')\n .option('-c, --cwd <path>', 'Working directory', process.cwd())\n .action((options: { cwd: string }) => {\n try {\n const config = versionguard.getConfig(options.cwd);\n const version = versionguard.getPackageVersion(options.cwd);\n const results = fix.fixSyncIssues(config, options.cwd);\n\n console.log(styles.bold(`Syncing version ${version}...`));\n for (const result of results) {\n const printer = result.fixed ? styles.success : styles.dim;\n console.log(printer(`${result.fixed ? '✓' : '•'} ${result.message}`));\n }\n } catch (error) {\n console.error(styles.error(`✗ ${(error as Error).message}`));\n process.exit(1);\n }\n });\n\n program\n .command('bump')\n .description('Suggest and optionally apply the next version')\n .option('-c, --cwd <path>', 'Working directory', process.cwd())\n .option('-t, --type <type>', 'Bump type (major, minor, patch, auto)')\n .option('--apply', 'Apply the first suggested version')\n .action(\n (options: { cwd: string; type?: 'major' | 'minor' | 'patch' | 'auto'; apply?: boolean }) => {\n try {\n const config = versionguard.getConfig(options.cwd);\n const currentVersion = versionguard.getPackageVersion(options.cwd);\n const suggestions = fix.suggestNextVersion(currentVersion, config, options.type);\n\n console.log(styles.bold(`Current version: ${currentVersion}`));\n console.log('');\n for (const [index, suggestion] of suggestions.entries()) {\n console.log(` ${index + 1}. ${styles.bold(suggestion.version)}`);\n console.log(` ${styles.dim(suggestion.reason)}`);\n }\n\n if (options.apply) {\n const nextVersion = suggestions[0]?.version;\n if (!nextVersion) {\n throw new Error('No version suggestion available');\n }\n project.setPackageVersion(nextVersion, options.cwd);\n fix.fixAll(config, nextVersion, options.cwd);\n console.log(styles.success(`✓ Updated to ${nextVersion}`));\n }\n } catch (error) {\n console.error(styles.error(`✗ ${(error as Error).message}`));\n process.exit(1);\n }\n },\n );\n\n program\n .command('tag')\n .description('Create a git tag with automation')\n .argument('[version]', 'Version to tag (defaults to package.json version)')\n .option('-c, --cwd <path>', 'Working directory', process.cwd())\n .option('-m, --message <msg>', 'Tag message')\n .option('--no-fix', 'Skip auto-fixing files before tagging')\n .action(\n (version: string | undefined, options: { cwd: string; message?: string; fix?: boolean }) => {\n try {\n const config = versionguard.getConfig(options.cwd);\n const tagVersion = version || versionguard.getPackageVersion(options.cwd);\n const result = tag.createTag(\n tagVersion,\n options.message,\n options.fix !== false,\n config,\n options.cwd,\n );\n\n if (!result.success) {\n console.log(styles.error(`✗ ${result.message}`));\n process.exit(1);\n }\n\n console.log(styles.success(`✓ ${result.message}`));\n for (const action of result.actions) {\n console.log(` • ${action}`);\n }\n } catch (error) {\n console.error(styles.error(`✗ ${(error as Error).message}`));\n process.exit(1);\n }\n },\n );\n\n const hooksCommand = program.command('hooks').description('Manage git hooks');\n\n hooksCommand\n .command('install')\n .description('Install git hooks')\n .option('-c, --cwd <path>', 'Working directory', process.cwd())\n .action((options: { cwd: string }) => {\n try {\n const config = versionguard.getConfig(options.cwd);\n versionguard.installHooks(config.git, options.cwd);\n console.log(styles.success('✓ Git hooks installed'));\n } catch (error) {\n console.error(styles.error(`✗ ${(error as Error).message}`));\n process.exit(1);\n }\n });\n\n hooksCommand\n .command('uninstall')\n .description('Uninstall git hooks')\n .option('-c, --cwd <path>', 'Working directory', process.cwd())\n .action((options: { cwd: string }) => {\n try {\n versionguard.uninstallHooks(options.cwd);\n console.log(styles.success('✓ Git hooks uninstalled'));\n } catch (error) {\n console.error(styles.error(`✗ ${(error as Error).message}`));\n process.exit(1);\n }\n });\n\n hooksCommand\n .command('status')\n .description('Check if hooks are installed')\n .option('-c, --cwd <path>', 'Working directory', process.cwd())\n .action((options: { cwd: string }) => {\n try {\n if (versionguard.areHooksInstalled(options.cwd)) {\n console.log(styles.success('✓ VersionGuard hooks are installed'));\n return;\n }\n\n console.log(styles.warning('✗ VersionGuard hooks are not installed'));\n process.exit(1);\n } catch (error) {\n console.error(styles.error(`✗ ${(error as Error).message}`));\n process.exit(1);\n }\n });\n\n return program;\n}\n\n/**\n * Parses CLI arguments and executes the matching command.\n *\n * @public\n * @since 0.1.0\n * @remarks\n * This helper delegates argument parsing to the Commander program created by\n * {@link createProgram}. It resolves when the selected command finishes.\n *\n * @param argv - Full argument vector to parse.\n * @see {@link createProgram}\n *\n * @example\n * ```typescript\n * const argv = ['node', 'versionguard', 'check'];\n * await runCli(argv);\n * ```\n */\nexport async function runCli(argv: string[] = process.argv): Promise<void> {\n await createProgram().parseAsync(argv);\n}\n\n/**\n * Determines whether the current module is the invoked CLI entry point.\n *\n * @public\n * @since 0.1.0\n * @remarks\n * This helper compares the resolved script path from `argv` with the current\n * module URL so the CLI runs only during direct execution.\n *\n * @param argv - Full process argument vector.\n * @param metaUrl - Module URL to compare against the invoked entry path.\n * @returns `true` when the current module should launch the CLI.\n *\n * @example\n * ```typescript\n * const shouldRun = shouldRunCli(process.argv, import.meta.url);\n * console.log(shouldRun);\n * ```\n */\nexport function shouldRunCli(\n argv: string[] = process.argv,\n metaUrl: string = import.meta.url,\n): boolean {\n const entryPath = argv[1] ? path.resolve(argv[1]) : null;\n return entryPath === fileURLToPath(metaUrl);\n}\n\n/* v8 ignore start -- exercised only by direct CLI execution */\nif (shouldRunCli()) {\n void runCli();\n}\n/* v8 ignore stop */\n"],"names":["versionguard.initConfig","versionguard.getConfig","versionguard.getPackageVersion","feedback.getVersionFeedback","versionguard.validate","tag.handlePostTag","feedback.getSyncFeedback","feedback.getChangelogFeedback","versionguard.doctor","fix.fixAll","fix.fixSyncIssues","fix.suggestNextVersion","project.setPackageVersion","tag.createTag","versionguard.installHooks","versionguard.uninstallHooks","versionguard.areHooksInstalled"],"mappings":"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"}
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import type { VersionGuardConfig } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Returns a deep-cloned copy of the built-in VersionGuard configuration.
|
|
4
|
+
*
|
|
5
|
+
* @public
|
|
6
|
+
* @since 0.1.0
|
|
7
|
+
* @remarks
|
|
8
|
+
* A fresh clone is returned so callers can safely modify the result without
|
|
9
|
+
* mutating shared defaults.
|
|
10
|
+
*
|
|
11
|
+
* @returns The default VersionGuard configuration.
|
|
12
|
+
* @example
|
|
13
|
+
* ```ts
|
|
14
|
+
* import { getDefaultConfig } from 'versionguard';
|
|
15
|
+
*
|
|
16
|
+
* const config = getDefaultConfig();
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
export declare function getDefaultConfig(): VersionGuardConfig;
|
|
20
|
+
/**
|
|
21
|
+
* Finds the first supported VersionGuard config file in a directory.
|
|
22
|
+
*
|
|
23
|
+
* @public
|
|
24
|
+
* @since 0.1.0
|
|
25
|
+
* @remarks
|
|
26
|
+
* Search order follows `CONFIG_FILE_NAMES`, so `.versionguard.yml` takes
|
|
27
|
+
* precedence over the other supported filenames.
|
|
28
|
+
*
|
|
29
|
+
* @param cwd - Directory to search.
|
|
30
|
+
* @returns The resolved config path, or `null` when no config file exists.
|
|
31
|
+
* @example
|
|
32
|
+
* ```ts
|
|
33
|
+
* import { findConfig } from 'versionguard';
|
|
34
|
+
*
|
|
35
|
+
* const configPath = findConfig(process.cwd());
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
export declare function findConfig(cwd?: string): string | null;
|
|
39
|
+
/**
|
|
40
|
+
* Loads a VersionGuard config file from disk.
|
|
41
|
+
*
|
|
42
|
+
* @public
|
|
43
|
+
* @since 0.1.0
|
|
44
|
+
* @remarks
|
|
45
|
+
* The parsed YAML object is merged with the built-in defaults so omitted keys
|
|
46
|
+
* inherit their default values.
|
|
47
|
+
*
|
|
48
|
+
* @param configPath - Path to the YAML config file.
|
|
49
|
+
* @returns The merged VersionGuard configuration.
|
|
50
|
+
* @example
|
|
51
|
+
* ```ts
|
|
52
|
+
* import { loadConfig } from 'versionguard';
|
|
53
|
+
*
|
|
54
|
+
* const config = loadConfig('.versionguard.yml');
|
|
55
|
+
* ```
|
|
56
|
+
*/
|
|
57
|
+
export declare function loadConfig(configPath: string): VersionGuardConfig;
|
|
58
|
+
/**
|
|
59
|
+
* Resolves the active VersionGuard configuration for a project.
|
|
60
|
+
*
|
|
61
|
+
* @public
|
|
62
|
+
* @since 0.1.0
|
|
63
|
+
* @remarks
|
|
64
|
+
* If no config file is present, this falls back to the built-in defaults.
|
|
65
|
+
*
|
|
66
|
+
* @param cwd - Project directory to inspect.
|
|
67
|
+
* @returns The resolved VersionGuard configuration.
|
|
68
|
+
* @example
|
|
69
|
+
* ```ts
|
|
70
|
+
* import { getConfig } from 'versionguard';
|
|
71
|
+
*
|
|
72
|
+
* const config = getConfig(process.cwd());
|
|
73
|
+
* ```
|
|
74
|
+
*/
|
|
75
|
+
export declare function getConfig(cwd?: string): VersionGuardConfig;
|
|
76
|
+
/**
|
|
77
|
+
* Initializes a new VersionGuard config file in a project.
|
|
78
|
+
*
|
|
79
|
+
* @public
|
|
80
|
+
* @since 0.1.0
|
|
81
|
+
* @remarks
|
|
82
|
+
* This writes `.versionguard.yml` using the bundled example when available,
|
|
83
|
+
* otherwise it writes a generated default configuration.
|
|
84
|
+
*
|
|
85
|
+
* @param cwd - Project directory where the config should be created.
|
|
86
|
+
* @returns The path to the created config file.
|
|
87
|
+
* @example
|
|
88
|
+
* ```ts
|
|
89
|
+
* import { initConfig } from 'versionguard';
|
|
90
|
+
*
|
|
91
|
+
* const configPath = initConfig(process.cwd());
|
|
92
|
+
* ```
|
|
93
|
+
*/
|
|
94
|
+
export declare function initConfig(cwd?: string): string;
|
|
95
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAiDlD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,gBAAgB,IAAI,kBAAkB,CAErD;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,UAAU,CAAC,GAAG,GAAE,MAAsB,GAAG,MAAM,GAAG,IAAI,CASrE;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,UAAU,CAAC,UAAU,EAAE,MAAM,GAAG,kBAAkB,CAajE;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,SAAS,CAAC,GAAG,GAAE,MAAsB,GAAG,kBAAkB,CAGzE;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,UAAU,CAAC,GAAG,GAAE,MAAsB,GAAG,MAAM,CAe9D"}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import type { ValidationError, VersionGuardConfig } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* Feedback helpers that turn validation failures into actionable suggestions.
|
|
4
|
+
*
|
|
5
|
+
* @packageDocumentation
|
|
6
|
+
* @public
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Feedback entry point exports for suggestion and guidance helpers.
|
|
10
|
+
*
|
|
11
|
+
* @packageDocumentation
|
|
12
|
+
* @public
|
|
13
|
+
* @since 0.1.0
|
|
14
|
+
* @forgeIgnore E020
|
|
15
|
+
*/
|
|
16
|
+
export interface Suggestion {
|
|
17
|
+
/**
|
|
18
|
+
* Human-readable guidance for the user.
|
|
19
|
+
*/
|
|
20
|
+
message: string;
|
|
21
|
+
/**
|
|
22
|
+
* Command or action text that can be used to address the issue.
|
|
23
|
+
*
|
|
24
|
+
* @defaultValue `undefined`
|
|
25
|
+
*/
|
|
26
|
+
fix?: string;
|
|
27
|
+
/**
|
|
28
|
+
* Indicates whether VersionGuard can apply the suggestion automatically.
|
|
29
|
+
*/
|
|
30
|
+
autoFixable: boolean;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Aggregates validation errors with suggested next steps.
|
|
34
|
+
*
|
|
35
|
+
* @public
|
|
36
|
+
* @since 0.1.0
|
|
37
|
+
*/
|
|
38
|
+
export interface FeedbackResult {
|
|
39
|
+
/**
|
|
40
|
+
* Indicates whether the inspected version state is valid.
|
|
41
|
+
*/
|
|
42
|
+
valid: boolean;
|
|
43
|
+
/**
|
|
44
|
+
* Validation errors collected during the check.
|
|
45
|
+
*/
|
|
46
|
+
errors: ValidationError[];
|
|
47
|
+
/**
|
|
48
|
+
* Suggested next steps for resolving the reported issues.
|
|
49
|
+
*/
|
|
50
|
+
suggestions: Suggestion[];
|
|
51
|
+
/**
|
|
52
|
+
* Indicates whether at least one suggestion can be auto-applied.
|
|
53
|
+
*/
|
|
54
|
+
canAutoFix: boolean;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Generates actionable feedback for a version string.
|
|
58
|
+
*
|
|
59
|
+
* @public
|
|
60
|
+
* @since 0.1.0
|
|
61
|
+
* @remarks
|
|
62
|
+
* This helper dispatches to the SemVer or CalVer feedback flow based on the
|
|
63
|
+
* configured versioning strategy and returns both hard validation errors and
|
|
64
|
+
* softer suggestions for likely fixes.
|
|
65
|
+
*
|
|
66
|
+
* @param version - Version string to evaluate.
|
|
67
|
+
* @param config - Loaded VersionGuard configuration.
|
|
68
|
+
* @param previousVersion - Optional previous version used for progression checks.
|
|
69
|
+
* @returns A feedback object with validation errors and suggested fixes.
|
|
70
|
+
*
|
|
71
|
+
* @example
|
|
72
|
+
* ```typescript
|
|
73
|
+
* const feedbackResult = getVersionFeedback('1.2.3', config, '1.2.2');
|
|
74
|
+
* console.log(feedbackResult.valid);
|
|
75
|
+
* ```
|
|
76
|
+
*/
|
|
77
|
+
export declare function getVersionFeedback(version: string, config: VersionGuardConfig, previousVersion?: string): FeedbackResult;
|
|
78
|
+
/**
|
|
79
|
+
* Generates suggestions for version sync mismatches in a file.
|
|
80
|
+
*
|
|
81
|
+
* @public
|
|
82
|
+
* @since 0.1.0
|
|
83
|
+
* @remarks
|
|
84
|
+
* The returned suggestions include a general sync command and may include
|
|
85
|
+
* file-type-specific hints for markdown or source files.
|
|
86
|
+
*
|
|
87
|
+
* @param file - File containing the mismatched version string.
|
|
88
|
+
* @param foundVersion - Version currently found in the file.
|
|
89
|
+
* @param expectedVersion - Version that should appear in the file.
|
|
90
|
+
* @returns Suggestions for resolving the mismatch.
|
|
91
|
+
*
|
|
92
|
+
* @example
|
|
93
|
+
* ```typescript
|
|
94
|
+
* const suggestions = getSyncFeedback('README.md', '1.0.0', '1.0.1');
|
|
95
|
+
* console.log(suggestions[0]?.message);
|
|
96
|
+
* ```
|
|
97
|
+
*/
|
|
98
|
+
export declare function getSyncFeedback(file: string, foundVersion: string, expectedVersion: string): Suggestion[];
|
|
99
|
+
/**
|
|
100
|
+
* Generates suggestions for changelog-related validation issues.
|
|
101
|
+
*
|
|
102
|
+
* @public
|
|
103
|
+
* @since 0.1.0
|
|
104
|
+
* @remarks
|
|
105
|
+
* This helper suggests either creating a missing entry or reconciling the latest
|
|
106
|
+
* changelog version with the package version.
|
|
107
|
+
*
|
|
108
|
+
* @param hasEntry - Whether the changelog already contains an entry for the version.
|
|
109
|
+
* @param version - Package version that should appear in the changelog.
|
|
110
|
+
* @param latestChangelogVersion - Most recent version currently found in the changelog.
|
|
111
|
+
* @returns Suggestions for bringing changelog state back into sync.
|
|
112
|
+
*
|
|
113
|
+
* @example
|
|
114
|
+
* ```typescript
|
|
115
|
+
* const suggestions = getChangelogFeedback(false, '1.2.3', '1.2.2');
|
|
116
|
+
* console.log(suggestions.length > 0);
|
|
117
|
+
* ```
|
|
118
|
+
*/
|
|
119
|
+
export declare function getChangelogFeedback(hasEntry: boolean, version: string, latestChangelogVersion?: string): Suggestion[];
|
|
120
|
+
/**
|
|
121
|
+
* Generates suggestions for git tag mismatches.
|
|
122
|
+
*
|
|
123
|
+
* @public
|
|
124
|
+
* @since 0.1.0
|
|
125
|
+
* @remarks
|
|
126
|
+
* This helper focuses on discrepancies between git tag versions, package.json,
|
|
127
|
+
* and repository files that still need to be synchronized.
|
|
128
|
+
*
|
|
129
|
+
* @param tagVersion - Version represented by the git tag.
|
|
130
|
+
* @param packageVersion - Version currently stored in `package.json`.
|
|
131
|
+
* @param hasUnsyncedFiles - Whether repository files are still out of sync.
|
|
132
|
+
* @returns Suggestions for correcting tag-related issues.
|
|
133
|
+
*
|
|
134
|
+
* @example
|
|
135
|
+
* ```typescript
|
|
136
|
+
* const suggestions = getTagFeedback('v1.2.2', '1.2.3', true);
|
|
137
|
+
* console.log(suggestions.map((item) => item.message));
|
|
138
|
+
* ```
|
|
139
|
+
*/
|
|
140
|
+
export declare function getTagFeedback(tagVersion: string, packageVersion: string, hasUnsyncedFiles: boolean): Suggestion[];
|
|
141
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/feedback/index.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAwB,eAAe,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAE1F;;;;;GAKG;AAEH;;;;;;;GAOG;AACH,MAAM,WAAW,UAAU;IACzB;;OAEG;IACH,OAAO,EAAE,MAAM,CAAC;IAEhB;;;;OAIG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IAEb;;OAEG;IACH,WAAW,EAAE,OAAO,CAAC;CACtB;AAED;;;;;GAKG;AACH,MAAM,WAAW,cAAc;IAC7B;;OAEG;IACH,KAAK,EAAE,OAAO,CAAC;IAEf;;OAEG;IACH,MAAM,EAAE,eAAe,EAAE,CAAC;IAE1B;;OAEG;IACH,WAAW,EAAE,UAAU,EAAE,CAAC;IAE1B;;OAEG;IACH,UAAU,EAAE,OAAO,CAAC;CACrB;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,kBAAkB,EAC1B,eAAe,CAAC,EAAE,MAAM,GACvB,cAAc,CAMhB;AA+PD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,eAAe,CAC7B,IAAI,EAAE,MAAM,EACZ,YAAY,EAAE,MAAM,EACpB,eAAe,EAAE,MAAM,GACtB,UAAU,EAAE,CAyBd;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,OAAO,EACjB,OAAO,EAAE,MAAM,EACf,sBAAsB,CAAC,EAAE,MAAM,GAC9B,UAAU,EAAE,CAyBd;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,cAAc,CAC5B,UAAU,EAAE,MAAM,EAClB,cAAc,EAAE,MAAM,EACtB,gBAAgB,EAAE,OAAO,GACxB,UAAU,EAAE,CAoBd"}
|