rman 2.15.2 → 2.17.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.
- package/builtins/platforms/node/node-config.interface.d.ts +11 -0
- package/builtins/platforms/node/services/publish.service.js +16 -1
- package/builtins/platforms/node/utils/copy-assets.d.ts +30 -0
- package/builtins/platforms/node/utils/copy-assets.js +104 -0
- package/commands/version.command.d.ts +6 -2
- package/commands/version.command.js +5 -2
- package/constants.js +1 -1
- package/index.d.ts +1 -0
- package/index.js +1 -0
- package/package.json +1 -1
- package/services/version-plan.service.d.ts +6 -0
- package/services/version-plan.service.js +31 -2
|
@@ -61,6 +61,17 @@ export declare namespace RmanNodeConfig {
|
|
|
61
61
|
* own "Unknown command: stage" is a better message than a guess made somewhere else.
|
|
62
62
|
*/
|
|
63
63
|
staged?: ConfigValue<boolean>;
|
|
64
|
+
/**
|
|
65
|
+
* The prerelease identifiers that are **not previews** for this package - a version on one of
|
|
66
|
+
* them publishes to `latest` like a release, instead of under a dist-tag of its own.
|
|
67
|
+
*
|
|
68
|
+
* For a package whose every release is a prerelease by design: `["rev"]` publishes
|
|
69
|
+
* `4.13.3-rev.9` to `latest`, while a `4.14.0-beta.0` of the same package keeps its own `beta`
|
|
70
|
+
* tag. Pairs with `.rmanrc "version.preid"`.
|
|
71
|
+
*
|
|
72
|
+
* @example ["rev"]
|
|
73
|
+
*/
|
|
74
|
+
latestPrereleases?: ConfigValue<string[]>;
|
|
64
75
|
}
|
|
65
76
|
}
|
|
66
77
|
/**
|
|
@@ -501,7 +501,7 @@ function retiredDirectoryKey(pkg) {
|
|
|
501
501
|
* checks; they agree deliberately.
|
|
502
502
|
*/
|
|
503
503
|
function distTagFor(pkg, tag) {
|
|
504
|
-
const isPreview = !isCalendarVersion(pkg.version) && pkg.versionScheme.isPrerelease(pkg.version);
|
|
504
|
+
const isPreview = !isCalendarVersion(pkg.version) && pkg.versionScheme.isPrerelease(pkg.version) && !releasesAsLatest(pkg);
|
|
505
505
|
if (!isPreview)
|
|
506
506
|
return { tag };
|
|
507
507
|
if (tag) {
|
|
@@ -553,3 +553,18 @@ function resolveStaged(pkg, override) {
|
|
|
553
553
|
return override;
|
|
554
554
|
return !!pkg.config?.publish?.npm?.staged;
|
|
555
555
|
}
|
|
556
|
+
/**
|
|
557
|
+
* Whether `pkg`'s prerelease identifier is one `.rmanrc "publish.npm.latestPrereleases"` lists - a
|
|
558
|
+
* line the package releases on for good, which publishes to `latest` like any release.
|
|
559
|
+
*/
|
|
560
|
+
/* **An explicit list, not "whatever `version.preid` says".** A repository can put its previews on a
|
|
561
|
+
* declared line too (`preid: beta`), and reading the bump's setting as a statement about the
|
|
562
|
+
* registry would have every such beta land on `latest` - the one mistake `distTagFor` exists to
|
|
563
|
+
* stop. Naming the identifier also keeps the protection for every other one: a `-beta.0` of a
|
|
564
|
+
* package publishing `-rev.N` to `latest` still gets its own tag. Requested from `panates/browsery`,
|
|
565
|
+
* which repackages upstream modules as `<upstream version>-rev.N`. */
|
|
566
|
+
function releasesAsLatest(pkg) {
|
|
567
|
+
const listed = pkg.config?.publish?.npm?.latestPrereleases;
|
|
568
|
+
const id = pkg.versionScheme.prereleaseId(pkg.version);
|
|
569
|
+
return !!id && Array.isArray(listed) && listed.includes(id);
|
|
570
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { RunBinOptions, RunBinResult } from '../../../../utils/run-bin.js';
|
|
2
|
+
/**
|
|
3
|
+
* The files `copyAssets` copies when it is given no patterns: the data formats a package keeps
|
|
4
|
+
* beside its sources - translations, fixtures, schemas - that `tsc` does not emit.
|
|
5
|
+
*/
|
|
6
|
+
export declare const DEFAULT_ASSET_PATTERNS: readonly string[];
|
|
7
|
+
export interface CopyAssetsOptions {
|
|
8
|
+
/** The tsconfig the build compiles with - its `rootDir` and `outDir` say where the files are and
|
|
9
|
+
* where they go. */
|
|
10
|
+
tsconfig: string;
|
|
11
|
+
/** Globs over paths relative to `rootDir`. Default `DEFAULT_ASSET_PATTERNS`. */
|
|
12
|
+
patterns?: readonly string[];
|
|
13
|
+
/** Runs `tsc` - a function step's own `ctx.runBin`, which already resolves the repository's
|
|
14
|
+
* installed copy. */
|
|
15
|
+
runBin: (bin: string, argv: string[], options?: RunBinOptions) => Promise<RunBinResult>;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Copies the files under a tsconfig's `rootDir` that match `patterns` into its `outDir`, keeping
|
|
19
|
+
* their place in the tree - `src/i18n/tr.json` lands at `build/i18n/tr.json`, where the compiled
|
|
20
|
+
* code that reads it expects to find it. Returns the files it wrote, absolute.
|
|
21
|
+
*
|
|
22
|
+
* `tsc` emits none of them: it compiles sources, and a `.json` reaches the output only when code
|
|
23
|
+
* imports it under `resolveJsonModule`. A file read at run time - a translation, an XML template, a
|
|
24
|
+
* fixture - is left behind, and the built package fails on a path that exists only in `src`.
|
|
25
|
+
*
|
|
26
|
+
* A tsconfig with no `outDir` compiles beside its sources, so there is nothing to copy and nothing
|
|
27
|
+
* is. `node_modules`, the output directory itself, `tsconfig*.json`, `package.json` and
|
|
28
|
+
* `package-lock.json` are never copied.
|
|
29
|
+
*/
|
|
30
|
+
export declare function copyAssets(options: CopyAssetsOptions): Promise<string[]>;
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import glob from 'fast-glob';
|
|
4
|
+
/**
|
|
5
|
+
* The files `copyAssets` copies when it is given no patterns: the data formats a package keeps
|
|
6
|
+
* beside its sources - translations, fixtures, schemas - that `tsc` does not emit.
|
|
7
|
+
*/
|
|
8
|
+
/* **A list, not "everything that is not TypeScript"** - the user's call, and the reason is what
|
|
9
|
+
* ships: a published package is what lands in a consumer's `node_modules`, and "every other file"
|
|
10
|
+
* puts a stray `.md`, a `.DS_Store` or a test's data file there with nothing saying so. A list
|
|
11
|
+
* leaves out what nobody named, and a repository that needs more names it. */
|
|
12
|
+
export const DEFAULT_ASSET_PATTERNS = ['**/*.json', '**/*.xml', '**/*.yaml', '**/*.yml'];
|
|
13
|
+
/**
|
|
14
|
+
* Copies the files under a tsconfig's `rootDir` that match `patterns` into its `outDir`, keeping
|
|
15
|
+
* their place in the tree - `src/i18n/tr.json` lands at `build/i18n/tr.json`, where the compiled
|
|
16
|
+
* code that reads it expects to find it. Returns the files it wrote, absolute.
|
|
17
|
+
*
|
|
18
|
+
* `tsc` emits none of them: it compiles sources, and a `.json` reaches the output only when code
|
|
19
|
+
* imports it under `resolveJsonModule`. A file read at run time - a translation, an XML template, a
|
|
20
|
+
* fixture - is left behind, and the built package fails on a path that exists only in `src`.
|
|
21
|
+
*
|
|
22
|
+
* A tsconfig with no `outDir` compiles beside its sources, so there is nothing to copy and nothing
|
|
23
|
+
* is. `node_modules`, the output directory itself, `tsconfig*.json`, `package.json` and
|
|
24
|
+
* `package-lock.json` are never copied.
|
|
25
|
+
*/
|
|
26
|
+
/* **`rootDir`/`outDir` are asked of `tsc --showConfig`, not read out of the file.** A package's
|
|
27
|
+
* tsconfig usually inherits both through `extends` - a relative path or a package such as
|
|
28
|
+
* `@panates/tsconfig` - and resolving that chain is `tsc`'s own logic: JSON with comments, a list
|
|
29
|
+
* of bases, package `exports`. `--showConfig` prints the resolved result with every path relative
|
|
30
|
+
* to the config it was given, in about 0.4s (measured on `panates/opra`'s `common`), which is small
|
|
31
|
+
* beside the compile it follows.
|
|
32
|
+
*
|
|
33
|
+
* **No `rootDir` means `tsc` computed one** - the common directory of its inputs - and `--showConfig`
|
|
34
|
+
* lists those inputs under `files`, so the same answer is taken from there. Declaration files are
|
|
35
|
+
* left out of it, as `tsc` leaves them out. */
|
|
36
|
+
export async function copyAssets(options) {
|
|
37
|
+
const configDir = path.dirname(path.resolve(options.tsconfig));
|
|
38
|
+
/** **`onLine` swallows the lines**: a step's `runBin` hands every line to the step's log, and the
|
|
39
|
+
* whole resolved configuration printed under the package is noise. `output` still collects them. */
|
|
40
|
+
let output;
|
|
41
|
+
try {
|
|
42
|
+
({ output } = await options.runBin('tsc', ['--showConfig', '-p', options.tsconfig], {
|
|
43
|
+
stdio: 'pipe',
|
|
44
|
+
onLine: () => undefined,
|
|
45
|
+
}));
|
|
46
|
+
}
|
|
47
|
+
catch (e) {
|
|
48
|
+
throw new Error(`"tsc --showConfig -p ${options.tsconfig}" failed:\n${String(e?.output ?? e?.message).trim()}`, {
|
|
49
|
+
cause: e,
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
const config = parseShowConfig(output, options.tsconfig);
|
|
53
|
+
const outDir = config.compilerOptions?.outDir;
|
|
54
|
+
if (!outDir)
|
|
55
|
+
return [];
|
|
56
|
+
const out = path.resolve(configDir, outDir);
|
|
57
|
+
const root = config.compilerOptions?.rootDir
|
|
58
|
+
? path.resolve(configDir, config.compilerOptions.rootDir)
|
|
59
|
+
: (commonDir((config.files ?? []).filter(f => !/\.d\.[cm]?ts$/.test(f)).map(f => path.resolve(configDir, f))) ??
|
|
60
|
+
configDir);
|
|
61
|
+
/** `package.json` and its lockfile because a `rootDir` of the package itself would otherwise send
|
|
62
|
+
* them along - and the build directory's manifest is `publish`'s (or the preset's) to write. */
|
|
63
|
+
const ignore = ['**/node_modules/**', '**/tsconfig*.json', '**/package.json', '**/package-lock.json'];
|
|
64
|
+
const outInsideRoot = path.relative(root, out);
|
|
65
|
+
if (outInsideRoot && !outInsideRoot.startsWith('..') && !path.isAbsolute(outInsideRoot)) {
|
|
66
|
+
ignore.push(`${outInsideRoot.split(path.sep).join('/')}/**`);
|
|
67
|
+
}
|
|
68
|
+
const files = await glob([...(options.patterns ?? DEFAULT_ASSET_PATTERNS)], {
|
|
69
|
+
cwd: root,
|
|
70
|
+
ignore,
|
|
71
|
+
onlyFiles: true,
|
|
72
|
+
dot: false,
|
|
73
|
+
});
|
|
74
|
+
const written = [];
|
|
75
|
+
for (const rel of files.sort()) {
|
|
76
|
+
const target = path.join(out, rel);
|
|
77
|
+
fs.mkdirSync(path.dirname(target), { recursive: true });
|
|
78
|
+
fs.copyFileSync(path.join(root, rel), target);
|
|
79
|
+
written.push(target);
|
|
80
|
+
}
|
|
81
|
+
return written;
|
|
82
|
+
}
|
|
83
|
+
/** `tsc --showConfig`'s answer. It prints the JSON alone on success; anything else is a tsconfig
|
|
84
|
+
* `tsc` could not read, which is reported with what it said. */
|
|
85
|
+
function parseShowConfig(output, tsconfig) {
|
|
86
|
+
const start = output.indexOf('{');
|
|
87
|
+
try {
|
|
88
|
+
return JSON.parse(output.slice(start));
|
|
89
|
+
}
|
|
90
|
+
catch {
|
|
91
|
+
throw new Error(`"tsc --showConfig -p ${tsconfig}" did not print a configuration:\n${output.trim()}`);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
/** The deepest directory holding every one of `files`, or `undefined` for none. */
|
|
95
|
+
function commonDir(files) {
|
|
96
|
+
if (!files.length)
|
|
97
|
+
return undefined;
|
|
98
|
+
let common = path.dirname(files[0]);
|
|
99
|
+
for (const file of files.slice(1)) {
|
|
100
|
+
while (path.relative(common, file).startsWith('..'))
|
|
101
|
+
common = path.dirname(common);
|
|
102
|
+
}
|
|
103
|
+
return common;
|
|
104
|
+
}
|
|
@@ -58,8 +58,10 @@ declare const config: {
|
|
|
58
58
|
describe: string;
|
|
59
59
|
type: "boolean";
|
|
60
60
|
};
|
|
61
|
+
/** `target: 'both'`: a flag for one prerelease, and `.rmanrc "version.preid"` for a repository
|
|
62
|
+
* that releases on a prerelease line for good (`4.13.3-rev.N`). */
|
|
61
63
|
preid: {
|
|
62
|
-
target: "
|
|
64
|
+
target: "both";
|
|
63
65
|
describe: string;
|
|
64
66
|
type: "string";
|
|
65
67
|
};
|
|
@@ -257,8 +259,10 @@ declare const versionCommand: (app: import("../index.js").RmanApplication) => {
|
|
|
257
259
|
describe: string;
|
|
258
260
|
type: "boolean";
|
|
259
261
|
};
|
|
262
|
+
/** `target: 'both'`: a flag for one prerelease, and `.rmanrc "version.preid"` for a repository
|
|
263
|
+
* that releases on a prerelease line for good (`4.13.3-rev.N`). */
|
|
260
264
|
preid: {
|
|
261
|
-
target: "
|
|
265
|
+
target: "both";
|
|
262
266
|
describe: string;
|
|
263
267
|
type: "string";
|
|
264
268
|
};
|
|
@@ -77,11 +77,14 @@ const config = {
|
|
|
77
77
|
'"version.changelog", or false - --no-changelog forces it off even when that\'s true.',
|
|
78
78
|
type: 'boolean',
|
|
79
79
|
},
|
|
80
|
+
/** `target: 'both'`: a flag for one prerelease, and `.rmanrc "version.preid"` for a repository
|
|
81
|
+
* that releases on a prerelease line for good (`4.13.3-rev.N`). */
|
|
80
82
|
preid: {
|
|
81
|
-
target: '
|
|
83
|
+
target: 'both',
|
|
82
84
|
describe: 'Make the bump a prerelease with this identifier (e.g. "beta" -> 1.2.3-beta.0). ' +
|
|
83
85
|
'Running again with the same --preid increments it (-> 1.2.3-beta.1); a different ' +
|
|
84
|
-
'identifier starts a fresh prerelease line. Ignored when bump is an explicit version.'
|
|
86
|
+
'identifier starts a fresh prerelease line. Ignored when bump is an explicit version. ' +
|
|
87
|
+
'Default: .rmanrc "version.preid", which every member of a group has to agree on.',
|
|
85
88
|
type: 'string',
|
|
86
89
|
},
|
|
87
90
|
/**
|
package/constants.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const version = '2.
|
|
1
|
+
export const version = '2.17.0';
|
package/index.d.ts
CHANGED
|
@@ -169,6 +169,7 @@ export { CiService } from './builtins/platforms/node/services/ci.service.js';
|
|
|
169
169
|
export { CleanService } from './builtins/platforms/node/services/clean.service.js';
|
|
170
170
|
export { PublishService } from './builtins/platforms/node/services/publish.service.js';
|
|
171
171
|
export { NodeVersionPlanService } from './builtins/platforms/node/services/version-plan.service.js';
|
|
172
|
+
export { copyAssets, type CopyAssetsOptions, DEFAULT_ASSET_PATTERNS, } from './builtins/platforms/node/utils/copy-assets.js';
|
|
172
173
|
export type { ParsedWorkspaceRange } from './builtins/platforms/node/utils/workspace-range.js';
|
|
173
174
|
export { NPM_TARGET, NpmPublishTarget } from './builtins/publish-targets/npm/npm-publish-target.js';
|
|
174
175
|
export { isCalendarVersion } from './utils/release-version.js';
|
package/index.js
CHANGED
|
@@ -135,6 +135,7 @@ export { CiService } from './builtins/platforms/node/services/ci.service.js';
|
|
|
135
135
|
export { CleanService } from './builtins/platforms/node/services/clean.service.js';
|
|
136
136
|
export { PublishService } from './builtins/platforms/node/services/publish.service.js';
|
|
137
137
|
export { NodeVersionPlanService } from './builtins/platforms/node/services/version-plan.service.js';
|
|
138
|
+
export { copyAssets, DEFAULT_ASSET_PATTERNS, } from './builtins/platforms/node/utils/copy-assets.js';
|
|
138
139
|
export { NPM_TARGET, NpmPublishTarget } from './builtins/publish-targets/npm/npm-publish-target.js';
|
|
139
140
|
export { isCalendarVersion } from './utils/release-version.js';
|
|
140
141
|
export { runBin } from './utils/run-bin.js';
|
package/package.json
CHANGED
|
@@ -129,6 +129,12 @@ export declare abstract class VersionPlanService {
|
|
|
129
129
|
* case the technology's own `cascade` answers. Members disagreeing take the widest, the same rule
|
|
130
130
|
* and the same direction `cascadeFor` applies to two technologies.
|
|
131
131
|
*/
|
|
132
|
+
/**
|
|
133
|
+
* The prerelease identifier a group's members declare in `.rmanrc "version.preid"`, or `undefined`
|
|
134
|
+
* when none does. Members declaring different ones are an error naming them: a group is one
|
|
135
|
+
* version line, and a line cannot be on two prerelease identifiers at once.
|
|
136
|
+
*/
|
|
137
|
+
protected declaredPreid(members: Package[], label: string): string | undefined;
|
|
132
138
|
protected declaredCascade(members: Package[]): VersionPlanService.Cascade | undefined;
|
|
133
139
|
/**
|
|
134
140
|
* The largest bump `commits` ask for, in `scheme`'s own names.
|
|
@@ -160,7 +160,8 @@ export class VersionPlanService {
|
|
|
160
160
|
groups.set(key, [pkg]);
|
|
161
161
|
}
|
|
162
162
|
for (const [key, members] of groups) {
|
|
163
|
-
|
|
163
|
+
const preid = options.preid ?? this.declaredPreid(members, this.groupLabel(key));
|
|
164
|
+
this.computeGroupPlan(key, members, changeByPackage, explicitVersion, preid, entries);
|
|
164
165
|
}
|
|
165
166
|
this.rippleCrossGroup(packages, entries, options.preid);
|
|
166
167
|
const result = packages.map(pkg => entries.get(pkg.name));
|
|
@@ -267,6 +268,31 @@ export class VersionPlanService {
|
|
|
267
268
|
* `^1.0.0` does not admit `2.0.0` and an in-group dependent left at the old number would declare
|
|
268
269
|
* a range its own group no longer satisfies. So `changed` means "no floor of my own", not "never
|
|
269
270
|
* more than the changed packages". */
|
|
271
|
+
/**
|
|
272
|
+
* The prerelease identifier a group's members declare in `.rmanrc "version.preid"`, or `undefined`
|
|
273
|
+
* when none does. Members declaring different ones are an error naming them: a group is one
|
|
274
|
+
* version line, and a line cannot be on two prerelease identifiers at once.
|
|
275
|
+
*/
|
|
276
|
+
/* **A member saying nothing agrees with whoever does.** The usual shape is one declaration above
|
|
277
|
+
* the group (`"[*]"`, or a shared preset), which reaches every member; a group where only some
|
|
278
|
+
* members say it is still one line, and refusing it would make adding a package to a group a way
|
|
279
|
+
* to break its release. Two different words are the only disagreement, and that one has no
|
|
280
|
+
* answer: `4.13.3-rev.9` and `4.13.3-beta.0` cannot both be the group's next version. */
|
|
281
|
+
declaredPreid(members, label) {
|
|
282
|
+
const declared = new Map();
|
|
283
|
+
for (const m of members) {
|
|
284
|
+
const preid = m.config?.version?.preid;
|
|
285
|
+
if (typeof preid !== 'string' || !preid)
|
|
286
|
+
continue;
|
|
287
|
+
declared.set(preid, [...(declared.get(preid) ?? []), m.name]);
|
|
288
|
+
}
|
|
289
|
+
if (declared.size > 1) {
|
|
290
|
+
const sides = [...declared].map(([preid, names]) => `"${preid}" (${names.join(', ')})`).join(' and ');
|
|
291
|
+
throw new Error(`Group ${label} is one version line, but its members declare different "version.preid": ${sides}. ` +
|
|
292
|
+
'Declare one identifier for the whole group.');
|
|
293
|
+
}
|
|
294
|
+
return declared.keys().next().value;
|
|
295
|
+
}
|
|
270
296
|
declaredCascade(members) {
|
|
271
297
|
const declared = new Set(members.map(m => m.config?.version?.cascade).filter((c) => !!c));
|
|
272
298
|
if (!declared.size)
|
|
@@ -454,7 +480,10 @@ export class VersionPlanService {
|
|
|
454
480
|
const next = {
|
|
455
481
|
...entry,
|
|
456
482
|
status: 'bump',
|
|
457
|
-
to: pkg.versionScheme.next(groupCeiling, pkg.versionScheme.smallestBump(), {
|
|
483
|
+
to: pkg.versionScheme.next(groupCeiling, pkg.versionScheme.smallestBump(), {
|
|
484
|
+
preid: preid ??
|
|
485
|
+
this.declaredPreid(packages.filter(p => entries.get(p.name).groupKey === entry.groupKey), entry.group ?? entry.groupKey),
|
|
486
|
+
}),
|
|
458
487
|
reason: `depends on ${source.package.name}@${source.to}`,
|
|
459
488
|
};
|
|
460
489
|
entries.set(pkg.name, next);
|