rman 1.3.0 → 2.0.0-beta.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (187) hide show
  1. package/README.md +65 -31
  2. package/builtins/platforms/node/augmentation/rmanrc.augmentation.d.ts +83 -0
  3. package/builtins/platforms/node/augmentation/system-info.augmentation.d.ts +26 -0
  4. package/builtins/platforms/node/augmentation/system-info.augmentation.js +79 -0
  5. package/builtins/platforms/node/commands/ci.command.d.ts +133 -0
  6. package/builtins/platforms/node/commands/ci.command.js +60 -0
  7. package/builtins/platforms/node/commands/clean.command.d.ts +185 -0
  8. package/builtins/platforms/node/commands/clean.command.js +74 -0
  9. package/builtins/platforms/node/index.d.ts +8 -0
  10. package/builtins/platforms/node/index.js +8 -0
  11. package/builtins/platforms/node/node-config.interface.d.ts +76 -0
  12. package/builtins/platforms/node/node-config.interface.js +7 -0
  13. package/builtins/platforms/node/node-manifest.provider.d.ts +68 -0
  14. package/builtins/platforms/node/node-manifest.provider.js +125 -0
  15. package/builtins/platforms/node/node.platform.d.ts +53 -0
  16. package/builtins/platforms/node/node.platform.js +134 -0
  17. package/builtins/platforms/node/services/ci.service.d.ts +47 -0
  18. package/builtins/platforms/node/services/ci.service.js +213 -0
  19. package/builtins/platforms/node/services/clean.service.d.ts +53 -0
  20. package/builtins/platforms/node/services/clean.service.js +237 -0
  21. package/builtins/platforms/node/services/publish.service.d.ts +114 -0
  22. package/builtins/platforms/node/services/publish.service.js +371 -0
  23. package/builtins/platforms/node/services/version-plan.service.d.ts +44 -0
  24. package/builtins/platforms/node/services/version-plan.service.js +58 -0
  25. package/builtins/platforms/node/utils/workspace-range.d.ts +26 -0
  26. package/builtins/platforms/node/utils/workspace-range.js +28 -0
  27. package/builtins/presets/index.d.ts +15 -0
  28. package/builtins/presets/index.js +57 -0
  29. package/builtins/presets/node.d.ts +16 -0
  30. package/builtins/presets/node.js +57 -0
  31. package/{services → builtins/publish-targets/docker}/docker-publish.service.d.ts +52 -31
  32. package/{services → builtins/publish-targets/docker}/docker-publish.service.js +49 -26
  33. package/builtins/publish-targets/docker/docker.target.d.ts +54 -0
  34. package/builtins/publish-targets/docker/docker.target.js +40 -0
  35. package/builtins/publish-targets/docker/index.d.ts +2 -0
  36. package/builtins/publish-targets/docker/index.js +2 -0
  37. package/builtins/publish-targets/npm/index.d.ts +2 -0
  38. package/builtins/publish-targets/npm/index.js +2 -0
  39. package/builtins/publish-targets/npm/npm-publish-target.d.ts +73 -0
  40. package/builtins/publish-targets/npm/npm-publish-target.js +95 -0
  41. package/builtins/publish-targets/npm/npm-view.d.ts +48 -0
  42. package/builtins/publish-targets/npm/npm-view.js +71 -0
  43. package/cli.d.ts +8 -0
  44. package/cli.js +228 -93
  45. package/commands/build.command.d.ts +177 -3
  46. package/commands/build.command.js +20 -10
  47. package/commands/changelog.command.d.ts +296 -3
  48. package/commands/changelog.command.js +127 -43
  49. package/commands/config.command.d.ts +44 -3
  50. package/commands/config.command.js +53 -24
  51. package/commands/diff.command.d.ts +37 -3
  52. package/commands/diff.command.js +25 -16
  53. package/commands/exec.command.d.ts +193 -3
  54. package/commands/exec.command.js +60 -58
  55. package/commands/github-release.command.d.ts +154 -3
  56. package/commands/github-release.command.js +67 -37
  57. package/commands/import.command.d.ts +36 -3
  58. package/commands/import.command.js +28 -20
  59. package/commands/info.command.d.ts +35 -7
  60. package/commands/info.command.js +36 -30
  61. package/commands/lint.command.d.ts +176 -0
  62. package/commands/lint.command.js +34 -0
  63. package/commands/list.command.d.ts +163 -3
  64. package/commands/list.command.js +109 -71
  65. package/commands/publish.command.d.ts +231 -0
  66. package/commands/publish.command.js +304 -0
  67. package/commands/run.command.d.ts +186 -6
  68. package/commands/run.command.js +26 -72
  69. package/commands/test.command.d.ts +173 -3
  70. package/commands/test.command.js +16 -10
  71. package/commands/version.command.d.ts +330 -3
  72. package/commands/version.command.js +292 -78
  73. package/commands.d.ts +32 -0
  74. package/commands.js +28 -0
  75. package/constants.js +1 -1
  76. package/core/application.d.ts +116 -0
  77. package/core/application.js +160 -0
  78. package/core/classes/package.d.ts +219 -0
  79. package/core/classes/package.js +214 -0
  80. package/core/classes/registry.d.ts +30 -0
  81. package/core/classes/registry.js +47 -0
  82. package/core/{repository.d.ts → classes/repository.d.ts} +69 -20
  83. package/core/{repository.js → classes/repository.js} +195 -75
  84. package/core/classes/service.d.ts +49 -0
  85. package/core/classes/service.js +40 -0
  86. package/core/{version-scheme.d.ts → classes/version-scheme.d.ts} +23 -1
  87. package/core/{version-scheme.js → classes/version-scheme.js} +29 -1
  88. package/core/classes/workspace.d.ts +275 -0
  89. package/core/classes/workspace.js +537 -0
  90. package/core/command-builder.d.ts +14 -0
  91. package/core/command-builder.js +94 -0
  92. package/core/config/config-file-scope.d.ts +107 -0
  93. package/core/config/config-file-scope.js +226 -0
  94. package/core/config/config-interpolator.d.ts +164 -0
  95. package/core/config/config-interpolator.js +577 -0
  96. package/core/config/config-paths.d.ts +65 -0
  97. package/core/config/config-paths.js +78 -0
  98. package/core/config/config-reader.d.ts +192 -0
  99. package/core/config/config-reader.js +727 -0
  100. package/core/{merge-config.d.ts → config/merge-config.d.ts} +33 -34
  101. package/core/config/merge-config.js +260 -0
  102. package/core/{resolve-target.d.ts → config/resolve-config-target.d.ts} +1 -1
  103. package/core/{resolve-target.js → config/resolve-config-target.js} +1 -1
  104. package/core/{custom-command.d.ts → interfaces/custom-command.d.ts} +46 -10
  105. package/core/{custom-command.js → interfaces/custom-command.js} +44 -17
  106. package/core/{manifest.d.ts → interfaces/manifest.d.ts} +49 -27
  107. package/core/interfaces/manifest.js +132 -0
  108. package/core/interfaces/plugin.d.ts +174 -0
  109. package/core/interfaces/plugin.js +124 -0
  110. package/core/interfaces/publish-target.d.ts +136 -0
  111. package/core/interfaces/publish-target.js +43 -0
  112. package/core/{run-step.d.ts → interfaces/run-step.d.ts} +4 -4
  113. package/core/interfaces/run-step.js +1 -0
  114. package/core/plugin-loader.d.ts +25 -0
  115. package/core/plugin-loader.js +53 -0
  116. package/index.d.ts +122 -24
  117. package/index.js +66 -16
  118. package/interfaces/config-scope.interface.d.ts +223 -0
  119. package/interfaces/config-scope.interface.js +1 -0
  120. package/interfaces/rman-config.interface.d.ts +821 -203
  121. package/interfaces/rman-config.interface.js +78 -1
  122. package/package.json +3 -1
  123. package/services/change-hash.service.d.ts +42 -8
  124. package/services/change-hash.service.js +92 -13
  125. package/services/changelog.service.d.ts +91 -52
  126. package/services/changelog.service.js +460 -74
  127. package/services/config-service.d.ts +8 -0
  128. package/services/config-service.js +3 -0
  129. package/services/exec.service.d.ts +23 -12
  130. package/services/exec.service.js +14 -9
  131. package/services/github-release.service.d.ts +45 -34
  132. package/services/github-release.service.js +15 -12
  133. package/services/import.service.d.ts +25 -14
  134. package/services/import.service.js +9 -5
  135. package/services/list.service.d.ts +67 -13
  136. package/services/list.service.js +62 -15
  137. package/services/run.service.d.ts +35 -22
  138. package/services/run.service.js +316 -233
  139. package/services/system-info.d.ts +1 -1
  140. package/services/version-plan.service.d.ts +35 -8
  141. package/services/version-plan.service.js +96 -36
  142. package/services/version.service.d.ts +34 -14
  143. package/services/version.service.js +35 -16
  144. package/services.d.ts +1 -1
  145. package/services.js +1 -1
  146. package/utils/bin-path.d.ts +6 -7
  147. package/utils/bin-path.js +7 -18
  148. package/utils/branch-guard.d.ts +30 -1
  149. package/utils/branch-guard.js +31 -0
  150. package/utils/color-yaml.d.ts +8 -0
  151. package/utils/color-yaml.js +86 -0
  152. package/utils/exec.d.ts +10 -0
  153. package/utils/exec.js +1 -1
  154. package/utils/git.d.ts +26 -0
  155. package/utils/git.js +65 -0
  156. package/utils/logger.d.ts +2 -2
  157. package/utils/logger.js +1 -1
  158. package/utils/package-filter.d.ts +135 -8
  159. package/utils/package-filter.js +204 -16
  160. package/utils/printable-config.d.ts +9 -1
  161. package/utils/printable-config.js +46 -1
  162. package/utils/progress-panel.d.ts +9 -0
  163. package/utils/progress-panel.js +23 -1
  164. package/utils/release-version.d.ts +1 -1
  165. package/utils/run-bin.d.ts +10 -0
  166. package/utils/run-bin.js +1 -1
  167. package/utils/run-options.d.ts +97 -0
  168. package/utils/run-options.js +81 -0
  169. package/utils/version-group.d.ts +31 -0
  170. package/utils/version-group.js +43 -0
  171. package/utils/version-stamp.d.ts +1 -1
  172. package/utils/version-stamp.js +1 -1
  173. package/commands/changed.command.d.ts +0 -3
  174. package/commands/changed.command.js +0 -29
  175. package/core/config.d.ts +0 -409
  176. package/core/config.js +0 -939
  177. package/core/extends-config.d.ts +0 -27
  178. package/core/extends-config.js +0 -89
  179. package/core/manifest.js +0 -150
  180. package/core/merge-config.js +0 -219
  181. package/core/package.d.ts +0 -83
  182. package/core/package.js +0 -106
  183. package/core/plugin.d.ts +0 -112
  184. package/core/plugin.js +0 -189
  185. package/core/workspace.d.ts +0 -68
  186. package/core/workspace.js +0 -83
  187. /package/{core/run-step.js → builtins/platforms/node/augmentation/rmanrc.augmentation.js} +0 -0
