@webiny/build-tools 0.0.0-unstable.81ae05e56b → 0.0.0-unstable.a4f3e4ea8b

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,4 +1,3 @@
1
- import { createRsbuild } from "@rsbuild/core";
2
1
  import { createRsbuildConfig } from "./createRsbuildConfig.js";
3
2
  import { printBuildStats } from "../printBuildStats.js";
4
3
 
@@ -7,6 +6,8 @@ export const createBuildAdmin =
7
6
  async ({ cwd }) => {
8
7
  process.env.NODE_ENV = "production";
9
8
 
9
+ // Must be a dynamic import — see rslibCompile.js for the reason.
10
+ const { createRsbuild } = await import("@rsbuild/core");
10
11
  const rsbuildConfig = createRsbuildConfig({ cwd });
11
12
 
12
13
  const rsbuild = await createRsbuild({ rsbuildConfig });
@@ -19,12 +19,6 @@ export const createRsbuildConfig = ({ cwd }) => {
19
19
  },
20
20
  define: envVars
21
21
  },
22
- resolve: {
23
- alias: {
24
- // This is a temporary fix, until we sort out the `react-butterfiles` dependency.
25
- "react-butterfiles": "@webiny/app/react-butterfiles"
26
- }
27
- },
28
22
  output: { distPath: { root: paths.admin.outputFolder } },
29
23
  mode,
30
24
  dev: { hmr: true },
@@ -33,11 +27,15 @@ export const createRsbuildConfig = ({ cwd }) => {
33
27
  },
34
28
  tools: {
35
29
  postcss: (_, { addPlugins }) => {
36
- addPlugins(
30
+ addPlugins([
31
+ createInjectTailwindSourcePlugin(
32
+ path.join(paths.projectRootFolder, "extensions")
33
+ ),
37
34
  tailwindcss({
38
35
  base: getTailwindBasePath(paths.projectRootFolder)
39
- })
40
- );
36
+ }),
37
+ createStripTailwindSourceLeftoverPlugin()
38
+ ]);
41
39
  },
42
40
  rspack: {
43
41
  watchOptions: {
@@ -47,7 +45,7 @@ export const createRsbuildConfig = ({ cwd }) => {
47
45
  }
48
46
  }
49
47
  },
50
- server: { port: 3001 },
48
+ server: { port: process.env.PORT || 3001, host: "0.0.0.0" },
51
49
  html: {
52
50
  template: paths.projectRootFolder + "/public/index.html"
53
51
  },
@@ -111,6 +109,31 @@ const getTailwindBasePath = projectRootFolderPath => {
111
109
  return path.join(projectRootFolderPath, "node_modules", "@webiny");
112
110
  };
