@webiny/build-tools 0.0.0-unstable.0d717d18dd

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.
Files changed (36) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +11 -0
  3. package/bundling/admin/createBuildAdmin.js +18 -0
  4. package/bundling/admin/createRsbuildConfig.js +174 -0
  5. package/bundling/admin/createWatchAdmin.js +15 -0
  6. package/bundling/admin/index.js +3 -0
  7. package/bundling/function/createBuildFunction.js +18 -0
  8. package/bundling/function/createRsbuildConfig.js +126 -0
  9. package/bundling/function/createWatchFunction.js +15 -0
  10. package/bundling/function/index.js +3 -0
  11. package/bundling/importValidatorPlugin.js +93 -0
  12. package/bundling/printBuildStats.js +46 -0
  13. package/index.d.ts +69 -0
  14. package/index.js +3 -0
  15. package/package.json +82 -0
  16. package/packages/buildPackage/copyToDist.js +11 -0
  17. package/packages/buildPackage/rslibCompile.js +65 -0
  18. package/packages/buildPackage/tsAliasReplacer.js +125 -0
  19. package/packages/buildPackage/tsCompile.js +80 -0
  20. package/packages/buildPackage/typescript/getTscBinaryPath.js +47 -0
  21. package/packages/buildPackage/typescript/readTsConfig.js +8 -0
  22. package/packages/buildPackage/typescript/runTsc.js +15 -0
  23. package/packages/buildPackage/typescript/writeTempTsConfig.js +10 -0
  24. package/packages/buildPackage/validateEsmImports.js +91 -0
  25. package/packages/buildPackage.js +93 -0
  26. package/packages/createBuildPackage.js +7 -0
  27. package/packages/createWatchPackage.js +7 -0
  28. package/packages/index.js +4 -0
  29. package/packages/watchPackage.js +39 -0
  30. package/traverseLoaders.js +14 -0
  31. package/utils/PackageJson.backup.ts +45 -0
  32. package/utils/PackageJson.d.ts +33 -0
  33. package/utils/PackageJson.js +44 -0
  34. package/utils.js +33 -0
  35. package/workspaces/index.js +15 -0
  36. package/workspaces/linkWorkspaces.js +100 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) Webiny
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,11 @@
1
+ # @webiny/build-tools
2
+
3
+ > [!NOTE]
4
+ > This package is part of the [Webiny](https://www.webiny.com) monorepo.
5
+ > It’s **included in every Webiny project by default** and is not meant to be used as a standalone package.
6
+
7
+ 📘 **Documentation:** [https://www.webiny.com/docs](https://www.webiny.com/docs)
8
+
9
+ ---
10
+
11
+ _This README file is automatically generated during the publish process._
@@ -0,0 +1,18 @@
1
+ import { createRsbuildConfig } from "./createRsbuildConfig.js";
2
+ import { printBuildStats } from "../printBuildStats.js";
3
+
4
+ export const createBuildAdmin =
5
+ () =>
6
+ async ({ cwd }) => {
7
+ process.env.NODE_ENV = "production";
8
+
9
+ // Must be a dynamic import — see rslibCompile.js for the reason.
10
+ const { createRsbuild } = await import("@rsbuild/core");
11
+ const rsbuildConfig = createRsbuildConfig({ cwd });
12
+
13
+ const rsbuild = await createRsbuild({ rsbuildConfig });
14
+
15
+ rsbuild.onAfterBuild(printBuildStats({ cwd, label: "admin", extensions: [".js", ".css"] }));
16
+
17
+ await rsbuild.build();
18
+ };
@@ -0,0 +1,174 @@
1
+ import fs from "fs";
2
+ import path from "path";
3
+ import { pluginReact } from "@rsbuild/plugin-react";
4
+ import { pluginSvgr } from "@rsbuild/plugin-svgr";
5
+ import { pluginSass } from "@rsbuild/plugin-sass";
6
+ import { pluginTypeCheck } from "@rsbuild/plugin-type-check";
7
+ import tailwindcss from "@tailwindcss/postcss";
8
+ import { createImportValidatorPlugin } from "../importValidatorPlugin.js";
9
+
10
+ export const createRsbuildConfig = ({ cwd }) => {
11
+ const paths = getPaths(cwd);
12
+ const envVars = getEnvVars();
13
+ const mode = getMode();
14
+
15
+ return /** @type {import("@rsbuild/core").RsbuildConfig} */ ({
16
+ source: {
17
+ entry: {
18
+ index: paths.admin.entryFile
19
+ },
20
+ define: envVars
21
+ },
22
+ output: { distPath: { root: paths.admin.outputFolder } },
23
+ mode,
24
+ dev: { hmr: true },
25
+ performance: {
26
+ printFileSize: false
27
+ },
28
+ tools: {
29
+ postcss: (_, { addPlugins }) => {
30
+ addPlugins([
31
+ createInjectTailwindSourcePlugin(
32
+ path.join(paths.projectRootFolder, "extensions")
33
+ ),
34
+ tailwindcss({
35
+ base: getTailwindBasePath(paths.projectRootFolder)
36
+ }),
37
+ createStripTailwindSourceLeftoverPlugin()
38
+ ]);
39
+ },
40
+ rspack: {
41
+ watchOptions: {
42
+ // Wait for dependency builds to finish before triggering a recompilation.
43
+ aggregateTimeout: 500,
44
+ ignored: ["**/node_modules/**", "**/.git/**"]
45
+ }
46
+ }
47
+ },
48
+ server: { port: process.env.PORT || 3001, host: "0.0.0.0" },
49
+ html: {
50
+ template: paths.projectRootFolder + "/public/index.html"
51
+ },
52
+ plugins: [
53
+ createImportValidatorPlugin(),
54
+ pluginTypeCheck({
55
+ tsCheckerOptions: {
56
+ typescript: { configFile: paths.admin.tsConfig },
57
+ async: mode === "development"
58
+ }
59
+ }),
60
+ pluginReact({
61
+ splitChunks: false
62
+ }),
63
+ pluginSass(),
64
+ pluginSvgr({
65
+ mixedImport: true,
66
+ svgrOptions: {
67
+ exportType: "named",
68
+ svgoConfig: {
69
+ plugins: [
70
+ {
71
+ name: "pres" + "et-default",
72
+ params: { overrides: { removeViewBox: false } }
73
+ }
74
+ ]
75
+ }
76
+ }
77
+ })
78
+ ]
79
+ });
80
+ };
81
+
82
+ const getPaths = cwd => {
83
+ const adminRootFolderPath = cwd;
84
+ const adminOutputFolderPath = path.join(adminRootFolderPath, "build");
85
+ const adminEntryFilePath = path.join(adminRootFolderPath, "src", "index.tsx");
86
+
87
+ const adminTsConfigFilePath = path.join(adminRootFolderPath, "tsconfig.json");
88
+
89
+ return {
90
+ projectRootFolder: process.cwd(),
91
+ admin: {
92
+ rootFolder: adminRootFolderPath,
93
+ tsConfig: adminTsConfigFilePath,
94
+ outputFolder: adminOutputFolderPath,
95
+ entryFile: adminEntryFilePath
96
+ }
97
+ };
98
+ };
99
+
100
+ const getTailwindBasePath = projectRootFolderPath => {
101
+ const adminUiPkgPath = path.join(projectRootFolderPath, "packages", "admin-ui");
102
+
103
+ const isWebinyJsRepo = fs.existsSync(adminUiPkgPath);
104
+
105
+ if (isWebinyJsRepo) {
106
+ return path.join(projectRootFolderPath, "packages");
107
+ }
108
+
109
+ return path.join(projectRootFolderPath, "node_modules", "@webiny");
110
+ };
111
+
112
+ /*
113
+ Injects an `@source` directive into the Tailwind CSS AST at build time, pointing to the
114
+ given absolute path. https://tailwindcss.com/docs/functions-and-directives#source-directive
115
+ */
116
+ const createInjectTailwindSourcePlugin = sourcePath => ({
117
+ postcssPlugin: "inject-tailwind-source",
118
+ Once(root) {
119
+ root.prepend(`@source "${sourcePath}";`);
120
+ }
121
+ });
122
+
123
+ /*
124
+ Removes any leftover `@source` at-rule from the output. Tailwind v4 strips the
125
+ directive from files it processes, but `@tailwindcss/postcss` only processes
126
+ files containing one of its trigger at-rules; for other files (e.g., pre-bundled
127
+ component CSS imported through JS), the injected directive would otherwise
128
+ survive into the production bundle, exposing the absolute build-machine path.
129
+ */
130
+ const createStripTailwindSourceLeftoverPlugin = () => ({
131
+ postcssPlugin: "strip-tailwind-source-leftover",
132
+ Once(root) {
133
+ root.walkAtRules("source", node => node.remove());
134
+ }
135
+ });
136
+
137
+ const getEnvVars = () => {
138
+ const raw = Object.keys(process.env)
139
+ .filter(key => {
140
+ if (new RegExp(/^REACT_APP_/i).test(key)) {
141
+ return true;
142
+ }
143
+
144
+ return new RegExp(/^WEBINY_ADMIN_/i).test(key);
145
+ })
146
+ .reduce(
147
+ (env, key) => {
148
+ env[key] = process.env[key];
149
+ return env;
150
+ },
151
+ {
152
+ // Useful for determining whether we're running in production mode.
153
+ // Most importantly, it switches React into the correct mode.
154
+ NODE_ENV: process.env.NODE_ENV || "development"
155
+ }
156
+ );
157
+
158
+ // Stringify all values so we can feed into Webpack DefinePlugin.
159
+ // Provide values one by one, not as a single process.env object,
160
+ // because otherwise plugin will put a big JSON object every time process.env is used in code.
161
+ // This way minifier also removes redundant code on prod (like if(process.env.NODE_ENV === 'development')).
162
+ const envVarsAsStrings = {
163
+ "process.env": "{}"
164
+ };
165
+ for (const key of Object.keys(raw)) {
166
+ envVarsAsStrings[`process.env.${key}`] = JSON.stringify(raw[key]);
167
+ }
168
+
169
+ return envVarsAsStrings;
170
+ };
171
+
172
+ const getMode = () => {
173
+ return process.env.NODE_ENV === "production" ? "production" : "development";
174
+ };
@@ -0,0 +1,15 @@
1
+ import { createRsbuildConfig } from "./createRsbuildConfig.js";
2
+
3
+ export const createWatchAdmin =
4
+ () =>
5
+ async ({ cwd }) => {
6
+ process.env.NODE_ENV = "development";
7
+
8
+ // Must be a dynamic import — see rslibCompile.js for the reason.
9
+ const { createRsbuild } = await import("@rsbuild/core");
10
+ const rsbuildConfig = createRsbuildConfig({ cwd });
11
+
12
+ const rsbuild = await createRsbuild({ rsbuildConfig });
13
+
14
+ await rsbuild.startDevServer();
15
+ };
@@ -0,0 +1,3 @@
1
+ export { createBuildAdmin } from "./createBuildAdmin.js";
2
+ export { createWatchAdmin } from "./createWatchAdmin.js";
3
+ export { printBuildStats } from "../printBuildStats.js";
@@ -0,0 +1,18 @@
1
+ import { createRsbuildConfig } from "./createRsbuildConfig.js";
2
+ import { printBuildStats } from "../printBuildStats.js";
3
+
4
+ export const createBuildFunction =
5
+ () =>
6
+ async ({ cwd }) => {
7
+ process.env.NODE_ENV = "production";
8
+
9
+ // Must be a dynamic import — see rslibCompile.js for the reason.
10
+ const { createRsbuild } = await import("@rsbuild/core");
11
+ const rsbuildConfig = await createRsbuildConfig({ cwd, enforceMaxBundleSize: true });
12
+
13
+ const rsbuild = await createRsbuild({ rsbuildConfig });
14
+
15
+ rsbuild.onAfterBuild(printBuildStats({ cwd, label: "node", extensions: [".mjs"] }));
16
+
17
+ await rsbuild.build();
18
+ };
@@ -0,0 +1,126 @@
1
+ import path from "path";
2
+ import { pluginTypeCheck } from "@rsbuild/plugin-type-check";
3
+ import { createImportValidatorPlugin } from "../importValidatorPlugin.js";
4
+
5
+ const DEFAULT_WEBINY_INFRA_API_MAX_BUNDLE_SIZE = 6_291_456; // 6 MB
6
+
7
+ export const createRsbuildConfig = async ({ cwd, enforceMaxBundleSize }) => {
8
+ // Must be a dynamic import — see rslibCompile.js for the reason.
9
+ const { default: rspack } = await import("@rspack/core");
10
+ const paths = getPaths(cwd);
11
+ const mode = getMode();
12
+ const isDebugEnabled = process.env.DEBUG === "true";
13
+ // NOTE: dirty for now — sniffing the hosting type off an env var here. Ideally the build config
14
+ // wouldn't know about hosting types at all: the caller (createBuildFunction, or the flavour's own
15
+ // build layer) would pass in the externals policy + assetPrefix as options, keeping this file
16
+ // hosting-agnostic. Good enough while the server hosting type is ALPHA; revisit when it settles.
17
+ const isServer = process.env.WEBINY_HOSTING_TYPE === "server";
18
+
19
+ // Configurable via WEBINY_INFRA_API_MAX_BUNDLE_SIZE (bytes).
20
+ // Only enforced during build — watch mode skips size checks.
21
+ const maxBundleSize =
22
+ parseInt(process.env.WEBINY_INFRA_API_MAX_BUNDLE_SIZE) ||
23
+ DEFAULT_WEBINY_INFRA_API_MAX_BUNDLE_SIZE;
24
+
25
+ return /** @type {import("@rsbuild/core").RsbuildConfig} */ ({
26
+ source: { entry: { index: paths.fn.entryFile } },
27
+ // Resolve chunk/asset URLs relative to the running module, not from an absolute root. The
28
+ // server's bg-tasks worker chunk is spawned via `new Worker(new URL("...", import.meta.url))`
29
+ // and rsbuild's default publicPath "/" turns that into an ABSOLUTE url ("/xyz.mjs"), which
30
+ // resolves to the filesystem root and can't be found. "auto" resolves it relative to the module
31
+ // (handler.mjs) instead, so the chunk loads from build/. publicPath comes from
32
+ // `output.assetPrefix` in production and `dev.assetPrefix` in development (watch runs
33
+ // `rsbuild.build({ watch: true })` under NODE_ENV=development), so set BOTH. Not gated to the
34
+ // server hosting type: AWS has no worker chunks so it's a no-op there, and for any other
35
+ // (async import) chunks "auto" is at least as correct as "/" (Lambda runs from its own dir too).
36
+ dev: { assetPrefix: "auto" },
37
+ output: {
38
+ module: true,
39
+ target: "node",
40
+ assetPrefix: "auto",
41
+ minify: true,
42
+ sourceMap: {
43
+ js: isDebugEnabled || mode === "development" ? "source-map" : false
44
+ },
45
+ filename: {
46
+ js: pathData => {
47
+ if (pathData.chunk?.name === "index") {
48
+ return "handler.mjs";
49
+ }
50
+ return "[name].mjs";
51
+ }
52
+ },
53
+ distPath: { root: paths.fn.outputFolder }
54
+ },
55
+ performance: {
56
+ printFileSize: false
57
+ },
58
+ tools: {
59
+ rspack: {
60
+ ...(enforceMaxBundleSize && {
61
+ performance: {
62
+ hints: "error",
63
+ maxEntrypointSize: maxBundleSize,
64
+ maxAssetSize: maxBundleSize
65
+ }
66
+ }),
67
+ // Both hosting types bundle; externalize only what genuinely can't be bundled.
68
+ // sharp is a native .node binary; knex statically require()s a driver for every SQL
69
+ // dialect (bundling pulls in uninstalled ones) and lazily loads only the configured
70
+ // one at runtime (e.g. better-sqlite3). AWS additionally externalizes aws-sdk (the
71
+ // Lambda runtime provides it). Server ships these in build/node_modules — the build's
72
+ // packaging step (CI/Linux) copies them, natives included.
73
+ externals: isServer
74
+ ? [/^sharp$/, /^knex(\/|$)/]
75
+ : [/^@aws-sdk/, /^aws-sdk$/, /^sharp$/, /^knex(\/|$)/],
76
+ plugins: [
77
+ // Ignore optional `canvas` native module required by jsdom.
78
+ // https://rspack.dev/plugins/webpack/ignore-plugin
79
+ new rspack.IgnorePlugin({
80
+ resourceRegExp: /^canvas$/,
81
+ contextRegExp: /jsdom/
82
+ })
83
+ ],
84
+ resolve: {
85
+ fallback: {
86
+ // Disable optional native dependency used by 'ws' package for performance optimizations.
87
+ // Not needed in Lambda environment and can cause bundling/deployment issues.
88
+ bufferutil: false
89
+ }
90
+ }
91
+ }
92
+ },
93
+ mode,
94
+ plugins: [
95
+ createImportValidatorPlugin(),
96
+ pluginTypeCheck({
97
+ tsCheckerOptions: {
98
+ typescript: { configFile: paths.fn.tsConfig },
99
+ async: mode === "development"
100
+ }
101
+ })
102
+ ]
103
+ });
104
+ };
105
+
106
+ const getPaths = cwd => {
107
+ const fnRootFolderPath = cwd;
108
+ const fnOutputFolderPath = path.join(fnRootFolderPath, "build");
109
+ const fnEntryFilePath = path.join(fnRootFolderPath, "src", "index.ts");
110
+
111
+ const fnTsConfigFilePath = path.join(fnRootFolderPath, "tsconfig.json");
112
+
113
+ return {
114
+ projectRootFolder: process.cwd(),
115
+ fn: {
116
+ rootFolder: fnRootFolderPath,
117
+ tsConfig: fnTsConfigFilePath,
118
+ outputFolder: fnOutputFolderPath,
119
+ entryFile: fnEntryFilePath
120
+ }
121
+ };
122
+ };
123
+
124
+ const getMode = () => {
125
+ return process.env.NODE_ENV === "production" ? "production" : "development";
126
+ };
@@ -0,0 +1,15 @@
1
+ import { createRsbuildConfig } from "./createRsbuildConfig.js";
2
+
3
+ export const createWatchFunction =
4
+ () =>
5
+ async ({ cwd }) => {
6
+ process.env.NODE_ENV = "development";
7
+
8
+ // Must be a dynamic import — see rslibCompile.js for the reason.
9
+ const { createRsbuild } = await import("@rsbuild/core");
10
+ const rsbuildConfig = await createRsbuildConfig({ cwd, enforceMaxBundleSize: false });
11
+
12
+ const rsbuild = await createRsbuild({ rsbuildConfig });
13
+
14
+ await rsbuild.build({ watch: true });
15
+ };
@@ -0,0 +1,3 @@
1
+ export { createBuildFunction } from "./createBuildFunction.js";
2
+ export { createWatchFunction } from "./createWatchFunction.js";
3
+ export { printBuildStats } from "../printBuildStats.js";
@@ -0,0 +1,93 @@
1
+ // ANSI color codes
2
+ const red = "\x1b[31m";
3
+ const yellow = "\x1b[33m";
4
+ const cyan = "\x1b[36m";
5
+ const reset = "\x1b[0m";
6
+ const bold = "\x1b[1m";
7
+
8
+ const whitelist = [
9
+ "@webiny/cognito",
10
+ "@webiny/auth0",
11
+ "@webiny/okta",
12
+ "@webiny/self-hosted-auth",
13
+ "@webiny/plugins",
14
+ "@webiny/sdk",
15
+ "@webiny/stdlib",
16
+ "@webiny/lexical-converter",
17
+ "@webiny/lexical-nodes",
18
+ "@webiny/lexical-theme"
19
+ ];
20
+
21
+ export const createImportValidatorPlugin = () => {
22
+ return {
23
+ name: "extensions-import-validator",
24
+ setup(api) {
25
+ api.modifyRspackConfig(config => {
26
+ config.plugins = config.plugins || [];
27
+ config.plugins.push({
28
+ name: "ExtensionsImportValidatorPlugin",
29
+ apply(compiler) {
30
+ compiler.hooks.compilation.tap(
31
+ "ExtensionsImportValidatorPlugin",
32
+ (compilation, { normalModuleFactory }) => {
33
+ normalModuleFactory.hooks.beforeResolve.tap(
34
+ "ExtensionsImportValidatorPlugin",
35
+ resolveData => {
36
+ const request = resolveData.request;
37
+ const contextInfo = resolveData.contextInfo;
38
+ const issuer = contextInfo?.issuer;
39
+
40
+ // Check if the import request is a @webiny/* package
41
+ if (!request?.startsWith("@webiny/")) {
42
+ return;
43
+ }
44
+
45
+ // Allow whitelisted packages
46
+ if (whitelist.some(pkg => request.startsWith(pkg))) {
47
+ return;
48
+ }
49
+
50
+ // Check if the import originates from extensions folder
51
+ if (!issuer) {
52
+ return;
53
+ }
54
+
55
+ const normalizedIssuer = issuer.replace(/\\/g, "/");
56
+
57
+ // Check if the issuer is within the extensions folder
58
+ if (!normalizedIssuer.includes("/extensions/")) {
59
+ return;
60
+ }
61
+
62
+ // Check if the import is coming through the webiny parent package
63
+ // by checking if the issuer is from node_modules/webiny
64
+ const issuerModule = contextInfo?.issuerModule;
65
+ if (issuerModule) {
66
+ const moduleIdentifier =
67
+ issuerModule.identifier?.() || "";
68
+ if (
69
+ moduleIdentifier.includes("/node_modules/webiny/")
70
+ ) {
71
+ return; // Allow imports through webiny package
72
+ }
73
+ }
74
+
75
+ const error = new Error(
76
+ `${red}Direct imports of @webiny/* packages are not allowed. Import from "webiny" package instead.${reset}\n\n` +
77
+ `${bold}Location:${reset} ${cyan}${issuer.replace(process.cwd(), "")}${reset}\n` +
78
+ `${bold}Import:${reset} ${yellow}${request}${reset}\n`
79
+ );
80
+ error.name = "ExtensionsImportError";
81
+ error.hideStack = true;
82
+
83
+ compilation.errors.push(error);
84
+ }
85
+ );
86
+ }
87
+ );
88
+ }
89
+ });
90
+ });
91
+ }
92
+ };
93
+ };
@@ -0,0 +1,46 @@
1
+ import path from "path";
2
+ import chalk from "chalk";
3
+
4
+ export const printBuildStats =
5
+ ({ cwd, label = "build", extensions = [".js", ".mjs", ".css"] }) =>
6
+ ({ stats }) => {
7
+ if (!stats) {
8
+ return;
9
+ }
10
+
11
+ const statsJson = stats.toJson({ assets: true, children: false });
12
+ const assets = statsJson.assets || [];
13
+
14
+ // Compute cleaner display path
15
+ const projectRoot = process.cwd();
16
+ const outputPath = statsJson.outputPath || path.join(cwd, "build");
17
+ const webinyWorkspacePrefix = ".webiny/workspace/";
18
+ let displayPath = path.relative(projectRoot, outputPath);
19
+
20
+ if (displayPath.startsWith(webinyWorkspacePrefix)) {
21
+ displayPath = displayPath.slice(webinyWorkspacePrefix.length);
22
+ }
23
+
24
+ // Sort assets by size for better readability
25
+ const sortedAssets = assets
26
+ .filter(asset => extensions.some(ext => asset.name.endsWith(ext)))
27
+ .sort((a, b) => a.size - b.size);
28
+
29
+ // Print header with blue color
30
+ console.log(
31
+ `\n${chalk.blue(`File (${label})`.padEnd(50))}${chalk.blue("Size".padStart(11))}`
32
+ );
33
+
34
+ let totalSize = 0;
35
+ for (const asset of sortedAssets) {
36
+ const fileName = path.basename(asset.name);
37
+ const sizeKB = (asset.size / 1024).toFixed(1);
38
+ totalSize += asset.size;
39
+
40
+ // Print filename in cyan
41
+ console.log(`${chalk.cyan(fileName.padEnd(50))}${sizeKB.padStart(10)} kB`);
42
+ }
43
+
44
+ const totalSizeKB = (totalSize / 1024).toFixed(1);
45
+ console.log(`\n${chalk.magenta("Total:".padEnd(50))}${totalSizeKB.padStart(10)} kB\n`);
46
+ };
package/index.d.ts ADDED
@@ -0,0 +1,69 @@
1
+ import { Configuration as RspackConfig } from "@rspack/core";
2
+
3
+ export { RspackConfig };
4
+
5
+ // Build commands.
6
+ export type BuildCommand<TOptions = Record<string, any>> = (options: TOptions) => Promise<void>;
7
+
8
+ export interface SwcConfig {
9
+ [key: string]: any;
10
+ }
11
+
12
+ export interface DefinePluginOptions {
13
+ [key: string]: any;
14
+ }
15
+
16
+ export interface BuildAppConfigOverrides {
17
+ entry?: string;
18
+ openBrowser?: boolean;
19
+ }
20
+ // Build commands - apps.
21
+ export interface BuildAppConfig {
22
+ cwd: string;
23
+ openBrowser?: boolean;
24
+ overrides?: BuildAppConfigOverrides;
25
+ }
26
+
27
+ export function createBuildAdmin(options: BuildAppConfig): BuildCommand;
28
+ export function createWatchAdmin(options: BuildAppConfig): BuildCommand;
29
+
30
+ // Build commands - functions.
31
+ interface BuildFunctionConfig {
32
+ [key: string]: any;
33
+ cwd: string;
34
+ logs?: boolean;
35
+ debug?: boolean;
36
+ /**
37
+ * Enables or disables source map generation for the function.
38
+ * By default is set to `true`
39
+ */
40
+ sourceMaps?: boolean;
41
+ overrides?: {
42
+ entry?: string;
43
+ output?: {
44
+ path?: string;
45
+ filename?: string;
46
+ };
47
+ define?: DefinePluginOptions;
48
+ rspack?: (config: RspackConfig) => RspackConfig;
49
+ swc?: (config: SwcConfig) => SwcConfig;
50
+ };
51
+ }
52
+
53
+ export function createBuildFunction(options: BuildFunctionConfig): BuildCommand;
54
+ export function createWatchFunction(options: BuildFunctionConfig): BuildCommand;
55
+
56
+ // Build commands - packages.
57
+ interface BuildPackageConfig {
58
+ [key: string]: any;
59
+ cwd: string;
60
+ logs?: boolean;
61
+ debug?: boolean;
62
+
63
+ overrides?: {
64
+ tsConfig?: Record<string, any> | ((tsConfig: Record<string, any>) => Record<string, any>);
65
+ };
66
+ }
67
+
68
+ export function createBuildPackage(options: BuildPackageConfig): BuildCommand;
69
+ export function createWatchPackage(options: BuildPackageConfig): BuildCommand;
package/index.js ADDED
@@ -0,0 +1,3 @@
1
+ export { createWatchAdmin, createBuildAdmin } from "./bundling/admin/index.js";
2
+ export { createBuildFunction, createWatchFunction } from "./bundling/function/index.js";
3
+ export { createWatchPackage, createBuildPackage } from "./packages/index.js";