rman 2.0.0-beta.2 → 2.0.0-beta.4

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.
Files changed (162) hide show
  1. package/README.md +2 -12
  2. package/{plugins/node/augmentation/rman.augmentation.d.ts → builtins/platforms/node/augmentation/rmanrc.augmentation.d.ts} +4 -5
  3. package/{plugins → builtins/platforms}/node/augmentation/system-info.augmentation.js +1 -1
  4. package/{plugins → builtins/platforms}/node/commands/ci.command.d.ts +5 -3
  5. package/{plugins → builtins/platforms}/node/commands/ci.command.js +6 -5
  6. package/{plugins → builtins/platforms}/node/commands/clean.command.d.ts +6 -4
  7. package/{plugins → builtins/platforms}/node/commands/clean.command.js +6 -5
  8. package/builtins/platforms/node/index.d.ts +8 -0
  9. package/builtins/platforms/node/index.js +8 -0
  10. package/{plugins → builtins/platforms}/node/node-config.interface.d.ts +1 -2
  11. package/{plugins → builtins/platforms}/node/node-manifest.provider.d.ts +3 -3
  12. package/{plugins → builtins/platforms}/node/node-manifest.provider.js +3 -3
  13. package/{plugins → builtins/platforms}/node/node.platform.d.ts +3 -3
  14. package/{plugins → builtins/platforms}/node/services/ci.service.d.ts +3 -3
  15. package/{plugins → builtins/platforms}/node/services/ci.service.js +4 -4
  16. package/{plugins → builtins/platforms}/node/services/clean.service.d.ts +3 -3
  17. package/{plugins → builtins/platforms}/node/services/clean.service.js +3 -3
  18. package/{plugins → builtins/platforms}/node/services/publish.service.d.ts +4 -4
  19. package/{plugins → builtins/platforms}/node/services/publish.service.js +13 -7
  20. package/{plugins → builtins/platforms}/node/services/version-plan.service.d.ts +3 -3
  21. package/{plugins → builtins/platforms}/node/services/version-plan.service.js +2 -2
  22. package/builtins/presets/index.d.ts +15 -0
  23. package/builtins/presets/index.js +57 -0
  24. package/builtins/presets/node.d.ts +16 -0
  25. package/builtins/presets/node.js +57 -0
  26. package/{services → builtins/publish-targets/docker}/docker-publish.service.d.ts +6 -6
  27. package/{services → builtins/publish-targets/docker}/docker-publish.service.js +9 -9
  28. package/{targets → builtins/publish-targets/docker}/docker.target.d.ts +6 -5
  29. package/{targets → builtins/publish-targets/docker}/docker.target.js +1 -1
  30. package/builtins/publish-targets/docker/index.d.ts +2 -0
  31. package/builtins/publish-targets/docker/index.js +2 -0
  32. package/builtins/publish-targets/npm/index.d.ts +2 -0
  33. package/builtins/publish-targets/npm/index.js +2 -0
  34. package/{plugins/node → builtins/publish-targets/npm}/npm-publish-target.d.ts +4 -4
  35. package/{plugins/node → builtins/publish-targets/npm}/npm-publish-target.js +4 -5
  36. package/cli.d.ts +3 -0
  37. package/cli.js +16 -7
  38. package/commands/changelog.command.d.ts +106 -2
  39. package/commands/changelog.command.js +40 -0
  40. package/commands/config.command.js +23 -5
  41. package/commands/list.command.js +1 -1
  42. package/commands/publish.command.d.ts +1 -1
  43. package/commands/publish.command.js +1 -1
  44. package/commands/run.command.js +1 -1
  45. package/commands/version.command.d.ts +16 -3
  46. package/commands/version.command.js +143 -9
  47. package/commands.d.ts +0 -1
  48. package/commands.js +0 -1
  49. package/constants.js +1 -1
  50. package/core/application.d.ts +10 -10
  51. package/core/application.js +28 -11
  52. package/core/{package.d.ts → classes/package.d.ts} +12 -4
  53. package/core/{package.js → classes/package.js} +17 -1
  54. package/core/{repository.d.ts → classes/repository.d.ts} +22 -36
  55. package/core/{repository.js → classes/repository.js} +112 -241
  56. package/core/{service.d.ts → classes/service.d.ts} +2 -2
  57. package/core/classes/workspace.d.ts +277 -0
  58. package/core/classes/workspace.js +585 -0
  59. package/core/command-builder.js +17 -1
  60. package/core/config/config-file-scope.d.ts +107 -0
  61. package/core/config/config-file-scope.js +226 -0
  62. package/core/config/config-interpolator.d.ts +164 -0
  63. package/core/config/config-interpolator.js +577 -0
  64. package/core/config/config-paths.d.ts +65 -0
  65. package/core/config/config-paths.js +78 -0
  66. package/core/config/config-reader.d.ts +215 -0
  67. package/core/config/config-reader.js +851 -0
  68. package/core/{merge-config.js → config/merge-config.js} +4 -8
  69. package/core/{custom-command.d.ts → interfaces/custom-command.d.ts} +5 -5
  70. package/core/{manifest.d.ts → interfaces/manifest.d.ts} +3 -3
  71. package/core/{manifest.js → interfaces/manifest.js} +2 -2
  72. package/core/{plugin.d.ts → interfaces/plugin.d.ts} +44 -27
  73. package/core/{plugin.js → interfaces/plugin.js} +48 -10
  74. package/core/{publish-target.d.ts → interfaces/publish-target.d.ts} +24 -12
  75. package/core/{publish-target.js → interfaces/publish-target.js} +16 -3
  76. package/core/{run-step.d.ts → interfaces/run-step.d.ts} +4 -4
  77. package/core/plugin-loader.d.ts +11 -51
  78. package/core/plugin-loader.js +21 -202
  79. package/index.d.ts +29 -28
  80. package/index.js +20 -46
  81. package/interfaces/config-scope.interface.d.ts +223 -0
  82. package/interfaces/config-scope.interface.js +1 -0
  83. package/interfaces/rman-config.interface.d.ts +100 -5
  84. package/interfaces/rman-config.interface.js +17 -0
  85. package/package.json +3 -2
  86. package/services/change-hash.service.d.ts +40 -6
  87. package/services/change-hash.service.js +90 -11
  88. package/services/changelog.service.d.ts +31 -3
  89. package/services/changelog.service.js +448 -65
  90. package/services/config-service.d.ts +8 -0
  91. package/services/config-service.js +3 -0
  92. package/services/exec.service.d.ts +2 -2
  93. package/services/exec.service.js +1 -1
  94. package/services/github-release.service.d.ts +3 -3
  95. package/services/github-release.service.js +3 -3
  96. package/services/import.service.d.ts +2 -2
  97. package/services/import.service.js +1 -1
  98. package/services/list.service.d.ts +9 -7
  99. package/services/list.service.js +2 -2
  100. package/services/run.service.d.ts +15 -11
  101. package/services/run.service.js +62 -18
  102. package/services/system-info.d.ts +1 -1
  103. package/services/version-plan.service.d.ts +8 -4
  104. package/services/version-plan.service.js +54 -21
  105. package/services/version.service.d.ts +5 -5
  106. package/services/version.service.js +7 -4
  107. package/services.d.ts +1 -1
  108. package/services.js +1 -1
  109. package/utils/branch-guard.d.ts +1 -1
  110. package/utils/color-yaml.d.ts +8 -0
  111. package/utils/color-yaml.js +86 -0
  112. package/utils/git.d.ts +26 -0
  113. package/utils/git.js +65 -0
  114. package/utils/logger.d.ts +1 -1
  115. package/utils/package-filter.d.ts +8 -1
  116. package/utils/package-filter.js +7 -0
  117. package/utils/printable-config.d.ts +8 -0
  118. package/utils/printable-config.js +45 -0
  119. package/utils/progress-panel.d.ts +9 -0
  120. package/utils/progress-panel.js +23 -1
  121. package/utils/release-version.d.ts +1 -1
  122. package/utils/run-options.js +1 -1
  123. package/utils/version-group.d.ts +31 -0
  124. package/utils/version-group.js +43 -0
  125. package/commands/changed.command.d.ts +0 -80
  126. package/commands/changed.command.js +0 -36
  127. package/core/config.d.ts +0 -530
  128. package/core/config.js +0 -1123
  129. package/core/core-services.d.ts +0 -14
  130. package/core/core-services.js +0 -30
  131. package/core/core-targets.d.ts +0 -14
  132. package/core/core-targets.js +0 -16
  133. package/core/extends-config.d.ts +0 -35
  134. package/core/extends-config.js +0 -129
  135. package/core/load-config-module.d.ts +0 -28
  136. package/core/load-config-module.js +0 -42
  137. package/core/workspace.d.ts +0 -119
  138. package/core/workspace.js +0 -124
  139. package/plugins/builtins.d.ts +0 -44
  140. package/plugins/builtins.js +0 -33
  141. package/plugins/detect.d.ts +0 -78
  142. package/plugins/detect.js +0 -70
  143. package/plugins/node/index.d.ts +0 -29
  144. package/plugins/node/index.js +0 -40
  145. /package/{core/run-step.js → builtins/platforms/node/augmentation/rmanrc.augmentation.js} +0 -0
  146. /package/{plugins → builtins/platforms}/node/augmentation/system-info.augmentation.d.ts +0 -0
  147. /package/{plugins → builtins/platforms}/node/node-config.interface.js +0 -0
  148. /package/{plugins → builtins/platforms}/node/node.platform.js +0 -0
  149. /package/{plugins → builtins/platforms}/node/utils/workspace-range.d.ts +0 -0
  150. /package/{plugins → builtins/platforms}/node/utils/workspace-range.js +0 -0
  151. /package/{plugins/node/utils → builtins/publish-targets/npm}/npm-view.d.ts +0 -0
  152. /package/{plugins/node/utils → builtins/publish-targets/npm}/npm-view.js +0 -0
  153. /package/core/{registry.d.ts → classes/registry.d.ts} +0 -0
  154. /package/core/{registry.js → classes/registry.js} +0 -0
  155. /package/core/{service.js → classes/service.js} +0 -0
  156. /package/core/{version-scheme.d.ts → classes/version-scheme.d.ts} +0 -0
  157. /package/core/{version-scheme.js → classes/version-scheme.js} +0 -0
  158. /package/core/{merge-config.d.ts → config/merge-config.d.ts} +0 -0
  159. /package/core/{resolve-target.d.ts → config/resolve-config-target.d.ts} +0 -0
  160. /package/core/{resolve-target.js → config/resolve-config-target.js} +0 -0
  161. /package/core/{custom-command.js → interfaces/custom-command.js} +0 -0
  162. /package/{plugins/node/augmentation/rman.augmentation.js → core/interfaces/run-step.js} +0 -0
