@guiho/mirror 3.0.0-alpha.4 → 3.0.0-alpha.9

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/jsr.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@guiho/mirror",
3
- "version": "3.0.0-alpha.4",
3
+ "version": "3.0.0-alpha.9",
4
4
  "exports": "./source/guiho-mirror.ts",
5
5
  "publish": {
6
6
  "include": [
package/library/cli.d.ts CHANGED
@@ -20,6 +20,10 @@ export declare const createMirrorCommand: () => import("citty").CommandDef<{
20
20
  type: "boolean";
21
21
  description: string;
22
22
  };
23
+ verbose: {
24
+ type: "boolean";
25
+ description: string;
26
+ };
23
27
  }>;
24
28
  export declare const runMirrorCli: (rawArgs?: string[]) => Promise<void>;
25
29
  //# sourceMappingURL=cli.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../source/cli.ts"],"names":[],"mappings":"AAAA;;GAEG;AA+CH,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;EAa5B,CAAA;AAEJ,eAAO,MAAM,YAAY,GAAU,kBAA+B,kBAyCjE,CAAA"}
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../source/cli.ts"],"names":[],"mappings":"AAAA;;GAEG;AAgDH,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;EAa5B,CAAA;AAEJ,eAAO,MAAM,YAAY,GAAU,kBAA+B,kBAyEjE,CAAA"}
package/library/cli.js CHANGED
@@ -18,6 +18,7 @@ const globalArgs = {
18
18
  cwd: { type: 'string', description: 'Run as if Mirror started in this directory' },
19
19
  format: { type: 'enum', options: ['text', 'json'], default: 'text', description: 'Output format' },
20
20
  'no-color': { type: 'boolean', description: 'Disable color output' },
21
+ verbose: { type: 'boolean', description: 'Show full error details and stack traces' },
21
22
  };
22
23
  const overrideArgs = {
23
24
  ...globalArgs,
@@ -53,6 +54,7 @@ export const createMirrorCommand = () => defineCommand({
53
54
  });
54
55
  export const runMirrorCli = async (rawArgs = process.argv.slice(2)) => {
55
56
  const effectiveArgs = rawArgs.length === 0 ? ['--help'] : rawArgs;
57
+ const verbose = effectiveArgs.includes('--verbose');
56
58
  const restoreColorOutput = effectiveArgs.includes('--no-color') ? stripColorFromProcessOutput() : () => { };
57
59
  try {
58
60
  if (effectiveArgs.includes('--no-color'))
@@ -78,19 +80,68 @@ export const runMirrorCli = async (rawArgs = process.argv.slice(2)) => {
78
80
  ].join('\n') + '\n');
79
81
  });
80
82
  }
81
- await runMain(createMirrorCommand(), { rawArgs: effectiveArgs });
83
+ // Intercept console.error during runMain to suppress citty's default
84
+ // ugly error dump (it does console.error(error, "\n") for non-CLIErrors).
85
+ // We capture the error object and handle it ourselves below.
86
+ let capturedError = undefined;
87
+ const originalConsoleError = console.error;
88
+ console.error = (...args) => {
89
+ // citty prints CLIError messages as strings — let those through
90
+ // citty prints non-CLIError errors as objects — capture those
91
+ if (args.length > 0 && args[0] instanceof Error) {
92
+ capturedError = args[0];
93
+ return;
94
+ }
95
+ originalConsoleError(...args);
96
+ };
97
+ const originalProcessExit = process.exit;
98
+ let exitCode;
99
+ process.exit = ((code) => {
100
+ // If runMain calls process.exit(1) after an error, intercept it
101
+ // so we can handle the error ourselves. Let exit(0) through (--help).
102
+ if (code !== 0 && capturedError) {
103
+ exitCode = code;
104
+ return undefined;
105
+ }
106
+ originalProcessExit(code);
107
+ });
108
+ try {
109
+ await runMain(createMirrorCommand(), { rawArgs: effectiveArgs });
110
+ }
111
+ finally {
112
+ console.error = originalConsoleError;
113
+ process.exit = originalProcessExit;
114
+ }
115
+ if (capturedError) {
116
+ handleCliError(capturedError, verbose, exitCode);
117
+ }
82
118
  }
83
119
  catch (error) {
84
- if (error instanceof MirrorError) {
85
- console.error(error.message);
86
- process.exit(error.exitCode);
87
- }
88
- throw error;
120
+ handleCliError(error, verbose);
89
121
  }
90
122
  finally {
91
123
  restoreColorOutput();
92
124
  }
93
125
  };
