@guiho/mirror 3.0.0-alpha.4
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 +16 -0
- package/LICENSE.md +23 -0
- package/README.md +190 -0
- package/bin/mirror.exe +0 -0
- package/jsr.json +12 -0
- package/library/adapters.d.ts +27 -0
- package/library/adapters.d.ts.map +1 -0
- package/library/adapters.js +152 -0
- package/library/cli.d.ts +25 -0
- package/library/cli.d.ts.map +1 -0
- package/library/cli.js +258 -0
- package/library/config.d.ts +14 -0
- package/library/config.d.ts.map +1 -0
- package/library/config.js +193 -0
- package/library/errors.d.ts +9 -0
- package/library/errors.d.ts.map +1 -0
- package/library/errors.js +15 -0
- package/library/executor.d.ts +7 -0
- package/library/executor.d.ts.map +1 -0
- package/library/executor.js +34 -0
- package/library/flags.d.ts +6 -0
- package/library/flags.d.ts.map +1 -0
- package/library/flags.js +69 -0
- package/library/guiho-mirror-bin.d.ts +6 -0
- package/library/guiho-mirror-bin.d.ts.map +1 -0
- package/library/guiho-mirror-bin.js +6 -0
- package/library/guiho-mirror.d.ts +14 -0
- package/library/guiho-mirror.d.ts.map +1 -0
- package/library/guiho-mirror.js +12 -0
- package/library/plan.d.ts +10 -0
- package/library/plan.d.ts.map +1 -0
- package/library/plan.js +81 -0
- package/library/reporter.d.ts +12 -0
- package/library/reporter.d.ts.map +1 -0
- package/library/reporter.js +121 -0
- package/library/types.d.ts +123 -0
- package/library/types.d.ts.map +1 -0
- package/library/types.js +4 -0
- package/library/version.d.ts +10 -0
- package/library/version.d.ts.map +1 -0
- package/library/version.js +31 -0
- package/package.json +81 -0
- package/source/adapters.ts +176 -0
- package/source/cli.ts +285 -0
- package/source/config.ts +224 -0
- package/source/errors.ts +17 -0
- package/source/executor.ts +39 -0
- package/source/flags.ts +84 -0
- package/source/guiho-mirror-bin.ts +8 -0
- package/source/guiho-mirror.spec.ts +501 -0
- package/source/guiho-mirror.ts +44 -0
- package/source/plan.ts +98 -0
- package/source/reporter.ts +127 -0
- package/source/types.ts +128 -0
- package/source/version.ts +39 -0
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Copyright (c) 2026 GUIHO Technologies as represented by Cristóvão GUIHO. All Rights Reserved.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
export type {
|
|
6
|
+
MirrorAdapterName,
|
|
7
|
+
MirrorCliOptions,
|
|
8
|
+
MirrorConfig,
|
|
9
|
+
MirrorExecutionResult,
|
|
10
|
+
MirrorFormat,
|
|
11
|
+
MirrorRawConfig,
|
|
12
|
+
MirrorVersionPlan,
|
|
13
|
+
MirrorVersionPlanAction,
|
|
14
|
+
MirrorVersionTarget,
|
|
15
|
+
} from './types'
|
|
16
|
+
|
|
17
|
+
export { MirrorError, invariant } from './errors'
|
|
18
|
+
export { parseMirrorCliOptions } from './flags'
|
|
19
|
+
export { createInitConfig, discoverMirrorConfig, loadMirrorConfig, normalizeMirrorConfig, writeInitConfig } from './config'
|
|
20
|
+
export { assertValidSemver, isMirrorReleaseTarget, mirrorReleaseTargets, resolveNextVersion, sortSemverDescending } from './version'
|
|
21
|
+
export {
|
|
22
|
+
createGitCommit,
|
|
23
|
+
createGitTag,
|
|
24
|
+
ensureAdapterFiles,
|
|
25
|
+
assertSupportedGitTagTemplate,
|
|
26
|
+
isGitDirty,
|
|
27
|
+
isGitRepository,
|
|
28
|
+
readCurrentVersion,
|
|
29
|
+
readGitVersion,
|
|
30
|
+
readJsrName,
|
|
31
|
+
readJsrVersion,
|
|
32
|
+
readPackageName,
|
|
33
|
+
readPackageVersion,
|
|
34
|
+
renderGitTag,
|
|
35
|
+
resolveProjectName,
|
|
36
|
+
supportedGitTagTemplates,
|
|
37
|
+
versionFromTag,
|
|
38
|
+
writeJsrVersion,
|
|
39
|
+
writePackageVersion,
|
|
40
|
+
} from './adapters'
|
|
41
|
+
export { buildVersionPlan, releaseLabel, resolveFileOutputPaths, validateMirrorConfig } from './plan'
|
|
42
|
+
export { applyVersionPlan, executeVersionPlan } from './executor'
|
|
43
|
+
export { mirrorBanner, reportConfig, reportConfigSchema, reportExecution, reportExecutionSummary, reportPlan, reportValue } from './reporter'
|
|
44
|
+
export { createMirrorCommand, runMirrorCli } from './cli'
|
package/source/plan.ts
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Copyright (c) 2026 GUIHO Technologies as represented by Cristóvão GUIHO. All Rights Reserved.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { relative } from 'node:path'
|
|
6
|
+
import type { MirrorCliOptions, MirrorConfig, MirrorVersionPlan, MirrorVersionPlanAction } from './types'
|
|
7
|
+
import { MirrorError } from './errors'
|
|
8
|
+
import { loadMirrorConfig, relativeFromCwd, resolveMirrorPath } from './config'
|
|
9
|
+
import { ensureAdapterFiles, readCurrentVersion, renderGitTag, resolveProjectName } from './adapters'
|
|
10
|
+
import { resolveNextVersion } from './version'
|
|
11
|
+
|
|
12
|
+
export const validateMirrorConfig = async (options: MirrorCliOptions = {}): Promise<MirrorConfig> => {
|
|
13
|
+
const config = await loadMirrorConfig(options)
|
|
14
|
+
await ensureAdapterFiles(config)
|
|
15
|
+
|
|
16
|
+
const projectName = await resolveProjectName(config)
|
|
17
|
+
|
|
18
|
+
if (config.version.source === 'git' || config.version.output.includes('git')) {
|
|
19
|
+
renderGitTag(config.git.tagTemplate, '0.0.0', projectName)
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return config
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export const buildVersionPlan = async (target: string, options: MirrorCliOptions = {}): Promise<MirrorVersionPlan> => {
|
|
26
|
+
const config = await validateMirrorConfig(options)
|
|
27
|
+
|
|
28
|
+
const projectName = await resolveProjectName(config)
|
|
29
|
+
const currentVersion = await readCurrentVersion(config, projectName)
|
|
30
|
+
const nextVersion = resolveNextVersion(currentVersion, target, config.version.prereleaseId)
|
|
31
|
+
const fileOutputPaths = resolveFileOutputPaths(config)
|
|
32
|
+
const commitEnabled = config.git.commit
|
|
33
|
+
const pushEnabled = config.git.push
|
|
34
|
+
const actions: MirrorVersionPlanAction[] = []
|
|
35
|
+
|
|
36
|
+
for (const path of fileOutputPaths) {
|
|
37
|
+
actions.push({
|
|
38
|
+
type: 'write-file',
|
|
39
|
+
adapter: path.endsWith(config.package.path) ? 'package.json' : 'jsr.json',
|
|
40
|
+
path,
|
|
41
|
+
currentVersion,
|
|
42
|
+
nextVersion,
|
|
43
|
+
})
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const gitTag = config.version.output.includes('git') ? renderGitTag(config.git.tagTemplate, nextVersion, projectName) : undefined
|
|
47
|
+
|
|
48
|
+
if (fileOutputPaths.length > 0 && gitTag && !commitEnabled && !pushEnabled) {
|
|
49
|
+
throw new MirrorError('Git tag output with file outputs requires --commit or --push so the tag points at the version commit.')
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (commitEnabled && fileOutputPaths.length > 0) {
|
|
53
|
+
actions.push({
|
|
54
|
+
type: 'git-commit',
|
|
55
|
+
message: releaseLabel(nextVersion, projectName),
|
|
56
|
+
paths: fileOutputPaths.map((path) => relative(config.cwd, path)),
|
|
57
|
+
})
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (gitTag) actions.push({ type: 'git-tag', tag: gitTag })
|
|
61
|
+
|
|
62
|
+
if (pushEnabled) {
|
|
63
|
+
actions.push({
|
|
64
|
+
type: 'git-push',
|
|
65
|
+
includeCommit: fileOutputPaths.length > 0,
|
|
66
|
+
includeTags: Boolean(gitTag),
|
|
67
|
+
})
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return {
|
|
71
|
+
cwd: config.cwd,
|
|
72
|
+
configPath: config.configPath,
|
|
73
|
+
source: config.version.source,
|
|
74
|
+
output: config.version.output,
|
|
75
|
+
currentVersion,
|
|
76
|
+
nextVersion,
|
|
77
|
+
project: { name: projectName },
|
|
78
|
+
commitEnabled,
|
|
79
|
+
pushEnabled,
|
|
80
|
+
allowDirty: config.git.allowDirty,
|
|
81
|
+
fileOutputPaths,
|
|
82
|
+
gitTag,
|
|
83
|
+
actions,
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export const resolveFileOutputPaths = (config: MirrorConfig) => {
|
|
88
|
+
const paths: string[] = []
|
|
89
|
+
|
|
90
|
+
if (config.version.output.includes('package.json')) paths.push(resolveMirrorPath(config.cwd, config.package.path))
|
|
91
|
+
if (config.version.output.includes('jsr.json')) paths.push(resolveMirrorPath(config.cwd, config.jsr.path))
|
|
92
|
+
|
|
93
|
+
return paths
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export const releaseLabel = (version: string, projectName?: string) => (projectName ? `${projectName}@${version}` : `v${version}`)
|
|
97
|
+
|
|
98
|
+
export const planPathForDisplay = (plan: MirrorVersionPlan, path: string) => relativeFromCwd(plan.cwd, path)
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Copyright (c) 2026 GUIHO Technologies as represented by Cristóvão GUIHO. All Rights Reserved.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type { MirrorConfig, MirrorExecutionResult, MirrorFormat, MirrorVersionPlan } from './types'
|
|
6
|
+
import { configPathForDisplay, relativeFromCwd } from './config'
|
|
7
|
+
|
|
8
|
+
export const mirrorBanner = (configPath?: string) => {
|
|
9
|
+
const noColor = process.env['NO_COLOR'] === '1'
|
|
10
|
+
const title = noColor ? '🪞 GUIHO Mirror' : '\x1b[1;36m🪞 GUIHO Mirror\x1b[0m'
|
|
11
|
+
|
|
12
|
+
if (configPath === undefined) return `\n${title}\n\n`
|
|
13
|
+
|
|
14
|
+
const dim = noColor ? '' : '\x1b[2m'
|
|
15
|
+
const reset = noColor ? '' : '\x1b[0m'
|
|
16
|
+
const status = configPath ? configPath : '(none)'
|
|
17
|
+
|
|
18
|
+
return `\n${title}\n\n${dim}config: ${status}${reset}\n\n`
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export const reportValue = (value: unknown, format: MirrorFormat = 'text') => {
|
|
22
|
+
if (format === 'json') return `${JSON.stringify(value, null, 2)}\n`
|
|
23
|
+
return `${String(value)}\n`
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export const reportConfig = (config: MirrorConfig, format: MirrorFormat = 'text') => {
|
|
27
|
+
if (format === 'json') return `${JSON.stringify(config, null, 2)}\n`
|
|
28
|
+
|
|
29
|
+
return [
|
|
30
|
+
`config: ${configPathForDisplay(config)}`,
|
|
31
|
+
`source: ${config.version.source}`,
|
|
32
|
+
`output: ${config.version.output.join(', ')}`,
|
|
33
|
+
`package: ${config.package.path}`,
|
|
34
|
+
`jsr: ${config.jsr.path}`,
|
|
35
|
+
`tag_template: ${config.git.tagTemplate}`,
|
|
36
|
+
`commit: ${String(config.git.commit)}`,
|
|
37
|
+
`push: ${String(config.git.push)}`,
|
|
38
|
+
`allow_dirty: ${String(config.git.allowDirty)}`,
|
|
39
|
+
'',
|
|
40
|
+
].join('\n')
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export const reportConfigSchema = (format: MirrorFormat = 'text') => {
|
|
44
|
+
if (format === 'json') {
|
|
45
|
+
return `${JSON.stringify({ schema: 'See text output for full reference.' }, null, 2)}\n`
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return [
|
|
49
|
+
'MIRROR CONFIGURATION SCHEMA (mirror.config.toml)',
|
|
50
|
+
'',
|
|
51
|
+
' schema = 1 Required. Schema version. Must be 1.',
|
|
52
|
+
'',
|
|
53
|
+
' [project]',
|
|
54
|
+
' name = "<string>" Optional. Explicit project name.',
|
|
55
|
+
' name_source = "package.json" | "jsr.json" Optional. Read project name from this adapter.',
|
|
56
|
+
'',
|
|
57
|
+
' [version]',
|
|
58
|
+
' scheme = "semver" Required. Only "semver" is supported.',
|
|
59
|
+
' source = "package.json" | "jsr.json" | "git" Required. Adapter to read the current version from.',
|
|
60
|
+
' output = ["package.json", "jsr.json", "git"] Required. Adapters to write the next version to.',
|
|
61
|
+
' prerelease_id = "<string>" Optional. Default prerelease identifier (e.g. "alpha").',
|
|
62
|
+
'',
|
|
63
|
+
' [package]',
|
|
64
|
+
' path = "<path>" Optional. Path to package.json. Default: "package.json".',
|
|
65
|
+
'',
|
|
66
|
+
' [jsr]',
|
|
67
|
+
' path = "<path>" Optional. Path to jsr.json. Default: "jsr.json".',
|
|
68
|
+
'',
|
|
69
|
+
' [git]',
|
|
70
|
+
' tag_template = "<template>" Optional. Git tag format. Default: "v{version}".',
|
|
71
|
+
' Supported: "v{version}", "{name}@{version}", "{name}/v{version}".',
|
|
72
|
+
' commit = true | false Optional. Create release commits. Default: false.',
|
|
73
|
+
' push = true | false Optional. Push release refs. Default: false.',
|
|
74
|
+
' allow_dirty = true | false Optional. Allow dirty Git worktree. Default: false.',
|
|
75
|
+
'',
|
|
76
|
+
].join('\n')
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export const reportPlan = (plan: MirrorVersionPlan, format: MirrorFormat = 'text') => {
|
|
80
|
+
if (format === 'json') return `${JSON.stringify(plan, null, 2)}\n`
|
|
81
|
+
|
|
82
|
+
const lines = [
|
|
83
|
+
`current: ${plan.currentVersion}`,
|
|
84
|
+
`next: ${plan.nextVersion}`,
|
|
85
|
+
`source: ${plan.source}`,
|
|
86
|
+
`output: ${plan.output.join(', ')}`,
|
|
87
|
+
]
|
|
88
|
+
|
|
89
|
+
if (plan.project.name) lines.push(`project: ${plan.project.name}`)
|
|
90
|
+
if (plan.configPath) lines.push(`config: ${relativeFromCwd(plan.cwd, plan.configPath)}`)
|
|
91
|
+
if (plan.fileOutputPaths.length > 0) lines.push(`files: ${plan.fileOutputPaths.map((path) => relativeFromCwd(plan.cwd, path)).join(', ')}`)
|
|
92
|
+
if (plan.gitTag) lines.push(`tag: ${plan.gitTag}`)
|
|
93
|
+
|
|
94
|
+
lines.push('actions:')
|
|
95
|
+
|
|
96
|
+
for (const action of plan.actions) {
|
|
97
|
+
if (action.type === 'write-file') lines.push(`- write ${relativeFromCwd(plan.cwd, action.path)}: ${action.currentVersion} -> ${action.nextVersion}`)
|
|
98
|
+
if (action.type === 'git-commit') lines.push(`- commit ${action.message}`)
|
|
99
|
+
if (action.type === 'git-tag') lines.push(`- tag ${action.tag}`)
|
|
100
|
+
if (action.type === 'git-push') lines.push(`- push commit=${String(action.includeCommit)} tags=${String(action.includeTags)}`)
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return `${lines.join('\n')}\n`
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export const reportExecution = (result: MirrorExecutionResult, format: MirrorFormat = 'text') => {
|
|
107
|
+
if (format === 'json') return `${JSON.stringify(result, null, 2)}\n`
|
|
108
|
+
return `${reportPlan(result.plan, 'text')}applied: ${String(result.applied)}\ndry_run: ${String(result.dryRun)}\n`
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export const reportExecutionSummary = (result: MirrorExecutionResult, format: MirrorFormat = 'text') => {
|
|
112
|
+
if (format === 'json') return `${JSON.stringify(result, null, 2)}\n`
|
|
113
|
+
|
|
114
|
+
const outputs = result.plan.output.join(', ')
|
|
115
|
+
const files = result.plan.fileOutputPaths.map((path) => relativeFromCwd(result.plan.cwd, path)).join(', ')
|
|
116
|
+
const lines = [
|
|
117
|
+
`applied: ${String(result.applied)}`,
|
|
118
|
+
`dry_run: ${String(result.dryRun)}`,
|
|
119
|
+
`version: ${result.plan.nextVersion}`,
|
|
120
|
+
`outputs: ${outputs}`,
|
|
121
|
+
]
|
|
122
|
+
|
|
123
|
+
if (files) lines.push(`files: ${files}`)
|
|
124
|
+
if (result.plan.gitTag) lines.push(`tag: ${result.plan.gitTag}`)
|
|
125
|
+
|
|
126
|
+
return `${lines.join('\n')}\n`
|
|
127
|
+
}
|
package/source/types.ts
ADDED
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Copyright (c) 2026 GUIHO Technologies as represented by Cristóvão GUIHO. All Rights Reserved.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type { ReleaseType } from 'semver'
|
|
6
|
+
|
|
7
|
+
export type MirrorAdapterName = 'package.json' | 'jsr.json' | 'git'
|
|
8
|
+
export type MirrorProjectNameSource = 'package.json' | 'jsr.json'
|
|
9
|
+
export type MirrorFormat = 'text' | 'json'
|
|
10
|
+
export type MirrorVersionTarget = ReleaseType | string
|
|
11
|
+
export type MirrorJsonObject = Record<string, unknown>
|
|
12
|
+
|
|
13
|
+
export type MirrorRawConfig = Partial<{
|
|
14
|
+
schema: number
|
|
15
|
+
project: Partial<{
|
|
16
|
+
name: string
|
|
17
|
+
name_source: MirrorProjectNameSource
|
|
18
|
+
}>
|
|
19
|
+
version: Partial<{
|
|
20
|
+
scheme: 'semver'
|
|
21
|
+
source: MirrorAdapterName
|
|
22
|
+
output: MirrorAdapterName[]
|
|
23
|
+
prerelease_id: string
|
|
24
|
+
}>
|
|
25
|
+
package: Partial<{ path: string }>
|
|
26
|
+
jsr: Partial<{ path: string }>
|
|
27
|
+
git: Partial<{
|
|
28
|
+
tag_template: string
|
|
29
|
+
commit: boolean
|
|
30
|
+
push: boolean
|
|
31
|
+
allow_dirty: boolean
|
|
32
|
+
}>
|
|
33
|
+
}>
|
|
34
|
+
|
|
35
|
+
export type MirrorConfig = {
|
|
36
|
+
schema: 1
|
|
37
|
+
cwd: string
|
|
38
|
+
configPath?: string
|
|
39
|
+
project: {
|
|
40
|
+
name?: string
|
|
41
|
+
nameSource?: MirrorProjectNameSource
|
|
42
|
+
}
|
|
43
|
+
version: {
|
|
44
|
+
scheme: 'semver'
|
|
45
|
+
source: MirrorAdapterName
|
|
46
|
+
output: MirrorAdapterName[]
|
|
47
|
+
prereleaseId: string
|
|
48
|
+
}
|
|
49
|
+
package: { path: string }
|
|
50
|
+
jsr: { path: string }
|
|
51
|
+
git: {
|
|
52
|
+
tagTemplate: string
|
|
53
|
+
commit: boolean
|
|
54
|
+
push: boolean
|
|
55
|
+
allowDirty: boolean
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export type MirrorCliOptions = {
|
|
60
|
+
cwd?: string
|
|
61
|
+
config?: string
|
|
62
|
+
format?: MirrorFormat
|
|
63
|
+
noColor?: boolean
|
|
64
|
+
source?: MirrorAdapterName
|
|
65
|
+
output?: MirrorAdapterName[]
|
|
66
|
+
packageFile?: string
|
|
67
|
+
jsrFile?: string
|
|
68
|
+
preid?: string
|
|
69
|
+
dryRun?: boolean
|
|
70
|
+
commit?: boolean
|
|
71
|
+
push?: boolean
|
|
72
|
+
allowDirty?: boolean
|
|
73
|
+
yes?: boolean
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export type MirrorConfigDiscovery = {
|
|
77
|
+
path?: string
|
|
78
|
+
raw?: MirrorRawConfig
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export type MirrorProject = {
|
|
82
|
+
name?: string
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export type MirrorVersionPlanAction =
|
|
86
|
+
| {
|
|
87
|
+
type: 'write-file'
|
|
88
|
+
adapter: 'package.json' | 'jsr.json'
|
|
89
|
+
path: string
|
|
90
|
+
currentVersion: string
|
|
91
|
+
nextVersion: string
|
|
92
|
+
}
|
|
93
|
+
| {
|
|
94
|
+
type: 'git-commit'
|
|
95
|
+
message: string
|
|
96
|
+
paths: string[]
|
|
97
|
+
}
|
|
98
|
+
| {
|
|
99
|
+
type: 'git-tag'
|
|
100
|
+
tag: string
|
|
101
|
+
}
|
|
102
|
+
| {
|
|
103
|
+
type: 'git-push'
|
|
104
|
+
includeCommit: boolean
|
|
105
|
+
includeTags: boolean
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export type MirrorVersionPlan = {
|
|
109
|
+
cwd: string
|
|
110
|
+
configPath?: string
|
|
111
|
+
source: MirrorAdapterName
|
|
112
|
+
output: MirrorAdapterName[]
|
|
113
|
+
currentVersion: string
|
|
114
|
+
nextVersion: string
|
|
115
|
+
project: MirrorProject
|
|
116
|
+
commitEnabled: boolean
|
|
117
|
+
pushEnabled: boolean
|
|
118
|
+
allowDirty: boolean
|
|
119
|
+
fileOutputPaths: string[]
|
|
120
|
+
gitTag?: string
|
|
121
|
+
actions: MirrorVersionPlanAction[]
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
export type MirrorExecutionResult = {
|
|
125
|
+
plan: MirrorVersionPlan
|
|
126
|
+
applied: boolean
|
|
127
|
+
dryRun: boolean
|
|
128
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @copyright Copyright (c) 2026 GUIHO Technologies as represented by Cristóvão GUIHO. All Rights Reserved.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { inc, rcompare, valid as validSemver } from 'semver'
|
|
6
|
+
import type { ReleaseType } from 'semver'
|
|
7
|
+
import { MirrorError } from './errors'
|
|
8
|
+
|
|
9
|
+
export const mirrorReleaseTargets = [
|
|
10
|
+
'major',
|
|
11
|
+
'premajor',
|
|
12
|
+
'minor',
|
|
13
|
+
'preminor',
|
|
14
|
+
'patch',
|
|
15
|
+
'prepatch',
|
|
16
|
+
'prerelease',
|
|
17
|
+
] as const satisfies readonly ReleaseType[]
|
|
18
|
+
|
|
19
|
+
export const isMirrorReleaseTarget = (target: string): target is ReleaseType =>
|
|
20
|
+
(mirrorReleaseTargets as readonly string[]).includes(target)
|
|
21
|
+
|
|
22
|
+
export const assertValidSemver = (version: string, label: string) => {
|
|
23
|
+
if (!validSemver(version)) throw new MirrorError(`${label} is not a valid semantic version: ${version}`)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export const resolveNextVersion = (currentVersion: string, target: string, prereleaseId = '') => {
|
|
27
|
+
assertValidSemver(currentVersion, 'Current version')
|
|
28
|
+
|
|
29
|
+
if (validSemver(target)) return target
|
|
30
|
+
if (!isMirrorReleaseTarget(target)) throw new MirrorError(`Invalid version target: ${target}`)
|
|
31
|
+
|
|
32
|
+
const nextVersion = prereleaseId ? inc(currentVersion, target, prereleaseId) : inc(currentVersion, target)
|
|
33
|
+
|
|
34
|
+
if (!nextVersion) throw new MirrorError(`Failed to resolve next version from ${currentVersion} using ${target}`)
|
|
35
|
+
|
|
36
|
+
return nextVersion
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export const sortSemverDescending = (versions: string[]) => [...versions].sort(rcompare)
|