@@ -1,9 +1,10 @@
1
1
  import path from 'node:path';
2
+ import { isPlainObject } from '@jsopen/objects';
2
3
  /** Where a repository keeps command modules of its own, as a glob or a list of them. */
3
4
  export const COMMANDS_KEY = 'commands';
4
5
  /** The keys whose string entries are globs, and so have to be anchored to the file that wrote
5
- * them - see `anchorContributions`. The same three that always append. */
6
- const GLOB_KEYS = ['plugins', COMMANDS_KEY, 'publishTargets'];
6
+ * them - see `anchorContributions`. The same four that always append. */
7
+ const GLOB_KEYS = ['plugins', 'platforms', COMMANDS_KEY, 'publishTargets'];
7
8
  /**
8
9
  * Keys that **append rather than replace**, which is the only append rman has.
9
10
  *
@@ -34,7 +35,7 @@ const GLOB_KEYS = ['plugins', COMMANDS_KEY, 'publishTargets'];
34
35
  * Do not extend this list casually: a key that always appends can never be *un*-said by a closer
35
36
  * layer, which is only acceptable where the value is a set of contributions rather than a decision.
36
37
  */
37
- export const ALWAYS_APPEND = ['plugins', COMMANDS_KEY, 'publishTargets'];
38
+ export const ALWAYS_APPEND = ['plugins', 'platforms', COMMANDS_KEY, 'publishTargets'];
38
39
  /**
39
40
  * Where a key keeps what it is replacing, so the replacement can be handed it back as `value`.
40
41
  *
@@ -257,8 +258,3 @@ function anchorContributions(value, origin) {
257
258
  function looksLikePackageName(entry) {
258
259
  return /^(?:@[a-z0-9-~][\w.-]*\/)?[a-z0-9-~][\w.-]*$/i.test(entry) && !/\.[cm]?js$/i.test(entry);
259
260
  }
260
- /** A config object, as opposed to an array or anything with its own prototype - only the former
261
- * merges key by key. */
262
- function isPlainObject(value) {
263
- return !!value && typeof value === 'object' && !Array.isArray(value);
264
- }
@@ -1,9 +1,9 @@
1
1
  import type { ArgumentsCamelCase, Argv } from 'yargs';