126
+ const handleCliError = (error, verbose, exitCode) => {
127
+ if (error instanceof MirrorError) {
128
+ console.error(`error: ${error.message}`);
129
+ if (verbose)
130
+ console.error(error.stack);
131
+ process.exit(error.exitCode);
132
+ }
133
+ if (error instanceof Error) {
134
+ console.error(`error: ${error.message}`);
135
+ if (verbose)
136
+ console.error(error.stack);
137
+ }
138
+ else {
139
+ console.error('error: An unexpected error occurred.');
140
+ if (verbose)
141
+ console.error(error);
142
+ }
143
+ process.exit(exitCode ?? 1);
144
+ };
94
145
  const createInitCommand = () => defineCommand({
95
146
  meta: { name: 'init', description: 'Create a Mirror configuration file.' },
96
147
  subCommands: {
@@ -214,6 +265,7 @@ const cliOptions = (rawArgs, args) => {
214
265
  push: parsed.push || args['push'] === true,
215
266
  allowDirty: parsed.allowDirty || args['allowDirty'] === true,
216
267
  yes: parsed.yes || args['yes'] === true,
268
+ verbose: parsed.verbose || args['verbose'] === true,
217
269
  };
218
270
  };
219
271
  const stringArg = (value) => (typeof value === 'string' ? value : undefined);
@@ -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,SAAS,CAAA;AAehF,eAAO,MAAM,qBAAqB,GAAI,SAAS,MAAM,EAAE,KAAG,gBAsDzD,CAAA"}
1
+ {"version":3,"file":"flags.d.ts","sourceRoot":"","sources":["../source/flags.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAqB,gBAAgB,EAAgB,MAAM,SAAS,CAAA;AAehF,eAAO,MAAM,qBAAqB,GAAI,SAAS,MAAM,EAAE,KAAG,gBAuDzD,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';
5
- const booleanFlags = new Set(['dry-run', 'commit', 'push', 'allow-dirty', 'yes', 'no-color', 'help', 'version']);
5
+ const booleanFlags = new Set(['dry-run', 'commit', 'push', 'allow-dirty', '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',
@@ -55,6 +55,7 @@ export const parseMirrorCliOptions = (rawArgs) => {
55
55
  push: parsed['push'] === true,
56
56
  allowDirty: parsed['allowDirty'] === true,
57
57
  yes: parsed['yes'] === true,
58
+ verbose: parsed['verbose'] === true,
58
59
  };
59
60
  };
60
61
  const assertAdapter = (value, flagName) => {
File without changes
@@ -74,6 +74,7 @@ export type MirrorCliOptions = {
74
74
  push?: boolean;
75
75
  allowDirty?: boolean;
76
76
  yes?: boolean;
77
+ verbose?: boolean;
77
78
  };
78
79
  export type MirrorConfigDiscovery = {
79
80
  path?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../source/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../source/types.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,12 +1,29 @@
1
1
  {
2
2
  "name": "@guiho/mirror",
3
3
  "description": "Open source project versioning for Bun, npm, JSR, and Git.",
4
- "version": "3.0.0-alpha.4",
5
- "main": "library/guiho-mirror.js",
6
- "types": "library/guiho-mirror.d.ts",
7
- "module": "source/guiho-mirror.ts",
4
+ "version": "3.0.0-alpha.9",
8
5
  "type": "module",
9
- "readmeFilename": "README.md",
6
+ "main": "./library/guiho-mirror.js",
7
+ "types": "./library/guiho-mirror.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./library/guiho-mirror.d.ts",
11
+ "import": "./library/guiho-mirror.js"
12
+ }
13
+ },
14
+ "bin": {
15
+ "mirror": "./library/guiho-mirror-bin.js"
16
+ },
17
+ "files": [
18
+ "README.md",
19
+ "library/",
20
+ "docs/",
21
+ "bin/",
22
+ "jsr.json",
23
+ "CHANGELOG.md",
24
+ "LICENSE.md",
25
+ "docs.md"
26
+ ],
10
27
  "keywords": [
11
28
  "bun",
12
29
  "cli",
@@ -22,16 +39,6 @@
22
39
  "url": "https://guiho.co/cg"
23
40
  },
24
41
  "sideEffects": false,
25
- "exports": {
26
- ".": {
27
- "types": "./library/guiho-mirror.d.ts",
28
- "import": "./library/guiho-mirror.js"
29
- },
30
- "./source": "./source/guiho-mirror.ts"
31
- },
32
- "bin": {
33
- "mirror": "./library/guiho-mirror-bin.js"
34
- },
35
42
  "publishConfig": {
36
43
  "access": "public"
37
44
  },
@@ -53,22 +60,13 @@
53
60
  },
54
61
  "repository": {
55
62
  "type": "git",
56
- "url": "git+ssh://git@github.com/CGuiho/mirror.git",
63
+ "url": "git+https://github.com/CGuiho/mirror.git",
57
64
  "directory": "mirror"
58
65
  },
59
66
  "homepage": "https://github.com/CGuiho/mirror#readme",
60
- "bugs": "https://github.com/CGuiho/mirror/issues",
61
- "files": [
62
- "README.md",
63
- "library/",
64
- "source/",
65
- "docs/",
66
- "bin/",
67
- "jsr.json",
68
- "CHANGELOG.md",
69
- "LICENSE.md",
70
- "docs.md"
71
- ],
67
+ "bugs": {
68
+ "url": "https://github.com/CGuiho/mirror/issues"
69
+ },
72
70
  "dependencies": {
73
71
  "citty": "^0.2.2",
74
72
  "semver": "^7.8.0"
package/bin/mirror.exe DELETED
Binary file
@@ -1,176 +0,0 @@
1
- /**
2
- * @copyright Copyright (c) 2026 GUIHO Technologies as represented by Cristóvão GUIHO. All Rights Reserved.
3
- */
4
-
5
- import { $ } from 'bun'
6
- import { existsSync } from 'node:fs'
7
- import type { MirrorConfig, MirrorJsonObject } from './types'
8
- import { MirrorError } from './errors'
9
- import { assertValidSemver, sortSemverDescending } from './version'
10
- import { resolveMirrorPath } from './config'
11
-
12
- export const supportedGitTagTemplates = ['v{version}', '{name}@{version}', '{name}/v{version}'] as const
13
-
14
- export const readPackageJson = async (path: string): Promise<MirrorJsonObject> => readJsonObject(path, 'package.json')
15
- export const readJsrJson = async (path: string): Promise<MirrorJsonObject> => readJsonObject(path, 'jsr.json')
16
-
17
- export const writeJsonObject = async (path: string, object: MirrorJsonObject) => {
18
- await Bun.write(path, `${JSON.stringify(object, null, 2)}\n`)
19
- }
20
-
21
- export const readPackageVersion = async (config: MirrorConfig) => readVersionField(resolveMirrorPath(config.cwd, config.package.path), 'package.json')
22
- export const readJsrVersion = async (config: MirrorConfig) => readVersionField(resolveMirrorPath(config.cwd, config.jsr.path), 'jsr.json')
23
- export const readPackageName = async (config: MirrorConfig) => readNameField(resolveMirrorPath(config.cwd, config.package.path), 'package.json')
24
- export const readJsrName = async (config: MirrorConfig) => readNameField(resolveMirrorPath(config.cwd, config.jsr.path), 'jsr.json')
25
-
26
- export const writePackageVersion = async (config: MirrorConfig, nextVersion: string) =>
27
- writeVersionField(resolveMirrorPath(config.cwd, config.package.path), 'package.json', nextVersion)
28
-
29
- export const writeJsrVersion = async (config: MirrorConfig, nextVersion: string) =>
30
- writeVersionField(resolveMirrorPath(config.cwd, config.jsr.path), 'jsr.json', nextVersion)
31
-
32
- export const ensureAdapterFiles = async (config: MirrorConfig) => {
33
- if (usesAdapter(config, 'package.json')) ensureFile(resolveMirrorPath(config.cwd, config.package.path), 'package.json')
34
- if (usesAdapter(config, 'jsr.json')) ensureFile(resolveMirrorPath(config.cwd, config.jsr.path), 'jsr.json')
35
- if (usesAdapter(config, 'git')) await ensureGitRepository(config.cwd)
36
- }
37
-
38
- export const resolveProjectName = async (config: MirrorConfig) => {
39
- if (config.project.name) return config.project.name
40
- if (config.project.nameSource === 'package.json') return readPackageName(config)
41
- if (config.project.nameSource === 'jsr.json') return readJsrName(config)
42
- return undefined
43
- }
44
-
45
- export const readCurrentVersion = async (config: MirrorConfig, projectName?: string) => {
46
- if (config.version.source === 'package.json') return readPackageVersion(config)
47
- if (config.version.source === 'jsr.json') return readJsrVersion(config)
48
- return readGitVersion(config, projectName)
49
- }
50
-
51
- export const readGitVersion = async (config: MirrorConfig, projectName?: string) => {
52
- await ensureGitRepository(config.cwd)
53
-
54
- const tagsOutput = await $`git -C ${config.cwd} tag --list`.text()
55
- const versions = tagsOutput
56
- .split(/\r?\n/)
57
- .map((line) => line.trim())
58
- .filter(Boolean)
59
- .map((tag) => versionFromTag(config.git.tagTemplate, tag, projectName))
60
- .filter((version): version is string => Boolean(version))
61
-
62
- if (versions.length === 0) throw new MirrorError(`No Git tags match template: ${config.git.tagTemplate}`)
63
-
64
- return sortSemverDescending(versions)[0] ?? ''
65
- }
66
-
67
- export const renderGitTag = (template: string, version: string, projectName?: string) => {
68
- assertSupportedGitTagTemplate(template)
69
- assertValidSemver(version, 'Git tag version')
70
-
71
- if (template.includes('{name}') && !projectName) throw new MirrorError(`Tag template requires a project name: ${template}`)
72
-
73
- return template.replaceAll('{version}', version).replaceAll('{name}', projectName ?? '')
74
- }
75
-
76
- export const versionFromTag = (template: string, tag: string, projectName?: string) => {
77
- assertSupportedGitTagTemplate(template)
78
-
79
- if (template.includes('{name}') && !projectName) throw new MirrorError(`Tag template requires a project name: ${template}`)
80
-
81
- const escapedTemplate = escapeRegex(template)
82
- .replaceAll('\\{version\\}', '(?<version>.+)')
83
- .replaceAll('\\{name\\}', escapeRegex(projectName ?? ''))
84
- const match = new RegExp(`^${escapedTemplate}$`).exec(tag)
85
- const version = match?.groups?.['version']
86
-
87
- if (!version) return undefined
88
-
89
- try {
90
- assertValidSemver(version, 'Git tag version')
91
- return version
92
- } catch {
93
- return undefined
94
- }
95
- }
96
-
97
- export const assertSupportedGitTagTemplate = (template: string) => {
98
- if (!(supportedGitTagTemplates as readonly string[]).includes(template)) {
99
- throw new MirrorError(`Unsupported Git tag template: ${template}. Expected v{version}, {name}@{version}, or {name}/v{version}.`)
100
- }
101
- }
102
-
103
- export const isGitRepository = async (cwd: string) => {
104
- try {
105
- await $`git -C ${cwd} rev-parse --is-inside-work-tree`.quiet()
106
- return true
107
- } catch {
108
- return false
109
- }
110
- }
111
-
112
- export const isGitDirty = async (cwd: string) => {
113
- const output = await $`git -C ${cwd} status --porcelain`.quiet().text()
114
- return output.trim().length > 0
115
- }
116
-
117
- export const createGitCommit = async (cwd: string, paths: string[], message: string) => {
118
- for (const path of paths) await $`git -C ${cwd} add ${path}`.quiet()
119
- await $`git -C ${cwd} commit -m ${message}`.quiet()
120
- }
121
-
122
- export const createGitTag = async (cwd: string, tag: string) => {
123
- await $`git -C ${cwd} tag ${tag} -m ${`Release ${tag}`}`.quiet()
124
- }
125
-
126
- export const pushGitRefs = async (cwd: string, includeCommit: boolean, includeTags: boolean) => {
127
- if (includeCommit) await $`git -C ${cwd} push`.quiet()
128
- if (includeTags) await $`git -C ${cwd} push --tags`.quiet()
129
- }
130
-
131
- const readJsonObject = async (path: string, label: string): Promise<MirrorJsonObject> => {
132
- ensureFile(path, label)
133
- const json = await Bun.file(path).json()
134
-
135
- if (typeof json !== 'object' || json === null || Array.isArray(json)) throw new MirrorError(`${label} must contain a JSON object: ${path}`)
136
-
137
- return json as MirrorJsonObject
138
- }
139
-
140
- const readVersionField = async (path: string, label: string): Promise<string> => {
141
- const json = await readJsonObject(path, label)
142
- const version = json['version']
143
-
144
- if (typeof version !== 'string') throw new MirrorError(`${label} must contain a string version field: ${path}`)
145
- assertValidSemver(version, `${label} version`)
146
-
147
- return version
148
- }
149
-
150
- const readNameField = async (path: string, label: string): Promise<string> => {
151
- const json = await readJsonObject(path, label)
152
- const name = json['name']
153
-
154
- if (typeof name !== 'string' || name.length === 0) throw new MirrorError(`${label} must contain a string name field: ${path}`)
155
-
156
- return name
157
- }
158
-
159
- const writeVersionField = async (path: string, label: string, nextVersion: string) => {
160
- const json = await readJsonObject(path, label)
161
- json['version'] = nextVersion
162
- await writeJsonObject(path, json)
163
- }
164
-
165
- const ensureFile = (path: string, label: string) => {
166
- if (!existsSync(path)) throw new MirrorError(`${label} file not found: ${path}`)
167
- }
168
-
169
- const ensureGitRepository = async (cwd: string) => {
170
- if (!(await isGitRepository(cwd))) throw new MirrorError(`Not a Git repository: ${cwd}`)
171
- }
172
-
173
- const usesAdapter = (config: MirrorConfig, adapter: 'package.json' | 'jsr.json' | 'git') =>
174
- config.version.source === adapter || config.version.output.includes(adapter)
175
-
176
- const escapeRegex = (value: string) => value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')