rman 1.3.0 → 2.0.0-beta.3
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 +65 -31
- package/builtins/platforms/node/augmentation/rmanrc.augmentation.d.ts +83 -0
- package/builtins/platforms/node/augmentation/system-info.augmentation.d.ts +26 -0
- package/builtins/platforms/node/augmentation/system-info.augmentation.js +79 -0
- package/builtins/platforms/node/commands/ci.command.d.ts +133 -0
- package/builtins/platforms/node/commands/ci.command.js +60 -0
- package/builtins/platforms/node/commands/clean.command.d.ts +185 -0
- package/builtins/platforms/node/commands/clean.command.js +74 -0
- package/builtins/platforms/node/index.d.ts +8 -0
- package/builtins/platforms/node/index.js +8 -0
- package/builtins/platforms/node/node-config.interface.d.ts +76 -0
- package/builtins/platforms/node/node-config.interface.js +7 -0
- package/builtins/platforms/node/node-manifest.provider.d.ts +68 -0
- package/builtins/platforms/node/node-manifest.provider.js +125 -0
- package/builtins/platforms/node/node.platform.d.ts +53 -0
- package/builtins/platforms/node/node.platform.js +134 -0
- package/builtins/platforms/node/services/ci.service.d.ts +47 -0
- package/builtins/platforms/node/services/ci.service.js +213 -0
- package/builtins/platforms/node/services/clean.service.d.ts +53 -0
- package/builtins/platforms/node/services/clean.service.js +237 -0
- package/builtins/platforms/node/services/publish.service.d.ts +114 -0
- package/builtins/platforms/node/services/publish.service.js +371 -0
- package/builtins/platforms/node/services/version-plan.service.d.ts +44 -0
- package/builtins/platforms/node/services/version-plan.service.js +58 -0
- package/builtins/platforms/node/utils/workspace-range.d.ts +26 -0
- package/builtins/platforms/node/utils/workspace-range.js +28 -0
- package/builtins/presets/index.d.ts +15 -0
- package/builtins/presets/index.js +57 -0
- package/builtins/presets/node.d.ts +16 -0
- package/builtins/presets/node.js +57 -0
- package/{services → builtins/publish-targets/docker}/docker-publish.service.d.ts +52 -31
- package/{services → builtins/publish-targets/docker}/docker-publish.service.js +49 -26
- package/builtins/publish-targets/docker/docker.target.d.ts +54 -0
- package/builtins/publish-targets/docker/docker.target.js +40 -0
- package/builtins/publish-targets/docker/index.d.ts +2 -0
- package/builtins/publish-targets/docker/index.js +2 -0
- package/builtins/publish-targets/npm/index.d.ts +2 -0
- package/builtins/publish-targets/npm/index.js +2 -0
- package/builtins/publish-targets/npm/npm-publish-target.d.ts +73 -0
- package/builtins/publish-targets/npm/npm-publish-target.js +95 -0
- package/builtins/publish-targets/npm/npm-view.d.ts +48 -0
- package/builtins/publish-targets/npm/npm-view.js +71 -0
- package/cli.d.ts +8 -0
- package/cli.js +228 -93
- package/commands/build.command.d.ts +177 -3
- package/commands/build.command.js +20 -10
- package/commands/changelog.command.d.ts +296 -3
- package/commands/changelog.command.js +127 -43
- package/commands/config.command.d.ts +44 -3
- package/commands/config.command.js +53 -24
- 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/lint.command.d.ts +176 -0
- package/commands/lint.command.js +34 -0
- 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 +330 -3
- package/commands/version.command.js +292 -78
- 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 +160 -0
- package/core/classes/package.d.ts +219 -0
- package/core/classes/package.js +214 -0
- package/core/classes/registry.d.ts +30 -0
- package/core/classes/registry.js +47 -0
- package/core/{repository.d.ts → classes/repository.d.ts} +69 -20
- package/core/{repository.js → classes/repository.js} +195 -75
- package/core/classes/service.d.ts +49 -0
- package/core/classes/service.js +40 -0
- package/core/{version-scheme.d.ts → classes/version-scheme.d.ts} +23 -1
- package/core/{version-scheme.js → classes/version-scheme.js} +29 -1
- package/core/classes/workspace.d.ts +275 -0
- package/core/classes/workspace.js +537 -0
- package/core/command-builder.d.ts +14 -0
- package/core/command-builder.js +94 -0
- package/core/config/config-file-scope.d.ts +107 -0
- package/core/config/config-file-scope.js +226 -0
- package/core/config/config-interpolator.d.ts +164 -0
- package/core/config/config-interpolator.js +577 -0
- package/core/config/config-paths.d.ts +65 -0
- package/core/config/config-paths.js +78 -0
- package/core/config/config-reader.d.ts +192 -0
- package/core/config/config-reader.js +727 -0
- package/core/{merge-config.d.ts → config/merge-config.d.ts} +33 -34
- package/core/config/merge-config.js +260 -0
- package/core/{resolve-target.d.ts → config/resolve-config-target.d.ts} +1 -1
- package/core/{resolve-target.js → config/resolve-config-target.js} +1 -1
- package/core/{custom-command.d.ts → interfaces/custom-command.d.ts} +46 -10
- package/core/{custom-command.js → interfaces/custom-command.js} +44 -17
- package/core/{manifest.d.ts → interfaces/manifest.d.ts} +49 -27
- package/core/interfaces/manifest.js +132 -0
- package/core/interfaces/plugin.d.ts +174 -0
- package/core/interfaces/plugin.js +124 -0
- package/core/interfaces/publish-target.d.ts +136 -0
- package/core/interfaces/publish-target.js +43 -0
- package/core/{run-step.d.ts → interfaces/run-step.d.ts} +4 -4
- package/core/interfaces/run-step.js +1 -0
- package/core/plugin-loader.d.ts +25 -0
- package/core/plugin-loader.js +53 -0
- package/index.d.ts +122 -24
- package/index.js +66 -16
- package/interfaces/config-scope.interface.d.ts +223 -0
- package/interfaces/config-scope.interface.js +1 -0
- package/interfaces/rman-config.interface.d.ts +821 -203
- package/interfaces/rman-config.interface.js +78 -1
- package/package.json +3 -1
- package/services/change-hash.service.d.ts +42 -8
- package/services/change-hash.service.js +92 -13
- package/services/changelog.service.d.ts +91 -52
- package/services/changelog.service.js +460 -74
- package/services/config-service.d.ts +8 -0
- package/services/config-service.js +3 -0
- package/services/exec.service.d.ts +23 -12
- package/services/exec.service.js +14 -9
- package/services/github-release.service.d.ts +45 -34
- package/services/github-release.service.js +15 -12
- package/services/import.service.d.ts +25 -14
- package/services/import.service.js +9 -5
- package/services/list.service.d.ts +67 -13
- package/services/list.service.js +62 -15
- package/services/run.service.d.ts +35 -22
- package/services/run.service.js +316 -233
- package/services/system-info.d.ts +1 -1
- package/services/version-plan.service.d.ts +35 -8
- package/services/version-plan.service.js +96 -36
- package/services/version.service.d.ts +34 -14
- package/services/version.service.js +35 -16
- package/services.d.ts +1 -1
- package/services.js +1 -1
- package/utils/bin-path.d.ts +6 -7
- package/utils/bin-path.js +7 -18
- package/utils/branch-guard.d.ts +30 -1
- package/utils/branch-guard.js +31 -0
- package/utils/color-yaml.d.ts +8 -0
- package/utils/color-yaml.js +86 -0
- package/utils/exec.d.ts +10 -0
- package/utils/exec.js +1 -1
- package/utils/git.d.ts +26 -0
- package/utils/git.js +65 -0
- package/utils/logger.d.ts +2 -2
- package/utils/logger.js +1 -1
- package/utils/package-filter.d.ts +135 -8
- package/utils/package-filter.js +204 -16
- package/utils/printable-config.d.ts +9 -1
- package/utils/printable-config.js +46 -1
- package/utils/progress-panel.d.ts +9 -0
- package/utils/progress-panel.js +23 -1
- package/utils/release-version.d.ts +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-group.d.ts +31 -0
- package/utils/version-group.js +43 -0
- package/utils/version-stamp.d.ts +1 -1
- package/utils/version-stamp.js +1 -1
- package/commands/changed.command.d.ts +0 -3
- package/commands/changed.command.js +0 -29
- package/core/config.d.ts +0 -409
- package/core/config.js +0 -939
- package/core/extends-config.d.ts +0 -27
- package/core/extends-config.js +0 -89
- package/core/manifest.js +0 -150
- package/core/merge-config.js +0 -219
- package/core/package.d.ts +0 -83
- package/core/package.js +0 -106
- package/core/plugin.d.ts +0 -112
- package/core/plugin.js +0 -189
- package/core/workspace.d.ts +0 -68
- package/core/workspace.js +0 -83
- /package/{core/run-step.js → builtins/platforms/node/augmentation/rmanrc.augmentation.js} +0 -0
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
1
|
+
import { RmanApplication } from '../application.js';
|
|
2
|
+
import type { Package } from '../classes/package.js';
|
|
3
|
+
import { type VersionScheme } from '../classes/version-scheme.js';
|
|
4
|
+
import type { Platform } from './plugin.js';
|
|
3
5
|
/**
|
|
4
6
|
* A package's identity, however its ecosystem happens to record it.
|
|
5
7
|
*
|
|
@@ -13,7 +15,7 @@ export interface Manifest {
|
|
|
13
15
|
/** Excluded from publishing by the package's own declaration (`package.json#private`). Not the
|
|
14
16
|
* same as `.rmanrc "publish.skip"`, which is the *repository's* declaration about it. */
|
|
15
17
|
private?: boolean;
|
|
16
|
-
/** The document as the ecosystem wrote it. `
|
|
18
|
+
/** The document as the ecosystem wrote it. The `node` built-in's own commands read `package.json` fields
|
|
17
19
|
* the core has no opinion about (`scripts`, `publishConfig`, `engines`) off this. */
|
|
18
20
|
raw: any;
|
|
19
21
|
}
|
|
@@ -23,7 +25,7 @@ export interface Manifest {
|
|
|
23
25
|
* **The core has no provider.** "The name and version live in a `package.json`" is true of npm and
|
|
24
26
|
* of nothing else - a `Cargo.toml`, a `pyproject.toml` and a `go.mod` each say the same thing
|
|
25
27
|
* differently, and the version is not even in the same *kind* of place in all of them.
|
|
26
|
-
* `
|
|
28
|
+
* The `node` built-in contributes the `package.json` one.
|
|
27
29
|
*
|
|
28
30
|
* Paired with `VersionScheme` on purpose: the ecosystem that decides *where* a version is written
|
|
29
31
|
* is the one that decides *how* it is numbered, so a provider supplies both and a package gets a
|
|
@@ -32,7 +34,7 @@ export interface Manifest {
|
|
|
32
34
|
export interface ManifestProvider {
|
|
33
35
|
/**
|
|
34
36
|
* **The ecosystem this provider speaks for**, surfaced on every package it reads as
|
|
35
|
-
* `Package.provider` - `'node'` for
|
|
37
|
+
* `Package.provider` - `'node'` for the built-in of that name. Short and about the technology, not about the
|
|
36
38
|
* file: `fileName` already says `package.json`, and a name repeating it would tell a caller
|
|
37
39
|
* nothing it did not have.
|
|
38
40
|
*
|
|
@@ -124,6 +126,23 @@ export interface ManifestProvider {
|
|
|
124
126
|
scope?: string;
|
|
125
127
|
unscopedName: string;
|
|
126
128
|
};
|
|
129
|
+
/**
|
|
130
|
+
* **What addresses this package** - what a `"[glob]"` block and `--scope`/`--ignore` match
|
|
131
|
+
* against, and what has to be unique within a repository.
|
|
132
|
+
*
|
|
133
|
+
* **The platform's job, because a name is an ecosystem's promise and not rman's.** npm guarantees
|
|
134
|
+
* `package.json#name` exists and identifies the package, so the node built-in has nothing to do
|
|
135
|
+
* here and the default - the manifest's own name - is already its answer. An ecosystem where a
|
|
136
|
+
* package need not be named, or where the name is not unique, returns `undefined` and the
|
|
137
|
+
* repository assigns one with `.rmanrc "name"`.
|
|
138
|
+
*
|
|
139
|
+
* Separate from `Manifest.name`, which is what the package *calls itself*: those coincide for npm
|
|
140
|
+
* and need not anywhere else. A Go module's name is an import path, and `--scope github.com/x/y`
|
|
141
|
+
* is not how anyone would want to address it.
|
|
142
|
+
*
|
|
143
|
+
* Omit it and the manifest's name is used, so this seam existing changes nothing.
|
|
144
|
+
*/
|
|
145
|
+
selector?(manifest: Manifest, dir: string): string | undefined;
|
|
127
146
|
/**
|
|
128
147
|
* Rewrites this manifest's references to in-repo packages that just got a new version.
|
|
129
148
|
*
|
|
@@ -147,35 +166,37 @@ export interface ManifestProvider {
|
|
|
147
166
|
*
|
|
148
167
|
* A namespace rather than loose `addManifestProvider`/`readManifest` functions because a namespace
|
|
149
168
|
* is what a plugin can *augment*: `declare module 'rman' { namespace Manifest { ... } }` is how
|
|
150
|
-
* `
|
|
169
|
+
* the `node` built-in already adds to `SystemInfo`, and anything this seam grows later can arrive the
|
|
151
170
|
* same way instead of as another top-level export.
|
|
152
171
|
*/
|
|
153
172
|
export declare namespace Manifest {
|
|
154
|
-
/** Registers a provider. Called by `loadPlugins` for each plugin's `manifest`, in `plugins`
|
|
155
|
-
* declaration order - so which one answers is a function of the repository's own config. */
|
|
156
|
-
function addProvider(provider: ManifestProvider): void;
|
|
157
|
-
/** For tests, which would otherwise leak a provider into every later case in the process. */
|
|
158
|
-
function clearProviders(): void;
|
|
159
173
|
/**
|
|
160
|
-
* Reads `dir`'s manifest through the
|
|
161
|
-
*
|
|
162
|
-
*
|
|
163
|
-
* **
|
|
164
|
-
*
|
|
165
|
-
*
|
|
166
|
-
*
|
|
167
|
-
* `
|
|
168
|
-
*
|
|
174
|
+
* Reads `dir`'s manifest through **the platform that already claimed it**, with the scheme that
|
|
175
|
+
* platform brings.
|
|
176
|
+
*
|
|
177
|
+
* **It takes a platform rather than searching for one**, and that is where the walk changed
|
|
178
|
+
* things. This used to loop over every registered platform, once per `Package` constructed - so a
|
|
179
|
+
* package asked "who am I?" and the answer was whoever recognized it first, re-derived at every
|
|
180
|
+
* construction. The walk decides it once per directory now (`Workspace.walk` ->
|
|
181
|
+
* `app.platformFor`) and hands it to the package, which is also what lets a nested Cargo package
|
|
182
|
+
* sit inside a Node monorepo: the platform is a fact about the directory, established by whoever
|
|
183
|
+
* found it, not re-guessed by whoever reads it.
|
|
184
|
+
*
|
|
185
|
+
* **When that platform reads nothing** - `basePlatform`, or a provider that claimed the directory
|
|
186
|
+
* and then found nothing in it - the fallback is a package named after its own directory at
|
|
187
|
+
* version `0.0.0`. Deliberately the least it can claim: the directory name is a fact, and `0.0.0`
|
|
188
|
+
* is the version a thing has when nothing says otherwise. The alternative - refusing to construct
|
|
189
|
+
* a package at all - would make `rman info` and `rman list` fail in a repository whose `.rmanrc`
|
|
190
|
+
* simply names no plugin yet, which is exactly when someone needs to run them.
|
|
169
191
|
*/
|
|
170
|
-
function read(dir: string): {
|
|
192
|
+
function read(platform: Platform, dir: string): {
|
|
171
193
|
manifest: Manifest;
|
|
172
194
|
versionScheme: VersionScheme;
|
|
173
195
|
fileName: string;
|
|
174
|
-
provider: string;
|
|
175
196
|
};
|
|
176
197
|
/** Writes through whichever provider recognizes `dir`. Throws when none does: a write that lands
|
|
177
198
|
* nowhere is worse than one that fails, since the caller has already decided the new version. */
|
|
178
|
-
function write(dir: string, manifest: Manifest): void;
|
|
199
|
+
function write(app: RmanApplication, dir: string, manifest: Manifest): void;
|
|
179
200
|
/**
|
|
180
201
|
* The packages `pkg` declares a dependency on, via whichever provider recognizes it.
|
|
181
202
|
*
|
|
@@ -186,7 +207,7 @@ export declare namespace Manifest {
|
|
|
186
207
|
function dependenciesOf(pkg: Package, candidates: readonly Package[]): Package[];
|
|
187
208
|
/** `${{ pkg.scope }}`/`${{ pkg.unscopedName }}`, by whichever provider recognizes `dir` - and
|
|
188
209
|
* "no scope, the name is its own unscoped form" when none has an opinion. */
|
|
189
|
-
function splitName(dir: string, name: string): {
|
|
210
|
+
function splitName(app: RmanApplication, dir: string, name: string): {
|
|
190
211
|
scope?: string;
|
|
191
212
|
unscopedName: string;
|
|
192
213
|
};
|
|
@@ -199,7 +220,7 @@ export declare namespace Manifest {
|
|
|
199
220
|
function updateDependencyVersions(pkg: Package, bumped: ReadonlyMap<Package, string>): void;
|
|
200
221
|
/**
|
|
201
222
|
* Rewrites a hard-coded version in `content` through `pkg`'s own ecosystem - see
|
|
202
|
-
* `
|
|
223
|
+
* `Plugin.stampVersion`.
|
|
203
224
|
*
|
|
204
225
|
* `undefined` covers three cases the caller has to tell apart from each other, and cannot: no
|
|
205
226
|
* provider claimed the package, the provider has no opinion about stamping, or it looked and found
|
|
@@ -217,6 +238,7 @@ export declare namespace Manifest {
|
|
|
217
238
|
* plugin: git tags then answer the boundary question alone.
|
|
218
239
|
*/
|
|
219
240
|
function publishedVersion(pkg: Package): Promise<string | undefined>;
|
|
220
|
-
/** The file names
|
|
221
|
-
|
|
241
|
+
/** The file names the registered technologies look for, for an error message that can say what
|
|
242
|
+
* was expected. */
|
|
243
|
+
function fileNames(app: RmanApplication): string[];
|
|
222
244
|
}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { RmanApplication } from '../application.js';
|
|
3
|
+
import { semverScheme } from '../classes/version-scheme.js';
|
|
4
|
+
/**
|
|
5
|
+
* The registry, merged onto the `Manifest` interface so one name carries both the shape and the
|
|
6
|
+
* operations - `Manifest.read(dir)` returns a `Manifest`.
|
|
7
|
+
*
|
|
8
|
+
* A namespace rather than loose `addManifestProvider`/`readManifest` functions because a namespace
|
|
9
|
+
* is what a plugin can *augment*: `declare module 'rman' { namespace Manifest { ... } }` is how
|
|
10
|
+
* the `node` built-in already adds to `SystemInfo`, and anything this seam grows later can arrive the
|
|
11
|
+
* same way instead of as another top-level export.
|
|
12
|
+
*/
|
|
13
|
+
export var Manifest;
|
|
14
|
+
(function (Manifest) {
|
|
15
|
+
/**
|
|
16
|
+
* Reads `dir`'s manifest through **the platform that already claimed it**, with the scheme that
|
|
17
|
+
* platform brings.
|
|
18
|
+
*
|
|
19
|
+
* **It takes a platform rather than searching for one**, and that is where the walk changed
|
|
20
|
+
* things. This used to loop over every registered platform, once per `Package` constructed - so a
|
|
21
|
+
* package asked "who am I?" and the answer was whoever recognized it first, re-derived at every
|
|
22
|
+
* construction. The walk decides it once per directory now (`Workspace.walk` ->
|
|
23
|
+
* `app.platformFor`) and hands it to the package, which is also what lets a nested Cargo package
|
|
24
|
+
* sit inside a Node monorepo: the platform is a fact about the directory, established by whoever
|
|
25
|
+
* found it, not re-guessed by whoever reads it.
|
|
26
|
+
*
|
|
27
|
+
* **When that platform reads nothing** - `basePlatform`, or a provider that claimed the directory
|
|
28
|
+
* and then found nothing in it - the fallback is a package named after its own directory at
|
|
29
|
+
* version `0.0.0`. Deliberately the least it can claim: the directory name is a fact, and `0.0.0`
|
|
30
|
+
* is the version a thing has when nothing says otherwise. The alternative - refusing to construct
|
|
31
|
+
* a package at all - would make `rman info` and `rman list` fail in a repository whose `.rmanrc`
|
|
32
|
+
* simply names no plugin yet, which is exactly when someone needs to run them.
|
|
33
|
+
*/
|
|
34
|
+
function read(platform, dir) {
|
|
35
|
+
const provider = platform.manifestProvider;
|
|
36
|
+
const manifest = provider.read(dir);
|
|
37
|
+
return {
|
|
38
|
+
manifest: manifest ?? { name: path.basename(dir), version: '0.0.0', raw: {} },
|
|
39
|
+
versionScheme: provider.versionScheme ?? semverScheme,
|
|
40
|
+
/** Nothing read means nothing to name - a caller listing "the file I changed" has no file to
|
|
41
|
+
* list, which is correct rather than a placeholder that does not exist. */
|
|
42
|
+
fileName: manifest ? provider.fileName : '',
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
Manifest.read = read;
|
|
46
|
+
/** Writes through whichever provider recognizes `dir`. Throws when none does: a write that lands
|
|
47
|
+
* nowhere is worse than one that fails, since the caller has already decided the new version. */
|
|
48
|
+
function write(app, dir, manifest) {
|
|
49
|
+
for (const platform of app.platforms) {
|
|
50
|
+
if (platform.manifestProvider.read(dir)) {
|
|
51
|
+
platform.manifestProvider.write(dir, manifest);
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
throw new Error(`No manifest provider recognizes "${dir}", so there is nowhere to write its version.\n` +
|
|
56
|
+
` A repository's ".rmanrc" names its technologies - see "plugins" (e.g. ['node']).`);
|
|
57
|
+
}
|
|
58
|
+
Manifest.write = write;
|
|
59
|
+
/**
|
|
60
|
+
* The packages `pkg` declares a dependency on, via whichever provider recognizes it.
|
|
61
|
+
*
|
|
62
|
+
* No provider, or one with no opinion, means no declared dependencies - `.rmanrc "dependencies"`
|
|
63
|
+
* is then the only source, which is exactly right: a repository rman cannot read the manifests
|
|
64
|
+
* of can still describe its own graph by hand.
|
|
65
|
+
*/
|
|
66
|
+
function dependenciesOf(pkg, candidates) {
|
|
67
|
+
return platformOf(pkg)?.manifestProvider.dependencies?.(pkg.manifest, candidates) ?? [];
|
|
68
|
+
}
|
|
69
|
+
Manifest.dependenciesOf = dependenciesOf;
|
|
70
|
+
/** `${{ pkg.scope }}`/`${{ pkg.unscopedName }}`, by whichever provider recognizes `dir` - and
|
|
71
|
+
* "no scope, the name is its own unscoped form" when none has an opinion. */
|
|
72
|
+
function splitName(app, dir, name) {
|
|
73
|
+
for (const platform of app.platforms) {
|
|
74
|
+
if (!platform.manifestProvider.read(dir))
|
|
75
|
+
continue;
|
|
76
|
+
return platform.manifestProvider.splitName?.(name) ?? { unscopedName: name };
|
|
77
|
+
}
|
|
78
|
+
return { unscopedName: name };
|
|
79
|
+
}
|
|
80
|
+
Manifest.splitName = splitName;
|
|
81
|
+
/**
|
|
82
|
+
* Refreshes `pkg`'s references to the packages in `bumped`, via whichever provider recognizes it.
|
|
83
|
+
*
|
|
84
|
+
* No provider, or one without an opinion, means nothing to rewrite - a repository whose packages
|
|
85
|
+
* reference each other by path has nothing here to go stale.
|
|
86
|
+
*/
|
|
87
|
+
function updateDependencyVersions(pkg, bumped) {
|
|
88
|
+
platformOf(pkg)?.manifestProvider.updateDependencyVersions?.(pkg.manifest, bumped);
|
|
89
|
+
}
|
|
90
|
+
Manifest.updateDependencyVersions = updateDependencyVersions;
|
|
91
|
+
/**
|
|
92
|
+
* Rewrites a hard-coded version in `content` through `pkg`'s own ecosystem - see
|
|
93
|
+
* `Plugin.stampVersion`.
|
|
94
|
+
*
|
|
95
|
+
* `undefined` covers three cases the caller has to tell apart from each other, and cannot: no
|
|
96
|
+
* provider claimed the package, the provider has no opinion about stamping, or it looked and found
|
|
97
|
+
* nothing to change. All three mean "this file was not stamped", which is what `version` reports.
|
|
98
|
+
*/
|
|
99
|
+
function stampVersion(pkg, file, content, version, options) {
|
|
100
|
+
return platformOf(pkg)?.manifestProvider.stampVersion?.(file, content, version, options);
|
|
101
|
+
}
|
|
102
|
+
Manifest.stampVersion = stampVersion;
|
|
103
|
+
/**
|
|
104
|
+
* What `pkg`'s own ecosystem's registry says its current version is - see
|
|
105
|
+
* `ManifestProvider.publishedVersion` for the one thing this is for and the one thing it must
|
|
106
|
+
* never be used for.
|
|
107
|
+
*
|
|
108
|
+
* `undefined` when the provider has no opinion, which includes every repository that names no
|
|
109
|
+
* plugin: git tags then answer the boundary question alone.
|
|
110
|
+
*/
|
|
111
|
+
async function publishedVersion(pkg) {
|
|
112
|
+
return platformOf(pkg)?.manifestProvider.publishedVersion?.(pkg);
|
|
113
|
+
}
|
|
114
|
+
Manifest.publishedVersion = publishedVersion;
|
|
115
|
+
/** The file names the registered technologies look for, for an error message that can say what
|
|
116
|
+
* was expected. */
|
|
117
|
+
function fileNames(app) {
|
|
118
|
+
return [...app.platforms].map(platform => platform.manifestProvider.fileName);
|
|
119
|
+
}
|
|
120
|
+
Manifest.fileNames = fileNames;
|
|
121
|
+
/**
|
|
122
|
+
* The technology that claimed `pkg`, or `undefined` when none did - with nothing to look up.
|
|
123
|
+
*
|
|
124
|
+
* This used to search a registry by `pkg.provider` and fall back to re-reading the directory,
|
|
125
|
+
* because a package could be constructed before the provider that would claim it was registered.
|
|
126
|
+
* It cannot now: a package is handed its `Platform` at construction, by the application that
|
|
127
|
+
* resolved it. The `name` test is what "none claimed it" looks like - see `basePlatform`.
|
|
128
|
+
*/
|
|
129
|
+
function platformOf(pkg) {
|
|
130
|
+
return pkg.platform.name ? pkg.platform : undefined;
|
|
131
|
+
}
|
|
132
|
+
})(Manifest || (Manifest = {}));
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
import type { RunService } from '../../services/run.service.js';
|
|
2
|
+
import type { VersionPlanService } from '../../services/version-plan.service.js';
|
|
3
|
+
import type { BinPath } from '../../utils/bin-path.js';
|
|
4
|
+
import type { RmanApplication } from '../application.js';
|
|
5
|
+
import type { Repository } from '../classes/repository.js';
|
|
6
|
+
import type { Workspace } from '../classes/workspace.js';
|
|
7
|
+
import type { ManifestProvider } from './manifest.js';
|
|
8
|
+
/**
|
|
9
|
+
* **One technology, as a whole** - Node, Cargo, Maven. Everything rman needs in order to treat a
|
|
10
|
+
* directory as a package of that technology.
|
|
11
|
+
*
|
|
12
|
+
* **This was called `Plugin`, and the name was a lie.** `manifestProvider` is required, which makes
|
|
13
|
+
* the type a *platform* by definition: a package that only ships commands never touches it, because
|
|
14
|
+
* commands are a config key. So the narrow thing took the narrow name, and `Plugin` became the
|
|
15
|
+
* broad one that may carry platforms - a plugin *provides* platforms, and may provide more than
|
|
16
|
+
* one (a package shipping both `maven` and `gradle` is one plugin, two platforms).
|
|
17
|
+
*
|
|
18
|
+
* These were six independent fields on a plugin, each with its own registry, and declaring one
|
|
19
|
+
* without the others type-checked. It is not a shape that admits sense: `getRunSteps` reads
|
|
20
|
+
* `pkg.manifest.raw?.scripts`, so contributing npm's step source without npm's manifest reader
|
|
21
|
+
* leaves it parsing whatever another technology produced. The coupling was already real; only the
|
|
22
|
+
* type failed to say so.
|
|
23
|
+
*
|
|
24
|
+
* **`RmanPlugin` and `TechStack` used to be two types and are now one.** The plugin existed solely to
|
|
25
|
+
* *register* the stack - its whole `init` was `ctx.addTechStack(...)` plus a command or two - and
|
|
26
|
+
* once a config carries commands and publish targets itself, that registration step has nothing
|
|
27
|
+
* left to do. What remains of a plugin is the technology, so that is what the type is.
|
|
28
|
+
*
|
|
29
|
+
* **`manifestProvider` stays grouped rather than flattened in here**, and it was tried the other
|
|
30
|
+
* way first: nine members about one file - reading it, writing it, what it declares, how its
|
|
31
|
+
* versions are numbered, stamped and looked up on a registry - are more legible as a named group
|
|
32
|
+
* than as nine siblings of `getBinPaths`. The name also keeps its distance from `Package.manifest`,
|
|
33
|
+
* which is the *data* this produces rather than the reader.
|
|
34
|
+
*
|
|
35
|
+
* **Everything optional is answered by its absence**, never by a default rman invented - see
|
|
36
|
+
* `basePlatform`.
|
|
37
|
+
*/
|
|
38
|
+
export interface Platform {
|
|
39
|
+
/**
|
|
40
|
+
* **The ecosystem this speaks for**, surfaced on every package it reads as `Package.platform` -
|
|
41
|
+
* `'node'` for the built-in of that name. Short and about the technology, not about the file:
|
|
42
|
+
* `manifestProvider.fileName` already says `package.json`, and a name repeating it would tell a
|
|
43
|
+
* caller nothing it did not have.
|
|
44
|
+
*
|
|
45
|
+
* This is what lets code that *does* know one ecosystem check before acting on a package -
|
|
46
|
+
* `if (pkg.platform === 'node')` - which matters most in a repository holding more than one,
|
|
47
|
+
* since a manifest is read per directory and two packages can legitimately answer to different
|
|
48
|
+
* technologies. It is also the de-duplication key: registering twice under one name is refused,
|
|
49
|
+
* because it would define the same commands twice and yargs does not survive that.
|
|
50
|
+
*/
|
|
51
|
+
name: string;
|
|
52
|
+
/** Where this technology's packages keep their identity, and how to change it - reading and
|
|
53
|
+
* writing the manifest, what it declares as dependencies, how its versions are numbered,
|
|
54
|
+
* stamped, and looked up on a registry. */
|
|
55
|
+
manifestProvider: ManifestProvider;
|
|
56
|
+
/** Where this technology's packages are, given the repository root - npm reads `workspaces`,
|
|
57
|
+
* Cargo a `[workspace] members`. `undefined` when it does not recognize the root. */
|
|
58
|
+
getWorkspace?: Workspace.Provider;
|
|
59
|
+
/** Directories to put in front of a child process's PATH, so a command an author wrote
|
|
60
|
+
* (`eslint .`) runs the repository's pinned copy - `node_modules/.bin` walked up the tree, for
|
|
61
|
+
* npm. Every plugin contributes, unlike the seams above where the first answer wins: a PATH is
|
|
62
|
+
* a list, and a polyglot repository wants both ecosystems' binaries reachable. */
|
|
63
|
+
getBinPaths?: BinPath.Provider;
|
|
64
|
+
/**
|
|
65
|
+
* What the *package itself* declares for a lifecycle script, from this technology's own files -
|
|
66
|
+
* npm's `package.json` `scripts`, with `pre<script>`/`<script>`/`post<script>`.
|
|
67
|
+
*
|
|
68
|
+
* **A query, not a hook, and not build-specific** - which is why it is `getRunSteps` rather than
|
|
69
|
+
* anything beginning `on`. It returns what the package declares and rman decides what to do with
|
|
70
|
+
* it; `run`/`build`/`test` ask, and so does `version`, whose `preversion`/`version`/`postversion`
|
|
71
|
+
* are the same shape (`runLifecycleSlot` -> `contributedSlots`). A name mentioning `build` would
|
|
72
|
+
* have been wrong about half its callers.
|
|
73
|
+
*/
|
|
74
|
+
getRunSteps?: RunService.StepSource;
|
|
75
|
+
/** How this technology's releases are planned - where a package's change boundary comes from
|
|
76
|
+
* when it has no release tag, and how far into its group a bump reaches. */
|
|
77
|
+
versionPlanner?: VersionPlanService;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* **A plugin is whatever a package contributes; a platform is one of the things it can contribute.**
|
|
81
|
+
*
|
|
82
|
+
* The broad half of the split. `Platform` is a technology and nothing else - required manifest
|
|
83
|
+
* reader, workspace layout, bin paths, steps, version planning. What is left over is this: an
|
|
84
|
+
* `init` for whatever the seams do not name yet, and the **declaration** that this plugin provides
|
|
85
|
+
* platforms.
|
|
86
|
+
*
|
|
87
|
+
* **`platforms` is a list, and that is not symmetry.** One package can speak for more than one
|
|
88
|
+
* technology - `maven` and `gradle` are the same toolchain family and a single plugin shipping both
|
|
89
|
+
* is the natural shape. A singular field would have made the second one a separate package for no
|
|
90
|
+
* reason.
|
|
91
|
+
*
|
|
92
|
+
* A bare `Platform` is accepted anywhere a `Plugin` is, as sugar for `{ name, platforms: [it] }` -
|
|
93
|
+
* which is what almost every entry is.
|
|
94
|
+
*/
|
|
95
|
+
export interface Plugin {
|
|
96
|
+
/** How this plugin is named in messages, and the de-duplication key: registering twice under one
|
|
97
|
+
* name is refused. */
|
|
98
|
+
name: string;
|
|
99
|
+
/**
|
|
100
|
+
* Run once the application exists and this plugin is on it, **before anything has been
|
|
101
|
+
* discovered** - no packages, no configs, no repository.
|
|
102
|
+
*
|
|
103
|
+
* This is where a plugin registers what the config keys have no word for: a service, a seam the
|
|
104
|
+
* core does not name yet. Reached through `ctx.app`.
|
|
105
|
+
*/
|
|
106
|
+
afterInitApplication?(ctx: PluginContext): void | Promise<void>;
|
|
107
|
+
/**
|
|
108
|
+
* Run once the repository is **resolved** - every package found, every config baked, the
|
|
109
|
+
* dependency graph linked.
|
|
110
|
+
*
|
|
111
|
+
* The stage `afterInitApplication` cannot reach: that one runs inside `Repository.create` before
|
|
112
|
+
* any package is known, so `ctx.app.repository` throws there.
|
|
113
|
+
*/
|
|
114
|
+
afterInitRepository?(ctx: PluginRepositoryContext): void | Promise<void>;
|
|
115
|
+
}
|
|
116
|
+
export declare namespace Plugin {
|
|
117
|
+
/** What a value was declared as - see {@link declaredKind}. */
|
|
118
|
+
type DeclaredKind = 'platform' | 'plugin';
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* What {@link Plugin.afterInitApplication} is handed.
|
|
122
|
+
*
|
|
123
|
+
* An object rather than a bare parameter so a member added later breaks nothing already written
|
|
124
|
+
* against it - the same reason `CommandContext` is one, which has already paid for itself twice.
|
|
125
|
+
*/
|
|
126
|
+
export interface PluginContext {
|
|
127
|
+
app: RmanApplication;
|
|
128
|
+
}
|
|
129
|
+
/** What {@link Plugin.afterInitRepository} is handed - the application, plus the repository that now
|
|
130
|
+
* exists. */
|
|
131
|
+
export interface PluginRepositoryContext extends PluginContext {
|
|
132
|
+
repository: Repository;
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* **What `value` was declared as**, or `undefined` for anything that was not - a plain object, an
|
|
136
|
+
* arbitrary module export, a config.
|
|
137
|
+
*/
|
|
138
|
+
export declare function declaredKind(value: unknown): Plugin.DeclaredKind | undefined;
|
|
139
|
+
/** Whether `value` came from `definePlatform` or `definePlugin`. */
|
|
140
|
+
export declare function isDeclared(value: unknown): boolean;
|
|
141
|
+
/** Declares a **platform** - one technology, whole. Returns it unchanged apart from the mark. */
|
|
142
|
+
export declare function definePlatform(platform: Platform): Platform;
|
|
143
|
+
/** Declares a **plugin** - a name and whatever it wants to do at one of the two stages. Returns
|
|
144
|
+
* it unchanged apart from the mark. */
|
|
145
|
+
export declare function definePlugin(plugin: Plugin): Plugin;
|
|
146
|
+
/**
|
|
147
|
+
* Whether `value` is a platform - **what it was declared as**, not what it looks like.
|
|
148
|
+
*/
|
|
149
|
+
export declare function isPlatform(value: unknown): value is Platform;
|
|
150
|
+
/** Whether `value` is a plugin - again by declaration, so a platform is not one. */
|
|
151
|
+
export declare function isPlugin(value: unknown): value is Plugin;
|
|
152
|
+
/**
|
|
153
|
+
* The platform a package gets when **none** claimed its directory - a repository naming no
|
|
154
|
+
* platform, or a directory none of the named ones recognized.
|
|
155
|
+
*
|
|
156
|
+
* It exists so `Package.platform` need not be optional. `Package.provider` was an empty string for
|
|
157
|
+
* exactly this case, and every reader had to know that; an object with an empty `name` says the
|
|
158
|
+
* same thing without a guard, and `pkg.provider === 'node'` - the check CLAUDE.md prescribes -
|
|
159
|
+
* reads the same either way.
|
|
160
|
+
*
|
|
161
|
+
* **Every documented behaviour of "no plugin" survives unchanged**, because the absences are the
|
|
162
|
+
* behaviour:
|
|
163
|
+
*
|
|
164
|
+
* - a reader that recognizes nothing -> `Manifest.read` falls through to its own empty manifest,
|
|
165
|
+
* exactly as it does when no plugin answers;
|
|
166
|
+
* - no `getWorkspace` -> a repository naming no plugin has no packages beyond itself, which is the
|
|
167
|
+
* boundary working rather than failing (`workspaces` in a `package.json` is npm's idea);
|
|
168
|
+
* - no `getBinPaths` -> nothing is prepended to a child process's PATH, so the inherited one
|
|
169
|
+
* stands on its own rather than being guessed at;
|
|
170
|
+
* - no `getRunSteps` -> a package's steps come from its `.rmanrc` alone, the core's only source;
|
|
171
|
+
* - no `versionPlanner` -> `version`/`changed` fail naming the key, rather than releasing a
|
|
172
|
+
* plausible but untrue set of packages from a default nobody chose.
|
|
173
|
+
*/
|
|
174
|
+
export declare const basePlatform: Platform;
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* **What `value` was declared as**, or `undefined` for anything that was not - a plain object, an
|
|
3
|
+
* arbitrary module export, a config.
|
|
4
|
+
*/
|
|
5
|
+
/* **One mark carrying the kind, rather than one mark per type.** The mark used to be `true`, so it
|
|
6
|
+
* could answer *whether* something was declared and never *what* - which left `isPlatform` testing
|
|
7
|
+
* for `manifestProvider`, a structural guess, and left the loader unable to say the one useful
|
|
8
|
+
* thing about the commonest mistake: that a platform was put in `plugins`.
|
|
9
|
+
*
|
|
10
|
+
* A symbol per type was the alternative and this is the same information for less machinery. The
|
|
11
|
+
* key has to be a **hoisted function** (see `declaredKey`), which is a trap every additional key
|
|
12
|
+
* would repeat; `isDeclared` stays one lookup instead of an OR someone has to remember to extend;
|
|
13
|
+
* and a third declarable slots in as a new string - `publishTargets` is checked structurally today
|
|
14
|
+
* (`typeof target.name === 'string'`) and is the obvious next one, though nothing is being built
|
|
15
|
+
* for it here.
|
|
16
|
+
*
|
|
17
|
+
* **The value was `true` before this**, and `Symbol.for` is shared - so an object marked by an
|
|
18
|
+
* older copy of rman in the same process now reads as undeclared. 2.0 is unreleased and the mark
|
|
19
|
+
* is 2.x's own, so there is nothing in the field to be compatible with. */
|
|
20
|
+
export function declaredKind(value) {
|
|
21
|
+
if (!value || typeof value !== 'object')
|
|
22
|
+
return undefined;
|
|
23
|
+
const kind = value[declaredKey()];
|
|
24
|
+
return kind === 'platform' || kind === 'plugin' ? kind : undefined;
|
|
25
|
+
}
|
|
26
|
+
/** Whether `value` came from `definePlatform` or `definePlugin`. */
|
|
27
|
+
export function isDeclared(value) {
|
|
28
|
+
return declaredKind(value) !== undefined;
|
|
29
|
+
}
|
|
30
|
+
/** Declares a **platform** - one technology, whole. Returns it unchanged apart from the mark. */
|
|
31
|
+
export function definePlatform(platform) {
|
|
32
|
+
return brand(platform, 'platform');
|
|
33
|
+
}
|
|
34
|
+
/** Declares a **plugin** - a name and whatever it wants to do at one of the two stages. Returns
|
|
35
|
+
* it unchanged apart from the mark. */
|
|
36
|
+
export function definePlugin(plugin) {
|
|
37
|
+
return brand(plugin, 'plugin');
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Whether `value` is a platform - **what it was declared as**, not what it looks like.
|
|
41
|
+
*/
|
|
42
|
+
/* It used to ask whether `manifestProvider` was present, which was the only test available while
|
|
43
|
+
* one type was both halves. As a question about an arbitrary import that is a guess, and it gets
|
|
44
|
+
* the commonest mistake exactly backwards: a config object carrying a `manifestProvider`-shaped key
|
|
45
|
+
* would pass, and a platform someone forgot to declare would be reported as an rman 1.x plugin.
|
|
46
|
+
*
|
|
47
|
+
* The cost, stated: an undeclared platform-shaped object is no longer a platform. Everything
|
|
48
|
+
* arriving through a config has to be declared anyway, and every `registerPlugin` caller in the
|
|
49
|
+
* tree passes a `definePlatform(...)` result. */
|
|
50
|
+
export function isPlatform(value) {
|
|
51
|
+
return declaredKind(value) === 'platform';
|
|
52
|
+
}
|
|
53
|
+
/** Whether `value` is a plugin - again by declaration, so a platform is not one. */
|
|
54
|
+
export function isPlugin(value) {
|
|
55
|
+
return declaredKind(value) === 'plugin';
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* The platform a package gets when **none** claimed its directory - a repository naming no
|
|
59
|
+
* platform, or a directory none of the named ones recognized.
|
|
60
|
+
*
|
|
61
|
+
* It exists so `Package.platform` need not be optional. `Package.provider` was an empty string for
|
|
62
|
+
* exactly this case, and every reader had to know that; an object with an empty `name` says the
|
|
63
|
+
* same thing without a guard, and `pkg.provider === 'node'` - the check CLAUDE.md prescribes -
|
|
64
|
+
* reads the same either way.
|
|
65
|
+
*
|
|
66
|
+
* **Every documented behaviour of "no plugin" survives unchanged**, because the absences are the
|
|
67
|
+
* behaviour:
|
|
68
|
+
*
|
|
69
|
+
* - a reader that recognizes nothing -> `Manifest.read` falls through to its own empty manifest,
|
|
70
|
+
* exactly as it does when no plugin answers;
|
|
71
|
+
* - no `getWorkspace` -> a repository naming no plugin has no packages beyond itself, which is the
|
|
72
|
+
* boundary working rather than failing (`workspaces` in a `package.json` is npm's idea);
|
|
73
|
+
* - no `getBinPaths` -> nothing is prepended to a child process's PATH, so the inherited one
|
|
74
|
+
* stands on its own rather than being guessed at;
|
|
75
|
+
* - no `getRunSteps` -> a package's steps come from its `.rmanrc` alone, the core's only source;
|
|
76
|
+
* - no `versionPlanner` -> `version`/`changed` fail naming the key, rather than releasing a
|
|
77
|
+
* plausible but untrue set of packages from a default nobody chose.
|
|
78
|
+
*/
|
|
79
|
+
export const basePlatform = definePlatform({
|
|
80
|
+
name: '',
|
|
81
|
+
manifestProvider: {
|
|
82
|
+
name: '',
|
|
83
|
+
fileName: '',
|
|
84
|
+
/** Recognizes nothing, which is the point: `Manifest.read` falls through to its own empty
|
|
85
|
+
* manifest exactly as it does when no plugin answers. */
|
|
86
|
+
read: () => undefined,
|
|
87
|
+
write: () => undefined,
|
|
88
|
+
},
|
|
89
|
+
});
|
|
90
|
+
/**
|
|
91
|
+
* **Marks an object as declared through one of the factories below**, so `loadPlugins` can tell a
|
|
92
|
+
* 2.x contribution from anything else that happens to have the same shape.
|
|
93
|
+
*
|
|
94
|
+
* It exists for one measured case, and there is no structural check that could replace it: an rman
|
|
95
|
+
* **1.x plugin was `{ name, init }`**, and under this split a 2.x plugin that only runs an `init`
|
|
96
|
+
* is *also* `{ name, init }`. They are indistinguishable by shape. The guard used to be
|
|
97
|
+
* `manifestProvider` being required - which only worked while the one type was both halves.
|
|
98
|
+
*
|
|
99
|
+
* Non-enumerable, so it never reaches `JSON.stringify`, `rman config` or a `toEqual` diff, the same
|
|
100
|
+
* way `ORIGINS` and `PREVIOUS_VALUES` travel.
|
|
101
|
+
*
|
|
102
|
+
* The cost, stated rather than hidden: a plain object literal in `plugins` is no longer accepted.
|
|
103
|
+
* `definePlatform`/`definePlugin` is one import and one call, and it is the explicit declaration
|
|
104
|
+
* that a runtime check needs - a type cannot reach a JavaScript config.
|
|
105
|
+
*
|
|
106
|
+
* **A function rather than a `const`, and that is not a preference.** The file layout puts private
|
|
107
|
+
* declarations below the exported ones, and `basePlatform` is an exported const whose initializer
|
|
108
|
+
* *calls* `definePlatform` - so a `const DECLARED` below it sits in its temporal dead zone while the
|
|
109
|
+
* module is still evaluating. Measured: the whole suite failed to load with
|
|
110
|
+
* `ReferenceError: Cannot access 'DECLARED' before initialization`. A function declaration hoists,
|
|
111
|
+
* so the key is resolved when it is asked for instead of when the module reaches this line.
|
|
112
|
+
*
|
|
113
|
+
* **`Symbol.for`, so two copies of rman in one process agree about the mark.** A per-module symbol
|
|
114
|
+
* would have a plugin declared against one copy refused by the other - with a message about rman
|
|
115
|
+
* 1.x plugins, which is the one explanation guaranteed to be wrong.
|
|
116
|
+
*/
|
|
117
|
+
function declaredKey() {
|
|
118
|
+
return Symbol.for('rman.declared');
|
|
119
|
+
}
|
|
120
|
+
/** Stamps the mark, non-enumerably, and hands the object back. */
|
|
121
|
+
function brand(value, kind) {
|
|
122
|
+
Object.defineProperty(value, declaredKey(), { value: kind, enumerable: false, configurable: true });
|
|
123
|
+
return value;
|
|
124
|
+
}
|