UNPKG

@chakra-icons/cli

Version:

a tooling for manage everything in @chakra-icons

457 lines (446 loc) 16.3 kB
#!/usr/bin/env node "use strict"; var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod )); // index.bin.ts var import_arg = __toESM(require("arg")); var ruins = __toESM(require("ruins-ts")); // package.json var package_default = { name: "@chakra-icons/cli", description: "a tooling for manage everything in @chakra-icons", version: "2.0.0", author: "ri7nz <ri7nz@koding.ninja>", homepage: "https://github.com/kodingdotninja/chakra-icons", repository: "https://github.com/kodingdotninja/chakra-icons.git", bugs: "https://github.com/kodingdotninja/chakra-icons/issues", bin: { "chakra-icons": "dist/index.bin.js" }, main: "./dist/index.js", module: "./dist/index.mjs", types: "./dist/index.d.ts", scripts: { "# general commands": "--------------------------------------------------", build: "tsup", format: 'prettier --write "**/*.{js,json,md,svg}"', lint: 'eslint --fix "**/*.ts"', "#": "-------------------------------------------------------------------" }, dependencies: { "@babel/generator": "^7.22.10", "@babel/types": "^7.22.11", arg: "^5.0.2", "change-case": "^4.1.2", "create-chakra-icons": "*", degit: "npm:tiged", "fp-ts": "^2.16.1", glob: "^10.3.3", "ruins-ts": "^0.0.4" }, devDependencies: { "@types/degit": "^2.8.3", eslint: "^8.47.0", "eslint-plugin-fp-ts": "^0.3.2", tsup: "^7.2.0", typescript: "^5.2.2" }, files: [ "dist/" ], keywords: [ "kdnj", "kodingdotninja", "chakra-icons", "create-chakra-icons" ], license: "MIT" }; // src/build.ts var import_generator = __toESM(require("@babel/generator")); var t = __toESM(require("@babel/types")); var import_change_case = require("change-case"); var import_create_chakra_icons = require("create-chakra-icons"); var import_degit = __toESM(require("degit")); var A = __toESM(require("fp-ts/Array")); var E = __toESM(require("fp-ts/Either")); var import_function = require("fp-ts/function"); var O = __toESM(require("fp-ts/Option")); var S = __toESM(require("fp-ts/string")); var TE = __toESM(require("fp-ts/TaskEither")); var fs = __toESM(require("fs/promises")); var _glob = __toESM(require("glob")); var path = __toESM(require("path")); var metaIconDefault = (name, repository, iconPath, clonePath, sourcePath) => ({ name, repository, iconPath, clonePath, sourcePath, sources: [] }); var prefixWhenNumeric = (prefix) => (n) => /^\d.*$/.test(n) ? `${prefix}${n}` : n; var moduleName = (0, import_function.flow)(prefixWhenNumeric("I"), import_change_case.pascalCase, S.replace(/[^A-Z0-9]/gi, "")); var hotfixPkgIconNameReplace = [ [ /tabler-icons/i, { "device-game-pad": "device-dpad" // prevent conflict with `device-gamepad` } ] ]; var hotfixName = (metaIcon) => (name) => (0, import_function.pipe)( hotfixPkgIconNameReplace, A.findFirst(([pattern]) => pattern.test(metaIcon.repository)), O.fold( () => name, ([, maps]) => (0, import_function.pipe)( maps[name], O.fromNullable, O.getOrElse(() => name) ) ) ); var setSources = (metaIcon) => (beSources) => { const createSource = (sources, svg) => { const { dir, name: _name } = path.parse(svg); const name = (0, import_function.pipe)(_name, hotfixName(metaIcon), moduleName); const entryPoint = path.join( dir.replace(path.join(metaIcon.clonePath, metaIcon.iconPath), metaIcon.sourcePath), "index.ts" ); const entry = { name, svg, code: path.join(path.dirname(entryPoint), `${name}.tsx`) }; const maybeIcon = sources.find((icon) => S.Eq.equals(icon.entryPoint, entryPoint)); if (maybeIcon) { sources[sources.indexOf(maybeIcon)]?.entries.push(entry); return sources; } return [...sources, { entryPoint, entries: [entry] }]; }; return { ...metaIcon, sources: beSources.reduce((a, b) => createSource(a, b), metaIcon.sources) }; }; var writeFile2 = (file, data) => TE.tryCatch(() => fs.mkdir(path.dirname(file), { recursive: true }).then(() => fs.writeFile(file, data)), E.toError); var glob2 = (target) => TE.tryCatch(() => _glob.glob(target), E.toError); var cloneRepository = (metaIcon) => TE.tryCatch( () => (0, import_degit.default)(metaIcon.repository, { force: true }).clone(metaIcon.clonePath).then(() => metaIcon), E.toError ); var findSvgs = (metaIcon) => (0, import_function.pipe)(path.join(metaIcon.clonePath, metaIcon.iconPath, "**", "*.svg"), glob2, TE.map(setSources(metaIcon))); var createIcons = (options) => TE.tryCatch(() => Promise.resolve(import_create_chakra_icons.cli.main(options)), E.toError); var generateIcons = (metaIcon) => (0, import_function.pipe)( metaIcon.sources, A.map( ({ entries }) => (0, import_function.pipe)( entries, A.map(({ name: n, svg: i, code: o }) => createIcons({ n, i, o, ts: true, T: "C", useFilename: true })) ) ), A.flatten, TE.sequenceArray ); var generateExportAllCode = (name) => (0, import_function.pipe)(`./${name}`, t.stringLiteral, t.exportAllDeclaration, import_generator.default, (b) => b.code); var genrateExportAllNamespace = (alias, source) => (0, import_generator.default)( t.exportNamedDeclaration(null, [(0, import_function.pipe)(alias, t.identifier, t.exportNamespaceSpecifier)], t.stringLiteral(source)) ).code; var generateEntrypointCode = (source) => (0, import_function.pipe)( source.entries, A.map((s) => generateExportAllCode(s.name)), (arr) => arr.join("\r\n") ); var generateEntrypoint = (metaIcon) => (0, import_function.pipe)( metaIcon.sources, A.map((a) => writeFile2(a.entryPoint, generateEntrypointCode(a))), TE.sequenceArray ); var generateSnapshot = (options) => (metaIcon) => (0, import_function.pipe)( options.snapshot, O.fromNullable, O.fold( () => TE.of(metaIcon), (file) => (0, import_function.pipe)( TE.of(metaIcon), TE.chainFirst((_metaIcon) => writeFile2(file, JSON.stringify(_metaIcon, null, 2))) ) ) ); var generateRootEntryPoint = (metaIcon) => (0, import_function.pipe)( metaIcon.sources, A.findFirst((source) => S.Eq.equals(source.entryPoint, path.join(metaIcon.sourcePath, "index.ts"))), O.fold( () => [ writeFile2( path.join(metaIcon.sourcePath, "index.ts"), (0, import_function.pipe)( metaIcon.sources, // eslint-disable-next-line @typescript-eslint/unbound-method A.map((source) => (0, import_function.pipe)(source.entryPoint, path.dirname, path.basename)), A.map((source) => genrateExportAllNamespace(source, "./".concat(source))), (arrs) => arrs.join("\r\n") ) ) ], () => [] ), TE.sequenceArray ); var buildFlow = (0, import_function.flow)( // make MetaIcon and cloneRepository TE.chain(cloneRepository), // scan svg in target directory TE.chain(findSvgs), // generated icons (src/*.tsx) in file system TE.chainFirst(generateIcons), // generated index.ts TE.chainFirst(generateEntrypoint), // generated src/index.ts when iconPath is nested TE.chainFirst(generateRootEntryPoint) ); var build = (options) => { const { name, repository, iconPath, clonePath, sourcePath } = options; const metaIcon = metaIconDefault(name, repository, iconPath, clonePath, sourcePath); return (0, import_function.pipe)( // make `metaIcon` object to TaskEither TE.of(metaIcon), // main flow buildFlow, // when pass `snapshot` in options TE.chainFirst(generateSnapshot(options)) // when pass `entryPoints` in options // it will be make entrypoints.ts for use in tsup.config // TE.chainFirst(generateExportEntrypoints(options)), // it will be update package.json // TE.chainFirst(updatePkgJson(options)), ); }; // src/init.ts var init = (options) => { console.log({ options }); }; // src/clean.ts var A2 = __toESM(require("fp-ts/Array")); var E2 = __toESM(require("fp-ts/Either")); var import_function2 = require("fp-ts/function"); var TE2 = __toESM(require("fp-ts/TaskEither")); var fs2 = __toESM(require("fs/promises")); var import_glob = __toESM(require("glob")); var import_path = __toESM(require("path")); var clean = (options) => (0, import_function2.pipe)( TE2.tryCatch(() => import_glob.default.glob(import_path.default.join(options.sourcePath, "**", "*.{ts,tsx}")), E2.toError), TE2.chainFirst(() => TE2.tryCatch(() => fs2.rmdir(options.clonePath, { recursive: true, maxRetries: 2 }), E2.toError)), TE2.chainFirst(() => TE2.tryCatch(() => fs2.rmdir(import_path.default.join("dist"), { recursive: true, maxRetries: 2 }), E2.toError)), TE2.chainFirst( (files) => (0, import_function2.pipe)( files, A2.map((file) => TE2.tryCatch(() => fs2.rm(file), E2.toError)), TE2.sequenceSeqArray ) ) ); // src/prepack.ts var fs3 = __toESM(require("fs/promises")); var import_path2 = __toESM(require("path")); var noOp = (a) => a; var ifThen = (condition, whenTrue, whenFalse) => (a) => (condition ? whenTrue : whenFalse)(a); var removeDevDependencies_ = ({ devDependencies: _, ...pkgJson }) => ({ ...pkgJson }); var addPeerDependencies_ = (peerDependencies) => (pkgJson) => ({ ...pkgJson, peerDependencies }); var addPkgScripts = (newScripts) => ({ scripts, ...pkgJson }) => ({ ...pkgJson, scripts: { ...scripts, ...newScripts } }); var mapDeps = (arr) => arr.reduce((acc, cur) => { const pkgVerRegex = ( // eslint-disable-next-line prefer-named-capture-group /(^(@[a-z0-9-~][a-z0-9-._~]*\/)?[a-z0-9-~][a-z0-9-._~]*)@([~^]?([\dvx*]+(?:[-.](?:[\dx*]+|alpha|beta))*))?$/ ); const [, name, , version2] = pkgVerRegex.exec(cur) ?? []; if (!name) throw Error("Package Name invalid"); if (!version2) throw Error("Package Version invalid"); return { ...acc, [name]: version2.replace("@", "") }; }, {}); var mapScripts = (arr) => arr.reduce((acc, cur) => { const [name, version2] = cur.split("="); if (!name) throw Error("Package Name invalid"); if (!version2) throw Error("Package Version invalid"); return { ...acc, [name]: version2 }; }, {}); var prepack = ({ removeDevDeps = false, addPeerDeps = [], addScripts: addScripts_ = [] }) => { if (!removeDevDeps && addPeerDeps.length === 0 && addScripts_.length === 0) return; const pkgJsonPath = import_path2.default.resolve("./package.json"); const removeDevDependencies = ifThen(removeDevDeps, removeDevDependencies_, noOp); const addPeerDependencies = ifThen(addPeerDeps.length > 0, addPeerDependencies_(mapDeps(addPeerDeps)), noOp); const addScripts = ifThen(addScripts_.length > 0, addPkgScripts(mapScripts(addScripts_)), noOp); const writePkgJson = (pkgJson) => fs3.writeFile(pkgJsonPath, pkgJson); return fs3.readFile(pkgJsonPath, { encoding: "utf8" }).then(JSON.parse).then(removeDevDependencies).then(addPeerDependencies).then(addScripts).then((pkgJson) => JSON.stringify(pkgJson, null, 2)).then(writePkgJson); }; // index.bin.ts var parseArgs = () => { try { const argv = process.argv.slice(2); const args = (0, import_arg.default)( { // COMMON OPTIONS "--help": Boolean, "-h": "--help", "--version": Boolean, "-v": "--version", // REQUIRED "--name": String, "-n": "--name", "--repo": String, "--icon-path": String, "-r": "--repo", "-i": "--icon-path", "--output": String, "-o": "--output", // OPTIONS "--clone-path": String, "-C": "--clone-path", "--snapshot": String, "-S": "--snapshot", // FLAGS "--with-entrypoints": Boolean, "--with-clean": Boolean, "-E": "--with-entrypoints", // Prepack Related "--remove-dev-deps": Boolean, "--add-peer-deps": String, // example --add-peer-deps "pkg@v1,pkg2@>=2" "--add-scripts": String, "--rd": "--remove-dev-deps", "--ap": "--add-peer-deps", "--ax": "--add-scripts" }, { argv } ); const [first] = args._; const { "--name": name, "--repo": repository, "--icon-path": iconPath, "--clone-path": _clonePath, "--output": _sourcePath, "--snapshot": snapshot, "--with-entrypoints": entryPoints, "--version": version2, "--help": help2, "--remove-dev-deps": removeDevDeps, "--add-peer-deps": addPeerDeps, "--add-scripts": addScripts } = args; const clonePath = _clonePath ?? ".chakraIcons"; const sourcePath = _sourcePath ?? "src"; if (first === "prepack") return { type: "prepack", options: { removeDevDeps, addPeerDeps: addPeerDeps?.split(",") ?? [], addScripts: addScripts?.split(",") ?? [] } }; if (first === "init" && name && repository && iconPath) return { type: "init", options: { name, repository, iconPath } }; if (name && repository && iconPath && clonePath && sourcePath) { const options = { name, repository, iconPath, clonePath, sourcePath, snapshot, entryPoints: Boolean(entryPoints) }; if (first === "clean") return { type: "clean", options }; return { type: "build", options }; } if (version2) return { type: "version" }; if (help2) return { type: "help" }; return { type: "fail", error: Error("cannot parse any arguments :(") }; } catch (e) { return { type: "fail", error: e }; } }; var help = () => process.stdout.write(` USAGE: ${package_default.name} <SUBCOMMAND> SUBCOMMAND: init: init -n <NAME> -r <ORGS/REPO-NAME> -i <PATH/SVG> build: build -n <NAME> -r <ORGS/REPO-NAME> -i <PATH/SVG> OPTIONS: --snapshot <NAME>, -S <NAME> create snapshot information (.json). FLAGS: --with-entrypoints, -E generate entrypoints when generating new icon. prepack: tools for manage package.json fields OPTIONS: --add-peer-deps, --ap add peer dependencies (e.g --ap "react@^17,react-dom@^17") --add-scripts, --ax add new script in scripts field of package.json (e.g --ax "prcommit=commitlint") FLAGS: --remove-dev-deps, --rd remove field devDependencies in current work directory (package.json) `); var version = () => console.log(package_default.version); var fail = (e) => { console.log("something wrong :( "); console.error(String(e)); process.exit(1); }; var run = async (command) => { switch (command.type) { case "prepack": return prepack(command.options); case "build": return ruins.fromTaskEither(build(command.options)).catch((e) => fail(e)); case "init": return init(command.options); case "clean": return ruins.fromTaskEither(clean(command.options)).then((files) => { console.log(`Clean ${files.length} files`); }).catch((e) => fail(e)); case "fail": return fail(command.error); case "version": return version(); default: return help(); } }; run(parseArgs()).then(() => process.exit(0)).catch((e) => console.error(e));