relion 0.2.0 → 0.3.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.
Files changed (42) hide show
  1. package/dist/cli.js +64 -0
  2. package/dist/index.d.ts +231 -0
  3. package/dist/index.js +652 -0
  4. package/package.json +31 -50
  5. package/src/cli.js +0 -6
  6. package/src/commands.js +0 -176
  7. package/src/defaults.js +0 -60
  8. package/src/index.js +0 -75
  9. package/src/lib/checkpoint.js +0 -23
  10. package/src/lib/configuration.js +0 -35
  11. package/src/lib/detect-package-manager.js +0 -52
  12. package/src/lib/format-commit-message.js +0 -4
  13. package/src/lib/latest-semver-tag.js +0 -34
  14. package/src/lib/lifecycles/bump.js +0 -242
  15. package/src/lib/lifecycles/changelog.js +0 -106
  16. package/src/lib/lifecycles/commit.js +0 -67
  17. package/src/lib/lifecycles/tag.js +0 -61
  18. package/src/lib/print-error.js +0 -15
  19. package/src/lib/run-exec.js +0 -20
  20. package/src/lib/run-execFile.js +0 -20
  21. package/src/lib/run-lifecycle-script.js +0 -18
  22. package/src/lib/stringify-package.js +0 -34
  23. package/src/lib/updaters/index.js +0 -130
  24. package/src/lib/updaters/types/csproj.js +0 -13
  25. package/src/lib/updaters/types/gradle.js +0 -16
  26. package/src/lib/updaters/types/json.js +0 -25
  27. package/src/lib/updaters/types/maven.js +0 -43
  28. package/src/lib/updaters/types/openapi.js +0 -15
  29. package/src/lib/updaters/types/plain-text.js +0 -7
  30. package/src/lib/updaters/types/python.js +0 -30
  31. package/src/lib/updaters/types/yaml.js +0 -15
  32. package/src/lib/write-file.js +0 -6
  33. package/src/preset/constants.js +0 -16
  34. package/src/preset/index.js +0 -19
  35. package/src/preset/parser.js +0 -11
  36. package/src/preset/templates/commit.hbs +0 -19
  37. package/src/preset/templates/footer.hbs +0 -10
  38. package/src/preset/templates/header.hbs +0 -10
  39. package/src/preset/templates/index.js +0 -13
  40. package/src/preset/templates/main.hbs +0 -21
  41. package/src/preset/whatBump.js +0 -33
  42. package/src/preset/writer.js +0 -201