2
- import type { RmanConfig as CommandDeclaration } from '../interfaces/rman-config.interface.js';
3
- import type { Logger } from '../utils/logger.js';
4
- import type { RunBinOptions, RunBinResult } from '../utils/run-bin.js';
5
- import type { Package } from './package.js';
6
- import type { Repository } from './repository.js';
2
+ import type { RmanConfig as CommandDeclaration } from '../../interfaces/rman-config.interface.js';
3
+ import type { Logger } from '../../utils/logger.js';
4
+ import type { RunBinOptions, RunBinResult } from '../../utils/run-bin.js';
5
+ import type { Package } from '../classes/package.js';
6
+ import type { Repository } from '../classes/repository.js';
7
7
  /** Where a repository keeps its own commands - one module per command, named after it. */
8
8
  export declare const CUSTOM_COMMAND_DIR = ".rman";
9
9
  /**
@@ -1,7 +1,7 @@
1
- import { RmanApplication } from './application.js';
2
- import type { Package } from './package.js';
1
+ import { RmanApplication } from '../application.js';
2
+ import type { Package } from '../classes/package.js';
3
+ import { type VersionScheme } from '../classes/version-scheme.js';
3
4
  import type { Platform } from './plugin.js';
4
- import { type VersionScheme } from './version-scheme.js';
5
5
  /**
6
6
  * A package's identity, however its ecosystem happens to record it.
7
7
  *
@@ -1,6 +1,6 @@
1
1
  import path from 'node:path';
2
- import { RmanApplication } from './application.js';
3
- import { semverScheme } from './version-scheme.js';
2
+ import { RmanApplication } from '../application.js';
3
+ import { semverScheme } from '../classes/version-scheme.js';
4
4
  /**
5
5
  * The registry, merged onto the `Manifest` interface so one name carries both the shape and the
6
6
  * operations - `Manifest.read(dir)` returns a `Manifest`.
@@ -1,9 +1,10 @@
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';
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';
5
7
  import type { ManifestProvider } from './manifest.js';
6
- import type { Workspace } from './workspace.js';
7
8
  /**
8
9
  * **One technology, as a whole** - Node, Cargo, Maven. Everything rman needs in order to treat a
9
10
  * directory as a package of that technology.
@@ -93,45 +94,61 @@ export interface Platform {
93
94
  */
