rman 0.38.0 → 1.0.2

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 (119) hide show
  1. package/README.md +371 -21
  2. package/cli.js +51 -29
  3. package/commands/build.command.d.ts +3 -0
  4. package/commands/build.command.js +14 -0
  5. package/commands/changed.command.d.ts +3 -0
  6. package/commands/changed.command.js +29 -0
  7. package/commands/changelog.command.d.ts +3 -0
  8. package/commands/changelog.command.js +63 -0
  9. package/commands/ci.command.d.ts +3 -0
  10. package/commands/ci.command.js +30 -0
  11. package/commands/clean.command.d.ts +3 -0
  12. package/commands/clean.command.js +36 -0
  13. package/commands/diff.command.d.ts +3 -0
  14. package/commands/diff.command.js +51 -0
  15. package/commands/exec.command.d.ts +3 -0
  16. package/commands/exec.command.js +83 -0
  17. package/commands/import.command.d.ts +3 -0
  18. package/commands/import.command.js +27 -0
  19. package/commands/info.command.d.ts +3 -0
  20. package/commands/info.command.js +61 -0
  21. package/commands/list.command.d.ts +3 -0
  22. package/commands/list.command.js +113 -0
  23. package/commands/publish.command.d.ts +3 -0
  24. package/commands/publish.command.js +147 -0
  25. package/commands/run.command.d.ts +6 -0
  26. package/commands/run.command.js +80 -0
  27. package/commands/test.command.d.ts +3 -0
  28. package/commands/test.command.js +14 -0
  29. package/commands/version.command.d.ts +3 -0
  30. package/commands/version.command.js +125 -0
  31. package/constants.js +1 -1
  32. package/core/config.d.ts +13 -0
  33. package/core/config.js +61 -0
  34. package/core/package.d.ts +2 -0
  35. package/core/package.js +2 -0
  36. package/core/repository.d.ts +36 -3
  37. package/core/repository.js +90 -45
  38. package/index.d.ts +17 -1
  39. package/index.js +15 -1
  40. package/package.json +8 -4
  41. package/rmanrc.schema.json +202 -0
  42. package/services/changelog.service.d.ts +99 -0
  43. package/services/changelog.service.js +272 -0
  44. package/services/ci.service.d.ts +40 -0
  45. package/services/ci.service.js +204 -0
  46. package/services/clean.service.d.ts +42 -0
  47. package/services/clean.service.js +226 -0
  48. package/services/exec.service.d.ts +35 -0
  49. package/services/exec.service.js +114 -0
  50. package/services/import.service.d.ts +30 -0
  51. package/services/import.service.js +84 -0
  52. package/services/list.service.d.ts +27 -0
  53. package/services/list.service.js +25 -0
  54. package/services/publish.service.d.ts +79 -0
  55. package/services/publish.service.js +199 -0
  56. package/services/run.service.d.ts +99 -0
  57. package/services/run.service.js +432 -0
  58. package/services/system-info.d.ts +16 -0
  59. package/services/system-info.js +25 -0
  60. package/services/version.service.d.ts +95 -0
  61. package/services/version.service.js +450 -0
  62. package/services.d.ts +10 -0
  63. package/services.js +10 -0
  64. package/utils/branch-guard.d.ts +25 -0
  65. package/utils/branch-guard.js +61 -0
  66. package/utils/change-hash.d.ts +55 -0
  67. package/utils/change-hash.js +80 -0
  68. package/utils/conventional-commits.d.ts +39 -0
  69. package/utils/conventional-commits.js +43 -0
  70. package/utils/exec.d.ts +5 -6
  71. package/utils/exec.js +45 -59
  72. package/utils/git.d.ts +86 -0
  73. package/utils/git.js +276 -0
  74. package/utils/live-region.d.ts +16 -0
  75. package/utils/live-region.js +59 -0
  76. package/utils/logger.d.ts +24 -0
  77. package/utils/logger.js +39 -0
  78. package/utils/npm-run-path.d.ts +1 -1
  79. package/utils/npm-run-path.js +10 -10
  80. package/utils/package-filter.d.ts +32 -0
  81. package/utils/package-filter.js +73 -0
  82. package/utils/progress-panel.d.ts +59 -0
  83. package/utils/progress-panel.js +149 -0
  84. package/utils/workspace-range.d.ts +17 -0
  85. package/utils/workspace-range.js +28 -0
  86. package/commands/build-command.d.ts +0 -11
  87. package/commands/build-command.js +0 -26
  88. package/commands/changed-command.d.ts +0 -16
  89. package/commands/changed-command.js +0 -35
  90. package/commands/ci-command.d.ts +0 -24
  91. package/commands/ci-command.js +0 -71
  92. package/commands/execute-command.d.ts +0 -19
  93. package/commands/execute-command.js +0 -75
  94. package/commands/info-command.d.ts +0 -10
  95. package/commands/info-command.js +0 -57
  96. package/commands/list-command.d.ts +0 -38
  97. package/commands/list-command.js +0 -137
  98. package/commands/multi-task-command.d.ts +0 -22
  99. package/commands/multi-task-command.js +0 -68
  100. package/commands/publish-command.d.ts +0 -24
  101. package/commands/publish-command.js +0 -135
  102. package/commands/run-command.d.ts +0 -28
  103. package/commands/run-command.js +0 -134
  104. package/commands/version-command.d.ts +0 -25
  105. package/commands/version-command.js +0 -198
  106. package/core/command.d.ts +0 -35
  107. package/core/command.js +0 -117
  108. package/core/constants.d.ts +0 -1
  109. package/core/constants.js +0 -2
  110. package/core/logger.d.ts +0 -12
  111. package/core/logger.js +0 -2
  112. package/utils/file-utils.d.ts +0 -4
  113. package/utils/file-utils.js +0 -29
  114. package/utils/git-utils.d.ts +0 -25
  115. package/utils/git-utils.js +0 -66
  116. package/utils/npm-utils.d.ts +0 -11
  117. package/utils/npm-utils.js +0 -33
  118. package/utils/package-not-found-error.d.ts +0 -2
  119. package/utils/package-not-found-error.js +0 -2
