@lerna-lite/publish 0.3.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.
Files changed (69) hide show
  1. package/LICENSE +20 -0
  2. package/README.md +415 -0
  3. package/dist/index.d.ts +2 -0
  4. package/dist/index.js +15 -0
  5. package/dist/index.js.map +1 -0
  6. package/dist/lib/create-temp-licenses.d.ts +7 -0
  7. package/dist/lib/create-temp-licenses.js +33 -0
  8. package/dist/lib/create-temp-licenses.js.map +1 -0
  9. package/dist/lib/fetch-config.d.ts +7 -0
  10. package/dist/lib/fetch-config.js +22 -0
  11. package/dist/lib/fetch-config.js.map +1 -0
  12. package/dist/lib/get-current-sha.d.ts +6 -0
  13. package/dist/lib/get-current-sha.js +20 -0
  14. package/dist/lib/get-current-sha.js.map +1 -0
  15. package/dist/lib/get-current-tags.d.ts +8 -0
  16. package/dist/lib/get-current-tags.js +36 -0
  17. package/dist/lib/get-current-tags.js.map +1 -0
  18. package/dist/lib/get-npm-username.d.ts +7 -0
  19. package/dist/lib/get-npm-username.js +50 -0
  20. package/dist/lib/get-npm-username.js.map +1 -0
  21. package/dist/lib/get-packages-without-license.d.ts +8 -0
  22. package/dist/lib/get-packages-without-license.js +23 -0
  23. package/dist/lib/get-packages-without-license.js.map +1 -0
  24. package/dist/lib/get-packed.d.ts +2 -0
  25. package/dist/lib/get-packed.js +66 -0
  26. package/dist/lib/get-packed.js.map +1 -0
  27. package/dist/lib/get-profile-data.d.ts +7 -0
  28. package/dist/lib/get-profile-data.js +23 -0
  29. package/dist/lib/get-profile-data.js.map +1 -0
  30. package/dist/lib/get-tagged-packages.d.ts +8 -0
  31. package/dist/lib/get-tagged-packages.js +30 -0
  32. package/dist/lib/get-tagged-packages.js.map +1 -0
  33. package/dist/lib/get-two-factor-auth-required.d.ts +7 -0
  34. package/dist/lib/get-two-factor-auth-required.js +43 -0
  35. package/dist/lib/get-two-factor-auth-required.js.map +1 -0
  36. package/dist/lib/get-unpublished-packages.d.ts +7 -0
  37. package/dist/lib/get-unpublished-packages.js +34 -0
  38. package/dist/lib/get-unpublished-packages.js.map +1 -0
  39. package/dist/lib/get-whoami.d.ts +11 -0
  40. package/dist/lib/get-whoami.js +21 -0
  41. package/dist/lib/get-whoami.js.map +1 -0
  42. package/dist/lib/git-checkout.d.ts +7 -0
  43. package/dist/lib/git-checkout.js +21 -0
  44. package/dist/lib/git-checkout.js.map +1 -0
  45. package/dist/lib/index.d.ts +19 -0
  46. package/dist/lib/index.js +32 -0
  47. package/dist/lib/index.js.map +1 -0
  48. package/dist/lib/log-packed.d.ts +1 -0
  49. package/dist/lib/log-packed.js +68 -0
  50. package/dist/lib/log-packed.js.map +1 -0
  51. package/dist/lib/npm-dist-tag.d.ts +30 -0
  52. package/dist/lib/npm-dist-tag.js +142 -0
  53. package/dist/lib/npm-dist-tag.js.map +1 -0
  54. package/dist/lib/npm-publish.d.ts +11 -0
  55. package/dist/lib/npm-publish.js +116 -0
  56. package/dist/lib/npm-publish.js.map +1 -0
  57. package/dist/lib/pack-directory.d.ts +8 -0
  58. package/dist/lib/pack-directory.js +68 -0
  59. package/dist/lib/pack-directory.js.map +1 -0
  60. package/dist/lib/remove-temp-licenses.d.ts +6 -0
  61. package/dist/lib/remove-temp-licenses.js +20 -0
  62. package/dist/lib/remove-temp-licenses.js.map +1 -0
  63. package/dist/lib/verify-npm-package-access.d.ts +9 -0
  64. package/dist/lib/verify-npm-package-access.js +56 -0
  65. package/dist/lib/verify-npm-package-access.js.map +1 -0
  66. package/dist/publishCommand.d.ts +59 -0
  67. package/dist/publishCommand.js +628 -0
  68. package/dist/publishCommand.js.map +1 -0
  69. package/package.json +82 -0
