@guiho/mirror 3.1.2 → 3.2.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 +26 -0
- package/DOCS.md +129 -6
- package/README.md +8 -5
- package/jsr.json +1 -1
- package/library/adapters.d.ts +4 -0
- package/library/adapters.d.ts.map +1 -1
- package/library/adapters.js +8 -1
- package/library/agents.d.ts +3 -1
- package/library/agents.d.ts.map +1 -1
- package/library/agents.js +14 -2
- package/library/cli.d.ts.map +1 -1
- package/library/cli.js +87 -20
- package/library/config.d.ts +5 -1
- package/library/config.d.ts.map +1 -1
- package/library/config.js +138 -89
- package/library/executor.d.ts +2 -2
- package/library/executor.d.ts.map +1 -1
- package/library/executor.js +27 -13
- package/library/flags.d.ts.map +1 -1
- package/library/flags.js +11 -1
- package/library/guiho-mirror.d.ts +7 -4
- package/library/guiho-mirror.d.ts.map +1 -1
- package/library/guiho-mirror.js +6 -3
- package/library/hooks.d.ts +14 -0
- package/library/hooks.d.ts.map +1 -0
- package/library/hooks.js +122 -0
- package/library/init.d.ts +12 -0
- package/library/init.d.ts.map +1 -0
- package/library/init.js +100 -0
- package/library/plan.d.ts.map +1 -1
- package/library/plan.js +9 -5
- package/library/reporter.d.ts +2 -1
- package/library/reporter.d.ts.map +1 -1
- package/library/reporter.js +31 -2
- package/library/schema.d.ts +164 -0
- package/library/schema.d.ts.map +1 -0
- package/library/schema.js +152 -0
- package/library/types.d.ts +50 -0
- package/library/types.d.ts.map +1 -1
- package/package.json +2 -1
- package/schema/mirror.config.schema.json +379 -0
- package/skills/guiho-as-mirror/SKILL.md +13 -7
package/library/config.js
CHANGED
|
@@ -6,6 +6,8 @@ import { readFile, writeFile } from 'node:fs/promises';
|
|
|
6
6
|
import { basename, isAbsolute, join, relative, resolve } from 'node:path';
|
|
7
7
|
import { parse as parseToml } from 'smol-toml';
|
|
8
8
|
import { MirrorError } from './errors.js';
|
|
9
|
+
import { mirrorConfigSchemaReference } from './schema.js';
|
|
10
|
+
import { normalizeHooksConfig } from './hooks.js';
|
|
9
11
|
const adapters = new Set(['package.json', 'jsr.json', 'git']);
|
|
10
12
|
const projectNameSources = new Set(['package.json', 'jsr.json']);
|
|
11
13
|
export const resolveMirrorPath = (cwd, path) => (isAbsolute(path) ? path : resolve(cwd, path));
|
|
@@ -62,6 +64,7 @@ export const normalizeMirrorConfig = (raw, cwd, configPath, options = {}) => {
|
|
|
62
64
|
const projectName = optionalString(raw.project?.name, 'project.name');
|
|
63
65
|
const prereleaseId = options.preid ?? optionalString(raw.version?.prerelease_id, 'version.prerelease_id') ?? '';
|
|
64
66
|
const packagePath = options.packageFile ?? optionalString(raw.package?.path, 'package.path') ?? 'package.json';
|
|
67
|
+
const packageAuxiliaryPaths = assertStringArray(raw.package?.auxiliary_paths, 'package.auxiliary_paths');
|
|
65
68
|
const jsrPath = options.jsrFile ?? optionalString(raw.jsr?.path, 'jsr.path') ?? 'jsr.json';
|
|
66
69
|
const tagTemplate = optionalString(raw.git?.tag_template, 'git.tag_template') ?? 'v{version}';
|
|
67
70
|
const gitCommit = optionalBoolean(raw.git?.commit, 'git.commit') === true;
|
|
@@ -71,6 +74,7 @@ export const normalizeMirrorConfig = (raw, cwd, configPath, options = {}) => {
|
|
|
71
74
|
const changelogPath = optionalString(raw.agents?.changelog_path, 'agents.changelog_path') ?? 'CHANGELOG.md';
|
|
72
75
|
const autoAgentsMd = optionalBoolean(raw.agents?.auto_agents_md, 'agents.auto_agents_md') !== false;
|
|
73
76
|
const autoSkillInstall = optionalBoolean(raw.agents?.auto_skill_install, 'agents.auto_skill_install') !== false;
|
|
77
|
+
const hooks = normalizeHooksConfig(raw.hooks);
|
|
74
78
|
return {
|
|
75
79
|
schema: 1,
|
|
76
80
|
cwd,
|
|
@@ -87,6 +91,7 @@ export const normalizeMirrorConfig = (raw, cwd, configPath, options = {}) => {
|
|
|
87
91
|
},
|
|
88
92
|
package: {
|
|
89
93
|
path: packagePath,
|
|
94
|
+
auxiliaryPaths: packageAuxiliaryPaths,
|
|
90
95
|
},
|
|
91
96
|
jsr: {
|
|
92
97
|
path: jsrPath,
|
|
@@ -103,100 +108,93 @@ export const normalizeMirrorConfig = (raw, cwd, configPath, options = {}) => {
|
|
|
103
108
|
autoAgentsMd,
|
|
104
109
|
autoSkillInstall,
|
|
105
110
|
},
|
|
111
|
+
hooks,
|
|
106
112
|
};
|
|
107
113
|
};
|
|
108
|
-
export const
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
[
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
[
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
[
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
[
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
write_changelog = true
|
|
164
|
-
changelog_path = "CHANGELOG.md"
|
|
165
|
-
auto_agents_md = true
|
|
166
|
-
auto_skill_install = true
|
|
167
|
-
`;
|
|
168
|
-
}
|
|
169
|
-
return `schema = 1
|
|
170
|
-
|
|
171
|
-
[project]
|
|
172
|
-
name = "${projectName}"
|
|
173
|
-
|
|
174
|
-
[version]
|
|
175
|
-
scheme = "semver"
|
|
176
|
-
source = "git"
|
|
177
|
-
output = ["git"]
|
|
178
|
-
prerelease_id = ""
|
|
179
|
-
|
|
180
|
-
[git]
|
|
181
|
-
tag_template = "v{version}"
|
|
182
|
-
commit = false
|
|
183
|
-
push = false
|
|
184
|
-
allow_dirty = false
|
|
185
|
-
|
|
186
|
-
[agents]
|
|
187
|
-
write_changelog = true
|
|
188
|
-
changelog_path = "CHANGELOG.md"
|
|
189
|
-
auto_agents_md = true
|
|
190
|
-
auto_skill_install = true
|
|
191
|
-
`;
|
|
192
|
-
};
|
|
193
|
-
export const writeInitConfig = async (kind, cwd, overwrite = false) => {
|
|
114
|
+
export const defaultInitAnswersForSource = (kind, cwd) => ({
|
|
115
|
+
source: kind,
|
|
116
|
+
output: kind === 'git' ? ['git'] : [kind, 'git'],
|
|
117
|
+
packagePath: 'package.json',
|
|
118
|
+
auxiliaryPaths: [],
|
|
119
|
+
jsrPath: 'jsr.json',
|
|
120
|
+
name: kind === 'git' ? basename(cwd) : undefined,
|
|
121
|
+
prereleaseId: '',
|
|
122
|
+
tagTemplate: '{name}@{version}',
|
|
123
|
+
commit: kind !== 'git',
|
|
124
|
+
push: false,
|
|
125
|
+
});
|
|
126
|
+
export const generateInitConfig = (answers, cwd) => {
|
|
127
|
+
const lines = [];
|
|
128
|
+
lines.push(`#:schema ${mirrorConfigSchemaReference}`);
|
|
129
|
+
lines.push('');
|
|
130
|
+
lines.push('schema = 1');
|
|
131
|
+
lines.push('');
|
|
132
|
+
lines.push('[project]');
|
|
133
|
+
if (answers.source === 'package.json')
|
|
134
|
+
lines.push('name_source = "package.json"');
|
|
135
|
+
else if (answers.source === 'jsr.json')
|
|
136
|
+
lines.push('name_source = "jsr.json"');
|
|
137
|
+
else
|
|
138
|
+
lines.push(`name = "${answers.name ?? basename(cwd)}"`);
|
|
139
|
+
lines.push('');
|
|
140
|
+
lines.push('[version]');
|
|
141
|
+
lines.push('scheme = "semver"');
|
|
142
|
+
lines.push(`source = "${answers.source}"`);
|
|
143
|
+
lines.push(`output = [${answers.output.map((value) => `"${value}"`).join(', ')}]`);
|
|
144
|
+
lines.push(`prerelease_id = "${answers.prereleaseId}"`);
|
|
145
|
+
lines.push('');
|
|
146
|
+
lines.push('[package]');
|
|
147
|
+
lines.push(`path = "${answers.packagePath}"`);
|
|
148
|
+
lines.push(`auxiliary_paths = [${answers.auxiliaryPaths.map((value) => `"${value}"`).join(', ')}]`);
|
|
149
|
+
lines.push('');
|
|
150
|
+
lines.push('[jsr]');
|
|
151
|
+
lines.push(`path = "${answers.jsrPath}"`);
|
|
152
|
+
lines.push('');
|
|
153
|
+
lines.push('[git]');
|
|
154
|
+
lines.push(`tag_template = "${answers.tagTemplate}"`);
|
|
155
|
+
lines.push(`commit = ${String(answers.commit)}`);
|
|
156
|
+
lines.push(`push = ${String(answers.push)}`);
|
|
157
|
+
lines.push('allow_dirty = false');
|
|
158
|
+
lines.push('');
|
|
159
|
+
lines.push('[agents]');
|
|
160
|
+
lines.push('write_changelog = true');
|
|
161
|
+
lines.push('changelog_path = "CHANGELOG.md"');
|
|
162
|
+
lines.push('auto_agents_md = true');
|
|
163
|
+
lines.push('auto_skill_install = true');
|
|
164
|
+
return `${lines.join('\n')}\n`;
|
|
165
|
+
};
|
|
166
|
+
export const createInitConfig = (kind, cwd) => generateInitConfig(defaultInitAnswersForSource(kind, cwd), cwd);
|
|
167
|
+
export const writeInitConfig = async (kind, cwd, overwrite = false) => writeInitConfigFromAnswers(defaultInitAnswersForSource(kind, cwd), cwd, overwrite);
|
|
168
|
+
export const writeInitConfigFromAnswers = async (answers, cwd, overwrite = false) => {
|
|
194
169
|
const path = join(cwd, 'mirror.config.toml');
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
170
|
+
const generated = generateInitConfig(answers, cwd);
|
|
171
|
+
if (existsSync(path) && !overwrite) {
|
|
172
|
+
await writeFile(path, reconcileInitConfig(await readFile(path, 'utf8'), generated), 'utf8');
|
|
173
|
+
return path;
|
|
174
|
+
}
|
|
175
|
+
await writeFile(path, generated, 'utf8');
|
|
198
176
|
return path;
|
|
199
177
|
};
|
|
178
|
+
export const reconcileInitConfig = (existingContent, defaultsContent) => {
|
|
179
|
+
const existingRaw = parseConfigContent(existingContent, 'existing configuration');
|
|
180
|
+
const defaultsRaw = parseConfigContent(defaultsContent, 'default configuration');
|
|
181
|
+
const additions = [];
|
|
182
|
+
for (const [sectionName, defaultSection] of Object.entries(defaultsRaw)) {
|
|
183
|
+
if (!isRecord(defaultSection))
|
|
184
|
+
continue;
|
|
185
|
+
const existingSection = existingRaw[sectionName];
|
|
186
|
+
if (!isRecord(existingSection)) {
|
|
187
|
+
additions.push(renderTomlSection(sectionName, defaultSection));
|
|
188
|
+
continue;
|
|
189
|
+
}
|
|
190
|
+
const missingValues = Object.fromEntries(Object.entries(defaultSection).filter(([key]) => existingSection[key] === undefined));
|
|
191
|
+
if (Object.keys(missingValues).length > 0)
|
|
192
|
+
existingContent = insertTomlValuesIntoSection(existingContent, sectionName, missingValues);
|
|
193
|
+
}
|
|
194
|
+
if (additions.length === 0)
|
|
195
|
+
return existingContent;
|
|
196
|
+
return `${existingContent.trimEnd()}\n\n${additions.join('\n\n')}\n`;
|
|
197
|
+
};
|
|
200
198
|
export const configPathForDisplay = (config) => (config.configPath ? relativeFromCwd(config.cwd, config.configPath) : '(none)');
|
|
201
199
|
const assertAdapter = (value, key) => {
|
|
202
200
|
if (typeof value !== 'string' || !adapters.has(value))
|
|
@@ -213,6 +211,17 @@ const assertOutput = (value) => {
|
|
|
213
211
|
throw new MirrorError('Invalid or missing version.output. Expected at least one output adapter.');
|
|
214
212
|
return value.map((item) => assertAdapter(item, 'version.output'));
|
|
215
213
|
};
|
|
214
|
+
const assertStringArray = (value, key) => {
|
|
215
|
+
if (value === undefined)
|
|
216
|
+
return [];
|
|
217
|
+
if (!Array.isArray(value))
|
|
218
|
+
throw new MirrorError(`Invalid ${key}. Expected an array of strings.`);
|
|
219
|
+
return value.map((item) => {
|
|
220
|
+
if (typeof item !== 'string' || item.length === 0)
|
|
221
|
+
throw new MirrorError(`Invalid ${key}. Expected an array of strings.`);
|
|
222
|
+
return item;
|
|
223
|
+
});
|
|
224
|
+
};
|
|
216
225
|
const dedupeAdapters = (value) => [...new Set(value)];
|
|
217
226
|
const optionalString = (value, key) => {
|
|
218
227
|
if (value === undefined)
|
|
@@ -229,3 +238,43 @@ const optionalBoolean = (value, key) => {
|
|
|
229
238
|
return value;
|
|
230
239
|
};
|
|
231
240
|
const isRecord = (value) => typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
241
|
+
const parseConfigContent = (content, label) => {
|
|
242
|
+
let parsed;
|
|
243
|
+
try {
|
|
244
|
+
parsed = parseToml(content);
|
|
245
|
+
}
|
|
246
|
+
catch (error) {
|
|
247
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
248
|
+
throw new MirrorError(`Invalid TOML in ${label}:\n${message}`);
|
|
249
|
+
}
|
|
250
|
+
if (!isRecord(parsed))
|
|
251
|
+
throw new MirrorError(`Invalid ${label}. Expected a TOML object.`);
|
|
252
|
+
return parsed;
|
|
253
|
+
};
|
|
254
|
+
const renderTomlSection = (sectionName, values) => {
|
|
255
|
+
const lines = [`[${sectionName}]`];
|
|
256
|
+
for (const [key, value] of Object.entries(values)) {
|
|
257
|
+
lines.push(`${key} = ${renderTomlValue(value)}`);
|
|
258
|
+
}
|
|
259
|
+
return lines.join('\n');
|
|
260
|
+
};
|
|
261
|
+
const insertTomlValuesIntoSection = (content, sectionName, values) => {
|
|
262
|
+
const lines = content.split(/\r?\n/);
|
|
263
|
+
const sectionIndex = lines.findIndex((line) => line.trim() === `[${sectionName}]`);
|
|
264
|
+
if (sectionIndex === -1)
|
|
265
|
+
return `${content.trimEnd()}\n\n${renderTomlSection(sectionName, values)}\n`;
|
|
266
|
+
const nextSectionIndex = lines.findIndex((line, index) => index > sectionIndex && /^\[[^\]]+]\s*$/.test(line.trim()));
|
|
267
|
+
const insertIndex = nextSectionIndex === -1 ? lines.length : nextSectionIndex;
|
|
268
|
+
const renderedValues = Object.entries(values).map(([key, value]) => `${key} = ${renderTomlValue(value)}`);
|
|
269
|
+
lines.splice(insertIndex, 0, ...renderedValues);
|
|
270
|
+
return lines.join('\n');
|
|
271
|
+
};
|
|
272
|
+
const renderTomlValue = (value) => {
|
|
273
|
+
if (typeof value === 'string')
|
|
274
|
+
return JSON.stringify(value);
|
|
275
|
+
if (typeof value === 'number' || typeof value === 'boolean')
|
|
276
|
+
return String(value);
|
|
277
|
+
if (Array.isArray(value))
|
|
278
|
+
return `[${value.map(renderTomlValue).join(', ')}]`;
|
|
279
|
+
throw new MirrorError('Cannot render unsupported init configuration value.');
|
|
280
|
+
};
|
package/library/executor.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @copyright Copyright (c) 2026 GUIHO Technologies as represented by Cristóvão GUIHO. All Rights Reserved.
|
|
3
3
|
*/
|
|
4
|
-
import type { MirrorCliOptions, MirrorExecutionResult } from './types.js';
|
|
4
|
+
import type { MirrorCliOptions, MirrorExecutionResult, MirrorHooksConfig } from './types.js';
|
|
5
5
|
export declare const applyVersionPlan: (target: string, options?: MirrorCliOptions) => Promise<MirrorExecutionResult>;
|
|
6
|
-
export declare const executeVersionPlan: (plan: MirrorExecutionResult["plan"], options?: MirrorCliOptions) => Promise<MirrorExecutionResult>;
|
|
6
|
+
export declare const executeVersionPlan: (plan: MirrorExecutionResult["plan"], options?: MirrorCliOptions, hooks?: MirrorHooksConfig, target?: string) => Promise<MirrorExecutionResult>;
|
|
7
7
|
//# sourceMappingURL=executor.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"executor.d.ts","sourceRoot":"","sources":["../source/executor.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAA;
|
|
1
|
+
{"version":3,"file":"executor.d.ts","sourceRoot":"","sources":["../source/executor.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA;AAM5F,eAAO,MAAM,gBAAgB,GAAU,QAAQ,MAAM,EAAE,UAAS,gBAAqB,KAAG,OAAO,CAAC,qBAAqB,CAIpH,CAAA;AAED,eAAO,MAAM,kBAAkB,GAC7B,MAAM,qBAAqB,CAAC,MAAM,CAAC,EACnC,UAAS,gBAAqB,EAC9B,QAAQ,iBAAiB,EACzB,eAAyB,KACxB,OAAO,CAAC,qBAAqB,CAoC/B,CAAA"}
|
package/library/executor.js
CHANGED
|
@@ -2,33 +2,47 @@
|
|
|
2
2
|
* @copyright Copyright (c) 2026 GUIHO Technologies as represented by Cristóvão GUIHO. All Rights Reserved.
|
|
3
3
|
*/
|
|
4
4
|
import { MirrorError } from './errors.js';
|
|
5
|
-
import { createGitCommit, createGitTag, isGitDirty, isGitRepository, pushGitRefs,
|
|
6
|
-
import { loadMirrorConfig } from './config.js';
|
|
5
|
+
import { createGitCommit, createGitTag, isGitDirty, isGitRepository, pushGitRefs, writeJsrVersionFile, writePackageVersionFile } from './adapters.js';
|
|
7
6
|
import { buildVersionPlan } from './plan.js';
|
|
7
|
+
import { hookEnvForAction, runActionHooks } from './hooks.js';
|
|
8
8
|
export const applyVersionPlan = async (target, options = {}) => {
|
|
9
9
|
const plan = await buildVersionPlan(target, options);
|
|
10
10
|
return executeVersionPlan(plan, options);
|
|
11
11
|
};
|
|
12
|
-
export const executeVersionPlan = async (plan, options = {}) => {
|
|
12
|
+
export const executeVersionPlan = async (plan, options = {}, hooks, target = plan.nextVersion) => {
|
|
13
|
+
const hookResults = [];
|
|
13
14
|
if (options.dryRun)
|
|
14
|
-
return { plan, applied: false, dryRun: true };
|
|
15
|
+
return { plan, applied: false, dryRun: true, hookResults };
|
|
15
16
|
if (!plan.allowDirty && (await isGitRepository(plan.cwd)) && (await isGitDirty(plan.cwd))) {
|
|
16
17
|
throw new MirrorError('Git worktree is dirty. Commit changes or pass --allow-dirty.');
|
|
17
18
|
}
|
|
18
19
|
if (!options.yes)
|
|
19
20
|
throw new MirrorError('Refusing to apply without confirmation. Pass --yes to apply the plan.');
|
|
20
|
-
const config = await loadMirrorConfig(options);
|
|
21
|
-
if (config.version.output.includes('package.json'))
|
|
22
|
-
await writePackageVersion(config, plan.nextVersion);
|
|
23
|
-
if (config.version.output.includes('jsr.json'))
|
|
24
|
-
await writeJsrVersion(config, plan.nextVersion);
|
|
25
21
|
for (const action of plan.actions) {
|
|
26
|
-
|
|
22
|
+
const actionEnv = hookEnvForAction(plan, target, action);
|
|
23
|
+
if (action.type === 'write-file') {
|
|
24
|
+
await runActionHooks('before:write', hooks?.['before:write'], actionEnv, plan.cwd, options);
|
|
25
|
+
if (action.adapter === 'package.json')
|
|
26
|
+
await writePackageVersionFile(action.path, plan.nextVersion);
|
|
27
|
+
if (action.adapter === 'jsr.json')
|
|
28
|
+
await writeJsrVersionFile(action.path, plan.nextVersion);
|
|
29
|
+
await runActionHooks('after:write', hooks?.['after:write'], actionEnv, plan.cwd, options);
|
|
30
|
+
}
|
|
31
|
+
if (action.type === 'git-commit') {
|
|
32
|
+
await runActionHooks('before:commit', hooks?.['before:commit'], actionEnv, plan.cwd, options);
|
|
27
33
|
await createGitCommit(plan.cwd, action.paths, action.message);
|
|
28
|
-
|
|
34
|
+
await runActionHooks('after:commit', hooks?.['after:commit'], actionEnv, plan.cwd, options);
|
|
35
|
+
}
|
|
36
|
+
if (action.type === 'git-tag') {
|
|
37
|
+
await runActionHooks('before:tag', hooks?.['before:tag'], actionEnv, plan.cwd, options);
|
|
29
38
|
await createGitTag(plan.cwd, action.tag);
|
|
30
|
-
|
|
39
|
+
await runActionHooks('after:tag', hooks?.['after:tag'], actionEnv, plan.cwd, options);
|
|
40
|
+
}
|
|
41
|
+
if (action.type === 'git-push') {
|
|
42
|
+
await runActionHooks('before:push', hooks?.['before:push'], actionEnv, plan.cwd, options);
|
|
31
43
|
await pushGitRefs(plan.cwd, action.includeCommit, action.includeTags);
|
|
44
|
+
await runActionHooks('after:push', hooks?.['after:push'], actionEnv, plan.cwd, options);
|
|
45
|
+
}
|
|
32
46
|
}
|
|
33
|
-
return { plan, applied: true, dryRun: false };
|
|
47
|
+
return { plan, applied: true, dryRun: false, hookResults };
|
|
34
48
|
};
|
package/library/flags.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"flags.d.ts","sourceRoot":"","sources":["../source/flags.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAqB,gBAAgB,EAAgB,MAAM,YAAY,CAAA;AAenF,eAAO,MAAM,qBAAqB,GAAI,SAAS,MAAM,EAAE,KAAG,
|
|
1
|
+
{"version":3,"file":"flags.d.ts","sourceRoot":"","sources":["../source/flags.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAqB,gBAAgB,EAAgB,MAAM,YAAY,CAAA;AAenF,eAAO,MAAM,qBAAqB,GAAI,SAAS,MAAM,EAAE,KAAG,gBAkEzD,CAAA"}
|
package/library/flags.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* @copyright Copyright (c) 2026 GUIHO Technologies as represented by Cristóvão GUIHO. All Rights Reserved.
|
|
3
3
|
*/
|
|
4
4
|
import { MirrorError } from './errors.js';
|
|
5
|
-
const booleanFlags = new Set(['dry-run', 'commit', 'push', 'allow-dirty', 'yes', 'no-color', 'verbose', 'help', 'version']);
|
|
5
|
+
const booleanFlags = new Set(['dry-run', 'commit', 'push', 'allow-dirty', 'non-interactive', 'yes', 'no-color', 'verbose', 'help', 'version']);
|
|
6
6
|
const adapterNames = new Set(['package.json', 'jsr.json', 'git']);
|
|
7
7
|
const shortFlagAliases = {
|
|
8
8
|
'-dy': '--dry-run',
|
|
@@ -38,6 +38,12 @@ export const parseMirrorCliOptions = (rawArgs) => {
|
|
|
38
38
|
parsed['output'] = [...(Array.isArray(current) ? current : current ? [String(current)] : []), ...nextValues];
|
|
39
39
|
continue;
|
|
40
40
|
}
|
|
41
|
+
if (key === 'auxiliary') {
|
|
42
|
+
const nextValues = value.split(',').map((item) => item.trim()).filter(Boolean);
|
|
43
|
+
const current = parsed['auxiliary'];
|
|
44
|
+
parsed['auxiliary'] = [...(Array.isArray(current) ? current : current ? [String(current)] : []), ...nextValues];
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
41
47
|
parsed[key] = value;
|
|
42
48
|
}
|
|
43
49
|
return {
|
|
@@ -49,11 +55,15 @@ export const parseMirrorCliOptions = (rawArgs) => {
|
|
|
49
55
|
output: Array.isArray(parsed['output']) ? parsed['output'].map((value) => assertAdapter(value, '--output')) : undefined,
|
|
50
56
|
packageFile: typeof parsed['packageFile'] === 'string' ? parsed['packageFile'] : undefined,
|
|
51
57
|
jsrFile: typeof parsed['jsrFile'] === 'string' ? parsed['jsrFile'] : undefined,
|
|
58
|
+
auxiliary: Array.isArray(parsed['auxiliary']) ? parsed['auxiliary'].map((value) => String(value)) : undefined,
|
|
59
|
+
tagTemplate: typeof parsed['tagTemplate'] === 'string' ? parsed['tagTemplate'] : undefined,
|
|
60
|
+
name: typeof parsed['name'] === 'string' ? parsed['name'] : undefined,
|
|
52
61
|
preid: typeof parsed['preid'] === 'string' ? parsed['preid'] : undefined,
|
|
53
62
|
dryRun: parsed['dryRun'] === true,
|
|
54
63
|
commit: parsed['commit'] === true,
|
|
55
64
|
push: parsed['push'] === true,
|
|
56
65
|
allowDirty: parsed['allowDirty'] === true,
|
|
66
|
+
nonInteractive: parsed['nonInteractive'] === true,
|
|
57
67
|
yes: parsed['yes'] === true,
|
|
58
68
|
verbose: parsed['verbose'] === true,
|
|
59
69
|
};
|
|
@@ -1,15 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @copyright Copyright (c) 2026 GUIHO Technologies as represented by Cristóvão GUIHO. All Rights Reserved.
|
|
3
3
|
*/
|
|
4
|
-
export type { MirrorAdapterName, MirrorCliOptions, MirrorConfig, MirrorExecutionResult, MirrorFormat, MirrorAgentAutomationResult, MirrorAgentSettings, MirrorAgentsInstructionsResult, MirrorRawConfig, MirrorSkillInstallResult, MirrorSkillInstallScope, MirrorVersionPlan, MirrorVersionPlanAction, MirrorVersionTarget, } from './types.js';
|
|
4
|
+
export type { MirrorAdapterName, MirrorCliOptions, MirrorConfig, MirrorExecutionResult, MirrorFormat, MirrorAgentAutomationResult, MirrorAgentSettings, MirrorAgentsInstructionsResult, MirrorHookCommand, MirrorHookName, MirrorHookResult, MirrorHooksConfig, MirrorInitAnswers, MirrorInitFlags, MirrorInitPrompter, MirrorRawConfig, MirrorSkillInstallResult, MirrorSkillInstallScope, MirrorVersionPlan, MirrorVersionPlanAction, MirrorVersionTarget, } from './types.js';
|
|
5
5
|
export { MirrorError, invariant } from './errors.js';
|
|
6
6
|
export { parseMirrorCliOptions } from './flags.js';
|
|
7
|
-
export { defaultMirrorAgentSettings, ensureMirrorAgentsInstructions, findAgentsFile, installMirrorSkill, isMirrorSkillInstalled, mirrorAgentsSection, mirrorAgentsSectionHeading, mirrorSkillName, resolveMirrorAgentSettings, resolveMirrorSkillPath, runMirrorAgentAutomation, } from './agents.js';
|
|
8
|
-
export { createInitConfig, discoverMirrorConfig, loadMirrorConfig, normalizeMirrorConfig, writeInitConfig } from './config.js';
|
|
7
|
+
export { defaultMirrorAgentSettings, ensureMirrorAgentsInstructions, findAgentsFile, installMirrorSkill, isMirrorSkillInstalled, mirrorAgentsSection, mirrorAgentsSectionEndMarker, mirrorAgentsSectionHeading, mirrorAgentsSectionStartMarker, mirrorSkillName, resolveMirrorAgentSettings, resolveMirrorSkillPath, runMirrorAgentAutomation, } from './agents.js';
|
|
8
|
+
export { createInitConfig, defaultInitAnswersForSource, discoverMirrorConfig, generateInitConfig, loadMirrorConfig, normalizeMirrorConfig, reconcileInitConfig, writeInitConfig, writeInitConfigFromAnswers, } from './config.js';
|
|
9
|
+
export { createReadlineInitPrompter, isInteractiveInit, parseAdapterList, resolveInitAnswers } from './init.js';
|
|
10
|
+
export { mirrorConfigJsonSchema, mirrorConfigSchemaReference, renderMirrorConfigJsonSchema } from './schema.js';
|
|
9
11
|
export { assertValidSemver, isMirrorReleaseTarget, mirrorReleaseTargets, resolveNextVersion, sortSemverDescending } from './version.js';
|
|
10
|
-
export { createGitCommit, createGitTag, ensureAdapterFiles, ensureGitAvailable, assertSupportedGitTagTemplate, isGitDirty, isGitRepository, readCurrentVersion, readGitVersion, readJsrName, readJsrVersion, readPackageName, readPackageVersion, renderGitTag, resolveProjectName, supportedGitTagTemplates, versionFromTag, writeJsrVersion, writePackageVersion, } from './adapters.js';
|
|
12
|
+
export { createGitCommit, createGitTag, ensureAdapterFiles, ensureGitAvailable, assertSupportedGitTagTemplate, isGitDirty, isGitRepository, readCurrentVersion, readGitVersion, readJsrName, readJsrVersion, readJsrVersionFile, readPackageName, readPackageVersion, readPackageVersionFile, renderGitTag, resolveProjectName, supportedGitTagTemplates, versionFromTag, writeJsrVersion, writeJsrVersionFile, writePackageVersion, writePackageVersionFile, } from './adapters.js';
|
|
11
13
|
export { buildVersionPlan, releaseLabel, resolveFileOutputPaths, validateMirrorConfig } from './plan.js';
|
|
12
14
|
export { applyVersionPlan, executeVersionPlan } from './executor.js';
|
|
15
|
+
export { hookEnvFromConfig, hookEnvForAction, hookEnvForPlan, hookEnvForResult, mirrorHookNames, normalizeHooksConfig, runHooks, runHooksQuiet, } from './hooks.js';
|
|
13
16
|
export { mirrorBanner, reportAgentsInstructions, reportConfig, reportConfigSchema, reportExecution, reportExecutionSummary, reportPlan, reportSkillInstall, reportValue, } from './reporter.js';
|
|
14
17
|
export { createMirrorCommand, runMirrorCli } from './cli.js';
|
|
15
18
|
//# sourceMappingURL=guiho-mirror.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"guiho-mirror.d.ts","sourceRoot":"","sources":["../source/guiho-mirror.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,YAAY,EACV,iBAAiB,EACjB,gBAAgB,EAChB,YAAY,EACZ,qBAAqB,EACrB,YAAY,EACZ,2BAA2B,EAC3B,mBAAmB,EACnB,8BAA8B,EAC9B,eAAe,EACf,wBAAwB,EACxB,uBAAuB,EACvB,iBAAiB,EACjB,uBAAuB,EACvB,mBAAmB,GACpB,MAAM,YAAY,CAAA;AAEnB,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AACpD,OAAO,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAA;AAClD,OAAO,EACL,0BAA0B,EAC1B,8BAA8B,EAC9B,cAAc,EACd,kBAAkB,EAClB,sBAAsB,EACtB,mBAAmB,EACnB,0BAA0B,EAC1B,eAAe,EACf,0BAA0B,EAC1B,sBAAsB,EACtB,wBAAwB,GACzB,MAAM,aAAa,CAAA;AACpB,OAAO,
|
|
1
|
+
{"version":3,"file":"guiho-mirror.d.ts","sourceRoot":"","sources":["../source/guiho-mirror.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,YAAY,EACV,iBAAiB,EACjB,gBAAgB,EAChB,YAAY,EACZ,qBAAqB,EACrB,YAAY,EACZ,2BAA2B,EAC3B,mBAAmB,EACnB,8BAA8B,EAC9B,iBAAiB,EACjB,cAAc,EACd,gBAAgB,EAChB,iBAAiB,EACjB,iBAAiB,EACjB,eAAe,EACf,kBAAkB,EAClB,eAAe,EACf,wBAAwB,EACxB,uBAAuB,EACvB,iBAAiB,EACjB,uBAAuB,EACvB,mBAAmB,GACpB,MAAM,YAAY,CAAA;AAEnB,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AACpD,OAAO,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAA;AAClD,OAAO,EACL,0BAA0B,EAC1B,8BAA8B,EAC9B,cAAc,EACd,kBAAkB,EAClB,sBAAsB,EACtB,mBAAmB,EACnB,4BAA4B,EAC5B,0BAA0B,EAC1B,8BAA8B,EAC9B,eAAe,EACf,0BAA0B,EAC1B,sBAAsB,EACtB,wBAAwB,GACzB,MAAM,aAAa,CAAA;AACpB,OAAO,EACL,gBAAgB,EAChB,2BAA2B,EAC3B,oBAAoB,EACpB,kBAAkB,EAClB,gBAAgB,EAChB,qBAAqB,EACrB,mBAAmB,EACnB,eAAe,EACf,0BAA0B,GAC3B,MAAM,aAAa,CAAA;AACpB,OAAO,EAAE,0BAA0B,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAA;AAC/G,OAAO,EAAE,sBAAsB,EAAE,2BAA2B,EAAE,4BAA4B,EAAE,MAAM,aAAa,CAAA;AAC/G,OAAO,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAA;AACvI,OAAO,EACL,eAAe,EACf,YAAY,EACZ,kBAAkB,EAClB,kBAAkB,EAClB,6BAA6B,EAC7B,UAAU,EACV,eAAe,EACf,kBAAkB,EAClB,cAAc,EACd,WAAW,EACX,cAAc,EACd,kBAAkB,EAClB,eAAe,EACf,kBAAkB,EAClB,sBAAsB,EACtB,YAAY,EACZ,kBAAkB,EAClB,wBAAwB,EACxB,cAAc,EACd,eAAe,EACf,mBAAmB,EACnB,mBAAmB,EACnB,uBAAuB,GACxB,MAAM,eAAe,CAAA;AACtB,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAE,sBAAsB,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAA;AACxG,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAA;AACpE,OAAO,EACL,iBAAiB,EACjB,gBAAgB,EAChB,cAAc,EACd,gBAAgB,EAChB,eAAe,EACf,oBAAoB,EACpB,QAAQ,EACR,aAAa,GACd,MAAM,YAAY,CAAA;AACnB,OAAO,EACL,YAAY,EACZ,wBAAwB,EACxB,YAAY,EACZ,kBAAkB,EAClB,eAAe,EACf,sBAAsB,EACtB,UAAU,EACV,kBAAkB,EAClB,WAAW,GACZ,MAAM,eAAe,CAAA;AACtB,OAAO,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,UAAU,CAAA"}
|
package/library/guiho-mirror.js
CHANGED
|
@@ -3,11 +3,14 @@
|
|
|
3
3
|
*/
|
|
4
4
|
export { MirrorError, invariant } from './errors.js';
|
|
5
5
|
export { parseMirrorCliOptions } from './flags.js';
|
|
6
|
-
export { defaultMirrorAgentSettings, ensureMirrorAgentsInstructions, findAgentsFile, installMirrorSkill, isMirrorSkillInstalled, mirrorAgentsSection, mirrorAgentsSectionHeading, mirrorSkillName, resolveMirrorAgentSettings, resolveMirrorSkillPath, runMirrorAgentAutomation, } from './agents.js';
|
|
7
|
-
export { createInitConfig, discoverMirrorConfig, loadMirrorConfig, normalizeMirrorConfig, writeInitConfig } from './config.js';
|
|
6
|
+
export { defaultMirrorAgentSettings, ensureMirrorAgentsInstructions, findAgentsFile, installMirrorSkill, isMirrorSkillInstalled, mirrorAgentsSection, mirrorAgentsSectionEndMarker, mirrorAgentsSectionHeading, mirrorAgentsSectionStartMarker, mirrorSkillName, resolveMirrorAgentSettings, resolveMirrorSkillPath, runMirrorAgentAutomation, } from './agents.js';
|
|
7
|
+
export { createInitConfig, defaultInitAnswersForSource, discoverMirrorConfig, generateInitConfig, loadMirrorConfig, normalizeMirrorConfig, reconcileInitConfig, writeInitConfig, writeInitConfigFromAnswers, } from './config.js';
|
|
8
|
+
export { createReadlineInitPrompter, isInteractiveInit, parseAdapterList, resolveInitAnswers } from './init.js';
|
|
9
|
+
export { mirrorConfigJsonSchema, mirrorConfigSchemaReference, renderMirrorConfigJsonSchema } from './schema.js';
|
|
8
10
|
export { assertValidSemver, isMirrorReleaseTarget, mirrorReleaseTargets, resolveNextVersion, sortSemverDescending } from './version.js';
|
|
9
|
-
export { createGitCommit, createGitTag, ensureAdapterFiles, ensureGitAvailable, assertSupportedGitTagTemplate, isGitDirty, isGitRepository, readCurrentVersion, readGitVersion, readJsrName, readJsrVersion, readPackageName, readPackageVersion, renderGitTag, resolveProjectName, supportedGitTagTemplates, versionFromTag, writeJsrVersion, writePackageVersion, } from './adapters.js';
|
|
11
|
+
export { createGitCommit, createGitTag, ensureAdapterFiles, ensureGitAvailable, assertSupportedGitTagTemplate, isGitDirty, isGitRepository, readCurrentVersion, readGitVersion, readJsrName, readJsrVersion, readJsrVersionFile, readPackageName, readPackageVersion, readPackageVersionFile, renderGitTag, resolveProjectName, supportedGitTagTemplates, versionFromTag, writeJsrVersion, writeJsrVersionFile, writePackageVersion, writePackageVersionFile, } from './adapters.js';
|
|
10
12
|
export { buildVersionPlan, releaseLabel, resolveFileOutputPaths, validateMirrorConfig } from './plan.js';
|
|
11
13
|
export { applyVersionPlan, executeVersionPlan } from './executor.js';
|
|
14
|
+
export { hookEnvFromConfig, hookEnvForAction, hookEnvForPlan, hookEnvForResult, mirrorHookNames, normalizeHooksConfig, runHooks, runHooksQuiet, } from './hooks.js';
|
|
12
15
|
export { mirrorBanner, reportAgentsInstructions, reportConfig, reportConfigSchema, reportExecution, reportExecutionSummary, reportPlan, reportSkillInstall, reportValue, } from './reporter.js';
|
|
13
16
|
export { createMirrorCommand, runMirrorCli } from './cli.js';
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Copyright (c) 2026 GUIHO Technologies as represented by Cristóvão GUIHO. All Rights Reserved.
|
|
3
|
+
*/
|
|
4
|
+
import type { MirrorCliOptions, MirrorConfig, MirrorHookCommand, MirrorHookName, MirrorHookResult, MirrorHooksConfig, MirrorVersionPlan, MirrorVersionPlanAction } from './types.js';
|
|
5
|
+
export declare const mirrorHookNames: MirrorHookName[];
|
|
6
|
+
export declare const normalizeHooksConfig: (raw: Record<string, MirrorHookCommand> | undefined) => MirrorHooksConfig;
|
|
7
|
+
export declare const runHooks: (name: MirrorHookName, commands: string[] | undefined, env: Record<string, string>, cwd: string) => Promise<MirrorHookResult | undefined>;
|
|
8
|
+
export declare const runHooksQuiet: (name: MirrorHookName, commands: string[] | undefined, env: Record<string, string>, cwd: string, results: MirrorHookResult[]) => Promise<void>;
|
|
9
|
+
export declare const runActionHooks: (name: MirrorHookName, commands: string[] | undefined, env: Record<string, string>, cwd: string, options: MirrorCliOptions) => Promise<MirrorHookResult | undefined>;
|
|
10
|
+
export declare const hookEnvFromConfig: (config: MirrorConfig, target: string) => Record<string, string>;
|
|
11
|
+
export declare const hookEnvForPlan: (plan: MirrorVersionPlan, target: string) => Record<string, string>;
|
|
12
|
+
export declare const hookEnvForAction: (plan: MirrorVersionPlan, target: string, action: MirrorVersionPlanAction) => Record<string, string>;
|
|
13
|
+
export declare const hookEnvForResult: (plan: MirrorVersionPlan, target: string, applied: boolean, dryRun: boolean) => Record<string, string>;
|
|
14
|
+
//# sourceMappingURL=hooks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../source/hooks.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,KAAK,EAAE,gBAAgB,EAAE,YAAY,EAAE,iBAAiB,EAAE,cAAc,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAA;AAUpL,eAAO,MAAM,eAAe,EAAE,cAAc,EAQ3C,CAAA;AAID,eAAO,MAAM,oBAAoB,GAAI,KAAK,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,GAAG,SAAS,KAAG,iBAezF,CAAA;AAED,eAAO,MAAM,QAAQ,GACnB,MAAM,cAAc,EACpB,UAAU,MAAM,EAAE,GAAG,SAAS,EAC9B,KAAK,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC3B,KAAK,MAAM,KACV,OAAO,CAAC,gBAAgB,GAAG,SAAS,CAwBtC,CAAA;AAED,eAAO,MAAM,aAAa,GACxB,MAAM,cAAc,EACpB,UAAU,MAAM,EAAE,GAAG,SAAS,EAC9B,KAAK,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC3B,KAAK,MAAM,EACX,SAAS,gBAAgB,EAAE,KAC1B,OAAO,CAAC,IAAI,CAUd,CAAA;AAED,eAAO,MAAM,cAAc,GACzB,MAAM,cAAc,EACpB,UAAU,MAAM,EAAE,GAAG,SAAS,EAC9B,KAAK,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC3B,KAAK,MAAM,EACX,SAAS,gBAAgB,KACxB,OAAO,CAAC,gBAAgB,GAAG,SAAS,CAItC,CAAA;AAED,eAAO,MAAM,iBAAiB,GAAI,QAAQ,YAAY,EAAE,QAAQ,MAAM,KAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAM5F,CAAA;AAEF,eAAO,MAAM,cAAc,GAAI,MAAM,iBAAiB,EAAE,QAAQ,MAAM,KAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAa5F,CAAA;AAEF,eAAO,MAAM,gBAAgB,GAAI,MAAM,iBAAiB,EAAE,QAAQ,MAAM,EAAE,QAAQ,uBAAuB,KAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAwBhI,CAAA;AAED,eAAO,MAAM,gBAAgB,GAAI,MAAM,iBAAiB,EAAE,QAAQ,MAAM,EAAE,SAAS,OAAO,EAAE,QAAQ,OAAO,KAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAIjI,CAAA"}
|
package/library/hooks.js
ADDED
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Copyright (c) 2026 GUIHO Technologies as represented by Cristóvão GUIHO. All Rights Reserved.
|
|
3
|
+
*/
|
|
4
|
+
import { exec } from 'node:child_process';
|
|
5
|
+
import { promisify } from 'node:util';
|
|
6
|
+
import { MirrorError } from './errors.js';
|
|
7
|
+
const execAsync = (command, options) => promisify(exec)(command, {
|
|
8
|
+
cwd: options.cwd,
|
|
9
|
+
env: { ...process.env, ...options.env },
|
|
10
|
+
maxBuffer: 10 * 1024 * 1024,
|
|
11
|
+
});
|
|
12
|
+
export const mirrorHookNames = [
|
|
13
|
+
'before:everything', 'after:everything',
|
|
14
|
+
'before:plan', 'after:plan',
|
|
15
|
+
'before:apply', 'after:apply',
|
|
16
|
+
'before:write', 'after:write',
|
|
17
|
+
'before:commit', 'after:commit',
|
|
18
|
+
'before:tag', 'after:tag',
|
|
19
|
+
'before:push', 'after:push',
|
|
20
|
+
];
|
|
21
|
+
const hookNameSet = new Set(mirrorHookNames);
|
|
22
|
+
export const normalizeHooksConfig = (raw) => {
|
|
23
|
+
if (!raw || typeof raw !== 'object')
|
|
24
|
+
return {};
|
|
25
|
+
const config = {};
|
|
26
|
+
for (const [key, value] of Object.entries(raw)) {
|
|
27
|
+
const name = key.replaceAll('_', ':');
|
|
28
|
+
if (!hookNameSet.has(name))
|
|
29
|
+
continue;
|
|
30
|
+
const commands = typeof value === 'string' ? [value] : value;
|
|
31
|
+
config[name] = commands;
|
|
32
|
+
}
|
|
33
|
+
return config;
|
|
34
|
+
};
|
|
35
|
+
export const runHooks = async (name, commands, env, cwd) => {
|
|
36
|
+
if (!commands || commands.length === 0)
|
|
37
|
+
return undefined;
|
|
38
|
+
const start = Date.now();
|
|
39
|
+
for (let i = 0; i < commands.length; i++) {
|
|
40
|
+
const command = commands[i];
|
|
41
|
+
if (!command)
|
|
42
|
+
continue;
|
|
43
|
+
try {
|
|
44
|
+
await execAsync(command, { cwd, env });
|
|
45
|
+
}
|
|
46
|
+
catch (error) {
|
|
47
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
48
|
+
const exitCode = typeof error['code'] === 'number' ? error['code'] : 1;
|
|
49
|
+
throw new MirrorError(`Hook '${name}' failed (exit code ${exitCode}): ${command}\n${message}`, Number(exitCode));
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return {
|
|
53
|
+
name,
|
|
54
|
+
commands,
|
|
55
|
+
status: 'success',
|
|
56
|
+
durationMs: Date.now() - start,
|
|
57
|
+
exitCode: 0,
|
|
58
|
+
};
|
|
59
|
+
};
|
|
60
|
+
export const runHooksQuiet = async (name, commands, env, cwd, results) => {
|
|
61
|
+
if (!commands || commands.length === 0)
|
|
62
|
+
return;
|
|
63
|
+
try {
|
|
64
|
+
await runHooks(name, commands, env, cwd);
|
|
65
|
+
results.push({ name, commands, status: 'success', durationMs: 0, exitCode: 0 });
|
|
66
|
+
}
|
|
67
|
+
catch (error) {
|
|
68
|
+
const exitCode = error instanceof MirrorError ? error.exitCode ?? 1 : 1;
|
|
69
|
+
results.push({ name, commands, status: 'failure', durationMs: 0, exitCode, stderr: error instanceof Error ? error.message : String(error) });
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
export const runActionHooks = async (name, commands, env, cwd, options) => {
|
|
73
|
+
if (options.dryRun || !commands || commands.length === 0)
|
|
74
|
+
return undefined;
|
|
75
|
+
return runHooks(name, commands, env, cwd);
|
|
76
|
+
};
|
|
77
|
+
export const hookEnvFromConfig = (config, target) => ({
|
|
78
|
+
MIRROR_CWD: config.cwd,
|
|
79
|
+
MIRROR_CONFIG_PATH: config.configPath ?? '',
|
|
80
|
+
MIRROR_SOURCE: config.version.source,
|
|
81
|
+
MIRROR_OUTPUT: config.version.output.join(','),
|
|
82
|
+
MIRROR_TARGET: target,
|
|
83
|
+
});
|
|
84
|
+
export const hookEnvForPlan = (plan, target) => ({
|
|
85
|
+
MIRROR_CWD: plan.cwd,
|
|
86
|
+
MIRROR_CONFIG_PATH: plan.configPath ?? '',
|
|
87
|
+
MIRROR_SOURCE: plan.source,
|
|
88
|
+
MIRROR_OUTPUT: plan.output.join(','),
|
|
89
|
+
MIRROR_TARGET: target,
|
|
90
|
+
MIRROR_CURRENT: plan.currentVersion,
|
|
91
|
+
MIRROR_NEXT: plan.nextVersion,
|
|
92
|
+
MIRROR_PROJECT_NAME: plan.project.name ?? '',
|
|
93
|
+
MIRROR_GIT_TAG: plan.gitTag ?? '',
|
|
94
|
+
MIRROR_FILE_PATHS: plan.fileOutputPaths.join(','),
|
|
95
|
+
MIRROR_COMMIT_ENABLED: String(plan.commitEnabled),
|
|
96
|
+
MIRROR_PUSH_ENABLED: String(plan.pushEnabled),
|
|
97
|
+
});
|
|
98
|
+
export const hookEnvForAction = (plan, target, action) => {
|
|
99
|
+
const env = hookEnvForPlan(plan, target);
|
|
100
|
+
if (action.type === 'write-file') {
|
|
101
|
+
env['MIRROR_FILE_PATH'] = action.path;
|
|
102
|
+
env['MIRROR_FILE_CURRENT'] = action.currentVersion;
|
|
103
|
+
env['MIRROR_FILE_NEXT'] = action.nextVersion;
|
|
104
|
+
}
|
|
105
|
+
if (action.type === 'git-commit') {
|
|
106
|
+
env['MIRROR_COMMIT_MSG'] = action.message;
|
|
107
|
+
env['MIRROR_COMMIT_PATHS'] = action.paths.join(' ');
|
|
108
|
+
}
|
|
109
|
+
if (action.type === 'git-tag') {
|
|
110
|
+
env['MIRROR_TAG'] = action.tag;
|
|
111
|
+
}
|
|
112
|
+
if (action.type === 'git-push') {
|
|
113
|
+
env['MIRROR_INCLUDE_COMMIT'] = String(action.includeCommit);
|
|
114
|
+
env['MIRROR_INCLUDE_TAGS'] = String(action.includeTags);
|
|
115
|
+
}
|
|
116
|
+
return env;
|
|
117
|
+
};
|
|
118
|
+
export const hookEnvForResult = (plan, target, applied, dryRun) => ({
|
|
119
|
+
...hookEnvForPlan(plan, target),
|
|
120
|
+
MIRROR_APPLIED: String(applied),
|
|
121
|
+
MIRROR_DRY_RUN: String(dryRun),
|
|
122
|
+
});
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Copyright (c) 2026 GUIHO Technologies as represented by Cristóvão GUIHO. All Rights Reserved.
|
|
3
|
+
*/
|
|
4
|
+
import type { MirrorAdapterName, MirrorInitAnswers, MirrorInitFlags, MirrorInitPrompter } from './types.js';
|
|
5
|
+
export declare const parseAdapterList: (value: string) => MirrorAdapterName[];
|
|
6
|
+
export declare const resolveInitAnswers: (flags: MirrorInitFlags, cwd: string, prompter?: MirrorInitPrompter) => Promise<MirrorInitAnswers>;
|
|
7
|
+
export declare const isInteractiveInit: (options: {
|
|
8
|
+
yes?: boolean;
|
|
9
|
+
nonInteractive?: boolean;
|
|
10
|
+
}) => boolean;
|
|
11
|
+
export declare const createReadlineInitPrompter: () => MirrorInitPrompter;
|
|
12
|
+
//# sourceMappingURL=init.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../source/init.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,KAAK,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAA;AAI3G,eAAO,MAAM,gBAAgB,GAAI,OAAO,MAAM,KAAG,iBAAiB,EAQjE,CAAA;AAQD,eAAO,MAAM,kBAAkB,GAC7B,OAAO,eAAe,EACtB,KAAK,MAAM,EACX,WAAW,kBAAkB,KAC5B,OAAO,CAAC,iBAAiB,CAkD3B,CAAA;AAED,eAAO,MAAM,iBAAiB,GAAI,SAAS;IAAE,GAAG,CAAC,EAAE,OAAO,CAAC;IAAC,cAAc,CAAC,EAAE,OAAO,CAAA;CAAE,YACG,CAAA;AAEzF,eAAO,MAAM,0BAA0B,QAAO,kBAmB7C,CAAA"}
|