@webiny/build-tools 6.6.0-alpha.0 → 6.6.0-alpha.1

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.
@@ -45,7 +45,12 @@ export const createRsbuildConfig = ({ cwd }) => {
45
45
  }
46
46
  }
47
47
  },
48
- server: { port: process.env.PORT || 3001, host: "0.0.0.0" },
48
+ // Port precedence matches the served admin app (`webiny serve admin`): an explicit
49
+ // WEBINY_ADMIN_PORT wins, then a PORT injected by the environment, then the 3001 default.
50
+ server: {
51
+ port: process.env.WEBINY_ADMIN_PORT || process.env.PORT || 3001,
52
+ host: "0.0.0.0"
53
+ },
49
54
  html: {
50
55
  template: paths.projectRootFolder + "/public/index.html"
51
56
  },
@@ -2,7 +2,7 @@ import path from "path";
2
2
  import { pluginTypeCheck } from "@rsbuild/plugin-type-check";
3
3
  import { createImportValidatorPlugin } from "../importValidatorPlugin.js";
4
4
 
5
- const DEFAULT_WEBINY_INFRA_API_MAX_BUNDLE_SIZE = 4_718_592; // 4.5 MB
5
+ const DEFAULT_WEBINY_INFRA_API_MAX_BUNDLE_SIZE = 6_291_456; // 6 MB
6
6
 
