@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.
- package/LICENSE +21 -0
- package/README.md +11 -0
- package/bundling/admin/createBuildAdmin.js +18 -0
- package/bundling/admin/createRsbuildConfig.js +174 -0
- package/bundling/admin/createWatchAdmin.js +15 -0
- package/bundling/admin/index.js +3 -0
- package/bundling/function/createBuildFunction.js +18 -0
- package/bundling/function/createRsbuildConfig.js +126 -0
- package/bundling/function/createWatchFunction.js +15 -0
- package/bundling/function/index.js +3 -0
- package/bundling/importValidatorPlugin.js +93 -0
- package/bundling/printBuildStats.js +46 -0
- package/index.d.ts +69 -0
- package/index.js +3 -0
- package/package.json +82 -0
- package/packages/buildPackage/copyToDist.js +11 -0
- package/packages/buildPackage/rslibCompile.js +65 -0
- package/packages/buildPackage/tsAliasReplacer.js +125 -0
- package/packages/buildPackage/tsCompile.js +80 -0
- package/packages/buildPackage/typescript/getTscBinaryPath.js +47 -0
- package/packages/buildPackage/typescript/readTsConfig.js +8 -0
- package/packages/buildPackage/typescript/runTsc.js +15 -0
- package/packages/buildPackage/typescript/writeTempTsConfig.js +10 -0
- package/packages/buildPackage/validateEsmImports.js +91 -0
- package/packages/buildPackage.js +93 -0
- package/packages/createBuildPackage.js +7 -0
- package/packages/createWatchPackage.js +7 -0
- package/packages/index.js +4 -0
- package/packages/watchPackage.js +39 -0
- package/traverseLoaders.js +14 -0
- package/utils/PackageJson.backup.ts +45 -0
- package/utils/PackageJson.d.ts +33 -0
- package/utils/PackageJson.js +44 -0
- package/utils.js +33 -0
- package/workspaces/index.js +15 -0
- 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,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,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