113
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
+
114
137
  const getEnvVars = () => {
115
138
  const raw = Object.keys(process.env)
116
139
  .filter(key => {
@@ -1,4 +1,3 @@
1
- import { createRsbuild } from "@rsbuild/core";
2
1
  import { createRsbuildConfig } from "./createRsbuildConfig.js";
3
2
 
4
3
  export const createWatchAdmin =
@@ -6,6 +5,8 @@ export const createWatchAdmin =
6
5
  async ({ cwd }) => {
7
6
  process.env.NODE_ENV = "development";
8
7
 
8
+ // Must be a dynamic import — see rslibCompile.js for the reason.
9
+ const { createRsbuild } = await import("@rsbuild/core");
9
10
  const rsbuildConfig = createRsbuildConfig({ cwd });
10
11
 
11
12
  const rsbuild = await createRsbuild({ rsbuildConfig });
@@ -1,4 +1,3 @@
1
- import { createRsbuild } from "@rsbuild/core";
2
1
  import { createRsbuildConfig } from "./createRsbuildConfig.js";
3
2
  import { printBuildStats } from "../printBuildStats.js";
4
3
 
@@ -7,7 +6,9 @@ export const createBuildFunction =
7
6
  async ({ cwd }) => {
8
7
  process.env.NODE_ENV = "production";
9
8
 
10
- const rsbuildConfig = createRsbuildConfig({ cwd });
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 });
11
12
 
12
13
  const rsbuild = await createRsbuild({ rsbuildConfig });
13
14
 
@@ -1,19 +1,30 @@
1
1
  import path from "path";
2
- import rspack from "@rspack/core";
3
2
  import { pluginTypeCheck } from "@rsbuild/plugin-type-check";
4
3
  import { createImportValidatorPlugin } from "../importValidatorPlugin.js";
5
4
 
6
- export const createRsbuildConfig = ({ cwd }) => {
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");
7
10
  const paths = getPaths(cwd);
8
11
  const mode = getMode();
12
+ const isDebugEnabled = process.env.DEBUG === "true";
13
+
14
+ // Configurable via WEBINY_INFRA_API_MAX_BUNDLE_SIZE (bytes).
15
+ // Only enforced during build — watch mode skips size checks.
16
+ const maxBundleSize =
17
+ parseInt(process.env.WEBINY_INFRA_API_MAX_BUNDLE_SIZE) ||
18
+ DEFAULT_WEBINY_INFRA_API_MAX_BUNDLE_SIZE;
9
19
 
10
20
  return /** @type {import("@rsbuild/core").RsbuildConfig} */ ({
11
21
  source: { entry: { index: paths.fn.entryFile } },
12
22
  output: {
13
23
  module: true,
14
24
  target: "node",
25
+ minify: true,
15
26
  sourceMap: {
16
- js: process.env.DEBUG === "true" ? "source-map" : false
27
+ js: isDebugEnabled || mode === "development" ? "source-map" : false
17
28
  },
18
29
  filename: {
19
30
  js: pathData => {
@@ -30,13 +41,33 @@ export const createRsbuildConfig = ({ cwd }) => {
30
41
  },
31
42
  tools: {
32
43
  rspack: {
33
- externals: [/^@aws-sdk/, /^sharp$/],
44
+ ...(enforceMaxBundleSize && {
45
+ performance: {
46
+ hints: "error",
47
+ maxEntrypointSize: maxBundleSize,
48
+ maxAssetSize: maxBundleSize
49
+ }
50
+ }),
51
+ externals: [
52
+ /^@aws-sdk/,
53
+ /^aws-sdk$/,
54
+ /^sharp$/,
55
+ // knex is a runtime-polymorphic package: its source statically require()s a
56
+ // driver for EVERY SQL dialect (pg, mysql, mariadb, mssql, sqlite, ...) and
57
+ // picks one at runtime from the configured `client`. Bundling it forces the
58
+ // bundler to resolve drivers that aren't installed (the mariadb/tedious/pg
59
+ // "Module not found" errors). The server flavour runs as a Node process with
60
+ // node_modules present, so we externalize knex and let Node load it — knex then
61
+ // lazily require()s ONLY the configured dialect's driver (e.g. better-sqlite3),
62
+ // never the others.
63
+ /^knex(\/|$)/
64
+ ],
34
65
  plugins: [
35
- // This is necessary to enable JSDOM usage in Lambda.
66
+ // Ignore optional `canvas` native module required by jsdom.
36
67
  // https://rspack.dev/plugins/webpack/ignore-plugin
37
68
  new rspack.IgnorePlugin({
38
- resourceRegExp: /canvas/,
39
- contextRegExp: /jsdom$/
69
+ resourceRegExp: /^canvas$/,
70
+ contextRegExp: /jsdom/
40
71
  })
41
72
  ],
42
73
  resolve: {
@@ -1,4 +1,3 @@
1
- import { createRsbuild } from "@rsbuild/core";
2
1
  import { createRsbuildConfig } from "./createRsbuildConfig.js";
3
2
 
4
3
  export const createWatchFunction =
@@ -6,7 +5,9 @@ export const createWatchFunction =
6
5
  async ({ cwd }) => {
7
6
  process.env.NODE_ENV = "development";
8
7
 
9
- const rsbuildConfig = createRsbuildConfig({ cwd });
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 });
10
11
 
11
12
  const rsbuild = await createRsbuild({ rsbuildConfig });
12
13
 
@@ -5,7 +5,17 @@ const cyan = "\x1b[36m";
5
5
  const reset = "\x1b[0m";
6
6
  const bold = "\x1b[1m";
7
7
 
8
- const whitelist = ["@webiny/cognito", "@webiny/auth0", "@webiny/okta", "@webiny/plugins"];
8
+ const whitelist = [
9
+ "@webiny/cognito",
10
+ "@webiny/auth0",
11
+ "@webiny/okta",
12
+ "@webiny/plugins",
13
+ "@webiny/sdk",
14
+ "@webiny/stdlib",
15
+ "@webiny/lexical-converter",
16
+ "@webiny/lexical-nodes",
17
+ "@webiny/lexical-theme"
18
+ ];
9
19
 
10
20
  export const createImportValidatorPlugin = () => {
11
21
  return {
@@ -4,7 +4,9 @@ import chalk from "chalk";
4
4
  export const printBuildStats =
5
5
  ({ cwd, label = "build", extensions = [".js", ".mjs", ".css"] }) =>
6
6
  ({ stats }) => {
7
- if (!stats) return;
7
+ if (!stats) {
8
+ return;
9
+ }
8
10
 
9
11
  const statsJson = stats.toJson({ assets: true, children: false });
10
12
  const assets = statsJson.assets || [];
package/index.d.ts CHANGED
@@ -5,10 +5,6 @@ export { RspackConfig };
5
5
  // Build commands.
6
6
  export type BuildCommand<TOptions = Record<string, any>> = (options: TOptions) => Promise<void>;
7
7
 
8
- export interface BabelConfig {
9
- [key: string]: any;
10
- }
11
-
12
8
  export interface SwcConfig {
13
9
  [key: string]: any;
14
10
  }
@@ -20,7 +16,6 @@ export interface DefinePluginOptions {
20
16
  export interface BuildAppConfigOverrides {
21
17
  entry?: string;
22
18
  openBrowser?: boolean;
23
- babel?: (config: BabelConfig) => BabelConfig;
24
19
  }
25
20
  // Build commands - apps.
26
21
  export interface BuildAppConfig {
@@ -51,7 +46,6 @@ interface BuildFunctionConfig {
51
46
  };
52
47
  define?: DefinePluginOptions;
53
48
  rspack?: (config: RspackConfig) => RspackConfig;
54
- babel?: (config: BabelConfig) => BabelConfig;
55
49
  swc?: (config: SwcConfig) => SwcConfig;
56
50
  };
57
51
  }
@@ -71,12 +65,5 @@ interface BuildPackageConfig {
71
65
  };
72
66
  }
73
67
 
74
- interface BabelConfigParams {
75
- path: string;
76
- esm?: boolean;
77
- }
78
-
79
68
  export function createBuildPackage(options: BuildPackageConfig): BuildCommand;
80
69
  export function createWatchPackage(options: BuildPackageConfig): BuildCommand;
81
- export function createBabelConfigForNode(options: BabelConfigParams): BabelConfig;
82
- export function createBabelConfigForReact(options: BabelConfigParams): BabelConfig;
package/index.js CHANGED
@@ -1,8 +1,3 @@
1
1
  export { createWatchAdmin, createBuildAdmin } from "./bundling/admin/index.js";
2
2
  export { createBuildFunction, createWatchFunction } from "./bundling/function/index.js";
3
- export {
4
- createWatchPackage,
5
- createBuildPackage,
6
- createBabelConfigForNode,
7
- createBabelConfigForReact
8
- } from "./packages/index.js";
3
+ export { createWatchPackage, createBuildPackage } from "./packages/index.js";
package/package.json CHANGED
@@ -1,8 +1,11 @@
1
1
  {
2
2
  "name": "@webiny/build-tools",
3
- "version": "0.0.0-unstable.81ae05e56b",
3
+ "version": "0.0.0-unstable.a4f3e4ea8b",
4
4
  "type": "module",
5
- "main": "index.js",
5
+ "exports": {
6
+ ".": "./index.js",
7
+ "./*": "./*"
8
+ },
6
9
  "description": "A collection of utilities for Webiny project.",
7
10
  "repository": {
8
11
  "type": "git",
@@ -14,43 +17,36 @@
14
17
  "Adrian Smijulj <adrian@webiny.com>"
15
18
  ],
16
19
  "dependencies": {
17
- "@babel/core": "7.29.0",
18
- "@babel/preset-env": "7.29.2",
19
- "@babel/preset-react": "7.28.5",
20
- "@babel/preset-typescript": "7.28.5",
21
- "@babel/runtime": "7.29.2",
22
- "@rsbuild/core": "1.7.3",
23
- "@rsbuild/plugin-react": "1.4.6",
24
- "@rsbuild/plugin-sass": "1.5.1",
25
- "@rsbuild/plugin-svgr": "1.3.1",
26
- "@rsbuild/plugin-type-check": "1.3.4",
27
- "@rspack/core": "1.7.9",
28
- "@svgr/webpack": "8.1.0",
29
- "@swc/plugin-emotion": "14.7.0",
30
- "@tailwindcss/postcss": "4.2.2",
31
- "@types/webpack-env": "1.18.8",
20
+ "@rsbuild/core": "2.1.7",
21
+ "@rsbuild/plugin-react": "2.1.0",
22
+ "@rsbuild/plugin-sass": "2.0.1",
23
+ "@rsbuild/plugin-svgr": "2.0.5",
24
+ "@rsbuild/plugin-type-check": "1.5.0",
25
+ "@rsdoctor/rspack-plugin": "1.6.1",
26
+ "@rslib/core": "0.23.2",
27
+ "@rspack/core": "2.1.5",
28
+ "@swc/plugin-emotion": "14.15.0",
29
+ "@tailwindcss/postcss": "4.3.3",
32
30
  "chalk": "5.6.2",
33
- "chokidar": "5.0.0",
34
31
  "css-loader": "7.1.4",
35
- "eslint": "10.0.3",
36
32
  "fast-glob": "3.3.3",
37
33
  "find-up": "8.0.0",
38
- "fs-extra": "11.3.4",
34
+ "fs-extra": "11.3.6",
39
35
  "get-yarn-workspaces": "1.0.2",
40
- "lodash": "4.17.23",
36
+ "load-json-file": "7.0.1",
37
+ "lodash": "4.18.1",
41
38
  "postcss-loader": "8.2.1",
42
- "process": "0.11.10",
43
39
  "raw-loader": "4.0.2",
44
40
  "react-dom": "18.3.1",
45
41
  "react-refresh": "0.18.0",
46
- "read-json-sync": "2.0.1",
47
42
  "rimraf": "6.1.3",
48
- "sass": "1.98.0",
49
- "sass-loader": "16.0.7",
43
+ "sass": "1.101.3",
44
+ "sass-loader": "17.0.0",
45
+ "strip-json-comments": "5.0.3",
50
46
  "style-loader": "4.0.0",
51
- "ts-morph": "27.0.2",
52
- "tsx": "4.21.0",
53
- "typescript": "5.9.3",
47
+ "ts-morph": "28.0.0",
48
+ "tsx": "4.23.1",
49
+ "typescript": "7.0.2",
54
50
  "url-loader": "4.1.1",
55
51
  "utf-8-validate": "6.0.6"
56
52
  },
@@ -63,31 +59,24 @@
63
59
  "!!raw-loader!"
64
60
  ],
65
61
  "dependencies": [
66
- "@babel/preset-react",
67
- "@svgr/webpack",
68
- "@babel/preset-env",
69
- "@babel/preset-typescript",
70
62
  "@swc/plugin-emotion",
71
- "@types/webpack-env",
72
63
  "postcss-loader",
73
64
  "raw-loader",
74
65
  "react-refresh",
75
66
  "style-loader",
76
67
  "typescript",
77
- "eslint",
78
- "process",
79
68
  "sass-loader",
80
69
  "sass",
81
70
  "bufferutil",
82
71
  "utf-8-validate",
83
72
  "css-loader",
84
- "url-loader"
73
+ "url-loader",
74
+ "@rsdoctor/rspack-plugin"
85
75
  ]
86
76
  }
87
77
  },
88
78
  "publishConfig": {
89
- "access": "public",
90
- "directory": "."
79
+ "access": "public"
91
80
  },
92
- "gitHead": "81ae05e56bcc774d1e077ca615a0005e736aa5a6"
81
+ "gitHead": "b8aec8a1be3f25c3b428b357fe1e352c7cbff9ae"
93
82
  }
@@ -1,9 +1,9 @@
1
1
  import fs from "fs";
2
2
  import { join } from "path";
3
3
 
4
- export const copyToDist = (path, { cwd, logs }) => {
4
+ export const copyToDist = (path, { cwd, logs, outputDir }) => {
5
5
  const from = join(cwd, path);
6
- const to = join(cwd, "dist", path);
6
+ const to = join(outputDir || join(cwd, "dist"), path);
7
7
  if (fs.existsSync(from)) {
8
8
  fs.copyFileSync(from, to);
9
9
  logs !== false && console.log(`Copied ${path}.`);
@@ -0,0 +1,65 @@
1
+ import path from "path";
2
+ import fs from "fs";
3
+ import { dirname } from "path";
4
+ import glob from "fast-glob";
5
+
6
+ const COMPILE_EXTENSIONS = [".js", ".jsx", ".ts", ".tsx"];
7
+ const SKIP_EXTENSIONS = [".d.ts"];
8
+
9
+ export const rslibCompile = async ({ cwd, outputDir }) => {
10
+ const distRoot = outputDir || path.join(cwd, "dist");
11
+
12
+ // Copy non-compilable files (assets, json, graphql, etc.) as-is.
13
+ const pattern = path.join(cwd, "src/**/*.*").replace(/\\/g, "/");
14
+ const allFiles = glob.sync(pattern, { onlyFiles: true, dot: true });
15
+
16
+ for (const file of allFiles) {
17
+ const shouldCompile = COMPILE_EXTENSIONS.some(ext => file.endsWith(ext));
18
+ const shouldSkip = SKIP_EXTENSIONS.some(ext => file.endsWith(ext));
19
+
20
+ if (!shouldCompile || shouldSkip) {
21
+ const destPath = file.replace(path.join(cwd, "src"), distRoot);
22
+ fs.mkdirSync(dirname(destPath), { recursive: true });
23
+ fs.copyFileSync(file, destPath);
24
+ }
25
+ }
26
+
27
+ // Must be a dynamic import. @rslib/core statically loads rspack's native
28
+ // binding. Workers that also run createBuildAdmin load a different rspack
29
+ // version via rsbuild, so two native binaries end up in the same process
30
+ // and cause a SIGSEGV. Deferring the import keeps each rspack isolated to
31
+ // the workers that actually need it.
32
+ const [{ createRslib }, { pluginSvgr }] = await Promise.all([
33
+ import("@rslib/core"),
34
+ import("@rsbuild/plugin-svgr")
35
+ ]);
36
+
37
+ const rslib = await createRslib({
38
+ cwd,
39
+ config: {
40
+ lib: [{ format: "esm", bundle: false }],
41
+ source: {
42
+ // SVGs included so rslib runs them through pluginSvgr and emits
43
+ // a .js React-component module alongside the copied .svg asset.
44
+ entry: ["./src/**/*.{ts,tsx,js,jsx,svg}"],
45
+ alias: { "~": "./src" }
46
+ },
47
+ output: {
48
+ target: "web",
49
+ distPath: { root: path.relative(cwd, distRoot) || "." },
50
+ cleanDistPath: false,
51
+ sourceMap: { js: "source-map" },
52
+ // mixedImport emits each SVG as a static asset for the default URL
53
+ // export. Without a hash, two files named the same (e.g. fullscreen.svg
54
+ // in different dirs) collide at static/svg/fullscreen.svg.
55
+ // loader-utils [ext] has no leading dot, so "[name].[hash][ext]" produces
56
+ // "foo.hashsvg". Use an explicit ".svg" suffix instead.
57
+ filename: { svg: "[name].[contenthash:8].svg" }
58
+ },
59
+ plugins: [pluginSvgr({ mixedImport: true, svgrOptions: { exportType: "named" } })]
60
+ }
61
+ });
62
+
63
+ const { close } = await rslib.build();
64
+ await close();
65
+ };
@@ -1,4 +1,4 @@
1
- import { dirname, relative } from "node:path";
1
+ import { dirname, join, relative, resolve } from "node:path";
2
2
  import fg from "fast-glob";
3
3
  import fs from "node:fs";
4
4
 
@@ -15,6 +15,11 @@ export const replaceTscAliases = async ({ distDir, cwd, debug = false }) => {
15
15
  absolute: true
16
16
  });
17
17
 
18
+ // Build a map of absolute src paths → package names, by scanning sibling packages.
19
+ // This is used to rewrite cross-package src paths (e.g. "../../api/src") back to
20
+ // proper package names (e.g. "@webiny/api") in generated .d.ts files.
21
+ const srcToPackageName = buildSrcToPackageNameMap(cwd);
22
+
18
23
  for (const dtsFile of dtsFiles) {
19
24
  let content = fs.readFileSync(dtsFile, "utf8").toString();
20
25
  let modified = false;
@@ -37,11 +42,84 @@ export const replaceTscAliases = async ({ distDir, cwd, debug = false }) => {
37
42
  }
38
43
  );
39
44
 
45
+ // Replace cross-package src paths (e.g. "../../api/src/types") with proper package
46
+ // names (e.g. "@webiny/api/types"). TypeScript inlines these relative paths when
47
+ // project references are used and dependencies have paths pointing to src/.
48
+ if (srcToPackageName.size > 0) {
49
+ content = content.replace(
50
+ /["'](\.\.[^"']*\/src(?:\/[^"']*)?)['"]/g,
51
+ (match, relPath) => {
52
+ const quote = match[0];
53
+ const absPath = resolve(dirname(dtsFile), relPath);
54
+ const packageName = resolveToPackageName(absPath, srcToPackageName);
55
+ if (packageName) {
56
+ modified = true;
57
+ return `${quote}${packageName}${quote}`;
58
+ }
59
+ return match;
60
+ }
61
+ );
62
+ }
63
+
40
64
  if (modified) {
41
65
  fs.writeFileSync(dtsFile, content, "utf8");
42
66
  if (debug) {
43
- console.log(`Resolved ~ aliases in: ${relative(cwd, dtsFile)}`);
67
+ console.log(`Resolved aliases in: ${relative(cwd, dtsFile)}`);
44
68
  }
45
69
  }
46
70
  }
47
71
  };
72
+
73
+ /**
74
+ * Scans sibling packages to build a map of absolute src directory paths → package names.
75
+ * @param {string} cwd - The current package directory.
76
+ * @returns {Map<string, string>}
77
+ */
78
+ function buildSrcToPackageNameMap(cwd) {
79
+ const map = new Map();
80
+ // Go up to the packages/ directory (cwd is packages/xxx, parent is packages/)
81
+ const packagesDir = resolve(cwd, "..");
82
+ if (!fs.existsSync(packagesDir)) {
83
+ return map;
84
+ }
85
+ let entries;
86
+ try {
87
+ entries = fs.readdirSync(packagesDir);
88
+ } catch {
89
+ return map;
90
+ }
91
+ for (const entry of entries) {
92
+ const pkgDir = join(packagesDir, entry);
93
+ const pkgJsonPath = join(pkgDir, "package.json");
94
+ if (!fs.existsSync(pkgJsonPath)) {
95
+ continue;
96
+ }
97
+ try {
98
+ const pkgJson = JSON.parse(fs.readFileSync(pkgJsonPath, "utf8"));
99
+ if (pkgJson.name) {
100
+ const srcDir = join(pkgDir, "src");
101
+ map.set(srcDir, pkgJson.name);
102
+ }
103
+ } catch {
104
+ // ignore
105
+ }
106
+ }
107
+ return map;
108
+ }
109
+
110
+ /**
111
+ * Given an absolute path that points into a package's src directory, returns the
112
+ * corresponding package name + sub-path (e.g. "@webiny/api/types").
113
+ * @param {string} absPath - Absolute path resolved from the relative import.
114
+ * @param {Map<string, string>} srcToPackageName
115
+ * @returns {string|null}
116
+ */
117
+ function resolveToPackageName(absPath, srcToPackageName) {
118
+ for (const [srcDir, packageName] of srcToPackageName) {
119
+ if (absPath === srcDir || absPath.startsWith(srcDir + "/")) {
120
+ const subPath = absPath.slice(srcDir.length).replace(/^\//, "");
121
+ return subPath ? `${packageName}/${subPath}` : packageName;
122
+ }
123
+ }
124
+ return null;
125
+ }