@lerna-lite/publish 1.16.1 → 1.16.2
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/dist/index.d.ts +3 -3
- package/dist/index.js +6 -6
- package/dist/lib/create-temp-licenses.d.ts +7 -7
- package/dist/lib/create-temp-licenses.js +30 -30
- package/dist/lib/fetch-config.d.ts +10 -10
- package/dist/lib/fetch-config.js +19 -19
- package/dist/lib/get-current-sha.d.ts +6 -6
- package/dist/lib/get-current-sha.js +17 -17
- package/dist/lib/get-current-tags.d.ts +8 -8
- package/dist/lib/get-current-tags.js +32 -32
- package/dist/lib/get-npm-username.d.ts +7 -7
- package/dist/lib/get-npm-username.js +52 -52
- package/dist/lib/get-packages-without-license.d.ts +8 -8
- package/dist/lib/get-packages-without-license.js +20 -20
- package/dist/lib/get-packed.d.ts +3 -3
- package/dist/lib/get-packed.js +63 -63
- package/dist/lib/get-profile-data.d.ts +7 -7
- package/dist/lib/get-profile-data.js +20 -20
- package/dist/lib/get-tagged-packages.d.ts +9 -9
- package/dist/lib/get-tagged-packages.js +26 -26
- package/dist/lib/get-two-factor-auth-required.d.ts +7 -7
- package/dist/lib/get-two-factor-auth-required.js +42 -42
- package/dist/lib/get-unpublished-packages.d.ts +8 -8
- package/dist/lib/get-unpublished-packages.js +34 -34
- package/dist/lib/get-whoami.d.ts +11 -11
- package/dist/lib/get-whoami.js +18 -18
- package/dist/lib/git-checkout.d.ts +10 -10
- package/dist/lib/git-checkout.js +18 -18
- package/dist/lib/index.d.ts +19 -19
- package/dist/lib/index.js +22 -22
- package/dist/lib/log-packed.d.ts +5 -5
- package/dist/lib/log-packed.js +70 -70
- package/dist/lib/npm-dist-tag.d.ts +33 -33
- package/dist/lib/npm-dist-tag.js +137 -137
- package/dist/lib/npm-publish.d.ts +11 -11
- package/dist/lib/npm-publish.js +93 -93
- package/dist/lib/override-publish-config.d.ts +6 -6
- package/dist/lib/override-publish-config.js +43 -43
- package/dist/lib/pack-directory.d.ts +9 -9
- package/dist/lib/pack-directory.js +67 -67
- package/dist/lib/remove-temp-licenses.d.ts +6 -6
- package/dist/lib/remove-temp-licenses.js +17 -17
- package/dist/lib/verify-npm-package-access.d.ts +9 -9
- package/dist/lib/verify-npm-package-access.js +53 -53
- package/dist/models/index.d.ts +34 -34
- package/dist/models/index.js +2 -2
- package/dist/publish-command.d.ts +74 -74
- package/dist/publish-command.js +781 -781
- package/package.json +4 -4
package/dist/publish-command.js
CHANGED
|
@@ -1,782 +1,782 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.PublishCommand = exports.factory = void 0;
|
|
4
|
-
const tslib_1 = require("tslib");
|
|
5
|
-
const chalk_1 = tslib_1.__importDefault(require("chalk"));
|
|
6
|
-
const glob_1 = tslib_1.__importDefault(require("glob"));
|
|
7
|
-
const fs_extra_1 = tslib_1.__importDefault(require("fs-extra"));
|
|
8
|
-
const os_1 = tslib_1.__importDefault(require("os"));
|
|
9
|
-
const path_1 = tslib_1.__importDefault(require("path"));
|
|
10
|
-
const crypto_1 = tslib_1.__importDefault(require("crypto"));
|
|
11
|
-
const p_map_1 = tslib_1.__importDefault(require("p-map"));
|
|
12
|
-
const p_pipe_1 = tslib_1.__importDefault(require("p-pipe"));
|
|
13
|
-
const semver_1 = tslib_1.__importDefault(require("semver"));
|
|
14
|
-
const temp_dir_1 = tslib_1.__importDefault(require("temp-dir"));
|
|
15
|
-
const version_1 = require("@lerna-lite/version");
|
|
16
|
-
const core_1 = require("@lerna-lite/core");
|
|
17
|
-
const get_current_tags_1 = require("./lib/get-current-tags");
|
|
18
|
-
const get_tagged_packages_1 = require("./lib/get-tagged-packages");
|
|
19
|
-
const get_unpublished_packages_1 = require("./lib/get-unpublished-packages");
|
|
20
|
-
const get_npm_username_1 = require("./lib/get-npm-username");
|
|
21
|
-
const verify_npm_package_access_1 = require("./lib/verify-npm-package-access");
|
|
22
|
-
const get_two_factor_auth_required_1 = require("./lib/get-two-factor-auth-required");
|
|
23
|
-
const get_current_sha_1 = require("./lib/get-current-sha");
|
|
24
|
-
const git_checkout_1 = require("./lib/git-checkout");
|
|
25
|
-
const pack_directory_1 = require("./lib/pack-directory");
|
|
26
|
-
const npm_publish_1 = require("./lib/npm-publish");
|
|
27
|
-
const log_packed_1 = require("./lib/log-packed");
|
|
28
|
-
const npm_dist_tag_1 = require("./lib/npm-dist-tag");
|
|
29
|
-
const override_publish_config_1 = require("./lib/override-publish-config");
|
|
30
|
-
const remove_temp_licenses_1 = require("./lib/remove-temp-licenses");
|
|
31
|
-
const create_temp_licenses_1 = require("./lib/create-temp-licenses");
|
|
32
|
-
const get_packages_without_license_1 = require("./lib/get-packages-without-license");
|
|
33
|
-
function factory(argv) {
|
|
34
|
-
return new PublishCommand(argv);
|
|
35
|
-
}
|
|
36
|
-
exports.factory = factory;
|
|
37
|
-
class PublishCommand extends core_1.Command {
|
|
38
|
-
get otherCommandConfigs() {
|
|
39
|
-
// back-compat
|
|
40
|
-
return ['version'];
|
|
41
|
-
}
|
|
42
|
-
get requiresGit() {
|
|
43
|
-
// `lerna publish from-package` doesn't _need_ git, per se
|
|
44
|
-
return this.options.bump !== 'from-package';
|
|
45
|
-
}
|
|
46
|
-
constructor(argv) {
|
|
47
|
-
super(argv);
|
|
48
|
-
/** command name */
|
|
49
|
-
this.name = 'publish';
|
|
50
|
-
this.gitReset = false;
|
|
51
|
-
this.savePrefix = '';
|
|
52
|
-
this.tagPrefix = '';
|
|
53
|
-
this.hasRootedLeaf = false;
|
|
54
|
-
this.npmSession = '';
|
|
55
|
-
this.packagesToPublish = [];
|
|
56
|
-
this.publishedPackages = [];
|
|
57
|
-
this.packagesToBeLicensed = [];
|
|
58
|
-
this.verifyAccess = false;
|
|
59
|
-
this.toposort = false;
|
|
60
|
-
this.twoFactorAuthRequired = false;
|
|
61
|
-
this.updates = [];
|
|
62
|
-
}
|
|
63
|
-
configureProperties() {
|
|
64
|
-
super.configureProperties();
|
|
65
|
-
// For publish we want to enable topological sorting by default, but allow users to override with --no-sort
|
|
66
|
-
this.toposort = this.options.sort !== false;
|
|
67
|
-
// Defaults are necessary here because yargs defaults
|
|
68
|
-
// override durable options provided by a config file
|
|
69
|
-
const {
|
|
70
|
-
// prettier-ignore
|
|
71
|
-
exact, gitHead, gitReset, tagVersionPrefix = 'v', verifyAccess, } = this.options;
|
|
72
|
-
if (this.requiresGit && gitHead) {
|
|
73
|
-
throw new core_1.ValidationError('EGITHEAD', '--git-head is only allowed with "from-package" positional');
|
|
74
|
-
}
|
|
75
|
-
// https://docs.npmjs.com/misc/config#save-prefix
|
|
76
|
-
this.savePrefix = exact ? '' : '^';
|
|
77
|
-
// https://docs.npmjs.com/misc/config#tag-version-prefix
|
|
78
|
-
this.tagPrefix = tagVersionPrefix;
|
|
79
|
-
// TODO: properly inherit from npm-conf
|
|
80
|
-
// inverted boolean options are only respected if prefixed with `--no-`, e.g. `--no-verify-access`
|
|
81
|
-
this.gitReset = gitReset !== false;
|
|
82
|
-
// consumed by npm-registry-fetch (via libnpmpublish)
|
|
83
|
-
this.npmSession = crypto_1.default.randomBytes(8).toString('hex');
|
|
84
|
-
this.verifyAccess = verifyAccess;
|
|
85
|
-
}
|
|
86
|
-
get userAgent() {
|
|
87
|
-
// consumed by npm-registry-fetch (via libnpmpublish)
|
|
88
|
-
return `lerna/${this.options.lernaVersion}/node@${process.version}+${process.arch} (${process.platform})`;
|
|
89
|
-
}
|
|
90
|
-
initialize() {
|
|
91
|
-
if (this.options.verifyAccess === false) {
|
|
92
|
-
this.logger.warn('verify-access', '--verify-access=false and --no-verify-access are no longer needed, because the legacy preemptive access verification is now disabled by default. Requests will fail with appropriate errors when not authorized correctly.');
|
|
93
|
-
}
|
|
94
|
-
if (this.options.graphType === 'dependencies') {
|
|
95
|
-
this.logger.warn('graph-type', '--graph-type=dependencies is deprecated and will be removed in the next major version of lerna-lite. If you have a use-case you feel requires it please open an issue to discuss: https://github.com/lerna/lerna/issues/new/choose');
|
|
96
|
-
}
|
|
97
|
-
if (this.options.workspaceStrictMatch === false) {
|
|
98
|
-
this.logger.warn('deprecation', 'Providing --no-workspace-strict-match is deprecated and will be removed in future version, we will make "workspace:" protocol strict matching in every case.');
|
|
99
|
-
}
|
|
100
|
-
if (this.options.buildMetadata && this.options.canary) {
|
|
101
|
-
throw new core_1.ValidationError('ENOTSATISFIED', 'Cannot use --build-metadata in conjunction with --canary option.');
|
|
102
|
-
}
|
|
103
|
-
else if (this.options.canary) {
|
|
104
|
-
this.logger.info('canary', 'enabled');
|
|
105
|
-
}
|
|
106
|
-
// @deprecated, to be removed in next major
|
|
107
|
-
if (this.options.requireScripts) {
|
|
108
|
-
this.logger.info('require-scripts', 'enabled');
|
|
109
|
-
}
|
|
110
|
-
// npmSession and user-agent are consumed by npm-registry-fetch (via libnpmpublish)
|
|
111
|
-
this.logger.verbose('session', this.npmSession);
|
|
112
|
-
this.logger.verbose('user-agent', this.userAgent);
|
|
113
|
-
this.conf = (0, core_1.npmConf)({
|
|
114
|
-
lernaCommand: 'publish',
|
|
115
|
-
_auth: this.options.legacyAuth,
|
|
116
|
-
npmSession: this.npmSession,
|
|
117
|
-
npmVersion: this.userAgent,
|
|
118
|
-
otp: this.options.otp,
|
|
119
|
-
registry: this.options.registry,
|
|
120
|
-
'ignore-prepublish': this.options.ignorePrepublish,
|
|
121
|
-
'ignore-scripts': this.options.ignoreScripts,
|
|
122
|
-
});
|
|
123
|
-
// cache to hold a one-time-password across publishes
|
|
124
|
-
this.otpCache = { otp: this.conf.get('otp') };
|
|
125
|
-
this.conf.set('user-agent', this.userAgent, 'cli');
|
|
126
|
-
if (this.conf.get('registry') === 'https://registry.yarnpkg.com') {
|
|
127
|
-
this.logger.warn('', `Yarn's registry proxy is broken, replacing with public npm registry`);
|
|
128
|
-
this.logger.warn('', `If you don't have an npm token, you should exit and run "npm login"`);
|
|
129
|
-
this.conf.set('registry', 'https://registry.npmjs.org/', 'cli');
|
|
130
|
-
}
|
|
131
|
-
// inject --dist-tag into opts, if present
|
|
132
|
-
const distTag = this.getDistTag();
|
|
133
|
-
if (distTag) {
|
|
134
|
-
this.conf.set('tag', distTag.trim(), 'cli');
|
|
135
|
-
}
|
|
136
|
-
// a 'rooted leaf' is the regrettable pattern of adding '.' to the 'packages' config in lerna.json
|
|
137
|
-
this.hasRootedLeaf = this.packageGraph.has(this.project.manifest.name);
|
|
138
|
-
if (this.hasRootedLeaf) {
|
|
139
|
-
this.logger.info('publish', 'rooted leaf detected, skipping synthetic root lifecycles');
|
|
140
|
-
}
|
|
141
|
-
this.runPackageLifecycle = (0, core_1.createRunner)(this.options);
|
|
142
|
-
// don't execute recursively if run from a poorly-named script
|
|
143
|
-
this.runRootLifecycle = /^(pre|post)?publish$/.test(process.env.npm_lifecycle_event || '')
|
|
144
|
-
? (stage) => this.logger.warn('lifecycle', 'Skipping root %j because it has already been called', stage)
|
|
145
|
-
: (stage) => this.runPackageLifecycle(this.project.manifest, stage);
|
|
146
|
-
let chain = Promise.resolve();
|
|
147
|
-
if (this.options.bump === 'from-git') {
|
|
148
|
-
chain = chain.then(() => this.detectFromGit());
|
|
149
|
-
}
|
|
150
|
-
else if (this.options.bump === 'from-package') {
|
|
151
|
-
chain = chain.then(() => this.detectFromPackage());
|
|
152
|
-
}
|
|
153
|
-
else if (this.options.canary) {
|
|
154
|
-
chain = chain.then(() => this.detectCanaryVersions());
|
|
155
|
-
}
|
|
156
|
-
else {
|
|
157
|
-
chain = chain.then(() => new version_1.VersionCommand(this.argv));
|
|
158
|
-
}
|
|
159
|
-
return chain.then((result) => {
|
|
160
|
-
if (!result) {
|
|
161
|
-
// early return from nested VersionCommand
|
|
162
|
-
return false;
|
|
163
|
-
}
|
|
164
|
-
if (!result.updates.length) {
|
|
165
|
-
this.logger.success('No changed packages to publish');
|
|
166
|
-
// still exits zero, aka 'ok'
|
|
167
|
-
return false;
|
|
168
|
-
}
|
|
169
|
-
// (occasionally) redundant private filtering necessary to handle nested VersionCommand
|
|
170
|
-
this.updates = result.updates.filter((node) => !node.pkg.private);
|
|
171
|
-
this.updatesVersions = new Map(result.updatesVersions);
|
|
172
|
-
this.packagesToPublish = this.updates.map((node) => node.pkg);
|
|
173
|
-
if (this.options.contents) {
|
|
174
|
-
// globally override directory to publish
|
|
175
|
-
for (const pkg of this.packagesToPublish) {
|
|
176
|
-
pkg.contents = this.options.contents;
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
if (result.needsConfirmation) {
|
|
180
|
-
// only confirm for --canary, bump === 'from-git',
|
|
181
|
-
// or bump === 'from-package', as VersionCommand
|
|
182
|
-
// has its own confirmation prompt
|
|
183
|
-
return this.confirmPublish();
|
|
184
|
-
}
|
|
185
|
-
return true;
|
|
186
|
-
});
|
|
187
|
-
}
|
|
188
|
-
async execute() {
|
|
189
|
-
var _a;
|
|
190
|
-
this.enableProgressBar();
|
|
191
|
-
this.logger.info('publish', 'Publishing packages to npm...');
|
|
192
|
-
await this.prepareRegistryActions();
|
|
193
|
-
await this.prepareLicenseActions();
|
|
194
|
-
if (this.options.canary) {
|
|
195
|
-
await this.updateCanaryVersions();
|
|
196
|
-
}
|
|
197
|
-
await this.resolveLocalDependencyLinks();
|
|
198
|
-
await this.resolveLocalDependencyWorkspaceProtocols();
|
|
199
|
-
if (this.options.removePackageFields) {
|
|
200
|
-
await this.removePackageProperties();
|
|
201
|
-
}
|
|
202
|
-
if (this.options.publishConfigOverrides !== false) {
|
|
203
|
-
await this.applyPublishConfigOverrides();
|
|
204
|
-
}
|
|
205
|
-
await this.annotateGitHead();
|
|
206
|
-
await this.serializeChanges();
|
|
207
|
-
await this.packUpdated();
|
|
208
|
-
await this.publishPacked();
|
|
209
|
-
if (this.gitReset) {
|
|
210
|
-
await this.resetChanges();
|
|
211
|
-
}
|
|
212
|
-
if (this.options.tempTag) {
|
|
213
|
-
await this.npmUpdateAsLatest();
|
|
214
|
-
}
|
|
215
|
-
const count = (_a = this.publishedPackages) === null || _a === void 0 ? void 0 : _a.length;
|
|
216
|
-
const publishedPackagesSorted = this.publishedPackages.sort((a, b) => a.name.localeCompare(b.name));
|
|
217
|
-
if (!count) {
|
|
218
|
-
this.logger.success('All packages have already been published.');
|
|
219
|
-
return;
|
|
220
|
-
}
|
|
221
|
-
(0, core_1.logOutput)('Successfully published:');
|
|
222
|
-
if (this.options.summaryFile !== undefined) {
|
|
223
|
-
// create a json object and output it to a file location.
|
|
224
|
-
const filePath = this.options.summaryFile
|
|
225
|
-
? `${this.options.summaryFile}/lerna-publish-summary.json`
|
|
226
|
-
: './lerna-publish-summary.json';
|
|
227
|
-
const jsonObject = publishedPackagesSorted.map((pkg) => {
|
|
228
|
-
return {
|
|
229
|
-
packageName: pkg.name,
|
|
230
|
-
version: pkg.version,
|
|
231
|
-
};
|
|
232
|
-
});
|
|
233
|
-
(0, core_1.logOutput)(jsonObject);
|
|
234
|
-
try {
|
|
235
|
-
fs_extra_1.default.outputFileSync(filePath, JSON.stringify(jsonObject));
|
|
236
|
-
(0, core_1.logOutput)('Publish summary created: ', filePath);
|
|
237
|
-
}
|
|
238
|
-
catch (error) {
|
|
239
|
-
(0, core_1.logOutput)('Failed to create the summary report', error);
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
else {
|
|
243
|
-
const message = publishedPackagesSorted.map((pkg) => ` - ${pkg.name}@${pkg.version}`);
|
|
244
|
-
(0, core_1.logOutput)(message.join(os_1.default.EOL));
|
|
245
|
-
}
|
|
246
|
-
// optionally cleanup temp packed files after publish, opt-in option
|
|
247
|
-
if (this.options.cleanupTempFiles) {
|
|
248
|
-
(0, glob_1.default)(path_1.default.join(temp_dir_1.default, '/lerna-*'), (_err, deleteFolders) => {
|
|
249
|
-
// delete silently all files/folders that startsWith "lerna-"
|
|
250
|
-
deleteFolders.forEach((folder) => fs_extra_1.default.removeSync(folder));
|
|
251
|
-
this.logger.verbose('publish', `Found ${deleteFolders.length} temp folders to cleanup after publish.`);
|
|
252
|
-
});
|
|
253
|
-
}
|
|
254
|
-
this.logger.success('published', '%d %s', count, count === 1 ? 'package' : 'packages');
|
|
255
|
-
}
|
|
256
|
-
verifyWorkingTreeClean() {
|
|
257
|
-
return (0, core_1.describeRef)(this.execOpts, undefined, this.options.dryRun).then(core_1.throwIfUncommitted);
|
|
258
|
-
}
|
|
259
|
-
detectFromGit() {
|
|
260
|
-
const matchingPattern = this.project.isIndependent() ? `*@*` : `${this.tagPrefix}*.*.*`;
|
|
261
|
-
let chain = Promise.resolve();
|
|
262
|
-
// attempting to publish a tagged release with local changes is not allowed
|
|
263
|
-
chain = chain.then(() => this.verifyWorkingTreeClean());
|
|
264
|
-
chain = chain.then(() => (0, get_current_tags_1.getCurrentTags)(this.execOpts, matchingPattern));
|
|
265
|
-
chain = chain.then((taggedPackageNames) => {
|
|
266
|
-
if (!taggedPackageNames.length) {
|
|
267
|
-
this.logger.notice('from-git', 'No tagged release found. You might not have fetched tags.');
|
|
268
|
-
return [];
|
|
269
|
-
}
|
|
270
|
-
if (this.project.isIndependent()) {
|
|
271
|
-
return taggedPackageNames.map((name) => this.packageGraph.get(name));
|
|
272
|
-
}
|
|
273
|
-
return (0, get_tagged_packages_1.getTaggedPackages)(this.packageGraph, this.project.rootPath, this.execOpts);
|
|
274
|
-
});
|
|
275
|
-
// private packages are never published, full stop.
|
|
276
|
-
chain = chain.then((updates) => updates.filter((node) => !node.pkg.private));
|
|
277
|
-
return chain.then((updates) => {
|
|
278
|
-
const updatesVersions = updates.map((node) => [node.name, node.version]);
|
|
279
|
-
return {
|
|
280
|
-
updates,
|
|
281
|
-
updatesVersions,
|
|
282
|
-
needsConfirmation: true,
|
|
283
|
-
};
|
|
284
|
-
});
|
|
285
|
-
}
|
|
286
|
-
detectFromPackage() {
|
|
287
|
-
let chain = Promise.resolve();
|
|
288
|
-
// attempting to publish a release with local changes is not allowed
|
|
289
|
-
chain = chain
|
|
290
|
-
.then(() => this.verifyWorkingTreeClean())
|
|
291
|
-
.catch((err) => {
|
|
292
|
-
// an execa error is thrown when git suffers a fatal error (such as no git repository present)
|
|
293
|
-
if (err.failed && /git describe/.test(err.command)) {
|
|
294
|
-
// (we tried)
|
|
295
|
-
this.logger.silly('EWORKINGTREE', err.message);
|
|
296
|
-
this.logger.notice('FYI', 'Unable to verify working tree, proceed at your own risk');
|
|
297
|
-
process.exitCode = 0;
|
|
298
|
-
}
|
|
299
|
-
else {
|
|
300
|
-
// validation errors should be preserved
|
|
301
|
-
throw err;
|
|
302
|
-
}
|
|
303
|
-
});
|
|
304
|
-
// private packages are already omitted by getUnpublishedPackages()
|
|
305
|
-
chain = chain.then(() => (0, get_unpublished_packages_1.getUnpublishedPackages)(this.packageGraph, this.conf.snapshot));
|
|
306
|
-
chain = chain.then((unpublished) => {
|
|
307
|
-
if (!unpublished.length) {
|
|
308
|
-
this.logger.notice('from-package', 'No unpublished release found');
|
|
309
|
-
}
|
|
310
|
-
return unpublished;
|
|
311
|
-
});
|
|
312
|
-
return chain.then((updates) => {
|
|
313
|
-
const updatesVersions = updates.map((node) => [node.name, node.version]);
|
|
314
|
-
return {
|
|
315
|
-
updates,
|
|
316
|
-
updatesVersions,
|
|
317
|
-
needsConfirmation: true,
|
|
318
|
-
};
|
|
319
|
-
});
|
|
320
|
-
}
|
|
321
|
-
detectCanaryVersions() {
|
|
322
|
-
const { cwd } = this.execOpts;
|
|
323
|
-
const { bump = 'prepatch', preid = 'alpha', ignoreChanges, forcePublish, includeMergedTags } = this.options;
|
|
324
|
-
// 'prerelease' and 'prepatch' are identical, for our purposes
|
|
325
|
-
const release = bump.startsWith('pre') ? bump.replace('release', 'patch') : `pre${bump}`;
|
|
326
|
-
let chain = Promise.resolve();
|
|
327
|
-
// attempting to publish a canary release with local changes is not allowed
|
|
328
|
-
chain = chain
|
|
329
|
-
.then(() => this.verifyWorkingTreeClean())
|
|
330
|
-
.catch((err) => {
|
|
331
|
-
// an execa error is thrown when git suffers a fatal error (such as no git repository present)
|
|
332
|
-
if (err.failed && /git describe/.test(err.command)) {
|
|
333
|
-
// (we tried)
|
|
334
|
-
this.logger.silly('EWORKINGTREE', err.message);
|
|
335
|
-
this.logger.notice('FYI', 'Unable to verify working tree, proceed at your own risk');
|
|
336
|
-
}
|
|
337
|
-
else {
|
|
338
|
-
// validation errors should be preserved
|
|
339
|
-
throw err;
|
|
340
|
-
}
|
|
341
|
-
});
|
|
342
|
-
const isIndependent = this.project.isIndependent();
|
|
343
|
-
// find changed packages since last release, if any
|
|
344
|
-
chain = chain.then(() => {
|
|
345
|
-
var _a, _b;
|
|
346
|
-
return (0, core_1.collectUpdates)((_b = (_a = this.packageGraph) === null || _a === void 0 ? void 0 : _a.rawPackageList) !== null && _b !== void 0 ? _b : [], this.packageGraph, this.execOpts, {
|
|
347
|
-
bump: 'prerelease',
|
|
348
|
-
canary: true,
|
|
349
|
-
ignoreChanges,
|
|
350
|
-
forcePublish,
|
|
351
|
-
includeMergedTags,
|
|
352
|
-
isIndependent,
|
|
353
|
-
// private packages are never published, don't bother describing their refs.
|
|
354
|
-
}, this.options.dryRun).filter((node) => !node.pkg.private);
|
|
355
|
-
});
|
|
356
|
-
// prettier-ignore
|
|
357
|
-
const makeVersion = (fallback) => ({ lastVersion = fallback, refCount, sha }) => {
|
|
358
|
-
// the next version is bumped without concern for preid or current index
|
|
359
|
-
// prettier-ignore
|
|
360
|
-
const nextVersion = semver_1.default.inc(lastVersion.replace(this.tagPrefix, ''), release.replace('pre', ''));
|
|
361
|
-
// semver.inc() starts a new prerelease at .0, git describe starts at .1
|
|
362
|
-
// and build metadata is always ignored when comparing dependency ranges
|
|
363
|
-
return `${nextVersion}-${preid}.${Math.max(0, refCount - 1)}+${sha}`;
|
|
364
|
-
};
|
|
365
|
-
if (isIndependent) {
|
|
366
|
-
// each package is described against its tags only
|
|
367
|
-
chain = chain.then((updates) => (0, p_map_1.default)(updates, (node) => (0, core_1.describeRef)({
|
|
368
|
-
match: `${node.name}@*`,
|
|
369
|
-
cwd,
|
|
370
|
-
}, includeMergedTags, this.options.dryRun)
|
|
371
|
-
// an unpublished package will have no reachable git tag
|
|
372
|
-
.then(makeVersion(node.version))
|
|
373
|
-
.then((version) => [node.name, version])).then((updatesVersions) => ({
|
|
374
|
-
updates,
|
|
375
|
-
updatesVersions,
|
|
376
|
-
})));
|
|
377
|
-
}
|
|
378
|
-
else {
|
|
379
|
-
// all packages are described against the last tag
|
|
380
|
-
chain = chain.then((updates) => (0, core_1.describeRef)({
|
|
381
|
-
match: `${this.tagPrefix}*.*.*`,
|
|
382
|
-
cwd,
|
|
383
|
-
}, includeMergedTags, this.options.dryRun)
|
|
384
|
-
// a repo with no tags should default to whatever lerna.json claims
|
|
385
|
-
.then(makeVersion(this.project.version))
|
|
386
|
-
.then((version) => updates.map((node) => [node.name, version]))
|
|
387
|
-
.then((updatesVersions) => ({
|
|
388
|
-
updates,
|
|
389
|
-
updatesVersions,
|
|
390
|
-
})));
|
|
391
|
-
}
|
|
392
|
-
return chain.then(({ updates, updatesVersions }) => ({
|
|
393
|
-
updates,
|
|
394
|
-
updatesVersions,
|
|
395
|
-
needsConfirmation: true,
|
|
396
|
-
}));
|
|
397
|
-
}
|
|
398
|
-
confirmPublish() {
|
|
399
|
-
var _a, _b, _c;
|
|
400
|
-
const count = (_a = this.packagesToPublish) === null || _a === void 0 ? void 0 : _a.length;
|
|
401
|
-
const message = (_c = (_b = this.packagesToPublish) === null || _b === void 0 ? void 0 : _b.map((pkg) => { var _a; return ` - ${pkg.name} => ${(_a = this.updatesVersions) === null || _a === void 0 ? void 0 : _a.get(pkg.name)}`; })) !== null && _c !== void 0 ? _c : [];
|
|
402
|
-
(0, core_1.logOutput)('');
|
|
403
|
-
(0, core_1.logOutput)(`Found ${count} ${count === 1 ? 'package' : 'packages'} to publish:`);
|
|
404
|
-
(0, core_1.logOutput)(message.join(os_1.default.EOL));
|
|
405
|
-
(0, core_1.logOutput)('');
|
|
406
|
-
if (this.options.yes) {
|
|
407
|
-
this.logger.info('auto-confirmed', '');
|
|
408
|
-
return true;
|
|
409
|
-
}
|
|
410
|
-
let confirmMessage = this.options.dryRun ? chalk_1.default.bgMagenta('[dry-run]') : '';
|
|
411
|
-
confirmMessage += ' Are you sure you want to publish these packages?';
|
|
412
|
-
return (0, core_1.promptConfirmation)(confirmMessage.trim());
|
|
413
|
-
}
|
|
414
|
-
prepareLicenseActions() {
|
|
415
|
-
return Promise.resolve()
|
|
416
|
-
.then(() => { var _a; return (0, get_packages_without_license_1.getPackagesWithoutLicense)(this.project, (_a = this.packagesToPublish) !== null && _a !== void 0 ? _a : []); })
|
|
417
|
-
.then((packagesWithoutLicense) => {
|
|
418
|
-
if (packagesWithoutLicense.length && !this.project.licensePath) {
|
|
419
|
-
this.packagesToBeLicensed = [];
|
|
420
|
-
const names = packagesWithoutLicense.map((pkg) => pkg.name);
|
|
421
|
-
const noun = names.length > 1 ? 'Packages' : 'Package';
|
|
422
|
-
const verb = names.length > 1 ? 'are' : 'is';
|
|
423
|
-
const list =
|
|
424
|
-
// prettier-ignore
|
|
425
|
-
names.length > 1
|
|
426
|
-
? `${names.slice(0, -1).join(', ')}${names.length > 2 ? ',' : ''} and ${names[names.length - 1] /* oxford commas _are_ that important */}`
|
|
427
|
-
: names[0];
|
|
428
|
-
this.logger.warn('ENOLICENSE', '%s %s %s missing a license.\n%s\n%s', noun, list, verb, 'One way to fix this is to add a LICENSE.md file to the root of this repository.', 'See https://choosealicense.com for additional guidance.');
|
|
429
|
-
}
|
|
430
|
-
else {
|
|
431
|
-
this.packagesToBeLicensed = packagesWithoutLicense;
|
|
432
|
-
}
|
|
433
|
-
});
|
|
434
|
-
}
|
|
435
|
-
prepareRegistryActions() {
|
|
436
|
-
let chain = Promise.resolve();
|
|
437
|
-
if (this.conf.get('registry') !== 'https://registry.npmjs.org/') {
|
|
438
|
-
this.logger.notice('', 'Skipping all user and access validation due to third-party registry');
|
|
439
|
-
this.logger.notice('', `Make sure you're authenticated properly "\\_(ツ)_ /"`);
|
|
440
|
-
return chain;
|
|
441
|
-
}
|
|
442
|
-
/* istanbul ignore if */
|
|
443
|
-
if (process.env.LERNA_INTEGRATION) {
|
|
444
|
-
return chain;
|
|
445
|
-
}
|
|
446
|
-
if (this.verifyAccess) {
|
|
447
|
-
// validate user has valid npm credentials first,
|
|
448
|
-
// by far the most common form of failed execution
|
|
449
|
-
chain = chain.then(() => (0, get_npm_username_1.getNpmUsername)(this.conf.snapshot));
|
|
450
|
-
chain = chain.then((username) => {
|
|
451
|
-
var _a;
|
|
452
|
-
// if no username was retrieved, don't bother validating
|
|
453
|
-
if (username) {
|
|
454
|
-
return (0, verify_npm_package_access_1.verifyNpmPackageAccess)((_a = this.packagesToPublish) !== null && _a !== void 0 ? _a : [], username, this.conf.snapshot);
|
|
455
|
-
}
|
|
456
|
-
});
|
|
457
|
-
// read profile metadata to determine if account-level 2FA is enabled
|
|
458
|
-
chain = chain.then(() => (0, get_two_factor_auth_required_1.getTwoFactorAuthRequired)(this.conf.snapshot));
|
|
459
|
-
chain = chain.then((isRequired) => {
|
|
460
|
-
// notably, this still doesn't handle package-level 2FA requirements
|
|
461
|
-
this.twoFactorAuthRequired = isRequired;
|
|
462
|
-
});
|
|
463
|
-
}
|
|
464
|
-
return chain;
|
|
465
|
-
}
|
|
466
|
-
updateCanaryVersions() {
|
|
467
|
-
return (0, p_map_1.default)(this.updates, (node) => {
|
|
468
|
-
var _a, _b, _c;
|
|
469
|
-
node.pkg.set('version', (_a = this.updatesVersions) === null || _a === void 0 ? void 0 : _a.get(node.name));
|
|
470
|
-
for (const [depName, resolved] of node.localDependencies) {
|
|
471
|
-
// other canary versions need to be updated, non-canary is a no-op
|
|
472
|
-
const depVersion = ((_b = this.updatesVersions) === null || _b === void 0 ? void 0 : _b.get(depName)) || ((_c = this.packageGraph) === null || _c === void 0 ? void 0 : _c.get(depName).pkg.version);
|
|
473
|
-
// it no longer matters if we mutate the shared Package instance
|
|
474
|
-
node.pkg.updateLocalDependency(resolved, depVersion, this.savePrefix, this.options.allowPeerDependenciesUpdate, this.options.workspaceStrictMatch, this.commandName);
|
|
475
|
-
}
|
|
476
|
-
// writing changes to disk handled in serializeChanges()
|
|
477
|
-
});
|
|
478
|
-
}
|
|
479
|
-
/**
|
|
480
|
-
* It is possible to override some fields in the manifest before the package is packed
|
|
481
|
-
* @see https://pnpm.io/package_json#publishconfig
|
|
482
|
-
* @returns
|
|
483
|
-
*/
|
|
484
|
-
applyPublishConfigOverrides() {
|
|
485
|
-
// potentially apply any packages that might have publishConfig overrides
|
|
486
|
-
return (0, p_map_1.default)(this.updates, (node) => (0, override_publish_config_1.overridePublishConfig)(node.pkg.manifest));
|
|
487
|
-
}
|
|
488
|
-
resolveLocalDependencyLinks() {
|
|
489
|
-
// resolve relative file: links to their actual version range
|
|
490
|
-
const updatesWithLocalLinks = this.updates.filter((node) => Array.from(node.localDependencies.values()).some((resolved) => resolved.type === 'directory'));
|
|
491
|
-
return (0, p_map_1.default)(updatesWithLocalLinks, (node) => {
|
|
492
|
-
var _a, _b;
|
|
493
|
-
for (const [depName, resolved] of node.localDependencies) {
|
|
494
|
-
// regardless of where the version comes from, we can't publish 'file:../sibling-pkg' specs
|
|
495
|
-
const depVersion = ((_a = this.updatesVersions) === null || _a === void 0 ? void 0 : _a.get(depName)) || ((_b = this.packageGraph) === null || _b === void 0 ? void 0 : _b.get(depName).pkg.version);
|
|
496
|
-
// it no longer matters if we mutate the shared Package instance
|
|
497
|
-
node.pkg.updateLocalDependency(resolved, depVersion, this.savePrefix, this.options.allowPeerDependenciesUpdate, this.options.workspaceStrictMatch, this.commandName);
|
|
498
|
-
}
|
|
499
|
-
// writing changes to disk handled in serializeChanges()
|
|
500
|
-
});
|
|
501
|
-
}
|
|
502
|
-
resolveLocalDependencyWorkspaceProtocols() {
|
|
503
|
-
// resolve workspace protocol: translates to their actual version target/range
|
|
504
|
-
const publishingPackagesWithLocalWorkspaces = this.updates.filter((node) => Array.from(node.localDependencies.values()).some((resolved) => resolved.workspaceSpec));
|
|
505
|
-
return (0, p_map_1.default)(publishingPackagesWithLocalWorkspaces, (node) => {
|
|
506
|
-
// regardless of where the version comes from, we can't publish 'workspace:*' specs, it has to be transformed for both local & external dependencies
|
|
507
|
-
// e.g. considering version is `1.2.3` and we have `workspace:*` it will be converted to "^1.2.3" or to "1.2.3" with strict match range enabled
|
|
508
|
-
var _a, _b;
|
|
509
|
-
// 1. update & bump version of local dependencies
|
|
510
|
-
for (const [depName, resolved] of node.localDependencies) {
|
|
511
|
-
const depVersion = ((_a = this.updatesVersions) === null || _a === void 0 ? void 0 : _a.get(depName)) || ((_b = this.packageGraph) === null || _b === void 0 ? void 0 : _b.get(depName).pkg.version);
|
|
512
|
-
// it no longer matters if we mutate the shared Package instance
|
|
513
|
-
node.pkg.updateLocalDependency(resolved, depVersion, this.savePrefix, this.options.allowPeerDependenciesUpdate, this.options.workspaceStrictMatch, this.commandName);
|
|
514
|
-
}
|
|
515
|
-
// 2. remove any "workspace:" prefix from the package to be published any of external dependencies (without anything being bumped)
|
|
516
|
-
// we will only accept "workspace:" with semver version, for example "workspace:1.2.3" is ok but "workspace:*" will log an error
|
|
517
|
-
for (const [_depName, resolved] of node.externalDependencies) {
|
|
518
|
-
node.pkg.removeDependencyWorkspaceProtocolPrefix(node.name, resolved);
|
|
519
|
-
}
|
|
520
|
-
// writing changes to disk handled in serializeChanges()
|
|
521
|
-
});
|
|
522
|
-
}
|
|
523
|
-
annotateGitHead() {
|
|
524
|
-
var _a;
|
|
525
|
-
try {
|
|
526
|
-
const gitHead = this.options.gitHead || (0, get_current_sha_1.getCurrentSHA)(this.execOpts);
|
|
527
|
-
for (const pkg of (_a = this.packagesToPublish) !== null && _a !== void 0 ? _a : []) {
|
|
528
|
-
// provide gitHead property that is normally added during npm publish
|
|
529
|
-
pkg.set('gitHead', gitHead);
|
|
530
|
-
}
|
|
531
|
-
}
|
|
532
|
-
catch (err) {
|
|
533
|
-
// from-package should be _able_ to run without git, but at least we tried
|
|
534
|
-
this.logger.silly('EGITHEAD', err.message);
|
|
535
|
-
this.logger.notice('FYI', 'Unable to set temporary gitHead property, it will be missing from registry metadata');
|
|
536
|
-
}
|
|
537
|
-
// writing changes to disk handled in serializeChanges()
|
|
538
|
-
}
|
|
539
|
-
serializeChanges() {
|
|
540
|
-
var _a;
|
|
541
|
-
return (0, p_map_1.default)((_a = this.packagesToPublish) !== null && _a !== void 0 ? _a : [], (pkg) => pkg.serialize());
|
|
542
|
-
}
|
|
543
|
-
resetChanges() {
|
|
544
|
-
// the package.json files are changed (by gitHead if not --canary)
|
|
545
|
-
// and we should always __attempt_ to leave the working tree clean
|
|
546
|
-
const { cwd } = this.execOpts;
|
|
547
|
-
const gitOpts = {
|
|
548
|
-
granularPathspec: this.options.granularPathspec !== false,
|
|
549
|
-
};
|
|
550
|
-
const dirtyManifests = [this.project.manifest]
|
|
551
|
-
.concat(this.packagesToPublish)
|
|
552
|
-
.map((pkg) => path_1.default.relative(cwd, pkg.manifestLocation));
|
|
553
|
-
return (0, git_checkout_1.gitCheckout)(dirtyManifests, gitOpts, this.execOpts, this.options.dryRun).catch((err) => {
|
|
554
|
-
this.logger.silly('EGITCHECKOUT', err.message);
|
|
555
|
-
this.logger.notice('FYI', `Unable to reset working tree changes, this probably isn't a git repo.`);
|
|
556
|
-
});
|
|
557
|
-
}
|
|
558
|
-
// @deprecated, see Lerna PR https://github.com/lerna/lerna/pull/1862/files
|
|
559
|
-
execScript(pkg, script) {
|
|
560
|
-
const scriptLocation = path_1.default.join(pkg.location, 'scripts', script);
|
|
561
|
-
try {
|
|
562
|
-
require(scriptLocation);
|
|
563
|
-
}
|
|
564
|
-
catch (ex) {
|
|
565
|
-
this.logger.silly('execScript', `No ${script} script found at ${scriptLocation}`);
|
|
566
|
-
}
|
|
567
|
-
return pkg;
|
|
568
|
-
}
|
|
569
|
-
removePackageProperties() {
|
|
570
|
-
const { removePackageFields } = this.options;
|
|
571
|
-
return (0, p_map_1.default)(this.updates, (node) => {
|
|
572
|
-
if (Array.isArray(removePackageFields)) {
|
|
573
|
-
for (const removeField of removePackageFields) {
|
|
574
|
-
(0, core_1.deleteComplexObjectProp)(node.pkg.manifest, removeField, `"${node.pkg.name}" package`);
|
|
575
|
-
}
|
|
576
|
-
}
|
|
577
|
-
});
|
|
578
|
-
}
|
|
579
|
-
removeTempLicensesOnError(error) {
|
|
580
|
-
return Promise.resolve()
|
|
581
|
-
.then(() => {
|
|
582
|
-
var _a;
|
|
583
|
-
return (0, remove_temp_licenses_1.removeTempLicenses)((_a = this.packagesToBeLicensed) !== null && _a !== void 0 ? _a : []).catch((removeError) => {
|
|
584
|
-
this.logger.error('licenses', 'error removing temporary license files', removeError.stack || removeError);
|
|
585
|
-
});
|
|
586
|
-
})
|
|
587
|
-
.then(() => {
|
|
588
|
-
// restore original error into promise chain
|
|
589
|
-
throw error;
|
|
590
|
-
});
|
|
591
|
-
}
|
|
592
|
-
requestOneTimePassword() {
|
|
593
|
-
if (this.options.dryRun) {
|
|
594
|
-
this.logger.info(chalk_1.default.bold.magenta('[dry-run] >'), 'will ask OTP');
|
|
595
|
-
return;
|
|
596
|
-
}
|
|
597
|
-
// if OTP has already been provided, skip prompt
|
|
598
|
-
if (this.otpCache.otp) {
|
|
599
|
-
return;
|
|
600
|
-
}
|
|
601
|
-
return Promise.resolve()
|
|
602
|
-
.then(() => (0, version_1.getOneTimePassword)('Enter OTP:'))
|
|
603
|
-
.then((otp) => (this.otpCache.otp = otp));
|
|
604
|
-
}
|
|
605
|
-
topoMapPackages(mapper) {
|
|
606
|
-
return (0, core_1.runTopologically)(this.packagesToPublish, mapper, {
|
|
607
|
-
concurrency: this.concurrency,
|
|
608
|
-
rejectCycles: this.options.rejectCycles,
|
|
609
|
-
/**
|
|
610
|
-
* Previously `publish` had unique default behavior for graph creation vs other commands: it would only consider dependencies when finding
|
|
611
|
-
* edges by default (i.e. relationships between packages specified via devDependencies would be ignored). It was documented to be the case
|
|
612
|
-
* in order to try and reduce the chance of dependency cycles.
|
|
613
|
-
*
|
|
614
|
-
* We are removing this behavior altogether in v6 because we do not want to have different ways of constructing the graph,
|
|
615
|
-
* only different ways of utilizing it (e.g. --no-sort vs topological sort).
|
|
616
|
-
*
|
|
617
|
-
* Therefore until we remove graphType altogether in v6, we provide a way for users to opt into the old default behavior
|
|
618
|
-
* by setting the `graphType` option to `dependencies`.
|
|
619
|
-
*/
|
|
620
|
-
// prettier-ignore
|
|
621
|
-
graphType: this.options.graphType === 'dependencies'
|
|
622
|
-
? 'dependencies'
|
|
623
|
-
: this.options.allowPeerDependenciesUpdate
|
|
624
|
-
? 'allPlusPeerDependencies'
|
|
625
|
-
: 'allDependencies',
|
|
626
|
-
});
|
|
627
|
-
}
|
|
628
|
-
packUpdated() {
|
|
629
|
-
var _a;
|
|
630
|
-
const tracker = this.logger.newItem('npm pack');
|
|
631
|
-
tracker.addWork((_a = this.packagesToPublish) === null || _a === void 0 ? void 0 : _a.length);
|
|
632
|
-
let chain = Promise.resolve();
|
|
633
|
-
chain = chain.then(() => { var _a; return (0, create_temp_licenses_1.createTempLicenses)(this.project.licensePath, (_a = this.packagesToBeLicensed) !== null && _a !== void 0 ? _a : []); });
|
|
634
|
-
if (!this.hasRootedLeaf) {
|
|
635
|
-
// despite being deprecated for years...
|
|
636
|
-
chain = chain.then(() => this.runRootLifecycle('prepublish'));
|
|
637
|
-
// these lifecycles _should_ never be employed to run `lerna publish`...
|
|
638
|
-
chain = chain.then(() => this.runPackageLifecycle(this.project.manifest, 'prepare'));
|
|
639
|
-
chain = chain.then(() => this.runPackageLifecycle(this.project.manifest, 'prepublishOnly'));
|
|
640
|
-
chain = chain.then(() => this.runPackageLifecycle(this.project.manifest, 'prepack'));
|
|
641
|
-
}
|
|
642
|
-
const opts = this.conf.snapshot;
|
|
643
|
-
const mapper = (0, p_pipe_1.default)(...[
|
|
644
|
-
this.options.requireScripts && ((pkg) => this.execScript(pkg, 'prepublish')),
|
|
645
|
-
(pkg) => (0, core_1.pulseTillDone)((0, pack_directory_1.packDirectory)(pkg, pkg.location, opts)).then((packed) => {
|
|
646
|
-
var _a;
|
|
647
|
-
tracker.verbose('packed', path_1.default.relative((_a = this.project.rootPath) !== null && _a !== void 0 ? _a : '', pkg.contents));
|
|
648
|
-
tracker.completeWork(1);
|
|
649
|
-
// store metadata for use in this.publishPacked()
|
|
650
|
-
pkg.packed = packed;
|
|
651
|
-
// manifest may be mutated by any previous lifecycle
|
|
652
|
-
return pkg.refresh();
|
|
653
|
-
}),
|
|
654
|
-
].filter(Boolean));
|
|
655
|
-
chain = chain.then(() => {
|
|
656
|
-
if (this.toposort) {
|
|
657
|
-
return this.topoMapPackages(mapper);
|
|
658
|
-
}
|
|
659
|
-
return (0, p_map_1.default)(this.packagesToPublish, mapper, { concurrency: this.concurrency });
|
|
660
|
-
});
|
|
661
|
-
chain = chain.then(() => { var _a; return (0, remove_temp_licenses_1.removeTempLicenses)((_a = this.packagesToBeLicensed) !== null && _a !== void 0 ? _a : []); });
|
|
662
|
-
// remove temporary license files if _any_ error occurs _anywhere_ in the promise chain
|
|
663
|
-
chain = chain.catch((error) => this.removeTempLicensesOnError(error));
|
|
664
|
-
if (!this.hasRootedLeaf) {
|
|
665
|
-
chain = chain.then(() => this.runPackageLifecycle(this.project.manifest, 'postpack'));
|
|
666
|
-
}
|
|
667
|
-
return chain.finally(() => tracker.finish());
|
|
668
|
-
}
|
|
669
|
-
publishPacked() {
|
|
670
|
-
var _a;
|
|
671
|
-
this.publishedPackages = [];
|
|
672
|
-
const tracker = this.logger.newItem('publish');
|
|
673
|
-
tracker.addWork((_a = this.packagesToPublish) === null || _a === void 0 ? void 0 : _a.length);
|
|
674
|
-
let chain = Promise.resolve();
|
|
675
|
-
// if account-level 2FA is enabled, prime the OTP cache
|
|
676
|
-
if (this.twoFactorAuthRequired) {
|
|
677
|
-
chain = chain.then(() => this.requestOneTimePassword());
|
|
678
|
-
}
|
|
679
|
-
const opts = Object.assign(this.conf.snapshot, {
|
|
680
|
-
// distTag defaults to 'latest' OR whatever is in pkg.publishConfig.tag
|
|
681
|
-
// if we skip temp tags we should tag with the proper value immediately
|
|
682
|
-
tag: this.options.tempTag ? 'lerna-temp' : this.conf.get('tag'),
|
|
683
|
-
'git-dry-run': this.options.dryRun || false,
|
|
684
|
-
});
|
|
685
|
-
const mapper = (0, p_pipe_1.default)(...[
|
|
686
|
-
(pkg) => {
|
|
687
|
-
const preDistTag = this.getPreDistTag(pkg);
|
|
688
|
-
const tag = !this.options.tempTag && preDistTag ? preDistTag : opts.tag;
|
|
689
|
-
const pkgOpts = Object.assign({}, opts, { tag });
|
|
690
|
-
return (0, core_1.pulseTillDone)((0, npm_publish_1.npmPublish)(pkg, pkg.packed.tarFilePath, pkgOpts, this.otpCache))
|
|
691
|
-
.then(() => {
|
|
692
|
-
this.publishedPackages.push(pkg);
|
|
693
|
-
tracker.success('published', pkg.name, pkg.version);
|
|
694
|
-
tracker.completeWork(1);
|
|
695
|
-
(0, log_packed_1.logPacked)(pkg, this.options.dryRun);
|
|
696
|
-
return pkg;
|
|
697
|
-
})
|
|
698
|
-
.catch((err) => {
|
|
699
|
-
if (err.code === 'EPUBLISHCONFLICT') {
|
|
700
|
-
tracker.warn('publish', `Package is already published: ${pkg.name}@${pkg.version}`);
|
|
701
|
-
tracker.completeWork(1);
|
|
702
|
-
return pkg;
|
|
703
|
-
}
|
|
704
|
-
this.logger.silly('', err);
|
|
705
|
-
this.logger.error(err.code, (err.body && err.body.error) || err.message);
|
|
706
|
-
// avoid dumping logs, this isn't a lerna problem
|
|
707
|
-
err.name = 'ValidationError';
|
|
708
|
-
// ensure process exits non-zero
|
|
709
|
-
process.exitCode = 'errno' in err ? err.errno : 1;
|
|
710
|
-
throw err;
|
|
711
|
-
});
|
|
712
|
-
},
|
|
713
|
-
this.options.requireScripts && ((pkg) => this.execScript(pkg, 'postpublish')),
|
|
714
|
-
].filter(Boolean));
|
|
715
|
-
chain = chain.then(() => {
|
|
716
|
-
if (this.toposort) {
|
|
717
|
-
return this.topoMapPackages(mapper);
|
|
718
|
-
}
|
|
719
|
-
return (0, p_map_1.default)(this.packagesToPublish, mapper, { concurrency: this.concurrency });
|
|
720
|
-
});
|
|
721
|
-
if (!this.hasRootedLeaf) {
|
|
722
|
-
// cyclical 'publish' lifecycles are automatically skipped
|
|
723
|
-
chain = chain.then(() => this.runRootLifecycle('publish'));
|
|
724
|
-
chain = chain.then(() => this.runRootLifecycle('postpublish'));
|
|
725
|
-
}
|
|
726
|
-
return chain.finally(() => tracker.finish());
|
|
727
|
-
}
|
|
728
|
-
npmUpdateAsLatest() {
|
|
729
|
-
var _a;
|
|
730
|
-
const tracker = this.logger.newItem('npmUpdateAsLatest');
|
|
731
|
-
tracker.addWork((_a = this.packagesToPublish) === null || _a === void 0 ? void 0 : _a.length);
|
|
732
|
-
tracker.showProgress();
|
|
733
|
-
let chain = Promise.resolve();
|
|
734
|
-
const opts = this.conf.snapshot;
|
|
735
|
-
const getDistTag = (publishConfig) => {
|
|
736
|
-
if (opts.tag === 'latest' && (publishConfig === null || publishConfig === void 0 ? void 0 : publishConfig.tag)) {
|
|
737
|
-
return publishConfig.tag;
|
|
738
|
-
}
|
|
739
|
-
return opts.tag;
|
|
740
|
-
};
|
|
741
|
-
const mapper = (pkg) => {
|
|
742
|
-
const spec = `${pkg.name}@${pkg.version}`;
|
|
743
|
-
const preDistTag = this.getPreDistTag(pkg);
|
|
744
|
-
const distTag = preDistTag || getDistTag(pkg.get('publishConfig'));
|
|
745
|
-
return Promise.resolve()
|
|
746
|
-
.then(() => (0, core_1.pulseTillDone)((0, npm_dist_tag_1.remove)(spec, 'lerna-temp', opts, this.otpCache)))
|
|
747
|
-
.then(() => (0, core_1.pulseTillDone)((0, npm_dist_tag_1.add)(spec, distTag, opts, this.otpCache)))
|
|
748
|
-
.then(() => {
|
|
749
|
-
tracker.success('dist-tag', '%s@%s => %j', pkg.name, pkg.version, distTag);
|
|
750
|
-
tracker.completeWork(1);
|
|
751
|
-
return pkg;
|
|
752
|
-
});
|
|
753
|
-
};
|
|
754
|
-
chain = chain.then(() => {
|
|
755
|
-
if (this.toposort) {
|
|
756
|
-
return this.topoMapPackages(mapper);
|
|
757
|
-
}
|
|
758
|
-
return (0, p_map_1.default)(this.packagesToPublish, mapper, { concurrency: this.concurrency });
|
|
759
|
-
});
|
|
760
|
-
return chain.finally(() => tracker.finish());
|
|
761
|
-
}
|
|
762
|
-
getDistTag() {
|
|
763
|
-
if (this.options.distTag) {
|
|
764
|
-
return this.options.distTag;
|
|
765
|
-
}
|
|
766
|
-
if (this.options.canary) {
|
|
767
|
-
return 'canary';
|
|
768
|
-
}
|
|
769
|
-
// undefined defaults to 'latest' OR whatever is in pkg.publishConfig.tag
|
|
770
|
-
}
|
|
771
|
-
getPreDistTag(pkg) {
|
|
772
|
-
if (!this.options.preDistTag) {
|
|
773
|
-
return;
|
|
774
|
-
}
|
|
775
|
-
const isPrerelease = (0, core_1.prereleaseIdFromVersion)(pkg.version);
|
|
776
|
-
if (isPrerelease) {
|
|
777
|
-
return this.options.preDistTag;
|
|
778
|
-
}
|
|
779
|
-
}
|
|
780
|
-
}
|
|
781
|
-
exports.PublishCommand = PublishCommand;
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PublishCommand = exports.factory = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const chalk_1 = tslib_1.__importDefault(require("chalk"));
|
|
6
|
+
const glob_1 = tslib_1.__importDefault(require("glob"));
|
|
7
|
+
const fs_extra_1 = tslib_1.__importDefault(require("fs-extra"));
|
|
8
|
+
const os_1 = tslib_1.__importDefault(require("os"));
|
|
9
|
+
const path_1 = tslib_1.__importDefault(require("path"));
|
|
10
|
+
const crypto_1 = tslib_1.__importDefault(require("crypto"));
|
|
11
|
+
const p_map_1 = tslib_1.__importDefault(require("p-map"));
|
|
12
|
+
const p_pipe_1 = tslib_1.__importDefault(require("p-pipe"));
|
|
13
|
+
const semver_1 = tslib_1.__importDefault(require("semver"));
|
|
14
|
+
const temp_dir_1 = tslib_1.__importDefault(require("temp-dir"));
|
|
15
|
+
const version_1 = require("@lerna-lite/version");
|
|
16
|
+
const core_1 = require("@lerna-lite/core");
|
|
17
|
+
const get_current_tags_1 = require("./lib/get-current-tags");
|
|
18
|
+
const get_tagged_packages_1 = require("./lib/get-tagged-packages");
|
|
19
|
+
const get_unpublished_packages_1 = require("./lib/get-unpublished-packages");
|
|
20
|
+
const get_npm_username_1 = require("./lib/get-npm-username");
|
|
21
|
+
const verify_npm_package_access_1 = require("./lib/verify-npm-package-access");
|
|
22
|
+
const get_two_factor_auth_required_1 = require("./lib/get-two-factor-auth-required");
|
|
23
|
+
const get_current_sha_1 = require("./lib/get-current-sha");
|
|
24
|
+
const git_checkout_1 = require("./lib/git-checkout");
|
|
25
|
+
const pack_directory_1 = require("./lib/pack-directory");
|
|
26
|
+
const npm_publish_1 = require("./lib/npm-publish");
|
|
27
|
+
const log_packed_1 = require("./lib/log-packed");
|
|
28
|
+
const npm_dist_tag_1 = require("./lib/npm-dist-tag");
|
|
29
|
+
const override_publish_config_1 = require("./lib/override-publish-config");
|
|
30
|
+
const remove_temp_licenses_1 = require("./lib/remove-temp-licenses");
|
|
31
|
+
const create_temp_licenses_1 = require("./lib/create-temp-licenses");
|
|
32
|
+
const get_packages_without_license_1 = require("./lib/get-packages-without-license");
|
|
33
|
+
function factory(argv) {
|
|
34
|
+
return new PublishCommand(argv);
|
|
35
|
+
}
|
|
36
|
+
exports.factory = factory;
|
|
37
|
+
class PublishCommand extends core_1.Command {
|
|
38
|
+
get otherCommandConfigs() {
|
|
39
|
+
// back-compat
|
|
40
|
+
return ['version'];
|
|
41
|
+
}
|
|
42
|
+
get requiresGit() {
|
|
43
|
+
// `lerna publish from-package` doesn't _need_ git, per se
|
|
44
|
+
return this.options.bump !== 'from-package';
|
|
45
|
+
}
|
|
46
|
+
constructor(argv) {
|
|
47
|
+
super(argv);
|
|
48
|
+
/** command name */
|
|
49
|
+
this.name = 'publish';
|
|
50
|
+
this.gitReset = false;
|
|
51
|
+
this.savePrefix = '';
|
|
52
|
+
this.tagPrefix = '';
|
|
53
|
+
this.hasRootedLeaf = false;
|
|
54
|
+
this.npmSession = '';
|
|
55
|
+
this.packagesToPublish = [];
|
|
56
|
+
this.publishedPackages = [];
|
|
57
|
+
this.packagesToBeLicensed = [];
|
|
58
|
+
this.verifyAccess = false;
|
|
59
|
+
this.toposort = false;
|
|
60
|
+
this.twoFactorAuthRequired = false;
|
|
61
|
+
this.updates = [];
|
|
62
|
+
}
|
|
63
|
+
configureProperties() {
|
|
64
|
+
super.configureProperties();
|
|
65
|
+
// For publish we want to enable topological sorting by default, but allow users to override with --no-sort
|
|
66
|
+
this.toposort = this.options.sort !== false;
|
|
67
|
+
// Defaults are necessary here because yargs defaults
|
|
68
|
+
// override durable options provided by a config file
|
|
69
|
+
const {
|
|
70
|
+
// prettier-ignore
|
|
71
|
+
exact, gitHead, gitReset, tagVersionPrefix = 'v', verifyAccess, } = this.options;
|
|
72
|
+
if (this.requiresGit && gitHead) {
|
|
73
|
+
throw new core_1.ValidationError('EGITHEAD', '--git-head is only allowed with "from-package" positional');
|
|
74
|
+
}
|
|
75
|
+
// https://docs.npmjs.com/misc/config#save-prefix
|
|
76
|
+
this.savePrefix = exact ? '' : '^';
|
|
77
|
+
// https://docs.npmjs.com/misc/config#tag-version-prefix
|
|
78
|
+
this.tagPrefix = tagVersionPrefix;
|
|
79
|
+
// TODO: properly inherit from npm-conf
|
|
80
|
+
// inverted boolean options are only respected if prefixed with `--no-`, e.g. `--no-verify-access`
|
|
81
|
+
this.gitReset = gitReset !== false;
|
|
82
|
+
// consumed by npm-registry-fetch (via libnpmpublish)
|
|
83
|
+
this.npmSession = crypto_1.default.randomBytes(8).toString('hex');
|
|
84
|
+
this.verifyAccess = verifyAccess;
|
|
85
|
+
}
|
|
86
|
+
get userAgent() {
|
|
87
|
+
// consumed by npm-registry-fetch (via libnpmpublish)
|
|
88
|
+
return `lerna/${this.options.lernaVersion}/node@${process.version}+${process.arch} (${process.platform})`;
|
|
89
|
+
}
|
|
90
|
+
initialize() {
|
|
91
|
+
if (this.options.verifyAccess === false) {
|
|
92
|
+
this.logger.warn('verify-access', '--verify-access=false and --no-verify-access are no longer needed, because the legacy preemptive access verification is now disabled by default. Requests will fail with appropriate errors when not authorized correctly.');
|
|
93
|
+
}
|
|
94
|
+
if (this.options.graphType === 'dependencies') {
|
|
95
|
+
this.logger.warn('graph-type', '--graph-type=dependencies is deprecated and will be removed in the next major version of lerna-lite. If you have a use-case you feel requires it please open an issue to discuss: https://github.com/lerna/lerna/issues/new/choose');
|
|
96
|
+
}
|
|
97
|
+
if (this.options.workspaceStrictMatch === false) {
|
|
98
|
+
this.logger.warn('deprecation', 'Providing --no-workspace-strict-match is deprecated and will be removed in future version, we will make "workspace:" protocol strict matching in every case.');
|
|
99
|
+
}
|
|
100
|
+
if (this.options.buildMetadata && this.options.canary) {
|
|
101
|
+
throw new core_1.ValidationError('ENOTSATISFIED', 'Cannot use --build-metadata in conjunction with --canary option.');
|
|
102
|
+
}
|
|
103
|
+
else if (this.options.canary) {
|
|
104
|
+
this.logger.info('canary', 'enabled');
|
|
105
|
+
}
|
|
106
|
+
// @deprecated, to be removed in next major
|
|
107
|
+
if (this.options.requireScripts) {
|
|
108
|
+
this.logger.info('require-scripts', 'enabled');
|
|
109
|
+
}
|
|
110
|
+
// npmSession and user-agent are consumed by npm-registry-fetch (via libnpmpublish)
|
|
111
|
+
this.logger.verbose('session', this.npmSession);
|
|
112
|
+
this.logger.verbose('user-agent', this.userAgent);
|
|
113
|
+
this.conf = (0, core_1.npmConf)({
|
|
114
|
+
lernaCommand: 'publish',
|
|
115
|
+
_auth: this.options.legacyAuth,
|
|
116
|
+
npmSession: this.npmSession,
|
|
117
|
+
npmVersion: this.userAgent,
|
|
118
|
+
otp: this.options.otp,
|
|
119
|
+
registry: this.options.registry,
|
|
120
|
+
'ignore-prepublish': this.options.ignorePrepublish,
|
|
121
|
+
'ignore-scripts': this.options.ignoreScripts,
|
|
122
|
+
});
|
|
123
|
+
// cache to hold a one-time-password across publishes
|
|
124
|
+
this.otpCache = { otp: this.conf.get('otp') };
|
|
125
|
+
this.conf.set('user-agent', this.userAgent, 'cli');
|
|
126
|
+
if (this.conf.get('registry') === 'https://registry.yarnpkg.com') {
|
|
127
|
+
this.logger.warn('', `Yarn's registry proxy is broken, replacing with public npm registry`);
|
|
128
|
+
this.logger.warn('', `If you don't have an npm token, you should exit and run "npm login"`);
|
|
129
|
+
this.conf.set('registry', 'https://registry.npmjs.org/', 'cli');
|
|
130
|
+
}
|
|
131
|
+
// inject --dist-tag into opts, if present
|
|
132
|
+
const distTag = this.getDistTag();
|
|
133
|
+
if (distTag) {
|
|
134
|
+
this.conf.set('tag', distTag.trim(), 'cli');
|
|
135
|
+
}
|
|
136
|
+
// a 'rooted leaf' is the regrettable pattern of adding '.' to the 'packages' config in lerna.json
|
|
137
|
+
this.hasRootedLeaf = this.packageGraph.has(this.project.manifest.name);
|
|
138
|
+
if (this.hasRootedLeaf) {
|
|
139
|
+
this.logger.info('publish', 'rooted leaf detected, skipping synthetic root lifecycles');
|
|
140
|
+
}
|
|
141
|
+
this.runPackageLifecycle = (0, core_1.createRunner)(this.options);
|
|
142
|
+
// don't execute recursively if run from a poorly-named script
|
|
143
|
+
this.runRootLifecycle = /^(pre|post)?publish$/.test(process.env.npm_lifecycle_event || '')
|
|
144
|
+
? (stage) => this.logger.warn('lifecycle', 'Skipping root %j because it has already been called', stage)
|
|
145
|
+
: (stage) => this.runPackageLifecycle(this.project.manifest, stage);
|
|
146
|
+
let chain = Promise.resolve();
|
|
147
|
+
if (this.options.bump === 'from-git') {
|
|
148
|
+
chain = chain.then(() => this.detectFromGit());
|
|
149
|
+
}
|
|
150
|
+
else if (this.options.bump === 'from-package') {
|
|
151
|
+
chain = chain.then(() => this.detectFromPackage());
|
|
152
|
+
}
|
|
153
|
+
else if (this.options.canary) {
|
|
154
|
+
chain = chain.then(() => this.detectCanaryVersions());
|
|
155
|
+
}
|
|
156
|
+
else {
|
|
157
|
+
chain = chain.then(() => new version_1.VersionCommand(this.argv));
|
|
158
|
+
}
|
|
159
|
+
return chain.then((result) => {
|
|
160
|
+
if (!result) {
|
|
161
|
+
// early return from nested VersionCommand
|
|
162
|
+
return false;
|
|
163
|
+
}
|
|
164
|
+
if (!result.updates.length) {
|
|
165
|
+
this.logger.success('No changed packages to publish');
|
|
166
|
+
// still exits zero, aka 'ok'
|
|
167
|
+
return false;
|
|
168
|
+
}
|
|
169
|
+
// (occasionally) redundant private filtering necessary to handle nested VersionCommand
|
|
170
|
+
this.updates = result.updates.filter((node) => !node.pkg.private);
|
|
171
|
+
this.updatesVersions = new Map(result.updatesVersions);
|
|
172
|
+
this.packagesToPublish = this.updates.map((node) => node.pkg);
|
|
173
|
+
if (this.options.contents) {
|
|
174
|
+
// globally override directory to publish
|
|
175
|
+
for (const pkg of this.packagesToPublish) {
|
|
176
|
+
pkg.contents = this.options.contents;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
if (result.needsConfirmation) {
|
|
180
|
+
// only confirm for --canary, bump === 'from-git',
|
|
181
|
+
// or bump === 'from-package', as VersionCommand
|
|
182
|
+
// has its own confirmation prompt
|
|
183
|
+
return this.confirmPublish();
|
|
184
|
+
}
|
|
185
|
+
return true;
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
async execute() {
|
|
189
|
+
var _a;
|
|
190
|
+
this.enableProgressBar();
|
|
191
|
+
this.logger.info('publish', 'Publishing packages to npm...');
|
|
192
|
+
await this.prepareRegistryActions();
|
|
193
|
+
await this.prepareLicenseActions();
|
|
194
|
+
if (this.options.canary) {
|
|
195
|
+
await this.updateCanaryVersions();
|
|
196
|
+
}
|
|
197
|
+
await this.resolveLocalDependencyLinks();
|
|
198
|
+
await this.resolveLocalDependencyWorkspaceProtocols();
|
|
199
|
+
if (this.options.removePackageFields) {
|
|
200
|
+
await this.removePackageProperties();
|
|
201
|
+
}
|
|
202
|
+
if (this.options.publishConfigOverrides !== false) {
|
|
203
|
+
await this.applyPublishConfigOverrides();
|
|
204
|
+
}
|
|
205
|
+
await this.annotateGitHead();
|
|
206
|
+
await this.serializeChanges();
|
|
207
|
+
await this.packUpdated();
|
|
208
|
+
await this.publishPacked();
|
|
209
|
+
if (this.gitReset) {
|
|
210
|
+
await this.resetChanges();
|
|
211
|
+
}
|
|
212
|
+
if (this.options.tempTag) {
|
|
213
|
+
await this.npmUpdateAsLatest();
|
|
214
|
+
}
|
|
215
|
+
const count = (_a = this.publishedPackages) === null || _a === void 0 ? void 0 : _a.length;
|
|
216
|
+
const publishedPackagesSorted = this.publishedPackages.sort((a, b) => a.name.localeCompare(b.name));
|
|
217
|
+
if (!count) {
|
|
218
|
+
this.logger.success('All packages have already been published.');
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
(0, core_1.logOutput)('Successfully published:');
|
|
222
|
+
if (this.options.summaryFile !== undefined) {
|
|
223
|
+
// create a json object and output it to a file location.
|
|
224
|
+
const filePath = this.options.summaryFile
|
|
225
|
+
? `${this.options.summaryFile}/lerna-publish-summary.json`
|
|
226
|
+
: './lerna-publish-summary.json';
|
|
227
|
+
const jsonObject = publishedPackagesSorted.map((pkg) => {
|
|
228
|
+
return {
|
|
229
|
+
packageName: pkg.name,
|
|
230
|
+
version: pkg.version,
|
|
231
|
+
};
|
|
232
|
+
});
|
|
233
|
+
(0, core_1.logOutput)(jsonObject);
|
|
234
|
+
try {
|
|
235
|
+
fs_extra_1.default.outputFileSync(filePath, JSON.stringify(jsonObject));
|
|
236
|
+
(0, core_1.logOutput)('Publish summary created: ', filePath);
|
|
237
|
+
}
|
|
238
|
+
catch (error) {
|
|
239
|
+
(0, core_1.logOutput)('Failed to create the summary report', error);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
else {
|
|
243
|
+
const message = publishedPackagesSorted.map((pkg) => ` - ${pkg.name}@${pkg.version}`);
|
|
244
|
+
(0, core_1.logOutput)(message.join(os_1.default.EOL));
|
|
245
|
+
}
|
|
246
|
+
// optionally cleanup temp packed files after publish, opt-in option
|
|
247
|
+
if (this.options.cleanupTempFiles) {
|
|
248
|
+
(0, glob_1.default)(path_1.default.join(temp_dir_1.default, '/lerna-*'), (_err, deleteFolders) => {
|
|
249
|
+
// delete silently all files/folders that startsWith "lerna-"
|
|
250
|
+
deleteFolders.forEach((folder) => fs_extra_1.default.removeSync(folder));
|
|
251
|
+
this.logger.verbose('publish', `Found ${deleteFolders.length} temp folders to cleanup after publish.`);
|
|
252
|
+
});
|
|
253
|
+
}
|
|
254
|
+
this.logger.success('published', '%d %s', count, count === 1 ? 'package' : 'packages');
|
|
255
|
+
}
|
|
256
|
+
verifyWorkingTreeClean() {
|
|
257
|
+
return (0, core_1.describeRef)(this.execOpts, undefined, this.options.dryRun).then(core_1.throwIfUncommitted);
|
|
258
|
+
}
|
|
259
|
+
detectFromGit() {
|
|
260
|
+
const matchingPattern = this.project.isIndependent() ? `*@*` : `${this.tagPrefix}*.*.*`;
|
|
261
|
+
let chain = Promise.resolve();
|
|
262
|
+
// attempting to publish a tagged release with local changes is not allowed
|
|
263
|
+
chain = chain.then(() => this.verifyWorkingTreeClean());
|
|
264
|
+
chain = chain.then(() => (0, get_current_tags_1.getCurrentTags)(this.execOpts, matchingPattern));
|
|
265
|
+
chain = chain.then((taggedPackageNames) => {
|
|
266
|
+
if (!taggedPackageNames.length) {
|
|
267
|
+
this.logger.notice('from-git', 'No tagged release found. You might not have fetched tags.');
|
|
268
|
+
return [];
|
|
269
|
+
}
|
|
270
|
+
if (this.project.isIndependent()) {
|
|
271
|
+
return taggedPackageNames.map((name) => this.packageGraph.get(name));
|
|
272
|
+
}
|
|
273
|
+
return (0, get_tagged_packages_1.getTaggedPackages)(this.packageGraph, this.project.rootPath, this.execOpts);
|
|
274
|
+
});
|
|
275
|
+
// private packages are never published, full stop.
|
|
276
|
+
chain = chain.then((updates) => updates.filter((node) => !node.pkg.private));
|
|
277
|
+
return chain.then((updates) => {
|
|
278
|
+
const updatesVersions = updates.map((node) => [node.name, node.version]);
|
|
279
|
+
return {
|
|
280
|
+
updates,
|
|
281
|
+
updatesVersions,
|
|
282
|
+
needsConfirmation: true,
|
|
283
|
+
};
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
detectFromPackage() {
|
|
287
|
+
let chain = Promise.resolve();
|
|
288
|
+
// attempting to publish a release with local changes is not allowed
|
|
289
|
+
chain = chain
|
|
290
|
+
.then(() => this.verifyWorkingTreeClean())
|
|
291
|
+
.catch((err) => {
|
|
292
|
+
// an execa error is thrown when git suffers a fatal error (such as no git repository present)
|
|
293
|
+
if (err.failed && /git describe/.test(err.command)) {
|
|
294
|
+
// (we tried)
|
|
295
|
+
this.logger.silly('EWORKINGTREE', err.message);
|
|
296
|
+
this.logger.notice('FYI', 'Unable to verify working tree, proceed at your own risk');
|
|
297
|
+
process.exitCode = 0;
|
|
298
|
+
}
|
|
299
|
+
else {
|
|
300
|
+
// validation errors should be preserved
|
|
301
|
+
throw err;
|
|
302
|
+
}
|
|
303
|
+
});
|
|
304
|
+
// private packages are already omitted by getUnpublishedPackages()
|
|
305
|
+
chain = chain.then(() => (0, get_unpublished_packages_1.getUnpublishedPackages)(this.packageGraph, this.conf.snapshot));
|
|
306
|
+
chain = chain.then((unpublished) => {
|
|
307
|
+
if (!unpublished.length) {
|
|
308
|
+
this.logger.notice('from-package', 'No unpublished release found');
|
|
309
|
+
}
|
|
310
|
+
return unpublished;
|
|
311
|
+
});
|
|
312
|
+
return chain.then((updates) => {
|
|
313
|
+
const updatesVersions = updates.map((node) => [node.name, node.version]);
|
|
314
|
+
return {
|
|
315
|
+
updates,
|
|
316
|
+
updatesVersions,
|
|
317
|
+
needsConfirmation: true,
|
|
318
|
+
};
|
|
319
|
+
});
|
|
320
|
+
}
|
|
321
|
+
detectCanaryVersions() {
|
|
322
|
+
const { cwd } = this.execOpts;
|
|
323
|
+
const { bump = 'prepatch', preid = 'alpha', ignoreChanges, forcePublish, includeMergedTags } = this.options;
|
|
324
|
+
// 'prerelease' and 'prepatch' are identical, for our purposes
|
|
325
|
+
const release = bump.startsWith('pre') ? bump.replace('release', 'patch') : `pre${bump}`;
|
|
326
|
+
let chain = Promise.resolve();
|
|
327
|
+
// attempting to publish a canary release with local changes is not allowed
|
|
328
|
+
chain = chain
|
|
329
|
+
.then(() => this.verifyWorkingTreeClean())
|
|
330
|
+
.catch((err) => {
|
|
331
|
+
// an execa error is thrown when git suffers a fatal error (such as no git repository present)
|
|
332
|
+
if (err.failed && /git describe/.test(err.command)) {
|
|
333
|
+
// (we tried)
|
|
334
|
+
this.logger.silly('EWORKINGTREE', err.message);
|
|
335
|
+
this.logger.notice('FYI', 'Unable to verify working tree, proceed at your own risk');
|
|
336
|
+
}
|
|
337
|
+
else {
|
|
338
|
+
// validation errors should be preserved
|
|
339
|
+
throw err;
|
|
340
|
+
}
|
|
341
|
+
});
|
|
342
|
+
const isIndependent = this.project.isIndependent();
|
|
343
|
+
// find changed packages since last release, if any
|
|
344
|
+
chain = chain.then(() => {
|
|
345
|
+
var _a, _b;
|
|
346
|
+
return (0, core_1.collectUpdates)((_b = (_a = this.packageGraph) === null || _a === void 0 ? void 0 : _a.rawPackageList) !== null && _b !== void 0 ? _b : [], this.packageGraph, this.execOpts, {
|
|
347
|
+
bump: 'prerelease',
|
|
348
|
+
canary: true,
|
|
349
|
+
ignoreChanges,
|
|
350
|
+
forcePublish,
|
|
351
|
+
includeMergedTags,
|
|
352
|
+
isIndependent,
|
|
353
|
+
// private packages are never published, don't bother describing their refs.
|
|
354
|
+
}, this.options.dryRun).filter((node) => !node.pkg.private);
|
|
355
|
+
});
|
|
356
|
+
// prettier-ignore
|
|
357
|
+
const makeVersion = (fallback) => ({ lastVersion = fallback, refCount, sha }) => {
|
|
358
|
+
// the next version is bumped without concern for preid or current index
|
|
359
|
+
// prettier-ignore
|
|
360
|
+
const nextVersion = semver_1.default.inc(lastVersion.replace(this.tagPrefix, ''), release.replace('pre', ''));
|
|
361
|
+
// semver.inc() starts a new prerelease at .0, git describe starts at .1
|
|
362
|
+
// and build metadata is always ignored when comparing dependency ranges
|
|
363
|
+
return `${nextVersion}-${preid}.${Math.max(0, refCount - 1)}+${sha}`;
|
|
364
|
+
};
|
|
365
|
+
if (isIndependent) {
|
|
366
|
+
// each package is described against its tags only
|
|
367
|
+
chain = chain.then((updates) => (0, p_map_1.default)(updates, (node) => (0, core_1.describeRef)({
|
|
368
|
+
match: `${node.name}@*`,
|
|
369
|
+
cwd,
|
|
370
|
+
}, includeMergedTags, this.options.dryRun)
|
|
371
|
+
// an unpublished package will have no reachable git tag
|
|
372
|
+
.then(makeVersion(node.version))
|
|
373
|
+
.then((version) => [node.name, version])).then((updatesVersions) => ({
|
|
374
|
+
updates,
|
|
375
|
+
updatesVersions,
|
|
376
|
+
})));
|
|
377
|
+
}
|
|
378
|
+
else {
|
|
379
|
+
// all packages are described against the last tag
|
|
380
|
+
chain = chain.then((updates) => (0, core_1.describeRef)({
|
|
381
|
+
match: `${this.tagPrefix}*.*.*`,
|
|
382
|
+
cwd,
|
|
383
|
+
}, includeMergedTags, this.options.dryRun)
|
|
384
|
+
// a repo with no tags should default to whatever lerna.json claims
|
|
385
|
+
.then(makeVersion(this.project.version))
|
|
386
|
+
.then((version) => updates.map((node) => [node.name, version]))
|
|
387
|
+
.then((updatesVersions) => ({
|
|
388
|
+
updates,
|
|
389
|
+
updatesVersions,
|
|
390
|
+
})));
|
|
391
|
+
}
|
|
392
|
+
return chain.then(({ updates, updatesVersions }) => ({
|
|
393
|
+
updates,
|
|
394
|
+
updatesVersions,
|
|
395
|
+
needsConfirmation: true,
|
|
396
|
+
}));
|
|
397
|
+
}
|
|
398
|
+
confirmPublish() {
|
|
399
|
+
var _a, _b, _c;
|
|
400
|
+
const count = (_a = this.packagesToPublish) === null || _a === void 0 ? void 0 : _a.length;
|
|
401
|
+
const message = (_c = (_b = this.packagesToPublish) === null || _b === void 0 ? void 0 : _b.map((pkg) => { var _a; return ` - ${pkg.name} => ${(_a = this.updatesVersions) === null || _a === void 0 ? void 0 : _a.get(pkg.name)}`; })) !== null && _c !== void 0 ? _c : [];
|
|
402
|
+
(0, core_1.logOutput)('');
|
|
403
|
+
(0, core_1.logOutput)(`Found ${count} ${count === 1 ? 'package' : 'packages'} to publish:`);
|
|
404
|
+
(0, core_1.logOutput)(message.join(os_1.default.EOL));
|
|
405
|
+
(0, core_1.logOutput)('');
|
|
406
|
+
if (this.options.yes) {
|
|
407
|
+
this.logger.info('auto-confirmed', '');
|
|
408
|
+
return true;
|
|
409
|
+
}
|
|
410
|
+
let confirmMessage = this.options.dryRun ? chalk_1.default.bgMagenta('[dry-run]') : '';
|
|
411
|
+
confirmMessage += ' Are you sure you want to publish these packages?';
|
|
412
|
+
return (0, core_1.promptConfirmation)(confirmMessage.trim());
|
|
413
|
+
}
|
|
414
|
+
prepareLicenseActions() {
|
|
415
|
+
return Promise.resolve()
|
|
416
|
+
.then(() => { var _a; return (0, get_packages_without_license_1.getPackagesWithoutLicense)(this.project, (_a = this.packagesToPublish) !== null && _a !== void 0 ? _a : []); })
|
|
417
|
+
.then((packagesWithoutLicense) => {
|
|
418
|
+
if (packagesWithoutLicense.length && !this.project.licensePath) {
|
|
419
|
+
this.packagesToBeLicensed = [];
|
|
420
|
+
const names = packagesWithoutLicense.map((pkg) => pkg.name);
|
|
421
|
+
const noun = names.length > 1 ? 'Packages' : 'Package';
|
|
422
|
+
const verb = names.length > 1 ? 'are' : 'is';
|
|
423
|
+
const list =
|
|
424
|
+
// prettier-ignore
|
|
425
|
+
names.length > 1
|
|
426
|
+
? `${names.slice(0, -1).join(', ')}${names.length > 2 ? ',' : ''} and ${names[names.length - 1] /* oxford commas _are_ that important */}`
|
|
427
|
+
: names[0];
|
|
428
|
+
this.logger.warn('ENOLICENSE', '%s %s %s missing a license.\n%s\n%s', noun, list, verb, 'One way to fix this is to add a LICENSE.md file to the root of this repository.', 'See https://choosealicense.com for additional guidance.');
|
|
429
|
+
}
|
|
430
|
+
else {
|
|
431
|
+
this.packagesToBeLicensed = packagesWithoutLicense;
|
|
432
|
+
}
|
|
433
|
+
});
|
|
434
|
+
}
|
|
435
|
+
prepareRegistryActions() {
|
|
436
|
+
let chain = Promise.resolve();
|
|
437
|
+
if (this.conf.get('registry') !== 'https://registry.npmjs.org/') {
|
|
438
|
+
this.logger.notice('', 'Skipping all user and access validation due to third-party registry');
|
|
439
|
+
this.logger.notice('', `Make sure you're authenticated properly "\\_(ツ)_ /"`);
|
|
440
|
+
return chain;
|
|
441
|
+
}
|
|
442
|
+
/* istanbul ignore if */
|
|
443
|
+
if (process.env.LERNA_INTEGRATION) {
|
|
444
|
+
return chain;
|
|
445
|
+
}
|
|
446
|
+
if (this.verifyAccess) {
|
|
447
|
+
// validate user has valid npm credentials first,
|
|
448
|
+
// by far the most common form of failed execution
|
|
449
|
+
chain = chain.then(() => (0, get_npm_username_1.getNpmUsername)(this.conf.snapshot));
|
|
450
|
+
chain = chain.then((username) => {
|
|
451
|
+
var _a;
|
|
452
|
+
// if no username was retrieved, don't bother validating
|
|
453
|
+
if (username) {
|
|
454
|
+
return (0, verify_npm_package_access_1.verifyNpmPackageAccess)((_a = this.packagesToPublish) !== null && _a !== void 0 ? _a : [], username, this.conf.snapshot);
|
|
455
|
+
}
|
|
456
|
+
});
|
|
457
|
+
// read profile metadata to determine if account-level 2FA is enabled
|
|
458
|
+
chain = chain.then(() => (0, get_two_factor_auth_required_1.getTwoFactorAuthRequired)(this.conf.snapshot));
|
|
459
|
+
chain = chain.then((isRequired) => {
|
|
460
|
+
// notably, this still doesn't handle package-level 2FA requirements
|
|
461
|
+
this.twoFactorAuthRequired = isRequired;
|
|
462
|
+
});
|
|
463
|
+
}
|
|
464
|
+
return chain;
|
|
465
|
+
}
|
|
466
|
+
updateCanaryVersions() {
|
|
467
|
+
return (0, p_map_1.default)(this.updates, (node) => {
|
|
468
|
+
var _a, _b, _c;
|
|
469
|
+
node.pkg.set('version', (_a = this.updatesVersions) === null || _a === void 0 ? void 0 : _a.get(node.name));
|
|
470
|
+
for (const [depName, resolved] of node.localDependencies) {
|
|
471
|
+
// other canary versions need to be updated, non-canary is a no-op
|
|
472
|
+
const depVersion = ((_b = this.updatesVersions) === null || _b === void 0 ? void 0 : _b.get(depName)) || ((_c = this.packageGraph) === null || _c === void 0 ? void 0 : _c.get(depName).pkg.version);
|
|
473
|
+
// it no longer matters if we mutate the shared Package instance
|
|
474
|
+
node.pkg.updateLocalDependency(resolved, depVersion, this.savePrefix, this.options.allowPeerDependenciesUpdate, this.options.workspaceStrictMatch, this.commandName);
|
|
475
|
+
}
|
|
476
|
+
// writing changes to disk handled in serializeChanges()
|
|
477
|
+
});
|
|
478
|
+
}
|
|
479
|
+
/**
|
|
480
|
+
* It is possible to override some fields in the manifest before the package is packed
|
|
481
|
+
* @see https://pnpm.io/package_json#publishconfig
|
|
482
|
+
* @returns
|
|
483
|
+
*/
|
|
484
|
+
applyPublishConfigOverrides() {
|
|
485
|
+
// potentially apply any packages that might have publishConfig overrides
|
|
486
|
+
return (0, p_map_1.default)(this.updates, (node) => (0, override_publish_config_1.overridePublishConfig)(node.pkg.manifest));
|
|
487
|
+
}
|
|
488
|
+
resolveLocalDependencyLinks() {
|
|
489
|
+
// resolve relative file: links to their actual version range
|
|
490
|
+
const updatesWithLocalLinks = this.updates.filter((node) => Array.from(node.localDependencies.values()).some((resolved) => resolved.type === 'directory'));
|
|
491
|
+
return (0, p_map_1.default)(updatesWithLocalLinks, (node) => {
|
|
492
|
+
var _a, _b;
|
|
493
|
+
for (const [depName, resolved] of node.localDependencies) {
|
|
494
|
+
// regardless of where the version comes from, we can't publish 'file:../sibling-pkg' specs
|
|
495
|
+
const depVersion = ((_a = this.updatesVersions) === null || _a === void 0 ? void 0 : _a.get(depName)) || ((_b = this.packageGraph) === null || _b === void 0 ? void 0 : _b.get(depName).pkg.version);
|
|
496
|
+
// it no longer matters if we mutate the shared Package instance
|
|
497
|
+
node.pkg.updateLocalDependency(resolved, depVersion, this.savePrefix, this.options.allowPeerDependenciesUpdate, this.options.workspaceStrictMatch, this.commandName);
|
|
498
|
+
}
|
|
499
|
+
// writing changes to disk handled in serializeChanges()
|
|
500
|
+
});
|
|
501
|
+
}
|
|
502
|
+
resolveLocalDependencyWorkspaceProtocols() {
|
|
503
|
+
// resolve workspace protocol: translates to their actual version target/range
|
|
504
|
+
const publishingPackagesWithLocalWorkspaces = this.updates.filter((node) => Array.from(node.localDependencies.values()).some((resolved) => resolved.workspaceSpec));
|
|
505
|
+
return (0, p_map_1.default)(publishingPackagesWithLocalWorkspaces, (node) => {
|
|
506
|
+
// regardless of where the version comes from, we can't publish 'workspace:*' specs, it has to be transformed for both local & external dependencies
|
|
507
|
+
// e.g. considering version is `1.2.3` and we have `workspace:*` it will be converted to "^1.2.3" or to "1.2.3" with strict match range enabled
|
|
508
|
+
var _a, _b;
|
|
509
|
+
// 1. update & bump version of local dependencies
|
|
510
|
+
for (const [depName, resolved] of node.localDependencies) {
|
|
511
|
+
const depVersion = ((_a = this.updatesVersions) === null || _a === void 0 ? void 0 : _a.get(depName)) || ((_b = this.packageGraph) === null || _b === void 0 ? void 0 : _b.get(depName).pkg.version);
|
|
512
|
+
// it no longer matters if we mutate the shared Package instance
|
|
513
|
+
node.pkg.updateLocalDependency(resolved, depVersion, this.savePrefix, this.options.allowPeerDependenciesUpdate, this.options.workspaceStrictMatch, this.commandName);
|
|
514
|
+
}
|
|
515
|
+
// 2. remove any "workspace:" prefix from the package to be published any of external dependencies (without anything being bumped)
|
|
516
|
+
// we will only accept "workspace:" with semver version, for example "workspace:1.2.3" is ok but "workspace:*" will log an error
|
|
517
|
+
for (const [_depName, resolved] of node.externalDependencies) {
|
|
518
|
+
node.pkg.removeDependencyWorkspaceProtocolPrefix(node.name, resolved);
|
|
519
|
+
}
|
|
520
|
+
// writing changes to disk handled in serializeChanges()
|
|
521
|
+
});
|
|
522
|
+
}
|
|
523
|
+
annotateGitHead() {
|
|
524
|
+
var _a;
|
|
525
|
+
try {
|
|
526
|
+
const gitHead = this.options.gitHead || (0, get_current_sha_1.getCurrentSHA)(this.execOpts);
|
|
527
|
+
for (const pkg of (_a = this.packagesToPublish) !== null && _a !== void 0 ? _a : []) {
|
|
528
|
+
// provide gitHead property that is normally added during npm publish
|
|
529
|
+
pkg.set('gitHead', gitHead);
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
catch (err) {
|
|
533
|
+
// from-package should be _able_ to run without git, but at least we tried
|
|
534
|
+
this.logger.silly('EGITHEAD', err.message);
|
|
535
|
+
this.logger.notice('FYI', 'Unable to set temporary gitHead property, it will be missing from registry metadata');
|
|
536
|
+
}
|
|
537
|
+
// writing changes to disk handled in serializeChanges()
|
|
538
|
+
}
|
|
539
|
+
serializeChanges() {
|
|
540
|
+
var _a;
|
|
541
|
+
return (0, p_map_1.default)((_a = this.packagesToPublish) !== null && _a !== void 0 ? _a : [], (pkg) => pkg.serialize());
|
|
542
|
+
}
|
|
543
|
+
resetChanges() {
|
|
544
|
+
// the package.json files are changed (by gitHead if not --canary)
|
|
545
|
+
// and we should always __attempt_ to leave the working tree clean
|
|
546
|
+
const { cwd } = this.execOpts;
|
|
547
|
+
const gitOpts = {
|
|
548
|
+
granularPathspec: this.options.granularPathspec !== false,
|
|
549
|
+
};
|
|
550
|
+
const dirtyManifests = [this.project.manifest]
|
|
551
|
+
.concat(this.packagesToPublish)
|
|
552
|
+
.map((pkg) => path_1.default.relative(cwd, pkg.manifestLocation));
|
|
553
|
+
return (0, git_checkout_1.gitCheckout)(dirtyManifests, gitOpts, this.execOpts, this.options.dryRun).catch((err) => {
|
|
554
|
+
this.logger.silly('EGITCHECKOUT', err.message);
|
|
555
|
+
this.logger.notice('FYI', `Unable to reset working tree changes, this probably isn't a git repo.`);
|
|
556
|
+
});
|
|
557
|
+
}
|
|
558
|
+
// @deprecated, see Lerna PR https://github.com/lerna/lerna/pull/1862/files
|
|
559
|
+
execScript(pkg, script) {
|
|
560
|
+
const scriptLocation = path_1.default.join(pkg.location, 'scripts', script);
|
|
561
|
+
try {
|
|
562
|
+
require(scriptLocation);
|
|
563
|
+
}
|
|
564
|
+
catch (ex) {
|
|
565
|
+
this.logger.silly('execScript', `No ${script} script found at ${scriptLocation}`);
|
|
566
|
+
}
|
|
567
|
+
return pkg;
|
|
568
|
+
}
|
|
569
|
+
removePackageProperties() {
|
|
570
|
+
const { removePackageFields } = this.options;
|
|
571
|
+
return (0, p_map_1.default)(this.updates, (node) => {
|
|
572
|
+
if (Array.isArray(removePackageFields)) {
|
|
573
|
+
for (const removeField of removePackageFields) {
|
|
574
|
+
(0, core_1.deleteComplexObjectProp)(node.pkg.manifest, removeField, `"${node.pkg.name}" package`);
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
});
|
|
578
|
+
}
|
|
579
|
+
removeTempLicensesOnError(error) {
|
|
580
|
+
return Promise.resolve()
|
|
581
|
+
.then(() => {
|
|
582
|
+
var _a;
|
|
583
|
+
return (0, remove_temp_licenses_1.removeTempLicenses)((_a = this.packagesToBeLicensed) !== null && _a !== void 0 ? _a : []).catch((removeError) => {
|
|
584
|
+
this.logger.error('licenses', 'error removing temporary license files', removeError.stack || removeError);
|
|
585
|
+
});
|
|
586
|
+
})
|
|
587
|
+
.then(() => {
|
|
588
|
+
// restore original error into promise chain
|
|
589
|
+
throw error;
|
|
590
|
+
});
|
|
591
|
+
}
|
|
592
|
+
requestOneTimePassword() {
|
|
593
|
+
if (this.options.dryRun) {
|
|
594
|
+
this.logger.info(chalk_1.default.bold.magenta('[dry-run] >'), 'will ask OTP');
|
|
595
|
+
return;
|
|
596
|
+
}
|
|
597
|
+
// if OTP has already been provided, skip prompt
|
|
598
|
+
if (this.otpCache.otp) {
|
|
599
|
+
return;
|
|
600
|
+
}
|
|
601
|
+
return Promise.resolve()
|
|
602
|
+
.then(() => (0, version_1.getOneTimePassword)('Enter OTP:'))
|
|
603
|
+
.then((otp) => (this.otpCache.otp = otp));
|
|
604
|
+
}
|
|
605
|
+
topoMapPackages(mapper) {
|
|
606
|
+
return (0, core_1.runTopologically)(this.packagesToPublish, mapper, {
|
|
607
|
+
concurrency: this.concurrency,
|
|
608
|
+
rejectCycles: this.options.rejectCycles,
|
|
609
|
+
/**
|
|
610
|
+
* Previously `publish` had unique default behavior for graph creation vs other commands: it would only consider dependencies when finding
|
|
611
|
+
* edges by default (i.e. relationships between packages specified via devDependencies would be ignored). It was documented to be the case
|
|
612
|
+
* in order to try and reduce the chance of dependency cycles.
|
|
613
|
+
*
|
|
614
|
+
* We are removing this behavior altogether in v6 because we do not want to have different ways of constructing the graph,
|
|
615
|
+
* only different ways of utilizing it (e.g. --no-sort vs topological sort).
|
|
616
|
+
*
|
|
617
|
+
* Therefore until we remove graphType altogether in v6, we provide a way for users to opt into the old default behavior
|
|
618
|
+
* by setting the `graphType` option to `dependencies`.
|
|
619
|
+
*/
|
|
620
|
+
// prettier-ignore
|
|
621
|
+
graphType: this.options.graphType === 'dependencies'
|
|
622
|
+
? 'dependencies'
|
|
623
|
+
: this.options.allowPeerDependenciesUpdate
|
|
624
|
+
? 'allPlusPeerDependencies'
|
|
625
|
+
: 'allDependencies',
|
|
626
|
+
});
|
|
627
|
+
}
|
|
628
|
+
packUpdated() {
|
|
629
|
+
var _a;
|
|
630
|
+
const tracker = this.logger.newItem('npm pack');
|
|
631
|
+
tracker.addWork((_a = this.packagesToPublish) === null || _a === void 0 ? void 0 : _a.length);
|
|
632
|
+
let chain = Promise.resolve();
|
|
633
|
+
chain = chain.then(() => { var _a; return (0, create_temp_licenses_1.createTempLicenses)(this.project.licensePath, (_a = this.packagesToBeLicensed) !== null && _a !== void 0 ? _a : []); });
|
|
634
|
+
if (!this.hasRootedLeaf) {
|
|
635
|
+
// despite being deprecated for years...
|
|
636
|
+
chain = chain.then(() => this.runRootLifecycle('prepublish'));
|
|
637
|
+
// these lifecycles _should_ never be employed to run `lerna publish`...
|
|
638
|
+
chain = chain.then(() => this.runPackageLifecycle(this.project.manifest, 'prepare'));
|
|
639
|
+
chain = chain.then(() => this.runPackageLifecycle(this.project.manifest, 'prepublishOnly'));
|
|
640
|
+
chain = chain.then(() => this.runPackageLifecycle(this.project.manifest, 'prepack'));
|
|
641
|
+
}
|
|
642
|
+
const opts = this.conf.snapshot;
|
|
643
|
+
const mapper = (0, p_pipe_1.default)(...[
|
|
644
|
+
this.options.requireScripts && ((pkg) => this.execScript(pkg, 'prepublish')),
|
|
645
|
+
(pkg) => (0, core_1.pulseTillDone)((0, pack_directory_1.packDirectory)(pkg, pkg.location, opts)).then((packed) => {
|
|
646
|
+
var _a;
|
|
647
|
+
tracker.verbose('packed', path_1.default.relative((_a = this.project.rootPath) !== null && _a !== void 0 ? _a : '', pkg.contents));
|
|
648
|
+
tracker.completeWork(1);
|
|
649
|
+
// store metadata for use in this.publishPacked()
|
|
650
|
+
pkg.packed = packed;
|
|
651
|
+
// manifest may be mutated by any previous lifecycle
|
|
652
|
+
return pkg.refresh();
|
|
653
|
+
}),
|
|
654
|
+
].filter(Boolean));
|
|
655
|
+
chain = chain.then(() => {
|
|
656
|
+
if (this.toposort) {
|
|
657
|
+
return this.topoMapPackages(mapper);
|
|
658
|
+
}
|
|
659
|
+
return (0, p_map_1.default)(this.packagesToPublish, mapper, { concurrency: this.concurrency });
|
|
660
|
+
});
|
|
661
|
+
chain = chain.then(() => { var _a; return (0, remove_temp_licenses_1.removeTempLicenses)((_a = this.packagesToBeLicensed) !== null && _a !== void 0 ? _a : []); });
|
|
662
|
+
// remove temporary license files if _any_ error occurs _anywhere_ in the promise chain
|
|
663
|
+
chain = chain.catch((error) => this.removeTempLicensesOnError(error));
|
|
664
|
+
if (!this.hasRootedLeaf) {
|
|
665
|
+
chain = chain.then(() => this.runPackageLifecycle(this.project.manifest, 'postpack'));
|
|
666
|
+
}
|
|
667
|
+
return chain.finally(() => tracker.finish());
|
|
668
|
+
}
|
|
669
|
+
publishPacked() {
|
|
670
|
+
var _a;
|
|
671
|
+
this.publishedPackages = [];
|
|
672
|
+
const tracker = this.logger.newItem('publish');
|
|
673
|
+
tracker.addWork((_a = this.packagesToPublish) === null || _a === void 0 ? void 0 : _a.length);
|
|
674
|
+
let chain = Promise.resolve();
|
|
675
|
+
// if account-level 2FA is enabled, prime the OTP cache
|
|
676
|
+
if (this.twoFactorAuthRequired) {
|
|
677
|
+
chain = chain.then(() => this.requestOneTimePassword());
|
|
678
|
+
}
|
|
679
|
+
const opts = Object.assign(this.conf.snapshot, {
|
|
680
|
+
// distTag defaults to 'latest' OR whatever is in pkg.publishConfig.tag
|
|
681
|
+
// if we skip temp tags we should tag with the proper value immediately
|
|
682
|
+
tag: this.options.tempTag ? 'lerna-temp' : this.conf.get('tag'),
|
|
683
|
+
'git-dry-run': this.options.dryRun || false,
|
|
684
|
+
});
|
|
685
|
+
const mapper = (0, p_pipe_1.default)(...[
|
|
686
|
+
(pkg) => {
|
|
687
|
+
const preDistTag = this.getPreDistTag(pkg);
|
|
688
|
+
const tag = !this.options.tempTag && preDistTag ? preDistTag : opts.tag;
|
|
689
|
+
const pkgOpts = Object.assign({}, opts, { tag });
|
|
690
|
+
return (0, core_1.pulseTillDone)((0, npm_publish_1.npmPublish)(pkg, pkg.packed.tarFilePath, pkgOpts, this.otpCache))
|
|
691
|
+
.then(() => {
|
|
692
|
+
this.publishedPackages.push(pkg);
|
|
693
|
+
tracker.success('published', pkg.name, pkg.version);
|
|
694
|
+
tracker.completeWork(1);
|
|
695
|
+
(0, log_packed_1.logPacked)(pkg, this.options.dryRun);
|
|
696
|
+
return pkg;
|
|
697
|
+
})
|
|
698
|
+
.catch((err) => {
|
|
699
|
+
if (err.code === 'EPUBLISHCONFLICT') {
|
|
700
|
+
tracker.warn('publish', `Package is already published: ${pkg.name}@${pkg.version}`);
|
|
701
|
+
tracker.completeWork(1);
|
|
702
|
+
return pkg;
|
|
703
|
+
}
|
|
704
|
+
this.logger.silly('', err);
|
|
705
|
+
this.logger.error(err.code, (err.body && err.body.error) || err.message);
|
|
706
|
+
// avoid dumping logs, this isn't a lerna problem
|
|
707
|
+
err.name = 'ValidationError';
|
|
708
|
+
// ensure process exits non-zero
|
|
709
|
+
process.exitCode = 'errno' in err ? err.errno : 1;
|
|
710
|
+
throw err;
|
|
711
|
+
});
|
|
712
|
+
},
|
|
713
|
+
this.options.requireScripts && ((pkg) => this.execScript(pkg, 'postpublish')),
|
|
714
|
+
].filter(Boolean));
|
|
715
|
+
chain = chain.then(() => {
|
|
716
|
+
if (this.toposort) {
|
|
717
|
+
return this.topoMapPackages(mapper);
|
|
718
|
+
}
|
|
719
|
+
return (0, p_map_1.default)(this.packagesToPublish, mapper, { concurrency: this.concurrency });
|
|
720
|
+
});
|
|
721
|
+
if (!this.hasRootedLeaf) {
|
|
722
|
+
// cyclical 'publish' lifecycles are automatically skipped
|
|
723
|
+
chain = chain.then(() => this.runRootLifecycle('publish'));
|
|
724
|
+
chain = chain.then(() => this.runRootLifecycle('postpublish'));
|
|
725
|
+
}
|
|
726
|
+
return chain.finally(() => tracker.finish());
|
|
727
|
+
}
|
|
728
|
+
npmUpdateAsLatest() {
|
|
729
|
+
var _a;
|
|
730
|
+
const tracker = this.logger.newItem('npmUpdateAsLatest');
|
|
731
|
+
tracker.addWork((_a = this.packagesToPublish) === null || _a === void 0 ? void 0 : _a.length);
|
|
732
|
+
tracker.showProgress();
|
|
733
|
+
let chain = Promise.resolve();
|
|
734
|
+
const opts = this.conf.snapshot;
|
|
735
|
+
const getDistTag = (publishConfig) => {
|
|
736
|
+
if (opts.tag === 'latest' && (publishConfig === null || publishConfig === void 0 ? void 0 : publishConfig.tag)) {
|
|
737
|
+
return publishConfig.tag;
|
|
738
|
+
}
|
|
739
|
+
return opts.tag;
|
|
740
|
+
};
|
|
741
|
+
const mapper = (pkg) => {
|
|
742
|
+
const spec = `${pkg.name}@${pkg.version}`;
|
|
743
|
+
const preDistTag = this.getPreDistTag(pkg);
|
|
744
|
+
const distTag = preDistTag || getDistTag(pkg.get('publishConfig'));
|
|
745
|
+
return Promise.resolve()
|
|
746
|
+
.then(() => (0, core_1.pulseTillDone)((0, npm_dist_tag_1.remove)(spec, 'lerna-temp', opts, this.otpCache)))
|
|
747
|
+
.then(() => (0, core_1.pulseTillDone)((0, npm_dist_tag_1.add)(spec, distTag, opts, this.otpCache)))
|
|
748
|
+
.then(() => {
|
|
749
|
+
tracker.success('dist-tag', '%s@%s => %j', pkg.name, pkg.version, distTag);
|
|
750
|
+
tracker.completeWork(1);
|
|
751
|
+
return pkg;
|
|
752
|
+
});
|
|
753
|
+
};
|
|
754
|
+
chain = chain.then(() => {
|
|
755
|
+
if (this.toposort) {
|
|
756
|
+
return this.topoMapPackages(mapper);
|
|
757
|
+
}
|
|
758
|
+
return (0, p_map_1.default)(this.packagesToPublish, mapper, { concurrency: this.concurrency });
|
|
759
|
+
});
|
|
760
|
+
return chain.finally(() => tracker.finish());
|
|
761
|
+
}
|
|
762
|
+
getDistTag() {
|
|
763
|
+
if (this.options.distTag) {
|
|
764
|
+
return this.options.distTag;
|
|
765
|
+
}
|
|
766
|
+
if (this.options.canary) {
|
|
767
|
+
return 'canary';
|
|
768
|
+
}
|
|
769
|
+
// undefined defaults to 'latest' OR whatever is in pkg.publishConfig.tag
|
|
770
|
+
}
|
|
771
|
+
getPreDistTag(pkg) {
|
|
772
|
+
if (!this.options.preDistTag) {
|
|
773
|
+
return;
|
|
774
|
+
}
|
|
775
|
+
const isPrerelease = (0, core_1.prereleaseIdFromVersion)(pkg.version);
|
|
776
|
+
if (isPrerelease) {
|
|
777
|
+
return this.options.preDistTag;
|
|
778
|
+
}
|
|
779
|
+
}
|
|
780
|
+
}
|
|
781
|
+
exports.PublishCommand = PublishCommand;
|
|
782
782
|
//# sourceMappingURL=publish-command.js.map
|