rman 2.0.0-beta.2 → 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.
Files changed (164) 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 +5 -5
  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/lint.command.d.ts +176 -0
  42. package/commands/lint.command.js +34 -0
  43. package/commands/list.command.js +1 -1
  44. package/commands/publish.command.d.ts +1 -1
  45. package/commands/publish.command.js +1 -1
  46. package/commands/run.command.js +1 -1
  47. package/commands/version.command.d.ts +16 -3
  48. package/commands/version.command.js +143 -9
  49. package/commands.d.ts +1 -1
  50. package/commands.js +1 -1
  51. package/constants.js +1 -1
  52. package/core/application.d.ts +10 -10
  53. package/core/application.js +28 -11
  54. package/core/{package.d.ts → classes/package.d.ts} +12 -4
  55. package/core/{package.js → classes/package.js} +17 -1
  56. package/core/{repository.d.ts → classes/repository.d.ts} +22 -36
  57. package/core/{repository.js → classes/repository.js} +112 -241
  58. package/core/{service.d.ts → classes/service.d.ts} +2 -2
  59. package/core/classes/workspace.d.ts +275 -0
  60. package/core/classes/workspace.js +537 -0
  61. package/core/command-builder.js +17 -1
  62. package/core/config/config-file-scope.d.ts +107 -0
  63. package/core/config/config-file-scope.js +226 -0
  64. package/core/config/config-interpolator.d.ts +164 -0
  65. package/core/config/config-interpolator.js +577 -0
  66. package/core/config/config-paths.d.ts +65 -0
  67. package/core/config/config-paths.js +78 -0
  68. package/core/config/config-reader.d.ts +192 -0
  69. package/core/config/config-reader.js +727 -0
  70. package/core/{merge-config.js → config/merge-config.js} +4 -8
  71. package/core/{custom-command.d.ts → interfaces/custom-command.d.ts} +5 -5
  72. package/core/{manifest.d.ts → interfaces/manifest.d.ts} +3 -3
  73. package/core/{manifest.js → interfaces/manifest.js} +2 -2
  74. package/core/{plugin.d.ts → interfaces/plugin.d.ts} +44 -27
  75. package/core/{plugin.js → interfaces/plugin.js} +48 -10
  76. package/core/{publish-target.d.ts → interfaces/publish-target.d.ts} +24 -12
  77. package/core/{publish-target.js → interfaces/publish-target.js} +16 -3
  78. package/core/{run-step.d.ts → interfaces/run-step.d.ts} +4 -4
  79. package/core/plugin-loader.d.ts +11 -51
  80. package/core/plugin-loader.js +21 -202
  81. package/index.d.ts +29 -28
  82. package/index.js +20 -46
  83. package/interfaces/config-scope.interface.d.ts +223 -0
  84. package/interfaces/config-scope.interface.js +1 -0
  85. package/interfaces/rman-config.interface.d.ts +100 -5
  86. package/interfaces/rman-config.interface.js +17 -0
  87. package/package.json +2 -1
  88. package/services/change-hash.service.d.ts +40 -6
  89. package/services/change-hash.service.js +90 -11
  90. package/services/changelog.service.d.ts +31 -3
  91. package/services/changelog.service.js +448 -65
  92. package/services/config-service.d.ts +8 -0
  93. package/services/config-service.js +3 -0
  94. package/services/exec.service.d.ts +2 -2
  95. package/services/exec.service.js +1 -1
  96. package/services/github-release.service.d.ts +3 -3
  97. package/services/github-release.service.js +3 -3
  98. package/services/import.service.d.ts +2 -2
  99. package/services/import.service.js +1 -1
  100. package/services/list.service.d.ts +9 -7
  101. package/services/list.service.js +2 -2
  102. package/services/run.service.d.ts +15 -11
  103. package/services/run.service.js +62 -18
  104. package/services/system-info.d.ts +1 -1
  105. package/services/version-plan.service.d.ts +8 -4
  106. package/services/version-plan.service.js +54 -21
  107. package/services/version.service.d.ts +5 -5
  108. package/services/version.service.js +7 -4
  109. package/services.d.ts +1 -1
  110. package/services.js +1 -1
  111. package/utils/branch-guard.d.ts +1 -1
  112. package/utils/color-yaml.d.ts +8 -0
  113. package/utils/color-yaml.js +86 -0
  114. package/utils/git.d.ts +26 -0
  115. package/utils/git.js +65 -0
  116. package/utils/logger.d.ts +1 -1
  117. package/utils/package-filter.d.ts +8 -1
  118. package/utils/package-filter.js +7 -0
  119. package/utils/printable-config.d.ts +8 -0
  120. package/utils/printable-config.js +45 -0
  121. package/utils/progress-panel.d.ts +9 -0
  122. package/utils/progress-panel.js +23 -1
  123. package/utils/release-version.d.ts +1 -1
  124. package/utils/run-options.js +1 -1
  125. package/utils/version-group.d.ts +31 -0
  126. package/utils/version-group.js +43 -0
  127. package/commands/changed.command.d.ts +0 -80
  128. package/commands/changed.command.js +0 -36
  129. package/core/config.d.ts +0 -530
  130. package/core/config.js +0 -1123
  131. package/core/core-services.d.ts +0 -14
  132. package/core/core-services.js +0 -30
  133. package/core/core-targets.d.ts +0 -14
  134. package/core/core-targets.js +0 -16
  135. package/core/extends-config.d.ts +0 -35
  136. package/core/extends-config.js +0 -129
  137. package/core/load-config-module.d.ts +0 -28
  138. package/core/load-config-module.js +0 -42
  139. package/core/workspace.d.ts +0 -119
  140. package/core/workspace.js +0 -124
  141. package/plugins/builtins.d.ts +0 -44
  142. package/plugins/builtins.js +0 -33
  143. package/plugins/detect.d.ts +0 -78
  144. package/plugins/detect.js +0 -70
  145. package/plugins/node/index.d.ts +0 -29
  146. package/plugins/node/index.js +0 -40
  147. /package/{core/run-step.js → builtins/platforms/node/augmentation/rmanrc.augmentation.js} +0 -0
  148. /package/{plugins → builtins/platforms}/node/augmentation/system-info.augmentation.d.ts +0 -0
  149. /package/{plugins → builtins/platforms}/node/node-config.interface.js +0 -0
  150. /package/{plugins → builtins/platforms}/node/node.platform.js +0 -0
  151. /package/{plugins → builtins/platforms}/node/utils/workspace-range.d.ts +0 -0
  152. /package/{plugins → builtins/platforms}/node/utils/workspace-range.js +0 -0
  153. /package/{plugins/node/utils → builtins/publish-targets/npm}/npm-view.d.ts +0 -0
  154. /package/{plugins/node/utils → builtins/publish-targets/npm}/npm-view.js +0 -0
  155. /package/core/{registry.d.ts → classes/registry.d.ts} +0 -0
  156. /package/core/{registry.js → classes/registry.js} +0 -0
  157. /package/core/{service.js → classes/service.js} +0 -0
  158. /package/core/{version-scheme.d.ts → classes/version-scheme.d.ts} +0 -0
  159. /package/core/{version-scheme.js → classes/version-scheme.js} +0 -0
  160. /package/core/{merge-config.d.ts → config/merge-config.d.ts} +0 -0
  161. /package/core/{resolve-target.d.ts → config/resolve-config-target.d.ts} +0 -0
  162. /package/core/{resolve-target.js → config/resolve-config-target.js} +0 -0
  163. /package/core/{custom-command.js → interfaces/custom-command.js} +0 -0
  164. /package/{plugins/node/augmentation/rman.augmentation.js → core/interfaces/run-step.js} +0 -0