94
95
  export interface Plugin {
95
96
  /** How this plugin is named in messages, and the de-duplication key: registering twice under one
96
- * name is refused. A platform contributed by it keeps its *own* name, which is what a package
97
- * reports as `pkg.platform`. */
97
+ * name is refused. */
98
98
  name: string;
99
- /** The technologies this plugin provides, if any. */
100
- platforms?: Platform[];
101
99
  /**
102
- * Anything this plugin contributes that is not a platform, run once when it is registered.
100
+ * Run once the application exists and this plugin is on it, **before anything has been
101
+ * discovered** - no packages, no configs, no repository.
103
102
  *
104
- * **The escape hatch, not the front door.** Commands and publish targets are `.rmanrc` keys
105
- * (`commands`, `publishTargets`), so a plugin contributing only those declares them in its own
106
- * config and needs no `init` at all. What is left for `init` is whatever the seams do not name
107
- * yet, reached through `ctx.app`.
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.
108
110
  *
109
- * **It runs inside `Repository.create`**, before any package is known, so `ctx.app.repository`
110
- * throws there. Anything wanting the repository belongs in a command's factory instead, which
111
- * runs once there is one.
111
+ * The stage `afterInitApplication` cannot reach: that one runs inside `Repository.create` before
112
+ * any package is known, so `ctx.app.repository` throws there.
112
113
  */
113
- init?(ctx: PluginContext): void | Promise<void>;
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';
114
119
  }
115
120
  /**
116
- * What `Plugin.init` is handed.
121
+ * What {@link Plugin.afterInitApplication} is handed.
117
122
  *
118
- * Only the application today. An object rather than a bare parameter so a member added later
119
- * breaks nothing already written against it - the same reason `CommandContext` is one, which has
120
- * already paid for itself twice.
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.
121
125
  */