package/package.json CHANGED
@@ -1,17 +1,12 @@
1
1
  {
2
2
  "name": "relion",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "Release workflow helper for Node.js projects.",
5
- "author": "Kh4f",
5
+ "author": "Kh4f <kh4f.dev@gmail.com>",
6
6
  "license": "MIT",
7
- "repository": {
8
- "type": "git",
9
- "url": "git+https://github.com/Kh4f/relion.git"
10
- },
11
- "bugs": {
12
- "url": "https://github.com/Kh4f/relion/issues"
13
- },
14
- "homepage": "https://github.com/Kh4f/relion#readme",
7
+ "repository": "https://github.com/kh4f/relion",
8
+ "bugs": "https://github.com/kh4f/relion/issues",
9
+ "homepage": "https://github.com/kh4f/relion#readme",
15
10
  "keywords": [
16
11
  "relion",
17
12
  "release",
@@ -22,55 +17,41 @@
22
17
  "standard-version",
23
18
  "commit-and-tag-version"
24
19
  ],
25
- "main": "./src/index.js",
26
- "type": "module",
27
- "bin": "./src/cli.js",
28
20
  "files": [
29
- "src",
21
+ "dist",
30
22
  "package.json",
31
23
  "LICENSE",
32
24
  "README.md"
33
25
  ],
26
+ "type": "module",
27
+ "main": "dist/index.js",
28
+ "types": "dist/index.d.ts",
29
+ "bin": "dist/cli.js",
30
+ "dependencies": {
31
+ "cleye": "^1.3.4",
32
+ "handlebars": "^4.7.8",
33
+ "semver": "^7.7.2"
34
+ },
35
+ "devDependencies": {
36
+ "@eslint/js": "^9.34.0",
37
+ "@stylistic/eslint-plugin": "^5.3.1",
38
+ "@types/node": "^24.3.1",
39
+ "@types/semver": "^7.7.1",
40
+ "eslint": "^9.34.0",
41
+ "globals": "^16.3.0",
42
+ "lint-staged": "^16.1.6",
43
+ "simple-git-hooks": "^2.13.1",
44
+ "tsdown": "^0.14.2",
45
+ "typescript": "^5.9.2",
46
+ "typescript-eslint": "^8.42.0",
47
+ "vitest": "^3.2.4"
48
+ },
34
49
  "simple-git-hooks": {
35
50
  "pre-commit": "pnpm lint-staged"
36
51
  },
37
52
  "lint-staged": {
38
53
  "*.{js,ts}": "pnpm lint:fix"
39
54
  },
40
- "dependencies": {
41
- "chalk": "^5.4.1",
42
- "compare-func": "^2.0.0",
43
- "conventional-changelog": "^6.0.0",
44
- "conventional-changelog-config-spec": "^2.1.0",
45
- "conventional-changelog-conventionalcommits": "^8.0.0",
46
- "conventional-recommended-bump": "^11.0.0",
47
- "detect-indent": "^7.0.1",
48
- "detect-newline": "^4.0.1",
49
- "dotgitignore": "^2.1.0",
50
- "figures": "^6.1.0",
51
- "find-up": "^7.0.0",
52
- "git-semver-tags": "^8.0.0",
53
- "jsdom": "^26.1.0",
54
- "mergician": "^2.0.2",
55
- "semver": "^7.7.2",
56
- "w3c-xmlserializer": "^5.0.0",
57
- "yaml": "^2.8.0",
58
- "yargs": "^17.7.2"
59
- },
60
- "devDependencies": {
61
- "@eslint/js": "^9.29.0",
62
- "@stylistic/eslint-plugin": "^4.4.1",
63
- "@types/node": "^24.0.3",
64
- "eslint": "^9.29.0",
65
- "globals": "^16.2.0",
66
- "lint-staged": "^16.1.2",
67
- "prettier": "^3.5.3",
68
- "simple-git-hooks": "^2.13.0",
69
- "tsdown": "^0.12.8",
70
- "typescript": "^5.8.3",
71
- "typescript-eslint": "^8.34.1",
72
- "vitest": "^3.2.4"
73
- },
74
55
  "scripts": {
75
56
  "lint": "eslint",
76
57
  "lint:fix": "eslint --fix",
@@ -79,7 +60,7 @@
79
60
  "build": "tsdown",
80
61
  "build:watch": "tsdown --watch",
81
62
  "build:prod": "tsdown --production",
82
- "release": "node ./src/cli.js --changelog --bump --commit --tag",
83
- "release:gh-notes": "node ./src/cli.js --changelog --profile gh-release-notes "
63
+ "release": "node dist/cli.js -blct",
64
+ "release:github": "node dist/cli.js -l -p github"
84
65
  }
85
66
  }
