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
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import type { RmanConfig } from '../interfaces/rman-config.interface.js';
|
|
2
|
+
import type { PackageFilterOptions } from '../utils/package-filter.js';
|
|
3
|
+
import type { RmanApplication } from './application.js';
|
|
4
|
+
import type { Package } from './package.js';
|
|
5
|
+
import type { Repository } from './repository.js';
|
|
6
|
+
/**
|
|
7
|
+
* **Where a package's artifact ships, as a contribution.**
|
|
8
|
+
*
|
|
9
|
+
* `publish` used to be `rman-node`'s command, and that was backwards in a way worth stating: the
|
|
10
|
+
* command itself is about a *repository* - which packages are candidates, which versions are
|
|
11
|
+
* already out there, what order to push them in, what to print - and none of that is npm's. What is
|
|
12
|
+
* npm's is one answer to "is this version on the registry, and how do I push it", which is exactly
|
|
13
|
+
* the size of this interface. Docker publishing was in the core all along and could only be reached
|
|
14
|
+
* through a Node plugin's command; a Cargo repository could reach neither.
|
|
15
|
+
*
|
|
16
|
+
* So: the core ships `publish` and the `docker` target, the `node` built-in contributes `npm`, and a
|
|
17
|
+
* repository in any other ecosystem contributes its own without either package knowing about it.
|
|
18
|
+
*
|
|
19
|
+
* A target owns three things and no more:
|
|
20
|
+
*
|
|
21
|
+
* - **Which packages are its own by default** (`claims`) - see below.
|
|
22
|
+
* - **Its own CLI options**, merged into `publish`'s by the command. Every flag that only meant
|
|
23
|
+
* something to npm (`--access`, `--tag`, `--otp`, `--registry`, `--userconfig`, `--contents`,
|
|
24
|
+
* `--package-manager`) is declared here now instead of on a command the core would otherwise have
|
|
25
|
+
* to know them all in advance.
|
|
26
|
+
* - **`getPlan`/`applyPlan`** - the same two-step shape every other rman service uses, and the
|
|
27
|
+
* reason `--dry-run` and the confirmation prompt are the command's business rather than each
|
|
28
|
+
* target's.
|
|
29
|
+
*/
|
|
30
|
+
export interface PublishTarget {
|
|
31
|
+
/** The name `publish.target` and `--target` use, and the label printed beside a package. */
|
|
32
|
+
readonly name: string;
|
|
33
|
+
/** One line for `--target`'s help - a reader asking `rman publish --help` in a polyglot
|
|
34
|
+
* repository has no other way to find out which targets are even installed. */
|
|
35
|
+
readonly describe?: string;
|
|
36
|
+
/**
|
|
37
|
+
* This target's own flags, merged into `publish`'s options.
|
|
38
|
+
*
|
|
39
|
+
* Flat, not namespaced: `--tag` reads better than `--npm-tag`, and two targets colliding on a
|
|
40
|
+
* name is refused loudly by the command rather than resolved by a rule nobody would remember.
|
|
41
|
+
* Name a flag for the target when it genuinely belongs to one (`--docker-namespace`).
|
|
42
|
+
*/
|
|
43
|
+
readonly options?: Record<string, RmanConfig.CommandOption>;
|
|
44
|
+
/**
|
|
45
|
+
* Whether a package that declares **no** `publish.target` at all ships here.
|
|
46
|
+
*
|
|
47
|
+
* Absent means never - the target is opt-in, which is what `docker` is. `npm`'s answer is
|
|
48
|
+
* `pkg.provider === 'node'`, and that is the fix for a real bug rather than a nicety: the default
|
|
49
|
+
* used to be a hardcoded `['npm']` in the core, so `rman list --json` reported
|
|
50
|
+
* `publishTargets: ["npm"]` for a Cargo package and `publish` treated it as an npm candidate.
|
|
51
|
+
* A default only the ecosystem can state had been written down by someone who could not know it.
|
|
52
|
+
*/
|
|
53
|
+
claims?(pkg: Package): boolean;
|
|
54
|
+
/** What this target *would* do - never publishes. Called even under `--dry-run`, which is the
|
|
55
|
+
* whole point of the split. */
|
|
56
|
+
getPlan(ctx: PublishTarget.Context): Promise<PublishTarget.Entry[]>;
|
|
57
|
+
/** Publishes every `'publish'` entry in `plan`, and returns what it did. */
|
|
58
|
+
applyPlan(ctx: PublishTarget.Context, plan: PublishTarget.Entry[]): Promise<PublishTarget.Entry[]>;
|
|
59
|
+
}
|
|
60
|
+
export declare namespace PublishTarget {
|
|
61
|
+
/**
|
|
62
|
+
* What a target is handed, once per call.
|
|
63
|
+
*
|
|
64
|
+
* `args` is the parsed argv, untyped on purpose: a target declared its own options, so it is the
|
|
65
|
+
* only thing that knows their names and types, and the core cannot be made to know them without
|
|
66
|
+
* becoming the thing this interface exists to stop it being.
|
|
67
|
+
*/
|
|
68
|
+
interface Context {
|
|
69
|
+
readonly app: RmanApplication;
|
|
70
|
+
readonly repository: Repository;
|
|
71
|
+
/** The filters every target shares, read off argv once by the command. */
|
|
72
|
+
readonly options: Options;
|
|
73
|
+
/** The whole parsed argv - a target reads the options it declared out of this. */
|
|
74
|
+
readonly args: Record<string, any>;
|
|
75
|
+
}
|
|
76
|
+
interface Options extends PackageFilterOptions {
|
|
77
|
+
/** A package with uncommitted local changes is excluded (`'skip'`) instead of aborting the
|
|
78
|
+
* whole plan (`'error'`). */
|
|
79
|
+
ignoreDirty?: boolean;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* One package's outcome for one target.
|
|
83
|
+
*
|
|
84
|
+
* `'skip'` and `'error'` differ in what they do to the run: an error aborts before anything is
|
|
85
|
+
* published, a skip is a package the plan deliberately leaves alone. A target may add fields of
|
|
86
|
+
* its own (docker carries the resolved image reference); `detail` is the one the command prints,
|
|
87
|
+
* so whatever a target wants shown beside a package goes there.
|
|
88
|
+
*/
|
|
89
|
+
interface Entry {
|
|
90
|
+
package: Package;
|
|
91
|
+
version: string;
|
|
92
|
+
status: 'publish' | 'skip' | 'up-to-date' | 'error';
|
|
93
|
+
/** Printed after the package name - docker's resolved `<namespace>/<image>`, for instance. */
|
|
94
|
+
detail?: string;
|
|
95
|
+
reason?: string;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* **A target's name, and deliberately not a union.**
|
|
100
|
+
*
|
|
101
|
+
* It was `'npm' | 'docker'`, the type half of a bug whose runtime half was a hardcoded `['npm']`
|
|
102
|
+
* default, so `rman list --json` reported `publishTargets: ["npm"]` for a Cargo package. Both are
|
|
103
|
+
* gone together - which targets exist is whatever the repository's plugins contribute
|
|
104
|
+
* (`RmanApplication.publishTargets`), so a union here would mean the core naming plugins it cannot
|
|
105
|
+
* know about, exactly as `Package.provider` must not.
|
|
106
|
+
*
|
|
107
|
+
* A name nothing implements is caught where the facts are, by `publish` itself, naming the targets
|
|
108
|
+
* this repository does have.
|
|
109
|
+
*/
|
|
110
|
+
export type PublishTargetName = string;
|
|
111
|
+
/**
|
|
112
|
+
* The targets a package **declares**, or `undefined` when it declares none - which is not the same
|
|
113
|
+
* as an empty list, and the difference is what `claims` is asked about.
|
|
114
|
+
*/
|
|
115
|
+
export declare function declaredTargets(pkg: Package): string[] | undefined;
|
|
116
|
+
/** Whether `pkg` ships to `target`: its own `publish.target` decides when it has one, and the
|
|
117
|
+
* target's own `claims` decides when it does not. */
|
|
118
|
+
export declare function shipsTo(pkg: Package, target: PublishTarget): boolean;
|
|
119
|
+
/** Every registered target `pkg` ships to, in registration order. The single answer to "where does
|
|
120
|
+
* this package go", so `publish` and `list --json` cannot disagree about it. */
|
|
121
|
+
export declare function targetsOf(app: RmanApplication, pkg: Package): PublishTarget[];
|
|
122
|
+
/** Names in a package's `publish.target` that no registered target answers to - a misconfiguration
|
|
123
|
+
* that used to be caught by a `choices: ['npm', 'docker']` the core can no longer write down. */
|
|
124
|
+
export declare function unknownTargets(app: RmanApplication, pkg: Package): string[];
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The targets a package **declares**, or `undefined` when it declares none - which is not the same
|
|
3
|
+
* as an empty list, and the difference is what `claims` is asked about.
|
|
4
|
+
*/
|
|
5
|
+
export function declaredTargets(pkg) {
|
|
6
|
+
const declared = pkg.config.publish?.target;
|
|
7
|
+
if (declared === undefined)
|
|
8
|
+
return undefined;
|
|
9
|
+
return Array.isArray(declared) ? [...declared] : [declared];
|
|
10
|
+
}
|
|
11
|
+
/** Whether `pkg` ships to `target`: its own `publish.target` decides when it has one, and the
|
|
12
|
+
* target's own `claims` decides when it does not. */
|
|
13
|
+
export function shipsTo(pkg, target) {
|
|
14
|
+
const declared = declaredTargets(pkg);
|
|
15
|
+
return declared ? declared.includes(target.name) : !!target.claims?.(pkg);
|
|
16
|
+
}
|
|
17
|
+
/** Every registered target `pkg` ships to, in registration order. The single answer to "where does
|
|
18
|
+
* this package go", so `publish` and `list --json` cannot disagree about it. */
|
|
19
|
+
export function targetsOf(app, pkg) {
|
|
20
|
+
return app.publishTargets.all.filter(target => shipsTo(pkg, target));
|
|
21
|
+
}
|
|
22
|
+
/** Names in a package's `publish.target` that no registered target answers to - a misconfiguration
|
|
23
|
+
* that used to be caught by a `choices: ['npm', 'docker']` the core can no longer write down. */
|
|
24
|
+
export function unknownTargets(app, pkg) {
|
|
25
|
+
const declared = declaredTargets(pkg);
|
|
26
|
+
if (!declared)
|
|
27
|
+
return [];
|
|
28
|
+
const known = new Set(app.publishTargets.all.map(t => t.name));
|
|
29
|
+
return declared.filter(name => !known.has(name));
|
|
30
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* An ordered collection of contributions, held **on the application** rather than in a module.
|
|
3
|
+
*
|
|
4
|
+
* Every registry rman had was a module-level array (`const providers: Provider[] = []` in
|
|
5
|
+
* `manifest.ts`, `workspace.ts`, `bin-path.ts`, `run.service.ts`), which made it process-global:
|
|
6
|
+
* two repositories in one process shared it. The test suite needed a root hook emptying five of
|
|
7
|
+
* them before every single test, and without it whichever spec ran first decided the answer for
|
|
8
|
+
* the rest - so the core appeared to work in tests that had registered nothing.
|
|
9
|
+
*
|
|
10
|
+
* An instance per `RmanApplication` closes the whole class: a new application starts empty, and
|
|
11
|
+
* nothing has to be cleaned up afterwards - the root hook is deleted.
|
|
12
|
+
*
|
|
13
|
+
* **Registry, not service.** The distinction is multiplicity: a registry is for a question whose
|
|
14
|
+
* answer is the *sum* of what was contributed (every provider's bin directories, the first provider
|
|
15
|
+
* that recognizes a directory). A question with exactly one answer is a service, replaceable
|
|
16
|
+
* through `RmanApplication.getService`.
|
|
17
|
+
*/
|
|
18
|
+
export declare class Registry<T> implements Iterable<T> {
|
|
19
|
+
private readonly items;
|
|
20
|
+
/** Contributions in registration order, which for a plugin is `plugins` declaration order. */
|
|
21
|
+
get all(): readonly T[];
|
|
22
|
+
get size(): number;
|
|
23
|
+
/** Idempotent by identity: a plugin may both declare a contribution and register it itself, and
|
|
24
|
+
* the same function arriving twice would make the registry lie about what is in it. */
|
|
25
|
+
add(item: T): this;
|
|
26
|
+
/** The first contribution `ask` gives an answer for - "first that recognizes it" resolution,
|
|
27
|
+
* which is how a directory finds the manifest reader and the workspace layout that claim it. */
|
|
28
|
+
first<R>(ask: (item: T) => R | undefined): R | undefined;
|
|
29
|
+
[Symbol.iterator](): Iterator<T>;
|
|
30
|
+
}
|
package/core/registry.js
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* An ordered collection of contributions, held **on the application** rather than in a module.
|
|
3
|
+
*
|
|
4
|
+
* Every registry rman had was a module-level array (`const providers: Provider[] = []` in
|
|
5
|
+
* `manifest.ts`, `workspace.ts`, `bin-path.ts`, `run.service.ts`), which made it process-global:
|
|
6
|
+
* two repositories in one process shared it. The test suite needed a root hook emptying five of
|
|
7
|
+
* them before every single test, and without it whichever spec ran first decided the answer for
|
|
8
|
+
* the rest - so the core appeared to work in tests that had registered nothing.
|
|
9
|
+
*
|
|
10
|
+
* An instance per `RmanApplication` closes the whole class: a new application starts empty, and
|
|
11
|
+
* nothing has to be cleaned up afterwards - the root hook is deleted.
|
|
12
|
+
*
|
|
13
|
+
* **Registry, not service.** The distinction is multiplicity: a registry is for a question whose
|
|
14
|
+
* answer is the *sum* of what was contributed (every provider's bin directories, the first provider
|
|
15
|
+
* that recognizes a directory). A question with exactly one answer is a service, replaceable
|
|
16
|
+
* through `RmanApplication.getService`.
|
|
17
|
+
*/
|
|
18
|
+
export class Registry {
|
|
19
|
+
items = [];
|
|
20
|
+
/** Contributions in registration order, which for a plugin is `plugins` declaration order. */
|
|
21
|
+
get all() {
|
|
22
|
+
return this.items;
|
|
23
|
+
}
|
|
24
|
+
get size() {
|
|
25
|
+
return this.items.length;
|
|
26
|
+
}
|
|
27
|
+
/** Idempotent by identity: a plugin may both declare a contribution and register it itself, and
|
|
28
|
+
* the same function arriving twice would make the registry lie about what is in it. */
|
|
29
|
+
add(item) {
|
|
30
|
+
if (!this.items.includes(item))
|
|
31
|
+
this.items.push(item);
|
|
32
|
+
return this;
|
|
33
|
+
}
|
|
34
|
+
/** The first contribution `ask` gives an answer for - "first that recognizes it" resolution,
|
|
35
|
+
* which is how a directory finds the manifest reader and the workspace layout that claim it. */
|
|
36
|
+
first(ask) {
|
|
37
|
+
for (const item of this.items) {
|
|
38
|
+
const answer = ask(item);
|
|
39
|
+
if (answer !== undefined)
|
|
40
|
+
return answer;
|
|
41
|
+
}
|
|
42
|
+
return undefined;
|
|
43
|
+
}
|
|
44
|
+
[Symbol.iterator]() {
|
|
45
|
+
return this.items[Symbol.iterator]();
|
|
46
|
+
}
|
|
47
|
+
}
|
package/core/repository.d.ts
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
|
+
import type { RmanConfig } from '../interfaces/rman-config.interface.js';
|
|
2
|
+
import { type DetectedBuiltin } from '../plugins/detect.js';
|
|
3
|
+
import { RmanApplication } from './application.js';
|
|
1
4
|
import { type ConfigScope, type GitScope, type PackageScope, type RepositoryScope } from './config.js';
|
|
2
|
-
import type { LoadedCommand } from './custom-command.js';
|
|
3
5
|
import { Package } from './package.js';
|
|
6
|
+
import type { Platform } from './plugin.js';
|
|
7
|
+
import { Workspace } from './workspace.js';
|
|
4
8
|
export declare class Repository extends Package {
|
|
5
9
|
readonly dirname: string;
|
|
6
10
|
readonly monorepo: boolean;
|
|
@@ -10,9 +14,10 @@ export declare class Repository extends Package {
|
|
|
10
14
|
* really was. Used by `currentPackage` to scope commands to "the package I'm standing in". */
|
|
11
15
|
readonly cwd: string;
|
|
12
16
|
readonly rootPackage: Package;
|
|
17
|
+
/** See the `defineProperty` in the constructor - what detection supplied, when it did. */
|
|
18
|
+
readonly detectedBuiltin?: DetectedBuiltin;
|
|
13
19
|
/** Commands the repository's plugins contributed, loaded during `create` because the workspace
|
|
14
20
|
* providers they bring are needed before any package can be found. `cli.ts` registers them. */
|
|
15
|
-
pluginCommands: LoadedCommand[];
|
|
16
21
|
/**
|
|
17
22
|
* Cached repository scope - see `_repositoryScope`.
|
|
18
23
|
*
|
|
@@ -36,11 +41,24 @@ export declare class Repository extends Package {
|
|
|
36
41
|
* for every package that mentions it.
|
|
37
42
|
*/
|
|
38
43
|
private readonly _readCache;
|
|
39
|
-
|
|
44
|
+
/**
|
|
45
|
+
* The application this repository belongs to - its services, its technologies, its logger.
|
|
46
|
+
*
|
|
47
|
+
* **Non-enumerable**, like `_repoScope` and `_git` beside it: the two things that walk a
|
|
48
|
+
* repository are `{...pkg}` spreads and the config scope, and an enumerable back-reference to the
|
|
49
|
+
* whole application would be dragged into both. A `Package` deliberately has no such field at
|
|
50
|
+
* all; a repository is never spread or serialized, which is what makes this one safe - measured,
|
|
51
|
+
* rather than assumed.
|
|
52
|
+
*/
|
|
53
|
+
readonly app: RmanApplication;
|
|
54
|
+
protected constructor(app: RmanApplication, dirname: string, monorepo: boolean, packages: Package[],
|
|
40
55
|
/** The directory `Repository.create()` was actually invoked from - unlike `dirname` (the
|
|
41
56
|
* resolved repository root, possibly several levels up), this is where the user's shell
|
|
42
57
|
* really was. Used by `currentPackage` to scope commands to "the package I'm standing in". */
|
|
43
|
-
cwd?: string
|
|
58
|
+
cwd?: string,
|
|
59
|
+
/** The root directory's own technology, from the same walk that found the packages - so the
|
|
60
|
+
* repository and its `rootPackage` agree without either searching the registry again. */
|
|
61
|
+
platform?: Platform);
|
|
44
62
|
/**
|
|
45
63
|
* The package whose own directory contains `cwd` (the deepest match, so a package nested
|
|
46
64
|
* inside another's directory resolves to the innermost one) - or `undefined` when `cwd` *is*
|
|
@@ -60,9 +78,21 @@ export declare class Repository extends Package {
|
|
|
60
78
|
* dirty, the reference point decides the rest: without `hash`, `committed`
|
|
61
79
|
* means committed but not yet in the upstream branch; with `hash`, `changed`
|
|
62
80
|
* means it differs from that commit. Otherwise a package is `clean`.
|
|
81
|
+
*
|
|
82
|
+
* **Keyed by `Package.selector`**, which is what addresses a package - it was `name`, and the two
|
|
83
|
+
* coincide wherever a technology names its packages. A repository whose does not had every such
|
|
84
|
+
* package answering to `""`, so one entry stood for all of them.
|
|
85
|
+
*
|
|
86
|
+
* **`includeRoot` is opt-in, and the reason is that the root's answer means something different.**
|
|
87
|
+
* Its directory contains every other package, so the same rule - "does a changed file fall under
|
|
88
|
+
* this directory" - reports `dirty` for the root whenever *anything* in the repository is dirty.
|
|
89
|
+
* That is the honest reading of the rule rather than a bug, and it is not what `run --changed`
|
|
90
|
+
* wants, so only a caller that asked for the root gets it (`rman list`'s table, which shows the
|
|
91
|
+
* root as the tree's own row).
|
|
63
92
|
*/
|
|
64
93
|
listStatus(options?: {
|
|
65
94
|
hash?: string;
|
|
95
|
+
includeRoot?: boolean;
|
|
66
96
|
}): Promise<Record<string, Repository.PackageStatus>>;
|
|
67
97
|
/**
|
|
68
98
|
* The scope a `${{ ... }}` expression is evaluated against for `pkg`, optionally with the version
|
|
@@ -89,13 +119,44 @@ export declare class Repository extends Package {
|
|
|
89
119
|
* nothing under `getPackages()` is the root, so only its own unmarked config applies.
|
|
90
120
|
*/
|
|
91
121
|
/**
|
|
92
|
-
* Gives every package its `repository
|
|
93
|
-
*
|
|
122
|
+
* Gives every package its `repository`, and hangs the `parent`/`children` tree off the walk that
|
|
123
|
+
* found them - before any config is resolved, since a config expression or a provider may already
|
|
124
|
+
* want to navigate from a package outwards.
|
|
125
|
+
*
|
|
126
|
+
* **The containment is read from the tree rather than recomputed from paths.** It used to be an
|
|
127
|
+
* O(n²) sweep comparing every package's directory against every other's and keeping the longest
|
|
128
|
+
* prefix - which is the same question `Workspace.walk` answers on the way down, asked again
|
|
129
|
+
* afterwards with the answer thrown away. Two places deriving one relationship is two places to
|
|
130
|
+
* disagree; there is one now.
|
|
131
|
+
*
|
|
132
|
+
* **`parent` is defined non-enumerably, `children` is a plain field**, which is the one asymmetry
|
|
133
|
+
* here and it is deliberate: a tree is serialized downwards, so `children` has to be walkable and
|
|
134
|
+
* `parent` must not be, or every `JSON.stringify` is a cycle. The same way `Repository.app` and
|
|
135
|
+
* `ORIGINS` travel.
|
|
94
136
|
*
|
|
95
137
|
* A repository's own `repository` is itself, which reads oddly and is the honest answer:
|
|
96
138
|
* `Repository extends Package`, so the repository *is* a package of its own repository.
|
|
97
139
|
*/
|
|
98
|
-
protected _linkPackages(): void;
|
|
140
|
+
protected _linkPackages(tree: Workspace.Node, nodes: Workspace.Node[], packages: Package[]): void;
|
|
141
|
+
/**
|
|
142
|
+
* Gives every package the selector a `"[glob]"` block and `--scope` match it by, and refuses two
|
|
143
|
+
* packages that would answer to the same one.
|
|
144
|
+
*
|
|
145
|
+
* **Its own step, before any config is resolved by a selector**, which is the ordering that makes
|
|
146
|
+
* the rest work: `_resolveConfigs` asks `resolveConfig` for each package *by selector*, so an
|
|
147
|
+
* address assigned afterwards would be applied to nothing.
|
|
148
|
+
*
|
|
149
|
+
* **`name` comes from the unmarked cascade only** - the same read `platform` gets, from the same
|
|
150
|
+
* cache, for the same reason. A `"[glob]"` block cannot set it (`assertSelectorBlocks` refuses
|
|
151
|
+
* one) because the glob matches the very thing the block would be setting.
|
|
152
|
+
*
|
|
153
|
+
* **Uniqueness is checked, and the cascade is the mistake it usually catches.** `name` cascades
|
|
154
|
+
* like every unmarked key, so one declaration above two packages gives both the same address -
|
|
155
|
+
* and the failure would otherwise be silent in the worst way: the config reaches both and
|
|
156
|
+
* `getPackage` returns whichever came first. The message names both directories, and says the
|
|
157
|
+
* cascade out loud when the two got it from one declaration.
|
|
158
|
+
*/
|
|
159
|
+
protected _assignSelectors(rootDir: string, cache: Map<string, RmanConfig>): Promise<void>;
|
|
99
160
|
protected _resolveConfigs(): Promise<void>;
|
|
100
161
|
protected _topoSortPackages(packages: Package[]): void;
|
|
101
162
|
protected _packageScope(pkg: Package, targetVersion?: string): PackageScope;
|
|
@@ -131,16 +192,18 @@ export declare class Repository extends Package {
|
|
|
131
192
|
* otherwise: the plugins that know what a package is are named in the config file this step
|
|
132
193
|
* is looking for.
|
|
133
194
|
* 2. **Load the plugins** the root's config names, which registers their workspace providers
|
|
134
|
-
* (
|
|
195
|
+
* (their commands arrive through `.rmanrc "commands"`, which `cli.ts` reads).
|
|
135
196
|
* 3. **Ask the providers** for the layout. None recognizing it means a repository that is itself
|
|
136
197
|
* the one package.
|
|
137
198
|
*
|
|
138
199
|
* **A repository whose `.rmanrc` names no plugin has no packages beyond itself**, and that is the
|
|
139
200
|
* boundary working rather than failing: `workspaces` in a `package.json` is npm's idea, so it
|
|
140
|
-
* takes `plugins: ['
|
|
201
|
+
* takes `plugins: ['node']` - or detection reading the directory as a Node one - for it to be
|
|
202
|
+
* read as a workspace at all.
|
|
141
203
|
*/
|
|
142
204
|
static create(root?: string, options?: {
|
|
143
205
|
deep?: number;
|
|
206
|
+
app?: RmanApplication;
|
|
144
207
|
}): Promise<Repository>;
|
|
145
208
|
/** Finishes constructing `repo` with the async work a constructor can't do itself - resolving
|
|
146
209
|
* `.rmanrc`/`.rmanrc.yml`/`.rmanrc.cjs`/`.mjs`/`.js` config (which may need a dynamic `import()`)
|