122
126
  export interface PluginContext {
123
127
  app: RmanApplication;
124
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;
125
139
  /** Whether `value` came from `definePlatform` or `definePlugin`. */
126
140
  export declare function isDeclared(value: unknown): boolean;
127
141
  /** Declares a **platform** - one technology, whole. Returns it unchanged apart from the mark. */
128
142
  export declare function definePlatform(platform: Platform): Platform;
129
- /** Declares a **plugin** - whatever a package contributes, platforms included. Returns it unchanged
130
- * apart from the mark. */
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. */
131
145
  export declare function definePlugin(plugin: Plugin): Plugin;
132
- /** Whether `value` is a platform rather than the broader plugin - `manifestProvider` is what makes
133
- * one, and it is the only required member either type has beyond `name`. */
134
- export declare function isPlatform(value: Plugin | Platform): value is Platform;
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;
135
152
  /**
136
153
  * The platform a package gets when **none** claimed its directory - a repository naming no
137
154
  * platform, or a directory none of the named ones recognized.
@@ -1,20 +1,58 @@
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
+ }
1
26
  /** Whether `value` came from `definePlatform` or `definePlugin`. */
2
27
  export function isDeclared(value) {
3
- return !!value && typeof value === 'object' && value[declaredKey()] === true;
28
+ return declaredKind(value) !== undefined;
4
29
  }
5
30
  /** Declares a **platform** - one technology, whole. Returns it unchanged apart from the mark. */
6
31
  export function definePlatform(platform) {
7
- return brand(platform);
32
+ return brand(platform, 'platform');
8
33
  }
9
- /** Declares a **plugin** - whatever a package contributes, platforms included. Returns it unchanged
10
- * apart from the mark. */
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. */
11
36
  export function definePlugin(plugin) {
12
- return brand(plugin);
37
+ return brand(plugin, 'plugin');
13
38
  }
14
- /** Whether `value` is a platform rather than the broader plugin - `manifestProvider` is what makes
15
- * one, and it is the only required member either type has beyond `name`. */
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. */
16
50
  export function isPlatform(value) {
17
- return !!value.manifestProvider;
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';
18
56
  }
19
57
  /**
20
58
  * The platform a package gets when **none** claimed its directory - a repository naming no
@@ -80,7 +118,7 @@ function declaredKey() {
80
118
  return Symbol.for('rman.declared');
81
119
  }
82
120
  /** Stamps the mark, non-enumerably, and hands the object back. */
83
- function brand(value) {
84
- Object.defineProperty(value, declaredKey(), { value: true, enumerable: false, configurable: true });
121
+ function brand(value, kind) {
122
+ Object.defineProperty(value, declaredKey(), { value: kind, enumerable: false, configurable: true });
85
123
  return value;
86
124
  }
@@ -1,8 +1,8 @@
1
- import type { RmanConfig } from '../interfaces/rman-config.interface.js';
2
- import type { PackageFilterOptions } from '../utils/package-filter.js';
3
- import type { RmanApplication } from './application.js';
4
- import type { Package } from './package.js';
5
- import type { Repository } from './repository.js';
1
+ import type { RmanConfig } from '../../interfaces/rman-config.interface.js';
2
+ import type { PackageFilterOptions } from '../../utils/package-filter.js';
3
+ import type { RmanApplication } from '../application.js';
4
+ import type { Package } from '../classes/package.js';
5
+ import type { Repository } from '../classes/repository.js';
6
6
  /**
7
7
  * **Where a package's artifact ships, as a contribution.**
8
8
  *
@@ -41,14 +41,24 @@ export interface PublishTarget {
41
41
  * Name a flag for the target when it genuinely belongs to one (`--docker-namespace`).
42
42
  */
43
43
  readonly options?: Record<string, RmanConfig.CommandOption>;
44
+ /**
45
+ * The technologies this target is for, by `Platform.name` - `['node']` for `npm`. Absent means
46
+ * every platform, which is what a technology-agnostic target says: any package can carry a
47
+ * Dockerfile, so `docker` declares none.
48
+ *
49
+ * On its own it is the whole of `claims`: a package of one of these platforms that declares no
50
+ * `publish.target` ships here. With `claims` beside it, this narrows first and `claims` decides
51
+ * within.
52
+ *
53
+ * The same word `CommandMetadata.platforms` uses, and the same question.
54
+ */
55
+ readonly platforms?: string[];
44
56
  /**
45
57
  * Whether a package that declares **no** `publish.target` at all ships here.
46
58
  *
47
- * Absent means never - the target is opt-in, which is what `docker` is. `npm`'s answer is
48
- * `pkg.provider === 'node'`, and that is the fix for a real bug rather than a nicety: the default
49
- * used to be a hardcoded `['npm']` in the core, so `rman list --json` reported
50
- * `publishTargets: ["npm"]` for a Cargo package and `publish` treated it as an npm candidate.
51
- * A default only the ecosystem can state had been written down by someone who could not know it.
59
+ * Absent means never - the target is opt-in, which is what `docker` is - unless `platforms` says
60
+ * otherwise, in which case that is the answer. Present, it decides for the packages `platforms`
61
+ * let through.
52
62
  */
53
63
  claims?(pkg: Package): boolean;
54
64
  /** What this target *would* do - never publishes. Called even under `--dry-run`, which is the
@@ -113,8 +123,10 @@ export type PublishTargetName = string;
113
123
  * as an empty list, and the difference is what `claims` is asked about.
114
124
  */
115
125
  export declare function declaredTargets(pkg: Package): string[] | undefined;
116
- /** Whether `pkg` ships to `target`: its own `publish.target` decides when it has one, and the
117
- * target's own `claims` decides when it does not. */
126
+ /**
127
+ * Whether `pkg` ships to `target`: its own `publish.target` decides when it has one, and the
128
+ * target's `platforms`/`claims` decide when it does not.
129
+ */
118
130
  export declare function shipsTo(pkg: Package, target: PublishTarget): boolean;
119
131
  /** Every registered target `pkg` ships to, in registration order. The single answer to "where does
120
132
  * this package go", so `publish` and `list --json` cannot disagree about it. */
@@ -8,11 +8,24 @@ export function declaredTargets(pkg) {
8
8
  return undefined;
9
9
  return Array.isArray(declared) ? [...declared] : [declared];
10
10
  }
11
- /** Whether `pkg` ships to `target`: its own `publish.target` decides when it has one, and the
12
- * target's own `claims` decides when it does not. */
11
+ /**
12
+ * Whether `pkg` ships to `target`: its own `publish.target` decides when it has one, and the
13
+ * target's `platforms`/`claims` decide when it does not.
14
+ */
15
+ /* **A declared `publish.target` is the last word**, and neither `platforms` nor `claims` is asked
16
+ * after it - a package naming a target has said where it goes, whatever ecosystem it is. Narrowing
17
+ * that would turn a default into a rule about who may say what. */
13
18
  export function shipsTo(pkg, target) {
14
19
  const declared = declaredTargets(pkg);
15
- return declared ? declared.includes(target.name) : !!target.claims?.(pkg);
20
+ if (declared)
21
+ return declared.includes(target.name);
22
+ /** `platforms` narrows first; `claims` decides within what it let through. With only `platforms`,
23
+ * belonging to one of them *is* the claim; with neither, the target is opt-in. */
24
+ if (target.platforms?.length && !target.platforms.includes(pkg.provider))
25
+ return false;
26
+ if (target.claims)
27
+ return target.claims(pkg);
28
+ return !!target.platforms?.length;
16
29
  }
17
30
  /** Every registered target `pkg` ships to, in registration order. The single answer to "where does
18
31
  * this package go", so `publish` and `list --json` cannot disagree about it. */
@@ -1,7 +1,7 @@
1
- import type { Logger } from '../utils/logger.js';
2
- import type { RunBinOptions, RunBinResult } from '../utils/run-bin.js';
3
- import type { Package } from './package.js';
4
- import type { Repository } from './repository.js';
1
+ import type { Logger } from '../../utils/logger.js';
2
+ import type { RunBinOptions, RunBinResult } from '../../utils/run-bin.js';
3
+ import type { Package } from '../classes/package.js';
4
+ import type { Repository } from '../classes/repository.js';
5
5
  /**
6
6
  * What a **function step** is handed - a `run.<script>.before`/`.exec`/`.after` or a
7
7
  * `version.<slot>` written as JavaScript instead of a shell command, and the `if` deciding whether
@@ -1,61 +1,21 @@
1
- import type { RmanConfig } from '../interfaces/rman-config.interface.js';
2
1
  import type { RmanApplication } from './application.js';
3
- import { type Platform, type Plugin } from './plugin.js';
2
+ import { type Platform, type Plugin } from './interfaces/plugin.js';
4
3
  /** The `.rmanrc` key naming plugin packages to load. */
5
4
  export declare const PLUGINS_KEY = "plugins";
6
5
  /**
7
- * The repository's plugins and publish targets, registered onto `app`.
6
+ * **Puts one contribution onto an application** - a technology, or a plugin - and the only place
7
+ * that knows how.
8
8
  *
9
- * **Three keys share one shape** - `plugins`, `publishTargets` and `commands` each take an
10
- * instance or a **glob** naming `.js` modules that `export default` one, and each appends rather
11
- * than replaces. Two of them are read here; `commands` is read by `cli.ts`, and the split is not
12
- * arbitrary:
9
+ * **Exported because a spec must not reimplement it.** A fixture writing the registrations out by
10
+ * hand is a second implementation that drifts, which is exactly how a fixture ends up proving the
11
+ * core works when it does not. A spec brings its own technology through this, the same door a
12
+ * config's does.
13
13
  *
14
- * - **`plugins` and `publishTargets` are root-level, because they have to be.** This runs inside
15
- * `Repository.create` *before* the packages are known, since a plugin's `getWorkspace` is what
16
- * finds them - so there are no package configs to read yet. A `plugins` entry in a package's own
17
- * `.rmanrc` is never seen, which has always been true and is now true for the same reason.
18
- * - **`commands` is read at any level**, after the packages exist, which is why `cli.ts` owns it:
19
- * it already holds the whole command pipeline - the `.rman/` default, de-duplication by name,
20
- * and the built-in shadow check. Reading it here as well would register every config-declared
21
- * command twice, and yargs does not survive that.
22
- *
23
- * **Order within this function is load-bearing**: plugins first, then targets. rman's own
24
- * `publish` builds its `--target` choices from `app.publishTargets` when its factory runs, and a
25
- * target contributed by a plugin's `init` has to be there before the list is read.
26
- *
27
- * **A contribution that cannot be loaded throws**, unlike a broken `.rman/*.mjs`, which is warned
28
- * about and skipped. The consequence differs: a skipped local command affects only itself, while a
29
- * missing plugin silently removes commands the repository is built around - `rman publish` would
30
- * simply not exist, and "not a known command" sends the reader looking in the wrong place.
31
- */
32
- export declare function loadPlugins(app: RmanApplication, rootConfig: RmanConfig): Promise<void>;
33
- /**
34
- * **Puts one plugin onto an application** - what `plugins` does with an entry once it has been
35
- * found and vetted, and the only place that knows how.
36
- *
37
- * **A bare `Platform` is sugar**, which is what almost every entry is - a plugin that provides one
38
- * technology and nothing else. Normalized here, so nothing downstream deals in two shapes.
39
- *
40
- * **Exported because a spec must not reimplement it.** The registration is two registries plus a
41
- * planner assignment, and a fixture writing that out by hand is a second implementation that
42
- * drifts - which is exactly how a fixture ends up proving the core works when it does not. A spec
43
- * brings its own technology through this, the same door a config's does.
44
- *
45
- * **`init` is not called here, and that is why this returns the normalized plugin.** An `init` runs
46
- * once, when a *config* brought the plugin in, and it may be asynchronous - so it belongs to the
47
- * loader above rather than to a function a fixture calls synchronously while building an
48
- * application.
49
- */
50
- export declare function registerPlugin(app: RmanApplication, entry: Plugin | Platform): Plugin;
51
- /**
52
- * A plugin's `CustomCommand`, checked the same way a `.rman/*.mjs` one is - the name it answers to
53
- * comes from its own `command` string, since a plugin has no file name to fall back on.
54
- *
55
- * Exported because `cli.ts` runs the identical checks on what a *declarative* command's factory
56
- * returns, and they must not drift: a plugin written in JavaScript reaches both forms with no type
57
- * checker in the way.
14
+ * **Neither hook is called here, and that is deliberate.** `afterInitApplication` and
15
+ * `afterInitRepository` belong to `Repository.create`, which knows when each stage is reached and
16
+ * can await them; this is a synchronous call a fixture makes while building an application.
58
17
  */
18
+ export declare function registerPlugin(app: RmanApplication, entry: Plugin | Platform): void;
59
19
  export declare function checkCustomCommand<T extends {
60
20
  command?: string;
61
21
  describe?: unknown;