rman 1.0.10 → 1.1.1
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/README.md +116 -85
- package/cli.js +225 -14
- package/commands/build.command.js +1 -0
- package/commands/changed.command.js +2 -2
- package/commands/changelog.command.js +13 -15
- package/commands/config.command.js +60 -0
- package/commands/diff.command.js +9 -4
- package/commands/exec.command.js +2 -8
- package/commands/github-release.command.js +1 -0
- package/commands/info.command.d.ts +9 -0
- package/commands/info.command.js +12 -2
- package/commands/run.command.js +5 -8
- package/commands/test.command.js +1 -0
- package/commands/version.command.js +53 -14
- package/constants.js +1 -1
- package/core/config.d.ts +257 -6
- package/core/config.js +409 -17
- package/core/custom-command.d.ts +133 -0
- package/core/custom-command.js +99 -0
- package/core/extends-config.d.ts +27 -0
- package/core/extends-config.js +89 -0
- package/core/manifest.d.ts +222 -0
- package/core/manifest.js +150 -0
- package/core/merge-config.d.ts +57 -0
- package/core/merge-config.js +146 -0
- package/core/package.d.ts +73 -7
- package/core/package.js +86 -24
- package/core/plugin.d.ts +112 -0
- package/core/plugin.js +189 -0
- package/core/repository.d.ts +85 -4
- package/core/repository.js +258 -81
- package/core/resolve-target.d.ts +12 -0
- package/core/resolve-target.js +33 -0
- package/core/version-scheme.d.ts +134 -0
- package/core/version-scheme.js +148 -0
- package/core/workspace.d.ts +68 -0
- package/core/workspace.js +83 -0
- package/index.d.ts +54 -8
- package/index.js +42 -7
- package/interfaces/rman-config.interface.d.ts +226 -28
- package/package.json +15 -7
- package/services/change-hash.service.d.ts +88 -0
- package/services/change-hash.service.js +112 -0
- package/services/changelog.service.d.ts +8 -13
- package/services/changelog.service.js +12 -11
- package/services/conventional-commits.service.d.ts +73 -0
- package/services/conventional-commits.service.js +116 -0
- package/services/docker-publish.service.js +1 -1
- package/services/exec.service.js +1 -1
- package/services/github-release.service.d.ts +2 -2
- package/services/github-release.service.js +10 -5
- package/services/list.service.js +5 -2
- package/services/run.service.d.ts +68 -3
- package/services/run.service.js +162 -70
- package/services/system-info.d.ts +22 -7
- package/services/system-info.js +8 -23
- package/services/version-plan.service.d.ts +244 -0
- package/services/version-plan.service.js +414 -0
- package/services/version.service.d.ts +92 -82
- package/services/version.service.js +233 -383
- package/services.d.ts +5 -3
- package/services.js +5 -3
- package/utils/bin-path.d.ts +59 -0
- package/utils/bin-path.js +82 -0
- package/utils/child-tracker.d.ts +16 -0
- package/utils/child-tracker.js +30 -0
- package/utils/exec.d.ts +13 -2
- package/utils/exec.js +17 -17
- package/utils/git.d.ts +9 -3
- package/utils/git.js +10 -2
- package/utils/package-filter.d.ts +33 -2
- package/utils/package-filter.js +47 -7
- package/utils/release-version.js +3 -3
- package/utils/run-bin.d.ts +46 -0
- package/utils/run-bin.js +63 -0
- package/utils/version-stamp.d.ts +48 -0
- package/utils/version-stamp.js +88 -0
- package/commands/ci.command.js +0 -30
- package/commands/clean.command.d.ts +0 -3
- package/commands/clean.command.js +0 -36
- package/commands/publish.command.d.ts +0 -3
- package/commands/publish.command.js +0 -225
- package/rmanrc.schema.json +0 -375
- package/services/ci.service.d.ts +0 -40
- package/services/ci.service.js +0 -204
- package/services/clean.service.d.ts +0 -42
- package/services/clean.service.js +0 -226
- package/services/publish.service.d.ts +0 -79
- package/services/publish.service.js +0 -207
- package/utils/change-hash.d.ts +0 -68
- package/utils/change-hash.js +0 -98
- package/utils/conventional-commits.d.ts +0 -52
- package/utils/conventional-commits.js +0 -90
- package/utils/npm-run-path.d.ts +0 -67
- package/utils/npm-run-path.js +0 -63
- package/utils/workspace-range.d.ts +0 -17
- package/utils/workspace-range.js +0 -28
- /package/commands/{ci.command.d.ts → config.command.d.ts} +0 -0
package/core/config.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import path from 'path';
|
|
2
|
+
import semver from 'semver';
|
|
1
3
|
import type { RmanConfig } from '../interfaces/rman-config.interface.js';
|
|
2
4
|
/**
|
|
3
5
|
* Identity helper for authoring a `.rmanrc.cjs`/`.mjs`/`.js` config with full type-checking and
|
|
@@ -21,10 +23,259 @@ export declare function defineConfig(config: RmanConfig): RmanConfig;
|
|
|
21
23
|
*/
|
|
22
24
|
export declare function readDirConfig(dirname: string): Promise<RmanConfig>;
|
|
23
25
|
/**
|
|
24
|
-
* Resolves the effective config for `targetDir
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
26
|
+
* Resolves the effective config for the package at `targetDir`, cascading from `rootDir` down to
|
|
27
|
+
* it (inclusive) - each directory level overrides the ones above it, the way tsconfig's `extends`
|
|
28
|
+
* chain does.
|
|
29
|
+
*
|
|
30
|
+
* Every level contributes in two ways, and the difference is the whole model:
|
|
31
|
+
*
|
|
32
|
+
* - **Unmarked keys configure the package of the directory that declares them.** The root's own
|
|
33
|
+
* `.rmanrc` therefore configures the *root package* - which is where repo-wide settings
|
|
34
|
+
* (`packageManager`, `allowBranch`, `version.*`, `githubRelease.*`) are read from anyway - and
|
|
35
|
+
* not, silently, every package under it.
|
|
36
|
+
* - **A `"[selector]"` block configures the packages it names** - `"[*]"` for all of them (the root
|
|
37
|
+
* included), `"[ws:*]"` for every one but the root, `"[/]"` for the root alone, `"[*-dialect]"`
|
|
38
|
+
* for a glob over package names. See `parseSelector`. This is the only way a directory speaks
|
|
39
|
+
* about anything but its own package.
|
|
40
|
+
*
|
|
41
|
+
* Splitting the two matters because the same key means different things to the two audiences. The
|
|
42
|
+
* clearest case is `run.<script>.postScript`: on a package it's that package's build hook, run in
|
|
43
|
+
* its own directory; on the root it's a repo-wide bookend run once at the repository root. A
|
|
44
|
+
* cascade that fed one declaration to both ran a package-relative command (`node
|
|
45
|
+
* ../../support/postbuild.cjs`) at the root, where it cannot resolve.
|
|
46
|
+
*
|
|
47
|
+
* `packageName` is what selectors match against; without it, selector blocks contribute nothing at
|
|
48
|
+
* all. The root package passes its own, since `"[/]"` and `"[*]"` speak to it.
|
|
49
|
+
*/
|
|
50
|
+
export declare function resolveConfig(rootDir: string, targetDir: string, cache?: Map<string, RmanConfig>, packageName?: string): Promise<RmanConfig>;
|
|
51
|
+
/** A config key naming packages rather than settings: `"[*]"`, `"[/]"`, `"[ws:*]"`, `"[pkg-a]"`. The
|
|
52
|
+
* brackets are what keep this space from colliding with real config keys - no setting starts with
|
|
53
|
+
* one - and in YAML they also mean the key always needs quoting (`"[*]":`), since a bare `[*]`
|
|
54
|
+
* parses as a flow sequence. */
|
|
55
|
+
export declare function isSelectorKey(key: string): boolean;
|
|
56
|
+
/**
|
|
57
|
+
* **Which packages a selector speaks for.** Three audiences, because a repository has three:
|
|
58
|
+
*
|
|
59
|
+
* | | |
|
|
60
|
+
* | --- | --- |
|
|
61
|
+
* | `"[/]"` | the **root package** only |
|
|
62
|
+
* | `"[*]"`, `"[pkg-a]"`, `"[*-dialect]"` | **every** package the glob matches, root included |
|
|
63
|
+
* | `"[ws:*]"`, `"[workspace:pkg-*]"` | every **non-root** package the glob matches |
|
|
64
|
+
*
|
|
65
|
+
* `/` for the root because that is what a repository root is called everywhere else, and it cannot
|
|
66
|
+
* collide with a package name. `ws:` is a qualifier on the glob rather than a separate spelling of
|
|
67
|
+
* `*`, so `"[ws:pkg-*]"` means what it looks like.
|
|
68
|
+
*
|
|
69
|
+
* **`"[*]"` includes the root, and that is a change from how it used to read.** Before, selectors
|
|
70
|
+
* were not applied to the root at all, so `"[*]"` silently meant "the workspace packages" - a
|
|
71
|
+
* catch-all with an exception nothing in the syntax mentioned. The three names above say which
|
|
72
|
+
* audience is meant; `"[ws:*]"` is the old behaviour, now spelled.
|
|
73
|
+
*/
|
|
74
|
+
export declare function parseSelector(key: string): {
|
|
75
|
+
scope: 'root' | 'all' | 'workspace';
|
|
76
|
+
test: (name: string) => boolean;
|
|
77
|
+
};
|
|
78
|
+
/** The glob inside a selector key, as a `RegExp` anchored at both ends - so `"[*-dialect]"` matches
|
|
79
|
+
* `mysql-dialect` but not `my-dialect-helper`. Glob rather than regex, to match every other
|
|
80
|
+
* pattern in rman (`allowBranch`, `changelog.tagPattern`, `clean.include`). */
|
|
81
|
+
export declare function selectorToRegExp(key: string): RegExp;
|
|
82
|
+
/** One package, as an expression sees it - the same shape for the package the config belongs to
|
|
83
|
+
* and for the repository itself, so `${{ repository.basename }}` reads the way `${{ pkg.basename }}` does. */
|
|
84
|
+
/**
|
|
85
|
+
* `file` in a `${{ ... }}` expression: what is actually on disk, resolved against **the package
|
|
86
|
+
* the config was resolved for** - so one declaration in a `"[*]"` block asks each package about
|
|
87
|
+
* its own directory.
|
|
88
|
+
*
|
|
89
|
+
* The pair exists because a config has two different questions about a path, and answering both
|
|
90
|
+
* with one function would mean picking a wrong default for the other:
|
|
91
|
+
*
|
|
92
|
+
* ```yaml
|
|
93
|
+
* "[*]":
|
|
94
|
+
* run:
|
|
95
|
+
* build:
|
|
96
|
+
* # first of these that exists, and an error naming the config path if none do
|
|
97
|
+
* exec: 'tsc -b ${{ file.exists("tsconfig-build.json") || file.resolve("tsconfig.json") }}'
|
|
98
|
+
* ```
|
|
99
|
+
*/
|
|
100
|
+
export interface FileScope {
|
|
101
|
+
/**
|
|
102
|
+
* The absolute path if it exists, **`''` if it does not** - so `a || b || c` picks the first one
|
|
103
|
+
* present, and so a miss never reaches the "nullish inside a string" guard that `undefined` would
|
|
104
|
+
* trip. Accepts a relative path (against the package directory) or an absolute one.
|
|
105
|
+
*
|
|
106
|
+
* It returns a path rather than a boolean on purpose: the caller almost always wants the path,
|
|
107
|
+
* and a separate `file.path()` to fetch it after a boolean test would read the disk twice and
|
|
108
|
+
* invite the two calls to disagree.
|
|
109
|
+
*/
|
|
110
|
+
exists(target: string): string;
|
|
111
|
+
/** The absolute path, or **throws** - for a file whose absence is a mistake rather than a case to
|
|
112
|
+
* handle. The error names the config path holding the expression, like any other. */
|
|
113
|
+
resolve(target: string): string;
|
|
114
|
+
/**
|
|
115
|
+
* The first of several that exists, or **throws** naming every candidate it tried:
|
|
116
|
+
*
|
|
117
|
+
* ```yaml
|
|
118
|
+
* exec: 'tsc -b ${{ file.resolveFirst("tsconfig-build.json", "tsconfig.build.json", "tsconfig.json") }}'
|
|
119
|
+
* ```
|
|
120
|
+
*
|
|
121
|
+
* The same thing an `exists() || exists() || resolve()` chain does, said once - and it cannot be
|
|
122
|
+
* got subtly wrong the way that chain can: ending it in `exists()` leaves `tsc -b ` with no
|
|
123
|
+
* argument when nothing matches, and tsc then silently falls back to the directory's default
|
|
124
|
+
* rather than reporting that the package has no build config.
|
|
125
|
+
*/
|
|
126
|
+
resolveFirst(...targets: string[]): string;
|
|
127
|
+
}
|
|
128
|
+
export interface PackageScope {
|
|
129
|
+
/** The package's own name, scope included (`@sqb/builder`). */
|
|
130
|
+
name: string;
|
|
131
|
+
/** Just the scope (`@sqb`), or `undefined` for an unscoped package. */
|
|
132
|
+
scope: string | undefined;
|
|
133
|
+
/** The name with its scope stripped (`builder`). */
|
|
134
|
+
unscopedName: string;
|
|
135
|
+
version: string;
|
|
136
|
+
/** The package directory's last segment (`builder`) - not always the same as `unscopedName`,
|
|
137
|
+
* which is why both exist, and usually what a sibling path (`../../coverage/builder`) is keyed on. */
|
|
138
|
+
basename: string;
|
|
139
|
+
/** Absolute path to the package's own directory - named as rman's own `Package.dirname` is. */
|
|
140
|
+
dirname: string;
|
|
141
|
+
/** That directory relative to the repository root (`packages/builder`), which is what a command
|
|
142
|
+
* addressing another package from the root usually needs. Empty string for the root itself. */
|
|
143
|
+
relativeDir: string;
|
|
144
|
+
/**
|
|
145
|
+
* Which ecosystem this package belongs to - `'node'` for one read by `rman-node`, empty when no
|
|
146
|
+
* plugin claimed it. The same `Package.provider`, so one declaration can address a single
|
|
147
|
+
* ecosystem in a polyglot repository (`if: "${{ pkg.provider === 'node' }}"`).
|
|
148
|
+
*/
|
|
149
|
+
provider: string;
|
|
150
|
+
/**
|
|
151
|
+
* The whole manifest, as a copy - so an expression can reach a field rman itself has no opinion
|
|
152
|
+
* about (`${{ pkg.manifest.engines.node }}`).
|
|
153
|
+
*
|
|
154
|
+
* Named `manifest`, not `json`: which file a package's identity lives in is the ecosystem's
|
|
155
|
+
* business now (see `ManifestProvider`), and `json` was that assumption showing through the one
|
|
156
|
+
* remaining user-facing name. A config written against `${{ pkg.json... }}` needs the rename.
|
|
157
|
+
*/
|
|
158
|
+
manifest: Record<string, unknown>;
|
|
159
|
+
/**
|
|
160
|
+
* The version this run is about to write - **bound only during `version`**, and only once its
|
|
161
|
+
* plan is computed. Reading it anywhere else throws rather than yielding `undefined`: no other
|
|
162
|
+
* command has a target version, so an expression asking for one has been put in the wrong place,
|
|
163
|
+
* and a config that quietly evaluates to "undefined" is the failure this evaluator exists to
|
|
164
|
+
* prevent.
|
|
165
|
+
*/
|
|
166
|
+
targetVersion: string;
|
|
167
|
+
}
|
|
168
|
+
/** Facts about the repository, on top of the root package's own - because the repository root *is*
|
|
169
|
+
* a package (`repository.name` is what its `package.json` says, `repository.basename` the directory
|
|
170
|
+
* it sits in, and the two genuinely differ). Sharing `PackageScope`'s shape is what makes
|
|
171
|
+
* `repository.version` read the way `pkg.version` does. */
|
|
172
|
+
export interface RepositoryScope extends PackageScope {
|
|
173
|
+
monorepo: boolean;
|
|
174
|
+
/** Every package in the repository - the root included only when it *is* the one package. */
|
|
175
|
+
packages: PackageScope[];
|
|
176
|
+
/** One package by name, or `undefined` - for reaching a sibling's directory. */
|
|
177
|
+
package(name: string): PackageScope | undefined;
|
|
178
|
+
/** Read from git only if an expression actually asks for it, then remembered: a repository that
|
|
179
|
+
* never mentions these pays nothing, and every command resolves config. All `undefined` outside
|
|
180
|
+
* a git checkout, which is a legitimate state rather than an error. */
|
|
181
|
+
git: GitScope;
|
|
182
|
+
}
|
|
183
|
+
export interface GitScope {
|
|
184
|
+
branch: string | undefined;
|
|
185
|
+
sha: string | undefined;
|
|
186
|
+
shortSha: string | undefined;
|
|
187
|
+
/** Whether the working tree has uncommitted changes. */
|
|
188
|
+
dirty: boolean | undefined;
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* What a `${{ ... }}` expression can see - the bindings of the fresh global it is evaluated in.
|
|
192
|
+
* Namespaced rather than a flat bag of loose names: one obvious place per fact, and room to add
|
|
193
|
+
* helpers to `pkg`/`repository` later without crowding the global.
|
|
194
|
+
*
|
|
195
|
+
* Alongside these, **the config's own top-level keys are bound bare** (`${{ publish.directory }}`,
|
|
196
|
+
* `${{ clean.include }}`) - see `interpolateConfig`. They are not listed here because they come
|
|
197
|
+
* from the config being interpolated, not from this object; a name here wins over a config key of
|
|
198
|
+
* the same name.
|
|
199
|
+
*
|
|
200
|
+
* **Trap: bare `${{ version }}` is the `version` *options block*, not the package's version
|
|
201
|
+
* string** - that is `${{ pkg.version }}`. Same word, two different things, and the plain one
|
|
202
|
+
* belongs to the config because every other config key is reachable that way.
|
|
203
|
+
*/
|
|
204
|
+
export interface ConfigScope {
|
|
205
|
+
/** The package the config was resolved for - which is what lets one declaration at the root
|
|
206
|
+
* still say something package-specific. */
|
|
207
|
+
pkg: PackageScope;
|
|
208
|
+
repository: RepositoryScope;
|
|
209
|
+
/** Paths, resolved against the package the config was resolved for. */
|
|
210
|
+
file: FileScope;
|
|
211
|
+
env: Record<string, string | undefined>;
|
|
212
|
+
/** rman's own `semver`, for the arithmetic every release config eventually wants
|
|
213
|
+
* (`semver.major(pkg.version)`). */
|
|
214
|
+
semver: typeof semver;
|
|
215
|
+
/**
|
|
216
|
+
* Node's own `node:path` - `${{ path.join(pkg.dirname, 'LICENSE') }}`, rather than gluing
|
|
217
|
+
* strings with `+ "/" +` and getting a double separator or none.
|
|
218
|
+
*
|
|
219
|
+
* The platform's flavour, not `path.posix`, so a joined path is the one the shell on *this*
|
|
220
|
+
* machine understands; `path.posix` and `path.win32` are reachable through it when a config
|
|
221
|
+
* genuinely needs one of them (a Docker image path, say, which is always posix).
|
|
222
|
+
*/
|
|
223
|
+
path: typeof path;
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Evaluates every `${{ ... }}` expression in **every** string value of a resolved config, against
|
|
227
|
+
* the package it was resolved for:
|
|
228
|
+
*
|
|
229
|
+
* ```yaml
|
|
230
|
+
* "[*]":
|
|
231
|
+
* clean:
|
|
232
|
+
* include: ["build", "../../coverage/${{ pkg.basename }}"]
|
|
233
|
+
* publish:
|
|
234
|
+
* directory: build
|
|
235
|
+
* docker:
|
|
236
|
+
* image: "panates/${{ pkg.basename }}:${{ semver.major(pkg.version) }}"
|
|
237
|
+
* run:
|
|
238
|
+
* build:
|
|
239
|
+
* # the config's own keys are in scope, so this is not a second copy of "build"
|
|
240
|
+
* after: "cp README.md ${{ publish.directory }}/"
|
|
241
|
+
* ```
|
|
242
|
+
*
|
|
243
|
+
* Every string, with no list of "interpolated keys" to memorize - a rule with exceptions is a rule
|
|
244
|
+
* nobody remembers.
|
|
245
|
+
*
|
|
246
|
+
* The contents are **real JavaScript**, not a template mini-language, so there is no growing list
|
|
247
|
+
* of substitutions to keep adding (`{{major}}`, `{{scope}}`, ...) - see `ConfigScope` for what is
|
|
248
|
+
* in scope.
|
|
249
|
+
*
|
|
250
|
+
* **`${{ }}`, deliberately not `{{ }}`.** A config value may legitimately carry `{{...}}` meant for
|
|
251
|
+
* something else entirely (`helm template --set tag={{.Values.tag}}`); with the plainer delimiter
|
|
252
|
+
* rman would try to evaluate it. To emit a literal, let an expression produce it, the way GitHub
|
|
253
|
+
* Actions does: `${{ '${{' }}`.
|
|
254
|
+
*
|
|
255
|
+
* A string that is *nothing but* one expression keeps the value's own type (`"${{ pkg.private }}"`
|
|
256
|
+
* -> a boolean), since otherwise this could only ever produce strings and settings like
|
|
257
|
+
* `run.<script>.skip` would be unreachable. Embedded in surrounding text it is stringified.
|
|
258
|
+
*
|
|
259
|
+
* Evaluation happens in a fresh V8 context holding only the scope's bindings. That is a clean
|
|
260
|
+
* scope, **not a sandbox** - `node:vm` is explicitly not a security mechanism, and no sandbox is
|
|
261
|
+
* called for here anyway: a `.rmanrc` that can say `exec: "..."` already runs arbitrary shell, so
|
|
262
|
+
* the expression evaluator adds no trust boundary that wasn't already wide open.
|
|
263
|
+
*
|
|
264
|
+
* A failing expression throws with the config path that holds it, rather than being left in place:
|
|
265
|
+
* silently passing through a mistake is how a config ends up quietly doing nothing.
|
|
266
|
+
*/
|
|
267
|
+
export declare function interpolateConfig<T>(config: T, scope: ConfigScope, options?: {
|
|
268
|
+
skip?: string[];
|
|
269
|
+
}): T;
|
|
270
|
+
/**
|
|
271
|
+
* Config paths left untouched when a repository's config is first resolved, and evaluated only by
|
|
272
|
+
* the command that runs them.
|
|
273
|
+
*
|
|
274
|
+
* `version`'s own hooks are the one place `${{ pkg.targetVersion }}` makes sense, and the version
|
|
275
|
+
* being written is not known until `version` has computed its plan - long after the config was
|
|
276
|
+
* resolved. Evaluating these eagerly would throw while merely *loading* the repository, so any
|
|
277
|
+
* command at all would fail on a config that mentions it.
|
|
29
278
|
*/
|
|
30
|
-
export declare
|
|
279
|
+
export declare const DEFERRED_PATHS: string[];
|
|
280
|
+
/** The `file` namespace for one package's directory - see `FileScope`. */
|
|
281
|
+
export declare function createFileScope(dirname: string): FileScope;
|