@@ -0,0 +1,78 @@
1
+ /**
2
+ * **Which config paths are code rather than data**, and which are left for later.
3
+ *
4
+ * Three lists, read by `ConfigInterpolator` as it walks and by the commands that own the keys. Not
5
+ * members of that class, and that is the exception CLAUDE.md records: `CodeSubtree` is derived from
6
+ * `CODE_SUBTREES` with `(typeof ...)[number]`, and a class field has no type to derive from. The
7
+ * test is whether a *type* reads the value, not whether the value feels constant.
8
+ */
9
+ /**
10
+ * Keys whose **whole subtree** is code rather than config, so no function under them is a value to
11
+ * compute.
12
+ *
13
+ * The three contribution keys, and each has to be here: an entry may be the *instance* itself, and
14
+ * a `Plugin` is almost entirely functions - `manifestProvider.read`, `getWorkspace`,
15
+ * `getBinPaths`, `versionPlanner` - while a command is often a bare factory and a publish target
16
+ * carries `getPlan`/`applyPlan`.
17
+ *
18
+ * Measured twice, once per shape. With `plugins` walked like any other key, resolving the config
19
+ * of a repository that named a plugin called that plugin's yargs builder with the config scope:
20
+ * `Config function in "plugins[0].commands[0].builder" failed: cmd.option is not a function`. And
21
+ * with `commands` left out of this list, a declarative command - which *is* a function - was
22
+ * invoked with the interpolation scope instead of the application, so its handler closed over a
23
+ * repository that was not one: `repository.getPackages is not a function`, from inside `clean`.
24
+ *
25
+ * These entries are loaded by `loadPlugins` and `cli.ts`, never read as settings.
26
+ */
27
+ export const CODE_SUBTREES = ['plugins', 'platforms', 'commands', 'publishTargets'];
28
+ /**
29
+ * Paths whose value is a **step** - something to run later - rather than a setting to compute now.
30
+ * `*` matches one path segment (`run.<script>.exec`).
31
+ *
32
+ * This is what tells a step function from a value function, and the two live side by side in one
33
+ * config:
34
+ *
35
+ * ```js
36
+ * '[*]': {
37
+ * clean: { include: ({ vars, value }) => [...value, vars.buildDir] }, // a value: called here
38
+ * run: { build: { after: ({ pkg }) => copyDocs(pkg) } }, // a step: called by `run`
39
+ * }
40
+ * ```
41
+ *
42
+ * **The key decides, and it already did.** `run.build.exec: 'tsc -b'` is a shell command and
43
+ * `publish.npm.directory: 'build'` is a path - not because of anything about the strings, but because of
44
+ * where they sit. A function inherits the same rule, so nothing new has to be learned and no marker
45
+ * has to be remembered. The alternative was inspecting the function (arity, parameter names), which
46
+ * is the kind of guess `loadPlugins` refuses to make about a module's export for the same reason:
47
+ * guessing wrong here means running build-time code while merely loading the repository, or
48
+ * silently never running it.
49
+ *
50
+ * A **string** at one of these paths is still interpolated - `exec: 'tsc -b ${{ file.resolve(...) }}'`
51
+ * has to keep working - so this is narrower than `DEFERRED_PATHS`, which skips its paths entirely.
52
+ */
53
+ export const STEP_PATHS = [
54
+ /** The bare-value shorthand: `run: { build: fn }` means `{ exec: fn }`, as `run: { build: 'cmd' }`
55
+ * means `{ exec: 'cmd' }`. Missing it made the two spellings disagree about *when* the function
56
+ * runs, which is worse than not supporting the short one at all. */
57
+ 'run.*',
58
+ 'run.*.before',
59
+ 'run.*.exec',
60
+ 'run.*.after',
61
+ /** A condition, evaluated per package by `RunService` when the run reaches it. Called here
62
+ * instead, it collapsed to the boolean it happened to return at load time - and `parseIfExpr`
63
+ * then read that boolean as "no condition given", so the script ran unconditionally (measured). */
64
+ 'run.*.if',
65
+ 'version.before',
66
+ 'version.exec',
67
+ 'version.after',
68
+ ];
69
+ /**
70
+ * Config paths left untouched when a repository's config is first resolved, and evaluated only by
71
+ * the command that runs them.
72
+ *
73
+ * `version`'s own hooks are the one place `${{ pkg.targetVersion }}` makes sense, and the version
74
+ * being written is not known until `version` has computed its plan - long after the config was
75
+ * resolved. Evaluating these eagerly would throw while merely *loading* the repository, so any
76
+ * command at all would fail on a config that mentions it.
77
+ */
78
+ export const DEFERRED_PATHS = ['version.before', 'version.exec', 'version.after'];
@@ -0,0 +1,192 @@
1
+ import type { RmanConfig } from '../../interfaces/rman-config.interface.js';
2
+ import type { Package } from '../classes/package.js';
3
+ import type { Repository } from '../classes/repository.js';
4
+ import { type Platform, type Plugin } from '../interfaces/plugin.js';
5
+ export declare class ConfigReader {
6
+ /**
7
+ *
8
+ * @protected
9
+ */
10
+ protected readonly configFiles: readonly string[];
11
+ /**
12
+ * Whether a config key names **packages** rather than a setting: `"[*]"`, `"[/]"`, `"[pkg-a]"`.
13
+ */
14
+ static isSelectorKey(key: string): boolean;
15
+ /**
16
+ * **Which packages a selector key speaks for.** Two audiences, and the second is a glob:
17
+ *
18
+ * | | matches | `test` is given |
19
+ * | --- | --- | --- |
20
+ * | `"[/]"` | the **root package** alone, structurally | - |
21
+ * | `"[platform:node]"`, `"[platform:node,cargo]"` | packages of those **technologies** | `pkg.platform.name` |
22
+ * | `"[*]"`, `"[pkg-a]"`, `"[*-dialect]"` | the packages **below** this directory the glob matches | `pkg.selector` |
23
+ *
24
+ * The glob is anchored at both ends, so `"[*-dialect]"` matches `mysql-dialect` but not
25
+ * `my-dialect-helper`. `"[ws:*]"` and `"[workspace:*]"` are accepted and mean exactly `"[*]"`.
26
+ */
27
+ static parseSelector(key: string): ConfigReader.ParsedSelector;
28
+ /**
29
+ *
30
+ */
31
+ resolve(dirname: string, options?: ConfigReader.Options): Promise<ConfigReader.ResolveResult>;
32
+ /**
33
+ *
34
+ * @protected
35
+ */
36
+ protected _resolve(context: ConfigReader.Context, options?: ConfigReader.Options): Promise<RmanConfig>;
37
+ protected _getDeclaredPlatform(config: RmanConfig): string | undefined;
38
+ /**
39
+ * The one config file `dirname` declares, or `undefined` for a directory that declares none.
40
+ *
41
+ * **Several is an error**, which is the whole point of reading the directory rather than probing
42
+ * the names in a fixed order: a probe cannot tell "this one" from "this one, and three others I
43
+ * am quietly folding in underneath". The message lists what it found, because the fix is to
44
+ * delete one and the reader has to know which are in play.
45
+ *
46
+ * Public because it answers a question a *reader* has and not only the resolver: `rman config`
47
+ * heads its output with the file you would open to change what it prints.
48
+ */
49
+ findConfigSource(dirname: string): string | undefined;
50
+ /** @see {@link ConfigReader.findConfigSource} */
51
+ protected _findConfigSource(dirname: string): string | undefined;
52
+ /** Reads one config file into a plain object. Nothing is merged and nothing is checked here
53
+ * beyond the file being an object at all - a config that is a list or a string is a mistake
54
+ * worth naming before any key of it is read. */
55
+ protected _readConfigFile(file: string): Promise<RmanConfig>;
56
+ /**
57
+ * Loads a config module - a `.rmanrc.cjs`/`.mjs`/`.js`, or an `extends` target that is one. The
58
+ * default export when there is one, the module's own exports object otherwise.
59
+ */
60
+ protected _loadConfigModule(file: string): Promise<any>;
61
+ protected _assertSelectorBlocks(config: RmanConfig, file: string): void;
62
+ protected _resolveExtends(context: ConfigReader.Context, config: RmanConfig, from: string, seen?: string[]): Promise<RmanConfig>;
63
+ /**
64
+ * Lays `options.presets` underneath this level's own config, exactly as an `extends` naming them
65
+ * would - so a repository that declares nothing still has rman's own technologies, commands and
66
+ * publish targets, and one that declares something still wins every key.
67
+ *
68
+ * Nothing happens without `options.presets`, which is how a level that is not the root - and a
69
+ * caller wanting a bare core - says so.
70
+ */
71
+ protected _applyPresets(config: RmanConfig, context: ConfigReader.Context, options?: ConfigReader.Options): Promise<RmanConfig>;
72
+ /**
73
+ * Loads the technologies a level's `platforms` names, into `context.platforms`.
74
+ *
75
+ * An entry is a `Platform`, or a glob naming `.js` modules that `export default` one. Already
76
+ * present by name, it is skipped - two layers naming one technology is ordinary rather than a
77
+ * mistake, and registering it twice would have two objects answering for one name.
78
+ */
79
+ protected _loadPlatforms(config: RmanConfig, context: ConfigReader.Context): Promise<void>;
80
+ /** Appends a technology unless one already answers to its name. */
81
+ protected _addPlatform(platform: Platform, context: ConfigReader.Context): void;
82
+ /** Appends a plugin unless one already answers to that name. */
83
+ protected _addPlugin(plugin: Plugin, context: ConfigReader.Context): void;
84
+ protected _loadPlugins(config: RmanConfig, context: ConfigReader.Context): Promise<void>;
85
+ /**
86
+ * Refuses a plugin that did not come through `definePlatform`/`definePlugin`.
87
+ *
88
+ * @param from where the entry came from, for the message - the config key for one written into
89
+ * the config, and the file for one a glob loaded.
90
+ */
91
+ protected _assertDeclaredPlugin(value: Plugin, from: string): void;
92
+ /**
93
+ * Loads the plugins a **string** `plugins` entry names.
94
+ *
95
+ * The string is a glob - never a package name, and already absolute by the time it arrives - so
96
+ * it may match several modules and this returns a list. An entry written as an instance does not
97
+ * come through here; it is already the plugin.
98
+ *
99
+ * Each match must `export default` a plugin declared through `definePlatform`/`definePlugin`.
100
+ * A glob matching nothing is an error.
101
+ */
102
+ protected _loadPluginsByEntry(entry: string): Promise<Plugin[]>;
103
+ /**
104
+ * Refuses whatever a glob matched when it is not the kind the key takes, naming what it *is*.
105
+ *
106
+ * @param want which key is being loaded, so the message can point at the other one.
107
+ */
108
+ protected _assertLoaded(value: unknown, file: string, want: Plugin.DeclaredKind): void;
109
+ /**
110
+ * Every default export a **glob** entry names, with the file each came from.
111
+ *
112
+ * Shared by `plugins` and `platforms`, which take the same two forms and differ only in what they
113
+ * accept back - so the caller checks the shape and this one only finds and imports.
114
+ *
115
+ * The glob is absolute by the time it arrives: `mergeConfig` anchors a contribution glob to the
116
+ * file that declared it (`anchorContributions`). Nothing here resolves a path, and a resolution
117
+ * step would make a preset's `'./x.js'` look in the consumer's directory. `.js` only - these are
118
+ * imported into rman's own process with no loader registered, so a `.ts` module cannot be one.
119
+ */
120
+ protected _loadByGlob(entry: string, key: string): Promise<{
121
+ value: unknown;
122
+ file: string;
123
+ }[]>;
124
+ /**
125
+ *
126
+ * @protected
127
+ */
128
+ protected _resolveExtendTarget(target: string, from: string, label: string): string;
129
+ /**
130
+ * Where one of rman's own presets lives - `extends: "rman:node"`.
131
+ *
132
+ * A preset is an ordinary config that happens to ship with rman: it contributes a technology, the
133
+ * commands that belong to it and its publish target, and it reaches a repository the same way any
134
+ * other config does.
135
+ */
136
+ protected _resolvePreset(name: string, label: string): string;
137
+ }
138
+ export declare namespace ConfigReader {
139
+ /** What a `"[...]"` key resolves to - see {@link ConfigReader.parseSelector}. */
140
+ interface ParsedSelector {
141
+ /**
142
+ * What `test` is asked about:
143
+ *
144
+ * - `'root'` - nothing; the root is matched by *being* the root.
145
+ * - `'platform'` - the package's `platform.name`.
146
+ * - `'package'` - the package's `selector`.
147
+ *
148
+ * A glob and a platform block both match packages below the root, never the root itself - its
149
+ * address is `"[/]"`.
150
+ */
151
+ scope: 'root' | 'package' | 'platform';
152
+ /** Whether a package's selector is one this key speaks for. Always `true` for a root key, which
153
+ * is matched by *being* the root rather than by name. */
154
+ test(name: string): boolean;
155
+ }
156
+ interface Options {
157
+ /** Plugins to start with - the application's. Optional like `platforms`, which it was not: a
158
+ * plugin used to be how a technology arrived, so a caller always had one. */
159
+ plugins?: Plugin[];
160
+ /**
161
+ * rman's own presets to lay **underneath** this level's config - `['node']`, the bare names
162
+ * `extends: "rman:node"` would have spelled. Omitted or empty, none are applied, which is what
163
+ * every level below the root passes and what a caller wanting a bare core passes too.
164
+ *
165
+ * They are loaded **after** whatever the config declared, so a repository's own technology is
166
+ * asked about a directory first.
167
+ */
168
+ presets?: readonly string[];
169
+ /** Technologies to start with - typically the application's. They come first, so a repository's
170
+ * own additions are appended after them. */
171
+ platforms?: Platform[];
172
+ }
173
+ interface Context {
174
+ dirname: string;
175
+ plugins: Plugin[];
176
+ platforms: Platform[];
177
+ }
178
+ interface ResolveResult {
179
+ config: RmanConfig;
180
+ /** Every plugin in play after this read - the ones passed in, plus whatever the config named. */
181
+ plugins: Plugin[];
182
+ /** Every technology in play, in the order it was contributed. A `platforms` entry comes before
183
+ * one a plugin carried, since a config naming a technology outright is the more direct
184
+ * statement. */
185
+ platforms: Platform[];
186
+ }
187
+ interface InterpolateArgs<T = RmanConfig> {
188
+ config: T;
189
+ repository: Repository;
190
+ pkg: Package;
191
+ }
192
+ }