rman 2.11.3 → 2.12.0

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.
@@ -33,7 +33,7 @@ export declare namespace CiService {
33
33
  * `"ci"` script, runs that instead. Once every package is clean, installs once at the root
34
34
  * with the configured package manager (`npm`/`yarn`/`pnpm`/`bun`).
35
35
  *
36
- * Uses the same live progress panel as `run`/`build` (see `../utils/progress-panel.ts`) while it
36
+ * Uses the same live progress panel as `run`/`build` (see `core/classes/progress-panel.ts`) while it
37
37
  * runs, falling back to a plain rmdir/clean/run/install log line per step when the panel is off.
38
38
  *
39
39
  * Unlike `run`/`build`, it does *not* end with a per-package success tally: `ci`'s packages don't
@@ -2,9 +2,9 @@ import fs from 'node:fs/promises';
2
2
  import path from 'node:path';
3
3
  import colors from 'ansi-colors';
4
4
  import { Logger, resolveRootLogLevel } from '../../../../core/classes/logger.js';
5
+ import { formatDuration, ProgressPanel } from '../../../../core/classes/progress-panel.js';
5
6
  import { exec } from '../../../../utils/exec.js';
6
7
  import { filterPackages } from '../../../../utils/package-filter.js';
7
- import { formatDuration, ProgressPanel } from '../../../../utils/progress-panel.js';
8
8
  export var CiService;
9
9
  (function (CiService) {
10
10
  /**
@@ -53,7 +53,7 @@ export var CiService;
53
53
  * `"ci"` script, runs that instead. Once every package is clean, installs once at the root
54
54
  * with the configured package manager (`npm`/`yarn`/`pnpm`/`bun`).
55
55
  *
56
- * Uses the same live progress panel as `run`/`build` (see `../utils/progress-panel.ts`) while it
56
+ * Uses the same live progress panel as `run`/`build` (see `core/classes/progress-panel.ts`) while it
57
57
  * runs, falling back to a plain rmdir/clean/run/install log line per step when the panel is off.
58
58
  *
59
59
  * Unlike `run`/`build`, it does *not* end with a per-package success tally: `ci`'s packages don't
@@ -46,7 +46,7 @@ export declare namespace CleanService {
46
46
  * Run from inside a single package's own directory, it only cleans that package unless
47
47
  * `options.fromRoot` says otherwise (see `Repository.currentPackage`).
48
48
  *
49
- * Uses the same live progress panel as `run`/`build` (see `../utils/progress-panel.ts`) - unlike
49
+ * Uses the same live progress panel as `run`/`build` (see `core/classes/progress-panel.ts`) - unlike
50
50
  * `ci`, cleaning genuinely is independent per-package work, so the final per-package tally stays.
51
51
  */
52
52
  function clean(repository: Repository, options?: Options): Promise<void>;
@@ -3,8 +3,8 @@ import path from 'node:path';
3
3
  import colors from 'ansi-colors';
4
4
  import fg from 'fast-glob';
5
5
  import { Logger, resolveRootLogLevel } from '../../../../core/classes/logger.js';
6
+ import { ProgressPanel } from '../../../../core/classes/progress-panel.js';
6
7
  import { filterPackages } from '../../../../utils/package-filter.js';
7
- import { ProgressPanel } from '../../../../utils/progress-panel.js';
8
8
  export var CleanService;
9
9
  (function (CleanService) {
10
10
  /**
@@ -38,7 +38,7 @@ export var CleanService;
38
38
  * Run from inside a single package's own directory, it only cleans that package unless
39
39
  * `options.fromRoot` says otherwise (see `Repository.currentPackage`).
40
40
  *
41
- * Uses the same live progress panel as `run`/`build` (see `../utils/progress-panel.ts`) - unlike
41
+ * Uses the same live progress panel as `run`/`build` (see `core/classes/progress-panel.ts`) - unlike
42
42
  * `ci`, cleaning genuinely is independent per-package work, so the final per-package tally stays.
43
43
  */
44
44
  async function clean(repository, options = {}) {
@@ -128,6 +128,11 @@ export declare namespace PublishService {
128
128
  * excludes it for a real monorepo (it only doubles as "the" package in a single-package repo,
129
129
  * where it's a normal candidate like any other).
130
130
  */
131
+ /**
132
+ * Why the npm target leaves `pkg` alone, from its manifest alone - `'private package'`, or
133
+ * `undefined` when it would be published. `rman list` asks this to grey a package out.
134
+ */
135
+ function skipReason(pkg: Package, contentsOverride?: string): string | undefined;
131
136
  function getPlan(repository: Repository, options?: Options, deps?: Deps): Promise<Entry[]>;
132
137
  /**
133
138
  * Publishes every `'publish'` entry in `plan`, topological order (already `plan`'s own order -
@@ -153,6 +153,26 @@ export var PublishService;
153
153
  * excludes it for a real monorepo (it only doubles as "the" package in a single-package repo,
154
154
  * where it's a normal candidate like any other).
155
155
  */
156
+ /**
157
+ * Why the npm target leaves `pkg` alone, from its manifest alone - `'private package'`, or
158
+ * `undefined` when it would be published. `rman list` asks this to grey a package out.
159
+ */
160
+ /* **The one statement of npm's `private` rule**, called by `getPlan` and by `NpmPublishTarget.
161
+ * skipReason` both, so the plan and the list cannot disagree. Two cases, both private:
162
+ * - **no `publishConfig`** (`privateBySource`) - private in the published manifest too, wherever it
163
+ * is published from;
164
+ * - **published in place** - the source manifest *is* the published one, so its `private` stands
165
+ * whatever else it declares.
166
+ * The second sat after the build-output check in `getPlan` and moved ahead of it unchanged:
167
+ * `hasBuildOutput` is always true in place, so nothing reached it any differently. */
168
+ function skipReason(pkg, contentsOverride) {
169
+ if (!pkg.manifest.raw.private)
170
+ return undefined;
171
+ if (privateBySource(pkg) || publishesInPlace(pkg, contentsOverride))
172
+ return 'private package';
173
+ return undefined;
174
+ }
175
+ PublishService.skipReason = skipReason;
156
176
  async function getPlan(repository, options = {}, deps = {}) {
157
177
  const git = new GitHelper({ cwd: repository.dirname });
158
178
  const packages = filterPackages(repository.getPackages({ toposort: true }), options);
@@ -173,6 +193,7 @@ export var PublishService;
173
193
  * finding that out after a round trip per package would be a slower way to the same
174
194
  * refusal. */
175
195
  const distTag = distTagFor(pkg, options.tag);
196
+ const privateReason = skipReason(pkg, options.contents);
176
197
  if (retiredDirectoryKey(pkg)) {
177
198
  entries.set(pkg.name, {
178
199
  package: pkg,
@@ -189,8 +210,8 @@ export var PublishService;
189
210
  reason: 'excluded via .rmanrc "publish.skip"',
190
211
  });
191
212
  }
192
- else if (privateBySource(pkg)) {
193
- entries.set(pkg.name, { package: pkg, version: pkg.version, status: 'skip', reason: 'private package' });
213
+ else if (privateReason) {
214
+ entries.set(pkg.name, { package: pkg, version: pkg.version, status: 'skip', reason: privateReason });
194
215
  }
195
216
  else if (!hasBuildOutput(pkg, options.contents)) {
196
217
  const dir = path.relative(pkg.dirname, resolvePublishDir(pkg, options.contents)) || '.';
@@ -201,9 +222,6 @@ export var PublishService;
201
222
  reason: `nothing to publish in "${dir}" - it is missing or empty; build the package first`,
202
223
  });
203
224
  }
204
- else if (publishesInPlace(pkg, options.contents) && pkg.manifest.raw.private) {
205
- entries.set(pkg.name, { package: pkg, version: pkg.version, status: 'skip', reason: 'private package' });
206
- }
207
225
  else if (distTag.error) {
208
226
  entries.set(pkg.name, { package: pkg, version: pkg.version, status: 'error', reason: distTag.error });
209
227
  }
@@ -1,3 +1,4 @@
1
+ import type { Package } from '../../../core/classes/package.js';
1
2
  import type { PublishTarget } from '../../../core/interfaces/publish-target.js';
2
3
  import { PublishService } from '../../platforms/node/services/publish.service.js';
3
4
  /** The name this target answers to in `publish.target` and `--target`. */
@@ -70,6 +71,8 @@ export declare class NpmPublishTarget implements PublishTarget {
70
71
  type: "string";
71
72
  };
72
73
  };
74
+ /** npm's `private` rule, the same function `getPlan` asks. */
75
+ skipReason(pkg: Package): string | undefined;
73
76
  getPlan(ctx: PublishTarget.Context): Promise<PublishService.Entry[]>;
74
77
  applyPlan(ctx: PublishTarget.Context, plan: PublishTarget.Entry[]): Promise<PublishService.Entry[]>;
75
78
  /** The shared filters plus the two flags both halves need - read here rather than in the
@@ -75,6 +75,10 @@ export class NpmPublishTarget {
75
75
  type: 'string',
76
76
  },
77
77
  };
78
+ /** npm's `private` rule, the same function `getPlan` asks. */
79
+ skipReason(pkg) {
80
+ return PublishService.skipReason(pkg);
81
+ }
78
82
  getPlan(ctx) {
79
83
  return PublishService.getPlan(ctx.repository, this.planOptions(ctx));
80
84
  }
@@ -1,10 +1,10 @@
1
1
  import path from 'node:path';
2
2
  import colors from 'ansi-colors';
3
3
  import { Logger, resolveRootLogLevel } from '../core/classes/logger.js';
4
+ import { ProgressPanel } from '../core/classes/progress-panel.js';
4
5
  import { registerCommand } from '../interfaces/rman-config.interface.js';
5
6
  import { ChangeHashService } from '../services/change-hash.service.js';
6
7
  import { fromRootOption, packageFilterOptions, readPackageFilterOptions } from '../utils/package-filter.js';
7
- import { ProgressPanel } from '../utils/progress-panel.js';
8
8
  const COMMAND = 'changelog';
9
9
  const config = {
10
10
  ...packageFilterOptions,
@@ -100,6 +100,11 @@ function statusLabel(status) {
100
100
  return '';
101
101
  }
102
102
  }
103
+ /** Where a package ships, one target name each - grey for a target `publish` would skip it for
104
+ * (`Item.skippedTargets`), so the column never reads as a promise the release will not keep. */
105
+ function publishLabel(it) {
106
+ return it.publishTargets.map(name => (it.skippedTargets[name] ? colors.gray(name) : colors.green(name))).join(', ');
107
+ }
103
108
  /**
104
109
  * **The tree, as a table**: the root first, then each package indented by how far below it sits.
105
110
  *
@@ -126,6 +131,7 @@ function printTable(items, withRoot) {
126
131
  table.cell('Version', colors.yellow(it.version));
127
132
  table.cell('Platform', it.platform ? colors.cyan(it.platform) : '');
128
133
  table.cell('Private', it.private ? colors.magentaBright('yes') : '');
134
+ table.cell('Publish', publishLabel(it));
129
135
  table.cell('Changed', statusLabel(it.status));
130
136
  table.cell('Path', it.location);
131
137
  table.newRow();
package/constants.js CHANGED
@@ -1 +1 @@
1
- export const version = '2.11.3';
1
+ export const version = '2.12.0';
@@ -1,5 +1,5 @@
1
- import type { ProgressItem } from '../../utils/progress-panel.js';
2
1
  import type { LogLevel } from './logger.js';
2
+ import type { ProgressItem } from './progress-panel.js';
3
3
  /**
4
4
  * One thing that happened during a run, in the order it happened. The JSON form is exactly this
5
5
  * object with a `time` added; the text form is one line per event.
@@ -1,5 +1,5 @@
1
+ import type { StatusRegion, TerminalRegion } from '../../utils/status-region.js';
1
2
  import { LiveRegion } from './live-region.js';
2
- import type { StatusRegion, TerminalRegion } from './status-region.js';
3
3
  export type ProgressStatus = 'pending' | 'running' | 'success' | 'failed' | 'skipped';
4
4
  export interface ProgressItem {
5
5
  readonly name: string;
@@ -1,6 +1,6 @@
1
- import type { ProgressPanel } from '../../utils/progress-panel.js';
2
1
  import type { LogEvent, Reporter, ReportOrigin } from './log-sink.js';
3
2
  import { type LogLevel } from './logger.js';
3
+ import type { ProgressPanel } from './progress-panel.js';
4
4
  /**
5
5
  * The screen with no live panel: each line a step prints, led by its package, and one line per step
6
6
  * when it ends - the output `--no-progress`, a pipe or CI gets.
@@ -61,6 +61,14 @@ export interface PublishTarget {
61
61
  * let through.
62
62
  */
63
63
  claims?(pkg: Package): boolean;
64
+ /**
65
+ * Why this target would leave a package it ships to alone, or `undefined` when it would not -
66
+ * answered from the config and the manifest alone, with no registry and no build.
67
+ *
68
+ * `publish.skip` is the core's and is asked before this (see `skipReasonFor`); a target answers
69
+ * only what is its own, such as npm's `private`.
70
+ */
71
+ skipReason?(pkg: Package): string | undefined;
64
72
  /** What this target *would* do - never publishes. Called even under `--dry-run`, which is the
65
73
  * whole point of the split. */
66
74
  getPlan(ctx: PublishTarget.Context): Promise<PublishTarget.Entry[]>;
@@ -131,6 +139,10 @@ export declare function shipsTo(pkg: Package, target: PublishTarget): boolean;
131
139
  /** Every registered target `pkg` ships to, in registration order. The single answer to "where does
132
140
  * this package go", so `publish` and `list --json` cannot disagree about it. */
133
141
  export declare function targetsOf(app: RmanApplication, pkg: Package): PublishTarget[];
142
+ /** Why `target` would leave `pkg` alone, or `undefined` when it would publish it: `.rmanrc
143
+ * "publish.skip"`, which excludes a package from every target, and then the target's own
144
+ * `skipReason`. */
145
+ export declare function skipReasonFor(pkg: Package, target: PublishTarget): string | undefined;
134
146
  /** Names in a package's `publish.target` that no registered target answers to - a misconfiguration
135
147
  * that used to be caught by a `choices: ['npm', 'docker']` the core can no longer write down. */
136
148
  export declare function unknownTargets(app: RmanApplication, pkg: Package): string[];
@@ -32,6 +32,14 @@ export function shipsTo(pkg, target) {
32
32
  export function targetsOf(app, pkg) {
33
33
  return app.publishTargets.all.filter(target => shipsTo(pkg, target));
34
34
  }
35
+ /** Why `target` would leave `pkg` alone, or `undefined` when it would publish it: `.rmanrc
36
+ * "publish.skip"`, which excludes a package from every target, and then the target's own
37
+ * `skipReason`. */
38
+ export function skipReasonFor(pkg, target) {
39
+ if (pkg.config.publish?.skip)
40
+ return 'excluded via .rmanrc "publish.skip"';
41
+ return target.skipReason?.(pkg);
42
+ }
35
43
  /** Names in a package's `publish.target` that no registered target answers to - a misconfiguration
36
44
  * that used to be caught by a `choices: ['npm', 'docker']` the core can no longer write down. */
37
45
  export function unknownTargets(app, pkg) {
package/index.d.ts CHANGED
@@ -65,7 +65,7 @@ export { Manifest } from './core/interfaces/manifest.js';
65
65
  export { Registry } from './core/classes/registry.js';
66
66
  export { Repository } from './core/classes/repository.js';
67
67
  export { Service, type ServiceFactory, type ServiceMap } from './core/classes/service.js';
68
- export { declaredTargets, type PublishTarget, shipsTo, targetsOf, unknownTargets, } from './core/interfaces/publish-target.js';
68
+ export { declaredTargets, type PublishTarget, shipsTo, skipReasonFor, targetsOf, unknownTargets, } from './core/interfaces/publish-target.js';
69
69
  export type { RunConditionFn, RunStepContext, RunStepFn, RunStepObject, RunStepValue, } from './core/interfaces/run-step.js';
70
70
  /**
71
71
  * **`Platform` is one technology, whole**; **`Plugin` is whatever a package contributes**, platforms
@@ -145,7 +145,7 @@ export { GitHelper } from './utils/git.js';
145
145
  export { applyFromRootOption, applyPackageFilterOptions, filterPackages, fromRootOption, type PackageFilterOptions, packageFilterOptions, readFromRootOption, readPackageFilterOptions, ROOT_SELECTOR, } from './utils/package-filter.js';
146
146
  /** The live panel `run`/`build`/`clean` print - a plugin's per-package command looks like the rest
147
147
  * of rman instead of like a script someone bolted on. */
148
- export { formatDuration, type ProgressItem, ProgressPanel, type ProgressStatus, type ProgressSummary, } from './utils/progress-panel.js';
148
+ export { formatDuration, type ProgressItem, ProgressPanel, type ProgressStatus, type ProgressSummary, } from './core/classes/progress-panel.js';
149
149
  /** Version stamping helpers a `Plugin.stampVersion` can delegate to - the quoted-constant
150
150
  * pattern most languages share, and the OCI Dockerfile label (which `version` stamps itself, since
151
151
  * the label's value is by specification the package's version). */
package/index.js CHANGED
@@ -71,7 +71,7 @@ export { Manifest } from './core/interfaces/manifest.js';
71
71
  export { Registry } from './core/classes/registry.js';
72
72
  export { Repository } from './core/classes/repository.js';
73
73
  export { Service } from './core/classes/service.js';
74
- export { declaredTargets, shipsTo, targetsOf, unknownTargets, } from './core/interfaces/publish-target.js';
74
+ export { declaredTargets, shipsTo, skipReasonFor, targetsOf, unknownTargets, } from './core/interfaces/publish-target.js';
75
75
  export { basePlatform, definePlatform, definePlugin, isPlatform, } from './core/interfaces/plugin.js';
76
76
  /** The numbering seam. `VersionScheme` is abstract - `highestVersion`/`highestBump`/`smallestBump`
77
77
  * are implemented from the members around them, so a scheme states only what it must and still
@@ -128,7 +128,7 @@ export { GitHelper } from './utils/git.js';
128
128
  export { applyFromRootOption, applyPackageFilterOptions, filterPackages, fromRootOption, packageFilterOptions, readFromRootOption, readPackageFilterOptions, ROOT_SELECTOR, } from './utils/package-filter.js';
129
129
  /** The live panel `run`/`build`/`clean` print - a plugin's per-package command looks like the rest
130
130
  * of rman instead of like a script someone bolted on. */
131
- export { formatDuration, ProgressPanel, } from './utils/progress-panel.js';
131
+ export { formatDuration, ProgressPanel, } from './core/classes/progress-panel.js';
132
132
  export { CiService } from './builtins/platforms/node/services/ci.service.js';
133
133
  export { CleanService } from './builtins/platforms/node/services/clean.service.js';
134
134
  export { PublishService } from './builtins/platforms/node/services/publish.service.js';
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "rman",
3
3
  "description": "Repository manager",
4
- "version": "2.11.3",
4
+ "version": "2.12.0",
5
5
  "author": "Panates",
6
6
  "license": "MIT",
7
7
  "dependencies": {
@@ -2,10 +2,10 @@ import os from 'node:os';
2
2
  import colors from 'ansi-colors';
3
3
  import { Task } from 'power-tasks';
4
4
  import { Logger, resolveRootLogLevel } from '../core/classes/logger.js';
5
+ import { ProgressPanel } from '../core/classes/progress-panel.js';
5
6
  import { Service } from '../core/classes/service.js';
6
7
  import { exec as execCommand } from '../utils/exec.js';
7
8
  import { filterPackages } from '../utils/package-filter.js';
8
- import { ProgressPanel } from '../utils/progress-panel.js';
9
9
  /**
10
10
  * A service class - see `ListService` for the shape and `Service` for the three measured
11
11
  * consequences a namespace had. `repository` left the signature because the application carries it.
@@ -76,6 +76,11 @@ export declare namespace ListService {
76
76
  * declares one, otherwise every registered target that claims it, which is the same question
77
77
  * `publish` asks. Empty in a repository whose plugins contribute no target the package fits. */
78
78
  publishTargets: PublishTargetName[];
79
+ /** The entries of `publishTargets` that `publish` would leave this package alone for, each with
80
+ * why - `.rmanrc "publish.skip"`, or the target's own rule (npm's `private`). Decided without the
81
+ * registry, so `{}` means "a candidate", not "will publish": whether the version is already out
82
+ * there is `publish --dry-run`'s answer. */
83
+ skippedTargets: Record<PublishTargetName, string>;
79
84
  /** Present only when `"docker"` is one of `publishTargets` and `publish.docker` is configured -
80
85
  * the raw `.rmanrc` config, unresolved (no namespace prefixing - see `DockerPublishService`). */
81
86
  docker?: DockerPublishOptions;
@@ -1,6 +1,6 @@
1
1
  import path from 'path';
2
2
  import { Service } from '../core/classes/service.js';
3
- import { targetsOf } from '../core/interfaces/publish-target.js';
3
+ import { skipReasonFor, targetsOf } from '../core/interfaces/publish-target.js';
4
4
  import { filterPackages } from '../utils/package-filter.js';
5
5
  /**
6
6
  * **A class, and the shape every service follows now.**
@@ -33,7 +33,17 @@ export class ListService extends Service {
33
33
  /** **Asked, not assumed.** This read the config key directly and defaulted to `['npm']`, so a
34
34
  * Cargo package in a polyglot repository was reported as shipping to npm - which is what
35
35
  * `PublishTarget.claims` exists to answer, per target, from the ecosystem that knows. */
36
- const publishTargets = targetsOf(this.app, p).map(t => t.name);
36
+ /** **A monorepo's root ships nowhere**: `publish` never makes it a candidate
37
+ * (`repository.getPackages()` leaves it out), so listing the target a root *would* claim
38
+ * says something no command does. */
39
+ const targets = p === repository.rootPackage && repository.monorepo ? [] : targetsOf(this.app, p);
40
+ const publishTargets = targets.map(t => t.name);
41
+ const skippedTargets = {};
42
+ for (const target of targets) {
43
+ const reason = skipReasonFor(p, target);
44
+ if (reason)
45
+ skippedTargets[target.name] = reason;
46
+ }
37
47
  return {
38
48
  name: p.name,
39
49
  selector: p.selector,
@@ -46,6 +56,7 @@ export class ListService extends Service {
46
56
  status: status[p.selector],
47
57
  dependencies: p.dependencies.map(d => d.name),
48
58
  publishTargets: [...publishTargets],
59
+ skippedTargets,
49
60
  docker: publishTargets.includes('docker') ? p.config.publish?.docker : undefined,
50
61
  };
51
62
  };
@@ -1,11 +1,11 @@
1
1
  import type { Reporter } from '../core/classes/log-sink.js';
2
2
  import { type LogLevel } from '../core/classes/logger.js';
3
3
  import type { Package } from '../core/classes/package.js';
4
+ import { ProgressPanel } from '../core/classes/progress-panel.js';
4
5
  import type { Repository } from '../core/classes/repository.js';
5
6
  import { Service } from '../core/classes/service.js';
6
7
  import type { RunStepContext, RunStepFn, RunStepValue } from '../core/interfaces/run-step.js';
7
8
  import { type PackageFilterOptions } from '../utils/package-filter.js';
8
- import { ProgressPanel } from '../utils/progress-panel.js';
9
9
  /**
10
10
  * A service class - see `ListService` for the shape and `Service` for the three measured
11
11
  * consequences a namespace had.
@@ -5,11 +5,11 @@ import colors from 'ansi-colors';
5
5
  import { tokenize } from 'fast-tokenizer';
6
6
  import { Task } from 'power-tasks';
7
7
  import { LOG_LEVELS, Logger, resolveRootLogLevel } from '../core/classes/logger.js';
8
+ import { ProgressPanel } from '../core/classes/progress-panel.js';
8
9
  import { PanelReporter, PlainReporter } from '../core/classes/run-reporters.js';
9
10
  import { Service } from '../core/classes/service.js';
10
11
  import { exec } from '../utils/exec.js';
11
12
  import { filterPackages } from '../utils/package-filter.js';
12
- import { ProgressPanel } from '../utils/progress-panel.js';
13
13
  import { runBin } from '../utils/run-bin.js';
14
14
  /**
15
15
  * A service class - see `ListService` for the shape and `Service` for the three measured
@@ -1,5 +1,5 @@
1
1
  import colors from 'ansi-colors';
2
- import { LiveRegion } from './live-region.js';
2
+ import { LiveRegion } from '../core/classes/live-region.js';
3
3
  export class StatusRegion {
4
4
  label;
5
5
  detail;
File without changes
File without changes
File without changes