@chakra-icons/cli
Version:
a tooling for manage everything in @chakra-icons
172 lines (169 loc) • 5.69 kB
JavaScript
// src/build.ts
import babelGenerator from "@babel/generator";
import * as t from "@babel/types";
import { pascalCase } from "change-case";
import { cli } from "create-chakra-icons";
import degit from "degit";
import * as A from "fp-ts/Array";
import * as E from "fp-ts/Either";
import { flow, pipe } from "fp-ts/function";
import * as O from "fp-ts/Option";
import * as S from "fp-ts/string";
import * as TE from "fp-ts/TaskEither";
import * as fs from "fs/promises";
import * as _glob from "glob";
import * as path from "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 = flow(prefixWhenNumeric("I"), 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) => pipe(
hotfixPkgIconNameReplace,
A.findFirst(([pattern]) => pattern.test(metaIcon.repository)),
O.fold(
() => name,
([, maps]) => 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 = 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(
() => degit(metaIcon.repository, { force: true }).clone(metaIcon.clonePath).then(() => metaIcon),
E.toError
);
var findSvgs = (metaIcon) => pipe(path.join(metaIcon.clonePath, metaIcon.iconPath, "**", "*.svg"), glob2, TE.map(setSources(metaIcon)));
var createIcons = (options) => TE.tryCatch(() => Promise.resolve(cli.main(options)), E.toError);
var generateIcons = (metaIcon) => pipe(
metaIcon.sources,
A.map(
({ entries }) => 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) => pipe(`./${name}`, t.stringLiteral, t.exportAllDeclaration, babelGenerator, (b) => b.code);
var genrateExportAllNamespace = (alias, source) => babelGenerator(
t.exportNamedDeclaration(null, [pipe(alias, t.identifier, t.exportNamespaceSpecifier)], t.stringLiteral(source))
).code;
var generateEntrypointCode = (source) => pipe(
source.entries,
A.map((s) => generateExportAllCode(s.name)),
(arr) => arr.join("\r\n")
);
var generateEntrypoint = (metaIcon) => pipe(
metaIcon.sources,
A.map((a) => writeFile2(a.entryPoint, generateEntrypointCode(a))),
TE.sequenceArray
);
var generateSnapshot = (options) => (metaIcon) => pipe(
options.snapshot,
O.fromNullable,
O.fold(
() => TE.of(metaIcon),
(file) => pipe(
TE.of(metaIcon),
TE.chainFirst((_metaIcon) => writeFile2(file, JSON.stringify(_metaIcon, null, 2)))
)
)
);
var generateRootEntryPoint = (metaIcon) => 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"),
pipe(
metaIcon.sources,
// eslint-disable-next-line @typescript-eslint/unbound-method
A.map((source) => pipe(source.entryPoint, path.dirname, path.basename)),
A.map((source) => genrateExportAllNamespace(source, "./".concat(source))),
(arrs) => arrs.join("\r\n")
)
)
],
() => []
),
TE.sequenceArray
);
var buildFlow = 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 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 });
};
export {
buildFlow,
build,
init
};