@guiho/mirror 3.1.1 → 3.2.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.
@@ -2,8 +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
- import { createGitCommit, createGitTag, isGitDirty, isGitRepository, pushGitRefs, writeJsrVersion, writePackageVersion } from './adapters.js';
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';
8
7
  export const applyVersionPlan = async (target, options = {}) => {
9
8
  const plan = await buildVersionPlan(target, options);
@@ -17,12 +16,11 @@ export const executeVersionPlan = async (plan, options = {}) => {
17
16
  }
18
17
  if (!options.yes)
19
18
  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
19
  for (const action of plan.actions) {
20
+ if (action.type === 'write-file' && action.adapter === 'package.json')
21
+ await writePackageVersionFile(action.path, plan.nextVersion);
22
+ if (action.type === 'write-file' && action.adapter === 'jsr.json')
23
+ await writeJsrVersionFile(action.path, plan.nextVersion);
26
24
  if (action.type === 'git-commit')
27
25
  await createGitCommit(plan.cwd, action.paths, action.message);
28
26
  if (action.type === 'git-tag')
@@ -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,gBAuDzD,CAAA"}
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,13 +1,15 @@
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, 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
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';
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';
13
15
  export { mirrorBanner, reportAgentsInstructions, reportConfig, reportConfigSchema, reportExecution, reportExecutionSummary, reportPlan, reportSkillInstall, reportValue, } from './reporter.js';
@@ -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,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAC9H,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,eAAe,EACf,kBAAkB,EAClB,YAAY,EACZ,kBAAkB,EAClB,wBAAwB,EACxB,cAAc,EACd,eAAe,EACf,mBAAmB,GACpB,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,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"}
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,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,0BAA0B,EAC1B,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,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"}
@@ -4,9 +4,11 @@
4
4
  export { MirrorError, invariant } from './errors.js';
5
5
  export { parseMirrorCliOptions } from './flags.js';
6
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';
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';
12
14
  export { mirrorBanner, reportAgentsInstructions, reportConfig, reportConfigSchema, reportExecution, reportExecutionSummary, reportPlan, reportSkillInstall, reportValue, } from './reporter.js';
@@ -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"}
@@ -0,0 +1,100 @@
1
+ /**
2
+ * @copyright Copyright (c) 2026 GUIHO Technologies as represented by Cristóvão GUIHO. All Rights Reserved.
3
+ */
4
+ import { createInterface } from 'node:readline/promises';
5
+ import { basename } from 'node:path';
6
+ const adapterValues = new Set(['package.json', 'jsr.json', 'git']);
7
+ export const parseAdapterList = (value) => {
8
+ const values = value
9
+ .split(',')
10
+ .map((item) => item.trim())
11
+ .filter(Boolean)
12
+ .filter((item) => adapterValues.has(item));
13
+ return [...new Set(values)];
14
+ };
15
+ const parsePathList = (value) => value
16
+ .split(',')
17
+ .map((item) => item.trim())
18
+ .filter(Boolean);
19
+ export const resolveInitAnswers = async (flags, cwd, prompter) => {
20
+ const source = flags.source ?? (await askAdapter(prompter, 'Version source (package.json, jsr.json, git)', 'package.json'));
21
+ const output = flags.output ?? (await askAdapterList(prompter, 'Version outputs (comma separated)', ['package.json', 'git']));
22
+ const usesPackage = source === 'package.json' || output.includes('package.json');
23
+ const usesJsr = source === 'jsr.json' || output.includes('jsr.json');
24
+ const usesGit = source === 'git' || output.includes('git');
25
+ const hasFileOutput = output.includes('package.json') || output.includes('jsr.json');
26
+ const packagePath = usesPackage
27
+ ? flags.packagePath ?? (prompter ? await prompter.text('package.json path', 'package.json') : 'package.json')
28
+ : 'package.json';
29
+ const auxiliaryPaths = usesPackage
30
+ ? flags.auxiliaryPaths ??
31
+ (prompter ? parsePathList(await prompter.text('Auxiliary package.json paths (comma separated, blank for none)', '')) : [])
32
+ : [];
33
+ const jsrPath = usesJsr
34
+ ? flags.jsrPath ?? (prompter ? await prompter.text('jsr.json path', 'jsr.json') : 'jsr.json')
35
+ : 'jsr.json';
36
+ const name = flags.name ?? (source === 'git' ? basename(cwd) : undefined);
37
+ const nameAvailable = source === 'package.json' || source === 'jsr.json' || Boolean(name);
38
+ const defaultTagTemplate = nameAvailable ? '{name}@{version}' : 'v{version}';
39
+ const tagTemplate = usesGit
40
+ ? flags.tagTemplate ?? (prompter ? await prompter.text('Git tag template', defaultTagTemplate) : defaultTagTemplate)
41
+ : defaultTagTemplate;
42
+ const defaultCommit = usesGit && hasFileOutput;
43
+ const commit = flags.commit ?? (usesGit && prompter ? await prompter.confirm('Create release commits?', defaultCommit) : defaultCommit);
44
+ const push = flags.push ?? (usesGit && prompter ? await prompter.confirm('Push release refs?', false) : false);
45
+ const prereleaseId = flags.prereleaseId ?? '';
46
+ return {
47
+ source,
48
+ output,
49
+ packagePath,
50
+ auxiliaryPaths,
51
+ jsrPath,
52
+ name,
53
+ prereleaseId,
54
+ tagTemplate,
55
+ commit,
56
+ push,
57
+ };
58
+ };
59
+ export const isInteractiveInit = (options) => Boolean(process.stdin.isTTY) && options.yes !== true && options.nonInteractive !== true;
60
+ export const createReadlineInitPrompter = () => {
61
+ const rl = createInterface({ input: process.stdin, output: process.stdout });
62
+ return {
63
+ async text(question, defaultValue) {
64
+ const suffix = defaultValue.length > 0 ? ` [${defaultValue}]` : ' [none]';
65
+ const answer = (await rl.question(`${question}${suffix}: `)).trim();
66
+ return answer.length > 0 ? answer : defaultValue;
67
+ },
68
+ async confirm(question, defaultValue) {
69
+ const suffix = defaultValue ? ' [Y/n]' : ' [y/N]';
70
+ const answer = (await rl.question(`${question}${suffix}: `)).trim().toLowerCase();
71
+ if (answer.length === 0)
72
+ return defaultValue;
73
+ return answer === 'y' || answer === 'yes';
74
+ },
75
+ close() {
76
+ rl.close();
77
+ },
78
+ };
79
+ };
80
+ const askAdapter = async (prompter, question, defaultValue) => {
81
+ if (!prompter)
82
+ return defaultValue;
83
+ for (let attempt = 0; attempt < 3; attempt += 1) {
84
+ const answer = (await prompter.text(question, defaultValue)).trim();
85
+ if (adapterValues.has(answer))
86
+ return answer;
87
+ }
88
+ return defaultValue;
89
+ };
90
+ const askAdapterList = async (prompter, question, defaultValue) => {
91
+ if (!prompter)
92
+ return defaultValue;
93
+ for (let attempt = 0; attempt < 3; attempt += 1) {
94
+ const answer = await prompter.text(question, defaultValue.join(', '));
95
+ const parsed = parseAdapterList(answer);
96
+ if (parsed.length > 0)
97
+ return parsed;
98
+ }
99
+ return defaultValue;
100
+ };
@@ -1 +1 @@
1
- {"version":3,"file":"plan.d.ts","sourceRoot":"","sources":["../source/plan.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,KAAK,EAAE,gBAAgB,EAAE,YAAY,EAAE,iBAAiB,EAA2B,MAAM,YAAY,CAAA;AAM5G,eAAO,MAAM,oBAAoB,GAAU,UAAS,gBAAqB,KAAG,OAAO,CAAC,YAAY,CAW/F,CAAA;AAED,eAAO,MAAM,gBAAgB,GAAU,QAAQ,MAAM,EAAE,UAAS,gBAAqB,KAAG,OAAO,CAAC,iBAAiB,CA4DhH,CAAA;AAED,eAAO,MAAM,sBAAsB,GAAI,QAAQ,YAAY,aAO1D,CAAA;AAED,eAAO,MAAM,YAAY,GAAI,SAAS,MAAM,EAAE,cAAc,MAAM,WAAgE,CAAA;AAElI,eAAO,MAAM,kBAAkB,GAAI,MAAM,iBAAiB,EAAE,MAAM,MAAM,WAAoC,CAAA"}
1
+ {"version":3,"file":"plan.d.ts","sourceRoot":"","sources":["../source/plan.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,KAAK,EAAE,gBAAgB,EAAE,YAAY,EAAE,iBAAiB,EAA2B,MAAM,YAAY,CAAA;AAM5G,eAAO,MAAM,oBAAoB,GAAU,UAAS,gBAAqB,KAAG,OAAO,CAAC,YAAY,CAW/F,CAAA;AAED,eAAO,MAAM,gBAAgB,GAAU,QAAQ,MAAM,EAAE,UAAS,gBAAqB,KAAG,OAAO,CAAC,iBAAiB,CA8DhH,CAAA;AAED,eAAO,MAAM,sBAAsB,GAAI,QAAQ,YAAY,aAU1D,CAAA;AAED,eAAO,MAAM,YAAY,GAAI,SAAS,MAAM,EAAE,cAAc,MAAM,WAAgE,CAAA;AAElI,eAAO,MAAM,kBAAkB,GAAI,MAAM,iBAAiB,EAAE,MAAM,MAAM,WAAoC,CAAA"}
package/library/plan.js CHANGED
@@ -4,7 +4,7 @@
4
4
  import { relative } from 'node:path';
5
5
  import { MirrorError } from './errors.js';
6
6
  import { loadMirrorConfig, relativeFromCwd, resolveMirrorPath } from './config.js';
7
- import { ensureAdapterFiles, readCurrentVersion, renderGitTag, resolveProjectName } from './adapters.js';
7
+ import { ensureAdapterFiles, readCurrentVersion, readJsrVersionFile, readPackageVersionFile, renderGitTag, resolveProjectName } from './adapters.js';
8
8
  import { resolveNextVersion } from './version.js';
9
9
  export const validateMirrorConfig = async (options = {}) => {
10
10
  const config = await loadMirrorConfig(options);
@@ -25,11 +25,12 @@ export const buildVersionPlan = async (target, options = {}) => {
25
25
  const pushEnabled = config.git.push;
26
26
  const actions = [];
27
27
  for (const path of fileOutputPaths) {
28
+ const adapter = path === resolveMirrorPath(config.cwd, config.jsr.path) ? 'jsr.json' : 'package.json';
28
29
  actions.push({
29
30
  type: 'write-file',
30
- adapter: path.endsWith(config.package.path) ? 'package.json' : 'jsr.json',
31
+ adapter,
31
32
  path,
32
- currentVersion,
33
+ currentVersion: adapter === 'package.json' ? await readPackageVersionFile(path) : await readJsrVersionFile(path),
33
34
  nextVersion,
34
35
  });
35
36
  }
@@ -71,11 +72,14 @@ export const buildVersionPlan = async (target, options = {}) => {
71
72
  };
72
73
  export const resolveFileOutputPaths = (config) => {
73
74
  const paths = [];
74
- if (config.version.output.includes('package.json'))
75
+ if (config.version.output.includes('package.json')) {
75
76
  paths.push(resolveMirrorPath(config.cwd, config.package.path));
77
+ for (const path of config.package.auxiliaryPaths)
78
+ paths.push(resolveMirrorPath(config.cwd, path));
79
+ }
76
80
  if (config.version.output.includes('jsr.json'))
77
81
  paths.push(resolveMirrorPath(config.cwd, config.jsr.path));
78
- return paths;
82
+ return [...new Set(paths)];
79
83
  };
80
84
  export const releaseLabel = (version, projectName) => (projectName ? `${projectName}@${version}` : `v${version}`);
81
85
  export const planPathForDisplay = (plan, path) => relativeFromCwd(plan.cwd, path);
@@ -1 +1 @@
1
- {"version":3,"file":"reporter.d.ts","sourceRoot":"","sources":["../source/reporter.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EACV,8BAA8B,EAC9B,YAAY,EACZ,qBAAqB,EACrB,YAAY,EACZ,wBAAwB,EACxB,iBAAiB,EAClB,MAAM,YAAY,CAAA;AAGnB,eAAO,MAAM,YAAY,GAAI,aAAa,MAAM,WAW/C,CAAA;AAED,eAAO,MAAM,WAAW,GAAI,OAAO,OAAO,EAAE,SAAQ,YAAqB,WAGxE,CAAA;AAED,eAAO,MAAM,YAAY,GAAI,QAAQ,YAAY,EAAE,SAAQ,YAAqB,WAmB/E,CAAA;AAED,eAAO,MAAM,kBAAkB,GAAI,SAAQ,YAAqB,WAwC/D,CAAA;AAED,eAAO,MAAM,kBAAkB,GAAI,QAAQ,wBAAwB,EAAE,SAAQ,YAAqB,WAWjG,CAAA;AAED,eAAO,MAAM,wBAAwB,GAAI,QAAQ,8BAA8B,EAAE,SAAQ,YAAqB,WAS7G,CAAA;AAED,eAAO,MAAM,UAAU,GAAI,MAAM,iBAAiB,EAAE,SAAQ,YAAqB,WAyBhF,CAAA;AAED,eAAO,MAAM,eAAe,GAAI,QAAQ,qBAAqB,EAAE,SAAQ,YAAqB,WAG3F,CAAA;AAED,eAAO,MAAM,sBAAsB,GAAI,QAAQ,qBAAqB,EAAE,SAAQ,YAAqB,WAgBlG,CAAA"}
1
+ {"version":3,"file":"reporter.d.ts","sourceRoot":"","sources":["../source/reporter.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EACV,8BAA8B,EAC9B,YAAY,EACZ,qBAAqB,EACrB,YAAY,EACZ,wBAAwB,EACxB,iBAAiB,EAClB,MAAM,YAAY,CAAA;AAInB,eAAO,MAAM,YAAY,GAAI,aAAa,MAAM,WAW/C,CAAA;AAED,eAAO,MAAM,WAAW,GAAI,OAAO,OAAO,EAAE,SAAQ,YAAqB,WAGxE,CAAA;AAED,eAAO,MAAM,YAAY,GAAI,QAAQ,YAAY,EAAE,SAAQ,YAAqB,WAoB/E,CAAA;AAED,eAAO,MAAM,kBAAkB,GAAI,SAAQ,YAAqB,WAyC/D,CAAA;AAED,eAAO,MAAM,kBAAkB,GAAI,QAAQ,wBAAwB,EAAE,SAAQ,YAAqB,WAWjG,CAAA;AAED,eAAO,MAAM,wBAAwB,GAAI,QAAQ,8BAA8B,EAAE,SAAQ,YAAqB,WAS7G,CAAA;AAED,eAAO,MAAM,UAAU,GAAI,MAAM,iBAAiB,EAAE,SAAQ,YAAqB,WAyBhF,CAAA;AAED,eAAO,MAAM,eAAe,GAAI,QAAQ,qBAAqB,EAAE,SAAQ,YAAqB,WAG3F,CAAA;AAED,eAAO,MAAM,sBAAsB,GAAI,QAAQ,qBAAqB,EAAE,SAAQ,YAAqB,WAgBlG,CAAA"}
@@ -2,6 +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 { configPathForDisplay, relativeFromCwd } from './config.js';
5
+ import { renderMirrorConfigJsonSchema } from './schema.js';
5
6
  export const mirrorBanner = (configPath) => {
6
7
  const noColor = process.env['NO_COLOR'] === '1';
7
8
  const title = noColor ? '🪞 GUIHO Mirror' : '\x1b[1;36m🪞 GUIHO Mirror\x1b[0m';
@@ -25,6 +26,7 @@ export const reportConfig = (config, format = 'text') => {
25
26
  `source: ${config.version.source}`,
26
27
  `output: ${config.version.output.join(', ')}`,
27
28
  `package: ${config.package.path}`,
29
+ `package_auxiliary: ${config.package.auxiliaryPaths.join(', ') || '(none)'}`,
28
30
  `jsr: ${config.jsr.path}`,
29
31
  `tag_template: ${config.git.tagTemplate}`,
30
32
  `commit: ${String(config.git.commit)}`,
@@ -39,7 +41,7 @@ export const reportConfig = (config, format = 'text') => {
39
41
  };
40
42
  export const reportConfigSchema = (format = 'text') => {
41
43
  if (format === 'json') {
42
- return `${JSON.stringify({ schema: 'See text output for full reference.' }, null, 2)}\n`;
44
+ return renderMirrorConfigJsonSchema();
43
45
  }
44
46
  return [
45
47
  'MIRROR CONFIGURATION SCHEMA (mirror.config.toml)',
@@ -58,6 +60,7 @@ export const reportConfigSchema = (format = 'text') => {
58
60
  '',
59
61
  ' [package]',
60
62
  ' path = "<path>" Optional. Path to package.json. Default: "package.json".',
63
+ ' auxiliary_paths = ["<path>"] Optional. Extra package.json files that mirror the main package version.',
61
64
  '',
62
65
  ' [jsr]',
63
66
  ' path = "<path>" Optional. Path to jsr.json. Default: "jsr.json".',
@@ -0,0 +1,133 @@
1
+ /**
2
+ * @copyright Copyright (c) 2026 GUIHO Technologies as represented by Cristóvão GUIHO. All Rights Reserved.
3
+ */
4
+ export declare const mirrorConfigSchemaReference = "./node_modules/@guiho/mirror/schema/mirror.config.schema.json";
5
+ export declare const mirrorConfigJsonSchema: {
6
+ readonly $schema: "http://json-schema.org/draft-07/schema#";
7
+ readonly $id: "https://guiho.co/schema/mirror.config.schema.json";
8
+ readonly title: "GUIHO Mirror Configuration";
9
+ readonly description: "Configuration schema for mirror.config.toml.";
10
+ readonly type: "object";
11
+ readonly required: readonly ["schema", "version"];
12
+ readonly additionalProperties: false;
13
+ readonly properties: {
14
+ readonly schema: {
15
+ readonly const: 1;
16
+ readonly description: "Configuration schema version. Must be 1.";
17
+ };
18
+ readonly project: {
19
+ readonly type: "object";
20
+ readonly additionalProperties: false;
21
+ readonly properties: {
22
+ readonly name: {
23
+ readonly type: "string";
24
+ readonly description: "Explicit project name.";
25
+ };
26
+ readonly name_source: {
27
+ readonly enum: readonly ["package.json", "jsr.json"];
28
+ readonly description: "Adapter used to read the project name.";
29
+ };
30
+ };
31
+ };
32
+ readonly version: {
33
+ readonly type: "object";
34
+ readonly additionalProperties: false;
35
+ readonly required: readonly ["source", "output"];
36
+ readonly properties: {
37
+ readonly scheme: {
38
+ readonly const: "semver";
39
+ readonly description: "Versioning scheme. Only \"semver\" is supported.";
40
+ };
41
+ readonly source: {
42
+ readonly enum: readonly ["package.json", "jsr.json", "git"];
43
+ readonly description: "Adapter Mirror reads the current version from.";
44
+ };
45
+ readonly output: {
46
+ readonly type: "array";
47
+ readonly minItems: 1;
48
+ readonly items: {
49
+ readonly enum: readonly ["package.json", "jsr.json", "git"];
50
+ };
51
+ readonly description: "Adapters Mirror writes the next version to.";
52
+ };
53
+ readonly prerelease_id: {
54
+ readonly type: "string";
55
+ readonly description: "Default prerelease identifier, for example \"alpha\".";
56
+ };
57
+ };
58
+ };
59
+ readonly package: {
60
+ readonly type: "object";
61
+ readonly additionalProperties: false;
62
+ readonly properties: {
63
+ readonly path: {
64
+ readonly type: "string";
65
+ readonly description: "Path to the main package.json.";
66
+ };
67
+ readonly auxiliary_paths: {
68
+ readonly type: "array";
69
+ readonly items: {
70
+ readonly type: "string";
71
+ };
72
+ readonly description: "Extra package.json files that mirror the main package version.";
73
+ };
74
+ };
75
+ };
76
+ readonly jsr: {
77
+ readonly type: "object";
78
+ readonly additionalProperties: false;
79
+ readonly properties: {
80
+ readonly path: {
81
+ readonly type: "string";
82
+ readonly description: "Path to jsr.json.";
83
+ };
84
+ };
85
+ };
86
+ readonly git: {
87
+ readonly type: "object";
88
+ readonly additionalProperties: false;
89
+ readonly properties: {
90
+ readonly tag_template: {
91
+ readonly enum: readonly ["v{version}", "{name}@{version}", "{name}/v{version}"];
92
+ readonly description: "Git tag format.";
93
+ };
94
+ readonly commit: {
95
+ readonly type: "boolean";
96
+ readonly description: "Create release commits.";
97
+ };
98
+ readonly push: {
99
+ readonly type: "boolean";
100
+ readonly description: "Push release refs.";
101
+ };
102
+ readonly allow_dirty: {
103
+ readonly type: "boolean";
104
+ readonly description: "Allow release in a dirty Git worktree.";
105
+ };
106
+ };
107
+ };
108
+ readonly agents: {
109
+ readonly type: "object";
110
+ readonly additionalProperties: false;
111
+ readonly properties: {
112
+ readonly write_changelog: {
113
+ readonly type: "boolean";
114
+ readonly description: "Tell agents whether changelog edits are allowed.";
115
+ };
116
+ readonly changelog_path: {
117
+ readonly type: "string";
118
+ readonly description: "Changelog file path for agents.";
119
+ };
120
+ readonly auto_agents_md: {
121
+ readonly type: "boolean";
122
+ readonly description: "Insert Mirror guidance into AGENTS.md when present.";
123
+ };
124
+ readonly auto_skill_install: {
125
+ readonly type: "boolean";
126
+ readonly description: "Install guiho-as-mirror globally when missing.";
127
+ };
128
+ };
129
+ };
130
+ };
131
+ };
132
+ export declare const renderMirrorConfigJsonSchema: () => string;
133
+ //# sourceMappingURL=schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../source/schema.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,eAAO,MAAM,2BAA2B,kEAAkE,CAAA;AAE1G,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA0HzB,CAAA;AAEV,eAAO,MAAM,4BAA4B,cAA+D,CAAA"}
@@ -0,0 +1,128 @@
1
+ /**
2
+ * @copyright Copyright (c) 2026 GUIHO Technologies as represented by Cristóvão GUIHO. All Rights Reserved.
3
+ */
4
+ export const mirrorConfigSchemaReference = './node_modules/@guiho/mirror/schema/mirror.config.schema.json';
5
+ export const mirrorConfigJsonSchema = {
6
+ $schema: 'http://json-schema.org/draft-07/schema#',
7
+ $id: 'https://guiho.co/schema/mirror.config.schema.json',
8
+ title: 'GUIHO Mirror Configuration',
9
+ description: 'Configuration schema for mirror.config.toml.',
10
+ type: 'object',
11
+ required: ['schema', 'version'],
12
+ additionalProperties: false,
13
+ properties: {
14
+ schema: {
15
+ const: 1,
16
+ description: 'Configuration schema version. Must be 1.',
17
+ },
18
+ project: {
19
+ type: 'object',
20
+ additionalProperties: false,
21
+ properties: {
22
+ name: {
23
+ type: 'string',
24
+ description: 'Explicit project name.',
25
+ },
26
+ name_source: {
27
+ enum: ['package.json', 'jsr.json'],
28
+ description: 'Adapter used to read the project name.',
29
+ },
30
+ },
31
+ },
32
+ version: {
33
+ type: 'object',
34
+ additionalProperties: false,
35
+ required: ['source', 'output'],
36
+ properties: {
37
+ scheme: {
38
+ const: 'semver',
39
+ description: 'Versioning scheme. Only "semver" is supported.',
40
+ },
41
+ source: {
42
+ enum: ['package.json', 'jsr.json', 'git'],
43
+ description: 'Adapter Mirror reads the current version from.',
44
+ },
45
+ output: {
46
+ type: 'array',
47
+ minItems: 1,
48
+ items: { enum: ['package.json', 'jsr.json', 'git'] },
49
+ description: 'Adapters Mirror writes the next version to.',
50
+ },
51
+ prerelease_id: {
52
+ type: 'string',
53
+ description: 'Default prerelease identifier, for example "alpha".',
54
+ },
55
+ },
56
+ },
57
+ package: {
58
+ type: 'object',
59
+ additionalProperties: false,
60
+ properties: {
61
+ path: {
62
+ type: 'string',
63
+ description: 'Path to the main package.json.',
64
+ },
65
+ auxiliary_paths: {
66
+ type: 'array',
67
+ items: { type: 'string' },
68
+ description: 'Extra package.json files that mirror the main package version.',
69
+ },
70
+ },
71
+ },
72
+ jsr: {
73
+ type: 'object',
74
+ additionalProperties: false,
75
+ properties: {
76
+ path: {
77
+ type: 'string',
78
+ description: 'Path to jsr.json.',
79
+ },
80
+ },
81
+ },
82
+ git: {
83
+ type: 'object',
84
+ additionalProperties: false,
85
+ properties: {
86
+ tag_template: {
87
+ enum: ['v{version}', '{name}@{version}', '{name}/v{version}'],
88
+ description: 'Git tag format.',
89
+ },
90
+ commit: {
91
+ type: 'boolean',
92
+ description: 'Create release commits.',
93
+ },
94
+ push: {
95
+ type: 'boolean',
96
+ description: 'Push release refs.',
97
+ },
98
+ allow_dirty: {
99
+ type: 'boolean',
100
+ description: 'Allow release in a dirty Git worktree.',
101
+ },
102
+ },
103
+ },
104
+ agents: {
105
+ type: 'object',
106
+ additionalProperties: false,
107
+ properties: {
108
+ write_changelog: {
109
+ type: 'boolean',
110
+ description: 'Tell agents whether changelog edits are allowed.',
111
+ },
112
+ changelog_path: {
113
+ type: 'string',
114
+ description: 'Changelog file path for agents.',
115
+ },
116
+ auto_agents_md: {
117
+ type: 'boolean',
118
+ description: 'Insert Mirror guidance into AGENTS.md when present.',
119
+ },
120
+ auto_skill_install: {
121
+ type: 'boolean',
122
+ description: 'Install guiho-as-mirror globally when missing.',
123
+ },
124
+ },
125
+ },
126
+ },
127
+ };
128
+ export const renderMirrorConfigJsonSchema = () => `${JSON.stringify(mirrorConfigJsonSchema, null, 2)}\n`;
@@ -22,6 +22,7 @@ export type MirrorRawConfig = Partial<{
22
22
  }>;
23
23
  package: Partial<{
24
24
  path: string;
25
+ auxiliary_paths: string[];
25
26
  }>;
26
27
  jsr: Partial<{
27
28
  path: string;
@@ -55,6 +56,7 @@ export type MirrorConfig = {
55
56
  };
56
57
  package: {
57
58
  path: string;
59
+ auxiliaryPaths: string[];
58
60
  };
59
61
  jsr: {
60
62
  path: string;
@@ -82,14 +84,47 @@ export type MirrorCliOptions = {
82
84
  output?: MirrorAdapterName[];
83
85
  packageFile?: string;
84
86
  jsrFile?: string;
87
+ auxiliary?: string[];
88
+ tagTemplate?: string;
89
+ name?: string;
85
90
  preid?: string;
86
91
  dryRun?: boolean;
87
92
  commit?: boolean;
88
93
  push?: boolean;
89
94
  allowDirty?: boolean;
95
+ nonInteractive?: boolean;
90
96
  yes?: boolean;
91
97
  verbose?: boolean;
92
98
  };
99
+ export type MirrorInitAnswers = {
100
+ source: MirrorAdapterName;
101
+ output: MirrorAdapterName[];
102
+ packagePath: string;
103
+ auxiliaryPaths: string[];
104
+ jsrPath: string;
105
+ name?: string;
106
+ prereleaseId: string;
107
+ tagTemplate: string;
108
+ commit: boolean;
109
+ push: boolean;
110
+ };
111
+ export type MirrorInitFlags = Partial<{
112
+ source: MirrorAdapterName;
113
+ output: MirrorAdapterName[];
114
+ packagePath: string;
115
+ auxiliaryPaths: string[];
116
+ jsrPath: string;
117
+ name: string;
118
+ prereleaseId: string;
119
+ tagTemplate: string;
120
+ commit: boolean;
121
+ push: boolean;
122
+ }>;
123
+ export type MirrorInitPrompter = {
124
+ text(question: string, defaultValue: string): Promise<string>;
125
+ confirm(question: string, defaultValue: boolean): Promise<boolean>;
126
+ close(): Promise<void> | void;
127
+ };
93
128
  export type MirrorConfigDiscovery = {
94
129
  path?: string;
95
130
  raw?: MirrorRawConfig;