@sanity/plugin-kit
7.0.28.0.0
dist/init-BDY7XRmJ.js+
dist/init-BDY7XRmJ.jsNew file+824
Index: package/dist/init-BDY7XRmJ.js
===================================================================
--- package/dist/init-BDY7XRmJ.js
+++ package/dist/init-BDY7XRmJ.js
@@ -0,0 +1,824 @@
+import { n as defaultOutDir } from "./constants-BLTUL_Wd.js";
+import { n as sharedFlags_default, t as log_default } from "./log-DgQL-Rv9.js";
+import { B as writeFileWithOverwritePrompt, H as promptForPackageName, L as readFile, M as copyFileWithOverwritePrompt, N as ensureDir, P as fileExists, R as readJsonFile, U as promptForRepoOrigin, V as prompt, a as getPackage, c as writePackageJsonDirect, f as errorToUndefined, i as forceDependencyVersions, l as resolveLatestVersions, m as forcedPackageVersions, n as addPackageJsonScripts, o as sortKeys, p as forcedDevPackageVersions, r as addScript, s as writePackageJson, t as addBuildScripts, z as writeFile } from "./package-BrKrShA_.js";
+import { n as name, r as version } from "./package-z3cLp2Jt.js";
+import chalk from "chalk";
+import path from "path";
+import outdent, { outdent as outdent$1 } from "outdent";
+import { fileURLToPath } from "url";
+import licenses from "@rexxars/choosealicense-list";
+import gitRemoteOriginUrl from "git-remote-origin-url";
+import { execSync } from "child_process";
+import { validate } from "email-validator";
+import xdgBasedir from "xdg-basedir";
+import { createRequester } from "get-it";
+function defaultSourceJs(pkg) {
+ return outdent`
+ import {definePlugin} from 'sanity'
+
+ /**
+ * Usage in sanity.config.js (or .ts)
+ *
+ * \`\`\`js
+ * import {defineConfig} from 'sanity'
+ * import {myPlugin} from '${pkg.name}'
+ *
+ * export default defineConfig({
+ * // ...
+ * plugins: [myPlugin({})],
+ * })
+ * \`\`\`
+ *
+ * @public
+ */
+ export const myPlugin = definePlugin((_config = {}) => {
+ // oxlint-disable-next-line no-console
+ console.log(\`hello from ${pkg.name}\`)
+ return {
+ name: '${pkg.name}',
+ }
+ })
+`.trimStart() + "\n";
+}
+function defaultSourceTs(pkg) {
+ return outdent`
+ import {definePlugin} from 'sanity'
+
+ interface MyPluginConfig {
+ /* nothing here yet */
+ }
+
+ /**
+ * Usage in \`sanity.config.ts\` (or .js)
+ *
+ * \`\`\`ts
+ * import {defineConfig} from 'sanity'
+ * import {myPlugin} from '${pkg.name}'
+ *
+ * export default defineConfig({
+ * // ...
+ * plugins: [myPlugin()],
+ * })
+ * \`\`\`
+ *
+ * @public
+ */
+ export const myPlugin = definePlugin<MyPluginConfig | void>((_config = {}) => {
+ // oxlint-disable-next-line no-console
+ console.log('hello from ${pkg.name}')
+ return {
+ name: '${pkg.name}',
+ }
+ })
+`.trimStart() + "\n";
+}
+function gitignoreTemplate() {
+ return {
+ type: "template",
+ to: ".gitignore",
+ value: outdent$1`
+ # Logs
+ logs
+ *.log
+ npm-debug.log*
+
+ # Runtime data
+ pids
+ *.pid
+ *.seed
+
+ # Directory for instrumented libs generated by jscoverage/JSCover
+ lib-cov
+
+ # Coverage directory used by tools like istanbul
+ coverage
+
+ # nyc test coverage
+ .nyc_output
+
+ # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
+ .grunt
+
+ # node-waf configuration
+ .lock-wscript
+
+ # Compiled binary addons (http://nodejs.org/api/addons.html)
+ build/Release
+
+ # Dependency directories
+ node_modules
+ jspm_packages
+
+ # Optional npm cache directory
+ .npm
+
+ # Optional REPL history
+ .node_repl_history
+
+ # macOS finder cache file
+ .DS_Store
+
+ # VS Code settings
+ .vscode
+
+ # IntelliJ
+ .idea
+ *.iml
+
+ # Cache
+ .cache
+
+ # Yalc
+ .yalc
+ yalc.lock
+
+ # npm package zips
+ *.tgz
+ `
+ };
+}
+function oxfmtConfigTemplate(options) {
+ let { flags } = options;
+ return {
+ type: "template",
+ force: flags.force,
+ to: "oxfmt.config.ts",
+ value: "export {default} from '@sanity/plugin-kit/oxfmt'"
+ };
+}
+function oxlintConfigTemplate(options) {
+ let { flags } = options;
+ return {
+ type: "template",
+ force: flags.force,
+ to: "oxlint.config.ts",
+ value: "export {default} from '@sanity/plugin-kit/oxlint'"
+ };
+}
+function pkgConfigTemplate(options) {
+ let { flags, outDir } = options;
+ return {
+ type: "template",
+ force: flags.force,
+ to: "package.config.ts",
+ value: outdent$1`
+ import {defineConfig} from '@sanity/pkg-utils'
+
+ export default defineConfig({
+ dist: '${outDir}',
+ tsconfig: 'tsconfig.${outDir}.json',
+
+ // Remove this block to enable strict export validation
+ extract: {
+ rules: {
+ 'ae-incompatible-release-tags': 'off',
+ 'ae-internal-missing-underscore': 'off',
+ 'ae-missing-release-tag': 'off',
+ },
+ },
+ })
+ `
+ };
+}
+function tsconfigTemplate(options) {
+ let { flags } = options;
+ return {
+ type: "template",
+ force: flags.force,
+ to: "tsconfig.json",
+ value: outdent$1`
+ {
+ "extends": "./tsconfig.settings",
+ "include": ["./src", "./package.config.ts"]
+ }
+ `
+ };
+}
+function tsconfigTemplateDist(options) {
+ let { flags, outDir } = options;
+ return {
+ type: "template",
+ force: flags.force,
+ to: `tsconfig.${outDir}.json`,
+ value: outdent$1`
+ {
+ "extends": "./tsconfig.settings",
+ "include": ["./src"],
+ "exclude": [
+ "./src/**/__fixtures__",
+ "./src/**/__mocks__",
+ "./src/**/*.test.ts",
+ "./src/**/*.test.tsx"
+ ]
+ }
+ `
+ };
+}
+function tsconfigTemplateSettings(options) {
+ let { flags, outDir } = options;
+ return {
+ type: "template",
+ force: flags.force,
+ to: "tsconfig.settings.json",
+ value: outdent$1`
+ {
+ "compilerOptions": {
+ "rootDir": ".",
+ "outDir": "./${outDir}",
+
+ "target": "esnext",
+ "jsx": "preserve",
+ "module": "preserve",
+ "moduleResolution": "bundler",
+ "esModuleInterop": true,
+ "resolveJsonModule": true,
+ "moduleDetection": "force",
+ "strict": true,
+ "allowSyntheticDefaultImports": true,
+ "skipLibCheck": true,
+ "forceConsistentCasingInFileNames": true,
+ "isolatedModules": true,
+
+ // Don't emit by default, pkg-utils will ignore this when generating .d.ts files
+ "noEmit": true
+ }
+ }
+ `
+ };
+}
+const renovatePreset = {
+ name: "renovatebot",
+ description: "Files to enable renovatebot.",
+ apply: applyPreset$2
+};
+async function applyPreset$2(options) {
+ await writeAssets([{
+ type: "copy",
+ from: ["renovatebot", "renovate.json"],
+ to: "renovate.json"
+ }], options);
+}
+function generateReadme(data) {
+ let { user, pluginName, license } = data;
+ return outdent`
+ # ${pluginName}
+
+
+ ${installationSnippet(pluginName ?? "unknown")}
+
+ ## Usage
+
+ Add it as a plugin in \`sanity.config.ts\` (or .js):
+
+ \`\`\`ts
+ import {defineConfig} from 'sanity'
+ import {myPlugin} from '${pluginName}'
+
+ export default defineConfig({
+ //...
+ plugins: [myPlugin({})],
+ })
+ \`\`\`
+
+ ${getLicenseText(license?.id, user?.name ? user : void 0)}
+ ${developTestSnippet()}
+ ` + "\n";
+}
+function installationSnippet(packageName) {
+ return outdent`
+ ## Installation
+
+ \`\`\`sh
+ npm install ${packageName}
+ \`\`\`
+ `;
+}
+function developTestSnippet() {
+ return outdent`
+ ## Develop & test
+
+ This plugin uses [@sanity/plugin-kit](https://github.com/sanity-io/plugin-kit)
+ with default configuration for build & watch scripts.
+
+ See [Testing a plugin in Sanity Studio](https://github.com/sanity-io/plugin-kit#testing-a-plugin-in-sanity-studio)
+ on how to run this plugin with hotreload in the studio.
+ `;
+}
+function getLicenseText(licenseId, user) {
+ if (!licenseId) return "";
+ let license = licenses.find(licenseId), licenseName = license ? license.title : void 0;
+ licenseName = licenseName?.replace(/\s+license$/i, "");
+ let licenseText = "## License\n";
+ return licenseText = licenseName && user?.name ? `${licenseText}\n[${licenseName}](LICENSE) © ${user?.name}\n` : licenseName ? `${licenseText}\n[${licenseName}](LICENSE)\n` : `${licenseText}\nSee [LICENSE](LICENSE)`, licenseText;
+}
+function isDefaultGitHubReadme(readme) {
+ if (!readme) return !1;
+ let lines = readme.split("\n", 20).filter(Boolean);
+ return lines.length <= 2 && lines[0].startsWith("#");
+}
+const requester = createRequester({
+ headers: { "User-Agent": `${name}@${version}` },
+ as: "json"
+});
+async function getUserInfo({ requireUserConfirmation, flags }, pkg) {
+ let userInfo = getPackageUserInfo({ author: flags.author ?? pkg?.author }) || await getSanityUserInfo() || await getGitUserInfo();
+ return requireUserConfirmation ? promptForInfo(userInfo) : userInfo;
+}
+function getPackageUserInfo(pkg) {
+ let author = pkg?.author;
+ if (!author) return;
+ if (author && typeof author != "string") return author;
+ if (!author.includes("@")) return { name: author };
+ let [pre, ...post] = author.replace(/[<>[\]]/g, "").split(/@/), nameParts = pre.split(/\s+/), email = [nameParts[nameParts.length - 1], ...post].join("@");
+ return {
+ name: nameParts.slice(0, -1).join(" "),
+ email
+ };
+}
+async function promptForInfo(defValue) {
+ return {
+ name: await prompt("Author name", {
+ filter: filterString,
+ default: defValue && defValue.name,
+ validate: requiredString
+ }),
+ email: await prompt("Author email", {
+ filter: filterString,
+ default: defValue && defValue.email,
+ validate: validOrEmptyEmail
+ })
+ };
+}
+async function getSanityUserInfo() {
+ try {
+ let token = (await readJsonFile(path.join(xdgBasedir.config ?? "", "sanity", "config.json")))?.authToken;
+ if (!token) return;
+ let { body: user } = await requester({
+ url: "https://api.sanity.io/v1/users/me",
+ as: "json",
+ headers: { Authorization: `Bearer ${token}` }
+ });
+ if (!user) return;
+ let { name, email } = user;
+ return {
+ name,
+ email
+ };
+ } catch {
+ return;
+ }
+}
+async function getGitUserInfo() {
+ try {
+ let name = execSync("git config user.name", { encoding: "utf8" }).trim(), email = execSync("git config user.email", { encoding: "utf8" }).trim();
+ return name ? {
+ name,
+ email: email || void 0
+ } : void 0;
+ } catch {
+ return;
+ }
+}
+function filterString(val) {
+ return (val || "").trim();
+}
+function requiredString(value) {
+ return value.length > 1 || "Required";
+}
+function validOrEmptyEmail(value) {
+ return value ? validate(value) ? !0 : "Must either be a valid email or empty" : !0;
+}
+const semverWorkflowPreset = {
+ name: "semver-workflow",
+ description: "Files and dependencies for conventional-commits, github workflow and semantic-release.",
+ apply: applyPreset$1
+}, info = (write, msg, ...args) => write && log_default.info(msg, ...args);
+async function applyPreset$1(options) {
+ await writeAssets(semverWorkflowFiles(), options), await addPrepareScript(options), await addDevDependencies$1(options), await updateReadme(options);
+}
+async function addPrepareScript(options) {
+ let didWrite = await addPackageJsonScripts(await getPackage(options), options, (scripts) => (scripts.prepare = addScript("husky", scripts.prepare), scripts));
+ info(didWrite, "Added prepare script to package.json");
+}
+async function addDevDependencies$1(options) {
+ let pkg = await getPackage(options), devDeps = sortKeys({
+ ...pkg.devDependencies,
+ ...await semverWorkflowDependencies()
+ }), newPkg = { ...pkg };
+ newPkg.devDependencies = devDeps, await writePackageJsonDirect(newPkg, options), log_default.info("Updated devDependencies."), log_default.info(chalk.green(outdent`
+ semantic-release preset injected.
+
+ Please confer
+ https://github.com/sanity-io/plugin-kit/blob/main/docs/semver-workflow.md#manual-steps-after-inject
+ to finalize configuration for this preset.
+ `.trim()));
+}
+async function updateReadme(options) {
+ let { basePath } = options, readmePath = path.join(basePath, "README.md"), readme = await readFile(readmePath, "utf8").catch(errorToUndefined) ?? "", { install, usage, developTest, license, releaseSnippet } = await readmeSnippets(options), prependSections = missingSections(readme, [install, usage]), appendSections = missingSections(readme, [
+ license,
+ developTest,
+ releaseSnippet
+ ]);
+ (prependSections.length || appendSections.length) && (await writeFile(readmePath, [
+ ...prependSections,
+ readme,
+ ...appendSections
+ ].filter(Boolean).join("\n\n"), { encoding: "utf8" }), log_default.info("Updated README. Please review the changes."));
+}
+async function readmeSnippets(options) {
+ let pkg = await getPackage(options), user = await getUserInfo(options, pkg), bestEffortUrl = readmeBaseurl(pkg), install = installationSnippet(pkg.name ?? "unknown"), usage = outdent`
+ ## Usage
+ `, license = getLicenseText(typeof pkg.license == "string" ? pkg.license : void 0, user), releaseSnippet = outdent`
+ ### Release new version
+
+ Run ["CI & Release" workflow](${bestEffortUrl}/actions/workflows/main.yml).
+ Make sure to select the main branch and check "Release new version".
+
+ Semantic release will only release on configured branches, so it is safe to run release on any branch.
+ `;
+ return {
+ install,
+ usage,
+ license,
+ developTest: developTestSnippet(),
+ releaseSnippet
+ };
+}
+/**
+* Returns sections that do not exist "close enough" in readme
+*/
+function missingSections(readme, sections) {
+ return sections.filter((section) => !closeEnough(section, readme));
+}
+/**
+* a and b are considered "close enough" if > 50% of a lines exist in b lines
+* @param a
+* @param b
+*/
+function closeEnough(a, b) {
+ let aLines = a.split("\n"), bLines = b.split("\n");
+ return aLines.filter((line) => bLines.find((bLine) => bLine === line)).length >= aLines.length * .5;
+}
+function semverWorkflowFiles() {
+ return [
+ {
+ type: "copy",
+ from: [
+ ".github",
+ "workflows",
+ "main.yml"
+ ],
+ to: [
+ ".github",
+ "workflows",
+ "main.yml"
+ ]
+ },
+ {
+ type: "copy",
+ from: [".husky", "commit-msg"],
+ to: [".husky", "commit-msg"]
+ },
+ {
+ type: "copy",
+ from: [".husky", "pre-commit"],
+ to: [".husky", "pre-commit"]
+ },
+ {
+ type: "copy",
+ from: [".releaserc.json"],
+ to: ".releaserc.json"
+ },
+ {
+ type: "copy",
+ from: ["commitlint.template.js"],
+ to: "commitlint.config.js"
+ },
+ {
+ type: "copy",
+ from: ["lint-staged.template.js"],
+ to: "lint-staged.config.js"
+ }
+ ].map((fromTo) => fromTo.type === "copy" ? {
+ ...fromTo,
+ from: ["semver-workflow", ...fromTo.from]
+ } : fromTo);
+}
+async function semverWorkflowDependencies() {
+ return resolveLatestVersions([
+ "@commitlint/cli",
+ "@commitlint/config-conventional",
+ "@sanity/semantic-release-preset",
+ "husky",
+ "lint-staged"
+ ]);
+}
+function readmeBaseurl(pkg) {
+ return (pkg.repository?.url ?? pkg.homepage ?? "TODO").replace(/.+:\/\//g, "https://").replace(/\.git/g, "").replace(/[email protected]\//g, "github.com/").replace(/[email protected]:/g, "https://github.com/").replace(/#.+/g, "");
+}
+const ui = {
+ name: "ui",
+ description: "`@sanity/ui` and dependencies",
+ apply: applyPreset
+};
+async function applyPreset(options) {
+ await addDependencies(options), await addDevDependencies(options), log_default.info(chalk.green("ui preset injected"));
+}
+async function addDependencies(options) {
+ let pkg = await getPackage(options), newDeps = sortKeys(forceDependencyVersions({
+ ...pkg.dependencies,
+ ...await resolveDependencyList()
+ }, forcedPackageVersions)), newPkg = { ...pkg };
+ newPkg.dependencies = newDeps, await writePackageJsonDirect(newPkg, options), log_default.info("Updated dependencies.");
+}
+async function addDevDependencies(options) {
+ let pkg = await getPackage(options), newDeps = sortKeys(forceDependencyVersions({
+ ...pkg.devDependencies,
+ ...await resolveDevDependencyList()
+ }, forcedDevPackageVersions)), newPkg = { ...pkg };
+ newPkg.devDependencies = newDeps, await writePackageJsonDirect(newPkg, options), log_default.info("Updated devDependencies.");
+}
+async function resolveDependencyList() {
+ return resolveLatestVersions(["@sanity/icons", "@sanity/ui"]);
+}
+async function resolveDevDependencyList() {
+ return resolveLatestVersions([
+ "react",
+ "react-dom",
+ "styled-components"
+ ]);
+}
+const presets = [
+ semverWorkflowPreset,
+ renovatePreset,
+ ui
+], presetNames = presets.map((p) => p?.name);
+function presetHelpList(padStart) {
+ return presets.map((p) => `${"".padStart(padStart)}${p.name.padEnd(20)}${p.description}`).join("\n");
+}
+async function injectPresets(options) {
+ if (options.flags.presetOnly && !options.flags.preset?.length) throw Error("--preset-only, but no --preset [preset-name] was provided.");
+ let applyPresets = presetsFromInput(options.flags.preset);
+ for (let preset of applyPresets) await preset.apply(options);
+}
+function presetsFromInput(inputPresets) {
+ if (!inputPresets) return [];
+ let unknownPresets = inputPresets.filter((p) => !presetNames.includes(p));
+ if (unknownPresets.length) throw Error(`Unknown --preset(s): [${unknownPresets.join(", ")}]. Must be one of: [${presetNames.join(", ")}]`);
+ return inputPresets.filter(onlyUnique).map((presetName) => presets.find((p) => p.name === presetName)).filter((p) => !!p);
+}
+function onlyUnique(value, index, arr) {
+ return arr.indexOf(value) === index;
+}
+const bannedFields = [
+ "login",
+ "description",
+ "projecturl",
+ "email"
+], preferredLicenses = [
+ "MIT",
+ "ISC",
+ "BSD-3-Clause"
+], otherLicenses = Object.keys(licenses.list).filter((id) => {
+ let license = licenses.list[id];
+ return !preferredLicenses.includes(id) && !bannedFields.some((field) => license.body.includes(`[${field}]`));
+});
+async function inject(options) {
+ options.flags.presetOnly ? log_default.info("Only apply presets, skipping default inject.") : await injectBase(options), await injectPresets(options);
+}
+async function injectBase(options) {
+ let { basePath, flags, requireUserConfirmation } = options, info = (write, msg, ...args) => write && log_default.info(msg, ...args), pkg = await getPackage(options).catch(errorToUndefined);
+ log_default.debug("Plugin has package.json: %s", pkg ? "yes" : "no");
+ let user = await getUserInfo(options, pkg);
+ log_default.debug("User information: %o", user);
+ let pkgName = flags.name ?? pkg?.name, pluginName = requireUserConfirmation || !pkgName ? await promptForPackageName(options, pkgName) : pkgName;
+ log_default.debug("Plugin name: %s", pluginName);
+ let license = await getLicense(flags, {
+ user,
+ pluginName,
+ pkg,
+ requireUserConfirmation
+ }), licenseChanged = (pkg && pkg.license) !== (license && license.id);
+ log_default.debug("License: %s", license ? license.id : "<none>");
+ let description = await getProjectDescription(basePath, pkg, requireUserConfirmation);
+ log_default.debug("Description: %s", description || "<none>");
+ let repoUrl = flags.repo ?? (await gitRemoteOriginUrl(basePath).catch(errorToUndefined) || pkg?.repository?.url), gitOrigin = requireUserConfirmation ? await promptForRepoOrigin(options, repoUrl) : repoUrl;
+ log_default.debug("Remote origin: %s", gitOrigin || "<none>");
+ let data = {
+ user,
+ pluginName,
+ license,
+ description,
+ pkg,
+ gitOrigin
+ }, didWrite, newPkg = await writePackageJson(data, options);
+ info(newPkg !== pkg, "Wrote package.json"), data.pkg = newPkg, didWrite = await writeLicense(data, options, licenseChanged), info(didWrite, "Wrote license file (LICENSE)"), didWrite = await writeReadme(data, options), info(didWrite, "Wrote readme file (README.md)"), didWrite = await writeStaticAssets(options), info(didWrite.length > 0, "Wrote static asset files: %s", didWrite.join(", ")), didWrite = await addBuildScripts(newPkg, options), info(didWrite, "Added build scripts to package.json"), didWrite = await addCompileDirToGitIgnore(options), info(didWrite, "Added compilation output directory to .gitignore");
+}
+async function writeReadme(data, options) {
+ let { basePath } = options, readmePath = path.join(basePath, "README.md"), readme = await readFile(readmePath, "utf8").catch(errorToUndefined);
+ return readme && !isDefaultGitHubReadme(readme) ? !1 : (await writeFileWithOverwritePrompt(readmePath, generateReadme(data), {
+ encoding: "utf8",
+ force: options.flags.force
+ }), !0);
+}
+async function writeLicense({ license }, options, licenseChanged) {
+ let { basePath, flags } = options;
+ if (flags.license === !1 || !license) return !1;
+ let hasLicenseMdFile = await fileExists(path.join(basePath, "LICENSE.md"));
+ return await writeFileWithOverwritePrompt(path.join(basePath, hasLicenseMdFile ? "LICENSE.md" : "LICENSE"), license.text, {
+ encoding: "utf8",
+ default: licenseChanged,
+ force: flags.force
+ }), !0;
+}
+async function getLicense(flags, { user, pluginName, pkg, requireUserConfirmation }) {
+ let license = await getLicenseIdentifier(flags, pkg, requireUserConfirmation);
+ if (!license) return;
+ let text = license.body.replace(/\[fullname\]/g, user?.name ?? "").replace(/\[project\]/g, pluginName ?? "").replace(/\[year\]/g, String((/* @__PURE__ */ new Date()).getFullYear()));
+ return {
+ id: license.id,
+ text
+ };
+}
+async function getLicenseIdentifier(flags, pkg, requireUserConfirmation = !1) {
+ if (flags.license === !1) return null;
+ if (typeof flags.license == "string") {
+ let license = licenses.find(`${flags.license}`);
+ if (!license) throw Error(`License "${flags.license}" not found`);
+ return license;
+ }
+ if (pkg && pkg.license && !requireUserConfirmation) {
+ let license = licenses.find(`${pkg.license}`);
+ if (license) return license;
+ log_default.warn(`package.json contains license "${pkg.license}", which is not recognized`);
+ }
+ let licenseId = await prompt("Which license do you want to use?", {
+ default: pkg && pkg.license && licenses.find(pkg.license) ? pkg.license : preferredLicenses[0],
+ choices: [
+ prompt.separator(),
+ ...preferredLicenses.map((value) => ({
+ value,
+ name: licenses.list[value].title
+ })),
+ prompt.separator(),
+ ...otherLicenses.map((value) => ({
+ value,
+ name: licenses.list[value].title
+ }))
+ ]
+ });
+ return licenses.find(licenseId);
+}
+async function getProjectDescription(basePath, pkg, requireUserConfirmation = !1) {
+ let description = await resolveProjectDescription(basePath, pkg);
+ return requireUserConfirmation && (description = await prompt("Plugin description", { default: description || "" })), description ?? "";
+}
+async function resolveProjectDescription(basePath, pkg) {
+ if (pkg && typeof pkg.description == "string" && pkg.description.length > 5) return pkg.description;
+ try {
+ let [title, description] = (await readFile(path.join(basePath, "README.md"), "utf8")).split("\n").filter(Boolean);
+ if (!title || !description || !title.match(/^#\s+\w+/)) return null;
+ let unlinked = description.replace(/\[(.*?)\]\(.*?\)/g, "$1");
+ return /^[^#]/.test(unlinked) ? unlinked : null;
+ } catch (err) {
+ return errorToUndefined(err);
+ }
+}
+async function writeAssets(injectables, { basePath, flags }) {
+ let assetsDir = await findAssetsDir(), from = (...segments) => path.join(assetsDir, "inject", ...segments), to = (...segments) => path.join(basePath, ...segments), writes = [];
+ for (let injectable of injectables) {
+ if (injectable.type === "copy") {
+ let fromPath = asArray(injectable.from), toPath = asArray(injectable.to);
+ await copyFileWithOverwritePrompt(from(...fromPath), to(...toPath), flags) && writes.push(path.join(...toPath));
+ continue;
+ }
+ if (injectable.type === "template") {
+ let toPath = asArray(injectable.to);
+ await writeFileWithOverwritePrompt(to(...toPath), `${injectable.value.trim()}\n`, {
+ default: "n",
+ force: injectable.force || flags.force
+ }), writes.push(path.join(...toPath));
+ continue;
+ }
+ throw Error(`Unknown operation type "${injectable.type}"`);
+ }
+ return writes;
+}
+async function writeStaticAssets(options) {
+ let { outDir, flags } = options;
+ return writeAssets([
+ flags.oxlint && oxlintConfigTemplate({ flags: options.flags }),
+ {
+ type: "copy",
+ from: "editorconfig",
+ to: ".editorconfig"
+ },
+ pkgConfigTemplate({
+ outDir,
+ flags: options.flags
+ }),
+ flags.gitignore && gitignoreTemplate(),
+ flags.typescript && tsconfigTemplate({ flags: options.flags }),
+ flags.typescript && tsconfigTemplateDist({
+ outDir,
+ flags: options.flags
+ }),
+ flags.typescript && tsconfigTemplateSettings({
+ outDir,
+ flags: options.flags
+ }),
+ flags.oxfmt && oxfmtConfigTemplate({ flags: options.flags })
+ ].map((f) => f || void 0).filter((f) => !!f), options);
+}
+function asArray(input) {
+ return typeof input == "string" ? [input] : input;
+}
+/**
+* assets dir might be in higher or lower in the dir hierarchy depending on
+* if we run from `dist` or `src`
+*/
+async function findAssetsDir() {
+ let maxBackpaddle = 3, currDir = path.dirname(fileURLToPath(import.meta.url)), assetsDir = "";
+ for (; !assetsDir && maxBackpaddle;) {
+ currDir = path.join(currDir, "..");
+ let assets = path.join(currDir, "assets");
+ await fileExists(assets) ? assetsDir = assets : maxBackpaddle--;
+ }
+ if (!assetsDir) throw Error("Could not find assets directory!");
+ return assetsDir;
+}
+async function addCompileDirToGitIgnore(options) {
+ let gitIgnorePath = path.join(options.basePath, ".gitignore"), gitignore = await readFile(gitIgnorePath, "utf8").catch(errorToUndefined);
+ if (!gitignore) return !1;
+ let ignore = options.outDir.replace(/^[./]+/, "").split("/")[0];
+ if (!ignore) return !1;
+ let lines = gitignore.trim().split("\n");
+ return lines.includes(ignore) ? !1 : (lines.push("", "# Compiled plugin", ignore), await writeFile(gitIgnorePath, lines.join("\n") + "\n", { encoding: "utf8" }), !0);
+}
+const initFlags = {
+ ...sharedFlags_default,
+ scripts: {
+ type: "boolean",
+ default: !0
+ },
+ oxlint: {
+ type: "boolean",
+ default: !0
+ },
+ typescript: {
+ type: "boolean",
+ default: !0
+ },
+ oxfmt: {
+ type: "boolean",
+ default: !0
+ },
+ license: { type: "string" },
+ editorconfig: {
+ type: "boolean",
+ default: !0
+ },
+ gitignore: {
+ type: "boolean",
+ default: !0
+ },
+ force: {
+ type: "boolean",
+ default: !1
+ },
+ install: {
+ type: "boolean",
+ default: !0
+ },
+ name: { type: "string" },
+ author: { type: "string" },
+ repo: { type: "string" },
+ presetOnly: {
+ type: "boolean",
+ default: !1
+ },
+ preset: {
+ type: "string",
+ isMultiple: !0
+ }
+};
+async function init(options) {
+ let dependencies = {}, devDependencies = {}, peerDependencies = {};
+ await inject({
+ ...options,
+ outDir: defaultOutDir,
+ requireUserConfirmation: !options.flags.force,
+ dependencies,
+ devDependencies,
+ peerDependencies,
+ validate: !1
+ });
+ let packageJson = await getPackage({
+ basePath: options.basePath,
+ validate: !1
+ }), typescript = options.flags.typescript, source = typescript ? defaultSourceTs(packageJson) : defaultSourceJs(packageJson), filename = typescript ? "index.ts" : "index.js", srcDir = path.resolve(options.basePath, "src");
+ await ensureDir(srcDir), await writeFile(path.join(srcDir, filename), source, { encoding: "utf8" });
+}
+export { presetHelpList as i, initFlags as n, inject as r, init as t };
+
+//# sourceMappingURL=init-BDY7XRmJ.js.map
\ No newline at end of file