quickbundle 1.2.0 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,92 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.watch = exports.build = void 0;
4
- const esbuild_1 = require("esbuild");
5
- const threads_1 = require("threads");
6
- const helpers_1 = require("../helpers");
7
- const configs_1 = require("./configs");
8
- const build = async () => {
9
- const { pkg, typescript } = await (0, configs_1.getConfigs)({
10
- isProduction: true,
11
- });
12
- const promises = [
13
- buildJavaScript("cjs"),
14
- ...(pkg.hasModule ? [buildJavaScript("esm")] : []),
15
- ...(typescript.isEnabled
16
- ? [
17
- buildDts({
18
- source: pkg.source,
19
- destination: pkg.types,
20
- }),
21
- ]
22
- : []),
23
- ];
24
- return Promise.all(promises);
25
- };
26
- exports.build = build;
27
- const watch = async (onWatch) => {
28
- const { esbuild, pkg, typescript } = await (0, configs_1.getConfigs)({
29
- isProduction: false,
30
- });
31
- const defaultTarget = pkg.hasModule ? "esm" : "cjs";
32
- const ctx = await (0, esbuild_1.context)({
33
- ...esbuild({
34
- format: defaultTarget,
35
- outfile: pkg.destination[defaultTarget],
36
- }),
37
- plugins: [
38
- {
39
- name: "onBuildEnd",
40
- setup(build) {
41
- build.onStart(() => {
42
- onWatch("loading");
43
- });
44
- build.onEnd(async (result) => {
45
- const error = (await (0, esbuild_1.formatMessages)(result.errors, {
46
- kind: "error",
47
- color: true,
48
- terminalWidth: 100,
49
- })).join("\n");
50
- // If there's already a build error, no need to run
51
- // a heavy typing generation process until the error is fixed
52
- if (!error && typescript.isEnabled) {
53
- buildDts({
54
- source: pkg.source,
55
- destination: pkg.types,
56
- })
57
- .then(() => {
58
- onWatch("result");
59
- })
60
- .catch((err) => {
61
- onWatch("result", err);
62
- });
63
- }
64
- else {
65
- onWatch("result", error);
66
- }
67
- });
68
- },
69
- },
70
- ],
71
- });
72
- await ctx.watch();
73
- };
74
- exports.watch = watch;
75
- const buildJavaScript = async (format) => {
76
- const worker = await (0, threads_1.spawn)(new threads_1.Worker("./workers/esbuild"));
77
- const outfile = await worker(format);
78
- await threads_1.Thread.terminate(worker);
79
- return outfile;
80
- };
81
- const buildDts = async ({ source, destination, }) => {
82
- try {
83
- const worker = await (0, threads_1.spawn)(new threads_1.Worker("./workers/dts"));
84
- const dtsContent = await worker(source);
85
- await (0, helpers_1.writeFile)(destination, dtsContent);
86
- await threads_1.Thread.terminate(worker);
87
- return destination;
88
- }
89
- catch (error) {
90
- throw new Error(`Type generation failed:\n${error}`);
91
- }
92
- };
@@ -1,8 +0,0 @@
1
- import type { BuildOptions } from "esbuild";
2
- import type { TSConfig } from "./typescript";
3
- export interface EsbuildConfig extends Required<Pick<BuildOptions, "format" | "outfile" | "external" | "platform">> {
4
- isProduction: boolean;
5
- source: string;
6
- tsConfig: TSConfig | null;
7
- }
8
- export declare const getEsbuildConfig: ({ external, format, isProduction, outfile, platform, source, tsConfig, }: EsbuildConfig) => BuildOptions;
@@ -1,65 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getEsbuildConfig = void 0;
4
- const helpers_1 = require("../../helpers");
5
- const constants_1 = require("../../constants");
6
- const getEsbuildConfig = ({ external, format, isProduction, outfile, platform, source, tsConfig, }) => ({
7
- absWorkingDir: constants_1.CWD,
8
- bundle: true,
9
- color: true,
10
- define: {
11
- "process.env.NODE_ENV": isProduction ? '"production"' : '"development"',
12
- },
13
- entryPoints: [source],
14
- external,
15
- format,
16
- loader: {
17
- // Data URI is used by default to include a web resource without needing to make an HTTP request (as it can be with file loader for example):
18
- ".jpg": "dataurl",
19
- ".jpeg": "dataurl",
20
- ".png": "dataurl",
21
- ".gif": "dataurl",
22
- ".svg": "dataurl",
23
- ".webp": "dataurl",
24
- },
25
- logLevel: "silent",
26
- metafile: true,
27
- minify: isProduction,
28
- outfile,
29
- plugins: [jsxPlugin(tsConfig)],
30
- platform,
31
- sourcemap: true,
32
- target: tsConfig?.target || "esnext",
33
- treeShaking: true,
34
- });
35
- exports.getEsbuildConfig = getEsbuildConfig;
36
- /**
37
- * Plugin to automatically inject React import for jsx management
38
- * ESBuild doesn't support `jsx` tsconfig field: this plugin aims to add a tiny wrapper to support it
39
- * We could use the `inject` ESBuild feature but it will break the tree shaking behavior since the React import will
40
- * be imported on each file (even in .ts file) leading React being included in the bundle even if not needed
41
- * @see: https://github.com/evanw/esbuild/issues/334
42
- * @param tsConfig
43
- * @returns Plugin
44
- */
45
- const jsxPlugin = (tsConfig) => ({
46
- name: "jsx-runtime",
47
- setup(build) {
48
- build.onLoad({ filter: /\.(j|t)sx$/ }, async ({ path }) => {
49
- // Enable plugin only if
50
- // - `${module}/jsx-runtime` package is available (for js project, it's the only condition to check!)
51
- // - if ts project: jsx compilerOption === "react-jsx" or "react-jsxdev"
52
- if (!tsConfig || !tsConfig.hasJsxRuntime)
53
- return;
54
- const module = tsConfig.jsxImportSource || "react";
55
- if (!(0, helpers_1.resolveModulePath)(`${module}/jsx-runtime`)) {
56
- throw new Error("Unable to find the JSX runtime.\nPotential solutions:\n1. If you rely on a non React runtime, set a valid `jsxImportSource` in your tsconfig\n2. Make sure that you've installed your project dependencies");
57
- }
58
- const content = await (0, helpers_1.readFile)(path, "utf8");
59
- return {
60
- contents: `import * as React from "${module}";${content}`,
61
- loader: "tsx",
62
- };
63
- });
64
- },
65
- });
@@ -1,22 +0,0 @@
1
- import { BuildOptions } from "esbuild";
2
- import { EsbuildConfig } from "./esbuild";
3
- type ConfigOptions = {
4
- isProduction: boolean;
5
- };
6
- export declare const getConfigs: ({ isProduction }: ConfigOptions) => Promise<{
7
- esbuild: ({ format, outfile, }: Pick<EsbuildConfig, "format" | "outfile">) => BuildOptions;
8
- pkg: {
9
- destination: {
10
- readonly esm?: string;
11
- readonly cjs: string;
12
- };
13
- hasModule: boolean;
14
- source: string;
15
- types: string | undefined;
16
- };
17
- typescript: {
18
- configuration: import("./typescript").TSConfig | null;
19
- isEnabled: boolean;
20
- };
21
- }>;
22
- export {};
@@ -1,34 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getConfigs = void 0;
4
- const esbuild_1 = require("./esbuild");
5
- const package_1 = require("./package");
6
- const typescript_1 = require("./typescript");
7
- const getConfigs = async ({ isProduction }) => {
8
- const { destination, externalDependencies, hasModule, platform, source, types, } = (0, package_1.getPkgConfig)();
9
- const tsConfig = await (0, typescript_1.getTSConfig)();
10
- const hasTyping = typeof types === "string" && Boolean(tsConfig);
11
- const esbuild = ({ format, outfile, }) => (0, esbuild_1.getEsbuildConfig)({
12
- external: externalDependencies,
13
- format,
14
- isProduction,
15
- outfile,
16
- platform,
17
- source,
18
- tsConfig,
19
- });
20
- return {
21
- esbuild,
22
- pkg: {
23
- destination,
24
- hasModule,
25
- source,
26
- types,
27
- },
28
- typescript: {
29
- configuration: tsConfig,
30
- isEnabled: hasTyping,
31
- },
32
- };
33
- };
34
- exports.getConfigs = getConfigs;
@@ -1,11 +0,0 @@
1
- export declare const getPkgConfig: () => {
2
- readonly destination: {
3
- readonly esm?: string;
4
- readonly cjs: string;
5
- };
6
- readonly externalDependencies: string[];
7
- readonly hasModule: boolean;
8
- readonly platform: "browser" | "node";
9
- readonly source: string;
10
- readonly types: string | undefined;
11
- };
@@ -1,28 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getPkgConfig = void 0;
4
- const path_1 = require("path");
5
- const constants_1 = require("../../constants");
6
- const helpers_1 = require("../../helpers");
7
- const getPkgConfig = () => {
8
- const { peerDependencies = {}, dependencies = {}, main, module, platform = "browser", source, types, } = require((0, path_1.resolve)(constants_1.CWD, "package.json"));
9
- (0, helpers_1.assert)(main, "A `main` field is required in `package.json`. Did you forget to add it?");
10
- (0, helpers_1.assert)(source, "A `source` field is required in `package.json`. Did you forget to add it?");
11
- (0, helpers_1.assert)(["browser", "node"].includes(platform), "The `platform` package field can only accept `browser` or `node` value.");
12
- const externalDependencies = [
13
- ...Object.keys(peerDependencies),
14
- ...Object.keys(dependencies),
15
- ];
16
- return {
17
- destination: {
18
- cjs: main,
19
- ...(module && { esm: module }),
20
- },
21
- externalDependencies,
22
- hasModule: Boolean(module),
23
- platform,
24
- source,
25
- types,
26
- };
27
- };
28
- exports.getPkgConfig = getPkgConfig;
@@ -1,6 +0,0 @@
1
- export type TSConfig = {
2
- target: string;
3
- jsxImportSource: string | undefined;
4
- hasJsxRuntime: boolean;
5
- };
6
- export declare const getTSConfig: () => Promise<TSConfig | null>;
@@ -1,33 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.getTSConfig = void 0;
7
- const path_1 = require("path");
8
- const typescript_1 = __importDefault(require("typescript"));
9
- const constants_1 = require("../../constants");
10
- const TSCONFIG_PATH = (0, path_1.resolve)(constants_1.CWD, "tsconfig.json");
11
- const getTSConfig = async () => {
12
- try {
13
- const { jsx, jsxImportSource, target } = typescript_1.default.parseJsonConfigFileContent(
14
- // eslint-disable-next-line @typescript-eslint/no-var-requires
15
- require(TSCONFIG_PATH), typescript_1.default.sys, constants_1.CWD).options;
16
- // Convert ts target value to esbuild ones (latest value is not supported)
17
- const esbuildTarget = !target ||
18
- [typescript_1.default.ScriptTarget.ESNext, typescript_1.default.ScriptTarget.Latest].includes(target)
19
- ? "esnext"
20
- : typescript_1.default.ScriptTarget[target]?.toLowerCase();
21
- const hasJsxRuntime = jsx !== undefined &&
22
- [typescript_1.default.JsxEmit["ReactJSX"], typescript_1.default.JsxEmit["ReactJSXDev"]].includes(jsx);
23
- return {
24
- target: esbuildTarget,
25
- jsxImportSource,
26
- hasJsxRuntime,
27
- };
28
- }
29
- catch (error) {
30
- return null;
31
- }
32
- };
33
- exports.getTSConfig = getTSConfig;
@@ -1 +0,0 @@
1
- export { build, watch } from "./bundler";
@@ -1,6 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.watch = exports.build = void 0;
4
- var bundler_1 = require("./bundler");
5
- Object.defineProperty(exports, "build", { enumerable: true, get: function () { return bundler_1.build; } });
6
- Object.defineProperty(exports, "watch", { enumerable: true, get: function () { return bundler_1.watch; } });
@@ -1 +0,0 @@
1
- export {};
@@ -1,25 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const dts_bundle_generator_1 = require("dts-bundle-generator");
4
- const worker_1 = require("threads/worker");
5
- (0, worker_1.expose)((source) => {
6
- const errors = [];
7
- // To prevent any UI glitch, catch any error by monkey patching
8
- // the default error logger and forward them to the parent worker
9
- console.error = (error) => {
10
- errors.push(error);
11
- };
12
- try {
13
- return (0, dts_bundle_generator_1.generateDtsBundle)([
14
- {
15
- filePath: source,
16
- output: {
17
- noBanner: true,
18
- },
19
- },
20
- ])[0];
21
- }
22
- catch {
23
- throw errors;
24
- }
25
- });
@@ -1 +0,0 @@
1
- export {};
@@ -1,15 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const esbuild_1 = require("esbuild");
4
- const worker_1 = require("threads/worker");
5
- const configs_1 = require("../configs");
6
- (0, worker_1.expose)(async (format) => {
7
- const { esbuild, pkg } = await (0, configs_1.getConfigs)({
8
- isProduction: true,
9
- });
10
- const outfile = pkg.destination[format];
11
- if (!outfile)
12
- return null;
13
- await (0, esbuild_1.build)(esbuild({ format, outfile }));
14
- return outfile;
15
- });
@@ -1 +0,0 @@
1
- export declare const CWD: string;
package/bin/constants.js DELETED
@@ -1,4 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.CWD = void 0;
4
- exports.CWD = process.cwd();
package/bin/helpers.d.ts DELETED
@@ -1,6 +0,0 @@
1
- /// <reference types="node" />
2
- import fs from "node:fs/promises";
3
- export declare function assert(condition: unknown, message: string): asserts condition;
4
- export declare const readFile: typeof fs.readFile;
5
- export declare const resolveModulePath: (path: string) => boolean;
6
- export declare const writeFile: (filePath: string, content: string) => Promise<void>;
package/bin/helpers.js DELETED
@@ -1,36 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.writeFile = exports.resolveModulePath = exports.readFile = exports.assert = void 0;
7
- const node_path_1 = require("node:path");
8
- const promises_1 = __importDefault(require("node:fs/promises"));
9
- const node_fs_1 = require("node:fs");
10
- const constants_1 = require("./constants");
11
- // TS assertion not working properly with arrow function
12
- // @see: https://github.com/microsoft/TypeScript/issues/34523
13
- function assert(condition, message) {
14
- if (!condition) {
15
- throw new Error(message);
16
- }
17
- }
18
- exports.assert = assert;
19
- exports.readFile = promises_1.default.readFile;
20
- const resolveModulePath = (path) => {
21
- try {
22
- return Boolean(require.resolve(path, { paths: [constants_1.CWD] }));
23
- }
24
- catch (error) {
25
- return false;
26
- }
27
- };
28
- exports.resolveModulePath = resolveModulePath;
29
- const writeFile = async (filePath, content) => {
30
- const dir = (0, node_path_1.dirname)(filePath);
31
- if (!(0, node_fs_1.existsSync)(dir)) {
32
- await promises_1.default.mkdir(dir, { recursive: true });
33
- }
34
- await promises_1.default.writeFile(filePath, content, "utf8");
35
- };
36
- exports.writeFile = writeFile;
package/bin/index.d.ts DELETED
@@ -1,2 +0,0 @@
1
- #!/usr/bin/env node
2
- import "./program";
package/bin/index.js DELETED
@@ -1,4 +0,0 @@
1
- #!/usr/bin/env node
2
- "use strict";
3
- Object.defineProperty(exports, "__esModule", { value: true });
4
- require("./program");
@@ -1,2 +0,0 @@
1
- import { Termost } from "termost";
2
- export declare const createBuildCommand: (program: Termost) => void;
@@ -1,63 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.createBuildCommand = void 0;
7
- const gzip_size_1 = __importDefault(require("gzip-size"));
8
- const termost_1 = require("termost");
9
- const bundler_1 = require("../../bundler");
10
- const helpers_1 = require("../../helpers");
11
- const createBuildCommand = (program) => {
12
- program
13
- .command({
14
- name: "build",
15
- description: "Build the source code (production mode)",
16
- })
17
- .task({
18
- key: "outfiles",
19
- label: "Bundle assets 📦",
20
- async handler() {
21
- const outfiles = await (0, bundler_1.build)();
22
- return outfiles.filter((outfile) => outfile !== null);
23
- },
24
- })
25
- .task({
26
- key: "sizes",
27
- label: "Compute sizes 🔢",
28
- async handler(context) {
29
- return await calculateBundleSize(context.outfiles);
30
- },
31
- })
32
- .task({
33
- handler(context) {
34
- const padding = context.sizes
35
- .map((item) => item.raw)
36
- .reduce((pad, currentRawSize) => {
37
- return Math.max(pad, String(currentRawSize).length);
38
- }, 0) + 2;
39
- context.sizes.forEach((item) => {
40
- termost_1.helpers.message([
41
- `${item.raw.toString().padStart(padding)} B raw`,
42
- `${item.gzip.toString().padStart(padding)} B gz`,
43
- ], {
44
- label: item.filename,
45
- type: "information",
46
- });
47
- });
48
- },
49
- });
50
- };
51
- exports.createBuildCommand = createBuildCommand;
52
- const calculateBundleSize = async (filenames) => {
53
- const calculateFileSize = async (filename) => {
54
- const content = await (0, helpers_1.readFile)(filename);
55
- const gzSize = await (0, gzip_size_1.default)(content);
56
- return {
57
- filename,
58
- raw: content.byteLength,
59
- gzip: gzSize,
60
- };
61
- };
62
- return await Promise.all(filenames.map((filename) => calculateFileSize(filename)));
63
- };
@@ -1,2 +0,0 @@
1
- import { Termost } from "termost";
2
- export declare const createWatchCommand: (program: Termost) => void;
@@ -1,52 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.createWatchCommand = void 0;
4
- const termost_1 = require("termost");
5
- const bundler_1 = require("../../bundler");
6
- const createWatchCommand = (program) => {
7
- program
8
- .command({
9
- name: "watch",
10
- description: "Watch and rebuild on any code change (development mode)",
11
- })
12
- .task({
13
- key: "callbacks",
14
- label: "Setup watcher",
15
- async handler() {
16
- const callbacks = {
17
- onError() { },
18
- onLoading() { },
19
- onSuccess() { },
20
- };
21
- (0, bundler_1.watch)((type, error) => {
22
- if (type === "loading")
23
- return callbacks.onLoading();
24
- if (error) {
25
- callbacks.onError(String(error));
26
- }
27
- else {
28
- callbacks.onSuccess();
29
- }
30
- });
31
- return callbacks;
32
- },
33
- })
34
- .task({
35
- handler(context) {
36
- const onNotify = (type, message) => {
37
- console.clear();
38
- if (type === "loading") {
39
- termost_1.helpers.message(`Waiting for the build to be done...`, {
40
- type: "information",
41
- });
42
- return;
43
- }
44
- termost_1.helpers.message(`Last update at ${new Date().toLocaleTimeString()}\n${message ? `\n${message}\n` : ""}`, { type });
45
- };
46
- context.callbacks.onSuccess = () => onNotify("success");
47
- context.callbacks.onError = (error) => onNotify("error", error);
48
- context.callbacks.onLoading = () => onNotify("loading");
49
- },
50
- });
51
- };
52
- exports.createWatchCommand = createWatchCommand;
@@ -1 +0,0 @@
1
- export {};
@@ -1,12 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const termost_1 = require("termost");
4
- const build_1 = require("./commands/build");
5
- const watch_1 = require("./commands/watch");
6
- const createProgram = (...commandBuilders) => {
7
- const program = (0, termost_1.termost)("The zero-configuration bundler powered by ESBuild");
8
- for (const commandBuilder of commandBuilders) {
9
- commandBuilder(program);
10
- }
11
- };
12
- createProgram(build_1.createBuildCommand, watch_1.createWatchCommand);