package/README.md CHANGED
@@ -1,33 +1,383 @@
1
- ## rman
2
-
1
+ # rman
2
+
3
3
  [![NPM Version][npm-image]][npm-url]
4
4
  [![NPM Downloads][downloads-image]][downloads-url]
5
- [![Build Status][travis-image]][travis-url]
5
+ [![CI Tests][ci-test-image]][ci-test-url]
6
6
  [![Test Coverage][coveralls-image]][coveralls-url]
7
7
 
8
+ **rman** is a monorepo management CLI: a self-contained alternative to reaching for Lerna,
9
+ Changesets, and a handful of shell scripts glued together. One tool for running scripts across
10
+ packages, computing semantic version bumps from your commit history, publishing, changelogs,
11
+ importing external repos with history intact, and more - all driven by a single, cascading
12
+ `.rmanrc`/`.rman.yml` config.
13
+
14
+ Every command is also available as a **programmatic API** - see [docs/api.md](docs/api.md) if you
15
+ want to call `rman`'s logic directly from a Node.js script instead of shelling out to the CLI.
16
+
17
+ ## Table of contents
18
+
19
+ - [Installation](#installation)
20
+ - [Quick start](#quick-start)
21
+ - [Commands](#commands)
22
+ - [Configuration](#configuration)
23
+ - [Programmatic API](#programmatic-api)
24
+ - [Node compatibility](#node-compatibility)
25
+ - [License](#license)
26
+
27
+ ## Installation
28
+
29
+ ```bash
30
+ npm install --save-dev rman
31
+ ```
32
+
33
+ Or run it without installing, via `npx`:
34
+
35
+ ```bash
36
+ npx rman list
37
+ ```
38
+
39
+ `rman` requires **Node.js >= 20**.
40
+
41
+ ## Quick start
42
+
43
+ `rman` auto-detects your repository layout - point it at a directory containing a `package.json`
44
+ with a `workspaces` array (npm/yarn/pnpm-style) and every matched package becomes available to
45
+ every command:
46
+
47
+ ```json
48
+ // package.json (repository root)
49
+ {
50
+ "name": "my-monorepo",
51
+ "private": true,
52
+ "workspaces": ["packages/*"]
53
+ }
54
+ ```
55
+
56
+ ```bash
57
+ # See what's in the repository
58
+ rman list
59
+
60
+ # Run "build" in every package, dependencies first
61
+ rman build
62
+
63
+ # See what the next release would look like, without changing anything
64
+ rman version
65
+
66
+ # Apply it: bump versions, write CHANGELOG.md, commit, tag
67
+ rman version --changelog
68
+
69
+ # Publish everything that isn't already on the registry
70
+ rman publish
71
+ ```
72
+
73
+ Run any command with `--help` for its full option list (`rman version --help`, `rman run --help`, ...).
74
+
75
+ ## Commands
76
+
77
+ The summaries and examples below cover the common cases. For the full option list, defaults, and
78
+ worked examples of every single command, see **[docs/cli.md](docs/cli.md)**.
79
+
80
+ | Command | Purpose |
81
+ | --- | --- |
82
+ | [`list` (`ls`)](#rman-list) | Lists packages in the repository. |
83
+ | [`info`](#rman-info) | Prints local environment and repository information. |
84
+ | [`run <script>`](#rman-run-script) | Runs an npm script in each package. |
85
+ | [`build`](#rman-build) | Alias for `run build`. |
86
+ | [`test`](#rman-test) | Alias for `run test`. |
87
+ | [`exec <command..>`](#rman-exec-command) | Runs an arbitrary shell command in each package. |
88
+ | [`ci`](#rman-ci) | Deletes `node_modules`/lockfiles everywhere, then reinstalls from scratch. |
89
+ | [`clean`](#rman-clean) | Removes compiled TypeScript output and configured extra files/dirs. |
90
+ | [`changed`](#rman-changed) | Shows which packages the next `version` run would bump. |
91
+ | [`diff [package]`](#rman-diff-package) | Shows the git diff since a package's (or the repo's) last release tag. |
92
+ | [`changelog`](#rman-changelog) | Generates a changelog per package from unreleased commits. |
93
+ | [`version [bump]`](#rman-version-bump) | Bumps versions of changed packages (and their dependents). |
94
+ | [`publish`](#rman-publish) | Publishes every non-private package not already on the registry. |
95
+ | [`import <path>`](#rman-import-path) | Imports an external git repository as a new package, with history. |
96
+
97
+ Options shared across several commands:
98
+
99
+ - **Package filtering** (`list`, `run`/`build`/`test`, `exec`, `ci`, `clean`, `version`, `publish`,
100
+ `changelog`): `--scope <glob>`, `--ignore <glob>`, `--deps`, `--dependents` - see
101
+ [Package filtering](docs/api.md#package-filtering-scopeignoredepsdependents) for the full
102
+ semantics.
103
+ - **Branch guard** (every command that mutates state or runs scripts - `run`/`build`/`test`,
104
+ `exec`, `ci`, `clean`, `version`, `publish`): `--allow-branch <glob>`, `--ignore-branch <glob>` -
105
+ refuses to run unless (or if) the current git branch matches, the same idea as GitHub Actions'
106
+ own `branches`/`branches-ignore` workflow filters.
107
+
108
+ ### `rman list`
109
+
110
+ Lists packages in the repository (alias: `ls`).
111
+
112
+ ```bash
113
+ rman list # table: Package / Version / Private / Changed / Path
114
+ rman ls --short # just the bare package names
115
+ rman list --json # full detail as JSON
116
+ rman list --parseable # location::name::version::PRIVATE::STATUS lines, for scripting
117
+ rman list --toposort # dependencies before dependents, instead of directory order
118
+ rman list --graph # dependency graph as a JSON adjacency list
119
+ rman list --changed # only packages changed since the last publish
120
+ rman list --changed-since HEAD~5
121
+ rman list --scope '@myorg/*' --ignore '*-internal'
122
+ ```
123
+
124
+ ### `rman info`
125
+
126
+ Prints local environment (OS/CPU/memory, Node/npm/Yarn versions, git) and repository information.
127
+
128
+ ```bash
129
+ rman info
130
+ rman info --json
131
+ ```
132
+
133
+ ### `rman run <script>`
134
+
135
+ Runs an npm script in each package, in dependency order by default.
136
+
137
+ ```bash
138
+ rman run build
139
+ rman run lint --topo=false # independent packages, alphabetical order, no dependency waiting
140
+ rman run test --changed # only in packages changed since the last publish
141
+ rman run build --changed-since v1.2.0
142
+ rman run build --parallel 4 # at most 4 packages at once
143
+ rman run build --parallel false # serially, one at a time
144
+ rman run build --bail=false # don't stop the whole batch on one package's failure
145
+ rman run build --scope pkg-a --deps # pkg-a plus everything it depends on
146
+ ```
147
+
148
+ Per-package/script behavior (pre/post hooks, `if` conditions, skip, concurrency, ...) is
149
+ configurable via `.rmanrc run.<script>.*` - see [Configuration](#configuration) below and the full
150
+ writeup in [docs/api.md](docs/api.md#runservice).
151
+
152
+ ### `rman build`
153
+
154
+ Alias for `rman run build`.
155
+
156
+ ```bash
157
+ rman build
158
+ ```
159
+
160
+ ### `rman test`
161
+
162
+ Alias for `rman run test`.
163
+
164
+ ```bash
165
+ rman test
166
+ ```
167
+
168
+ ### `rman exec <command..>`
169
+
170
+ Runs an arbitrary shell command in each package - unlike `run`, it isn't tied to any npm script.
171
+
172
+ ```bash
173
+ rman exec rm -rf dist
174
+ rman exec -- eslint --fix # "--" needed only if the command shares a flag name with exec's own
175
+ rman exec --scope pkg-a -- ls -la
176
+ rman exec --topo=false pwd # every package independently, alphabetical order
177
+ ```
178
+
179
+ ### `rman ci`
180
+
181
+ Deletes `node_modules` and any lockfile in every package (or runs the package's own `"ci"` script
182
+ instead, if it defines one), then installs once at the root.
183
+
184
+ ```bash
185
+ rman ci
186
+ rman ci --package-manager pnpm
187
+ ```
8
188
 
9
- Monorepo repository manager
189
+ ### `rman clean`
10
190
 
11
- ## Node Compatibility
191
+ Removes compiled TypeScript output (`.js`/`.js.map`/`.d.ts` under `src`/`test`, plus any
192
+ `*.tsbuildinfo`) and whatever `.rmanrc clean.include`/`clean.exclude` configures. Never touches
193
+ `node_modules` - that's `ci`'s job.
12
194
 
13
- - node >= 14.x
195
+ ```bash
196
+ rman clean
197
+ rman clean --dry-run # preview what would be removed
198
+ ```
14
199
 
15
- ### License
16
- rman is available under [MIT](LICENSE) license.
200
+ ### `rman changed`
17
201
 
18
- [npm-image]: https://img.shields.io/npm/v/rman.svg
202
+ Shows which packages the next `rman version` run would bump, without changing anything.
203
+
204
+ ```bash
205
+ rman changed
206
+ rman changed --json
207
+ ```
208
+
209
+ ### `rman diff [package]`
210
+
211
+ Shows the git diff since a package's (or the whole repository's) last release tag.
212
+
213
+ ```bash
214
+ rman diff # since the repository's own last tag
215
+ rman diff pkg-a # since pkg-a's own last tag, scoped to its directory
216
+ ```
217
+
218
+ ### `rman changelog`
219
+
220
+ Generates a changelog per package from unreleased commits, grouped into ✨ Features / 🐛 Bug Fixes
221
+ / 🔧 Other Changes.
222
+
223
+ ```bash
224
+ rman changelog # auto-detects each package's last published npm version
225
+ rman changelog --from a1b2c3d # since a specific commit, for every package
226
+ rman changelog --write # prepend into each package's own CHANGELOG.md
227
+ rman changelog --write --file-path docs/CHANGELOG.md
228
+ ```
229
+
230
+ ### `rman version [bump]`
231
+
232
+ Bumps versions of changed packages (and their in-group dependents), grouped via `.rmanrc "group"`.
233
+
234
+ ```bash
235
+ rman version # auto-detect severity from commits, preview only - writes nothing
236
+ rman version --interactive # preview, then ask for confirmation either way
237
+ rman version patch # apply a patch bump to every changed package/group, immediately
238
+ rman version minor
239
+ rman version major
240
+ rman version 2.0.0-rc.1 # an explicit semver version, applied verbatim
241
+ rman version minor --preid beta # 1.2.3 -> 1.3.0-beta.0 (run again with --preid beta to increment it)
242
+ rman version --changelog # also write/fold in each bumped package's CHANGELOG.md
243
+ rman version patch --push # commit, tag, and push in one go
244
+ rman version patch --message "chore(release): {version}"
245
+ rman version --ignore-dirty # exclude dirty packages instead of aborting the whole run
246
+ ```
247
+
248
+ Severity, when not given explicitly, is auto-detected per package/group from
249
+ [Conventional Commits](https://www.conventionalcommits.org/) since that group's last release tag -
250
+ `fix:` → patch, `feat:` → minor, `feat!:`/a `BREAKING CHANGE:` footer → major. A `Release-As:
251
+ patch|minor|major` commit-body footer can override one specific commit's own contribution to that
252
+ - e.g. to ship a `feat:` as a patch right now instead of waiting for the rest of a minor's worth of
253
+ work:
254
+
255
+ ```
256
+ feat: needs to ship right now
257
+
258
+ Release-As: patch
259
+ ```
260
+
261
+ See [docs/api.md#versionservice](docs/api.md#versionservice) for the full grouping/propagation
262
+ algorithm, prerelease semantics, and `"workspace:"` dependency-range handling.
263
+
264
+ ### `rman publish`
265
+
266
+ Publishes every non-private package whose local version isn't already on the registry.
267
+
268
+ ```bash
269
+ rman publish # show the plan, then ask for confirmation
270
+ rman publish --yes # publish immediately, no confirmation
271
+ rman publish --dry-run # only show the plan, never publish
272
+ rman publish --access public # required for a new scoped package
273
+ rman publish --tag next
274
+ rman publish --otp 123456
275
+ rman publish --registry https://registry.example.com --userconfig ./ci.npmrc
276
+ rman publish --package-manager pnpm
277
+ ```
278
+
279
+ A `"workspace:*"`/`"workspace:^"`/`"workspace:~"` dependency range is automatically rewritten to a
280
+ real, registry-consumable range immediately before each package's publish, and restored right
281
+ after - see [docs/api.md#publishservice](docs/api.md#publishservice).
282
+
283
+ ### `rman import <path>`
284
+
285
+ Imports an external git repository as a new package, preserving its **entire commit history**
286
+ (`git blame`/`git log --follow` keep working on the imported files afterward).
287
+
288
+ ```bash
289
+ rman import ../my-old-standalone-repo
290
+ rman import ../my-old-standalone-repo --dest libs # under libs/ instead of packages/
291
+ ```
292
+
293
+ `path` must be a local clone (not a URL) - clone the source repository first if it isn't local
294
+ already. After importing, add the new directory to your `workspaces` glob if it isn't already
295
+ covered, then run `rman ci` to install it.
296
+
297
+ ## Configuration
298
+
299
+ `rman` reads config cascaded from the repository root down to each package's own directory (the
300
+ same way a `tsconfig.json` `extends` chain works) - a value set closer to a package overrides the
301
+ same key set further up. Three file forms are supported per directory, merged in increasing
302
+ precedence: `package.json`'s own `"rman"` key, `.rman.yml` (YAML), and `.rmanrc` (**JSON**, despite
303
+ the dotfile-style name).
304
+
305
+ ```yaml
306
+ # .rman.yml, at the repository root
307
+ packageManager: pnpm
308
+ logLevel: info
309
+ allowBranch: [main, release/*]
310
+
311
+ group: true # implicit repo-wide version group by default
312
+
313
+ version:
314
+ commitMessage: 'chore(release): v{version}'
315
+
316
+ changelog:
317
+ ignoreTypes: [chore, ci]
318
+ tagPattern: 'v*'
319
+
320
+ run:
321
+ build:
322
+ concurrency: 4
323
+ lint:
324
+ topo: false
325
+ bail: false
326
+ test:
327
+ changedSince: v1.0.0
328
+ ```
329
+
330
+ ```json
331
+ // packages/core/.rmanrc - this one package overrides just its own group
332
+ { "group": false }
333
+ ```
334
+
335
+ ```json
336
+ // packages/plugin-a/.rmanrc - versions together with plugin-b, independent of everyone else
337
+ { "group": "plugins" }
338
+ ```
339
+
340
+ See [docs/api.md#configuration-rmanrc-rmanyml](docs/api.md#configuration-rmanrc-rmanyml) for the
341
+ full key reference (every `run.<script>.*` sub-key, `clean.*`, `changelog.*`, precedence rules,
342
+ and which keys are root-level-only today).
343
+
344
+ **Editor autocomplete:** `rman` ships a JSON Schema for `.rmanrc`/`.rman.yml` at
345
+ `rman/rmanrc.schema.json` - add `"$schema": "./node_modules/rman/rmanrc.schema.json"` to your
346
+ `.rmanrc` (or the equivalent `# yaml-language-server: $schema=...` comment in `.rman.yml`) to get
347
+ autocomplete and validation in VS Code/WebStorm. See
348
+ [docs/api.md#editor-support-json-schema](docs/api.md#editor-support-json-schema) for details,
349
+ including a WebStorm setup that needs no changes to the config file itself.
350
+
351
+ ## Programmatic API
352
+
353
+ Every command above is a thin wrapper around an exported service function - call them directly
354
+ from your own Node.js scripts without shelling out to the `rman` binary:
355
+
356
+ ```ts
357
+ import { Repository, VersionService } from 'rman';
358
+
359
+ const repository = Repository.create();
360
+ const plan = await VersionService.getPlan(repository);
361
+ await VersionService.applyPlan(repository, plan, { changelog: true, push: true });
362
+ ```
363
+
364
+ Full reference, with detailed examples for every service (`VersionService`, `PublishService`,
365
+ `ChangelogService`, `RunService`, `CiService`, `CleanService`, `ExecService`, `ListService`,
366
+ `ImportService`, `SystemInfo`) and the `Repository`/`Package` core classes: **[docs/api.md](docs/api.md)**.
367
+
368
+ ## Node compatibility
369
+
370
+ - Node.js >= 20
371
+
372
+ ## License
373
+
374
+ rman is available under the [MIT](LICENSE) license.
375
+
376
+ [npm-image]: https://img.shields.io/npm/v/rman
19
377
  [npm-url]: https://npmjs.org/package/rman
20
- [travis-image]: https://img.shields.io/travis/panates/rman/master.svg
21
- [travis-url]: https://travis-ci.com/panates/rman
22
- [coveralls-image]: https://img.shields.io/coveralls/panates/rman/master.svg
23
- [coveralls-url]: https://coveralls.io/r/panates/rman
24
378
  [downloads-image]: https://img.shields.io/npm/dm/rman.svg
25
379
  [downloads-url]: https://npmjs.org/package/rman
26
- [gitter-image]: https://badges.gitter.im/panates/rman.svg
27
- [gitter-url]: https://gitter.im/panates/rman?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge
28
- [dependencies-image]: https://david-dm.org/panates/rman/status.svg
29
- [dependencies-url]:https://david-dm.org/panates/rman
30
- [devdependencies-image]: https://david-dm.org/panates/rman/dev-status.svg
31
- [devdependencies-url]:https://david-dm.org/panates/rman?type=dev
32
- [quality-image]: http://npm.packagequality.com/shield/rman.png
33
- [quality-url]: http://packagequality.com/#?package=rman
380
+ [ci-test-image]: https://github.com/panates/rman/actions/workflows/test.yml/badge.svg
381
+ [ci-test-url]: https://github.com/panates/rman/actions/workflows/test.yml
382
+ [coveralls-image]: https://img.shields.io/coveralls/panates/rman/dev.svg
383
+ [coveralls-url]: https://coveralls.io/r/panates/rman
package/cli.js CHANGED
@@ -1,31 +1,42 @@
1
1
  #!/usr/bin/env node
2
+ import { realpathSync } from 'node:fs';
3
+ import { fileURLToPath } from 'node:url';
2
4
  import colors from 'ansi-colors';
3
5
  import yargs from 'yargs';
4
- import { BuildCommand } from './commands/build-command.js';
5
- import { ChangedCommand } from './commands/changed-command.js';
6
- import { CleanInstallCommand } from './commands/ci-command.js';
7
- import { ExecuteCommand } from './commands/execute-command.js';
8
- import { InfoCommand } from './commands/info-command.js';
9
- import { ListCommand } from './commands/list-command.js';
10
- import { PublishCommand } from './commands/publish-command.js';
11
- import { RunCommand } from './commands/run-command.js';
12
- import { VersionCommand } from './commands/version-command.js';
6
+ import { hideBin } from 'yargs/helpers';
7
+ import * as buildCommand from './commands/build.command.js';
8
+ import * as changedCommand from './commands/changed.command.js';
9
+ import * as changelogCommand from './commands/changelog.command.js';
10
+ import * as ciCommand from './commands/ci.command.js';
11
+ import * as cleanCommand from './commands/clean.command.js';
12
+ import * as diffCommand from './commands/diff.command.js';
13
+ import * as execCommand from './commands/exec.command.js';
14
+ import * as importCommand from './commands/import.command.js';
15
+ import * as infoCommand from './commands/info.command.js';
16
+ import * as listCommand from './commands/list.command.js';
17
+ import * as publishCommand from './commands/publish.command.js';
18
+ import * as runCommand from './commands/run.command.js';
19
+ import * as testCommand from './commands/test.command.js';
20
+ import * as versionCommand from './commands/version.command.js';
13
21
  import { version } from './constants.js';
14
- import { Command } from './core/command.js';
15
22
  import { Repository } from './core/repository.js';
23
+ import { LOG_LEVELS } from './utils/logger.js';
16
24
  export async function runCli(options) {
17
25
  try {
18
26
  const repository = Repository.create(options?.cwd);
19
- const _argv = options?.argv || process.argv.slice(2);
20
- const globalKeys = Object.keys(Command.globalOptions).concat(['help', 'version']);
27
+ const _argv = options?.argv || hideBin(process.argv);
21
28
  const program = yargs(_argv)
22
- // .scriptName('rman')
23
- .strict()
29
+ .scriptName('rman')
24
30
  .version(version)
25
31
  .alias('version', 'v')
26
32
  .usage('$0 <cmd> [options...]')
27
33
  .help('help')
28
34
  .alias('help', 'h')
35
+ .option('log-level', {
36
+ describe: 'Default verbosity of the per-step log for run/build/ci (default: info, or .rmanrc "logLevel"; ' +
37
+ 'overridable per-package via .rmanrc run.<script>.logLevel)',
38
+ choices: LOG_LEVELS,
39
+ })
29
40
  .showHelpOnFail(false, 'Run with --help for available options')
30
41
  .fail((msg, err) => {
31
42
  if (!err?.logged) {
@@ -39,19 +50,22 @@ export async function runCli(options) {
39
50
  }
40
51
  else
41
52
  process.exit(1);
42
- })
43
- // group options under "Global Options:" header
44
- .options(Command.globalOptions)
45
- .group(globalKeys, 'Global Options:');
46
- InfoCommand.initCli(repository, program);
47
- ListCommand.initCli(repository, program);
48
- ChangedCommand.initCli(repository, program);
49
- ExecuteCommand.initCli(repository, program);
50
- RunCommand.initCli(repository, program);
51
- VersionCommand.initCli(repository, program);
52
- PublishCommand.initCli(repository, program);
53
- CleanInstallCommand.initCli(repository, program);
54
- BuildCommand.initCli(repository, program);
53
+ });
54
+ infoCommand.initCli(repository, program);
55
+ listCommand.initCli(repository, program);
56
+ runCommand.initCli(repository, program);
57
+ buildCommand.initCli(repository, program);
58
+ ciCommand.initCli(repository, program);
59
+ cleanCommand.initCli(repository, program);
60
+ changelogCommand.initCli(repository, program);
61
+ testCommand.initCli(repository, program);
62
+ versionCommand.initCli(repository, program);
63
+ publishCommand.initCli(repository, program);
64
+ execCommand.initCli(repository, program);
65
+ changedCommand.initCli(repository, program);
66
+ diffCommand.initCli(repository, program);
67
+ importCommand.initCli(repository, program);
68
+ program.demandCommand(1).strict().completion();
55
69
  if (!_argv.length)
56
70
  program.showHelp();
57
71
  else
@@ -59,7 +73,15 @@ export async function runCli(options) {
59
73
  }
60
74
  catch (e) {
61
75
  console.error(colors.red(e.message));
62
- // logger.error('rman', e.message);
63
76
  }
64
77
  }
65
- runCli().catch(() => 0);
78
+ function isMain() {
79
+ try {
80
+ return !!process.argv[1] && realpathSync(fileURLToPath(import.meta.url)) === realpathSync(process.argv[1]);
81
+ }
82
+ catch {
83
+ return false;
84
+ }
85
+ }
86
+ if (isMain())
87
+ runCli().catch(() => 0);
@@ -0,0 +1,3 @@
1
+ import type { Argv } from 'yargs';
2
+ import type { Repository } from '../core/repository.js';
3
+ export declare function initCli(repository: Repository, program: Argv): void;
@@ -0,0 +1,14 @@
1
+ import { RunService } from '../services/run.service.js';
2
+ import { assertAllowedBranch, readBranchGuardOptions } from '../utils/branch-guard.js';
3
+ import { applyRunOptions, readRunOptions } from './run.command.js';
4
+ export function initCli(repository, program) {
5
+ program.command({
6
+ command: 'build',
7
+ describe: 'Alias for "run build"',
8
+ builder: cmd => applyRunOptions(cmd).example('$0 build', '# Builds packages'),
9
+ handler: async (args) => {
10
+ await assertAllowedBranch(repository, readBranchGuardOptions(args));
11
+ await RunService.runScript(repository, 'build', { ...readRunOptions(args), commandName: 'build' });
12
+ },
13
+ });
14
+ }
@@ -0,0 +1,3 @@
1
+ import type { Argv } from 'yargs';
2
+ import type { Repository } from '../core/repository.js';
3
+ export declare function initCli(repository: Repository, program: Argv): void;
@@ -0,0 +1,29 @@
1
+ import colors from 'ansi-colors';
2
+ import { VersionService } from '../services/version.service.js';
3
+ import { applyPackageFilterOptions, readPackageFilterOptions } from '../utils/package-filter.js';
4
+ export function initCli(repository, program) {
5
+ program.command({
6
+ command: 'changed',
7
+ describe: 'Shows which packages the next "version" run would bump, without changing anything',
8
+ builder: cmd => applyPackageFilterOptions(cmd).example('$0 changed', '').example('$0 changed --json', '').option('json', {
9
+ alias: 'j',
10
+ describe: 'Print output as JSON',
11
+ type: 'boolean',
12
+ }),
13
+ handler: async (args) => {
14
+ const plan = await VersionService.getPlan(repository, readPackageFilterOptions(args));
15
+ const changed = plan.filter(e => e.status === 'bump');
16
+ if (args.json) {
17
+ console.log(JSON.stringify(changed.map(e => ({ name: e.package.name, group: e.group, from: e.from, to: e.to, reason: e.reason })), undefined, 2));
18
+ return;
19
+ }
20
+ if (!changed.length) {
21
+ console.log(colors.gray('Nothing has changed.'));
22
+ return;
23
+ }
24
+ for (const e of changed) {
25
+ console.log(colors.green('changed'), colors.cyan(e.package.name), colors.gray(`(${e.group})`), e.from, '->', colors.yellow(e.to));
26
+ }
27
+ },
28
+ });
29
+ }
@@ -0,0 +1,3 @@
1
+ import type { Argv } from 'yargs';
2
+ import type { Repository } from '../core/repository.js';
3
+ export declare function initCli(repository: Repository, program: Argv): void;
@@ -0,0 +1,63 @@
1
+ import colors from 'ansi-colors';
2
+ import { ChangelogService } from '../services/changelog.service.js';
3
+ import { Logger, resolveRootLogLevel } from '../utils/logger.js';
4
+ import { applyPackageFilterOptions, readPackageFilterOptions } from '../utils/package-filter.js';
5
+ export function initCli(repository, program) {
6
+ program.command({
7
+ command: 'changelog',
8
+ describe: 'Generates a changelog per package from unreleased commits',
9
+ builder: cmd => applyPackageFilterOptions(cmd)
10
+ .example('$0 changelog', "# Auto-detects each package's last published version on npm")
11
+ .example('$0 changelog --from <hash> --write', '# Since a specific commit, written to file')
12
+ .option('from', {
13
+ describe: 'Generate the changelog since this commit/hash, applied the same way to every package. ' +
14
+ 'Default (also "npm" explicitly): auto-detect per package from its published npm version, ' +
15
+ "falling back to not-yet-pushed commits for a package that can't be resolved this way",
16
+ type: 'string',
17
+ })
18
+ .option('write', {
19
+ describe: "Prepend the entry into each package's own changelog file instead of printing it",
20
+ type: 'boolean',
21
+ })
22
+ .option('file-path', {
23
+ describe: "With --write, the file to prepend into, relative to each package's own directory " +
24
+ '(default: "CHANGELOG.md", or .rmanrc "changelog.filePath")',
25
+ type: 'string',
26
+ })
27
+ .option('root', {
28
+ alias: 'r',
29
+ describe: 'Generate for the whole repository even when the current directory is inside a single ' +
30
+ 'package (which otherwise scopes it to just that package). No effect elsewhere.',
31
+ type: 'boolean',
32
+ }),
33
+ handler: async (args) => {
34
+ const from = args.from;
35
+ const write = args.write;
36
+ const logger = new Logger(args.logLevel ?? resolveRootLogLevel(repository));
37
+ if (!from || from === 'npm') {
38
+ // A network round trip per package, even run concurrently, can still take a visible
39
+ // moment - without this, the command looks hung for that stretch instead of just busy.
40
+ logger.info(colors.gray('Checking published npm versions...'));
41
+ }
42
+ const options = {
43
+ ...readPackageFilterOptions(args),
44
+ from,
45
+ filePath: args.filePath,
46
+ root: args.root,
47
+ };
48
+ const entries = args.write
49
+ ? await ChangelogService.generateToFile(repository, options)
50
+ : await ChangelogService.getEntries(repository, options);
51
+ if (!entries.length) {
52
+ logger.info(colors.gray('No unreleased changes.'));
53
+ return;
54
+ }
55
+ for (const entry of entries) {
56
+ if (write)
57
+ logger.info(colors.green('updated'), colors.cyan(entry.label), entry.filePath);
58
+ else
59
+ console.log(entry.content);
60
+ }
61
+ },
62
+ });
63
+ }
@@ -0,0 +1,3 @@
1
+ import type { Argv } from 'yargs';
2
+ import type { Repository } from '../core/repository.js';
3
+ export declare function initCli(repository: Repository, program: Argv): void;