@guiho/mirror 3.2.0 → 3.3.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +27 -0
- package/DOCS.md +142 -76
- package/README.md +15 -41
- package/jsr.json +4 -2
- package/package.json +11 -20
- package/schema/mirror.config.schema.json +231 -0
- package/scripts/install-package.ts +70 -0
- package/scripts/mirror-bin.ts +20 -0
- package/skills/guiho-as-mirror/SKILL.md +2 -29
- package/library/adapters.d.ts +0 -32
- package/library/adapters.d.ts.map +0 -1
- package/library/adapters.js +0 -210
- package/library/agents.d.ts +0 -27
- package/library/agents.d.ts.map +0 -1
- package/library/agents.js +0 -200
- package/library/cli.d.ts +0 -29
- package/library/cli.d.ts.map +0 -1
- package/library/cli.js +0 -387
- package/library/config.d.ts +0 -18
- package/library/config.d.ts.map +0 -1
- package/library/config.js +0 -277
- package/library/errors.d.ts +0 -9
- package/library/errors.d.ts.map +0 -1
- package/library/errors.js +0 -15
- package/library/executor.d.ts +0 -7
- package/library/executor.d.ts.map +0 -1
- package/library/executor.js +0 -32
- package/library/flags.d.ts +0 -6
- package/library/flags.d.ts.map +0 -1
- package/library/flags.js +0 -80
- package/library/guiho-mirror-bin.d.ts +0 -6
- package/library/guiho-mirror-bin.d.ts.map +0 -1
- package/library/guiho-mirror-bin.js +0 -6
- package/library/guiho-mirror.d.ts +0 -17
- package/library/guiho-mirror.d.ts.map +0 -1
- package/library/guiho-mirror.js +0 -15
- package/library/init.d.ts +0 -12
- package/library/init.d.ts.map +0 -1
- package/library/init.js +0 -100
- package/library/plan.d.ts +0 -10
- package/library/plan.d.ts.map +0 -1
- package/library/plan.js +0 -85
- package/library/reporter.d.ts +0 -14
- package/library/reporter.d.ts.map +0 -1
- package/library/reporter.js +0 -156
- package/library/schema.d.ts +0 -133
- package/library/schema.d.ts.map +0 -1
- package/library/schema.js +0 -128
- package/library/types.d.ts +0 -190
- package/library/types.d.ts.map +0 -1
- package/library/types.js +0 -4
- package/library/version.d.ts +0 -10
- package/library/version.d.ts.map +0 -1
- package/library/version.js +0 -31
package/library/agents.js
DELETED
|
@@ -1,200 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @copyright Copyright (c) 2026 GUIHO Technologies as represented by Cristóvão GUIHO. All Rights Reserved.
|
|
3
|
-
*/
|
|
4
|
-
import { existsSync } from 'node:fs';
|
|
5
|
-
import { mkdir, readFile, writeFile } from 'node:fs/promises';
|
|
6
|
-
import { homedir } from 'node:os';
|
|
7
|
-
import { dirname, resolve } from 'node:path';
|
|
8
|
-
import { MirrorError } from './errors.js';
|
|
9
|
-
import { discoverMirrorConfig, resolveMirrorPath } from './config.js';
|
|
10
|
-
export const mirrorSkillName = 'guiho-as-mirror';
|
|
11
|
-
export const mirrorAgentsSectionHeading = '## Semantic Project Versioning -- GUIHO Mirror';
|
|
12
|
-
export const defaultMirrorAgentSettings = {
|
|
13
|
-
writeChangelog: true,
|
|
14
|
-
changelogPath: 'CHANGELOG.md',
|
|
15
|
-
autoAgentsMd: true,
|
|
16
|
-
autoSkillInstall: true,
|
|
17
|
-
};
|
|
18
|
-
export const mirrorAgentsSection = `${mirrorAgentsSectionHeading}
|
|
19
|
-
|
|
20
|
-
Invoke the guiho-as-mirror agent skill every time the user wants to bump, tag, release, plan, initialize, configure, or troubleshoot semantic project versioning with GUIHO Mirror.
|
|
21
|
-
|
|
22
|
-
Before editing release docs or changelogs, inspect mirror.config.toml. If [agents].write_changelog is false, skip changelog edits. If it is missing or true, changelog edits are allowed when the project has a changelog.
|
|
23
|
-
|
|
24
|
-
Use [agents].changelog_path as the changelog file path. If it is missing, use CHANGELOG.md in the project root.
|
|
25
|
-
`;
|
|
26
|
-
export const resolveMirrorSkillPath = (scope, options = {}) => {
|
|
27
|
-
if (scope === 'local')
|
|
28
|
-
return resolve(options.cwd ?? process.cwd(), '.agents', 'skills', mirrorSkillName, 'SKILL.md');
|
|
29
|
-
return resolve(resolveMirrorAgentHome(options.homeDirectory), '.agents', 'skills', mirrorSkillName, 'SKILL.md');
|
|
30
|
-
};
|
|
31
|
-
export const isMirrorSkillInstalled = (scope, options = {}) => existsSync(resolveMirrorSkillPath(scope, options));
|
|
32
|
-
export const installMirrorSkill = async (scope, options = {}) => {
|
|
33
|
-
const path = resolveMirrorSkillPath(scope, options);
|
|
34
|
-
const exists = existsSync(path);
|
|
35
|
-
if (exists && options.overwrite === false)
|
|
36
|
-
return { scope, path, installed: false, updated: false };
|
|
37
|
-
const content = await readBundledMirrorSkill();
|
|
38
|
-
const current = exists ? await readFile(path, 'utf8') : undefined;
|
|
39
|
-
if (current === content)
|
|
40
|
-
return { scope, path, installed: false, updated: false };
|
|
41
|
-
await mkdir(dirname(path), { recursive: true });
|
|
42
|
-
await writeFile(path, content, 'utf8');
|
|
43
|
-
return { scope, path, installed: !exists, updated: exists };
|
|
44
|
-
};
|
|
45
|
-
export const ensureMirrorAgentsInstructions = async (cwd, create = false) => {
|
|
46
|
-
const path = findAgentsFile(cwd) ?? resolve(cwd, 'AGENTS.md');
|
|
47
|
-
const exists = existsSync(path);
|
|
48
|
-
if (!exists && !create)
|
|
49
|
-
return { path, exists: false, changed: false };
|
|
50
|
-
if (!exists) {
|
|
51
|
-
await writeFile(path, `# Project Agents\n\n${mirrorAgentsSection}\n`, 'utf8');
|
|
52
|
-
return { path, exists: true, changed: true };
|
|
53
|
-
}
|
|
54
|
-
const content = await readFile(path, 'utf8');
|
|
55
|
-
if (content.includes(mirrorAgentsSectionHeading))
|
|
56
|
-
return { path, exists: true, changed: false };
|
|
57
|
-
const nextContent = `${content.trimEnd()}\n\n${mirrorAgentsSection}\n`;
|
|
58
|
-
await writeFile(path, nextContent, 'utf8');
|
|
59
|
-
return { path, exists: true, changed: true };
|
|
60
|
-
};
|
|
61
|
-
export const findAgentsFile = (cwd) => {
|
|
62
|
-
let current = resolve(cwd);
|
|
63
|
-
while (true) {
|
|
64
|
-
const path = resolve(current, 'AGENTS.md');
|
|
65
|
-
if (existsSync(path))
|
|
66
|
-
return path;
|
|
67
|
-
const parent = dirname(current);
|
|
68
|
-
if (parent === current)
|
|
69
|
-
return undefined;
|
|
70
|
-
current = parent;
|
|
71
|
-
}
|
|
72
|
-
};
|
|
73
|
-
export const resolveMirrorAgentSettings = async (options = {}) => {
|
|
74
|
-
const cwd = resolve(options.cwd ?? process.cwd());
|
|
75
|
-
const discovered = await discoverMirrorConfig(cwd, options.config);
|
|
76
|
-
if (!discovered.raw)
|
|
77
|
-
return { ...defaultMirrorAgentSettings };
|
|
78
|
-
if (discovered.raw.schema !== 1)
|
|
79
|
-
throw new MirrorError('Unsupported or missing configuration schema. Expected `schema = 1`.');
|
|
80
|
-
return {
|
|
81
|
-
writeChangelog: optionalBoolean(discovered.raw.agents?.write_changelog, 'agents.write_changelog') !== false,
|
|
82
|
-
changelogPath: optionalString(discovered.raw.agents?.changelog_path, 'agents.changelog_path') ?? 'CHANGELOG.md',
|
|
83
|
-
autoAgentsMd: optionalBoolean(discovered.raw.agents?.auto_agents_md, 'agents.auto_agents_md') !== false,
|
|
84
|
-
autoSkillInstall: optionalBoolean(discovered.raw.agents?.auto_skill_install, 'agents.auto_skill_install') !== false,
|
|
85
|
-
};
|
|
86
|
-
};
|
|
87
|
-
export const runMirrorAgentAutomation = async (options = {}, notify = () => { }) => {
|
|
88
|
-
const cwd = resolve(options.cwd ?? process.cwd());
|
|
89
|
-
const settings = await resolveMirrorAgentSettings(options);
|
|
90
|
-
const result = { settings };
|
|
91
|
-
if (settings.autoAgentsMd)
|
|
92
|
-
result.agentsMd = await ensureMirrorAgentsInstructions(cwd, false);
|
|
93
|
-
if (settings.autoSkillInstall) {
|
|
94
|
-
const scope = 'global';
|
|
95
|
-
if (!isMirrorSkillInstalled(scope, { cwd, homeDirectory: options.homeDirectory })) {
|
|
96
|
-
const path = resolveMirrorSkillPath(scope, { cwd, homeDirectory: options.homeDirectory });
|
|
97
|
-
notify(`notice: ${mirrorSkillName} skill not found ${scope}; Mirror is installing it at ${path}`);
|
|
98
|
-
result.globalSkill = await installMirrorSkill(scope, { cwd, homeDirectory: options.homeDirectory, overwrite: false });
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
return result;
|
|
102
|
-
};
|
|
103
|
-
const readBundledMirrorSkill = async () => {
|
|
104
|
-
try {
|
|
105
|
-
return await readFile(new URL('../skills/guiho-as-mirror/SKILL.md', import.meta.url), 'utf8');
|
|
106
|
-
}
|
|
107
|
-
catch {
|
|
108
|
-
return embeddedMirrorSkillContent;
|
|
109
|
-
}
|
|
110
|
-
};
|
|
111
|
-
const resolveMirrorAgentHome = (homeDirectory) => {
|
|
112
|
-
const value = homeDirectory ?? process.env['MIRROR_AGENT_HOME'] ?? homedir();
|
|
113
|
-
return resolveMirrorPath(process.cwd(), value);
|
|
114
|
-
};
|
|
115
|
-
const optionalBoolean = (value, key) => {
|
|
116
|
-
if (value === undefined)
|
|
117
|
-
return undefined;
|
|
118
|
-
if (typeof value !== 'boolean')
|
|
119
|
-
throw new MirrorError(`Invalid ${key}. Expected true or false.`);
|
|
120
|
-
return value;
|
|
121
|
-
};
|
|
122
|
-
const optionalString = (value, key) => {
|
|
123
|
-
if (value === undefined)
|
|
124
|
-
return undefined;
|
|
125
|
-
if (typeof value !== 'string')
|
|
126
|
-
throw new MirrorError(`Invalid ${key}. Expected a string.`);
|
|
127
|
-
return value;
|
|
128
|
-
};
|
|
129
|
-
const embeddedMirrorSkillContent = [
|
|
130
|
-
'---',
|
|
131
|
-
'name: guiho-as-mirror',
|
|
132
|
-
'description: Use this skill whenever the user asks to version, bump, release, tag, initialize, configure, or troubleshoot a project with GUIHO Mirror. This includes Bun, npm, JSR, package.json, jsr.json, Git tag, semantic versioning, changelog, release-plan, prerelease, and what version comes next workflows.',
|
|
133
|
-
'---',
|
|
134
|
-
'',
|
|
135
|
-
'# GUIHO Mirror',
|
|
136
|
-
'',
|
|
137
|
-
'GUIHO Mirror is a deterministic CLI and TypeScript library for semantic project versioning. Use it instead of ad hoc version edits, manual package-manager version commands, or manual release tags.',
|
|
138
|
-
'',
|
|
139
|
-
'## Command Selection',
|
|
140
|
-
'',
|
|
141
|
-
'1. Use `bun @guiho/mirror` when the package is installed locally and Bun is available.',
|
|
142
|
-
'2. Use `mirror` when a global binary is available.',
|
|
143
|
-
'3. Use `bunx @guiho/mirror` when running without installation.',
|
|
144
|
-
'',
|
|
145
|
-
'Run `mirror --help` or `mirror <command> --help` for command-specific details when needed.',
|
|
146
|
-
'',
|
|
147
|
-
'## Release Workflow',
|
|
148
|
-
'',
|
|
149
|
-
'When the user asks to bump, release, tag, or version a project, follow this sequence:',
|
|
150
|
-
'',
|
|
151
|
-
'1. Confirm the target and project root. Supported targets are `major`, `premajor`, `minor`, `preminor`, `patch`, `prepatch`, `prerelease`, or an exact semver like `2.0.0`.',
|
|
152
|
-
'2. Run `<mirror> config show` and read `[git].allow_dirty`, `[agents].write_changelog`, and `[agents].changelog_path`.',
|
|
153
|
-
'3. If `allow_dirty = false` or absent, check `git status --short` and stop if the worktree is dirty.',
|
|
154
|
-
'4. Run the project type checker, commonly `bun run typecheck`.',
|
|
155
|
-
'5. Run the project test suite, commonly `bun test`.',
|
|
156
|
-
'6. Run `<mirror> version plan <target>` and use the planned next version as the source of truth.',
|
|
157
|
-
'7. Update release documentation only when it is part of the project release process.',
|
|
158
|
-
'8. If `[agents].write_changelog = false`, skip changelog edits. Otherwise update `[agents].changelog_path`, defaulting to `CHANGELOG.md` in the project root, and summarize only real changes.',
|
|
159
|
-
'9. Commit release-preparation changes before applying the version bump.',
|
|
160
|
-
'10. Run `<mirror> version apply <target> --yes`. Include `--commit` when file outputs and Git tag output are combined unless config already enables commits or push.',
|
|
161
|
-
'',
|
|
162
|
-
'## Safety Rules',
|
|
163
|
-
'',
|
|
164
|
-
'- Never skip `version plan`.',
|
|
165
|
-
'- Never hand-edit `package.json` or `jsr.json` version fields as a Mirror substitute.',
|
|
166
|
-
'- Never create Git tags manually for a Mirror-managed release unless recovering intentionally.',
|
|
167
|
-
'- Do not apply a version bump after failed typecheck or tests.',
|
|
168
|
-
'- Do not push release refs unless explicitly requested or configured.',
|
|
169
|
-
'- When plan output is surprising, stop and explain the mismatch.',
|
|
170
|
-
'',
|
|
171
|
-
'## Initialization Workflow',
|
|
172
|
-
'',
|
|
173
|
-
'Use `mirror init package.json`, `mirror init jsr.json`, or `mirror init git`, then validate with `mirror config check`, inspect with `mirror config show`, and test with `mirror version current` plus `mirror version plan patch`.',
|
|
174
|
-
'',
|
|
175
|
-
'## Configuration Reference',
|
|
176
|
-
'',
|
|
177
|
-
'Mirror searches for configuration via `--config <path>`, `./mirror.config.toml`, or `./config/mirror.config.toml`.',
|
|
178
|
-
'',
|
|
179
|
-
'Common configuration keys: `[version].source`, `[version].output`, `[version].prerelease_id`, `[git].tag_template`, `[git].commit`, `[git].push`, `[git].allow_dirty`, `[agents].write_changelog`, `[agents].changelog_path`, `[agents].auto_agents_md`, and `[agents].auto_skill_install`.',
|
|
180
|
-
'',
|
|
181
|
-
'Agent automation options default to true. Set `write_changelog = false` to tell agents to skip changelog edits, `changelog_path = "docs/CHANGELOG.md"` to specify the changelog file, `auto_agents_md = false` to stop Mirror from inserting its AGENTS.md section, and `auto_skill_install = false` to stop Mirror from installing `guiho-as-mirror` globally when missing.',
|
|
182
|
-
'',
|
|
183
|
-
'## CLI Reference',
|
|
184
|
-
'',
|
|
185
|
-
'- `mirror config show`',
|
|
186
|
-
'- `mirror config check`',
|
|
187
|
-
'- `mirror config schema`',
|
|
188
|
-
'- `mirror agents install local`',
|
|
189
|
-
'- `mirror agents install global`',
|
|
190
|
-
'- `mirror agents instructions`',
|
|
191
|
-
'- `mirror version current`',
|
|
192
|
-
'- `mirror version next <target>`',
|
|
193
|
-
'- `mirror version plan <target>`',
|
|
194
|
-
'- `mirror version apply <target> --yes`',
|
|
195
|
-
'',
|
|
196
|
-
'## Response Style',
|
|
197
|
-
'',
|
|
198
|
-
'When reporting a Mirror release result, include the target, current version, planned next version, typecheck/test status, docs or changelog files changed, final apply command, and whether commits, tags, or pushes were created.',
|
|
199
|
-
'',
|
|
200
|
-
].join('\n');
|
package/library/cli.d.ts
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @copyright Copyright (c) 2026 GUIHO Technologies as represented by Cristóvão GUIHO. All Rights Reserved.
|
|
3
|
-
*/
|
|
4
|
-
export declare const createMirrorCommand: () => import("citty").CommandDef<{
|
|
5
|
-
config: {
|
|
6
|
-
type: "string";
|
|
7
|
-
description: string;
|
|
8
|
-
};
|
|
9
|
-
cwd: {
|
|
10
|
-
type: "string";
|
|
11
|
-
description: string;
|
|
12
|
-
};
|
|
13
|
-
format: {
|
|
14
|
-
type: "enum";
|
|
15
|
-
options: string[];
|
|
16
|
-
default: string;
|
|
17
|
-
description: string;
|
|
18
|
-
};
|
|
19
|
-
'no-color': {
|
|
20
|
-
type: "boolean";
|
|
21
|
-
description: string;
|
|
22
|
-
};
|
|
23
|
-
verbose: {
|
|
24
|
-
type: "boolean";
|
|
25
|
-
description: string;
|
|
26
|
-
};
|
|
27
|
-
}>;
|
|
28
|
-
export declare const runMirrorCli: (rawArgs?: string[]) => Promise<void>;
|
|
29
|
-
//# sourceMappingURL=cli.d.ts.map
|
package/library/cli.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../source/cli.ts"],"names":[],"mappings":"AAAA;;GAEG;AA4DH,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;EAc5B,CAAA;AAEJ,eAAO,MAAM,YAAY,GAAU,kBAA+B,kBAwEjE,CAAA"}
|
package/library/cli.js
DELETED
|
@@ -1,387 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @copyright Copyright (c) 2026 GUIHO Technologies as represented by Cristóvão GUIHO. All Rights Reserved.
|
|
3
|
-
*/
|
|
4
|
-
import { defineCommand, runMain } from 'citty';
|
|
5
|
-
import { readFileSync } from 'node:fs';
|
|
6
|
-
import { resolve } from 'node:path';
|
|
7
|
-
import { ensureMirrorAgentsInstructions, installMirrorSkill, runMirrorAgentAutomation } from './agents.js';
|
|
8
|
-
import { MirrorError } from './errors.js';
|
|
9
|
-
import { readCurrentVersion, resolveProjectName } from './adapters.js';
|
|
10
|
-
import { configPathForDisplay, discoverMirrorConfig, loadMirrorConfig, relativeFromCwd, writeInitConfigFromAnswers } from './config.js';
|
|
11
|
-
import { executeVersionPlan } from './executor.js';
|
|
12
|
-
import { parseMirrorCliOptions } from './flags.js';
|
|
13
|
-
import { createReadlineInitPrompter, isInteractiveInit, resolveInitAnswers } from './init.js';
|
|
14
|
-
import { buildVersionPlan, validateMirrorConfig } from './plan.js';
|
|
15
|
-
import { mirrorBanner, reportAgentsInstructions, reportConfig, reportConfigSchema, reportExecution, reportExecutionSummary, reportPlan, reportSkillInstall, reportValue, } from './reporter.js';
|
|
16
|
-
import { resolveNextVersion } from './version.js';
|
|
17
|
-
const mirrorVersion = readInstalledVersion();
|
|
18
|
-
const globalArgs = {
|
|
19
|
-
config: { type: 'string', description: 'Path to mirror.config.toml' },
|
|
20
|
-
cwd: { type: 'string', description: 'Run as if Mirror started in this directory' },
|
|
21
|
-
format: { type: 'enum', options: ['text', 'json'], default: 'text', description: 'Output format' },
|
|
22
|
-
'no-color': { type: 'boolean', description: 'Disable color output' },
|
|
23
|
-
verbose: { type: 'boolean', description: 'Show full error details and stack traces' },
|
|
24
|
-
};
|
|
25
|
-
const overrideArgs = {
|
|
26
|
-
...globalArgs,
|
|
27
|
-
source: { type: 'enum', options: ['package.json', 'jsr.json', 'git'], description: 'Override version source' },
|
|
28
|
-
output: { type: 'string', description: 'Override version output. Repeat or comma-separate values.' },
|
|
29
|
-
'package-file': { type: 'string', description: 'Override package.json path' },
|
|
30
|
-
'jsr-file': { type: 'string', description: 'Override jsr.json path' },
|
|
31
|
-
preid: { type: 'string', description: 'Override prerelease identifier' },
|
|
32
|
-
};
|
|
33
|
-
const applyArgs = {
|
|
34
|
-
...overrideArgs,
|
|
35
|
-
'dry-run': { type: 'boolean', alias: 'dy', description: 'Build and print the plan without applying it' },
|
|
36
|
-
commit: { type: 'boolean', description: 'Create a release commit when file outputs changed' },
|
|
37
|
-
push: { type: 'boolean', description: 'Create the release commit when needed, then push release refs' },
|
|
38
|
-
'allow-dirty': { type: 'boolean', description: 'Allow release in a dirty Git worktree' },
|
|
39
|
-
yes: { type: 'boolean', alias: 'y', description: 'Apply without interactive confirmation' },
|
|
40
|
-
};
|
|
41
|
-
const targetArg = {
|
|
42
|
-
target: { type: 'positional', description: 'Release target or exact semantic version', required: true },
|
|
43
|
-
};
|
|
44
|
-
export const createMirrorCommand = () => defineCommand({
|
|
45
|
-
meta: {
|
|
46
|
-
name: 'mirror',
|
|
47
|
-
version: mirrorVersion,
|
|
48
|
-
description: 'Open source project versioning for Bun, npm, JSR, and Git.',
|
|
49
|
-
},
|
|
50
|
-
args: globalArgs,
|
|
51
|
-
subCommands: {
|
|
52
|
-
init: createInitCommand(),
|
|
53
|
-
config: createConfigCommand(),
|
|
54
|
-
agents: createAgentsCommand(),
|
|
55
|
-
version: createVersionCommand(),
|
|
56
|
-
},
|
|
57
|
-
});
|
|
58
|
-
export const runMirrorCli = async (rawArgs = process.argv.slice(2)) => {
|
|
59
|
-
const effectiveArgs = rawArgs.length === 0 ? ['--help'] : rawArgs;
|
|
60
|
-
const verbose = effectiveArgs.includes('--verbose');
|
|
61
|
-
const restoreColorOutput = effectiveArgs.includes('--no-color') ? stripColorFromProcessOutput() : () => { };
|
|
62
|
-
try {
|
|
63
|
-
if (effectiveArgs.includes('--no-color'))
|
|
64
|
-
process.env['NO_COLOR'] = '1';
|
|
65
|
-
if (rawArgs.length === 0) {
|
|
66
|
-
await prepareAgents({});
|
|
67
|
-
}
|
|
68
|
-
if (effectiveArgs.includes('--help')) {
|
|
69
|
-
const parsed = parseMirrorCliOptions(effectiveArgs);
|
|
70
|
-
const cwd = resolve(parsed.cwd ?? process.cwd());
|
|
71
|
-
const discovery = await discoverMirrorConfig(cwd, parsed.config);
|
|
72
|
-
const configDisplay = discovery.path ? relativeFromCwd(cwd, discovery.path) : '';
|
|
73
|
-
process.stdout.write(mirrorBanner(configDisplay));
|
|
74
|
-
}
|
|
75
|
-
if (rawArgs.length === 0) {
|
|
76
|
-
process.on('exit', () => {
|
|
77
|
-
process.stdout.write([
|
|
78
|
-
'EXAMPLES',
|
|
79
|
-
'',
|
|
80
|
-
' mirror version current # Print the current version',
|
|
81
|
-
' mirror version plan patch # Preview a patch release plan',
|
|
82
|
-
' mirror version apply minor --commit # Apply a minor release with commit',
|
|
83
|
-
' mirror version plan patch --output=package.json,jsr.json,git # Plan with package, jsr, and git',
|
|
84
|
-
' mirror agents install local # Install guiho-as-mirror in this project',
|
|
85
|
-
' mirror agents instructions # Insert Mirror guidance into AGENTS.md',
|
|
86
|
-
' mirror config schema # Print the configuration file reference',
|
|
87
|
-
'',
|
|
88
|
-
].join('\n') + '\n');
|
|
89
|
-
});
|
|
90
|
-
}
|
|
91
|
-
let capturedError = undefined;
|
|
92
|
-
const originalConsoleError = console.error;
|
|
93
|
-
console.error = (...args) => {
|
|
94
|
-
if (args.length > 0 && args[0] instanceof Error) {
|
|
95
|
-
capturedError = args[0];
|
|
96
|
-
return;
|
|
97
|
-
}
|
|
98
|
-
originalConsoleError(...args);
|
|
99
|
-
};
|
|
100
|
-
const originalProcessExit = process.exit;
|
|
101
|
-
let exitCode;
|
|
102
|
-
process.exit = ((code) => {
|
|
103
|
-
if (code !== 0 && capturedError) {
|
|
104
|
-
exitCode = code;
|
|
105
|
-
return undefined;
|
|
106
|
-
}
|
|
107
|
-
originalProcessExit(code);
|
|
108
|
-
});
|
|
109
|
-
try {
|
|
110
|
-
await runMain(createMirrorCommand(), { rawArgs: effectiveArgs });
|
|
111
|
-
}
|
|
112
|
-
finally {
|
|
113
|
-
console.error = originalConsoleError;
|
|
114
|
-
process.exit = originalProcessExit;
|
|
115
|
-
}
|
|
116
|
-
if (capturedError) {
|
|
117
|
-
handleCliError(capturedError, verbose, exitCode);
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
catch (error) {
|
|
121
|
-
handleCliError(error, verbose);
|
|
122
|
-
}
|
|
123
|
-
finally {
|
|
124
|
-
restoreColorOutput();
|
|
125
|
-
}
|
|
126
|
-
};
|
|
127
|
-
const handleCliError = (error, verbose, exitCode) => {
|
|
128
|
-
if (error instanceof MirrorError) {
|
|
129
|
-
console.error(`error: ${error.message}`);
|
|
130
|
-
if (verbose)
|
|
131
|
-
console.error(error.stack);
|
|
132
|
-
process.exit(error.exitCode);
|
|
133
|
-
}
|
|
134
|
-
if (error instanceof Error) {
|
|
135
|
-
console.error(`error: ${error.message}`);
|
|
136
|
-
if (verbose)
|
|
137
|
-
console.error(error.stack);
|
|
138
|
-
}
|
|
139
|
-
else {
|
|
140
|
-
console.error('error: An unexpected error occurred.');
|
|
141
|
-
if (verbose)
|
|
142
|
-
console.error(error);
|
|
143
|
-
}
|
|
144
|
-
process.exit(exitCode ?? 1);
|
|
145
|
-
};
|
|
146
|
-
const createInitCommand = () => defineCommand({
|
|
147
|
-
meta: { name: 'init', description: 'Create or update a Mirror configuration file.' },
|
|
148
|
-
args: {
|
|
149
|
-
...globalArgs,
|
|
150
|
-
source: { type: 'positional', required: false, description: 'Version source: package.json, jsr.json, or git' },
|
|
151
|
-
output: { type: 'string', description: 'Version outputs. Repeat or comma-separate package.json, jsr.json, git.' },
|
|
152
|
-
'package-file': { type: 'string', description: 'Path to package.json' },
|
|
153
|
-
'jsr-file': { type: 'string', description: 'Path to jsr.json' },
|
|
154
|
-
auxiliary: { type: 'string', description: 'Auxiliary package.json paths. Repeat or comma-separate values.' },
|
|
155
|
-
'tag-template': { type: 'string', description: 'Git tag template' },
|
|
156
|
-
name: { type: 'string', description: 'Explicit project name' },
|
|
157
|
-
preid: { type: 'string', description: 'Default prerelease identifier' },
|
|
158
|
-
commit: { type: 'boolean', description: 'Create release commits' },
|
|
159
|
-
push: { type: 'boolean', description: 'Push release refs' },
|
|
160
|
-
'non-interactive': { type: 'boolean', description: 'Skip interactive prompts and use flags + defaults' },
|
|
161
|
-
yes: { type: 'boolean', description: 'Overwrite an existing mirror.config.toml with generated defaults' },
|
|
162
|
-
},
|
|
163
|
-
async run(context) {
|
|
164
|
-
const options = cliOptions(context.rawArgs, context.args);
|
|
165
|
-
const cwd = resolve(options.cwd ?? process.cwd());
|
|
166
|
-
const positionalSource = adapterArg(context.args['source']);
|
|
167
|
-
const commitProvided = context.rawArgs.includes('--commit');
|
|
168
|
-
const pushProvided = context.rawArgs.includes('--push');
|
|
169
|
-
const flags = {
|
|
170
|
-
source: options.source ?? positionalSource,
|
|
171
|
-
output: options.output,
|
|
172
|
-
packagePath: options.packageFile,
|
|
173
|
-
auxiliaryPaths: options.auxiliary,
|
|
174
|
-
jsrPath: options.jsrFile,
|
|
175
|
-
tagTemplate: options.tagTemplate,
|
|
176
|
-
name: options.name,
|
|
177
|
-
prereleaseId: options.preid,
|
|
178
|
-
commit: commitProvided ? options.commit : undefined,
|
|
179
|
-
push: pushProvided ? options.push : undefined,
|
|
180
|
-
};
|
|
181
|
-
const interactive = isInteractiveInit(options);
|
|
182
|
-
const prompter = interactive ? createReadlineInitPrompter() : undefined;
|
|
183
|
-
try {
|
|
184
|
-
const answers = await resolveInitAnswers(flags, cwd, prompter);
|
|
185
|
-
const path = await writeInitConfigFromAnswers(answers, cwd, Boolean(options.yes));
|
|
186
|
-
process.stdout.write(reportValue(`created ${path}`, options.format));
|
|
187
|
-
}
|
|
188
|
-
finally {
|
|
189
|
-
await prompter?.close();
|
|
190
|
-
}
|
|
191
|
-
},
|
|
192
|
-
});
|
|
193
|
-
const createConfigCommand = () => defineCommand({
|
|
194
|
-
meta: { name: 'config', description: 'Inspect and validate Mirror configuration.' },
|
|
195
|
-
subCommands: {
|
|
196
|
-
show: defineCommand({
|
|
197
|
-
meta: { name: 'show', description: 'Print the resolved configuration.' },
|
|
198
|
-
args: overrideArgs,
|
|
199
|
-
async run(context) {
|
|
200
|
-
const options = cliOptions(context.rawArgs, context.args);
|
|
201
|
-
await prepareAgents(options);
|
|
202
|
-
const config = await loadMirrorConfig(options);
|
|
203
|
-
if (options.format !== 'json')
|
|
204
|
-
process.stdout.write(mirrorBanner(configPathForDisplay(config)));
|
|
205
|
-
process.stdout.write(reportConfig(config, options.format));
|
|
206
|
-
},
|
|
207
|
-
}),
|
|
208
|
-
check: defineCommand({
|
|
209
|
-
meta: { name: 'check', description: 'Validate the resolved configuration.' },
|
|
210
|
-
args: overrideArgs,
|
|
211
|
-
async run(context) {
|
|
212
|
-
const options = cliOptions(context.rawArgs, context.args);
|
|
213
|
-
await prepareAgents(options);
|
|
214
|
-
await validateMirrorConfig(options);
|
|
215
|
-
process.stdout.write(reportValue('ok', options.format));
|
|
216
|
-
},
|
|
217
|
-
}),
|
|
218
|
-
schema: defineCommand({
|
|
219
|
-
meta: { name: 'schema', description: 'Print the configuration file reference.' },
|
|
220
|
-
args: globalArgs,
|
|
221
|
-
run(context) {
|
|
222
|
-
const options = cliOptions(context.rawArgs, context.args);
|
|
223
|
-
if (options.format !== 'json')
|
|
224
|
-
process.stdout.write(mirrorBanner());
|
|
225
|
-
process.stdout.write(reportConfigSchema(options.format));
|
|
226
|
-
},
|
|
227
|
-
}),
|
|
228
|
-
},
|
|
229
|
-
});
|
|
230
|
-
const createAgentsCommand = () => defineCommand({
|
|
231
|
-
meta: { name: 'agents', description: 'Install Mirror agent skills and AGENTS.md instructions.' },
|
|
232
|
-
subCommands: {
|
|
233
|
-
install: defineCommand({
|
|
234
|
-
meta: { name: 'install', description: 'Install the guiho-as-mirror agent skill.' },
|
|
235
|
-
subCommands: {
|
|
236
|
-
local: createInstallSkillCommand('local'),
|
|
237
|
-
global: createInstallSkillCommand('global'),
|
|
238
|
-
},
|
|
239
|
-
}),
|
|
240
|
-
instructions: defineCommand({
|
|
241
|
-
meta: { name: 'instructions', description: 'Insert GUIHO Mirror semantic versioning guidance into AGENTS.md.' },
|
|
242
|
-
args: globalArgs,
|
|
243
|
-
async run(context) {
|
|
244
|
-
const options = cliOptions(context.rawArgs, context.args);
|
|
245
|
-
const result = await ensureMirrorAgentsInstructions(resolve(options.cwd ?? process.cwd()), true);
|
|
246
|
-
process.stdout.write(reportAgentsInstructions(result, options.format));
|
|
247
|
-
},
|
|
248
|
-
}),
|
|
249
|
-
},
|
|
250
|
-
});
|
|
251
|
-
const createInstallSkillCommand = (scope) => defineCommand({
|
|
252
|
-
meta: { name: scope, description: `Install the guiho-as-mirror skill ${scope}.` },
|
|
253
|
-
args: globalArgs,
|
|
254
|
-
async run(context) {
|
|
255
|
-
const options = cliOptions(context.rawArgs, context.args);
|
|
256
|
-
const result = await installMirrorSkill(scope, { cwd: resolve(options.cwd ?? process.cwd()) });
|
|
257
|
-
process.stdout.write(reportSkillInstall(result, options.format));
|
|
258
|
-
},
|
|
259
|
-
});
|
|
260
|
-
const createVersionCommand = () => defineCommand({
|
|
261
|
-
meta: { name: 'version', description: 'Read, plan, and apply version changes.' },
|
|
262
|
-
subCommands: {
|
|
263
|
-
current: defineCommand({
|
|
264
|
-
meta: { name: 'current', description: 'Print the current project version.' },
|
|
265
|
-
args: overrideArgs,
|
|
266
|
-
async run(context) {
|
|
267
|
-
const options = cliOptions(context.rawArgs, context.args);
|
|
268
|
-
await prepareAgents(options);
|
|
269
|
-
const config = await loadMirrorConfig(options);
|
|
270
|
-
const projectName = await resolveProjectName(config);
|
|
271
|
-
process.stdout.write(reportValue(await readCurrentVersion(config, projectName), options.format));
|
|
272
|
-
},
|
|
273
|
-
}),
|
|
274
|
-
next: defineCommand({
|
|
275
|
-
meta: { name: 'next', description: 'Print the next version without checking outputs.' },
|
|
276
|
-
args: { ...overrideArgs, ...targetArg },
|
|
277
|
-
async run(context) {
|
|
278
|
-
const options = cliOptions(context.rawArgs, context.args);
|
|
279
|
-
await prepareAgents(options);
|
|
280
|
-
const config = await loadMirrorConfig(options);
|
|
281
|
-
const projectName = await resolveProjectName(config);
|
|
282
|
-
const currentVersion = await readCurrentVersion(config, projectName);
|
|
283
|
-
process.stdout.write(reportValue(resolveNextVersion(currentVersion, String(context.args['target']), config.version.prereleaseId), options.format));
|
|
284
|
-
},
|
|
285
|
-
}),
|
|
286
|
-
plan: defineCommand({
|
|
287
|
-
meta: { name: 'plan', description: 'Print the release plan without writing anything.' },
|
|
288
|
-
args: { ...overrideArgs, ...targetArg },
|
|
289
|
-
async run(context) {
|
|
290
|
-
const options = cliOptions(context.rawArgs, context.args);
|
|
291
|
-
await prepareAgents(options);
|
|
292
|
-
const plan = await buildVersionPlan(String(context.args['target']), options);
|
|
293
|
-
if (options.format !== 'json')
|
|
294
|
-
process.stdout.write(mirrorBanner(plan.configPath ? plan.configPath : ''));
|
|
295
|
-
process.stdout.write(reportPlan(plan, options.format));
|
|
296
|
-
},
|
|
297
|
-
}),
|
|
298
|
-
apply: defineCommand({
|
|
299
|
-
meta: { name: 'apply', description: 'Apply the release plan.' },
|
|
300
|
-
args: { ...applyArgs, ...targetArg },
|
|
301
|
-
async run(context) {
|
|
302
|
-
const options = cliOptions(context.rawArgs, context.args);
|
|
303
|
-
await prepareAgents(options);
|
|
304
|
-
const plan = await buildVersionPlan(String(context.args['target']), options);
|
|
305
|
-
if (options.format !== 'json')
|
|
306
|
-
process.stdout.write(mirrorBanner(plan.configPath ? plan.configPath : ''));
|
|
307
|
-
if (options.format !== 'json')
|
|
308
|
-
process.stdout.write(reportPlan(plan, options.format));
|
|
309
|
-
const result = await executeVersionPlan(plan, options);
|
|
310
|
-
process.stdout.write(options.format === 'json' ? reportExecution(result, options.format) : reportExecutionSummary(result, options.format));
|
|
311
|
-
},
|
|
312
|
-
}),
|
|
313
|
-
},
|
|
314
|
-
});
|
|
315
|
-
const cliOptions = (rawArgs, args) => {
|
|
316
|
-
const parsed = parseMirrorCliOptions(rawArgs);
|
|
317
|
-
return {
|
|
318
|
-
...parsed,
|
|
319
|
-
config: parsed.config ?? stringArg(args['config']),
|
|
320
|
-
cwd: parsed.cwd ?? stringArg(args['cwd']),
|
|
321
|
-
format: parsed.format ?? (args['format'] === 'json' ? 'json' : 'text'),
|
|
322
|
-
source: parsed.source ?? adapterArg(args['source']),
|
|
323
|
-
output: parsed.output ?? outputArg(args['output']),
|
|
324
|
-
packageFile: parsed.packageFile ?? stringArg(args['packageFile']),
|
|
325
|
-
jsrFile: parsed.jsrFile ?? stringArg(args['jsrFile']),
|
|
326
|
-
auxiliary: parsed.auxiliary ?? outputListArg(args['auxiliary']),
|
|
327
|
-
tagTemplate: parsed.tagTemplate ?? stringArg(args['tagTemplate']),
|
|
328
|
-
name: parsed.name ?? stringArg(args['name']),
|
|
329
|
-
preid: parsed.preid ?? stringArg(args['preid']),
|
|
330
|
-
dryRun: parsed.dryRun || args['dryRun'] === true,
|
|
331
|
-
commit: parsed.commit || args['commit'] === true,
|
|
332
|
-
push: parsed.push || args['push'] === true,
|
|
333
|
-
allowDirty: parsed.allowDirty || args['allowDirty'] === true,
|
|
334
|
-
nonInteractive: parsed.nonInteractive || args['nonInteractive'] === true,
|
|
335
|
-
yes: parsed.yes || args['yes'] === true,
|
|
336
|
-
verbose: parsed.verbose || args['verbose'] === true,
|
|
337
|
-
};
|
|
338
|
-
};
|
|
339
|
-
const stringArg = (value) => (typeof value === 'string' ? value : undefined);
|
|
340
|
-
const outputListArg = (value) => {
|
|
341
|
-
if (typeof value !== 'string')
|
|
342
|
-
return undefined;
|
|
343
|
-
const values = value.split(',').map((item) => item.trim()).filter(Boolean);
|
|
344
|
-
return values.length > 0 ? values : undefined;
|
|
345
|
-
};
|
|
346
|
-
const adapterArg = (value) => {
|
|
347
|
-
if (value === 'package.json' || value === 'jsr.json' || value === 'git')
|
|
348
|
-
return value;
|
|
349
|
-
return undefined;
|
|
350
|
-
};
|
|
351
|
-
const outputArg = (value) => {
|
|
352
|
-
if (typeof value !== 'string')
|
|
353
|
-
return undefined;
|
|
354
|
-
const values = value.split(',').map((item) => item.trim()).filter(Boolean);
|
|
355
|
-
if (values.length === 0)
|
|
356
|
-
return undefined;
|
|
357
|
-
return values.map((item) => {
|
|
358
|
-
const adapter = adapterArg(item);
|
|
359
|
-
if (!adapter)
|
|
360
|
-
throw new MirrorError(`Invalid --output value: ${item}`);
|
|
361
|
-
return adapter;
|
|
362
|
-
});
|
|
363
|
-
};
|
|
364
|
-
const prepareAgents = async (options) => {
|
|
365
|
-
await runMirrorAgentAutomation(options, (message) => console.error(message));
|
|
366
|
-
};
|
|
367
|
-
function readInstalledVersion() {
|
|
368
|
-
try {
|
|
369
|
-
const packageJson = JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf8'));
|
|
370
|
-
return typeof packageJson['version'] === 'string' ? packageJson['version'] : '0.0.0';
|
|
371
|
-
}
|
|
372
|
-
catch {
|
|
373
|
-
return '0.0.0';
|
|
374
|
-
}
|
|
375
|
-
}
|
|
376
|
-
const stripAnsi = (value) => value.replace(/\u001B\[[0-?]*[ -/]*[@-~]/g, '');
|
|
377
|
-
const stripColorFromProcessOutput = () => {
|
|
378
|
-
const originalLog = console.log;
|
|
379
|
-
const originalError = console.error;
|
|
380
|
-
console.log = (...values) => originalLog(...values.map(stripAnsiValue));
|
|
381
|
-
console.error = (...values) => originalError(...values.map(stripAnsiValue));
|
|
382
|
-
return () => {
|
|
383
|
-
console.log = originalLog;
|
|
384
|
-
console.error = originalError;
|
|
385
|
-
};
|
|
386
|
-
};
|
|
387
|
-
const stripAnsiValue = (value) => (typeof value === 'string' ? stripAnsi(value) : value);
|
package/library/config.d.ts
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @copyright Copyright (c) 2026 GUIHO Technologies as represented by Cristóvão GUIHO. All Rights Reserved.
|
|
3
|
-
*/
|
|
4
|
-
import type { MirrorAdapterName, MirrorCliOptions, MirrorConfig, MirrorConfigDiscovery, MirrorInitAnswers, MirrorRawConfig } from './types.js';
|
|
5
|
-
export declare const resolveMirrorPath: (cwd: string, path: string) => string;
|
|
6
|
-
export declare const relativeFromCwd: (cwd: string, path: string) => string;
|
|
7
|
-
export declare const discoverMirrorConfig: (cwd: string, explicitPath?: string) => Promise<MirrorConfigDiscovery>;
|
|
8
|
-
export declare const readConfigFile: (path: string) => Promise<MirrorRawConfig>;
|
|
9
|
-
export declare const loadMirrorConfig: (options?: MirrorCliOptions) => Promise<MirrorConfig>;
|
|
10
|
-
export declare const normalizeMirrorConfig: (raw: MirrorRawConfig, cwd: string, configPath: string | undefined, options?: MirrorCliOptions) => MirrorConfig;
|
|
11
|
-
export declare const defaultInitAnswersForSource: (kind: MirrorAdapterName, cwd: string) => MirrorInitAnswers;
|
|
12
|
-
export declare const generateInitConfig: (answers: MirrorInitAnswers, cwd: string) => string;
|
|
13
|
-
export declare const createInitConfig: (kind: MirrorAdapterName, cwd: string) => string;
|
|
14
|
-
export declare const writeInitConfig: (kind: MirrorAdapterName, cwd: string, overwrite?: boolean) => Promise<string>;
|
|
15
|
-
export declare const writeInitConfigFromAnswers: (answers: MirrorInitAnswers, cwd: string, overwrite?: boolean) => Promise<string>;
|
|
16
|
-
export declare const reconcileInitConfig: (existingContent: string, defaultsContent: string) => string;
|
|
17
|
-
export declare const configPathForDisplay: (config: MirrorConfig) => string;
|
|
18
|
-
//# sourceMappingURL=config.d.ts.map
|
package/library/config.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../source/config.ts"],"names":[],"mappings":"AAAA;;GAEG;AAMH,OAAO,KAAK,EACV,iBAAiB,EACjB,gBAAgB,EAChB,YAAY,EACZ,qBAAqB,EACrB,iBAAiB,EAEjB,eAAe,EAChB,MAAM,YAAY,CAAA;AAOnB,eAAO,MAAM,iBAAiB,GAAI,KAAK,MAAM,EAAE,MAAM,MAAM,WAAmD,CAAA;AAE9G,eAAO,MAAM,eAAe,GAAI,KAAK,MAAM,EAAE,MAAM,MAAM,WAGxD,CAAA;AAED,eAAO,MAAM,oBAAoB,GAAU,KAAK,MAAM,EAAE,eAAe,MAAM,KAAG,OAAO,CAAC,qBAAqB,CAa5G,CAAA;AAED,eAAO,MAAM,cAAc,GAAU,MAAM,MAAM,KAAG,OAAO,CAAC,eAAe,CAe1E,CAAA;AAED,eAAO,MAAM,gBAAgB,GAAU,UAAS,gBAAqB,KAAG,OAAO,CAAC,YAAY,CAO3F,CAAA;AAED,eAAO,MAAM,qBAAqB,GAChC,KAAK,eAAe,EACpB,KAAK,MAAM,EACX,YAAY,MAAM,GAAG,SAAS,EAC9B,UAAS,gBAAqB,KAC7B,YAyDF,CAAA;AAED,eAAO,MAAM,2BAA2B,GAAI,MAAM,iBAAiB,EAAE,KAAK,MAAM,KAAG,iBAWjF,CAAA;AAEF,eAAO,MAAM,kBAAkB,GAAI,SAAS,iBAAiB,EAAE,KAAK,MAAM,WAsCzE,CAAA;AAED,eAAO,MAAM,gBAAgB,GAAI,MAAM,iBAAiB,EAAE,KAAK,MAAM,WAAoE,CAAA;AAEzI,eAAO,MAAM,eAAe,GAAU,MAAM,iBAAiB,EAAE,KAAK,MAAM,EAAE,mBAAiB,oBACT,CAAA;AAEpF,eAAO,MAAM,0BAA0B,GAAU,SAAS,iBAAiB,EAAE,KAAK,MAAM,EAAE,mBAAiB,oBAW1G,CAAA;AAED,eAAO,MAAM,mBAAmB,GAAI,iBAAiB,MAAM,EAAE,iBAAiB,MAAM,WAyBnF,CAAA;AAED,eAAO,MAAM,oBAAoB,GAAI,QAAQ,YAAY,WAAoF,CAAA"}
|