@@ -0,0 +1,185 @@
1
+ import type { ArgsOf } from '../../../../index.js';
2
+ import type { ConfigValue } from '../../../../interfaces/rman-config.interface.js';
3
+ /** Hoisted for `ArgsOf` - see `ci.command.ts` and `RmanConfig.ArgsOf`. */
4
+ declare const COMMAND: "clean";
5
+ declare const config: {
6
+ progress: {
7
+ target: "cli";
8
+ describe: string;
9
+ type: "boolean";
10
+ };
11
+ dryRun: {
12
+ target: "cli";
13
+ cliName: string;
14
+ describe: string;
15
+ type: "boolean";
16
+ };
17
+ /** Config-only: `.rmanrc "clean.skip"` excludes a package from `clean` entirely. Not a flag -
18
+ * a single run narrows with `--scope`/`--ignore`, which every command already has. */
19
+ skip: {
20
+ target: "config";
21
+ describe: string;
22
+ type: "boolean";
23
+ };
24
+ fromRoot: {
25
+ target: "cli";
26
+ cliName: string;
27
+ alias: string;
28
+ describe: string;
29
+ type: "boolean";
30
+ };
31
+ allowBranch: {
32
+ target: "cli";
33
+ cliName: string;
34
+ describe: string;
35
+ type: "string";
36
+ };
37
+ ignoreBranch: {
38
+ target: "cli";
39
+ cliName: string;
40
+ describe: string;
41
+ type: "string";
42
+ };
43
+ scope: {
44
+ target: "cli";
45
+ describe: string;
46
+ type: "string";
47
+ };
48
+ ignore: {
49
+ target: "cli";
50
+ describe: string;
51
+ type: "string";
52
+ };
53
+ platform: {
54
+ target: "cli";
55
+ describe: string;
56
+ type: "string";
57
+ };
58
+ deps: {
59
+ target: "cli";
60
+ describe: string;
61
+ type: "boolean";
62
+ };
63
+ dependents: {
64
+ target: "cli";
65
+ describe: string;
66
+ type: "boolean";
67
+ };
68
+ };
69
+ /**
70
+ * The rest of `clean.*` - the two keys an option cannot describe.
71
+ *
72
+ * `include`/`exclude` are each **a glob or a list of them**, and a `CommandOption` says one or the
73
+ * other: `type: 'string'` is a string, `array: true` beside it is a `string[]`. Neither is the
74
+ * union, and the union is what a config author actually writes (`include: 'build'` as often as
75
+ * `include: ['build', '*.tsbuildinfo']`). So they are written out and intersected in, which is what
76
+ * `Extra` is for - `skip` above is an ordinary option and is derived like everything else.
77
+ */
78
+ export interface CleanExtraKeys {
79
+ /** Extra files and directories to remove, beyond TypeScript's own output - globs relative to
80
+ * each package's own directory. Per-package cascaded; a package declaring its own `clean` block
81
+ * replaces the root's entirely for itself, rather than combining with it. */
82
+ include?: ConfigValue<string | string[]>;
83
+ /** Globs to keep, applied after `include`. */
84
+ exclude?: ConfigValue<string | string[]>;
85
+ }
86
+ type Args = ArgsOf<typeof config, typeof COMMAND>;
87
+ /**
88
+ * `rman clean` - contributed by the `node` built-in rather than always present, because what
89
+ * it deletes is TypeScript's output. See `CleanService.clean`.
90
+ *
91
+ * Declared the same way `ci` is - see that file for why a plugin uses `declareCommand` rather than
92
+ * `registerCommand`.
93
+ */
94
+ export declare const cleanCommand: (app: import("../../../../index.js").RmanApplication) => {
95
+ command: "clean";
96
+ /** npm's alone: it deletes TypeScript build output, which no other ecosystem has. */
97
+ platforms: string[];
98
+ describe: string;
99
+ /**
100
+ * **No `configKeys`, because `clean` is this command's *own* key now** - derived from the
101
+ * `config` block above and contributed to `RmanConfig` by `CommandContribution`, exactly as a
102
+ * built-in contributes its own. It used to be hand-written in `NodeConfigKeys` *and* named
103
+ * here, which is two statements about one key.
104
+ *
105
+ * **The contribution itself is in `augmentation/rman.augmentation.ts`, not here**, and that is
106
+ * not a stylistic choice: one `declare module 'rman'` block per package is the limit, and a
107
+ * second silently disables the first. Measured again while moving this - a second block left
108
+ * `SystemInfo.PackageManager` unresolved at four call sites, with nothing pointing at the
109
+ * cause. rman's own commands declare theirs beside themselves because they augment a *module
110
+ * path*, which has no such limit.
111
+ */
112
+ config: {
113
+ progress: {
114
+ target: "cli";
115
+ describe: string;
116
+ type: "boolean";
117
+ };
118
+ dryRun: {
119
+ target: "cli";
120
+ cliName: string;
121
+ describe: string;
122
+ type: "boolean";
123
+ };
124
+ /** Config-only: `.rmanrc "clean.skip"` excludes a package from `clean` entirely. Not a flag -
125
+ * a single run narrows with `--scope`/`--ignore`, which every command already has. */
126
+ skip: {
127
+ target: "config";
128
+ describe: string;
129
+ type: "boolean";
130
+ };
131
+ fromRoot: {
132
+ target: "cli";
133
+ cliName: string;
134
+ alias: string;
135
+ describe: string;
136
+ type: "boolean";
137
+ };
138
+ allowBranch: {
139
+ target: "cli";
140
+ cliName: string;
141
+ describe: string;
142
+ type: "string";
143
+ };
144
+ ignoreBranch: {
145
+ target: "cli";
146
+ cliName: string;
147
+ describe: string;
148
+ type: "string";
149
+ };
150
+ scope: {
151
+ target: "cli";
152
+ describe: string;
153
+ type: "string";
154
+ };
155
+ ignore: {
156
+ target: "cli";
157
+ describe: string;
158
+ type: "string";
159
+ };
160
+ platform: {
161
+ target: "cli";
162
+ describe: string;
163
+ type: "string";
164
+ };
165
+ deps: {
166
+ target: "cli";
167
+ describe: string;
168
+ type: "boolean";
169
+ };
170
+ dependents: {
171
+ target: "cli";
172
+ describe: string;
173
+ type: "boolean";
174
+ };
175
+ };
176
+ examples: ({
177
+ command: string;
178
+ description?: undefined;
179
+ } | {
180
+ command: string;
181
+ description: string;
182
+ })[];
183
+ handler: (args: Args) => Promise<void>;
184
+ };
185
+ export {};
@@ -0,0 +1,74 @@
1
+ import { declareCommand } from '../../../../interfaces/rman-config.interface.js';
2
+ import { assertAllowedBranch, branchGuardOptions, readBranchGuardOptions } from '../../../../utils/branch-guard.js';
3
+ import { fromRootOption, packageFilterOptions, readPackageFilterOptions } from '../../../../utils/package-filter.js';
4
+ import { CleanService } from '../services/clean.service.js';
5
+ /** Hoisted for `ArgsOf` - see `ci.command.ts` and `RmanConfig.ArgsOf`. */
6
+ const COMMAND = 'clean';
7
+ const config = {
8
+ ...packageFilterOptions,
9
+ ...branchGuardOptions,
10
+ /** A group of one, and a function because its text is this command's own word for what it does. */
11
+ ...fromRootOption('Clean'),
12
+ progress: {
13
+ target: 'cli',
14
+ describe: 'Show a live progress panel (default: true; auto-disabled when not a TTY)',
15
+ type: 'boolean',
16
+ },
17
+ dryRun: {
18
+ target: 'cli',
19
+ cliName: 'dry-run',
20
+ describe: 'Report what would be removed without actually removing anything',
21
+ type: 'boolean',
22
+ },
23
+ /** Config-only: `.rmanrc "clean.skip"` excludes a package from `clean` entirely. Not a flag -
24
+ * a single run narrows with `--scope`/`--ignore`, which every command already has. */
25
+ skip: {
26
+ target: 'config',
27
+ describe: 'Excludes this package from clean entirely',
28
+ type: 'boolean',
29
+ },
30
+ };
31
+ /**
32
+ * `rman clean` - contributed by the `node` built-in rather than always present, because what
33
+ * it deletes is TypeScript's output. See `CleanService.clean`.
34
+ *
35
+ * Declared the same way `ci` is - see that file for why a plugin uses `declareCommand` rather than
36
+ * `registerCommand`.
37
+ */
38
+ export const cleanCommand = declareCommand(app => {
39
+ const repository = app.repository;
40
+ return {
41
+ command: COMMAND,
42
+ /** npm's alone: it deletes TypeScript build output, which no other ecosystem has. */
43
+ platforms: ['node'],
44
+ describe: 'Removes compiled TypeScript output and any extra files/dirs configured via .rmanrc "clean"',
45
+ /**
46
+ * **No `configKeys`, because `clean` is this command's *own* key now** - derived from the
47
+ * `config` block above and contributed to `RmanConfig` by `CommandContribution`, exactly as a
48
+ * built-in contributes its own. It used to be hand-written in `NodeConfigKeys` *and* named
49
+ * here, which is two statements about one key.
50
+ *
51
+ * **The contribution itself is in `augmentation/rman.augmentation.ts`, not here**, and that is
52
+ * not a stylistic choice: one `declare module 'rman'` block per package is the limit, and a
53
+ * second silently disables the first. Measured again while moving this - a second block left
54
+ * `SystemInfo.PackageManager` unresolved at four call sites, with nothing pointing at the
55
+ * cause. rman's own commands declare theirs beside themselves because they augment a *module
56
+ * path*, which has no such limit.
57
+ */
58
+ config,
59
+ examples: [
60
+ { command: '$0 clean' },
61
+ { command: '$0 clean --dry-run', description: '# Preview what would be removed' },
62
+ ],
63
+ handler: async (args) => {
64
+ await assertAllowedBranch(repository, readBranchGuardOptions(args));
65
+ await CleanService.clean(repository, {
66
+ ...readPackageFilterOptions(args),
67
+ progress: args.progress,
68
+ dryRun: args.dryRun,
69
+ fromRoot: args.fromRoot,
70
+ logLevel: args.logLevel,
71
+ });
72
+ },
73
+ };
74
+ });
@@ -0,0 +1,8 @@
1
+ export * from './augmentation/rmanrc.augmentation.js';
2
+ export * from './augmentation/system-info.augmentation.js';
3
+ export * from './commands/ci.command.js';
4
+ export * from './commands/clean.command.js';
5
+ export * from './node.platform.js';
6
+ export * from './node-config.interface.js';
7
+ export * from './node-manifest.provider.js';
8
+ export * from './utils/workspace-range.js';
@@ -0,0 +1,8 @@
1
+ export * from './augmentation/rmanrc.augmentation.js';
2
+ export * from './augmentation/system-info.augmentation.js';
3
+ export * from './commands/ci.command.js';
4
+ export * from './commands/clean.command.js';
5
+ export * from './node.platform.js';
6
+ export * from './node-config.interface.js';
7
+ export * from './node-manifest.provider.js';
8
+ export * from './utils/workspace-range.js';
@@ -0,0 +1,76 @@
1
+ import type { ConfigValue, RmanConfig, ScopedVars } from '../../../interfaces/rman-config.interface.js';
2
+ import type { CiService } from './services/ci.service.js';
3
+ /**
4
+ * The `.rmanrc` keys that only mean something because the repository is a Node one.
5
+ *
6
+ * **One key, and it is here because no single command owns it**: `packageManager` is read by `ci`
7
+ * *and* by the `npm` publish target, so neither can contribute it. Everything else this package
8
+ * adds to `.rmanrc` is declared by whoever reads it - `clean.*` by `clean.command.ts` (through
9
+ * `CommandContribution`), `publish.npm.*` by the target, below.
10
+ *
11
+ * **Two surfaces, and they are not alternatives:**
12
+ *
13
+ * - the `declare module 'rman'` block in [`../augmentation/rman.augmentation.ts`] merges this into
14
+ * `RmanConfigKeys`, so `repository.config.packageManager` stays typed wherever it is read with no
15
+ * cast. It lives there because one such block per package is the limit;
16
+ * - `RmanNodeConfig` is the name a *config author* annotates with, which is what makes the import
17
+ * carrying that augmentation explicit instead of a side effect someone has to remember.
18
+ */
19
+ export interface NodeConfigKeys {
20
+ /**
21
+ * Which package manager `ci`/`publish` shell out to, and whose version `info` reports under
22
+ * `Binaries`. Root level only. Default `npm`.
23
+ *
24
+ * It used to be a core key, on the grounds that `info` read it - and that stopped being true the
25
+ * moment `SystemInfo`'s npm half moved here: measured, **nothing in rman's core reads it at
26
+ * all**, only the declaration was left behind. The value set was npm's tooling the whole time.
27
+ */
28
+ packageManager?: CiService.PackageManager;
29
+ }
30
+ export declare namespace RmanNodeConfig {
31
+ /**
32
+ * **`publish.npm.*`** - the `npm` publish target's own block, contributed through the
33
+ * `PublishTargetConfigs` slot rman's `publish` command exports for any target.
34
+ *
35
+ * Named after the target, the way `publish.docker.*` already was. It used to be `publish.directory`
36
+ * - a bare key sitting directly beside `target`, `skip` and `docker`, so the one block that was
37
+ * *not* a target's read as though it belonged to publishing in general. `target` and `skip` are
38
+ * genuinely `publish`'s own; `directory` never was.
39
+ */
40
+ interface NpmPublishOptions extends NpmPublishOptionsKeys, ScopedVars {
41
+ }
42
+ interface NpmPublishOptionsKeys {
43
+ /** Where this package's publishable output lives, relative to its own directory (e.g.
44
+ * `"build"`). Per-package cascaded, so a root `"[*]"` block can say it once for the whole
45
+ * repository instead of repeating `publishConfig.directory` in every `package.json` - which
46
+ * still wins when a package declares it, being the more specific statement.
47
+ *
48
+ * Publishing from such a directory means the manifest there is **generated by `publish`**,
49
+ * from the package's own - see `PublishService`. There is nothing to configure about it. */
50
+ directory?: ConfigValue<string>;
51
+ }
52
+ }
53
+ /**
54
+ * `.rmanrc` for a repository using this plugin: rman's own keys plus the ones above.
55
+ *
56
+ * ```js
57
+ * // .rmanrc.mjs
58
+ * import { defineConfig } from 'rman';
59
+ *
60
+ * export default defineConfig({
61
+ * plugins: ['node'],
62
+ * '[*]': { clean: { include: 'build' }, publish: { npm: { directory: 'build' } } },
63
+ * });
64
+ * ```
65
+ *
66
+ * `.mjs`, not `.ts`: rman loads `.rmanrc.cjs`/`.mjs`/`.js` and no TypeScript form, so the type
67
+ * reaches a config file through the editor rather than through a compiler. The JSON and YAML forms
68
+ * carry no type at all - since the JSON Schema was removed, they are unchecked.
69
+ */
70
+ export interface RmanNodeConfig extends RmanConfig {
71
+ }
72
+ /**
73
+ * Identity helper for authoring a `.rmanrc.mjs`/`.cjs`/`.js` config with this plugin's keys checked
74
+ * - rman's own `defineConfig` with a narrower parameter, nothing more. Returns `config` unchanged.
75
+ */
76
+ export declare function defineConfig(config: RmanNodeConfig): RmanNodeConfig;
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Identity helper for authoring a `.rmanrc.mjs`/`.cjs`/`.js` config with this plugin's keys checked
3
+ * - rman's own `defineConfig` with a narrower parameter, nothing more. Returns `config` unchanged.
4
+ */
5
+ export function defineConfig(config) {
6
+ return config;
7
+ }
@@ -0,0 +1,68 @@
1
+ import type { Package } from '../../../core/classes/package.js';
2
+ import type { ManifestProvider } from '../../../core/interfaces/manifest.js';
3
+ import { Manifest } from '../../../core/interfaces/manifest.js';
4
+ export declare class NodeManifestProvider implements ManifestProvider {
5
+ name: string;
6
+ fileName: string;
7
+ read(dir: string): Manifest | undefined;
8
+ /**
9
+ * npm's four dependency fields, and only the entries naming a package of this repository -
10
+ * an external dependency is not an edge in rman's graph.
11
+ *
12
+ * Matched by name, which is npm's own identifier and unique by construction; an ecosystem where
13
+ * that does not hold resolves its own way, which is why this is the provider's job.
14
+ */
15
+ dependencies(manifest: Manifest, candidates: readonly Package[]): Package[];
16
+ /** npm's `@scope/name`. A name with no `/` has no scope and is its own unscoped form; the
17
+ * *last* `/` splits it, so `@scope/a/b` keeps `@scope/a` as the scope the registry would. */
18
+ splitName(name: string): {
19
+ scope?: string;
20
+ unscopedName: string;
21
+ };
22
+ /**
23
+ * Rewrites a sibling's range in all four fields after it was bumped.
24
+ *
25
+ * **A bare `"workspace:*"`/`"^"`/`"~"` selector is left alone**, and that is the load-bearing
26
+ * case: it resolves to the dependency's *current* version at publish time (see
27
+ * `resolveWorkspaceRange`), so rewriting it would replace a live reference with a frozen one.
28
+ * Only an explicit version after `workspace:` needs bumping, like a plain range.
29
+ */
30
+ updateDependencyVersions(manifest: Manifest, bumped: ReadonlyMap<Package, string>): void;
31
+ /**
32
+ * What the npm registry says this package's current version is - used *only* by
33
+ * `detectChangeHash`, to guess a tag name for a package that has no git tag yet. See
34
+ * `Plugin.publishedVersion` for why that is not a "has this been published" check.
35
+ *
36
+ * No `--registry`/`--userconfig`: a bare `npm view` run in the package's own directory already
37
+ * honours the repository's `.npmrc`, and the flags exist for `publish`'s CLI overrides, which
38
+ * this path has none of.
39
+ */
40
+ publishedVersion(pkg: Package): Promise<string | undefined>;
41
+ /**
42
+ * npm's source shape: a quoted string assigned to an identifier, which is what a `.ts`/`.js`
43
+ * version constant looks like. `constant` comes from the repository's own `version.stamp` entry,
44
+ * for a file whose identifier is not literally `version`.
45
+ *
46
+ * One line, because `stampVersionConstant` is exported for it - the *pattern* is shared by most
47
+ * languages, while *choosing* it is this ecosystem's call. A provider for a format with no
48
+ * identifier at all (a `pom.xml`) would ignore `constant` and match its own way.
49
+ */
50
+ stampVersion(file: string, content: string, version: string, options?: {
51
+ constant?: string;
52
+ }): string | undefined;
53
+ write(dir: string, manifest: Manifest): void;
54
+ }
55
+ /**
56
+ * `package.json` as rman's manifest: where an npm package's name and version are written.
57
+ *
58
+ * This is the deepest npm assumption that used to be in rman's core - `Package.name`,
59
+ * `Package.version`, `Package.json` and `Package.isPrivate` all read this file directly, which
60
+ * meant every command that asked a package what it was called was asking npm.
61
+ *
62
+ * The version scheme is left unset, so packages get the core's semver default: npm versions *are*
63
+ * semver, and saying so again here would only be a second place for the two to disagree.
64
+ */
65
+ export declare const packageJsonManifest: {};
66
+ /** npm's four dependency fields. Was `rman`'s `DEPENDENCY_KEYS`, which made the core carry npm's
67
+ * field names - `publish` imports it from here now. */
68
+ export declare const DEPENDENCY_KEYS: readonly ["dependencies", "devDependencies", "peerDependencies", "optionalDependencies"];
@@ -0,0 +1,125 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { Manifest } from '../../../core/interfaces/manifest.js';
4
+ import { stampVersionConstant } from '../../../utils/version-stamp.js';
5
+ import { npmViewVersion } from '../../publish-targets/npm/npm-view.js';
6
+ import { parseWorkspaceRange } from './utils/workspace-range.js';
7
+ export class NodeManifestProvider {
8
+ name = 'node';
9
+ fileName = 'package.json';
10
+ read(dir) {
11
+ const file = path.join(dir, 'package.json');
12
+ if (!fs.existsSync(file))
13
+ return undefined;
14
+ const raw = JSON.parse(fs.readFileSync(file, 'utf-8'));
15
+ return {
16
+ /** A `package.json` with no `name` is unusual but legal, and `info` prints such a package
17
+ * rather than refusing it - so the directory name stands in, as it does for a package with
18
+ * no manifest at all. */
19
+ name: typeof raw?.name === 'string' && raw.name ? raw.name : path.basename(dir),
20
+ version: typeof raw?.version === 'string' && raw.version ? raw.version : '0.0.0',
21
+ private: !!raw?.private,
22
+ raw: raw ?? {},
23
+ };
24
+ }
25
+ /**
26
+ * npm's four dependency fields, and only the entries naming a package of this repository -
27
+ * an external dependency is not an edge in rman's graph.
28
+ *
29
+ * Matched by name, which is npm's own identifier and unique by construction; an ecosystem where
30
+ * that does not hold resolves its own way, which is why this is the provider's job.
31
+ */
32
+ dependencies(manifest, candidates) {
33
+ const declared = Object.assign({}, ...DEPENDENCY_KEYS.map(key => manifest.raw[key]));
34
+ const byName = new Map(candidates.map(p => [p.name, p]));
35
+ const result = [];
36
+ for (const name of Object.keys(declared)) {
37
+ const pkg = byName.get(name);
38
+ if (pkg && !result.includes(pkg))
39
+ result.push(pkg);
40
+ }
41
+ return result;
42
+ }
43
+ /** npm's `@scope/name`. A name with no `/` has no scope and is its own unscoped form; the
44
+ * *last* `/` splits it, so `@scope/a/b` keeps `@scope/a` as the scope the registry would. */
45
+ splitName(name) {
46
+ const at = name.lastIndexOf('/');
47
+ return at > 0 ? { scope: name.slice(0, at), unscopedName: name.slice(at + 1) } : { unscopedName: name };
48
+ }
49
+ /**
50
+ * Rewrites a sibling's range in all four fields after it was bumped.
51
+ *
52
+ * **A bare `"workspace:*"`/`"^"`/`"~"` selector is left alone**, and that is the load-bearing
53
+ * case: it resolves to the dependency's *current* version at publish time (see
54
+ * `resolveWorkspaceRange`), so rewriting it would replace a live reference with a frozen one.
55
+ * Only an explicit version after `workspace:` needs bumping, like a plain range.
56
+ */
57
+ updateDependencyVersions(manifest, bumped) {
58
+ const versionByName = new Map([...bumped].map(([pkg, version]) => [pkg.name, version]));
59
+ for (const depKey of DEPENDENCY_KEYS) {
60
+ const deps = manifest.raw[depKey];
61
+ if (!deps)
62
+ continue;
63
+ for (const depName of Object.keys(deps)) {
64
+ const to = versionByName.get(depName);
65
+ if (!to)
66
+ continue;
67
+ const workspace = parseWorkspaceRange(deps[depName]);
68
+ if (workspace) {
69
+ if (workspace.selector === 'explicit')
70
+ deps[depName] = `workspace:^${to}`;
71
+ continue;
72
+ }
73
+ deps[depName] = '^' + to;
74
+ }
75
+ }
76
+ }
77
+ /**
78
+ * What the npm registry says this package's current version is - used *only* by
79
+ * `detectChangeHash`, to guess a tag name for a package that has no git tag yet. See
80
+ * `Plugin.publishedVersion` for why that is not a "has this been published" check.
81
+ *
82
+ * No `--registry`/`--userconfig`: a bare `npm view` run in the package's own directory already
83
+ * honours the repository's `.npmrc`, and the flags exist for `publish`'s CLI overrides, which
84
+ * this path has none of.
85
+ */
86
+ publishedVersion(pkg) {
87
+ return npmViewVersion(pkg.name, pkg.dirname);
88
+ }
89
+ /**
90
+ * npm's source shape: a quoted string assigned to an identifier, which is what a `.ts`/`.js`
91
+ * version constant looks like. `constant` comes from the repository's own `version.stamp` entry,
92
+ * for a file whose identifier is not literally `version`.
93
+ *
94
+ * One line, because `stampVersionConstant` is exported for it - the *pattern* is shared by most
95
+ * languages, while *choosing* it is this ecosystem's call. A provider for a format with no
96
+ * identifier at all (a `pom.xml`) would ignore `constant` and match its own way.
97
+ */
98
+ stampVersion(file, content, version, options) {
99
+ return stampVersionConstant(content, version, options?.constant);
100
+ }
101
+ write(dir, manifest) {
102
+ /**
103
+ * The version is written back into `raw` before serializing, because `raw` is the document and
104
+ * `manifest.version` is rman's view of one field in it. Writing only the view would produce a
105
+ * file whose `version` never changed; writing only `raw` would leave the two disagreeing for
106
+ * anything still holding the manifest.
107
+ */
108
+ const raw = { ...manifest.raw, version: manifest.version };
109
+ fs.writeFileSync(path.join(dir, 'package.json'), JSON.stringify(raw, undefined, 2) + '\n', 'utf-8');
110
+ }
111
+ }
112
+ /**
113
+ * `package.json` as rman's manifest: where an npm package's name and version are written.
114
+ *
115
+ * This is the deepest npm assumption that used to be in rman's core - `Package.name`,
116
+ * `Package.version`, `Package.json` and `Package.isPrivate` all read this file directly, which
117
+ * meant every command that asked a package what it was called was asking npm.
118
+ *
119
+ * The version scheme is left unset, so packages get the core's semver default: npm versions *are*
120
+ * semver, and saying so again here would only be a second place for the two to disagree.
121
+ */
122
+ export const packageJsonManifest = {};
123
+ /** npm's four dependency fields. Was `rman`'s `DEPENDENCY_KEYS`, which made the core carry npm's
124
+ * field names - `publish` imports it from here now. */
125
+ export const DEPENDENCY_KEYS = ['dependencies', 'devDependencies', 'peerDependencies', 'optionalDependencies'];
@@ -0,0 +1,53 @@
1
+ import type { Package } from '../../../core/classes/package.js';
2
+ import type { Platform } from '../../../core/interfaces/plugin.js';
3
+ import type { RunService } from '../../../services/run.service.js';
4
+ import { NodeManifestProvider } from './node-manifest.provider.js';
5
+ import { NodeVersionPlanService } from './services/version-plan.service.js';
6
+ export declare class NodePlatform implements Platform {
7
+ /** The ecosystem, not the file - this is what every package it reads reports as
8
+ * `pkg.provider === 'node'`. `manifestProvider.fileName` already says `package.json`. */
9
+ name: string;
10
+ manifestProvider: NodeManifestProvider;
11
+ versionPlanner: NodeVersionPlanService;
12
+ /**
13
+ * npm's `workspaces` globs, resolved against `dir` - the directories directly below it that hold
14
+ * a `package.json`.
15
+ *
16
+ * **Asked of every directory the walk reaches, not only of the repository root**, which is what
17
+ * the seam changing from a layout to a per-directory question bought: a `package.json` naming
18
+ * `workspaces` is a workspace root wherever it sits, so a Node sub-workspace inside a larger
19
+ * repository is now found by the same code that finds the top one. `deep: 0` already made the
20
+ * globs one level, so nothing here had to change to make that true.
21
+ */
22
+ getWorkspace(dir: string): string[] | undefined;
23
+ /**
24
+ * Teaches `run` about `package.json#scripts`.
25
+ *
26
+ * rman's core resolves a script from `.rmanrc` alone - `before`/`exec`/`after`. That a script might
27
+ * *also* live in `package.json`, that `prebuild` and `postbuild` run around `build`, and that
28
+ * `a && b` is two steps rather than one, are all facts about npm, so they are here.
29
+ *
30
+ * Registered as a `RunService` step source rather than by wrapping anything: the npm part of `run`
31
+ * is inside step resolution, not at its entry point, so there is nothing a wrapper could reach.
32
+ * The core decides what to do with what this returns - see `getScriptSteps` for the precedence.
33
+ */
34
+ getRunSteps(pkg: Package, script: string): RunService.ScriptSlots | undefined;
35
+ /**
36
+ * Where npm puts a repository's locally installed executables: `node_modules/.bin`, at **every**
37
+ * level from `cwd` up to the filesystem root - which is how npm itself resolves a binary, so a
38
+ * package's `eslint` is found whether it was installed in that package or hoisted to the workspace
39
+ * root.
40
+ *
41
+ * Adapted from [npm-run-path](https://github.com/sindresorhus/npm-run-path), and it used to sit in
42
+ * rman's core. It is npm's directory layout from end to end: a Cargo or Go repository has no
43
+ * `node_modules` to walk, and nothing here would ever fire for it.
44
+ *
45
+ * **The running `node`'s own directory goes last**, after the walk, and its position is
46
+ * load-bearing. It is there so a script calling `node` gets the interpreter rman itself runs on
47
+ * rather than whatever the shell would pick. It also puts rman's own bin directory ahead of the
48
+ * inherited PATH, which is a measured trap: a nested `rman` invocation inside a `run` script
49
+ * resolves to the globally installed one, not to the repository's. Shim it in
50
+ * `<root>/node_modules/.bin` when that has to be overridden - the walk above reaches there first.
51
+ */
52
+ getBinPaths(cwd: string): string[];
53
+ }