UNPKG

40.6 kBJavaScriptView Raw
1"use strict";
2
3var meow = require("meow"), errors = require("@changesets/errors"), logger = require("@changesets/logger"), util = require("util"), fs = require("fs-extra"), path = require("path"), getPackages = require("@manypkg/get-packages"), getDependentsGraph = require("@changesets/get-dependents-graph"), config = require("@changesets/config"), chalk = require("chalk"), child_process = require("child_process"), termSize = require("term-size"), enquirer = require("enquirer"), externalEditor = require("external-editor"), git = require("@changesets/git"), writeChangeset = require("@changesets/write"), semver = require("semver"), boxen = require("boxen"), outdent = require("outdent"), applyReleasePlan = require("@changesets/apply-release-plan"), readChangesets = require("@changesets/read"), assembleReleasePlan = require("@changesets/assemble-release-plan"), pre$1 = require("@changesets/pre"), pLimit = require("p-limit"), preferredPM = require("preferred-pm"), spawn = require("spawndamnit"), isCI$1 = require("is-ci"), table = require("tty-table"), getReleasePlan = require("@changesets/get-release-plan");
4
5function _interopDefault(e) {
6 return e && e.__esModule ? e : {
7 default: e
8 };
9}
10
11var meow__default = _interopDefault(meow), fs__default = _interopDefault(fs), path__default = _interopDefault(path), chalk__default = _interopDefault(chalk), termSize__default = _interopDefault(termSize), writeChangeset__default = _interopDefault(writeChangeset), semver__default = _interopDefault(semver), boxen__default = _interopDefault(boxen), outdent__default = _interopDefault(outdent), applyReleasePlan__default = _interopDefault(applyReleasePlan), readChangesets__default = _interopDefault(readChangesets), assembleReleasePlan__default = _interopDefault(assembleReleasePlan), pLimit__default = _interopDefault(pLimit), preferredPM__default = _interopDefault(preferredPM), spawn__default = _interopDefault(spawn), isCI__default = _interopDefault(isCI$1), table__default = _interopDefault(table), getReleasePlan__default = _interopDefault(getReleasePlan);
12
13const pkgPath = path__default.default.dirname(require.resolve("@changesets/cli/package.json"));
14
15async function init(cwd) {
16 const changesetBase = path__default.default.resolve(cwd, ".changeset");
17 fs__default.default.existsSync(changesetBase) ? fs__default.default.existsSync(path__default.default.join(changesetBase, "config.json")) ? logger.warn("It looks like you already have changesets initialized. You should be able to run changeset commands no problems.") : (fs__default.default.existsSync(path__default.default.join(changesetBase, "config.js")) ? (logger.error("It looks like you're using the version 1 `.changeset/config.js` file"),
18 logger.error("The format of the config object has significantly changed in v2 as well"),
19 logger.error(" - we thoroughly recommend looking at the changelog for this package for what has changed"),
20 logger.error("Changesets will write the defaults for the new config, remember to transfer your options into the new config at `.changeset/config.json`")) : (logger.error("It looks like you don't have a config file"),
21 logger.info("The default config file will be written at `.changeset/config.json`")),
22 await fs__default.default.writeFile(path__default.default.resolve(changesetBase, "config.json"), JSON.stringify(config.defaultWrittenConfig, null, 2))) : (await fs__default.default.copy(path__default.default.resolve(pkgPath, "./default-files"), changesetBase),
23 await fs__default.default.writeFile(path__default.default.resolve(changesetBase, "config.json"), JSON.stringify(config.defaultWrittenConfig, null, 2)),
24 logger.log(chalk__default.default`Thanks for choosing {green changesets} to help manage your versioning and publishing\n`),
25 logger.log("You should be set up to start using changesets now!\n"), logger.info("We have added a `.changeset` folder, and a couple of files to help you out:"),
26 logger.info(chalk__default.default`- {blue .changeset/README.md} contains information about using changesets`),
27 logger.info(chalk__default.default`- {blue .changeset/config.json} is our default config`));
28}
29
30function _defineProperty(obj, key, value) {
31 return key in obj ? Object.defineProperty(obj, key, {
32 value: value,
33 enumerable: !0,
34 configurable: !0,
35 writable: !0
36 }) : obj[key] = value, obj;
37}
38
39function ownKeys(object, enumerableOnly) {
40 var keys = Object.keys(object);
41 if (Object.getOwnPropertySymbols) {
42 var symbols = Object.getOwnPropertySymbols(object);
43 enumerableOnly && (symbols = symbols.filter((function(sym) {
44 return Object.getOwnPropertyDescriptor(object, sym).enumerable;
45 }))), keys.push.apply(keys, symbols);
46 }
47 return keys;
48}
49
50function _objectSpread2(target) {
51 for (var i = 1; i < arguments.length; i++) {
52 var source = null != arguments[i] ? arguments[i] : {};
53 i % 2 ? ownKeys(Object(source), !0).forEach((function(key) {
54 _defineProperty(target, key, source[key]);
55 })) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach((function(key) {
56 Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
57 }));
58 }
59 return target;
60}
61
62const serialId = function() {
63 let id = 0;
64 return () => id++;
65}(), limit = Math.max(termSize__default.default().rows - 5, 10);
66
67let cancelFlow = () => {
68 logger.success("Cancelled... 👋 "), process.exit();
69};
70
71async function askCheckboxPlus(message, choices, format) {
72 const name = "CheckboxPlus-" + serialId();
73 return enquirer.prompt({
74 type: "autocomplete",
75 name: name,
76 message: message,
77 prefix: logger.prefix,
78 multiple: !0,
79 choices: choices,
80 format: format,
81 limit: limit,
82 onCancel: cancelFlow
83 }).then((responses => responses[name])).catch((err => {
84 logger.error(err);
85 }));
86}
87
88async function askQuestion(message) {
89 const name = "Question-" + serialId();
90 return enquirer.prompt([ {
91 type: "input",
92 message: message,
93 name: name,
94 prefix: logger.prefix,
95 onCancel: cancelFlow
96 } ]).then((responses => responses[name])).catch((err => {
97 logger.error(err);
98 }));
99}
100
101function askQuestionWithEditor(message) {
102 return externalEditor.edit(message, {
103 postfix: ".md"
104 }).replace(/^#.*\n?/gm, "").replace(/\n+$/g, "").trim();
105}
106
107async function askConfirm(message) {
108 const name = "Confirm-" + serialId();
109 return enquirer.prompt([ {
110 message: message,
111 name: name,
112 prefix: logger.prefix,
113 type: "confirm",
114 initial: !0,
115 onCancel: cancelFlow
116 } ]).then((responses => responses[name])).catch((err => {
117 logger.error(err);
118 }));
119}
120
121async function askList(message, choices) {
122 const name = "List-" + serialId();
123 return enquirer.prompt([ {
124 choices: choices,
125 message: message,
126 name: name,
127 prefix: logger.prefix,
128 type: "select",
129 onCancel: cancelFlow
130 } ]).then((responses => responses[name])).catch((err => {
131 logger.error(err);
132 }));
133}
134
135const {green: green, yellow: yellow, red: red, bold: bold, blue: blue, cyan: cyan} = chalk__default.default;
136
137async function confirmMajorRelease(pkgJSON) {
138 if (semver__default.default.lt(pkgJSON.version, "1.0.0")) {
139 return logger.log(yellow(`WARNING: Releasing a major version for ${green(pkgJSON.name)} will be its ${red("first major release")}.`)),
140 logger.log(yellow(`If you are unsure if this is correct, contact the package's maintainers ${red("before committing this changeset")}.`)),
141 await askConfirm(bold(`Are you sure you want still want to release the ${red("first major release")} of ${pkgJSON.name}?`));
142 }
143 return !0;
144}
145
146async function getPackagesToRelease(changedPackages, allPackages) {
147 function askInitialReleaseQuestion(defaultChoiceList) {
148 return askCheckboxPlus("Which packages would you like to include?", defaultChoiceList, (x => Array.isArray(x) ? x.filter((x => "changed packages" !== x && "unchanged packages" !== x)).map((x => cyan(x))).join(", ") : x));
149 }
150 if (allPackages.length > 1) {
151 const unchangedPackagesNames = allPackages.map((({packageJson: packageJson}) => packageJson.name)).filter((name => !changedPackages.includes(name))), defaultChoiceList = [ {
152 name: "changed packages",
153 choices: changedPackages
154 }, {
155 name: "unchanged packages",
156 choices: unchangedPackagesNames
157 } ].filter((({choices: choices}) => 0 !== choices.length));
158 let packagesToRelease = await askInitialReleaseQuestion(defaultChoiceList);
159 if (0 === packagesToRelease.length) do {
160 logger.error("You must select at least one package to release"), logger.error("(You most likely hit enter instead of space!)"),
161 packagesToRelease = await askInitialReleaseQuestion(defaultChoiceList);
162 } while (0 === packagesToRelease.length);
163 return packagesToRelease.filter((pkgName => "changed packages" !== pkgName && "unchanged packages" !== pkgName));
164 }
165 return [ allPackages[0].packageJson.name ];
166}
167
168function formatPkgNameAndVersion(pkgName, version) {
169 return `${bold(pkgName)}@${bold(version)}`;
170}
171
172async function createChangeset(changedPackages, allPackages) {
173 const releases = [];
174 if (allPackages.length > 1) {
175 const packagesToRelease = await getPackagesToRelease(changedPackages, allPackages);
176 let pkgJsonsByName = new Map(allPackages.map((({packageJson: packageJson}) => [ packageJson.name, packageJson ]))), pkgsLeftToGetBumpTypeFor = new Set(packagesToRelease), pkgsThatShouldBeMajorBumped = (await askCheckboxPlus(bold(`Which packages should have a ${red("major")} bump?`), [ {
177 name: "all packages",
178 choices: packagesToRelease.map((pkgName => ({
179 name: pkgName,
180 message: formatPkgNameAndVersion(pkgName, pkgJsonsByName.get(pkgName).version)
181 })))
182 } ], (x => Array.isArray(x) ? x.filter((x => "all packages" !== x)).map((x => cyan(x))).join(", ") : x))).filter((x => "all packages" !== x));
183 for (const pkgName of pkgsThatShouldBeMajorBumped) {
184 let pkgJson = pkgJsonsByName.get(pkgName);
185 await confirmMajorRelease(pkgJson) && (pkgsLeftToGetBumpTypeFor.delete(pkgName),
186 releases.push({
187 name: pkgName,
188 type: "major"
189 }));
190 }
191 if (0 !== pkgsLeftToGetBumpTypeFor.size) {
192 let pkgsThatShouldBeMinorBumped = (await askCheckboxPlus(bold(`Which packages should have a ${green("minor")} bump?`), [ {
193 name: "all packages",
194 choices: [ ...pkgsLeftToGetBumpTypeFor ].map((pkgName => ({
195 name: pkgName,
196 message: formatPkgNameAndVersion(pkgName, pkgJsonsByName.get(pkgName).version)
197 })))
198 } ], (x => Array.isArray(x) ? x.filter((x => "all packages" !== x)).map((x => cyan(x))).join(", ") : x))).filter((x => "all packages" !== x));
199 for (const pkgName of pkgsThatShouldBeMinorBumped) pkgsLeftToGetBumpTypeFor.delete(pkgName),
200 releases.push({
201 name: pkgName,
202 type: "minor"
203 });
204 }
205 if (0 !== pkgsLeftToGetBumpTypeFor.size) {
206 logger.log(`The following packages will be ${blue("patch")} bumped:`), pkgsLeftToGetBumpTypeFor.forEach((pkgName => {
207 logger.log(formatPkgNameAndVersion(pkgName, pkgJsonsByName.get(pkgName).version));
208 }));
209 for (const pkgName of pkgsLeftToGetBumpTypeFor) releases.push({
210 name: pkgName,
211 type: "patch"
212 });
213 }
214 } else {
215 let pkg = allPackages[0], type = await askList(`What kind of change is this for ${green(pkg.packageJson.name)}? (current version is ${pkg.packageJson.version})`, [ "patch", "minor", "major" ]);
216 if ("major" === type) {
217 if (!await confirmMajorRelease(pkg.packageJson)) throw new errors.ExitError(1);
218 }
219 releases.push({
220 name: pkg.packageJson.name,
221 type: type
222 });
223 }
224 logger.log("Please enter a summary for this change (this will be in the changelogs). Submit empty line to open external editor");
225 let summary = await askQuestion("Summary");
226 if (0 === summary.length) {
227 try {
228 if (summary = askQuestionWithEditor("\n\n# Please enter a summary for your changes.\n# An empty message aborts the editor."),
229 summary.length > 0) return {
230 confirmed: !0,
231 summary: summary,
232 releases: releases
233 };
234 } catch (err) {
235 logger.log("An error happened using external editor. Please type your summary here:");
236 }
237 for (summary = await askQuestion(""); 0 === summary.length; ) summary = await askQuestion("\n\n# A summary is required for the changelog! 😪");
238 }
239 return {
240 confirmed: !1,
241 summary: summary,
242 releases: releases
243 };
244}
245
246function printConfirmationMessage(changeset, repoHasMultiplePackages) {
247 function getReleasesOfType(type) {
248 return changeset.releases.filter((release => release.type === type)).map((release => release.name));
249 }
250 logger.log("=== Releasing the following packages ===");
251 const majorReleases = getReleasesOfType("major"), minorReleases = getReleasesOfType("minor"), patchReleases = getReleasesOfType("patch");
252 if (majorReleases.length > 0 && logger.log(`${chalk__default.default.green("[Major]")}\n ${majorReleases.join(", ")}`),
253 minorReleases.length > 0 && logger.log(`${chalk__default.default.green("[Minor]")}\n ${minorReleases.join(", ")}`),
254 patchReleases.length > 0 && logger.log(`${chalk__default.default.green("[Patch]")}\n ${patchReleases.join(", ")}`),
255 repoHasMultiplePackages) {
256 const message = outdent__default.default`
257 ${chalk__default.default.red("========= NOTE ========")}
258 All dependents of these packages that will be incompatible with the new version will be ${chalk__default.default.red("patch bumped")} when this changeset is applied.`, prettyMessage = boxen__default.default(message, {
259 borderStyle: "double",
260 align: "center"
261 });
262 logger.log(prettyMessage);
263 }
264}
265
266async function add(cwd, {empty: empty, open: open}, config) {
267 const packages = await getPackages.getPackages(cwd), changesetBase = path__default.default.resolve(cwd, ".changeset");
268 let newChangeset;
269 if (empty) newChangeset = {
270 confirmed: !0,
271 releases: [],
272 summary: ""
273 }; else {
274 const changePackagesName = (await git.getChangedPackagesSinceRef({
275 cwd: cwd,
276 ref: config.baseBranch
277 })).filter((a => a)).map((pkg => pkg.packageJson.name));
278 newChangeset = await createChangeset(changePackagesName, packages.packages), printConfirmationMessage(newChangeset, packages.packages.length > 1),
279 newChangeset.confirmed || (newChangeset = _objectSpread2(_objectSpread2({}, newChangeset), {}, {
280 confirmed: await askConfirm("Is this your desired changeset?")
281 }));
282 }
283 if (newChangeset.confirmed) {
284 const changesetID = await writeChangeset__default.default(newChangeset, cwd);
285 config.commit ? (await git.add(path__default.default.resolve(changesetBase, changesetID + ".md"), cwd),
286 await git.commit("docs(changeset): " + newChangeset.summary, cwd), logger.log(chalk__default.default.green((empty ? "Empty " : "") + "Changeset added and committed"))) : logger.log(chalk__default.default.green((empty ? "Empty " : "") + "Changeset added! - you can now commit it\n")),
287 [ ...newChangeset.releases ].find((c => "major" === c.type)) ? (logger.warn("This Changeset includes a major change and we STRONGLY recommend adding more information to the changeset:"),
288 logger.warn("WHAT the breaking change is"), logger.warn("WHY the change was made"),
289 logger.warn("HOW a consumer should update their code")) : logger.log(chalk__default.default.green("If you want to modify or expand on the changeset summary, you can find it here"));
290 const changesetPath = path__default.default.resolve(changesetBase, changesetID + ".md");
291 if (logger.info(chalk__default.default.blue(changesetPath)), open) {
292 const externalEditor$1 = new externalEditor.ExternalEditor;
293 externalEditor$1.cleanup(), child_process.spawn(externalEditor$1.editor.bin, externalEditor$1.editor.args.concat([ changesetPath ]), {
294 detached: !0,
295 stdio: "inherit"
296 });
297 }
298 }
299}
300
301const removeEmptyFolders = async folderPath => {
302 const dirContents = fs__default.default.readdirSync(folderPath);
303 return Promise.all(dirContents.map((async contentPath => {
304 const singleChangesetPath = path__default.default.resolve(folderPath, contentPath);
305 try {
306 (await fs__default.default.readdir(singleChangesetPath)).length < 1 && await fs__default.default.rmdir(singleChangesetPath);
307 } catch (err) {
308 if ("ENOTDIR" !== err.code) throw err;
309 }
310 })));
311};
312
313let importantSeparator = chalk__default.default.red("===============================IMPORTANT!==============================="), importantEnd = chalk__default.default.red("----------------------------------------------------------------------");
314
315async function version(cwd, options, config) {
316 const releaseConfig = _objectSpread2(_objectSpread2({}, config), {}, {
317 commit: !options.snapshot && config.commit
318 }), [changesets, preState] = await Promise.all([ readChangesets__default.default(cwd), pre$1.readPreState(cwd), removeEmptyFolders(path__default.default.resolve(cwd, ".changeset")) ]);
319 if ("pre" === (null == preState ? void 0 : preState.mode)) {
320 if (logger.warn(importantSeparator), void 0 !== options.snapshot) throw logger.error("Snapshot release is not allowed in pre mode"),
321 logger.log("To resolve this exit the pre mode by running `changeset pre exit`"),
322 new errors.ExitError(1);
323 logger.warn("You are in prerelease mode"), logger.warn("If you meant to do a normal release you should revert these changes and run `changeset pre exit`"),
324 logger.warn("You can then run `changeset version` again to do a normal release"),
325 logger.warn(importantEnd);
326 }
327 if (0 === changesets.length && (void 0 === preState || "exit" !== preState.mode)) return void logger.warn("No unreleased changesets found, exiting.");
328 let packages = await getPackages.getPackages(cwd), releasePlan = assembleReleasePlan__default.default(changesets, packages, releaseConfig, preState, options.snapshot);
329 await applyReleasePlan__default.default(releasePlan, packages, releaseConfig, options.snapshot),
330 releaseConfig.commit ? logger.log("All files have been updated and committed. You're ready to publish!") : logger.log("All files have been updated. Review them and commit at your leisure");
331}
332
333var isCI = !(!isCI__default.default && !process.env.GITHUB_ACTIONS);
334
335const npmRequestLimit = pLimit__default.default(40), npmPublishLimit = pLimit__default.default(10);
336
337function jsonParse(input) {
338 try {
339 return JSON.parse(input);
340 } catch (err) {
341 throw err instanceof SyntaxError && console.error("error parsing json:", input),
342 err;
343 }
344}
345
346function getCorrectRegistry(packageJson) {
347 var _packageJson$publishC, _packageJson$publishC2;
348 const registry = null !== (_packageJson$publishC = null == packageJson || null === (_packageJson$publishC2 = packageJson.publishConfig) || void 0 === _packageJson$publishC2 ? void 0 : _packageJson$publishC2.registry) && void 0 !== _packageJson$publishC ? _packageJson$publishC : process.env.npm_config_registry;
349 return registry && "https://registry.yarnpkg.com" !== registry ? registry : "https://registry.npmjs.org";
350}
351
352async function getPublishTool(cwd) {
353 const pm = await preferredPM__default.default(cwd);
354 if (!pm || "pnpm" !== pm.name) return {
355 name: "npm"
356 };
357 try {
358 let version = (await spawn__default.default("pnpm", [ "--version" ], {
359 cwd: cwd
360 })).stdout.toString().trim(), parsed = semver__default.default.parse(version);
361 return {
362 name: "pnpm",
363 shouldAddNoGitChecks: void 0 !== (null == parsed ? void 0 : parsed.major) && parsed.major >= 5
364 };
365 } catch (e) {
366 return {
367 name: "pnpm",
368 shouldAddNoGitChecks: !1
369 };
370 }
371}
372
373async function getTokenIsRequired() {
374 const envOverride = {
375 npm_config_registry: getCorrectRegistry()
376 };
377 let json = jsonParse((await spawn__default.default("npm", [ "profile", "get", "--json" ], {
378 env: Object.assign({}, process.env, envOverride)
379 })).stdout.toString());
380 return !(json.error || !json.tfa || !json.tfa.mode) && "auth-and-writes" === json.tfa.mode;
381}
382
383function getPackageInfo(packageJson) {
384 return npmRequestLimit((async () => {
385 logger.info("npm info " + packageJson.name);
386 let result = await spawn__default.default("npm", [ "info", packageJson.name, "--registry", getCorrectRegistry(packageJson), "--json" ]);
387 return "" === result.stdout.toString() ? {
388 error: {
389 code: "E404"
390 }
391 } : jsonParse(result.stdout.toString());
392 }));
393}
394
395async function infoAllow404(packageJson) {
396 var _pkgInfo$error;
397 let pkgInfo = await getPackageInfo(packageJson);
398 if ("E404" === (null === (_pkgInfo$error = pkgInfo.error) || void 0 === _pkgInfo$error ? void 0 : _pkgInfo$error.code)) return logger.warn("Received 404 for npm info " + chalk__default.default.cyan(`"${packageJson.name}"`)),
399 {
400 published: !1,
401 pkgInfo: {}
402 };
403 if (pkgInfo.error) throw logger.error(`Received an unknown error code: ${pkgInfo.error.code} for npm info ${chalk__default.default.cyan(`"${packageJson.name}"`)}`),
404 logger.error(pkgInfo.error.summary), pkgInfo.error.detail && logger.error(pkgInfo.error.detail),
405 new errors.ExitError(1);
406 return {
407 published: !0,
408 pkgInfo: pkgInfo
409 };
410}
411
412let otpAskLimit = pLimit__default.default(1), askForOtpCode = twoFactorState => otpAskLimit((async () => {
413 if (null !== twoFactorState.token) return twoFactorState.token;
414 logger.info("This operation requires a one-time password from your authenticator.");
415 let val = await askQuestion("Enter one-time password:");
416 return twoFactorState.token = val, val;
417})), getOtpCode = async twoFactorState => null !== twoFactorState.token ? twoFactorState.token : askForOtpCode(twoFactorState);
418
419async function internalPublish(pkgName, opts, twoFactorState) {
420 let publishTool = await getPublishTool(opts.cwd), publishFlags = opts.access ? [ "--access", opts.access ] : [];
421 if (publishFlags.push("--tag", opts.tag), await twoFactorState.isRequired && !isCI) {
422 let otpCode = await getOtpCode(twoFactorState);
423 publishFlags.push("--otp", otpCode);
424 }
425 "pnpm" === publishTool.name && publishTool.shouldAddNoGitChecks && publishFlags.push("--no-git-checks");
426 const envOverride = {
427 npm_config_registry: getCorrectRegistry()
428 };
429 let {stdout: stdout} = await spawn__default.default(publishTool.name, [ "publish", opts.cwd, "--json", ...publishFlags ], {
430 env: Object.assign({}, process.env, envOverride)
431 }), json = jsonParse(stdout.toString().replace(/[^{]*/, ""));
432 return json.error ? ("EOTP" === json.error.code || "E401" === json.error.code && json.error.detail.includes("--otp=<code>")) && !isCI ? (null !== twoFactorState.token && (twoFactorState.token = null),
433 twoFactorState.isRequired = Promise.resolve(!0), internalPublish(pkgName, opts, twoFactorState)) : (logger.error(`an error occurred while publishing ${pkgName}: ${json.error.code}`, json.error.summary, json.error.detail ? "\n" + json.error.detail : ""),
434 {
435 published: !1
436 }) : {
437 published: !0
438 };
439}
440
441function publish(pkgName, opts, twoFactorState) {
442 return npmRequestLimit((() => npmPublishLimit((() => internalPublish(pkgName, opts, twoFactorState)))));
443}
444
445function getReleaseTag(pkgInfo, preState, tag) {
446 return tag || (void 0 !== preState && "only-pre" !== pkgInfo.publishedState ? preState.tag : "latest");
447}
448
449const isCustomRegistry = registry => !!registry && "https://registry.npmjs.org" !== registry && "https://registry.yarnpkg.com" !== registry, getTwoFactorState = ({otp: otp, publicPackages: publicPackages}) => otp ? {
450 token: otp,
451 isRequired: Promise.resolve(!0)
452} : isCI || publicPackages.some((pkg => {
453 var _pkg$packageJson$publ;
454 return isCustomRegistry(null === (_pkg$packageJson$publ = pkg.packageJson.publishConfig) || void 0 === _pkg$packageJson$publ ? void 0 : _pkg$packageJson$publ.registry);
455})) || isCustomRegistry(process.env.npm_config_registry) ? {
456 token: null,
457 isRequired: Promise.resolve(!1)
458} : {
459 token: null,
460 isRequired: getTokenIsRequired()
461};
462
463async function publishPackages({packages: packages, access: access, otp: otp, preState: preState, tag: tag}) {
464 const packagesByName = new Map(packages.map((x => [ x.packageJson.name, x ]))), publicPackages = packages.filter((pkg => !pkg.packageJson.private)), twoFactorState = getTwoFactorState({
465 otp: otp,
466 publicPackages: publicPackages
467 }), unpublishedPackagesInfo = await getUnpublishedPackages(publicPackages, preState);
468 return 0 === unpublishedPackagesInfo.length && logger.warn("No unpublished packages to publish"),
469 Promise.all(unpublishedPackagesInfo.map((pkgInfo => publishAPackage(packagesByName.get(pkgInfo.name), access, twoFactorState, getReleaseTag(pkgInfo, preState, tag)))));
470}
471
472async function publishAPackage(pkg, access, twoFactorState, tag) {
473 const {name: name, version: version, publishConfig: publishConfig} = pkg.packageJson, localAccess = null == publishConfig ? void 0 : publishConfig.access;
474 logger.info(`Publishing ${chalk__default.default.cyan(`"${name}"`)} at ${chalk__default.default.green(`"${version}"`)}`);
475 const publishDir = (null == publishConfig ? void 0 : publishConfig.directory) ? path.join(pkg.dir, publishConfig.directory) : pkg.dir;
476 return {
477 name: name,
478 newVersion: version,
479 published: (await publish(name, {
480 cwd: publishDir,
481 access: localAccess || access,
482 tag: tag
483 }, twoFactorState)).published
484 };
485}
486
487async function getUnpublishedPackages(packages, preState) {
488 const results = await Promise.all(packages.map((async ({packageJson: packageJson}) => {
489 const response = await infoAllow404(packageJson);
490 let publishedState = "never";
491 return response.published && (publishedState = "published", void 0 !== preState && response.pkgInfo.versions && response.pkgInfo.versions.every((version => semver__default.default.parse(version).prerelease[0] === preState.tag)) && (publishedState = "only-pre")),
492 {
493 name: packageJson.name,
494 localVersion: packageJson.version,
495 publishedState: publishedState,
496 publishedVersions: response.pkgInfo.versions || []
497 };
498 }))), packagesToPublish = [];
499 for (const pkgInfo of results) {
500 const {name: name, publishedState: publishedState, localVersion: localVersion, publishedVersions: publishedVersions} = pkgInfo;
501 publishedVersions.includes(localVersion) ? logger.warn(`${name} is not being published because version ${localVersion} is already published on npm`) : (packagesToPublish.push(pkgInfo),
502 logger.info(`${name} is being published because our local version (${localVersion}) has not been published on npm`),
503 void 0 !== preState && "only-pre" === publishedState && logger.info(`${name} is being published to ${chalk__default.default.cyan("latest")} rather than ${chalk__default.default.cyan(preState.tag)} because there has not been a regular release of it yet`));
504 }
505 return packagesToPublish;
506}
507
508function logReleases(pkgs) {
509 const mappedPkgs = pkgs.map((p => `${p.name}@${p.newVersion}`)).join("\n");
510 logger.log(mappedPkgs);
511}
512
513let importantSeparator$1 = chalk__default.default.red("===============================IMPORTANT!==============================="), importantEnd$1 = chalk__default.default.red("----------------------------------------------------------------------");
514
515function showNonLatestTagWarning(tag, preState) {
516 logger.warn(importantSeparator$1), preState ? logger.warn(`You are in prerelease mode so packages will be published to the ${chalk__default.default.cyan(preState.tag)}\n dist tag except for packages that have not had normal releases which will be published to ${chalk__default.default.cyan("latest")}`) : "latest" !== tag && logger.warn(`Packages will be released under the ${tag} tag`),
517 logger.warn(importantEnd$1);
518}
519
520async function run(cwd, {otp: otp, tag: tag}, config) {
521 const releaseTag = tag && tag.length > 0 ? tag : void 0;
522 let preState = await pre$1.readPreState(cwd);
523 if (releaseTag && preState && "pre" === preState.mode) throw logger.error("Releasing under custom tag is not allowed in pre mode"),
524 logger.log("To resolve this exit the pre mode by running `changeset pre exit`"),
525 new errors.ExitError(1);
526 (releaseTag || preState) && showNonLatestTagWarning(tag, preState);
527 const {packages: packages, tool: tool} = await getPackages.getPackages(cwd), response = await publishPackages({
528 packages: packages,
529 access: config.access,
530 otp: otp,
531 preState: preState,
532 tag: releaseTag
533 }), successful = response.filter((p => p.published)), unsuccessful = response.filter((p => !p.published));
534 if (successful.length > 0) if (logger.success("packages published successfully:"),
535 logReleases(successful), logger.log(`Creating git tag${successful.length > 1 ? "s" : ""}...`),
536 "root" !== tool) for (const pkg of successful) {
537 const tag = `${pkg.name}@${pkg.newVersion}`;
538 logger.log("New tag: ", tag), await git.tag(tag, cwd);
539 } else {
540 const tag = "v" + successful[0].newVersion;
541 logger.log("New tag: ", tag), await git.tag(tag, cwd);
542 }
543 if (unsuccessful.length > 0) throw logger.error("packages failed to publish:"),
544 logReleases(unsuccessful), new errors.ExitError(1);
545}
546
547async function getStatus(cwd, {sinceMaster: sinceMaster, since: since, verbose: verbose, output: output}, config) {
548 sinceMaster && (logger.warn("--sinceMaster is deprecated and will be removed in a future major version"),
549 logger.warn("Use --since=master instead"));
550 const sinceBranch = void 0 === since ? sinceMaster ? "master" : void 0 : since, releasePlan = await getReleasePlan__default.default(cwd, sinceBranch, config), {changesets: changesets, releases: releases} = releasePlan;
551 if ((await git.getChangedPackagesSinceRef({
552 cwd: cwd,
553 ref: sinceBranch || config.baseBranch
554 })).length > 0 && 0 === changesets.length && (logger.error("Some packages have been changed but no changesets were found. Run `changeset add` to resolve this error."),
555 logger.error("If this change doesn't need a release, run `changeset add --empty`."),
556 process.exit(1)), output) return void await fs__default.default.writeFile(path__default.default.join(cwd, output), JSON.stringify(releasePlan, void 0, 2));
557 const print = verbose ? verbosePrint : SimplePrint;
558 return print("patch", releases), logger.log("---"), print("minor", releases), logger.log("---"),
559 print("major", releases), releasePlan;
560}
561
562function SimplePrint(type, releases) {
563 const packages = releases.filter((r => r.type === type));
564 if (packages.length) {
565 logger.info(chalk__default.default`Packages to be bumped at {green ${type}}:\n`);
566 const pkgs = packages.map((({name: name}) => "- " + name)).join("\n");
567 logger.log(chalk__default.default.green(pkgs));
568 } else logger.info(chalk__default.default`{red NO} packages to be bumped at {green ${type}}`);
569}
570
571function verbosePrint(type, releases) {
572 const packages = releases.filter((r => r.type === type));
573 if (packages.length) {
574 logger.info(chalk__default.default`Packages to be bumped at {green ${type}}`);
575 const columns = packages.map((({name: name, newVersion: version, changesets: changesets}) => [ chalk__default.default.green(name), version, changesets.map((c => chalk__default.default.blue(` .changeset/${c}/changes.md`))).join(" +") ])), t1 = table__default.default([ {
576 value: "Package Name",
577 width: 20
578 }, {
579 value: "New Version",
580 width: 20
581 }, {
582 value: "Related Changeset Summaries",
583 width: 70
584 } ], columns, {
585 paddingLeft: 1,
586 paddingRight: 0,
587 headerAlign: "center",
588 align: "left"
589 });
590 logger.log(t1.render() + "\n");
591 } else logger.info(chalk__default.default`Running release would release {red NO} packages as a {green ${type}}`);
592}
593
594async function pre(cwd, options) {
595 if ("enter" === options.command) try {
596 await pre$1.enterPre(cwd, options.tag), logger.success("Entered pre mode with tag " + chalk__default.default.cyan(options.tag)),
597 logger.info("Run `changeset version` to version packages with prerelease versions");
598 } catch (err) {
599 if (err instanceof errors.PreEnterButInPreModeError) throw logger.error("`changeset pre enter` cannot be run when in pre mode"),
600 logger.info("If you're trying to exit pre mode, run `changeset pre exit`"), new errors.ExitError(1);
601 throw err;
602 } else try {
603 await pre$1.exitPre(cwd), logger.success("Exited pre mode"), logger.info("Run `changeset version` to version packages with normal versions");
604 } catch (err) {
605 if (err instanceof errors.PreExitButNotInPreModeError) throw logger.error("`changeset pre exit` can only be run when in pre mode"),
606 logger.info("If you're trying to enter pre mode, run `changeset pre enter`"), new errors.ExitError(1);
607 throw err;
608 }
609}
610
611async function run$1(cwd) {
612 const {packages: packages, tool: tool} = await getPackages.getPackages(cwd), allExistingTags = await git.getAllTags(cwd);
613 for (const pkg of packages) {
614 const tag = "root" !== tool ? `${pkg.packageJson.name}@${pkg.packageJson.version}` : "v" + pkg.packageJson.version;
615 allExistingTags.has(tag) ? logger.log("Skipping tag (already exists): ", tag) : (logger.log("New tag: ", tag),
616 await git.tag(tag, cwd));
617 }
618}
619
620async function run$2(input, flags, cwd) {
621 if ("init" === input[0]) return void await init(cwd);
622 if (!fs__default.default.existsSync(path__default.default.resolve(cwd, ".changeset"))) throw logger.error("There is no .changeset folder. "),
623 logger.error("If this is the first time `changesets` have been used in this project, run `yarn changeset init` to get set up."),
624 logger.error("If you expected there to be changesets, you should check git history for when the folder was removed to ensure you do not lose any configuration."),
625 new errors.ExitError(1);
626 const packages = await getPackages.getPackages(cwd);
627 let config$1;
628 try {
629 config$1 = await config.read(cwd, packages);
630 } catch (e) {
631 throw await fs__default.default.pathExists(path__default.default.resolve(cwd, ".changeset/config.js")) ? (logger.error("It looks like you're using the version 1 `.changeset/config.js` file"),
632 logger.error("You'll need to convert it to a `.changeset/config.json` file"), logger.error("The format of the config object has significantly changed in v2 as well"),
633 logger.error(" - we thoroughly recommend looking at the changelog for this package for what has changed"),
634 new errors.ExitError(1)) : e;
635 }
636 if (input.length < 1) {
637 const {empty: empty, open: open} = flags;
638 await add(cwd, {
639 empty: empty,
640 open: open
641 }, config$1);
642 } else if ("pre" !== input[0] && input.length > 1) logger.error("Too many arguments passed to changesets - we only accept the command name as an argument"); else {
643 const {sinceMaster: sinceMaster, since: since, verbose: verbose, output: output, otp: otp, empty: empty, ignore: ignore, snapshot: snapshot, tag: tag, open: open} = flags;
644 switch ([ "updateChangelog", "isPublic", "skipCI", "commit" ].forEach((flag => {
645 if (flags[flag]) throw logger.error(`the flag ${flag} has been removed from changesets for version 2`),
646 logger.error("Please encode the desired value into your config"), logger.error("See our changelog for more details"),
647 new errors.ExitError(1);
648 })), input[0]) {
649 case "add":
650 return void await add(cwd, {
651 empty: empty,
652 open: open
653 }, config$1);
654
655 case "version":
656 {
657 let ignoreArrayFromCmd;
658 ignoreArrayFromCmd = "string" == typeof ignore ? [ ignore ] : ignore;
659 let pkgNames = new Set(packages.packages.map((({packageJson: packageJson}) => packageJson.name)));
660 const messages = [];
661 for (const pkgName of ignoreArrayFromCmd || []) pkgNames.has(pkgName) || messages.push(`The package "${pkgName}" is passed to the \`--ignore\` option but it is not found in the project. You may have misspelled the package name.`);
662 config$1.ignore.length > 0 && ignoreArrayFromCmd ? messages.push("It looks like you are trying to use the `--ignore` option while ignore is defined in the config file. This is currently not allowed, you can only use one of them at a time.") : ignoreArrayFromCmd && (config$1.ignore = ignoreArrayFromCmd);
663 const dependentsGraph = getDependentsGraph.getDependentsGraph(packages, {
664 bumpVersionsWithWorkspaceProtocolOnly: config$1.bumpVersionsWithWorkspaceProtocolOnly
665 });
666 for (const ignoredPackage of config$1.ignore) {
667 const dependents = dependentsGraph.get(ignoredPackage) || [];
668 for (const dependent of dependents) config$1.ignore.includes(dependent) || messages.push(`The package "${dependent}" depends on the ignored package "${ignoredPackage}", but "${dependent}" is not being ignored. Please pass "${dependent}" to the \`--ignore\` flag.`);
669 }
670 if (messages.length > 0) throw logger.error(messages.join("\n")), new errors.ExitError(1);
671 return void await version(cwd, {
672 snapshot: snapshot
673 }, config$1);
674 }
675
676 case "publish":
677 return void await run(cwd, {
678 otp: otp,
679 tag: tag
680 }, config$1);
681
682 case "status":
683 return void await getStatus(cwd, {
684 sinceMaster: sinceMaster,
685 since: since,
686 verbose: verbose,
687 output: output
688 }, config$1);
689
690 case "tag":
691 return void await run$1(cwd);
692
693 case "pre":
694 {
695 let command = input[1];
696 if ("enter" !== command && "exit" !== command) throw logger.error("`enter`, `exit` or `snapshot` must be passed after prerelease"),
697 new errors.ExitError(1);
698 let tag = input[2];
699 if ("enter" === command && "string" != typeof tag) throw logger.error("A tag must be passed when using prerelese enter"),
700 new errors.ExitError(1);
701 return void await pre(cwd, {
702 command: command,
703 tag: tag
704 });
705 }
706
707 case "bump":
708 throw logger.error('In version 2 of changesets, "bump" has been renamed to "version" - see our changelog for an explanation'),
709 logger.error("To fix this, use `changeset version` instead, and update any scripts that use changesets"),
710 new errors.ExitError(1);
711
712 case "release":
713 throw logger.error('In version 2 of changesets, "release" has been renamed to "publish" - see our changelog for an explanation'),
714 logger.error("To fix this, use `changeset publish` instead, and update any scripts that use changesets"),
715 new errors.ExitError(1);
716
717 default:
718 throw logger.error(`Invalid command ${input[0]} was provided`), new errors.ExitError(1);
719 }
720 }
721}
722
723const {input: input, flags: flags} = meow__default.default("\n Usage\n $ changesets [command]\n Commands\n init\n add [--empty] [--open]\n version [--ignore]\n publish [--otp=code]\n status [--since <branch>] [--verbose] [--output=JSON_FILE.json]\n pre <enter|exit> <tag>\n tag\n ", {
724 flags: {
725 sinceMaster: {
726 type: "boolean"
727 },
728 verbose: {
729 type: "boolean",
730 alias: "v"
731 },
732 output: {
733 type: "string",
734 alias: "o"
735 },
736 otp: {
737 type: "string"
738 },
739 empty: {
740 type: "boolean"
741 },
742 since: {
743 type: "string"
744 },
745 ignore: {
746 type: "string",
747 isMultiple: !0
748 },
749 tag: {
750 type: "string"
751 },
752 open: {
753 type: "boolean"
754 }
755 }
756}), cwd = process.cwd();
757
758run$2(input, flags, cwd).catch((err => {
759 if (err instanceof errors.InternalError && (logger.error("The following error is an internal unexpected error, these should never happen."),
760 logger.error("Please open an issue with the following link"), logger.error(`https://github.com/atlassian/changesets/issues/new?title=${encodeURIComponent(`Unexpected error during ${input[0] || "add"} command`)}&body=${encodeURIComponent(`## Error\n\n\`\`\`\n${util.format("", err).replace(process.cwd(), "<cwd>")}\n\`\`\`\n\n## Versions\n\n- @changesets/cli@${require("@changesets/cli/package.json").version}\n- node@${process.version}\n\n## Extra details\n\n\x3c!-- Add any extra details of what you were doing, ideas you have about what might have caused the error and reproduction steps if possible. If you have a repository we can look at that would be great. 😁 --\x3e\n`)}`)),
761 err instanceof errors.ExitError) return process.exit(err.code);
762 logger.error(err), process.exit(1);
763}));