@@ -0,0 +1,628 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.PublishCommand = void 0;
7
+ const os_1 = __importDefault(require("os"));
8
+ const path_1 = __importDefault(require("path"));
9
+ const crypto_1 = __importDefault(require("crypto"));
10
+ const p_map_1 = __importDefault(require("p-map"));
11
+ const p_pipe_1 = __importDefault(require("p-pipe"));
12
+ const semver_1 = __importDefault(require("semver"));
13
+ const version_1 = require("@lerna-lite/version");
14
+ const core_1 = require("@lerna-lite/core");
15
+ const get_current_tags_1 = require("./lib/get-current-tags");
16
+ const get_tagged_packages_1 = require("./lib/get-tagged-packages");
17
+ const get_unpublished_packages_1 = require("./lib/get-unpublished-packages");
18
+ const get_npm_username_1 = require("./lib/get-npm-username");
19
+ const verify_npm_package_access_1 = require("./lib/verify-npm-package-access");
20
+ const get_two_factor_auth_required_1 = require("./lib/get-two-factor-auth-required");
21
+ const get_current_sha_1 = require("./lib/get-current-sha");
22
+ const git_checkout_1 = require("./lib/git-checkout");
23
+ const pack_directory_1 = require("./lib/pack-directory");
24
+ const npm_publish_1 = require("./lib/npm-publish");
25
+ const log_packed_1 = require("./lib/log-packed");
26
+ const npm_dist_tag_1 = require("./lib/npm-dist-tag");
27
+ const remove_temp_licenses_1 = require("./lib/remove-temp-licenses");
28
+ const create_temp_licenses_1 = require("./lib/create-temp-licenses");
29
+ const get_packages_without_license_1 = require("./lib/get-packages-without-license");
30
+ class PublishCommand extends core_1.Command {
31
+ constructor() {
32
+ super(...arguments);
33
+ /** command name */
34
+ this.name = 'publish';
35
+ this.gitReset = false;
36
+ this.savePrefix = '';
37
+ this.tagPrefix = '';
38
+ this.hasRootedLeaf = false;
39
+ this.npmSession = '';
40
+ this.packagesToPublish = [];
41
+ this.packagesToBeLicensed = [];
42
+ this.verifyAccess = false;
43
+ this.twoFactorAuthRequired = false;
44
+ this.updates = [];
45
+ }
46
+ get otherCommandConfigs() {
47
+ // back-compat
48
+ return ['version'];
49
+ }
50
+ get requiresGit() {
51
+ // `ws-roller publish from-package` doesn't _need_ git, per se
52
+ return this.options.bump !== 'from-package';
53
+ }
54
+ configureProperties() {
55
+ super.configureProperties();
56
+ // Defaults are necessary here because yargs defaults
57
+ // override durable options provided by a config file
58
+ const {
59
+ // prettier-ignore
60
+ exact, gitHead, gitReset, tagVersionPrefix = 'v', verifyAccess, } = this.options;
61
+ if (this.requiresGit && gitHead) {
62
+ throw new core_1.ValidationError('EGITHEAD', '--git-head is only allowed with "from - package" positional');
63
+ }
64
+ // https://docs.npmjs.com/misc/config#save-prefix
65
+ this.savePrefix = exact ? '' : '^';
66
+ // https://docs.npmjs.com/misc/config#tag-version-prefix
67
+ this.tagPrefix = tagVersionPrefix;
68
+ // TODO: properly inherit from npm-conf
69
+ // inverted boolean options are only respected if prefixed with `--no-`, e.g. `--no-verify-access`
70
+ this.gitReset = gitReset !== false;
71
+ this.verifyAccess = verifyAccess !== false;
72
+ // consumed by npm-registry-fetch (via libnpmpublish)
73
+ this.npmSession = crypto_1.default.randomBytes(8).toString('hex');
74
+ }
75
+ get userAgent() {
76
+ // consumed by npm-registry-fetch (via libnpmpublish)
77
+ return `lerna/${this.options.libVersion}/node@${process.version}+${process.arch} (${process.platform})`;
78
+ }
79
+ async initialize() {
80
+ var _a, _b, _c;
81
+ if (this.options.canary) {
82
+ this.logger.info('canary', 'enabled');
83
+ }
84
+ if (this.options.requireScripts) {
85
+ this.logger.info('require-scripts', 'enabled');
86
+ }
87
+ // npmSession and user-agent are consumed by npm-registry-fetch (via libnpmpublish)
88
+ this.logger.verbose('session', this.npmSession);
89
+ this.logger.verbose('user-agent', this.userAgent);
90
+ this.conf = (0, core_1.npmConf)({
91
+ lernaCommand: 'publish',
92
+ _auth: this.options.legacyAuth,
93
+ npmSession: this.npmSession,
94
+ npmVersion: this.userAgent,
95
+ otp: this.options.otp,
96
+ registry: this.options.registry,
97
+ 'ignore-prepublish': this.options.ignorePrepublish,
98
+ 'ignore-scripts': this.options.ignoreScripts,
99
+ });
100
+ // cache to hold a one-time-password across publishes
101
+ this.otpCache = { otp: this.conf.get('otp') };
102
+ this.conf.set('user-agent', this.userAgent, 'cli');
103
+ if (this.conf.get('registry') === 'https://registry.yarnpkg.com') {
104
+ this.logger.warn('', `Yarn's registry proxy is broken, replacing with public npm registry`);
105
+ this.logger.warn('', `If you don't have an npm token, you should exit and run "npm login"`);
106
+ this.conf.set('registry', 'https://registry.npmjs.org/', 'cli');
107
+ }
108
+ // inject --dist-tag into opts, if present
109
+ const distTag = this.getDistTag();
110
+ if (distTag) {
111
+ this.conf.set('tag', distTag.trim(), 'cli');
112
+ }
113
+ // a 'rooted leaf' is the regrettable pattern of adding '.' to the 'packages' config in lerna.json
114
+ this.hasRootedLeaf = (_c = (_a = this.packageGraph) === null || _a === void 0 ? void 0 : _a.has((_b = this.project) === null || _b === void 0 ? void 0 : _b.manifest.name)) !== null && _c !== void 0 ? _c : false;
115
+ if (this.hasRootedLeaf) {
116
+ this.logger.info('publish', 'rooted leaf detected, skipping synthetic root lifecycles');
117
+ }
118
+ this.runPackageLifecycle = (0, core_1.createRunner)(this.options);
119
+ // don't execute recursively if run from a poorly-named script
120
+ this.runRootLifecycle = /^(pre|post)?publish$/.test(process.env.npm_lifecycle_event || '')
121
+ ? (stage) => this.logger.warn('lifecycle', 'Skipping root %j because it has already been called', stage)
122
+ : (stage) => { var _a; return this.runPackageLifecycle((_a = this.project) === null || _a === void 0 ? void 0 : _a.manifest, stage); };
123
+ let promiseResult;
124
+ if (this.options.bump === 'from-git') {
125
+ promiseResult = await this.detectFromGit();
126
+ }
127
+ else if (this.options.bump === 'from-package') {
128
+ promiseResult = await this.detectFromPackage();
129
+ }
130
+ else if (this.options.canary) {
131
+ promiseResult = await this.detectCanaryVersions();
132
+ }
133
+ else {
134
+ promiseResult = new version_1.VersionCommand(this.argv);
135
+ }
136
+ if (!promiseResult) {
137
+ // early return from nested VersionCommand
138
+ return false;
139
+ }
140
+ if (!promiseResult.updates.length) {
141
+ this.logger.success('No changed packages to publish');
142
+ // still exits zero, aka 'ok'
143
+ return false;
144
+ }
145
+ // (occasionally) redundant private filtering necessary to handle nested VersionCommand
146
+ this.updates = promiseResult.updates.filter((node) => !node.pkg.private);
147
+ this.updatesVersions = new Map(promiseResult.updatesVersions);
148
+ this.packagesToPublish = this.updates.map((node) => node.pkg);
149
+ if (this.options.contents) {
150
+ // globally override directory to publish
151
+ for (const pkg of this.packagesToPublish) {
152
+ pkg.contents = this.options.contents;
153
+ }
154
+ }
155
+ if (promiseResult.needsConfirmation) {
156
+ // only confirm for --canary, bump === 'from-git',
157
+ // or bump === 'from-package', as VersionCommand
158
+ // has its own confirmation prompt
159
+ return this.confirmPublish();
160
+ }
161
+ return true;
162
+ }
163
+ async execute() {
164
+ var _a, _b, _c;
165
+ this.enableProgressBar();
166
+ this.logger.info('publish', 'Publishing packages to npm...');
167
+ await this.prepareRegistryActions();
168
+ await this.prepareLicenseActions();
169
+ if (this.options.canary) {
170
+ await this.updateCanaryVersions();
171
+ }
172
+ await this.resolveLocalDependencyLinks();
173
+ await this.annotateGitHead();
174
+ await this.serializeChanges();
175
+ await this.packUpdated();
176
+ await this.publishPacked();
177
+ if (this.gitReset) {
178
+ await this.resetChanges();
179
+ }
180
+ if (this.options.tempTag) {
181
+ await this.npmUpdateAsLatest();
182
+ }
183
+ const count = (_a = this.packagesToPublish) === null || _a === void 0 ? void 0 : _a.length;
184
+ const message = (_c = (_b = this.packagesToPublish) === null || _b === void 0 ? void 0 : _b.map((pkg) => ` - ${pkg.name}@${pkg.version}`)) !== null && _c !== void 0 ? _c : [];
185
+ this.logOutput('Successfully published:');
186
+ this.logOutput(message.join(os_1.default.EOL));
187
+ this.logger.success('published', '%d %s', count, count === 1 ? 'package' : 'packages');
188
+ }
189
+ verifyWorkingTreeClean() {
190
+ return (0, core_1.describeRef)(this.execOpts, undefined, this.options.gitDryRun).then(core_1.throwIfUncommitted);
191
+ }
192
+ async detectFromGit() {
193
+ var _a, _b, _c;
194
+ try {
195
+ const matchingPattern = ((_a = this.project) === null || _a === void 0 ? void 0 : _a.isIndependent()) ? '*@*' : `${this.tagPrefix}*.*.*`;
196
+ // attempting to publish a tagged release with local changes is not allowed
197
+ await this.verifyWorkingTreeClean();
198
+ const taggedPackageNames = await (0, get_current_tags_1.getCurrentTags)(this.execOpts, matchingPattern, this.options.gitDryRun);
199
+ if (!taggedPackageNames.length) {
200
+ this.logger.notice('from-git', 'No tagged release found. You might not have fetched tags.');
201
+ return [];
202
+ }
203
+ if ((_b = this.project) === null || _b === void 0 ? void 0 : _b.isIndependent()) {
204
+ return taggedPackageNames.map((name) => { var _a; return (_a = this.packageGraph) === null || _a === void 0 ? void 0 : _a.get(name); });
205
+ }
206
+ const updates = await (0, get_tagged_packages_1.getTaggedPackages)(this.packageGraph, (_c = this.project) === null || _c === void 0 ? void 0 : _c.rootPath, this.execOpts, this.options.gitDryRun);
207
+ // private packages are never published, full stop.
208
+ updates.filter((node) => !node.pkg.private);
209
+ const updatesVersions = updates.map((node) => [node.name, node.version]);
210
+ return {
211
+ updates,
212
+ updatesVersions,
213
+ needsConfirmation: true,
214
+ };
215
+ }
216
+ catch (err) {
217
+ // an execa error is thrown when git suffers a fatal error (such as no git repository present)
218
+ if (err.failed && /git describe/.test(err.command)) {
219
+ // (we tried)
220
+ this.logger.silly('EWORKINGTREE', err.message);
221
+ this.logger.notice('FYI', 'Unable to verify working tree, proceed at your own risk');
222
+ }
223
+ else {
224
+ // validation errors should be preserved
225
+ throw err;
226
+ }
227
+ }
228
+ }
229
+ async detectFromPackage() {
230
+ try {
231
+ // attempting to publish a release with local changes is not allowed
232
+ await this.verifyWorkingTreeClean();
233
+ }
234
+ catch (err) {
235
+ // an execa error is thrown when git suffers a fatal error (such as no git repository present)
236
+ if (err.failed && /git describe/.test(err.command)) {
237
+ // (we tried)
238
+ this.logger.silly('EWORKINGTREE', err.message);
239
+ this.logger.notice('FYI', 'Unable to verify working tree, proceed at your own risk');
240
+ }
241
+ else {
242
+ // validation errors should be preserved
243
+ throw err;
244
+ }
245
+ }
246
+ // private packages are already omitted by getUnpublishedPackages()
247
+ const unpublishedUpdates = await (0, get_unpublished_packages_1.getUnpublishedPackages)(this.packageGraph, this.conf.snapshot);
248
+ if (!unpublishedUpdates.length) {
249
+ this.logger.notice('from-package', 'No unpublished release found');
250
+ }
251
+ const updatesVersions = unpublishedUpdates.map((node) => [node.name, node.version]);
252
+ return {
253
+ updates: unpublishedUpdates,
254
+ updatesVersions,
255
+ needsConfirmation: true,
256
+ };
257
+ }
258
+ detectCanaryVersions() {
259
+ var _a;
260
+ const { cwd } = this.execOpts;
261
+ const { bump = 'prepatch', preid = 'alpha', ignoreChanges, forcePublish, includeMergedTags, } = this.options;
262
+ // 'prerelease' and 'prepatch' are identical, for our purposes
263
+ const release = bump.startsWith('pre') ? bump.replace('release', 'patch') : `pre${bump}`;
264
+ let chain = Promise.resolve();
265
+ // attempting to publish a canary release with local changes is not allowed
266
+ chain = chain
267
+ .then(() => this.verifyWorkingTreeClean())
268
+ .catch((err) => {
269
+ // an execa error is thrown when git suffers a fatal error (such as no git repository present)
270
+ if (err.failed && /git describe/.test(err.command)) {
271
+ // (we tried)
272
+ this.logger.silly('EWORKINGTREE', err.message);
273
+ this.logger.notice('FYI', 'Unable to verify working tree, proceed at your own risk');
274
+ }
275
+ else {
276
+ // validation errors should be preserved
277
+ throw err;
278
+ }
279
+ });
280
+ // find changed packages since last release, if any
281
+ chain = chain.then(() => {
282
+ var _a;
283
+ return (0, core_1.collectUpdates)((_a = this.packageGraph) === null || _a === void 0 ? void 0 : _a.rawPackageList, this.packageGraph, this.execOpts, {
284
+ bump: 'prerelease',
285
+ canary: true,
286
+ ignoreChanges,
287
+ forcePublish,
288
+ includeMergedTags,
289
+ // private packages are never published, don't bother describing their refs.
290
+ }, this.options.gitDryRun).filter((node) => !node.pkg.private);
291
+ });
292
+ const makeVersion = (fallback) => ({ lastVersion = fallback, refCount, sha }) => {
293
+ // the next version is bumped without concern for preid or current index
294
+ const nextVersion = semver_1.default.inc(lastVersion.replace(this.tagPrefix, ''), release.replace('pre', ''));
295
+ // semver.inc() starts a new prerelease at .0, git describe starts at .1
296
+ // and build metadata is always ignored when comparing dependency ranges
297
+ return `${nextVersion}-${preid}.${Math.max(0, refCount - 1)}+${sha}`;
298
+ };
299
+ if ((_a = this.project) === null || _a === void 0 ? void 0 : _a.isIndependent()) {
300
+ // each package is described against its tags only
301
+ chain = chain.then((updates) => (0, p_map_1.default)(updates, (node) => (0, core_1.describeRef)({
302
+ match: `${node.name}@*`,
303
+ cwd,
304
+ }, includeMergedTags, this.options.gitDryRun)
305
+ // an unpublished package will have no reachable git tag
306
+ .then(makeVersion(node.version))
307
+ .then((version) => [node.name, version])).then((updatesVersions) => ({
308
+ updates,
309
+ updatesVersions,
310
+ })));
311
+ }
312
+ else {
313
+ // all packages are described against the last tag
314
+ chain = chain.then((updates) => {
315
+ var _a;
316
+ return (0, core_1.describeRef)({
317
+ match: `${this.tagPrefix}*.*.*`,
318
+ cwd,
319
+ }, includeMergedTags, this.options.gitDryRun)
320
+ // a repo with no tags should default to whatever lerna.json claims
321
+ .then(makeVersion((_a = this.project) === null || _a === void 0 ? void 0 : _a.version))
322
+ .then((version) => updates.map((node) => [node.name, version]))
323
+ .then((updatesVersions) => ({
324
+ updates,
325
+ updatesVersions,
326
+ }));
327
+ });
328
+ }
329
+ return chain.then(({ updates, updatesVersions }) => ({
330
+ updates,
331
+ updatesVersions,
332
+ needsConfirmation: true,
333
+ }));
334
+ }
335
+ confirmPublish() {
336
+ var _a, _b, _c;
337
+ const count = (_a = this.packagesToPublish) === null || _a === void 0 ? void 0 : _a.length;
338
+ 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 : [];
339
+ this.logOutput('');
340
+ this.logOutput(`Found ${count} ${count === 1 ? 'package' : 'packages'} to publish:`);
341
+ this.logOutput(message.join(os_1.default.EOL));
342
+ this.logOutput('');
343
+ if (this.options.yes) {
344
+ this.logger.info('auto-confirmed', '');
345
+ return true;
346
+ }
347
+ return core_1.PromptUtilities.confirm('Are you sure you want to publish these packages?');
348
+ }
349
+ prepareLicenseActions() {
350
+ return Promise.resolve()
351
+ .then(() => { var _a; return (0, get_packages_without_license_1.getPackagesWithoutLicense)(this.project, (_a = this.packagesToPublish) !== null && _a !== void 0 ? _a : []); })
352
+ .then((packagesWithoutLicense) => {
353
+ var _a;
354
+ if (packagesWithoutLicense.length && !((_a = this.project) === null || _a === void 0 ? void 0 : _a.licensePath)) {
355
+ this.packagesToBeLicensed = [];
356
+ const names = packagesWithoutLicense.map((pkg) => pkg.name);
357
+ const noun = names.length > 1 ? 'Packages' : 'Package';
358
+ const verb = names.length > 1 ? 'are' : 'is';
359
+ const list = names.length > 1
360
+ ? `${names.slice(0, -1).join(', ')}${names.length > 2 ? ',' : ''} and ${names[names.length - 1] /* oxford commas _are_ that important */}`
361
+ : names[0];
362
+ 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.');
363
+ }
364
+ else {
365
+ this.packagesToBeLicensed = packagesWithoutLicense;
366
+ }
367
+ });
368
+ }
369
+ prepareRegistryActions() {
370
+ let chain = Promise.resolve();
371
+ if (this.conf.get('registry') !== 'https://registry.npmjs.org/') {
372
+ this.logger.notice('', 'Skipping all user and access validation due to third-party registry');
373
+ this.logger.notice('', `Make sure you're authenticated properly "\\_(ツ)_ /"`);
374
+ return chain;
375
+ }
376
+ /* istanbul ignore if */
377
+ if (process.env.LERNA_INTEGRATION) {
378
+ return chain;
379
+ }
380
+ if (this.verifyAccess) {
381
+ // validate user has valid npm credentials first,
382
+ // by far the most common form of failed execution
383
+ chain = chain.then(() => (0, get_npm_username_1.getNpmUsername)(this.conf.snapshot));
384
+ chain = chain.then((username) => {
385
+ var _a;
386
+ // if no username was retrieved, don't bother validating
387
+ if (username) {
388
+ return (0, verify_npm_package_access_1.verifyNpmPackageAccess)((_a = this.packagesToPublish) !== null && _a !== void 0 ? _a : [], username, this.conf.snapshot);
389
+ }
390
+ });
391
+ // read profile metadata to determine if account-level 2FA is enabled
392
+ chain = chain.then(() => (0, get_two_factor_auth_required_1.getTwoFactorAuthRequired)(this.conf.snapshot));
393
+ chain = chain.then((isRequired) => {
394
+ // notably, this still doesn't handle package-level 2FA requirements
395
+ this.twoFactorAuthRequired = isRequired;
396
+ });
397
+ }
398
+ return chain;
399
+ }
400
+ updateCanaryVersions() {
401
+ return (0, p_map_1.default)(this.updates, (node) => {
402
+ var _a, _b, _c;
403
+ node.pkg.set('version', (_a = this.updatesVersions) === null || _a === void 0 ? void 0 : _a.get(node.name));
404
+ for (const [depName, resolved] of node.localDependencies) {
405
+ // other canary versions need to be updated, non-canary is a no-op
406
+ 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);
407
+ // it no longer matters if we mutate the shared Package instance
408
+ node.pkg.updateLocalDependency(resolved, depVersion, this.savePrefix);
409
+ }
410
+ // writing changes to disk handled in serializeChanges()
411
+ });
412
+ }
413
+ resolveLocalDependencyLinks() {
414
+ // resolve relative file: links to their actual version range
415
+ const updatesWithLocalLinks = this.updates.filter((node) => Array.from(node.localDependencies.values()).some((resolved) => resolved.type === 'directory'));
416
+ return (0, p_map_1.default)(updatesWithLocalLinks, (node) => {
417
+ var _a, _b;
418
+ for (const [depName, resolved] of node.localDependencies) {
419
+ // regardless of where the version comes from, we can't publish 'file:../sibling-pkg' specs
420
+ 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);
421
+ // it no longer matters if we mutate the shared Package instance
422
+ node.pkg.updateLocalDependency(resolved, depVersion, this.savePrefix);
423
+ }
424
+ // writing changes to disk handled in serializeChanges()
425
+ });
426
+ }
427
+ annotateGitHead() {
428
+ var _a;
429
+ try {
430
+ const gitHead = this.options.gitHead || (0, get_current_sha_1.getCurrentSHA)(this.execOpts);
431
+ for (const pkg of (_a = this.packagesToPublish) !== null && _a !== void 0 ? _a : []) {
432
+ // provide gitHead property that is normally added during npm publish
433
+ pkg.set('gitHead', gitHead);
434
+ }
435
+ }
436
+ catch (err) {
437
+ // from-package should be _able_ to run without git, but at least we tried
438
+ this.logger.silly('EGITHEAD', err.message);
439
+ this.logger.notice('FYI', 'Unable to set temporary gitHead property, it will be missing from registry metadata');
440
+ }
441
+ // writing changes to disk handled in serializeChanges()
442
+ }
443
+ serializeChanges() {
444
+ var _a;
445
+ return (0, p_map_1.default)((_a = this.packagesToPublish) !== null && _a !== void 0 ? _a : [], (pkg) => pkg.serialize());
446
+ }
447
+ resetChanges() {
448
+ var _a;
449
+ // the package.json files are changed (by gitHead if not --canary)
450
+ // and we should always __attempt_ to leave the working tree clean
451
+ const { cwd } = this.execOpts;
452
+ const gitOpts = {
453
+ granularPathspec: this.options.granularPathspec !== false,
454
+ };
455
+ const dirtyManifests = [(_a = this.project) === null || _a === void 0 ? void 0 : _a.manifest]
456
+ .concat(this.packagesToPublish)
457
+ .map((pkg) => path_1.default.relative(cwd, pkg.manifestLocation));
458
+ return (0, git_checkout_1.gitCheckout)(dirtyManifests, gitOpts, this.execOpts, this.options.gitDryRun).catch((err) => {
459
+ this.logger.silly('EGITCHECKOUT', err.message);
460
+ this.logger.notice('FYI', `Unable to reset working tree changes, this probably isn't a git repo.`);
461
+ });
462
+ }
463
+ execScript(pkg, script) {
464
+ const scriptLocation = path_1.default.join(pkg.location, 'scripts', script);
465
+ try {
466
+ require(scriptLocation);
467
+ }
468
+ catch (ex) {
469
+ this.logger.silly('execScript', `No ${script} script found at ${scriptLocation}`);
470
+ }
471
+ return pkg;
472
+ }
473
+ removeTempLicensesOnError(error) {
474
+ return Promise.resolve()
475
+ .then(() => {
476
+ var _a;
477
+ return (0, remove_temp_licenses_1.removeTempLicenses)((_a = this.packagesToBeLicensed) !== null && _a !== void 0 ? _a : []).catch((removeError) => {
478
+ this.logger.error('licenses', 'error removing temporary license files', removeError.stack || removeError);
479
+ });
480
+ })
481
+ .then(() => {
482
+ // restore original error into promise chain
483
+ throw error;
484
+ });
485
+ }
486
+ requestOneTimePassword() {
487
+ // if OTP has already been provided, skip prompt
488
+ if (this.otpCache.otp) {
489
+ return;
490
+ }
491
+ return Promise.resolve()
492
+ .then(() => (0, core_1.getOneTimePassword)('Enter OTP:'))
493
+ .then((otp) => this.otpCache.otp = otp);
494
+ }
495
+ topoMapPackages(mapper) {
496
+ // we don't respect --no-sort here, sorry
497
+ return (0, core_1.runTopologically)(this.packagesToPublish, mapper, {
498
+ concurrency: this.concurrency,
499
+ rejectCycles: this.options.rejectCycles,
500
+ // By default, do not include devDependencies in the graph because it would
501
+ // increase the chance of dependency cycles, causing less-than-ideal order.
502
+ // If the user has opted-in to --graph-type=all (or 'graphType': 'all' in lerna.json),
503
+ // devDependencies _will_ be included in the graph construction.
504
+ graphType: this.options.graphType === 'all' ? 'allDependencies' : 'dependencies',
505
+ });
506
+ }
507
+ packUpdated() {
508
+ var _a;
509
+ const tracker = this.logger.newItem('npm pack');
510
+ tracker.addWork((_a = this.packagesToPublish) === null || _a === void 0 ? void 0 : _a.length);
511
+ let chain = Promise.resolve();
512
+ chain = chain.then(() => { var _a, _b; return (0, create_temp_licenses_1.createTempLicenses)((_a = this.project) === null || _a === void 0 ? void 0 : _a.licensePath, (_b = this.packagesToBeLicensed) !== null && _b !== void 0 ? _b : []); });
513
+ if (!this.hasRootedLeaf) {
514
+ // despite being deprecated for years...
515
+ chain = chain.then(() => this.runRootLifecycle('prepublish'));
516
+ // these lifecycles _should_ never be employed to run `ws-roller publish`...
517
+ chain = chain.then(() => { var _a; return this.runPackageLifecycle((_a = this.project) === null || _a === void 0 ? void 0 : _a.manifest, 'prepare'); });
518
+ chain = chain.then(() => { var _a; return this.runPackageLifecycle((_a = this.project) === null || _a === void 0 ? void 0 : _a.manifest, 'prepublishOnly'); });
519
+ chain = chain.then(() => { var _a; return this.runPackageLifecycle((_a = this.project) === null || _a === void 0 ? void 0 : _a.manifest, 'prepack'); });
520
+ }
521
+ const opts = this.conf.snapshot;
522
+ const mapper = (0, p_pipe_1.default)(...[
523
+ this.options.requireScripts && ((pkg) => this.execScript(pkg, 'prepublish')),
524
+ (pkg) => (0, core_1.pulseTillDone)((0, pack_directory_1.packDirectory)(pkg, pkg.location, opts)).then((packed) => {
525
+ var _a, _b;
526
+ tracker.verbose('packed', path_1.default.relative((_b = (_a = this.project) === null || _a === void 0 ? void 0 : _a.rootPath) !== null && _b !== void 0 ? _b : '', pkg.contents));
527
+ tracker.completeWork(1);
528
+ // store metadata for use in this.publishPacked()
529
+ pkg.packed = packed;
530
+ // manifest may be mutated by any previous lifecycle
531
+ return pkg.refresh();
532
+ }),
533
+ ].filter(Boolean));
534
+ chain = chain.then(() => this.topoMapPackages(mapper));
535
+ chain = chain.then(() => { var _a; return (0, remove_temp_licenses_1.removeTempLicenses)((_a = this.packagesToBeLicensed) !== null && _a !== void 0 ? _a : []); });
536
+ // remove temporary license files if _any_ error occurs _anywhere_ in the promise chain
537
+ chain = chain.catch((error) => this.removeTempLicensesOnError(error));
538
+ if (!this.hasRootedLeaf) {
539
+ chain = chain.then(() => { var _a; return this.runPackageLifecycle((_a = this.project) === null || _a === void 0 ? void 0 : _a.manifest, 'postpack'); });
540
+ }
541
+ return chain.finally(() => tracker.finish());
542
+ }
543
+ publishPacked() {
544
+ var _a;
545
+ const tracker = this.logger.newItem('publish');
546
+ tracker.addWork((_a = this.packagesToPublish) === null || _a === void 0 ? void 0 : _a.length);
547
+ let chain = Promise.resolve();
548
+ // if account-level 2FA is enabled, prime the OTP cache
549
+ if (this.twoFactorAuthRequired) {
550
+ chain = chain.then(() => this.requestOneTimePassword());
551
+ }
552
+ const opts = Object.assign(this.conf.snapshot, {
553
+ // distTag defaults to 'latest' OR whatever is in pkg.publishConfig.tag
554
+ // if we skip temp tags we should tag with the proper value immediately
555
+ tag: this.options.tempTag ? 'lerna-temp' : this.conf.get('tag'),
556
+ });
557
+ const mapper = (0, p_pipe_1.default)(...[
558
+ (pkg) => {
559
+ const preDistTag = this.getPreDistTag(pkg);
560
+ const tag = !this.options.tempTag && preDistTag ? preDistTag : opts.tag;
561
+ const pkgOpts = Object.assign({}, opts, { tag });
562
+ return (0, core_1.pulseTillDone)((0, npm_publish_1.npmPublish)(pkg, pkg.packed.tarFilePath, pkgOpts, this.otpCache)).then(() => {
563
+ tracker.success('published', pkg.name, pkg.version);
564
+ tracker.completeWork(1);
565
+ (0, log_packed_1.logPacked)(pkg.packed);
566
+ return pkg;
567
+ });
568
+ },
569
+ this.options.requireScripts && ((pkg) => this.execScript(pkg, 'postpublish')),
570
+ ].filter(Boolean));
571
+ chain = chain.then(() => this.topoMapPackages(mapper));
572
+ if (!this.hasRootedLeaf) {
573
+ // cyclical 'publish' lifecycles are automatically skipped
574
+ chain = chain.then(() => this.runRootLifecycle('publish'));
575
+ chain = chain.then(() => this.runRootLifecycle('postpublish'));
576
+ }
577
+ return chain.finally(() => tracker.finish());
578
+ }
579
+ npmUpdateAsLatest() {
580
+ var _a;
581
+ const tracker = this.logger.newItem('npmUpdateAsLatest');
582
+ tracker.addWork((_a = this.packagesToPublish) === null || _a === void 0 ? void 0 : _a.length);
583
+ tracker.showProgress();
584
+ let chain = Promise.resolve();
585
+ const opts = this.conf.snapshot;
586
+ const getDistTag = (publishConfig) => {
587
+ if (opts.tag === 'latest' && publishConfig && publishConfig.tag) {
588
+ return publishConfig.tag;
589
+ }
590
+ return opts.tag;
591
+ };
592
+ const mapper = (pkg) => {
593
+ const spec = `${pkg.name}@${pkg.version}`;
594
+ const preDistTag = this.getPreDistTag(pkg);
595
+ const distTag = preDistTag || getDistTag(pkg.get('publishConfig'));
596
+ return Promise.resolve()
597
+ .then(() => (0, core_1.pulseTillDone)((0, npm_dist_tag_1.remove)(spec, 'lerna-temp', opts, this.otpCache)))
598
+ .then(() => (0, core_1.pulseTillDone)((0, npm_dist_tag_1.add)(spec, distTag, opts, this.otpCache)))
599
+ .then(() => {
600
+ tracker.success('dist-tag', '%s@%s => %j', pkg.name, pkg.version, distTag);
601
+ tracker.completeWork(1);
602
+ return pkg;
603
+ });
604
+ };
605
+ chain = chain.then(() => this.topoMapPackages(mapper));
606
+ return chain.finally(() => tracker.finish());
607
+ }
608
+ getDistTag() {
609
+ if (this.options.distTag) {
610
+ return this.options.distTag;
611
+ }
612
+ if (this.options.canary) {
613
+ return 'canary';
614
+ }
615
+ // undefined defaults to 'latest' OR whatever is in pkg.publishConfig.tag
616
+ }
617
+ getPreDistTag(pkg) {
618
+ if (!this.options.preDistTag) {
619
+ return;
620
+ }
621
+ const isPrerelease = (0, core_1.prereleaseIdFromVersion)(pkg.version);
622
+ if (isPrerelease) {
623
+ return this.options.preDistTag;
624
+ }
625
+ }
626
+ }
627
+ exports.PublishCommand = PublishCommand;
628
+ //# sourceMappingURL=publishCommand.js.map