rman 1.2.5 → 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 +180 -50
- package/core/config.js +332 -153
- 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 +138 -93
- 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 -43
- 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 +739 -212
- 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,49 @@
|
|
|
1
|
+
import type { Logger } from '../utils/logger.js';
|
|
2
|
+
import type { RmanApplication } from './application.js';
|
|
3
|
+
import type { Repository } from './repository.js';
|
|
4
|
+
/**
|
|
5
|
+
* **The one service shape.** Everything that does work on a repository is a class extending this,
|
|
6
|
+
* constructed once per `RmanApplication` and reached through `app.getService(name)`.
|
|
7
|
+
*
|
|
8
|
+
* rman's services were `export namespace` blocks, and the split between those and the two classes
|
|
9
|
+
* (`VersionPlanService`, `VersionScheme`) was historical rather than principled: whatever needed to
|
|
10
|
+
* be *extended* became a class, and the rest stayed a namespace. Three consequences, all of them
|
|
11
|
+
* measured in this repository:
|
|
12
|
+
*
|
|
13
|
+
* - **A namespace that needs state can only have global state.** `RunService` is a namespace and
|
|
14
|
+
* acquired three module-level variables - `stepSources` and two "already warned" sets - which is
|
|
15
|
+
* why a warning printed for one repository was suppressed for the next one in the same process.
|
|
16
|
+
* - **A namespace cannot be extended.** The two seams a plugin has to specialize
|
|
17
|
+
* (`NodeVersionPlanService extends VersionPlanService`) are precisely the two that are classes.
|
|
18
|
+
* - **A namespace has to be stubbed by mutating the module**, and CLAUDE.md records that failing:
|
|
19
|
+
* a spec that captured a core function at module scope and restored it put the *un-augmented*
|
|
20
|
+
* version back for the rest of the process and broke a spec two files away. An instance is
|
|
21
|
+
* rebuilt per application, so a stub dies with it.
|
|
22
|
+
*
|
|
23
|
+
* **`repository` is no longer a parameter.** Nearly every service method took it first; it now
|
|
24
|
+
* comes from the application, which is what made the argument redundant in the first place.
|
|
25
|
+
*
|
|
26
|
+
* Pure functions of their arguments stay plain exported functions rather than becoming services -
|
|
27
|
+
* `ConventionalCommitsService.parseSubject('feat: x')` parses a string and will never hold state,
|
|
28
|
+
* and making it `app.getService('conventionalCommits').parseSubject(...)` would be ceremony that
|
|
29
|
+
* also puts an application between a caller and a parser. The line is whether it needs the
|
|
30
|
+
* repository.
|
|
31
|
+
*/
|
|
32
|
+
export declare abstract class Service {
|
|
33
|
+
protected readonly app: RmanApplication;
|
|
34
|
+
constructor(app: RmanApplication);
|
|
35
|
+
protected get repository(): Repository;
|
|
36
|
+
protected get logger(): Logger;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Every service the application can hand out, by name.
|
|
40
|
+
*
|
|
41
|
+
* Declaration-merged, like `RmanConfigKeys`: the core declares its own here, and a plugin adds its
|
|
42
|
+
* own from its own package with `declare module 'rman'`. That is what keeps `getService` typed -
|
|
43
|
+
* a bare `Map<string, Service>` would need a cast at every call and would turn a misspelled name
|
|
44
|
+
* into a runtime failure instead of a compile error.
|
|
45
|
+
*/
|
|
46
|
+
export interface ServiceMap {
|
|
47
|
+
}
|
|
48
|
+
/** How a service is built when the application first needs it. */
|
|
49
|
+
export type ServiceFactory<T> = (app: RmanApplication) => T;
|
package/core/service.js
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* **The one service shape.** Everything that does work on a repository is a class extending this,
|
|
3
|
+
* constructed once per `RmanApplication` and reached through `app.getService(name)`.
|
|
4
|
+
*
|
|
5
|
+
* rman's services were `export namespace` blocks, and the split between those and the two classes
|
|
6
|
+
* (`VersionPlanService`, `VersionScheme`) was historical rather than principled: whatever needed to
|
|
7
|
+
* be *extended* became a class, and the rest stayed a namespace. Three consequences, all of them
|
|
8
|
+
* measured in this repository:
|
|
9
|
+
*
|
|
10
|
+
* - **A namespace that needs state can only have global state.** `RunService` is a namespace and
|
|
11
|
+
* acquired three module-level variables - `stepSources` and two "already warned" sets - which is
|
|
12
|
+
* why a warning printed for one repository was suppressed for the next one in the same process.
|
|
13
|
+
* - **A namespace cannot be extended.** The two seams a plugin has to specialize
|
|
14
|
+
* (`NodeVersionPlanService extends VersionPlanService`) are precisely the two that are classes.
|
|
15
|
+
* - **A namespace has to be stubbed by mutating the module**, and CLAUDE.md records that failing:
|
|
16
|
+
* a spec that captured a core function at module scope and restored it put the *un-augmented*
|
|
17
|
+
* version back for the rest of the process and broke a spec two files away. An instance is
|
|
18
|
+
* rebuilt per application, so a stub dies with it.
|
|
19
|
+
*
|
|
20
|
+
* **`repository` is no longer a parameter.** Nearly every service method took it first; it now
|
|
21
|
+
* comes from the application, which is what made the argument redundant in the first place.
|
|
22
|
+
*
|
|
23
|
+
* Pure functions of their arguments stay plain exported functions rather than becoming services -
|
|
24
|
+
* `ConventionalCommitsService.parseSubject('feat: x')` parses a string and will never hold state,
|
|
25
|
+
* and making it `app.getService('conventionalCommits').parseSubject(...)` would be ceremony that
|
|
26
|
+
* also puts an application between a caller and a parser. The line is whether it needs the
|
|
27
|
+
* repository.
|
|
28
|
+
*/
|
|
29
|
+
export class Service {
|
|
30
|
+
app;
|
|
31
|
+
constructor(app) {
|
|
32
|
+
this.app = app;
|
|
33
|
+
}
|
|
34
|
+
get repository() {
|
|
35
|
+
return this.app.repository;
|
|
36
|
+
}
|
|
37
|
+
get logger() {
|
|
38
|
+
return this.app.logger;
|
|
39
|
+
}
|
|
40
|
+
}
|
package/core/version-scheme.d.ts
CHANGED
|
@@ -16,7 +16,7 @@ export type ChangeKind = 'fix' | 'feature' | 'breaking';
|
|
|
16
16
|
* "is this version on the registry yet", `"workspace:"` range rewriting all assume versions that
|
|
17
17
|
* can be ordered and incremented. This is the seam for an ecosystem that numbers differently (PEP
|
|
18
18
|
* 440, a date-based scheme, a build counter), and it is a *meaning* seam rather than a storage one:
|
|
19
|
-
* `
|
|
19
|
+
* `Plugin`'s manifest members answers "where is the version written", this answers "what does the next one
|
|
20
20
|
* look like".
|
|
21
21
|
*
|
|
22
22
|
* **`bumpNames` and `bumpFor` are the interesting part.** `fix:` -> patch, `feat:` -> minor,
|
|
@@ -64,6 +64,20 @@ export declare abstract class VersionScheme {
|
|
|
64
64
|
}): string;
|
|
65
65
|
/** Is this version a preview rather than a release? `github-release` reads it. */
|
|
66
66
|
abstract isPrerelease(version: string): boolean;
|
|
67
|
+
/**
|
|
68
|
+
* Which prerelease line this version belongs to - `'beta'` for `2.0.0-beta.1` - or `undefined`
|
|
69
|
+
* when it is not a preview, or is one with no identifier to name (`2.0.0-1`).
|
|
70
|
+
*
|
|
71
|
+
* **The one thing a preview needs beyond "is it one", and it is a *name*, which is why it is
|
|
72
|
+
* here rather than read out of the version with a regex by whoever wants it.** npm's publish
|
|
73
|
+
* target derives its dist-tag from this, so a beta lands on `beta` instead of on `latest`; the
|
|
74
|
+
* identifier is written in the version itself, so that is a reading rather than a guess.
|
|
75
|
+
*
|
|
76
|
+
* Implemented, not abstract, and returning `undefined` by default: a scheme whose previews have
|
|
77
|
+
* no name (or which has no previews at all) is answering honestly, and the caller's job is to
|
|
78
|
+
* say so rather than invent one. `SemverScheme` overrides it.
|
|
79
|
+
*/
|
|
80
|
+
prereleaseId(version: string): string | undefined;
|
|
67
81
|
/**
|
|
68
82
|
* The highest of `versions` - a group's current version is the highest among its members, and a
|
|
69
83
|
* monorepo root's release identity the highest among the groups.
|
|
@@ -111,6 +125,14 @@ export declare class SemverScheme extends VersionScheme {
|
|
|
111
125
|
preid?: string;
|
|
112
126
|
}): string;
|
|
113
127
|
isPrerelease(version: string): boolean;
|
|
128
|
+
/**
|
|
129
|
+
* semver's first prerelease identifier, when it is a word: `2.0.0-beta.1` -> `'beta'`.
|
|
130
|
+
*
|
|
131
|
+
* **`undefined` for a numeric-only prerelease** (`2.0.0-1`, whose identifiers are `[1]`), because
|
|
132
|
+
* there is no name there to use - and a caller turning that into a dist-tag called `1` would be
|
|
133
|
+
* inventing one. Same answer for a release, which has no prerelease at all.
|
|
134
|
+
*/
|
|
135
|
+
prereleaseId(version: string): string | undefined;
|
|
114
136
|
}
|
|
115
137
|
/**
|
|
116
138
|
* The default, and what every package gets unless something says otherwise - so nothing about
|
package/core/version-scheme.js
CHANGED
|
@@ -6,7 +6,7 @@ import semver from 'semver';
|
|
|
6
6
|
* "is this version on the registry yet", `"workspace:"` range rewriting all assume versions that
|
|
7
7
|
* can be ordered and incremented. This is the seam for an ecosystem that numbers differently (PEP
|
|
8
8
|
* 440, a date-based scheme, a build counter), and it is a *meaning* seam rather than a storage one:
|
|
9
|
-
* `
|
|
9
|
+
* `Plugin`'s manifest members answers "where is the version written", this answers "what does the next one
|
|
10
10
|
* look like".
|
|
11
11
|
*
|
|
12
12
|
* **`bumpNames` and `bumpFor` are the interesting part.** `fix:` -> patch, `feat:` -> minor,
|
|
@@ -25,6 +25,23 @@ import semver from 'semver';
|
|
|
25
25
|
* `SemverScheme` to keep semver's numbering and change only one of these.
|
|
26
26
|
*/
|
|
27
27
|
export class VersionScheme {
|
|
28
|
+
/**
|
|
29
|
+
* Which prerelease line this version belongs to - `'beta'` for `2.0.0-beta.1` - or `undefined`
|
|
30
|
+
* when it is not a preview, or is one with no identifier to name (`2.0.0-1`).
|
|
31
|
+
*
|
|
32
|
+
* **The one thing a preview needs beyond "is it one", and it is a *name*, which is why it is
|
|
33
|
+
* here rather than read out of the version with a regex by whoever wants it.** npm's publish
|
|
34
|
+
* target derives its dist-tag from this, so a beta lands on `beta` instead of on `latest`; the
|
|
35
|
+
* identifier is written in the version itself, so that is a reading rather than a guess.
|
|
36
|
+
*
|
|
37
|
+
* Implemented, not abstract, and returning `undefined` by default: a scheme whose previews have
|
|
38
|
+
* no name (or which has no previews at all) is answering honestly, and the caller's job is to
|
|
39
|
+
* say so rather than invent one. `SemverScheme` overrides it.
|
|
40
|
+
*/
|
|
41
|
+
prereleaseId(version) {
|
|
42
|
+
void version;
|
|
43
|
+
return undefined;
|
|
44
|
+
}
|
|
28
45
|
/**
|
|
29
46
|
* The highest of `versions` - a group's current version is the highest among its members, and a
|
|
30
47
|
* monorepo root's release identity the highest among the groups.
|
|
@@ -117,6 +134,17 @@ export class SemverScheme extends VersionScheme {
|
|
|
117
134
|
isPrerelease(version) {
|
|
118
135
|
return !!semver.prerelease(version);
|
|
119
136
|
}
|
|
137
|
+
/**
|
|
138
|
+
* semver's first prerelease identifier, when it is a word: `2.0.0-beta.1` -> `'beta'`.
|
|
139
|
+
*
|
|
140
|
+
* **`undefined` for a numeric-only prerelease** (`2.0.0-1`, whose identifiers are `[1]`), because
|
|
141
|
+
* there is no name there to use - and a caller turning that into a dist-tag called `1` would be
|
|
142
|
+
* inventing one. Same answer for a release, which has no prerelease at all.
|
|
143
|
+
*/
|
|
144
|
+
prereleaseId(version) {
|
|
145
|
+
const first = semver.prerelease(version)?.[0];
|
|
146
|
+
return typeof first === 'string' ? first : undefined;
|
|
147
|
+
}
|
|
120
148
|
}
|
|
121
149
|
/**
|
|
122
150
|
* The default, and what every package gets unless something says otherwise - so nothing about
|
package/core/workspace.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import type { RmanApplication } from './application.js';
|
|
2
|
+
import type { Platform } from './plugin.js';
|
|
1
3
|
/**
|
|
2
4
|
* How a repository is laid out, and who decides.
|
|
3
5
|
*
|
|
@@ -6,45 +8,94 @@
|
|
|
6
8
|
* arrives as a member here rather than as another top-level export.
|
|
7
9
|
*/
|
|
8
10
|
export declare namespace Workspace {
|
|
9
|
-
/** What a repository looks like: where its root is, and which directories hold its packages. */
|
|
10
|
-
interface Layout {
|
|
11
|
-
/** Absolute path to the repository root. */
|
|
12
|
-
root: string;
|
|
13
|
-
/**
|
|
14
|
-
* Absolute paths to the package **directories**, outside the root. Empty for a repository that
|
|
15
|
-
* is itself the one package.
|
|
16
|
-
*
|
|
17
|
-
* Directories rather than `Package` objects, and not for want of trying: a provider runs before
|
|
18
|
-
* any package exists - `Repository.create` constructs them from these paths afterwards, through
|
|
19
|
-
* the *manifest* provider. A discovery provider returning packages would have to construct them
|
|
20
|
-
* itself, making discovery the owner of identity too.
|
|
21
|
-
*
|
|
22
|
-
* Unlike `Package.dependencies`, there is no identity question here: these are paths, and a
|
|
23
|
-
* path is unique by construction where a name is only unique if the ecosystem says so.
|
|
24
|
-
*/
|
|
25
|
-
packageDirs: string[];
|
|
26
|
-
}
|
|
27
11
|
/**
|
|
28
|
-
*
|
|
12
|
+
* **Where one directory's own child packages are** - the directories immediately below it that
|
|
13
|
+
* hold a package, as absolute paths. `undefined` for "this is not a directory I recognize".
|
|
14
|
+
*
|
|
15
|
+
* **A provider answers for one directory, not for the repository**, and that is the whole
|
|
16
|
+
* correction. It used to be `(root) => { root, packageDirs }`: asked once, at the top, by the
|
|
17
|
+
* first platform that recognized it - so in a polyglot repository the technology listed first in
|
|
18
|
+
* `plugins` decided which directories were packages *at all*. Measured, and documented as a known
|
|
19
|
+
* limitation for a year: a `Cargo.toml`-only package was simply not found until a provider that
|
|
20
|
+
* looks for both was listed first.
|
|
21
|
+
*
|
|
22
|
+
* Asked per directory, each platform only ever answers about its own packages - which is all a
|
|
23
|
+
* platform knows - and the recursion is the core's (see `walk`). A Cargo workspace nested inside
|
|
24
|
+
* a Node monorepo is then just a node in the tree whose children came from a different platform.
|
|
25
|
+
*
|
|
26
|
+
* **Children, not descendants.** A provider returning the whole subtree would have to know what
|
|
27
|
+
* the platforms below it consider a package; returning one level means it never has to. npm's
|
|
28
|
+
* `workspaces` globs are already one level by construction (`deep: 0`).
|
|
29
|
+
*
|
|
30
|
+
* Still directories rather than `Package` objects, for the reason it always was: discovery runs
|
|
31
|
+
* before any package exists, so a provider returning packages would make discovery the owner of
|
|
32
|
+
* identity too. A path is also unique by construction, where a name is only unique if the
|
|
33
|
+
* ecosystem says so.
|
|
34
|
+
*/
|
|
35
|
+
type Provider = (dir: string) => string[] | undefined;
|
|
36
|
+
/**
|
|
37
|
+
* One directory in the walk's result: which technology claimed it, and what sits below it.
|
|
29
38
|
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
|
|
39
|
+
* A plain tree rather than `Package`s, keeping the line `Provider` draws: `Repository.create`
|
|
40
|
+
* turns this into packages, so identity stays with the manifest provider and discovery stays
|
|
41
|
+
* with this one.
|
|
42
|
+
*/
|
|
43
|
+
interface Node {
|
|
44
|
+
/** Absolute path to the directory. */
|
|
45
|
+
dirname: string;
|
|
46
|
+
/** The technology that claimed it - `basePlatform` when none did, so a reader needs no guard. */
|
|
47
|
+
platform: Platform;
|
|
48
|
+
/** The nodes for the package directories directly below it, in the order the platform gave
|
|
49
|
+
* them. Empty for a leaf. */
|
|
50
|
+
children: Node[];
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* What a directory's `.rmanrc "platform"` resolves to, when it declares one - `undefined` when
|
|
54
|
+
* it says nothing, so the walk falls back to the guess.
|
|
34
55
|
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
56
|
+
* **A callback rather than config knowledge in here**, which keeps this namespace answering one
|
|
57
|
+
* question. Reading a directory's cascaded config, deciding that a declared name has to be
|
|
58
|
+
* loaded, and refusing one that cannot be, are all the repository's business; where the packages
|
|
59
|
+
* are is this one's. `Repository.create` supplies it - and it is also the seam a spec uses to
|
|
60
|
+
* drive the declaration path without writing a config file.
|
|
37
61
|
*/
|
|
38
|
-
type
|
|
62
|
+
type DeclaredPlatform = (dir: string) => Promise<Platform | undefined>;
|
|
39
63
|
/**
|
|
40
|
-
*
|
|
41
|
-
*
|
|
64
|
+
* **The walk**: descend from `rootDir`, asking each directory's own technology where its children
|
|
65
|
+
* are, and repeating for each answer.
|
|
66
|
+
*
|
|
67
|
+
* One step, applied recursively:
|
|
68
|
+
*
|
|
69
|
+
* 1. take the directory's **declared** platform if it has one, and otherwise the first registered
|
|
70
|
+
* platform whose manifest provider recognizes it (`app.platformFor`, `basePlatform` if none);
|
|
71
|
+
* 2. ask **that** platform's `getWorkspace` for the directories below it holding packages;
|
|
72
|
+
* 3. do the same for each of them.
|
|
73
|
+
*
|
|
74
|
+
* **A declaration wins, and is then held to it.** A platform named for a directory it does not
|
|
75
|
+
* recognize is a statement that is simply untrue, and the failure it would otherwise become is
|
|
76
|
+
* invisible: the manifest reads as nothing, so the package is named after its directory at
|
|
77
|
+
* `0.0.0` and the repository looks like it works. The error names the directory, the platform and
|
|
78
|
+
* the file that platform looked for.
|
|
79
|
+
*
|
|
80
|
+
* The root node always exists - a repository is a package whatever its technology - so this never
|
|
81
|
+
* returns `undefined`. A repository nobody recognizes is a root with no children, which is the
|
|
82
|
+
* single-package answer arrived at rather than guessed.
|
|
83
|
+
*
|
|
84
|
+
* **A directory is visited once.** A provider may legitimately name a directory another one
|
|
85
|
+
* already claimed (two globs overlapping, a symlinked package), and a provider naming an ancestor
|
|
86
|
+
* would otherwise recurse forever. First visit wins, so a package sits where it was first found.
|
|
87
|
+
*
|
|
88
|
+
* `deep` bounds the descent for the same reason `findRoot` bounds its climb: a provider computing
|
|
89
|
+
* paths rather than reading them can produce a chain that never ends, and a guessed depth is
|
|
90
|
+
* better than a hang with nothing printed.
|
|
42
91
|
*/
|
|
43
|
-
function
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
92
|
+
function walk(app: RmanApplication, rootDir: string, options?: {
|
|
93
|
+
deep?: number;
|
|
94
|
+
declared?: DeclaredPlatform;
|
|
95
|
+
}): Promise<Node>;
|
|
96
|
+
/** Every node below `node`, depth-first, excluding `node` itself - the flat list `Repository`
|
|
97
|
+
* reports as its packages, since the root is not one of its own members. */
|
|
98
|
+
function flatten(node: Node): Node[];
|
|
48
99
|
/**
|
|
49
100
|
* Where the repository starts, decided **without knowing anything about any ecosystem** - it has
|
|
50
101
|
* to be, because the plugins that do know are named in the config file this walk is looking for.
|
package/core/workspace.js
CHANGED
|
@@ -10,30 +10,72 @@ import path from 'node:path';
|
|
|
10
10
|
export var Workspace;
|
|
11
11
|
(function (Workspace) {
|
|
12
12
|
/**
|
|
13
|
-
*
|
|
14
|
-
*
|
|
13
|
+
* **The walk**: descend from `rootDir`, asking each directory's own technology where its children
|
|
14
|
+
* are, and repeating for each answer.
|
|
15
|
+
*
|
|
16
|
+
* One step, applied recursively:
|
|
17
|
+
*
|
|
18
|
+
* 1. take the directory's **declared** platform if it has one, and otherwise the first registered
|
|
19
|
+
* platform whose manifest provider recognizes it (`app.platformFor`, `basePlatform` if none);
|
|
20
|
+
* 2. ask **that** platform's `getWorkspace` for the directories below it holding packages;
|
|
21
|
+
* 3. do the same for each of them.
|
|
22
|
+
*
|
|
23
|
+
* **A declaration wins, and is then held to it.** A platform named for a directory it does not
|
|
24
|
+
* recognize is a statement that is simply untrue, and the failure it would otherwise become is
|
|
25
|
+
* invisible: the manifest reads as nothing, so the package is named after its directory at
|
|
26
|
+
* `0.0.0` and the repository looks like it works. The error names the directory, the platform and
|
|
27
|
+
* the file that platform looked for.
|
|
28
|
+
*
|
|
29
|
+
* The root node always exists - a repository is a package whatever its technology - so this never
|
|
30
|
+
* returns `undefined`. A repository nobody recognizes is a root with no children, which is the
|
|
31
|
+
* single-package answer arrived at rather than guessed.
|
|
32
|
+
*
|
|
33
|
+
* **A directory is visited once.** A provider may legitimately name a directory another one
|
|
34
|
+
* already claimed (two globs overlapping, a symlinked package), and a provider naming an ancestor
|
|
35
|
+
* would otherwise recurse forever. First visit wins, so a package sits where it was first found.
|
|
36
|
+
*
|
|
37
|
+
* `deep` bounds the descent for the same reason `findRoot` bounds its climb: a provider computing
|
|
38
|
+
* paths rather than reading them can produce a chain that never ends, and a guessed depth is
|
|
39
|
+
* better than a hang with nothing printed.
|
|
15
40
|
*/
|
|
16
|
-
function
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
41
|
+
async function walk(app, rootDir, options) {
|
|
42
|
+
const visited = new Set();
|
|
43
|
+
const descend = async (dir, remaining) => {
|
|
44
|
+
const resolved = path.resolve(dir);
|
|
45
|
+
visited.add(resolved);
|
|
46
|
+
const declared = await options?.declared?.(resolved);
|
|
47
|
+
if (declared && !declared.manifestProvider.read(resolved)) {
|
|
48
|
+
throw new Error(`"${resolved}" declares \`platform: '${declared.name}'\`, and that platform does not ` +
|
|
49
|
+
`recognize it - it looks for "${declared.manifestProvider.fileName}". Either the ` +
|
|
50
|
+
`directory is not a ${declared.name} package, or the declaration belongs one level down.`);
|
|
51
|
+
}
|
|
52
|
+
const platform = declared ?? app.platformFor(resolved);
|
|
53
|
+
const node = { dirname: resolved, platform, children: [] };
|
|
54
|
+
if (remaining <= 0)
|
|
55
|
+
return node;
|
|
56
|
+
/**
|
|
57
|
+
* **Its own platform is asked, and nobody else.** A platform that did not claim the directory
|
|
58
|
+
* has no standing to say what is under it - that was the old first-wins rule, one level up.
|
|
59
|
+
* `basePlatform` has no `getWorkspace`, so a directory no technology claimed has no children,
|
|
60
|
+
* which is the documented behaviour of a repository naming no plugin.
|
|
61
|
+
*/
|
|
62
|
+
for (const child of platform.getWorkspace?.(resolved) ?? []) {
|
|
63
|
+
const childDir = path.resolve(child);
|
|
64
|
+
if (visited.has(childDir))
|
|
65
|
+
continue;
|
|
66
|
+
node.children.push(await descend(childDir, remaining - 1));
|
|
67
|
+
}
|
|
68
|
+
return node;
|
|
69
|
+
};
|
|
70
|
+
return descend(rootDir, options?.deep ?? 10);
|
|
20
71
|
}
|
|
21
|
-
Workspace.
|
|
22
|
-
/**
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
Workspace.clearProviders = clearProviders;
|
|
27
|
-
/** The first provider that recognizes `root`, in declaration order. */
|
|
28
|
-
function resolve(root) {
|
|
29
|
-
for (const provider of providers) {
|
|
30
|
-
const layout = provider(root);
|
|
31
|
-
if (layout)
|
|
32
|
-
return layout;
|
|
33
|
-
}
|
|
34
|
-
return undefined;
|
|
72
|
+
Workspace.walk = walk;
|
|
73
|
+
/** Every node below `node`, depth-first, excluding `node` itself - the flat list `Repository`
|
|
74
|
+
* reports as its packages, since the root is not one of its own members. */
|
|
75
|
+
function flatten(node) {
|
|
76
|
+
return node.children.flatMap(child => [child, ...flatten(child)]);
|
|
35
77
|
}
|
|
36
|
-
Workspace.
|
|
78
|
+
Workspace.flatten = flatten;
|
|
37
79
|
/**
|
|
38
80
|
* Where the repository starts, decided **without knowing anything about any ecosystem** - it has
|
|
39
81
|
* to be, because the plugins that do know are named in the config file this walk is looking for.
|
|
@@ -79,5 +121,4 @@ export var Workspace;
|
|
|
79
121
|
function hasRmanConfig(dir) {
|
|
80
122
|
return CONFIG_FILES.some(name => fs.existsSync(path.join(dir, name)));
|
|
81
123
|
}
|
|
82
|
-
const providers = [];
|
|
83
124
|
})(Workspace || (Workspace = {}));
|
package/index.d.ts
CHANGED
|
@@ -6,44 +6,120 @@
|
|
|
6
6
|
* per domain - CLI-only concerns (argv parsing, `--help` text, and all console/file presentation)
|
|
7
7
|
* stay in `cli.ts` and the individual `commands/*.command.ts` modules, which are not exported here.
|
|
8
8
|
*
|
|
9
|
-
* **This is also the plugin contract.** A
|
|
10
|
-
*
|
|
11
|
-
* exported - the progress panel, the package filter, the branch guard, the git helper. What is
|
|
9
|
+
* **This is also the plugin contract.** A third-party plugin is an ordinary package that imports
|
|
10
|
+
* from here, so everything a command needs in order to live outside rman has to be exported - the progress panel, the package filter, the branch guard, the git helper. What is
|
|
12
11
|
* *not* exported is deliberately private: config resolution internals, the expression evaluator,
|
|
13
12
|
* the command registry.
|
|
14
13
|
*/
|
|
14
|
+
/**
|
|
15
|
+
* **The `node` built-in's type augmentation, imported for the same reason `commands.ts` is.**
|
|
16
|
+
*
|
|
17
|
+
* A `declare module` augmentation applies only where the module declaring it is part of the
|
|
18
|
+
* program. The node plugin's lives in `plugins/node/augmentation/rman.augmentation.ts` and is
|
|
19
|
+
* imported by the *plugin's* entry point - which nothing here reached, so `clean`, `publish.npm`
|
|
20
|
+
* and the rest existed for rman itself and for nobody else.
|
|
21
|
+
*
|
|
22
|
+
* **Measured on a real consumer**, `@panates/rman-node`, a config package annotated with these
|
|
23
|
+
* types: `Object literal may only specify known properties, and 'clean' does not exist in type
|
|
24
|
+
* 'RmanConfig'`, plus `Property 'npm' does not exist` - ten errors across its config and its own
|
|
25
|
+
* suite. It is the identical failure the core's command keys caused when they stopped being
|
|
26
|
+
* hand-written centrally, and it reappeared the moment the plugin moved *inside* rman: until then
|
|
27
|
+
* a consumer imported `rman-node` and got the augmentation with the package.
|
|
28
|
+
*
|
|
29
|
+
* Type-only, so the emitted module is empty - imported for what it declares, not for what it does.
|
|
30
|
+
* Pinned in `docs-api.spec.ts`, which imports only from this file.
|
|
31
|
+
*/
|
|
32
|
+
import './plugins/node/augmentation/rman.augmentation.js';
|
|
33
|
+
import type { RmanConfig as CommandDeclaration } from './interfaces/rman-config.interface.js';
|
|
15
34
|
export { defineConfig } from './core/config.js';
|
|
35
|
+
/**
|
|
36
|
+
* **A config value written as a function**, and the scope it is handed. Exported because a config
|
|
37
|
+
* author could not name either: `interpolateConfig` calls a function wherever a `${{ }}` could
|
|
38
|
+
* stand, but the only function form the types admitted was a *step* - so the primary spelling of
|
|
39
|
+
* `value` was unexpressible.
|
|
40
|
+
*
|
|
41
|
+
* `ConfigValueContext` is what a value function receives; `ConfigScope` is the same thing without
|
|
42
|
+
* `value`, i.e. what an expression sees. Not to be confused with `RunStepContext`, which is what a
|
|
43
|
+
* step gets, later, with a working directory and a `runBin`.
|
|
44
|
+
*/
|
|
45
|
+
export type { ConfigScope, ConfigValue, ConfigValueContext, FileScope, PackageScope, Resolved, ResolvedConfig, } from './core/config.js';
|
|
16
46
|
export type { CommandContext, CustomCommand } from './core/custom-command.js';
|
|
17
47
|
export { defineCommand } from './core/custom-command.js';
|
|
18
|
-
/** The manifest seam: where a package's name and version are written, and how it is numbered.
|
|
19
|
-
* The core has no provider - `package.json` is npm's answer, and lives in `rman-node`. */
|
|
20
|
-
export type { ManifestProvider } from './core/manifest.js';
|
|
21
48
|
/** Both the shape and the registry: `const m: Manifest` and `Manifest.read(dir)` - merged onto one
|
|
22
49
|
* name so a plugin can augment it the way it augments `SystemInfo`. */
|
|
50
|
+
export { RmanApplication } from './core/application.js';
|
|
51
|
+
/** The manifest seam, grouped on a plugin as `Plugin.manifestProvider`: where a package's name and
|
|
52
|
+
* version are written, what it declares, and how it is numbered and stamped. The core has none -
|
|
53
|
+
* `package.json` is npm's answer, and belongs to the `node` built-in. */
|
|
54
|
+
export type { ManifestProvider } from './core/manifest.js';
|
|
23
55
|
export { Manifest } from './core/manifest.js';
|
|
24
56
|
export { Package } from './core/package.js';
|
|
25
|
-
|
|
26
|
-
|
|
57
|
+
/** The publish seam: where a package's artifact ships. The core brings `docker` (nobody's
|
|
58
|
+
* ecosystem); npm's target is the `node` built-in's, and any other technology's is its own plugin's. */
|
|
59
|
+
export { declaredTargets, type PublishTarget, shipsTo, targetsOf, unknownTargets } from './core/publish-target.js';
|
|
60
|
+
export { Registry } from './core/registry.js';
|
|
27
61
|
export { Repository } from './core/repository.js';
|
|
28
62
|
export type { RunConditionFn, RunStepContext, RunStepFn, RunStepValue } from './core/run-step.js';
|
|
63
|
+
export { Service, type ServiceFactory, type ServiceMap } from './core/service.js';
|
|
64
|
+
/**
|
|
65
|
+
* **`Platform` is one technology, whole**; **`Plugin` is whatever a package contributes**, platforms
|
|
66
|
+
* among them.
|
|
67
|
+
*
|
|
68
|
+
* A platform says how its packages are recognized and written, where they live, what goes on a
|
|
69
|
+
* child's PATH and how its releases are planned - `manifestProvider` is what makes one, and it is
|
|
70
|
+
* required. A plugin carries `platforms` and an `init` for anything the seams do not name yet; a
|
|
71
|
+
* bare `Platform` is accepted wherever a `Plugin` is, as sugar for the plugin that provides only it.
|
|
72
|
+
*
|
|
73
|
+
* **Both must be declared through their factory.** `loadPlugins` checks for the mark, because an
|
|
74
|
+
* rman 1.x plugin was `{ name, init }` and so is a 2.x plugin contributing nothing but an `init` -
|
|
75
|
+
* no shape test can tell them apart.
|
|
76
|
+
*/
|
|
77
|
+
export { basePlatform, definePlatform, definePlugin, isPlatform, type Platform, type Plugin, type PluginContext, } from './core/plugin.js';
|
|
29
78
|
export type { ChangeKind } from './core/version-scheme.js';
|
|
30
79
|
/** The numbering seam. `VersionScheme` is abstract - `highestVersion`/`highestBump`/`smallestBump`
|
|
31
80
|
* are implemented from the members around them, so a scheme states only what it must and still
|
|
32
81
|
* overrides any of the three. `SemverScheme` is exported to subclass rather than restate. */
|
|
33
82
|
export { assertOneScheme, SemverScheme, semverScheme, VersionScheme } from './core/version-scheme.js';
|
|
34
83
|
/** The workspace seam: how a repository's packages are found. A plugin contributes a provider
|
|
35
|
-
* (see `
|
|
36
|
-
* `
|
|
84
|
+
* (see `Plugin.workspace`); the core has none, so `workspaces` is npm's idea and belongs to the
|
|
85
|
+
* `node` built-in. */
|
|
37
86
|
/** `Workspace.Layout`, `Workspace.Provider`, `Workspace.addProvider`, `Workspace.resolve`,
|
|
38
87
|
* `Workspace.findRoot` - one namespace, so a plugin can augment it. */
|
|
39
88
|
export { Workspace } from './core/workspace.js';
|
|
89
|
+
/**
|
|
90
|
+
* **How a command is declared** - the same API the built-ins use, so a plugin's command is declared
|
|
91
|
+
* rather than built: options as data (checked for typos), positionals named against the command
|
|
92
|
+
* string, `--config` keys derived from what the command owns, and `ArgsOf` for the handler.
|
|
93
|
+
*
|
|
94
|
+
* `declareCommand`, not `registerCommand`: the latter pushes onto a module-level registry every
|
|
95
|
+
* `runCli` walks, so a plugin using it would give its commands to repositories that never named it.
|
|
96
|
+
* Anything else puts the function in its config's `commands`.
|
|
97
|
+
*
|
|
98
|
+
* **Flat names rather than `RmanConfig.CommandOption`**, and they outlived the reason they were
|
|
99
|
+
* introduced: a second file exported a `RmanConfig` too, so the namespace holding these was
|
|
100
|
+
* unreachable from outside the package. The two are one file now and `RmanConfig` *is* exported -
|
|
101
|
+
* these stay because they are the better names for the job. A plugin author declaring a flag wants
|
|
102
|
+
* `CommandOption`; the config it happens to contribute to is not what they are naming.
|
|
103
|
+
*/
|
|
104
|
+
export { declareCommand } from './interfaces/rman-config.interface.js';
|
|
105
|
+
export type CommandOption = CommandDeclaration.CommandOption;
|
|
106
|
+
/** One declared positional, for the same reason `CommandOption` is here: it is the other half of a
|
|
107
|
+
* command's surface, and it was the half a plugin could not name without importing yargs. */
|
|
108
|
+
export type PositionalOption = CommandDeclaration.PositionalOption;
|
|
109
|
+
export type CommandMetadata = CommandDeclaration.CommandMetadata;
|
|
110
|
+
export type CommandRegisterFunction = CommandDeclaration.CommandRegisterFunction;
|
|
111
|
+
/** The argv a command's handler is annotated with - see `RmanConfig.ArgsOf` for why it is annotated
|
|
112
|
+
* rather than inferred. */
|
|
113
|
+
export type ArgsOf<C, Cmd extends string> = CommandDeclaration.ArgsOf<C, Cmd>;
|
|
114
|
+
export type GlobalArgs = CommandDeclaration.GlobalArgs;
|
|
115
|
+
export * from './commands.js';
|
|
40
116
|
export * from './interfaces/rman-config.interface.js';
|
|
41
117
|
export * from './services.js';
|
|
42
118
|
/** Branch guarding: `allowBranch`/`ignoreBranch`, so a plugin's release command refuses to run on
|
|
43
119
|
* the wrong branch exactly as `publish` and `version` do. */
|
|
44
|
-
export { applyBranchGuardOptions, assertAllowedBranch, type BranchGuardOptions, readBranchGuardOptions, } from './utils/branch-guard.js';
|
|
120
|
+
export { applyBranchGuardOptions, assertAllowedBranch, type BranchGuardOptions, branchGuardOptions, readBranchGuardOptions, } from './utils/branch-guard.js';
|
|
45
121
|
/** Where a repository's locally installed binaries live - the core spells the PATH variable, a
|
|
46
|
-
* plugin says which directories go on it (see `
|
|
122
|
+
* plugin says which directories go on it (see `Plugin.binPaths`). */
|
|
47
123
|
export { BinPath } from './utils/bin-path.js';
|
|
48
124
|
/** A shell command, with the repository's local binaries on PATH - for a command string an author
|
|
49
125
|
* wrote. `runBin` is the one to reach for when the arguments are assembled in code. */
|
|
@@ -54,13 +130,34 @@ export type { LogLevel } from './utils/logger.js';
|
|
|
54
130
|
export { LOG_LEVELS, Logger, resolveRootLogLevel } from './utils/logger.js';
|
|
55
131
|
/** `--scope`/`--deps`/`--dependents`/`--private`, so a plugin's command filters packages the same
|
|
56
132
|
* way every built-in does rather than inventing its own flags. */
|
|
57
|
-
export {
|
|
133
|
+
export { applyFromRootOption, applyPackageFilterOptions, filterPackages, fromRootOption, type PackageFilterOptions, packageFilterOptions, readFromRootOption, readPackageFilterOptions, ROOT_SELECTOR, } from './utils/package-filter.js';
|
|
58
134
|
/** The live panel `run`/`build`/`clean` print - a plugin's per-package command looks like the rest
|
|
59
135
|
* of rman instead of like a script someone bolted on. */
|
|
60
136
|
export { formatDuration, type ProgressItem, ProgressPanel, type ProgressStatus, type ProgressSummary, } from './utils/progress-panel.js';
|
|
61
|
-
/** Version stamping helpers a `
|
|
137
|
+
/** Version stamping helpers a `Plugin.stampVersion` can delegate to - the quoted-constant
|
|
62
138
|
* pattern most languages share, and the OCI Dockerfile label (which `version` stamps itself, since
|
|
63
139
|
* the label's value is by specification the package's version). */
|
|
140
|
+
/** A calendar version's time part (`2026.9.15-1430`) is a semver *prerelease identifier* by
|
|
141
|
+
* construction, so anything asking "is this a preview?" has to rule it out first - `github-release`
|
|
142
|
+
* does, and so must a publish target deciding whether a version needs its own dist-tag. Exported
|
|
143
|
+
* because that second caller lives in a plugin. */
|
|
144
|
+
/**
|
|
145
|
+
* **The `node` built-in's own surface.** It ships inside rman rather than as `rman-node`, so its
|
|
146
|
+
* services and target are named from here - a repository asks for the technology with
|
|
147
|
+
* `plugins: ['node']` (or lets detection find it) and never constructs any of this by hand.
|
|
148
|
+
*
|
|
149
|
+
* Its `.rmanrc` *keys* arrive separately, through the bare import at the top of this file - see
|
|
150
|
+
* there for why that import is not tidiness.
|
|
151
|
+
*/
|
|
152
|
+
export { BUILTIN_PLUGINS, builtinPluginNames, isBuiltinPlugin } from './plugins/builtins.js';
|
|
153
|
+
export type { NodeConfigKeys, RmanNodeConfig } from './plugins/node/node-config.interface.js';
|
|
154
|
+
export { NPM_TARGET, NpmPublishTarget } from './plugins/node/npm-publish-target.js';
|
|
155
|
+
export { CiService } from './plugins/node/services/ci.service.js';
|
|
156
|
+
export { CleanService } from './plugins/node/services/clean.service.js';
|
|
157
|
+
export { PublishService } from './plugins/node/services/publish.service.js';
|
|
158
|
+
export { NodeVersionPlanService } from './plugins/node/services/version-plan.service.js';
|
|
159
|
+
export type { ParsedWorkspaceRange } from './plugins/node/utils/workspace-range.js';
|
|
160
|
+
export { isCalendarVersion } from './utils/release-version.js';
|
|
64
161
|
export type { RunBinOptions, RunBinResult } from './utils/run-bin.js';
|
|
65
162
|
export { runBin } from './utils/run-bin.js';
|
|
66
163
|
export { OCI_VERSION_LABEL, stampVersionConstant, stampVersionLabel } from './utils/version-stamp.js';
|