@unconfig/changeset-config
Version:
🚀 The package offer changeset-config for @unconfig!
346 lines (313 loc) • 12.8 kB
JavaScript
;Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }// src/changelog-generate.ts
var _fs = require('fs');
var _assemblereleaseplan = require('@changesets/assemble-release-plan'); var _assemblereleaseplan2 = _interopRequireDefault(_assemblereleaseplan);
var _config = require('@changesets/config');
var _pre = require('@changesets/pre');
var _read = require('@changesets/read'); var _read2 = _interopRequireDefault(_read);
var _getpackages = require('@manypkg/get-packages');
var _meta = require('@unconfig/meta');
function getReleaseSummary(changesets, release) {
const formattedChangesets = release.changesets.map((changeset) => {
const { summary = "" } = _nullishCoalesce(changesets.find((cs) => cs.id === changeset), () => ( {}));
const changes = summary.split("\n");
return changes.map(
(change) => !change || _optionalChain([change, 'optionalAccess', _ => _.trim, 'call', _2 => _2(), 'access', _3 => _3.startsWith, 'call', _4 => _4("-")]) ? change : `- ${change}
`
).join("");
});
const displayName = `**${release.name}** \`v${release.newVersion}\``;
return {
...release,
changesets: formattedChangesets,
displayName: displayName.replace(/,\s*$/, "")
};
}
async function getChangesetEntries(options) {
const {
packages: changelogPackges,
ignorePackages: ignoreChangelogPackages,
cwd
} = options;
const packages = await _getpackages.getPackages.call(void 0, cwd);
const preState = await _pre.readPreState.call(void 0, cwd);
const config = await _config.read.call(void 0, cwd, packages);
const changesets = await _read2.default.call(void 0, cwd);
const releasePlan = _assemblereleaseplan2.default.call(void 0,
changesets,
packages,
config,
preState
);
const releases = releasePlan.releases.filter((release) => release.changesets.length > 0).filter((release) => !ignoreChangelogPackages.includes(release.name)).map((release) => getReleaseSummary(releasePlan.changesets, release)).sort((a, b) => {
if (changelogPackges.includes(a.name)) return -1;
if (changelogPackges.includes(b.name)) return 1;
return a.name < b.name ? -1 : 1;
});
return releases;
}
async function changesetsChangelogGenerate(options) {
const {
packages,
ignorePackages = [],
cwd,
projectChangelogTempPath = _meta.PROJECT_CHANGELOG_TEMP_FILE
} = options;
if (!cwd) return;
const releases = await getChangesetEntries({
packages,
ignorePackages,
cwd
});
if (!releases.length) return;
const content = JSON.parse(_fs.readFileSync.call(void 0, `${cwd}/${projectChangelogTempPath}`).toString()) || {};
releases.forEach(({ displayName, changesets }) => {
const prevState = content[displayName] || [];
content[displayName] = [.../* @__PURE__ */ new Set([...prevState, ...changesets])];
});
_fs.writeFileSync.call(void 0, `${cwd}/${projectChangelogTempPath}`, JSON.stringify(content));
}
// src/changelog-write.ts
var _prettier = require('prettier'); var _prettier2 = _interopRequireDefault(_prettier);
function getCurrentDate() {
const date = /* @__PURE__ */ new Date();
const day = date.getDate().toString().padStart(2, "0");
const month = (date.getMonth() + 1).toString().padStart(2, "0");
const year = date.getFullYear();
return [
`## ${day}-${month}-${year}`,
"\n\n",
`### ${(/* @__PURE__ */ new Date()).toLocaleTimeString()}`
].join("");
}
async function getContent(releases, prettierConfig) {
const releaseEntries = Object.entries(releases).map((release) => {
const [displayName, changesets] = release;
return [displayName, "\n\n", ...changesets].join("");
});
let content = [getCurrentDate(), ...releaseEntries].join("\n");
content = await _prettier2.default.format(content, prettierConfig);
return content;
}
async function changesetsChangelogWrite(options) {
const {
projectChangelogPath = _meta.PROJECT_CHANGELOG_FILE,
projectChangelogTempPath = _meta.PROJECT_CHANGELOG_TEMP_FILE,
websiteChangelogPath = _meta.PROJECT_WEBSITE_CHANGELOG_FILE,
cwd,
prettierConfig = {
parser: "markdown",
singleQuote: true,
trailingComma: "es5"
}
} = options;
if (!cwd) return;
const releases = JSON.parse(
_fs.readFileSync.call(void 0, `${cwd}/${projectChangelogTempPath}`).toString()
);
if (!Object.entries(releases).length) return;
const content = await getContent(releases, prettierConfig);
const changelog = _fs.readFileSync.call(void 0, `${cwd}/${projectChangelogPath}`, "utf8");
const newChangelog = changelog.replace(
"<!-- CHANGELOG:INSERT -->",
`<!-- CHANGELOG:INSERT -->
${content}`
);
_fs.writeFileSync.call(void 0, `${cwd}/${projectChangelogPath}`, newChangelog);
_fs.writeFileSync.call(void 0,
`${cwd}/${websiteChangelogPath}`,
newChangelog.replace("<!-- CHANGELOG:INSERT -->\n\n", "")
);
_fs.writeFileSync.call(void 0, `${cwd}/${projectChangelogTempPath}`, "{}");
}
// src/generate-releases.ts
var _path = require('path');
var _child_process = require('child_process');
var _process = require('process'); var _process2 = _interopRequireDefault(_process);
var _core = require('@octokit/core');
var _semver = require('semver'); var _semver2 = _interopRequireDefault(_semver);
async function createRelease(octokit, {
pkg,
tagName,
repoName,
repoOwner,
projectChangelogPath
}) {
const changelogPath = _path.resolve.call(void 0, pkg.dir, projectChangelogPath);
const changelog = _fs.readFileSync.call(void 0, changelogPath, "utf8");
const changelogArr = changelog.split("\n");
const releaseNotes = [];
for (const line of changelogArr) {
if (/^#{3}\s/.test(line)) releaseNotes.push(line);
else if (/^#{1,3}\s/.test(line) && releaseNotes.length > 0) break;
else if (releaseNotes.length > 0) releaseNotes.push(line);
}
const prereleaseParts = _semver2.default.prerelease(tagName.replace(`${pkg.packageJson.name}@`, "")) || [];
try {
const params = {
owner: repoOwner,
repo: repoName,
name: tagName,
tag_name: tagName,
body: releaseNotes.join("\n"),
prerelease: prereleaseParts.length > 0
};
await octokit.request("POST /repos/{owner}/{repo}/releases", params);
} catch (error) {
console.warn(
"[octokit 'POST /repos/{owner}/{repo}/releases'] has error.",
error
);
}
}
function getReleasedPackages(csOutput, pkgs, pkgPrefix) {
const tagNameRegex = new RegExp(
// eslint-disable-next-line no-useless-escape
`(${pkgPrefix}/[^@]+)@([^s]+)`
);
return csOutput.split("\n").reduce((acc, line) => {
const newTagPkgContent = line.includes("New tag:") ? line.split("New tag:")[1].trim() : "";
if (!newTagPkgContent) return acc;
const match = newTagPkgContent.match(tagNameRegex);
if (match === null) return acc;
const tagName = [match[1], match[2]].join("@");
const pkg = pkgs.find((p) => _optionalChain([p, 'access', _5 => _5.packageJson, 'optionalAccess', _6 => _6.name]) === match[1]);
return [...acc, { tagName, pkg }];
}, []);
}
async function changesetsGenerateReleases(options) {
const {
repoName = _meta.REPO_NAME,
repoOwner = _meta.REPO_OWNER,
pkgPrefix = _meta.PKG_PREFIX,
projectChangelogPath = _meta.PROJECT_CHANGELOG_FILE,
cwd
} = options;
if (!cwd) return;
const env = _process2.default.env;
const octokit = new (0, _core.Octokit)({
auth: env.GITHUB_TOKEN
});
const publishCommandOutput = _child_process.execSync.call(void 0, "pnpm changeset publish").toString();
console.log(
`
\u{1F680}\u{1F680}\u{1F680} Run changesets publish and get stdout. \u{1F680}\u{1F680}\u{1F680}
${publishCommandOutput}
`
);
const gitPushCommand = `git pull && git add . && git diff --staged --quiet || git commit -m "docs: \u{1F4DD} add changelogs for $(git rev-parse --short HEAD) [skip ci]" && git push origin ${env.GITHUB_BRANCH} --follow-tags`;
const gitPushCommandOutput = _child_process.execSync.call(void 0, gitPushCommand).toString();
console.log(
`
\u{1F680}\u{1F680}\u{1F680} Push updated packages to github with tags. \u{1F680}\u{1F680}\u{1F680}
${gitPushCommandOutput}
`
);
const { packages: pkgs } = await _getpackages.getPackages.call(void 0, cwd);
const releasedPkgs = getReleasedPackages(
publishCommandOutput,
pkgs,
pkgPrefix
);
for (const pkg of releasedPkgs) {
await createRelease(octokit, {
...pkg,
repoName,
repoOwner,
projectChangelogPath
});
}
console.log(`\u{1F680}\u{1F680}\u{1F680} Create release for each published package. \u{1F680}\u{1F680}\u{1F680}`);
}
// src/manual-generate-prereleases.ts
var _inquirer = require('inquirer'); var _inquirer2 = _interopRequireDefault(_inquirer);
function updatePackageJson(pkgJsonPath, version) {
const pkgRaw = _fs.readFileSync.call(void 0, pkgJsonPath, { encoding: "utf-8" });
const stringified = pkgRaw.replace(
/("version".*?) (".*?")/i,
`$1 "${version}"`
);
_fs.writeFileSync.call(void 0, pkgJsonPath, stringified);
}
async function ignorePackage(pkgName, cwd, projectChangesetsPath) {
const changesetConfigPath = _path.resolve.call(void 0, cwd, projectChangesetsPath);
const rawConfig = _fs.readFileSync.call(void 0, changesetConfigPath, {
encoding: "utf-8"
});
const jsonConfig = JSON.parse(rawConfig);
const ignorePkgs = jsonConfig.ignore || [];
if (!ignorePkgs.includes(pkgName)) {
jsonConfig.ignore = [pkgName, ...ignorePkgs];
const stringified = JSON.stringify(jsonConfig, null, 2);
await _fs.writeFileSync.call(void 0, changesetConfigPath, stringified, { encoding: "utf-8" });
}
}
async function manualGeneratePrereleases(options) {
const {
npmRegistryUrl = _meta.NPM_REGISTRY_URL,
projectChangesetsPath = _meta.PROJECT_CHANGESETS_CONFIG_FILE,
cwd
} = options;
if (!cwd) return;
const { packages } = await _getpackages.getPackages.call(void 0, cwd);
const choices = packages.map(({ packageJson: packageJson2 }) => ({
name: `${packageJson2.name} (${packageJson2.version})`,
value: packageJson2.name
})).concat(new _inquirer2.default.Separator());
const { pkgName } = await _inquirer2.default.prompt([
{
pageSize: 12,
name: "pkgName",
message: "Which package to make a pre-release?",
type: "list",
choices
}
]);
const { packageJson, dir } = packages.find(
({ packageJson: packageJson2 }) => packageJson2.name === pkgName
);
const { version, name } = packageJson;
const prereleaseTag = _optionalChain([_semver2.default, 'access', _7 => _7.prerelease, 'call', _8 => _8(version), 'optionalAccess', _9 => _9[0]]);
const { tag, publish } = await _inquirer2.default.prompt([
{
name: "tag",
message: "Which tag should be used for the pre-release?",
type: "list",
choices: [
{
name: "alpha"
},
{
name: "beta"
}
],
default: prereleaseTag
},
{
name: "publish",
message: "Should the package be published?",
type: "confirm"
}
]);
const increase = prereleaseTag === tag ? "prerelease" : "preminor";
const newVersion = _semver2.default.inc(version, increase, tag);
await updatePackageJson(_path.resolve.call(void 0, dir, "package.json"), newVersion);
await ignorePackage(name, cwd, projectChangesetsPath);
if (publish) {
await _child_process.exec.call(void 0, `npm publish ${dir} --tag ${tag}`, (error, stdout, stderr) => {
if (!error) {
console.log(stdout);
console.log(
`${name}@${newVersion} published:
${npmRegistryUrl}/${name}
`
);
} else {
console.error(error);
console.error(stderr);
}
});
} else {
console.log(`Version for ${name} updated on package.json.`);
}
}
exports.changesetsChangelogGenerate = changesetsChangelogGenerate; exports.changesetsChangelogWrite = changesetsChangelogWrite; exports.changesetsGenerateReleases = changesetsGenerateReleases; exports.manualGeneratePrereleases = manualGeneratePrereleases;