7
7
  export const createRsbuildConfig = async ({ cwd, enforceMaxBundleSize }) => {
8
8
  // Must be a dynamic import — see rslibCompile.js for the reason.
@@ -57,6 +57,21 @@ export const createRsbuildConfig = async ({ cwd, enforceMaxBundleSize }) => {
57
57
  },
58
58
  tools: {
59
59
  rspack: {
60
+ output: {
61
+ // Declares the entry's exports as the bundle's public API, so ALL of them survive.
62
+ //
63
+ // Nothing imports an entry's exports, so without this rspack treats any unused one
64
+ // as dead: it dropped `streamHandler` AND every module reachable only from it. The
65
+ // api bundle then exported just `handler` and contained zero streaming code, so the
66
+ // response-streaming Lambda (`handler.streamHandler`) had no handler to load and
67
+ // failed at cold start. `handler` survived only by accident of being first.
68
+ //
69
+ // To verify after changing anything here, grep the built bundle:
70
+ // .webiny/workspace/apps/api/graphql/build/_handler.mjs
71
+ // It must export BOTH `handler` and `streamHandler`. Removing this line takes the
72
+ // export count back to one — silently, with a green build.
73
+ library: { type: "module" }
74
+ },
60
75
  ...(enforceMaxBundleSize && {
61
76
  performance: {
62
77
  hints: "error",
@@ -74,11 +89,11 @@ export const createRsbuildConfig = async ({ cwd, enforceMaxBundleSize }) => {
74
89
  ? [/^sharp$/, /^knex(\/|$)/]
75
90
  : [/^@aws-sdk/, /^aws-sdk$/, /^sharp$/, /^knex(\/|$)/],
76
91
  plugins: [
77
- // This is necessary to enable JSDOM usage in Lambda.
92
+ // Ignore optional `canvas` native module required by jsdom.
78
93
  // https://rspack.dev/plugins/webpack/ignore-plugin
79
94
  new rspack.IgnorePlugin({
80
- resourceRegExp: /canvas/,
81
- contextRegExp: /jsdom$/
95
+ resourceRegExp: /^canvas$/,
96
+ contextRegExp: /jsdom/
82
97
  })
83
98
  ],
84
99
  resolve: {
@@ -87,7 +102,19 @@ export const createRsbuildConfig = async ({ cwd, enforceMaxBundleSize }) => {
87
102
  // Not needed in Lambda environment and can cause bundling/deployment issues.
88
103
  bufferutil: false
89
104
  }
90
- }
105
+ },
106
+ // bree's root-jobs loader does `await import(importUrl)` on a path it builds at runtime,
107
+ // which rspack can't resolve statically, so it reports a critical dependency. That import
108
+ // sits behind `if (this.config.root && ...)` (node_modules/bree/src/index.js), and
109
+ // BreeSchedulerService constructs Bree with `root: false` — the branch never runs, and
110
+ // nothing is missing from the bundle. Matched narrowly so a genuine expression-based
111
+ // import anywhere else still gets reported.
112
+ ignoreWarnings: [
113
+ {
114
+ module: /node_modules[\\/]bree[\\/]/,
115
+ message: /Critical dependency: the request of a dependency is an expression/
116
+ }
117
+ ]
91
118
  }
92
119
  },
93
120
  mode,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webiny/build-tools",
3
- "version": "6.6.0-alpha.0",
3
+ "version": "6.6.0-alpha.1",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": "./index.js",
@@ -17,17 +17,17 @@
17
17
  "Adrian Smijulj <adrian@webiny.com>"
18
18
  ],
19
19
  "dependencies": {
20
- "@rsbuild/core": "2.1.8",
20
+ "@rsbuild/core": "2.1.13",
21
21
  "@rsbuild/plugin-react": "2.1.0",
22
22
  "@rsbuild/plugin-sass": "2.0.1",
23
23
  "@rsbuild/plugin-svgr": "2.0.5",
24
24
  "@rsbuild/plugin-type-check": "1.6.0",
25
- "@rsdoctor/rspack-plugin": "1.6.1",
25
+ "@rsdoctor/rspack-plugin": "1.6.2",
26
26
  "@rslib/core": "0.23.2",
27
- "@rspack/core": "2.1.5",
28
- "@swc/plugin-emotion": "14.15.0",
27
+ "@rspack/core": "2.1.10",
28
+ "@swc/plugin-emotion": "15.0.0",
29
29
  "@tailwindcss/postcss": "4.3.3",
30
- "@webiny/stdlib": "0.0.14",
30
+ "@webiny/stdlib": "0.0.17",
31
31
  "chalk": "6.0.0",
32
32
  "css-loader": "7.1.4",
33
33
  "fast-glob": "3.3.3",
@@ -40,15 +40,16 @@
40
40
  "react-dom": "18.3.1",
41
41
  "react-refresh": "0.18.0",
42
42
  "rimraf": "6.1.3",
43
- "sass": "1.102.0",
43
+ "sass": "1.103.1",
44
44
  "sass-loader": "17.0.0",
45
45
  "strip-json-comments": "5.0.3",
46
46
  "style-loader": "4.0.0",
47
47
  "ts-morph": "28.0.0",
48
- "tsx": "4.23.1",
48
+ "tsx": "4.23.12",
49
49
  "typescript": "7.0.2",
50
50
  "url-loader": "4.1.1",
51
- "utf-8-validate": "6.0.6"
51
+ "utf-8-validate": "6.0.6",
52
+ "yargs": "18.1.0"
52
53
  },
53
54
  "license": "MIT",
54
55
  "adio": {
@@ -0,0 +1,6 @@
1
+ interface Preset {
2
+ setupFiles?: string[];
3
+ setupFilesAfterEnv?: string[];
4
+ }
5
+
6
+ export function getPresets(...keywords: string[][]): Promise<Preset[]>;
@@ -0,0 +1,162 @@
1
+ import path from "path";
2
+ import fs from "fs";
3
+ import { listWorkspaces } from "@webiny/stdlib/node";
4
+ import yargs from "yargs";
5
+ import { hideBin } from "yargs/helpers";
6
+ import { PackageJson } from "@webiny/build-tools/utils/PackageJson.js";
7
+
8
+ const MIN_STORAGE_LENGTH = 1;
9
+ const DEFAULT_STORAGE = "ddb";
10
+ /**
11
+ * @param argv {string[]}
12
+ * @returns {string}
13
+ */
14
+ const getStorage = argv => {
15
+ /**
16
+ * Storage is available in process.env?
17
+ */
18
+ const envValue = process.env.WEBINY_STORAGE;
19
+ if (typeof envValue === "string" && envValue.length > 2) {
20
+ return envValue;
21
+ }
22
+ /**
23
+ * This is if storage is available in args.
24
+ */
25
+ const args = yargs(argv);
26
+ const argsValue = args.storage;
27
+ if (typeof argsValue === "string" && argsValue.length > 2) {
28
+ return argsValue;
29
+ }
30
+ /**
31
+ * Then we try to get --storage=([a-z])
32
+ */
33
+ const matched = argv
34
+ .map(item => {
35
+ const matched = item.match(/^--storage=([^\s]+)$/);
36
+ return matched ? matched[1] : null;
37
+ })
38
+ .find(item => {
39
+ return !!item;
40
+ });
41
+ if (typeof matched === "string" && matched.length > MIN_STORAGE_LENGTH) {
42
+ return matched;
43
+ }
44
+ /**
45
+ * Last attempt is to find --storage and then take next index.
46
+ */
47
+ const index = argv.findIndex(item => {
48
+ return item === "--storage";
49
+ });
50
+ if (index === -1) {
51
+ return DEFAULT_STORAGE;
52
+ }
53
+ const value = argv[index + 1];
54
+ if (typeof value === "string" && value.length > MIN_STORAGE_LENGTH) {
55
+ return value;
56
+ }
57
+ return DEFAULT_STORAGE;
58
+ };
59
+
60
+ const getAllPackages = targetKeywords => {
61
+ const storage = getStorage(hideBin(process.argv));
62
+
63
+ if (!storage) {
64
+ throw Error(`Missing required --storage parameter!`);
65
+ }
66
+
67
+ // Set the storage type as an environment variable.
68
+ process.env.WEBINY_STORAGE_OPS = storage;
69
+
70
+ const storagePriority = storage.split(",");
71
+
72
+ const packages = listWorkspaces({
73
+ cwd: process.cwd()
74
+ })
75
+ .map(pkg => {
76
+ return pkg.path.replace(/\\/g, "/");
77
+ })
78
+ .filter(pkg => pkg.match(/\/packages\//) !== null);
79
+
80
+ // Find packages that match the given sets of tags.
81
+ const packageJsons = [];
82
+ for (const pkg of packages) {
83
+ const pkgJson = PackageJson.fromFile(pkg + "/package.json");
84
+ const { name, keywords = [] } = pkgJson.getJson();
85
+
86
+ for (const set of targetKeywords) {
87
+ if (set.every(tag => keywords.includes(tag))) {
88
+ packageJsons.push({
89
+ path: pkg,
90
+ name,
91
+ keywords
92
+ });
93
+ }
94
+ }
95
+ }
96
+ // Now we need to filter based on the required storage type, but also use fallback, if possible.
97
+ const results = [];
98
+
99
+ for (const set of targetKeywords) {
100
+ for (const storage of storagePriority) {
101
+ const matchingPackage = packageJsons.find(pkg => {
102
+ return [...set, storage].every(tag => pkg.keywords.includes(tag));
103
+ });
104
+
105
+ if (matchingPackage) {
106
+ results.push(matchingPackage);
107
+ break;
108
+ }
109
+ }
110
+ }
111
+
112
+ return results;
113
+ };
114
+
115
+ const removeEmptyPreset = preset => {
116
+ if (!preset || Object.keys(preset).length === 0) {
117
+ return false;
118
+ }
119
+ return true;
120
+ };
121
+
122
+ const getPackagesPresets = async targetKeywords => {
123
+ if (!targetKeywords || targetKeywords.length === 0) {
124
+ throw new Error(`You must pass keywords to search for in the packages.`);
125
+ }
126
+
127
+ if (!Array.isArray(targetKeywords[0])) {
128
+ targetKeywords = [targetKeywords];
129
+ }
130
+
131
+ const packages = getAllPackages(targetKeywords);
132
+ if (packages.length === 0) {
133
+ return [];
134
+ }
135
+ const items = [];
136
+ /**
137
+ * We go through all available packages to build presets for them.
138
+ */
139
+ for (const pkg of packages) {
140
+ const presetsPath = path.join(pkg.path, "__tests__/__api__/presets.js");
141
+ if (!fs.existsSync(presetsPath)) {
142
+ throw new Error(`Missing presets.js of the "${pkg.name}" package: ${presetsPath}`);
143
+ }
144
+ /**
145
+ * We expect presets file to contain an array of presets.
146
+ * We do not check for the actual contents of the presets arrays since they can be quite different per package.
147
+ */
148
+ const presets = await import(presetsPath).then(m => m.default ?? m);
149
+ if (Array.isArray(presets) === false) {
150
+ throw new Error(`Presets in package "${pkg.name}" must be defined as an array.`);
151
+ } else if (presets.length === 0) {
152
+ throw new Error(`There are no presets in the file "${presetsPath}".`);
153
+ }
154
+
155
+ items.push(...presets.filter(removeEmptyPreset));
156
+ }
157
+ return items;
158
+ };
159
+
160
+ export const getPresets = async (...targetKeywords) => {
161
+ return getPackagesPresets(targetKeywords);
162
+ };