rman 2.11.1 → 2.11.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.
|
@@ -102,11 +102,11 @@ export declare namespace PublishService {
|
|
|
102
102
|
* queries it to decide, so it's safe to call any time, including as the plan a bare `rman
|
|
103
103
|
* publish` shows before asking for confirmation.
|
|
104
104
|
*
|
|
105
|
-
* **Whether a package is private is
|
|
106
|
-
*
|
|
107
|
-
*
|
|
108
|
-
*
|
|
109
|
-
*
|
|
105
|
+
* **Whether a package is private is decided from the manifest that would be published.** From a
|
|
106
|
+
* build directory that is the one `publish` derives (see `derivePublishManifest`): `private` there
|
|
107
|
+
* only when the source has it and no `publishConfig`. In place it is the source's own. A build
|
|
108
|
+
* directory that is missing or holds nothing but a `package.json` is an `'error'`: nothing has been
|
|
109
|
+
* built to publish. Each remaining package's **dist-tag**
|
|
110
110
|
* is settled next (`distTagFor`): usually derived from the version itself, `'error'` in the two
|
|
111
111
|
* cases with nothing to derive - that one is about the invocation rather than the package, so it
|
|
112
112
|
* is answered before anything touches the network. A package with uncommitted local changes is
|
|
@@ -136,10 +136,12 @@ export declare namespace PublishService {
|
|
|
136
136
|
* landed on the registry first, and publishing is rare enough (once per release) that the
|
|
137
137
|
* simplicity is worth more than the parallelism `run` gets from `power-tasks`.
|
|
138
138
|
*
|
|
139
|
-
* If a package fails, every other still-pending entry
|
|
140
|
-
* `'error'` too and never attempted - publishing a package whose own new
|
|
141
|
-
* at a version that never actually reached the registry would hand
|
|
142
|
-
* A package's own failure doesn't stop unrelated packages elsewhere in
|
|
139
|
+
* If a package fails, every other still-pending entry that **a consumer's install needs it for**
|
|
140
|
+
* (transitively) is marked `'error'` too and never attempted - publishing a package whose own new
|
|
141
|
+
* dependency range points at a version that never actually reached the registry would hand
|
|
142
|
+
* consumers a broken install. A package's own failure doesn't stop unrelated packages elsewhere in
|
|
143
|
+
* the plan, though, nor one that lists it only where an install does not need it (see
|
|
144
|
+
* `consumerNeeds`).
|
|
143
145
|
*/
|
|
144
146
|
function applyPlan(repository: Repository, plan: Entry[], options?: ApplyOptions): Promise<Entry[]>;
|
|
145
147
|
}
|
|
@@ -127,11 +127,11 @@ export var PublishService;
|
|
|
127
127
|
* queries it to decide, so it's safe to call any time, including as the plan a bare `rman
|
|
128
128
|
* publish` shows before asking for confirmation.
|
|
129
129
|
*
|
|
130
|
-
* **Whether a package is private is
|
|
131
|
-
*
|
|
132
|
-
*
|
|
133
|
-
*
|
|
134
|
-
*
|
|
130
|
+
* **Whether a package is private is decided from the manifest that would be published.** From a
|
|
131
|
+
* build directory that is the one `publish` derives (see `derivePublishManifest`): `private` there
|
|
132
|
+
* only when the source has it and no `publishConfig`. In place it is the source's own. A build
|
|
133
|
+
* directory that is missing or holds nothing but a `package.json` is an `'error'`: nothing has been
|
|
134
|
+
* built to publish. Each remaining package's **dist-tag**
|
|
135
135
|
* is settled next (`distTagFor`): usually derived from the version itself, `'error'` in the two
|
|
136
136
|
* cases with nothing to derive - that one is about the invocation rather than the package, so it
|
|
137
137
|
* is answered before anything touches the network. A package with uncommitted local changes is
|
|
@@ -192,16 +192,16 @@ export var PublishService;
|
|
|
192
192
|
else if (privateBySource(pkg)) {
|
|
193
193
|
entries.set(pkg.name, { package: pkg, version: pkg.version, status: 'skip', reason: 'private package' });
|
|
194
194
|
}
|
|
195
|
-
else if (!
|
|
195
|
+
else if (!hasBuildOutput(pkg, options.contents)) {
|
|
196
196
|
const dir = path.relative(pkg.dirname, resolvePublishDir(pkg, options.contents)) || '.';
|
|
197
197
|
entries.set(pkg.name, {
|
|
198
198
|
package: pkg,
|
|
199
199
|
version: pkg.version,
|
|
200
200
|
status: 'error',
|
|
201
|
-
reason: `nothing to publish in "${dir}" - it
|
|
201
|
+
reason: `nothing to publish in "${dir}" - it is missing or empty; build the package first`,
|
|
202
202
|
});
|
|
203
203
|
}
|
|
204
|
-
else if (
|
|
204
|
+
else if (publishesInPlace(pkg, options.contents) && pkg.manifest.raw.private) {
|
|
205
205
|
entries.set(pkg.name, { package: pkg, version: pkg.version, status: 'skip', reason: 'private package' });
|
|
206
206
|
}
|
|
207
207
|
else if (distTag.error) {
|
|
@@ -259,10 +259,12 @@ export var PublishService;
|
|
|
259
259
|
* landed on the registry first, and publishing is rare enough (once per release) that the
|
|
260
260
|
* simplicity is worth more than the parallelism `run` gets from `power-tasks`.
|
|
261
261
|
*
|
|
262
|
-
* If a package fails, every other still-pending entry
|
|
263
|
-
* `'error'` too and never attempted - publishing a package whose own new
|
|
264
|
-
* at a version that never actually reached the registry would hand
|
|
265
|
-
* A package's own failure doesn't stop unrelated packages elsewhere in
|
|
262
|
+
* If a package fails, every other still-pending entry that **a consumer's install needs it for**
|
|
263
|
+
* (transitively) is marked `'error'` too and never attempted - publishing a package whose own new
|
|
264
|
+
* dependency range points at a version that never actually reached the registry would hand
|
|
265
|
+
* consumers a broken install. A package's own failure doesn't stop unrelated packages elsewhere in
|
|
266
|
+
* the plan, though, nor one that lists it only where an install does not need it (see
|
|
267
|
+
* `consumerNeeds`).
|
|
266
268
|
*/
|
|
267
269
|
async function applyPlan(repository, plan, options = {}) {
|
|
268
270
|
const packageManager = CiService.resolvePackageManager(repository, options.packageManager);
|
|
@@ -279,7 +281,7 @@ export var PublishService;
|
|
|
279
281
|
continue;
|
|
280
282
|
}
|
|
281
283
|
const pkg = entry.package;
|
|
282
|
-
const blocker = pkg.dependencies.find(d => failed.has(d.name));
|
|
284
|
+
const blocker = pkg.dependencies.find(d => failed.has(d.name) && consumerNeeds(pkg, d.name));
|
|
283
285
|
if (blocker) {
|
|
284
286
|
failed.add(pkg.name);
|
|
285
287
|
result.push({ ...entry, status: 'error', reason: `dependency "${blocker.name}" failed to publish` });
|
|
@@ -324,27 +326,59 @@ function resolvePublishDir(pkg, contentsOverride) {
|
|
|
324
326
|
const rel = (typeof native === 'string' && native) || configured || contentsOverride;
|
|
325
327
|
return rel ? path.resolve(pkg.dirname, rel) : pkg.dirname;
|
|
326
328
|
}
|
|
327
|
-
/**
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
*
|
|
331
|
-
*
|
|
332
|
-
*
|
|
333
|
-
*
|
|
334
|
-
*
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
*
|
|
343
|
-
/* Asked first so an unbuilt private package is skipped rather than reported as unbuilt: opra's
|
|
344
|
-
* examples inherit `publish.npm.directory` from the shared preset and skip their build. */
|
|
329
|
+
/** `private` in the source with no `publishConfig` - private in every manifest derived from it too. */
|
|
330
|
+
/* **Decided from the manifest `npm publish` reads, which rman writes.** Publishing from a build
|
|
331
|
+
* directory, that is `derivePublishManifest`'s output - written over whatever is there at publish time
|
|
332
|
+
* - so `private` is the source's, kept only without a `publishConfig`. Reported from
|
|
333
|
+
* `postgrejs-kysely`: its source carried `private: true` as a guard against a stray `npm publish`,
|
|
334
|
+
* the plan answered `skip - private package`, and version, tag and GitHub release went through with
|
|
335
|
+
* nothing on the registry.
|
|
336
|
+
*
|
|
337
|
+
* **2.11.1 read `build/package.json` instead, and that file is not what is published.** It is
|
|
338
|
+
* whatever the build left there - the shared preset writes one, but only from the build `after` step
|
|
339
|
+
* a package can replace, and `@opra/common`/`@opra/client` replace it with their own esbuild step. Both
|
|
340
|
+
* had 625 and 52 built files and no `package.json`, the plan answered `error` for both, and opra's
|
|
341
|
+
* release stopped after the version had been pushed.
|
|
342
|
+
*
|
|
343
|
+
* Asked before the build is looked for, so an unbuilt private package is skipped rather than
|
|
344
|
+
* reported as unbuilt: opra's examples inherit `publish.npm.directory` and skip their build. */
|
|
345
345
|
function privateBySource(pkg) {
|
|
346
346
|
return !!pkg.manifest.raw.private && !pkg.manifest.raw.publishConfig;
|
|
347
347
|
}
|
|
348
|
+
/** Whether a consumer installing `pkg` needs `name` to resolve: a `dependencies` entry, or a peer
|
|
349
|
+
* not marked optional. */
|
|
350
|
+
/* **Not every edge blocks a publish**, and blocking on all of them cost a release. A failed publish
|
|
351
|
+
* stops its dependents because their published range would point at a version that is not there -
|
|
352
|
+
* which is only true of what reaches the consumer:
|
|
353
|
+
* - `devDependencies` are removed from the published manifest (`derivePublishManifest`);
|
|
354
|
+
* - an optional peer that cannot be satisfied does not fail an install;
|
|
355
|
+
* - `optionalDependencies` are the ones npm proceeds without "if it cannot be found or fails to
|
|
356
|
+
* install" (npm's own documentation; not measured here).
|
|
357
|
+
* Measured on opra's 1.31.0 release: `@opra/api-ui` failed its first publish, and `@opra/http` -
|
|
358
|
+
* which lists it as an optional peer and a devDependency only - was blocked, taking elastic, mongodb
|
|
359
|
+
* and sqb with it, though none of their installs would have needed api-ui. */
|
|
360
|
+
function consumerNeeds(pkg, name) {
|
|
361
|
+
const raw = pkg.manifest.raw;
|
|
362
|
+
if (raw.dependencies?.[name] !== undefined)
|
|
363
|
+
return true;
|
|
364
|
+
return raw.peerDependencies?.[name] !== undefined && !raw.peerDependenciesMeta?.[name]?.optional;
|
|
365
|
+
}
|
|
366
|
+
/** Whether `pkg` is published from its own directory, whose `package.json` is then the manifest. */
|
|
367
|
+
/* In place, `private` is the source's whatever `publishConfig` says - npm refuses to publish it. */
|
|
368
|
+
function publishesInPlace(pkg, contentsOverride) {
|
|
369
|
+
return path.resolve(resolvePublishDir(pkg, contentsOverride)) === path.resolve(pkg.dirname);
|
|
370
|
+
}
|
|
371
|
+
/** Whether the directory `pkg` is published from holds something to publish - anything besides a
|
|
372
|
+
* `package.json`, which `publish` writes itself. Always true in place. */
|
|
373
|
+
/* Without it `applyPlan` creates the directory, writes the derived manifest and publishes a tarball
|
|
374
|
+
* holding nothing else. Not "has a package.json": that is the build's to write or not (see
|
|
375
|
+
* `privateBySource`). */
|
|
376
|
+
function hasBuildOutput(pkg, contentsOverride) {
|
|
377
|
+
if (publishesInPlace(pkg, contentsOverride))
|
|
378
|
+
return true;
|
|
379
|
+
const dir = resolvePublishDir(pkg, contentsOverride);
|
|
380
|
+
return fs.existsSync(dir) && fs.readdirSync(dir).some(name => name !== 'package.json');
|
|
381
|
+
}
|
|
348
382
|
/**
|
|
349
383
|
* Which registry a package's own version is asked about, and published to.
|
|
350
384
|
*
|
|
@@ -286,8 +286,11 @@ function printApplied(applied, plan, label) {
|
|
|
286
286
|
return failed;
|
|
287
287
|
}
|
|
288
288
|
/** The `logged` convention: printed here, so `runCli`'s catch does not print it a second time. */
|
|
289
|
+
/* On stderr, because under `--json` stdout is one JSON document: measured on opra's release, the
|
|
290
|
+
* failure line printed below the plan and a reader parsing it got `Unexpected non-whitespace
|
|
291
|
+
* character after JSON`. */
|
|
289
292
|
function logged(message) {
|
|
290
|
-
console.
|
|
293
|
+
console.error(colors.red(message));
|
|
291
294
|
const err = new Error(message);
|
|
292
295
|
err.logged = true;
|
|
293
296
|
return err;
|
package/constants.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const version = '2.11.
|
|
1
|
+
export const version = '2.11.3';
|