package/src/cli.js DELETED
@@ -1,6 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- import relion from './index.js'
4
- import cmdParser from './commands.js'
5
-
6
- relion(cmdParser.argv)
package/src/commands.js DELETED
@@ -1,176 +0,0 @@
1
- import spec from 'conventional-changelog-config-spec'
2
- import { getConfiguration } from './lib/configuration.js'
3
- import defaults from './defaults.js'
4
- import yargs from 'yargs/yargs'
5
- import { hideBin } from 'yargs/helpers'
6
-
7
- const yargsInstance = yargs(hideBin(process.argv))
8
- .usage('Usage: $0 [options]')
9
- .option('bumpFiles', {
10
- default: defaults.bumpFiles,
11
- array: true,
12
- })
13
- .option('release-as', {
14
- alias: 'r',
15
- describe: 'Specify the release type manually (like npm version <major|minor|patch>)',
16
- requiresArg: true,
17
- string: true,
18
- })
19
- .option('prerelease', {
20
- alias: 'P',
21
- describe: 'make a pre-release with optional option value to specify a tag id',
22
- string: true,
23
- })
24
- .option('infile', {
25
- alias: 'i',
26
- describe: 'Read the CHANGELOG from this file',
27
- default: defaults.infile,
28
- })
29
- .option('sign', {
30
- alias: 's',
31
- describe: 'Should the git commit and tag be signed?',
32
- type: 'boolean',
33
- default: defaults.sign,
34
- })
35
- .option('signoff', {
36
- describe: 'Should the git commit have a "Signed-off-by" trailer',
37
- type: 'boolean',
38
- default: defaults.signoff,
39
- })
40
- .option('no-verify', {
41
- alias: 'n',
42
- describe: 'Bypass pre-commit or commit-msg git hooks during the commit phase',
43
- type: 'boolean',
44
- default: defaults.noVerify,
45
- })
46
- .option('commit-all', {
47
- alias: 'C',
48
- describe: 'Commit all staged changes, not just files affected by relion',
49
- type: 'boolean',
50
- default: defaults.commitAll,
51
- })
52
- .option('silent', {
53
- describe: 'Don\'t print logs and errors',
54
- type: 'boolean',
55
- default: defaults.silent,
56
- })
57
- .option('tag-prefix', {
58
- alias: 'T',
59
- describe: 'Set a custom prefix for the git tag to be created',
60
- type: 'string',
61
- default: defaults.tagPrefix,
62
- })
63
- .option('release-count', {
64
- describe:
65
- 'How many releases of changelog you want to generate. It counts from the upcoming release. Useful when you forgot to generate any previous changelog. Set to 0 to regenerate all.',
66
- type: 'number',
67
- default: defaults.releaseCount,
68
- })
69
- .option('tag-force', {
70
- describe: 'Allow tag replacement',
71
- type: 'boolean',
72
- default: defaults.tagForce,
73
- })
74
- .option('scripts', {
75
- describe: 'Provide scripts to execute for lifecycle events (prebump, precommit, etc.,)',
76
- default: defaults.scripts,
77
- })
78
- .option('bump', {
79
- alias: 'b',
80
- describe: 'Bump the version in bumpFiles',
81
- type: 'boolean',
82
- default: defaults.bump,
83
- })
84
- .option('changelog', {
85
- alias: 'l',
86
- describe: 'Generate a changelog',
87
- type: 'boolean',
88
- default: defaults.changelog,
89
- })
90
- .option('commit', {
91
- alias: 'c',
92
- describe: 'Create a git commit',
93
- type: 'boolean',
94
- default: defaults.commit,
95
- })
96
- .option('tag', {
97
- alias: 't',
98
- describe: 'Create a git tag',
99
- type: 'boolean',
100
- default: defaults.tag,
101
- })
102
- .option('all', {
103
- alias: 'a',
104
- describe: 'Run all lifecycle events',
105
- type: 'boolean',
106
- default: defaults.all,
107
- })
108
- .option('context.linkReferences', {
109
- describe: 'Should all references be linked?',
110
- type: 'boolean',
111
- default: defaults.context.linkReferences,
112
- })
113
- .option('context.fullChangelogLink', {
114
- describe: 'Add a "Full Changelog: v1...v2" link to the footer',
115
- type: 'boolean',
116
- default: defaults.context.fullChangelogLink,
117
- })
118
- .option('profile', {
119
- alias: 'p',
120
- describe: 'Specify a named config profile to merge with the base config (properties under _<profile-name> in .versionrc)',
121
- type: 'string',
122
- })
123
- .option('dry-run', {
124
- type: 'boolean',
125
- default: defaults.dryRun,
126
- describe: 'See the commands that running relion would run',
127
- })
128
- .option('git-tag-fallback', {
129
- type: 'boolean',
130
- default: defaults.gitTagFallback,
131
- describe:
132
- 'fallback to git tags for version, if no meta-information file is found (e.g., package.json)',
133
- })
134
- .option('path', {
135
- type: 'string',
136
- describe: 'Only populate commits made under this path',
137
- })
138
- .option('lerna-package', {
139
- type: 'string',
140
- describe: 'Name of the package from which the tags will be extracted',
141
- })
142
- .option('npmPublishHint', {
143
- type: 'string',
144
- default: defaults.npmPublishHint,
145
- describe: 'Customized publishing hint',
146
- })
147
- .check((argv) => {
148
- if (typeof argv.scripts !== 'object' || Array.isArray(argv.scripts)) {
149
- throw Error('scripts must be an object')
150
- }
151
- else {
152
- return true
153
- }
154
- })
155
- .alias('version', 'v')
156
- .alias('help', 'h')
157
- .example('$0', 'Update changelog and tag release')
158
- .example(
159
- '$0 -m "%s: see changelog for details"',
160
- 'Update changelog and tag release with custom commit message',
161
- )
162
- .pkgConf('relion')
163
- .config(await getConfiguration())
164
- .wrap(97)
165
-
166
- Object.keys(spec.properties).forEach((propertyKey) => {
167
- const property = spec.properties[propertyKey]
168
- if (!defaults.preset[propertyKey]) return
169
- yargsInstance.option('preset.' + propertyKey, {
170
- type: property.type,
171
- describe: property.description,
172
- default: defaults.preset[propertyKey],
173
- })
174
- })
175
-
176
- export default yargsInstance
package/src/defaults.js DELETED
@@ -1,60 +0,0 @@
1
- const defaultPresetURL = import.meta.resolve('./preset/index.js')
2
-
3
- const defaults = {
4
- bump: false,
5
- changelog: false,
6
- commit: false,
7
- tag: false,
8
- all: false,
9
-
10
- infile: 'CHANGELOG.md',
11
- sign: false,
12
- signoff: false,
13
- noVerify: false,
14
- commitAll: false,
15
- silent: false,
16
- tagPrefix: 'v',
17
- releaseCount: 1,
18
- scripts: {},
19
- dryRun: false,
20
- tagForce: false,
21
- gitTagFallback: true,
22
- npmPublishHint: undefined,
23
- bumpFiles: ['package.json', 'package-lock.json'],
24
-
25
- context: {
26
- linkReferences: true,
27
- fullChangelogLink: false,
28
- },
29
-
30
- preset: {
31
- name: defaultPresetURL,
32
- header: '# Changelog\n\n\n',
33
- types: [
34
- { type: 'feat', section: 'Features' },
35
- { type: 'fix', section: 'Bug Fixes' },
36
- { type: 'chore', hidden: true },
37
- { type: 'docs', hidden: true },
38
- { type: 'style', hidden: true },
39
- { type: 'refactor', hidden: true },
40
- { type: 'perf', hidden: true },
41
- { type: 'test', hidden: true },
42
- ],
43
- /* Is set to true automatically if version < 1.0.0,
44
- or matches the user config if provided.
45
- */
46
- // preMajor: true,
47
- commitUrlFormat: '{{host}}/{{owner}}/{{repository}}/commit/{{hash}}',
48
- compareUrlFormat: '{{host}}/{{owner}}/{{repository}}/compare/{{previousTag}}...{{currentTag}}',
49
- issueUrlFormat: '{{host}}/{{owner}}/{{repository}}/issues/{{id}}',
50
- userUrlFormat: '{{host}}/{{user}}',
51
- releaseCommitMessageFormat: 'chore(release): {{currentTag}}',
52
- issuePrefixes: ['#'],
53
- },
54
-
55
- writerOpts: {
56
- commitsSort: false,
57
- },
58
- }
59
-
60
- export default defaults
package/src/index.js DELETED
@@ -1,75 +0,0 @@
1
- import bump, { getNewVersion } from './lib/lifecycles/bump.js'
2
- import changelog from './lib/lifecycles/changelog.js'
3
- import commit from './lib/lifecycles/commit.js'
4
- import { readFileSync } from 'fs'
5
- import tag from './lib/lifecycles/tag.js'
6
- import defaults from './defaults.js'
7
- import { mergician } from 'mergician'
8
- import { execSync } from 'child_process'
9
-
10
- export default async function relion(argv) {
11
- let args = mergician(defaults, argv)
12
- if (args.profile) args = mergeProfileConfig(args)
13
-
14
- if (args.all) args.bump = args.changelog = args.commit = args.tag = true
15
-
16
- const currentVersion = getCurrentVersion()
17
- const newVersion = await getNewVersion(args, currentVersion)
18
- args.context.version = newVersion
19
- args.context.newTag = args.tagPrefix + newVersion
20
-
21
- if (lastCommitHasTag()) {
22
- // use the current version as the new version if there's no new commits
23
- // to avoid empty new release changelog generation
24
- args.context.version = currentVersion
25
-
26
- if (args.releaseCount === 1) {
27
- // genearate the last release changelog
28
- args.releaseCount = 2
29
- }
30
- }
31
-
32
- if (args.bump) await bump(args, newVersion)
33
- if (args.changelog) await changelog(args, newVersion)
34
- if (args.commit) await commit(args, newVersion)
35
- if (args.tag) await tag(newVersion, false, args)
36
- }
37
-
38
- function getCurrentVersion() {
39
- const packageJsonContent = readFileSync('package.json', 'utf-8')
40
- return /"version".*?"(.*?)"/.exec(packageJsonContent)?.[1]
41
- }
42
-
43
- function lastCommitHasTag() {
44
- const lastCommit = execSync('git rev-parse HEAD').toString().trim()
45
- const tags = execSync(`git tag --points-at ${lastCommit}`).toString().trim()
46
- return !!tags
47
- }
48
-
49
- /**
50
- * Merge profile config if args.profile is specified.
51
- * Merges args._<profile> into args, then deletes args._<profile>.
52
- */
53
- function mergeProfileConfig(args) {
54
- function uniqBy(arr, keyFn) {
55
- const seen = new Set()
56
- return arr.filter((item) => {
57
- const key = keyFn(item)
58
- if (seen.has(key)) return false
59
- seen.add(key)
60
- return true
61
- })
62
- }
63
-
64
- const profileKey = `_${args.profile}`
65
- const merged = mergician({
66
- prependArrays: true,
67
- dedupArrays: true,
68
- })(args, structuredClone(args[profileKey]))
69
-
70
- const dedupedTypes = uniqBy(merged.preset.types, item => item.type)
71
- merged.preset.types = dedupedTypes
72
-
73
- delete merged[profileKey]
74
- return merged
75
- }
@@ -1,23 +0,0 @@
1
- import chalk from 'chalk'
2
- import figures from 'figures'
3
- import util from 'util'
4
-
5
- export default function (argv, msg, args, figure) {
6
- const defaultFigure = argv.dryRun
7
- ? chalk.yellow(figures.tick)
8
- : chalk.green(figures.tick)
9
- if (!argv.silent) {
10
- console.info(
11
- (figure || defaultFigure)
12
- + ' '
13
- + util.format.apply(
14
- util,
15
- [msg].concat(
16
- args.map(function (arg) {
17
- return chalk.bold(arg)
18
- }),
19
- ),
20
- ),
21
- )
22
- }
23
- }
@@ -1,35 +0,0 @@
1
- import path from 'path'
2
- import { findUpSync } from 'find-up'
3
- import { readFileSync } from 'fs'
4
- import { pathToFileURL } from 'url'
5
-
6
- const CONFIGURATION_FILES = [
7
- '', '.json', '.js', '.cjs', '.mjs', '.ts']
8
- .map(ext => `.versionrc${ext}`)
9
-
10
- export async function getConfiguration() {
11
- let config = {}
12
- const configPath = findUpSync(CONFIGURATION_FILES)
13
- if (!configPath) return config
14
-
15
- const ext = path.extname(configPath)
16
- const regex = /^\.([cm]?js|ts)$/
17
- if (regex.test(ext)) {
18
- const exportedConfig = (await import(pathToFileURL(configPath).href)).default
19
- if (typeof exportedConfig === 'function') {
20
- config = exportedConfig()
21
- }
22
- else {
23
- config = exportedConfig
24
- }
25
- }
26
- else {
27
- config = JSON.parse(readFileSync(configPath))
28
- }
29
-
30
- if (typeof config !== 'object') {
31
- throw Error(`[relion] Invalid configuration in ${configPath} provided. Expected an object but found ${typeof config}.`)
32
- }
33
-
34
- return config
35
- }
@@ -1,52 +0,0 @@
1
- /**
2
- * modified from <https://github.com/egoist/detect-package-manager/blob/main/src/index.ts>
3
- * the original code is licensed under MIT
4
- * modified to support only detecting lock file and not detecting global package manager
5
- */
6
-
7
- import { promises as fs } from 'fs'
8
- import { resolve } from 'path'
9
-
10
- /**
11
- * Check if a path exists
12
- */
13
- async function pathExists(p) {
14
- try {
15
- await fs.access(p)
16
- return true
17
- }
18
- catch {
19
- return false
20
- }
21
- }
22
-
23
- function getTypeofLockFile(cwd = '.') {
24
- return Promise.all([
25
- pathExists(resolve(cwd, 'yarn.lock')),
26
- pathExists(resolve(cwd, 'package-lock.json')),
27
- pathExists(resolve(cwd, 'pnpm-lock.yaml')),
28
- ]).then(([isYarn, isNpm, isPnpm]) => {
29
- let value = null
30
-
31
- if (isYarn) {
32
- value = 'yarn'
33
- }
34
- else if (isPnpm) {
35
- value = 'pnpm'
36
- }
37
- else if (isNpm) {
38
- value = 'npm'
39
- }
40
-
41
- return value
42
- })
43
- }
44
-
45
- export async function detectPMByLockFile(cwd) {
46
- const type = await getTypeofLockFile(cwd)
47
- if (type) {
48
- return type
49
- }
50
-
51
- return 'npm'
52
- }
@@ -1,4 +0,0 @@
1
- export default function (args) {
2
- const message = String(args.preset.releaseCommitMessageFormat)
3
- return message.replace(/{{currentTag}}/g, args.tagPrefix + args.context.version)
4
- }
@@ -1,34 +0,0 @@
1
- import * as gitSemverTags from 'git-semver-tags'
2
- import semver from 'semver'
3
-
4
- export default function ({ tagPrefix, prerelease }) {
5
- return new Promise((resolve, reject) => {
6
- gitSemverTags({ tagPrefix }, function (err, tags) {
7
- if (err) return reject(err)
8
- else if (!tags.length) return resolve('1.0.0')
9
- // Respect tagPrefix
10
- tags = tags.map(tag => tag.replace(new RegExp('^' + tagPrefix), ''))
11
- if (prerelease) {
12
- // ignore any other prelease tags
13
- tags = tags.filter((tag) => {
14
- if (!semver.valid(tag)) return false
15
- if (!semver.prerelease(tag)) {
16
- // include all non-prerelease versions
17
- return true
18
- }
19
- // check if the name of the prerelease matches the one we are looking for
20
- if (semver.prerelease(tag)[0] === prerelease) {
21
- return true
22
- }
23
- return false
24
- })
25
- }
26
- // ensure that the largest semver tag is at the head.
27
- tags = tags.map((tag) => {
28
- return semver.clean(tag)
29
- })
30
- tags.sort(semver.rcompare)
31
- return resolve(tags[0])
32
- })
33
- })
34
- }