From 1acb4f128a5751a98bc8fb9c51d05113a5e39b2c Mon Sep 17 00:00:00 2001 From: ncpa0cpl Date: Mon, 1 Aug 2022 11:44:05 +0200 Subject: [PATCH] refactor: build script update, disabled bundling --- .eslintrc.json | 1 + .npmignore | 12 +-- package.json | 3 +- scripts/build.mjs | 142 +++++++++++++++++++++------ src/index.ts | 13 +-- src/utilities/array-flat-polyfill.ts | 37 +++++++ 6 files changed, 166 insertions(+), 42 deletions(-) create mode 100644 src/utilities/array-flat-polyfill.ts diff --git a/.eslintrc.json b/.eslintrc.json index 2881686..205e23b 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -38,6 +38,7 @@ ], "semi": ["error", "always"], "@typescript-eslint/consistent-type-imports": 2, + "@typescript-eslint/consistent-type-exports": 2, "@typescript-eslint/member-delimiter-style": 2, "@typescript-eslint/no-confusing-non-null-assertion": 2, "@typescript-eslint/no-misused-new": 2, diff --git a/.npmignore b/.npmignore index 0e1caaf..d68070c 100644 --- a/.npmignore +++ b/.npmignore @@ -1,17 +1,17 @@ __mocks__ __tests__ -.eslintignore -.eslintrc.json .github -.gitignore .husky -.prettierrc.json .vscode coverage docs -git-hook-tasks.config.json -jest.config.js scripts src +.eslintignore +.eslintrc.json +.gitignore +.prettierrc.json +git-hook-tasks.config.json +jest.config.js tsconfig.test.json yarn-error.log \ No newline at end of file diff --git a/package.json b/package.json index 2a07713..39e6a4b 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,7 @@ "git-hook-tasks": "github:ncpa0cpl/git-hook-tasks", "husky": "^8.0.1", "jest": "^28.1.0", + "node-os-walk": "^1.0.0", "prettier": "^2.6.2", "prettier-plugin-jsdoc": "^0.3.38", "ts-jest": "^28.0.2", @@ -26,7 +27,7 @@ "require": "./dist/cjs/index.cjs" }, "./jsx-runtime": { - "types": "./dist/types/jsx/jsx-runtime.d.ts", + "types": "./dist/types/jsx-runtime.d.ts", "import": "./dist/esm/jsx-runtime.mjs", "require": "./dist/cjs/jsx-runtime.cjs" } diff --git a/scripts/build.mjs b/scripts/build.mjs index 4fd6daf..e760ae5 100644 --- a/scripts/build.mjs +++ b/scripts/build.mjs @@ -1,10 +1,9 @@ -// const esbuild = require("esbuild"); -// const path = require("path"); import esbuild from "esbuild"; import path from "path"; +import { walk } from "node-os-walk"; // get first process argument -const argv = process.argv.at(2); +const argv = process.argv[2]; if (argv !== "esmodule" && argv !== "commonjs") { console.error("Invalid target, allowed values: 'esmodule', 'commonjs'"); @@ -14,44 +13,129 @@ if (argv !== "esmodule" && argv !== "commonjs") { const format = argv === "esmodule" ? "esm" : "cjs"; const outDir = format === "esm" ? "./dist/esm" : "./dist/cjs"; -const ext = format === "esm" ? ".mjs" : ".cjs"; +const ALLOWED_EXTENSIONS = [ + ".ts", + ".js", + ".cjs", + ".mjs", + ".mts", + ".cts", + ".tsx", + ".jsx", +]; -async function main() { - await esbuild.build({ - outfile: path.resolve(process.cwd(), outDir, `index${ext}`), - tsconfig: path.resolve(process.cwd(), "tsconfig.build.json"), - entryPoints: [path.resolve(process.cwd(), "src/index.ts")], - format: format, - bundle: true, - }); +/** + * @param {string} relativePath + * @param {string[]} rest + */ +function p(relativePath, ...rest) { + return path.resolve(process.cwd(), relativePath, ...rest); +} +/** + * @param {string} str + * @param {string[]} suffixes + */ +function endsWith(str, ...suffixes) { + for (const suffix of suffixes) { + if (str.endsWith(suffix)) { + return true; + } + } + return false; +} + +/** @param {string} ext */ +const ESbuildImportExtensionPlugin = (ext) => ({ + name: "esbuild-esm-import-plugin", + setup(build) { + build.onResolve({ filter: /.*/ }, (args) => { + if (args.importer) return { path: args.path + ext, external: true }; + }); + }, +}); + +/** + * @param {{ + * entrypoint: string; + * outfile: string; + * format: "esm" | "cjs"; + * ext: string; + * }} options + */ +async function buildFile({ entrypoint, outfile, format, ext }) { await esbuild.build({ - outfile: path.resolve(process.cwd(), outDir, `jsx-runtime${ext}`), + target: "es6", + outfile, tsconfig: path.resolve(process.cwd(), "tsconfig.build.json"), - entryPoints: [path.resolve(process.cwd(), "src/jsx/jsx-runtime.ts")], + entryPoints: [entrypoint], format: format, bundle: true, + outExtension: { + ".js": ext, + }, + plugins: [ESbuildImportExtensionPlugin(ext)], }); +} + +/** + * @param {{ + * rootDir: string; + * outDir: string; + * format: "esm" | "cjs"; + * ext?: string; + * }} options + */ +async function build(options) { + const { format, outDir, rootDir } = options; + const ext = options.ext ?? (format === "esm" ? ".mjs" : ".cjs"); + + for await (const [root, _, files] of walk(rootDir)) { + for (const file of files) { + if (endsWith(file.name, ...ALLOWED_EXTENSIONS)) { + const fileName = path.parse(file.name).name; + const filepath = path.resolve(root, file.name); + const filepathRel = path.relative(rootDir, filepath); + const fileOutDirRel = path.dirname(filepathRel); + + buildFile({ + entrypoint: filepath, + outfile: path.resolve(outDir, fileOutDirRel, fileName + ext), + format, + ext, + }); + } + } + } +} + +async function main() { + /** @type Array> */ + const operations = []; + + operations.push( + build({ + rootDir: p("./src"), + outDir: p(outDir), + format, + }) + ); if (format === "cjs") { const legacyDir = "./dist/legacy"; - await esbuild.build({ - outfile: path.resolve(process.cwd(), legacyDir, `index.js`), - tsconfig: path.resolve(process.cwd(), "tsconfig.build.json"), - entryPoints: [path.resolve(process.cwd(), "src/index.ts")], - format: "cjs", - bundle: true, - }); - - await esbuild.build({ - outfile: path.resolve(process.cwd(), legacyDir, `jsx-runtime.js`), - tsconfig: path.resolve(process.cwd(), "tsconfig.build.json"), - entryPoints: [path.resolve(process.cwd(), "src/jsx/jsx-runtime.ts")], - format: "cjs", - bundle: true, - }); + // Build for legacy environments that do not support .cjs extensions + operations.push( + build({ + rootDir: p("./src"), + outDir: p(legacyDir), + format: "cjs", + ext: ".js", + }) + ); } + + await Promise.all(operations); } main(); diff --git a/src/index.ts b/src/index.ts index 453eb05..570a99b 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,14 +1,15 @@ +import "./utilities/array-flat-polyfill"; + +export * from "./express/index"; +export * from "./jsx/jsx.types"; + export { renderToHtml, renderToHtmlAsync } from "./html-parser/render-to-html"; -export * from "./express"; -export { - renderToStringTemplateTag, - type StringTemplateParserOptions, -} from "./string-template-parser/render-to-string-template-tag"; +export { renderToStringTemplateTag } from "./string-template-parser/render-to-string-template-tag"; export { type ContextDefinition, type ContextMap, defineContext, } from "./context-map/context-map"; export type { AttributeBool } from "./jsx/base-html-tag-props"; +export type { StringTemplateParserOptions } from "./string-template-parser/render-to-string-template-tag"; export type { HTMLProps } from "./jsx/base-html-tag-props"; -export * from "./jsx/jsx.types"; diff --git a/src/utilities/array-flat-polyfill.ts b/src/utilities/array-flat-polyfill.ts new file mode 100644 index 0000000..2ea3c4d --- /dev/null +++ b/src/utilities/array-flat-polyfill.ts @@ -0,0 +1,37 @@ +/* eslint-disable @typescript-eslint/prefer-for-of */ + +function flat( + this: A, + depth?: D +): FlatArray[] { + const copy: FlatArray[] = []; + + if (depth === undefined) { + // @ts-expect-error + depth = 1; + } + + for (let i = 0; i < this.length; i++) { + const item = this[i]; + + if (depth! > 0 && Array.isArray(item)) { + const itemFlatCopy = flat.call(item, depth! - 1); + for (let j = 0; j < itemFlatCopy.length; j++) { + copy.push(itemFlatCopy[j]); + } + } else { + copy.push(item); + } + } + + return copy; +} + +// Add flat polyfill to Array prototype if not defined +if (!Array.prototype.flat) { + Object.defineProperty(Array.prototype, "flat", { + configurable: true, + value: flat, + writable: true, + }); +}