rman 1.3.0 → 2.0.0-beta.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.
- package/README.md +63 -19
- package/cli.d.ts +5 -0
- package/cli.js +214 -88
- package/commands/build.command.d.ts +177 -3
- package/commands/build.command.js +20 -10
- package/commands/changed.command.d.ts +80 -3
- package/commands/changed.command.js +19 -12
- package/commands/changelog.command.d.ts +192 -3
- package/commands/changelog.command.js +87 -43
- package/commands/config.command.d.ts +44 -3
- package/commands/config.command.js +30 -19
- package/commands/diff.command.d.ts +37 -3
- package/commands/diff.command.js +25 -16
- package/commands/exec.command.d.ts +193 -3
- package/commands/exec.command.js +60 -58
- package/commands/github-release.command.d.ts +154 -3
- package/commands/github-release.command.js +67 -37
- package/commands/import.command.d.ts +36 -3
- package/commands/import.command.js +28 -20
- package/commands/info.command.d.ts +35 -7
- package/commands/info.command.js +36 -30
- package/commands/list.command.d.ts +163 -3
- package/commands/list.command.js +109 -71
- package/commands/publish.command.d.ts +231 -0
- package/commands/publish.command.js +304 -0
- package/commands/run.command.d.ts +186 -6
- package/commands/run.command.js +26 -72
- package/commands/test.command.d.ts +173 -3
- package/commands/test.command.js +16 -10
- package/commands/version.command.d.ts +317 -3
- package/commands/version.command.js +149 -69
- package/commands.d.ts +32 -0
- package/commands.js +28 -0
- package/constants.js +1 -1
- package/core/application.d.ts +116 -0
- package/core/application.js +143 -0
- package/core/command-builder.d.ts +14 -0
- package/core/command-builder.js +78 -0
- package/core/config.d.ts +140 -19
- package/core/config.js +258 -74
- package/core/core-services.d.ts +14 -0
- package/core/core-services.js +30 -0
- package/core/core-targets.d.ts +14 -0
- package/core/core-targets.js +16 -0
- package/core/custom-command.d.ts +42 -6
- package/core/custom-command.js +44 -17
- package/core/extends-config.d.ts +13 -5
- package/core/extends-config.js +52 -12
- package/core/load-config-module.d.ts +28 -0
- package/core/load-config-module.js +42 -0
- package/core/manifest.d.ts +47 -25
- package/core/manifest.js +51 -69
- package/core/merge-config.d.ts +33 -34
- package/core/merge-config.js +137 -92
- package/core/package.d.ts +145 -17
- package/core/package.js +128 -36
- package/core/plugin-loader.d.ts +65 -0
- package/core/plugin-loader.js +234 -0
- package/core/plugin.d.ts +135 -90
- package/core/plugin.js +70 -173
- package/core/publish-target.d.ts +124 -0
- package/core/publish-target.js +30 -0
- package/core/registry.d.ts +30 -0
- package/core/registry.js +47 -0
- package/core/repository.d.ts +72 -9
- package/core/repository.js +293 -44
- package/core/resolve-target.d.ts +1 -1
- package/core/resolve-target.js +1 -1
- package/core/service.d.ts +49 -0
- package/core/service.js +40 -0
- package/core/version-scheme.d.ts +23 -1
- package/core/version-scheme.js +29 -1
- package/core/workspace.d.ts +84 -33
- package/core/workspace.js +63 -22
- package/index.d.ts +111 -14
- package/index.js +85 -9
- package/interfaces/rman-config.interface.d.ts +725 -202
- package/interfaces/rman-config.interface.js +61 -1
- package/package.json +2 -1
- package/plugins/builtins.d.ts +44 -0
- package/plugins/builtins.js +33 -0
- package/plugins/detect.d.ts +78 -0
- package/plugins/detect.js +70 -0
- package/plugins/node/augmentation/rman.augmentation.d.ts +84 -0
- package/plugins/node/augmentation/rman.augmentation.js +1 -0
- package/plugins/node/augmentation/system-info.augmentation.d.ts +26 -0
- package/plugins/node/augmentation/system-info.augmentation.js +79 -0
- package/plugins/node/commands/ci.command.d.ts +131 -0
- package/plugins/node/commands/ci.command.js +59 -0
- package/plugins/node/commands/clean.command.d.ts +183 -0
- package/plugins/node/commands/clean.command.js +73 -0
- package/plugins/node/index.d.ts +29 -0
- package/plugins/node/index.js +40 -0
- package/plugins/node/node-config.interface.d.ts +77 -0
- package/plugins/node/node-config.interface.js +7 -0
- package/plugins/node/node-manifest.provider.d.ts +68 -0
- package/plugins/node/node-manifest.provider.js +125 -0
- package/plugins/node/node.platform.d.ts +53 -0
- package/plugins/node/node.platform.js +134 -0
- package/plugins/node/npm-publish-target.d.ts +73 -0
- package/plugins/node/npm-publish-target.js +96 -0
- package/plugins/node/services/ci.service.d.ts +47 -0
- package/plugins/node/services/ci.service.js +213 -0
- package/plugins/node/services/clean.service.d.ts +53 -0
- package/plugins/node/services/clean.service.js +237 -0
- package/plugins/node/services/publish.service.d.ts +114 -0
- package/plugins/node/services/publish.service.js +371 -0
- package/plugins/node/services/version-plan.service.d.ts +44 -0
- package/plugins/node/services/version-plan.service.js +58 -0
- package/plugins/node/utils/npm-view.d.ts +48 -0
- package/plugins/node/utils/npm-view.js +71 -0
- package/plugins/node/utils/workspace-range.d.ts +26 -0
- package/plugins/node/utils/workspace-range.js +28 -0
- package/services/change-hash.service.d.ts +2 -2
- package/services/change-hash.service.js +2 -2
- package/services/changelog.service.d.ts +62 -51
- package/services/changelog.service.js +14 -11
- package/services/docker-publish.service.d.ts +50 -29
- package/services/docker-publish.service.js +43 -20
- package/services/exec.service.d.ts +23 -12
- package/services/exec.service.js +14 -9
- package/services/github-release.service.d.ts +44 -33
- package/services/github-release.service.js +13 -10
- package/services/import.service.d.ts +25 -14
- package/services/import.service.js +9 -5
- package/services/list.service.d.ts +62 -10
- package/services/list.service.js +62 -15
- package/services/run.service.d.ts +22 -13
- package/services/run.service.js +262 -223
- package/services/version-plan.service.d.ts +27 -4
- package/services/version-plan.service.js +42 -15
- package/services/version.service.d.ts +31 -11
- package/services/version.service.js +29 -13
- package/targets/docker.target.d.ts +53 -0
- package/targets/docker.target.js +40 -0
- package/utils/bin-path.d.ts +6 -7
- package/utils/bin-path.js +7 -18
- package/utils/branch-guard.d.ts +29 -0
- package/utils/branch-guard.js +31 -0
- package/utils/exec.d.ts +10 -0
- package/utils/exec.js +1 -1
- package/utils/logger.d.ts +1 -1
- package/utils/logger.js +1 -1
- package/utils/package-filter.d.ts +127 -7
- package/utils/package-filter.js +197 -16
- package/utils/printable-config.d.ts +1 -1
- package/utils/printable-config.js +1 -1
- package/utils/run-bin.d.ts +10 -0
- package/utils/run-bin.js +1 -1
- package/utils/run-options.d.ts +97 -0
- package/utils/run-options.js +81 -0
- package/utils/version-stamp.d.ts +1 -1
- package/utils/version-stamp.js +1 -1
|
@@ -6,10 +6,29 @@ import type { Package } from '../core/package.js';
|
|
|
6
6
|
* `.rmanrc "skip"`, is applied by `filterPackages` itself rather than being an option here: it is
|
|
7
7
|
* the repository's statement, not the caller's. */
|
|
8
8
|
export interface PackageFilterOptions {
|
|
9
|
-
/** Only include packages whose name matches at least one of these globs (e.g. `@scope/*`)
|
|
9
|
+
/** Only include packages whose name matches at least one of these globs (e.g. `@scope/*`), or
|
|
10
|
+
* **`"/"`** for the repository's own root package - see `ROOT_SELECTOR`. */
|
|
10
11
|
scope?: string | string[];
|
|
11
|
-
/** Exclude packages whose name matches at least one of these globs - applied after
|
|
12
|
+
/** Exclude packages whose name matches at least one of these globs (or `"/"`) - applied after
|
|
13
|
+
* `scope`. */
|
|
12
14
|
ignore?: string | string[];
|
|
15
|
+
/**
|
|
16
|
+
* Only include packages belonging to one of these **platforms** (`Package.provider`) - `['node']`,
|
|
17
|
+
* or `'node,cargo'` as one comma-separated value.
|
|
18
|
+
*
|
|
19
|
+
* **Which technology a package belongs to only became a per-package question when the walk
|
|
20
|
+
* started finding nested packages of another platform**, and this is the filter that question
|
|
21
|
+
* needs: in a polyglot repository `rman run build --platform node` is the whole npm half of it,
|
|
22
|
+
* and there was no way to say that. Where every package is one technology it selects everything
|
|
23
|
+
* or nothing, which is the honest answer rather than a flag that does nothing.
|
|
24
|
+
*
|
|
25
|
+
* **Names, not globs.** A platform's name is a short identifier a plugin chose (`'node'`), so the
|
|
26
|
+
* set of valid values is known and finite - which is also why a name that no package in the
|
|
27
|
+
* repository belongs to is an **error** listing the ones that are there, the same call
|
|
28
|
+
* `publish --target` makes. A glob would put this back to guessing, and a typo back to a silent
|
|
29
|
+
* empty result.
|
|
30
|
+
*/
|
|
31
|
+
platform?: string | string[];
|
|
13
32
|
/** Also include every package the matched set depends on (transitively) - e.g. to build
|
|
14
33
|
* everything a scoped app actually needs. */
|
|
15
34
|
deps?: boolean;
|
|
@@ -17,6 +36,99 @@ export interface PackageFilterOptions {
|
|
|
17
36
|
* everything that could be affected by a scoped library's change. */
|
|
18
37
|
dependents?: boolean;
|
|
19
38
|
}
|
|
39
|
+
/**
|
|
40
|
+
* **`--scope /` is the repository's own root package**, the one selector that is not a glob.
|
|
41
|
+
*
|
|
42
|
+
* The same `/` `.rmanrc`'s `"[/]"` block uses, and for the same reason stated there: *the root is
|
|
43
|
+
* never selected by name.* A glob matches package names, and a name can be anything - so
|
|
44
|
+
* `--scope rman-repo` happened to work (measured) while being exactly the name-based addressing the
|
|
45
|
+
* config selectors were redesigned to remove. `/` is structural, cannot collide with a package
|
|
46
|
+
* (nothing can be named it), and gives "the root" one spelling across config and CLI.
|
|
47
|
+
*
|
|
48
|
+
* Accepted by `--ignore` too. The asymmetry would be the thing to remember, and `--ignore /` -
|
|
49
|
+
* every package but the root - is a real thing to want of `clean`.
|
|
50
|
+
*
|
|
51
|
+
* **It selects nothing on a command whose candidates exclude the root**, which is most of them:
|
|
52
|
+
* `repository.packages` holds the workspace members only, so `rman list --scope /` and
|
|
53
|
+
* `rman run build --scope /` match nothing and say so. That is the honest answer rather than a
|
|
54
|
+
* special case - the root has no `list` row and contributes only `pre`/`post` bookends to `run`.
|
|
55
|
+
* `clean` and `changelog`, which put the root in their candidate list on purpose, are where it bites.
|
|
56
|
+
*/
|
|
57
|
+
export declare const ROOT_SELECTOR = "/";
|
|
58
|
+
/**
|
|
59
|
+
* `--scope`/`--ignore`/`--deps`/`--dependents` as a **declaration** rather than a builder call -
|
|
60
|
+
* spread into a command's `config` block:
|
|
61
|
+
*
|
|
62
|
+
* ```ts
|
|
63
|
+
* config: { ...packageFilterOptions, ...branchGuardOptions, changelog: { ... } }
|
|
64
|
+
* ```
|
|
65
|
+
*
|
|
66
|
+
* **`satisfies`, never a `: Record<...>` annotation.** An annotation widens `type: 'string'` back to
|
|
67
|
+
* `string`, and every type derived from the declaration - the config contribution, the option's own
|
|
68
|
+
* value type - collapses with it. `satisfies` checks the shape and keeps the literals, and it also
|
|
69
|
+
* catches a misspelled key *here*, at the group's own line, rather than in the ten commands that
|
|
70
|
+
* spread it. The `Argv` chaining this replaces could not: a typo there was simply a new option.
|
|
71
|
+
*
|
|
72
|
+
* **Every option is `target: 'cli'`, including the ones that have a config twin.** A shared group
|
|
73
|
+
* belongs to no command, so declaring one `'both'` would contribute `version.scope` - a key nothing
|
|
74
|
+
* reads. Where a `.rmanrc` equivalent exists it is a core key in its own right (`allowBranch`), and
|
|
75
|
+
* a command that reads it names it in `configKeys`.
|
|
76
|
+
*/
|
|
77
|
+
export declare const packageFilterOptions: {
|
|
78
|
+
scope: {
|
|
79
|
+
target: "cli";
|
|
80
|
+
describe: string;
|
|
81
|
+
type: "string";
|
|
82
|
+
};
|
|
83
|
+
ignore: {
|
|
84
|
+
target: "cli";
|
|
85
|
+
describe: string;
|
|
86
|
+
type: "string";
|
|
87
|
+
};
|
|
88
|
+
platform: {
|
|
89
|
+
target: "cli";
|
|
90
|
+
describe: string;
|
|
91
|
+
type: "string";
|
|
92
|
+
};
|
|
93
|
+
deps: {
|
|
94
|
+
target: "cli";
|
|
95
|
+
describe: string;
|
|
96
|
+
type: "boolean";
|
|
97
|
+
};
|
|
98
|
+
dependents: {
|
|
99
|
+
target: "cli";
|
|
100
|
+
describe: string;
|
|
101
|
+
type: "boolean";
|
|
102
|
+
};
|
|
103
|
+
};
|
|
104
|
+
/**
|
|
105
|
+
* `--from-root`/`-r` - a group of one, and a function because its text is the command's own word
|
|
106
|
+
* for what it does. Spread it like the others: `...fromRootOption('Build')`.
|
|
107
|
+
*
|
|
108
|
+
* Only where a command scopes by the current directory; see `applyFromRootOption` for why adding it
|
|
109
|
+
* elsewhere is worse than leaving it out.
|
|
110
|
+
*
|
|
111
|
+
* **It was `--root` through 1.x, and the name said the opposite of what it does.** Every reader
|
|
112
|
+
* spells it the same single line - `options.fromRoot ? undefined : repository.currentPackage` - so
|
|
113
|
+
* the flag means *ignore where I am standing*, i.e. the **whole repository**. `--root` reads as "the
|
|
114
|
+
* root alone", which is the narrowest possible set rather than the widest, and the confusion was
|
|
115
|
+
* about to become a contradiction: a `--root-only` beside a `--root` that meant "everything" is
|
|
116
|
+
* unreadable.
|
|
117
|
+
*
|
|
118
|
+
* **`-r` is kept, and a two-letter `-fr` is not possible.** yargs' `short-option-groups` is on by
|
|
119
|
+
* default, so `-fr` parses as `-f -r` and `.strict()` answers `Unknown arguments: f, r` (measured).
|
|
120
|
+
* Turning that off makes `-fr` work and breaks every grouped short - `rman list -sj` works today.
|
|
121
|
+
* So the long name carries the meaning and the incumbent short stays.
|
|
122
|
+
*/
|
|
123
|
+
export declare function fromRootOption(verb: string): {
|
|
124
|
+
fromRoot: {
|
|
125
|
+
target: "cli";
|
|
126
|
+
cliName: string;
|
|
127
|
+
alias: string;
|
|
128
|
+
describe: string;
|
|
129
|
+
type: "boolean";
|
|
130
|
+
};
|
|
131
|
+
};
|
|
20
132
|
/** `--scope`/`--ignore`/`--deps`/`--dependents`, the same shape and describe text in every command
|
|
21
133
|
* that supports them - mirrors `run.command.ts`'s own `applyRunOptions`. */
|
|
22
134
|
export declare function applyPackageFilterOptions<T>(cmd: Argv<T>): Argv<T>;
|
|
@@ -24,7 +136,8 @@ export declare function readPackageFilterOptions(args: any): PackageFilterOption
|
|
|
24
136
|
/**
|
|
25
137
|
* Narrows `packages` (the full, already-resolved list - toposort order, if any, is preserved)
|
|
26
138
|
* down to what `options` selects. `scope`/`ignore` match against each package's bare name (glob
|
|
27
|
-
* syntax via `micromatch` - `*`, `**`, `{a,b}`, ...)
|
|
139
|
+
* syntax via `micromatch` - `*`, `**`, `{a,b}`, ...), plus `ROOT_SELECTOR` (`"/"`) for the root
|
|
140
|
+
* package, which is matched structurally rather than by name; `ignore` is applied after `scope`, on
|
|
28
141
|
* whatever it left. `deps`/`dependents` then each independently expand *that* matched set along
|
|
29
142
|
* `Package.dependencies` (already the full transitive closure - see
|
|
30
143
|
* `Repository`'s own `_updateDependencies`) and their results are unioned in - so `--deps
|
|
@@ -46,7 +159,7 @@ export declare function filterPackages(packages: Package[], options: PackageFilt
|
|
|
46
159
|
*/
|
|
47
160
|
applySkip?: boolean): Package[];
|
|
48
161
|
/**
|
|
49
|
-
* `--root`/`-r`, with one describe text instead of four near-identical ones.
|
|
162
|
+
* `--from-root`/`-r`, with one describe text instead of four near-identical ones.
|
|
50
163
|
*
|
|
51
164
|
* **It only means anything where a command scopes by the current directory** - `run`/`build`/`test`,
|
|
52
165
|
* `exec`, `clean`, `changelog` and `diff` narrow to `Repository.currentPackage` when you stand
|
|
@@ -54,10 +167,17 @@ applySkip?: boolean): Package[];
|
|
|
54
167
|
* repository (`version`, `publish`, `list`, `changed`) it would be a flag that does nothing, which
|
|
55
168
|
* is worse than not offering it: a no-op flag reads as a promise.
|
|
56
169
|
*
|
|
170
|
+
* That same rule is why there is no `--root-only` beside it, however naturally the pair reads: it
|
|
171
|
+
* would be a no-op on `run`/`build`/`test` (the root is not in `repository.packages` at all and
|
|
172
|
+
* contributes only `pre`/`post` bookends), identical to this flag on `diff`, already what this flag
|
|
173
|
+
* does on `config`, and on `clean` actively misleading - the root's own sweep recurses through
|
|
174
|
+
* `packages/*`, so a `--root-only` there deletes *more* than a package-scoped run, not less
|
|
175
|
+
* (measured). Where the root genuinely is a candidate, `--scope /` says so - see `ROOT_SELECTOR`.
|
|
176
|
+
*
|
|
57
177
|
* `verb` is the command's own word for what it does, so the text stays the sentence each command was
|
|
58
178
|
* already saying.
|
|
59
179
|
*/
|
|
60
|
-
export declare function
|
|
61
|
-
/** The `--root` flag as the services read it - beside `readPackageFilterOptions`, so a command
|
|
180
|
+
export declare function applyFromRootOption<T>(cmd: Argv<T>, verb: string): Argv<T>;
|
|
181
|
+
/** The `--from-root` flag as the services read it - beside `readPackageFilterOptions`, so a command
|
|
62
182
|
* reads both the same way. */
|
|
63
|
-
export declare function
|
|
183
|
+
export declare function readFromRootOption(args: any): boolean | undefined;
|
package/utils/package-filter.js
CHANGED
|
@@ -1,17 +1,120 @@
|
|
|
1
1
|
import micromatch from 'micromatch';
|
|
2
|
+
/**
|
|
3
|
+
* **`--scope /` is the repository's own root package**, the one selector that is not a glob.
|
|
4
|
+
*
|
|
5
|
+
* The same `/` `.rmanrc`'s `"[/]"` block uses, and for the same reason stated there: *the root is
|
|
6
|
+
* never selected by name.* A glob matches package names, and a name can be anything - so
|
|
7
|
+
* `--scope rman-repo` happened to work (measured) while being exactly the name-based addressing the
|
|
8
|
+
* config selectors were redesigned to remove. `/` is structural, cannot collide with a package
|
|
9
|
+
* (nothing can be named it), and gives "the root" one spelling across config and CLI.
|
|
10
|
+
*
|
|
11
|
+
* Accepted by `--ignore` too. The asymmetry would be the thing to remember, and `--ignore /` -
|
|
12
|
+
* every package but the root - is a real thing to want of `clean`.
|
|
13
|
+
*
|
|
14
|
+
* **It selects nothing on a command whose candidates exclude the root**, which is most of them:
|
|
15
|
+
* `repository.packages` holds the workspace members only, so `rman list --scope /` and
|
|
16
|
+
* `rman run build --scope /` match nothing and say so. That is the honest answer rather than a
|
|
17
|
+
* special case - the root has no `list` row and contributes only `pre`/`post` bookends to `run`.
|
|
18
|
+
* `clean` and `changelog`, which put the root in their candidate list on purpose, are where it bites.
|
|
19
|
+
*/
|
|
20
|
+
export const ROOT_SELECTOR = '/';
|
|
21
|
+
/**
|
|
22
|
+
* `--scope`/`--ignore`/`--deps`/`--dependents` as a **declaration** rather than a builder call -
|
|
23
|
+
* spread into a command's `config` block:
|
|
24
|
+
*
|
|
25
|
+
* ```ts
|
|
26
|
+
* config: { ...packageFilterOptions, ...branchGuardOptions, changelog: { ... } }
|
|
27
|
+
* ```
|
|
28
|
+
*
|
|
29
|
+
* **`satisfies`, never a `: Record<...>` annotation.** An annotation widens `type: 'string'` back to
|
|
30
|
+
* `string`, and every type derived from the declaration - the config contribution, the option's own
|
|
31
|
+
* value type - collapses with it. `satisfies` checks the shape and keeps the literals, and it also
|
|
32
|
+
* catches a misspelled key *here*, at the group's own line, rather than in the ten commands that
|
|
33
|
+
* spread it. The `Argv` chaining this replaces could not: a typo there was simply a new option.
|
|
34
|
+
*
|
|
35
|
+
* **Every option is `target: 'cli'`, including the ones that have a config twin.** A shared group
|
|
36
|
+
* belongs to no command, so declaring one `'both'` would contribute `version.scope` - a key nothing
|
|
37
|
+
* reads. Where a `.rmanrc` equivalent exists it is a core key in its own right (`allowBranch`), and
|
|
38
|
+
* a command that reads it names it in `configKeys`.
|
|
39
|
+
*/
|
|
40
|
+
export const packageFilterOptions = {
|
|
41
|
+
scope: {
|
|
42
|
+
target: 'cli',
|
|
43
|
+
describe: 'Only include packages whose name matches this glob, or "/" for the root package (repeatable)',
|
|
44
|
+
// Deliberately 'string', not 'array': an array-typed option greedily swallows every
|
|
45
|
+
// following bare word as its own value, which would eat "exec"'s [command..] positional
|
|
46
|
+
// whole. yargs still collects repeated "--scope a --scope b" into an array either way.
|
|
47
|
+
type: 'string',
|
|
48
|
+
},
|
|
49
|
+
ignore: {
|
|
50
|
+
target: 'cli',
|
|
51
|
+
describe: 'Exclude packages matching this glob (or "/" for the root) - applied after --scope',
|
|
52
|
+
type: 'string',
|
|
53
|
+
},
|
|
54
|
+
platform: {
|
|
55
|
+
target: 'cli',
|
|
56
|
+
describe: 'Only include packages of these platforms, e.g. --platform=node,cargo (repeatable)',
|
|
57
|
+
type: 'string',
|
|
58
|
+
},
|
|
59
|
+
deps: {
|
|
60
|
+
target: 'cli',
|
|
61
|
+
describe: 'Also include every package the matched set depends on',
|
|
62
|
+
type: 'boolean',
|
|
63
|
+
},
|
|
64
|
+
dependents: {
|
|
65
|
+
target: 'cli',
|
|
66
|
+
describe: 'Also include every package that depends on the matched set',
|
|
67
|
+
type: 'boolean',
|
|
68
|
+
},
|
|
69
|
+
};
|
|
70
|
+
/**
|
|
71
|
+
* `--from-root`/`-r` - a group of one, and a function because its text is the command's own word
|
|
72
|
+
* for what it does. Spread it like the others: `...fromRootOption('Build')`.
|
|
73
|
+
*
|
|
74
|
+
* Only where a command scopes by the current directory; see `applyFromRootOption` for why adding it
|
|
75
|
+
* elsewhere is worse than leaving it out.
|
|
76
|
+
*
|
|
77
|
+
* **It was `--root` through 1.x, and the name said the opposite of what it does.** Every reader
|
|
78
|
+
* spells it the same single line - `options.fromRoot ? undefined : repository.currentPackage` - so
|
|
79
|
+
* the flag means *ignore where I am standing*, i.e. the **whole repository**. `--root` reads as "the
|
|
80
|
+
* root alone", which is the narrowest possible set rather than the widest, and the confusion was
|
|
81
|
+
* about to become a contradiction: a `--root-only` beside a `--root` that meant "everything" is
|
|
82
|
+
* unreadable.
|
|
83
|
+
*
|
|
84
|
+
* **`-r` is kept, and a two-letter `-fr` is not possible.** yargs' `short-option-groups` is on by
|
|
85
|
+
* default, so `-fr` parses as `-f -r` and `.strict()` answers `Unknown arguments: f, r` (measured).
|
|
86
|
+
* Turning that off makes `-fr` work and breaks every grouped short - `rman list -sj` works today.
|
|
87
|
+
* So the long name carries the meaning and the incumbent short stays.
|
|
88
|
+
*/
|
|
89
|
+
export function fromRootOption(verb) {
|
|
90
|
+
return {
|
|
91
|
+
fromRoot: {
|
|
92
|
+
target: 'cli',
|
|
93
|
+
cliName: 'from-root',
|
|
94
|
+
alias: 'r',
|
|
95
|
+
describe: `${verb} across the whole repository even when the current directory is inside a single ` +
|
|
96
|
+
'package (which otherwise scopes it to just that package). No effect elsewhere.',
|
|
97
|
+
type: 'boolean',
|
|
98
|
+
},
|
|
99
|
+
};
|
|
100
|
+
}
|
|
2
101
|
/** `--scope`/`--ignore`/`--deps`/`--dependents`, the same shape and describe text in every command
|
|
3
102
|
* that supports them - mirrors `run.command.ts`'s own `applyRunOptions`. */
|
|
4
103
|
export function applyPackageFilterOptions(cmd) {
|
|
5
104
|
return cmd
|
|
6
105
|
.option('scope', {
|
|
7
|
-
describe: 'Only include packages whose name matches this glob (repeatable)',
|
|
106
|
+
describe: 'Only include packages whose name matches this glob, or "/" for the root package (repeatable)',
|
|
8
107
|
// Deliberately 'string', not 'array': an array-typed option greedily swallows every
|
|
9
108
|
// following bare word as its own value, which would eat "exec"'s [command..] positional
|
|
10
109
|
// whole. yargs still collects repeated "--scope a --scope b" into an array either way.
|
|
11
110
|
type: 'string',
|
|
12
111
|
})
|
|
13
112
|
.option('ignore', {
|
|
14
|
-
describe: 'Exclude packages
|
|
113
|
+
describe: 'Exclude packages matching this glob (or "/" for the root) - applied after --scope',
|
|
114
|
+
type: 'string',
|
|
115
|
+
})
|
|
116
|
+
.option('platform', {
|
|
117
|
+
describe: 'Only include packages of these platforms, e.g. --platform=node,cargo (repeatable)',
|
|
15
118
|
type: 'string',
|
|
16
119
|
})
|
|
17
120
|
.option('deps', {
|
|
@@ -27,6 +130,7 @@ export function readPackageFilterOptions(args) {
|
|
|
27
130
|
return {
|
|
28
131
|
scope: args.scope,
|
|
29
132
|
ignore: args.ignore,
|
|
133
|
+
platform: args.platform,
|
|
30
134
|
deps: args.deps,
|
|
31
135
|
dependents: args.dependents,
|
|
32
136
|
};
|
|
@@ -34,7 +138,8 @@ export function readPackageFilterOptions(args) {
|
|
|
34
138
|
/**
|
|
35
139
|
* Narrows `packages` (the full, already-resolved list - toposort order, if any, is preserved)
|
|
36
140
|
* down to what `options` selects. `scope`/`ignore` match against each package's bare name (glob
|
|
37
|
-
* syntax via `micromatch` - `*`, `**`, `{a,b}`, ...)
|
|
141
|
+
* syntax via `micromatch` - `*`, `**`, `{a,b}`, ...), plus `ROOT_SELECTOR` (`"/"`) for the root
|
|
142
|
+
* package, which is matched structurally rather than by name; `ignore` is applied after `scope`, on
|
|
38
143
|
* whatever it left. `deps`/`dependents` then each independently expand *that* matched set along
|
|
39
144
|
* `Package.dependencies` (already the full transitive closure - see
|
|
40
145
|
* `Repository`'s own `_updateDependencies`) and their results are unioned in - so `--deps
|
|
@@ -57,12 +162,16 @@ export function filterPackages(packages, options,
|
|
|
57
162
|
applySkip = true) {
|
|
58
163
|
let matched = applySkip ? packages.filter(p => p.config?.skip !== true) : packages;
|
|
59
164
|
if (options.scope) {
|
|
60
|
-
const
|
|
61
|
-
matched = matched.filter(p =>
|
|
165
|
+
const selects = selector(options.scope);
|
|
166
|
+
matched = matched.filter(p => selects(p));
|
|
62
167
|
}
|
|
63
168
|
if (options.ignore) {
|
|
64
|
-
const
|
|
65
|
-
matched = matched.filter(p => !
|
|
169
|
+
const selects = selector(options.ignore);
|
|
170
|
+
matched = matched.filter(p => !selects(p));
|
|
171
|
+
}
|
|
172
|
+
if (options.platform !== undefined) {
|
|
173
|
+
const wanted = platformNames(options.platform, packages);
|
|
174
|
+
matched = matched.filter(p => wanted.has(p.provider.toLowerCase()));
|
|
66
175
|
}
|
|
67
176
|
if (!options.deps && !options.dependents)
|
|
68
177
|
return matched;
|
|
@@ -83,11 +192,8 @@ applySkip = true) {
|
|
|
83
192
|
}
|
|
84
193
|
return packages.filter(p => included.has(p));
|
|
85
194
|
}
|
|
86
|
-
function toArray(value) {
|
|
87
|
-
return Array.isArray(value) ? value : [value];
|
|
88
|
-
}
|
|
89
195
|
/**
|
|
90
|
-
* `--root`/`-r`, with one describe text instead of four near-identical ones.
|
|
196
|
+
* `--from-root`/`-r`, with one describe text instead of four near-identical ones.
|
|
91
197
|
*
|
|
92
198
|
* **It only means anything where a command scopes by the current directory** - `run`/`build`/`test`,
|
|
93
199
|
* `exec`, `clean`, `changelog` and `diff` narrow to `Repository.currentPackage` when you stand
|
|
@@ -95,19 +201,94 @@ function toArray(value) {
|
|
|
95
201
|
* repository (`version`, `publish`, `list`, `changed`) it would be a flag that does nothing, which
|
|
96
202
|
* is worse than not offering it: a no-op flag reads as a promise.
|
|
97
203
|
*
|
|
204
|
+
* That same rule is why there is no `--root-only` beside it, however naturally the pair reads: it
|
|
205
|
+
* would be a no-op on `run`/`build`/`test` (the root is not in `repository.packages` at all and
|
|
206
|
+
* contributes only `pre`/`post` bookends), identical to this flag on `diff`, already what this flag
|
|
207
|
+
* does on `config`, and on `clean` actively misleading - the root's own sweep recurses through
|
|
208
|
+
* `packages/*`, so a `--root-only` there deletes *more* than a package-scoped run, not less
|
|
209
|
+
* (measured). Where the root genuinely is a candidate, `--scope /` says so - see `ROOT_SELECTOR`.
|
|
210
|
+
*
|
|
98
211
|
* `verb` is the command's own word for what it does, so the text stays the sentence each command was
|
|
99
212
|
* already saying.
|
|
100
213
|
*/
|
|
101
|
-
export function
|
|
102
|
-
return cmd.option('root', {
|
|
214
|
+
export function applyFromRootOption(cmd, verb) {
|
|
215
|
+
return cmd.option('from-root', {
|
|
103
216
|
alias: 'r',
|
|
104
217
|
describe: `${verb} across the whole repository even when the current directory is inside a single ` +
|
|
105
218
|
'package (which otherwise scopes it to just that package). No effect elsewhere.',
|
|
106
219
|
type: 'boolean',
|
|
107
220
|
});
|
|
108
221
|
}
|
|
109
|
-
/** The `--root` flag as the services read it - beside `readPackageFilterOptions`, so a command
|
|
222
|
+
/** The `--from-root` flag as the services read it - beside `readPackageFilterOptions`, so a command
|
|
110
223
|
* reads both the same way. */
|
|
111
|
-
export function
|
|
112
|
-
return args.
|
|
224
|
+
export function readFromRootOption(args) {
|
|
225
|
+
return args.fromRoot;
|
|
226
|
+
}
|
|
227
|
+
function toArray(value) {
|
|
228
|
+
return Array.isArray(value) ? value : [value];
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* One `--scope`/`--ignore` value list as a predicate, with `ROOT_SELECTOR` lifted out of the globs.
|
|
232
|
+
*
|
|
233
|
+
* Split once rather than per package. The root is answered by `wantsRoot` alone and everything else
|
|
234
|
+
* by the globs, so the two never consult each other - and `micromatch` is asked only when a glob is
|
|
235
|
+
* left, since an empty pattern list must match no member rather than all of them, which is what
|
|
236
|
+
* makes a bare `--scope /` select the root **and nothing else**.
|
|
237
|
+
*
|
|
238
|
+
* **A glob is never offered the root**, which is the other half of `ROOT_SELECTOR` and the reason it
|
|
239
|
+
* is not merely a second spelling. `.rmanrc`'s selectors state the same rule - `"[my-*]"` cannot
|
|
240
|
+
* pick up a repository whose root package is called `my-repo`, and `"[*]"` means the members - and
|
|
241
|
+
* the CLI disagreed with it: measured, `rman clean --scope 'rman*'` selected this repository's root.
|
|
242
|
+
* For `clean` that is destructive rather than merely surprising, since the root's own sweep recurses
|
|
243
|
+
* through `packages/*`. Globs are the members, `/` is the root, in both vocabularies.
|
|
244
|
+
*/
|
|
245
|
+
/**
|
|
246
|
+
* `--platform` as a set of lower-cased names, refusing one no package in the repository belongs to.
|
|
247
|
+
*
|
|
248
|
+
* **Comma-split, unlike `--scope`, and the asymmetry is the values' own.** A platform's name is a
|
|
249
|
+
* short identifier a plugin chose, so `--platform=node,cargo` cannot be ambiguous; a scope glob is
|
|
250
|
+
* arbitrary text, where splitting would take a character away from the pattern language. Repeating
|
|
251
|
+
* the flag works for both.
|
|
252
|
+
*
|
|
253
|
+
* **An unknown name is an error, where an unmatched `--scope` glob is not**, and the difference is
|
|
254
|
+
* whether rman knows the answer set. It does here: the platforms are the ones its packages belong
|
|
255
|
+
* to, so `--platform crago` is a typo rman can see, and left alone it is the silent empty result
|
|
256
|
+
* this whole codebase keeps ruling out. The message lists what the repository has - the same call
|
|
257
|
+
* `publish --target` makes against its registry.
|
|
258
|
+
*
|
|
259
|
+
* **Compared case-insensitively.** `Platform.name` is the authority on spelling and `--platform Node`
|
|
260
|
+
* is not a different request; refusing it would be pedantry with an empty result attached.
|
|
261
|
+
*
|
|
262
|
+
* Asked of the packages rather than of `app.platforms`, which `filterPackages` does not have and
|
|
263
|
+
* which would be the wrong set anyway: a registered platform that claimed no directory is not an
|
|
264
|
+
* answer to "what is in this repository".
|
|
265
|
+
*/
|
|
266
|
+
function platformNames(value, packages) {
|
|
267
|
+
const wanted = toArray(value)
|
|
268
|
+
.flatMap(entry => entry.split(','))
|
|
269
|
+
.map(name => name.trim().toLowerCase())
|
|
270
|
+
.filter(Boolean);
|
|
271
|
+
/** An empty `provider` is a package no technology claimed, and there is no spelling for it - a
|
|
272
|
+
* flag selecting "none" would be `--platform ''`, which no shell makes pleasant. Left out of the
|
|
273
|
+
* known set, so naming it is refused like any other unknown. */
|
|
274
|
+
const present = new Set(packages.map(p => p.provider.toLowerCase()).filter(Boolean));
|
|
275
|
+
for (const name of wanted) {
|
|
276
|
+
if (present.has(name))
|
|
277
|
+
continue;
|
|
278
|
+
throw new Error(`--platform "${name}" matches no package in this repository. ` +
|
|
279
|
+
(present.size
|
|
280
|
+
? `It holds: ${[...present].sort().join(', ')}.`
|
|
281
|
+
: 'No package here belongs to a platform - its ".rmanrc" names no "plugins".'));
|
|
282
|
+
}
|
|
283
|
+
return new Set(wanted);
|
|
284
|
+
}
|
|
285
|
+
function selector(value) {
|
|
286
|
+
const patterns = toArray(value);
|
|
287
|
+
const wantsRoot = patterns.includes(ROOT_SELECTOR);
|
|
288
|
+
const globs = patterns.filter(p => p !== ROOT_SELECTOR);
|
|
289
|
+
/** Against `pkg.selector`, which is what `.rmanrc`'s `"[glob]"` matches - one vocabulary, as the
|
|
290
|
+
* `/` above already is. It was `pkg.name`, and the two coincide for every Node repository; a
|
|
291
|
+
* package having a name at all is an ecosystem's promise, and a repository can assign a selector
|
|
292
|
+
* where its own does not offer one. */
|
|
293
|
+
return pkg => (pkg.isRoot ? wantsRoot : globs.length > 0 && micromatch.isMatch(pkg.selector, globs));
|
|
113
294
|
}
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* Needed because a config legitimately holds functions now: a `run.<script>` or `version.<slot>`
|
|
6
6
|
* step written as JavaScript, and an `if` written the same way. It was already needed before that,
|
|
7
7
|
* though, which is the better argument for doing it here rather than at one call site - a
|
|
8
|
-
* `plugins` entry given in its object form carries the plugin's seams, and `rman config --root`
|
|
8
|
+
* `plugins` entry given in its object form carries the plugin's seams, and `rman config --from-root`
|
|
9
9
|
* died on one with `unacceptable kind of an object to dump [object Function]` (measured, on a
|
|
10
10
|
* repository whose shared config did nothing more unusual than `extends` a plugin package).
|
|
11
11
|
*
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* Needed because a config legitimately holds functions now: a `run.<script>` or `version.<slot>`
|
|
6
6
|
* step written as JavaScript, and an `if` written the same way. It was already needed before that,
|
|
7
7
|
* though, which is the better argument for doing it here rather than at one call site - a
|
|
8
|
-
* `plugins` entry given in its object form carries the plugin's seams, and `rman config --root`
|
|
8
|
+
* `plugins` entry given in its object form carries the plugin's seams, and `rman config --from-root`
|
|
9
9
|
* died on one with `unacceptable kind of an object to dump [object Function]` (measured, on a
|
|
10
10
|
* repository whose shared config did nothing more unusual than `extends` a plugin package).
|
|
11
11
|
*
|
package/utils/run-bin.d.ts
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
|
+
import type { RmanApplication } from '../core/application.js';
|
|
1
2
|
import { type LogLevel } from './logger.js';
|
|
2
3
|
export interface RunBinOptions {
|
|
4
|
+
/**
|
|
5
|
+
* The application whose technologies put a repository's locally installed binaries on PATH -
|
|
6
|
+
* `node_modules/.bin` for a Node repository, whatever another technology uses.
|
|
7
|
+
*
|
|
8
|
+
* Passed rather than looked up, so a command run against one repository can never pick up the
|
|
9
|
+
* binaries of another in the same process. Omitted (a caller outside any repository) leaves the
|
|
10
|
+
* inherited PATH exactly as it was, which is also what a repository naming no plugin gets.
|
|
11
|
+
*/
|
|
12
|
+
app?: RmanApplication;
|
|
3
13
|
/** Where to run it, and the directory `node_modules/.bin` is resolved from. Default `process.cwd()`. */
|
|
4
14
|
cwd?: string;
|
|
5
15
|
/** 'inherit' streams the child's output straight to the terminal; 'pipe' captures it and resolves
|
package/utils/run-bin.js
CHANGED
|
@@ -34,7 +34,7 @@ export async function runBin(bin, argv, options = {}) {
|
|
|
34
34
|
const child = spawn(process.platform === 'win32' ? `${bin}.cmd` : bin, argv, {
|
|
35
35
|
cwd,
|
|
36
36
|
stdio: stdio === 'inherit' ? 'inherit' : 'pipe',
|
|
37
|
-
env: BinPath.env({ cwd, env: options.env }),
|
|
37
|
+
env: BinPath.env({ cwd, env: options.env, app: options.app }),
|
|
38
38
|
windowsHide: true,
|
|
39
39
|
});
|
|
40
40
|
/** So an interrupted rman does not leave this running - `exec` always did this and this did not,
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import type { RunService } from '../services/run.service.js';
|
|
2
|
+
/**
|
|
3
|
+
* Everything `run`, `build` and `test` accept - the package filter, the branch guard, `--from-root`, and
|
|
4
|
+
* the scheduling flags on top.
|
|
5
|
+
*
|
|
6
|
+
* **In `utils/` rather than in `run.command.ts`, which is where the `Argv` version lived.** `build`
|
|
7
|
+
* and `test` had to import it from a sibling command, which reads as a dependency between commands
|
|
8
|
+
* and is not one: they share a declaration, the way they already share `packageFilterOptions`.
|
|
9
|
+
*
|
|
10
|
+
* Every option is `target: 'cli'`. The `.rmanrc` half of these lives at `run.<script>.concurrency`,
|
|
11
|
+
* `.bail`, `.topo`, `.progress` - keyed by script name, so it is the one config shape that cannot be
|
|
12
|
+
* derived from a flat option map and stays hand-written in `RmanConfig`.
|
|
13
|
+
*/
|
|
14
|
+
export declare const runOptions: {
|
|
15
|
+
parallel: {
|
|
16
|
+
target: "cli";
|
|
17
|
+
describe: string;
|
|
18
|
+
/** No `type`: the flag takes a boolean *or* a number, and `coerce` is what says so - which is
|
|
19
|
+
* also where `OptionValue` reads this option's type from. */
|
|
20
|
+
coerce: (v: unknown) => boolean | number | undefined;
|
|
21
|
+
};
|
|
22
|
+
bail: {
|
|
23
|
+
target: "cli";
|
|
24
|
+
describe: string;
|
|
25
|
+
type: "boolean";
|
|
26
|
+
};
|
|
27
|
+
topo: {
|
|
28
|
+
target: "cli";
|
|
29
|
+
describe: string;
|
|
30
|
+
type: "boolean";
|
|
31
|
+
};
|
|
32
|
+
progress: {
|
|
33
|
+
target: "cli";
|
|
34
|
+
describe: string;
|
|
35
|
+
type: "boolean";
|
|
36
|
+
};
|
|
37
|
+
changed: {
|
|
38
|
+
target: "cli";
|
|
39
|
+
alias: string;
|
|
40
|
+
describe: string;
|
|
41
|
+
type: "boolean";
|
|
42
|
+
};
|
|
43
|
+
changedSince: {
|
|
44
|
+
target: "cli";
|
|
45
|
+
cliName: string;
|
|
46
|
+
describe: string;
|
|
47
|
+
type: "string";
|
|
48
|
+
/** Declared on the option rather than as a separate `.conflicts()` call - one place says what
|
|
49
|
+
* this flag is and what it cannot be combined with. */
|
|
50
|
+
conflicts: string;
|
|
51
|
+
};
|
|
52
|
+
fromRoot: {
|
|
53
|
+
target: "cli";
|
|
54
|
+
cliName: string;
|
|
55
|
+
alias: string;
|
|
56
|
+
describe: string;
|
|
57
|
+
type: "boolean";
|
|
58
|
+
};
|
|
59
|
+
allowBranch: {
|
|
60
|
+
target: "cli";
|
|
61
|
+
cliName: string;
|
|
62
|
+
describe: string;
|
|
63
|
+
type: "string";
|
|
64
|
+
};
|
|
65
|
+
ignoreBranch: {
|
|
66
|
+
target: "cli";
|
|
67
|
+
cliName: string;
|
|
68
|
+
describe: string;
|
|
69
|
+
type: "string";
|
|
70
|
+
};
|
|
71
|
+
scope: {
|
|
72
|
+
target: "cli";
|
|
73
|
+
describe: string;
|
|
74
|
+
type: "string";
|
|
75
|
+
};
|
|
76
|
+
ignore: {
|
|
77
|
+
target: "cli";
|
|
78
|
+
describe: string;
|
|
79
|
+
type: "string";
|
|
80
|
+
};
|
|
81
|
+
platform: {
|
|
82
|
+
target: "cli";
|
|
83
|
+
describe: string;
|
|
84
|
+
type: "string";
|
|
85
|
+
};
|
|
86
|
+
deps: {
|
|
87
|
+
target: "cli";
|
|
88
|
+
describe: string;
|
|
89
|
+
type: "boolean";
|
|
90
|
+
};
|
|
91
|
+
dependents: {
|
|
92
|
+
target: "cli";
|
|
93
|
+
describe: string;
|
|
94
|
+
type: "boolean";
|
|
95
|
+
};
|
|
96
|
+
};
|
|
97
|
+
export declare function readRunOptions(args: any): RunService.Options;
|