vinext 0.0.32 → 0.0.34

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 (95) hide show
  1. package/README.md +7 -6
  2. package/dist/config/next-config.d.ts +2 -0
  3. package/dist/config/next-config.js +4 -0
  4. package/dist/config/next-config.js.map +1 -1
  5. package/dist/deploy.js +52 -4
  6. package/dist/deploy.js.map +1 -1
  7. package/dist/entries/app-browser-entry.js +3 -330
  8. package/dist/entries/app-browser-entry.js.map +1 -1
  9. package/dist/entries/app-rsc-entry.js +444 -1265
  10. package/dist/entries/app-rsc-entry.js.map +1 -1
  11. package/dist/entries/app-ssr-entry.js +4 -460
  12. package/dist/entries/app-ssr-entry.js.map +1 -1
  13. package/dist/entries/pages-server-entry.js +8 -1
  14. package/dist/entries/pages-server-entry.js.map +1 -1
  15. package/dist/entries/runtime-entry-module.d.ts +13 -0
  16. package/dist/entries/runtime-entry-module.js +27 -0
  17. package/dist/entries/runtime-entry-module.js.map +1 -0
  18. package/dist/index.js +302 -23
  19. package/dist/index.js.map +1 -1
  20. package/dist/plugins/optimize-imports.d.ts +38 -0
  21. package/dist/plugins/optimize-imports.js +557 -0
  22. package/dist/plugins/optimize-imports.js.map +1 -0
  23. package/dist/server/app-browser-entry.d.ts +1 -0
  24. package/dist/server/app-browser-entry.js +160 -0
  25. package/dist/server/app-browser-entry.js.map +1 -0
  26. package/dist/server/app-browser-stream.d.ts +33 -0
  27. package/dist/server/app-browser-stream.js +54 -0
  28. package/dist/server/app-browser-stream.js.map +1 -0
  29. package/dist/server/app-page-boundary-render.d.ts +63 -0
  30. package/dist/server/app-page-boundary-render.js +182 -0
  31. package/dist/server/app-page-boundary-render.js.map +1 -0
  32. package/dist/server/app-page-boundary.d.ts +57 -0
  33. package/dist/server/app-page-boundary.js +60 -0
  34. package/dist/server/app-page-boundary.js.map +1 -0
  35. package/dist/server/app-page-cache.d.ts +61 -0
  36. package/dist/server/app-page-cache.js +133 -0
  37. package/dist/server/app-page-cache.js.map +1 -0
  38. package/dist/server/app-page-execution.d.ts +46 -0
  39. package/dist/server/app-page-execution.js +109 -0
  40. package/dist/server/app-page-execution.js.map +1 -0
  41. package/dist/server/app-page-probe.d.ts +17 -0
  42. package/dist/server/app-page-probe.js +35 -0
  43. package/dist/server/app-page-probe.js.map +1 -0
  44. package/dist/server/app-page-render.d.ts +59 -0
  45. package/dist/server/app-page-render.js +174 -0
  46. package/dist/server/app-page-render.js.map +1 -0
  47. package/dist/server/app-page-request.d.ts +58 -0
  48. package/dist/server/app-page-request.js +79 -0
  49. package/dist/server/app-page-request.js.map +1 -0
  50. package/dist/server/app-page-response.d.ts +51 -0
  51. package/dist/server/app-page-response.js +90 -0
  52. package/dist/server/app-page-response.js.map +1 -0
  53. package/dist/server/app-page-stream.d.ts +55 -0
  54. package/dist/server/app-page-stream.js +65 -0
  55. package/dist/server/app-page-stream.js.map +1 -0
  56. package/dist/server/app-route-handler-cache.d.ts +42 -0
  57. package/dist/server/app-route-handler-cache.js +69 -0
  58. package/dist/server/app-route-handler-cache.js.map +1 -0
  59. package/dist/server/app-route-handler-execution.d.ts +64 -0
  60. package/dist/server/app-route-handler-execution.js +100 -0
  61. package/dist/server/app-route-handler-execution.js.map +1 -0
  62. package/dist/server/app-route-handler-policy.d.ts +51 -0
  63. package/dist/server/app-route-handler-policy.js +57 -0
  64. package/dist/server/app-route-handler-policy.js.map +1 -0
  65. package/dist/server/app-route-handler-response.d.ts +26 -0
  66. package/dist/server/app-route-handler-response.js +61 -0
  67. package/dist/server/app-route-handler-response.js.map +1 -0
  68. package/dist/server/app-route-handler-runtime.d.ts +27 -0
  69. package/dist/server/app-route-handler-runtime.js +99 -0
  70. package/dist/server/app-route-handler-runtime.js.map +1 -0
  71. package/dist/server/app-ssr-entry.d.ts +19 -0
  72. package/dist/server/app-ssr-entry.js +105 -0
  73. package/dist/server/app-ssr-entry.js.map +1 -0
  74. package/dist/server/app-ssr-stream.d.ts +30 -0
  75. package/dist/server/app-ssr-stream.js +116 -0
  76. package/dist/server/app-ssr-stream.js.map +1 -0
  77. package/dist/server/prod-server.d.ts +13 -1
  78. package/dist/server/prod-server.js +113 -19
  79. package/dist/server/prod-server.js.map +1 -1
  80. package/dist/server/worker-utils.d.ts +0 -6
  81. package/dist/server/worker-utils.js +41 -5
  82. package/dist/server/worker-utils.js.map +1 -1
  83. package/dist/shims/error-boundary.js +1 -1
  84. package/dist/shims/font-google-base.js +1 -1
  85. package/dist/shims/font-google-base.js.map +1 -1
  86. package/dist/shims/font-google.d.ts +2 -3
  87. package/dist/shims/font-google.js +2 -3
  88. package/dist/shims/metadata.js +3 -3
  89. package/dist/shims/metadata.js.map +1 -1
  90. package/dist/shims/request-state-types.d.ts +2 -2
  91. package/dist/shims/unified-request-context.d.ts +1 -1
  92. package/package.json +1 -1
  93. package/dist/shims/font-google.generated.d.ts +0 -1929
  94. package/dist/shims/font-google.generated.js +0 -1929
  95. package/dist/shims/font-google.generated.js.map +0 -1
@@ -0,0 +1,38 @@
1
+ import { ResolvedNextConfig } from "../config/next-config.js";
2
+ import { Plugin } from "vite";
3
+
4
+ //#region src/plugins/optimize-imports.d.ts
5
+ interface BarrelExportEntry {
6
+ source: string;
7
+ isNamespace: boolean;
8
+ originalName?: string;
9
+ }
10
+ type BarrelExportMap = Map<string, BarrelExportEntry>;
11
+ /**
12
+ * Packages whose barrel imports are automatically optimized.
13
+ * Matches Next.js's built-in optimizePackageImports defaults plus radix-ui.
14
+ * @see https://github.com/vercel/next.js/blob/9c31bbdaa/packages/next/src/server/config.ts#L1301
15
+ */
16
+ declare const DEFAULT_OPTIMIZE_PACKAGES: string[];
17
+ /**
18
+ * Build a map of exported names → source sub-module for a barrel package.
19
+ *
20
+ * Parses the barrel entry file AST and extracts the export map.
21
+ * Handles: `export * as X from`, `export { A } from`, `import * as X; export { X }`,
22
+ * and `export * from "./sub"` (recursively resolves wildcard re-exports).
23
+ *
24
+ * Returns null if the entry cannot be resolved, the file cannot be read, or
25
+ * the file has a parse error. Returns an empty map if the file is valid but
26
+ * exports nothing.
27
+ */
28
+ declare function buildBarrelExportMap(packageName: string, resolveEntry: (pkg: string) => string | null, readFile: (filepath: string) => Promise<string | null>, cache?: Map<string, BarrelExportMap>): Promise<BarrelExportMap | null>;
29
+ /**
30
+ * Creates the vinext:optimize-imports Vite plugin.
31
+ *
32
+ * @param nextConfig - Resolved Next.js config (may be undefined before config hook runs).
33
+ * @param getRoot - Returns the current project root (set by the vinext:config hook).
34
+ */
35
+ declare function createOptimizeImportsPlugin(getNextConfig: () => ResolvedNextConfig | undefined, getRoot: () => string): Plugin;
36
+ //#endregion
37
+ export { DEFAULT_OPTIMIZE_PACKAGES, buildBarrelExportMap, createOptimizeImportsPlugin };
38
+ //# sourceMappingURL=optimize-imports.d.ts.map
@@ -0,0 +1,557 @@
1
+ import { createRequire } from "node:module";
2
+ import path from "node:path";
3
+ import { parseAst } from "vite";
4
+ import fs from "node:fs/promises";
5
+ import MagicString from "magic-string";
6
+ //#region src/plugins/optimize-imports.ts
7
+ /**
8
+ * Read a file's contents, returning null on any error.
9
+ * Module-level so a single function instance is shared across all transform calls.
10
+ */
11
+ async function readFileSafe(filepath) {
12
+ try {
13
+ return await fs.readFile(filepath, "utf-8");
14
+ } catch {
15
+ return null;
16
+ }
17
+ }
18
+ /** Extract the string name from an Identifier ({name}) or Literal ({value}) AST node.
19
+ * Returns null for unexpected node shapes so callers can degrade gracefully rather than crash. */
20
+ function astName(node) {
21
+ if (node.name !== void 0) return node.name;
22
+ if (typeof node.value === "string") return node.value;
23
+ return null;
24
+ }
25
+ /**
26
+ * Packages whose barrel imports are automatically optimized.
27
+ * Matches Next.js's built-in optimizePackageImports defaults plus radix-ui.
28
+ * @see https://github.com/vercel/next.js/blob/9c31bbdaa/packages/next/src/server/config.ts#L1301
29
+ */
30
+ const DEFAULT_OPTIMIZE_PACKAGES = [
31
+ "lucide-react",
32
+ "date-fns",
33
+ "lodash-es",
34
+ "ramda",
35
+ "antd",
36
+ "react-bootstrap",
37
+ "ahooks",
38
+ "@ant-design/icons",
39
+ "@headlessui/react",
40
+ "@headlessui-float/react",
41
+ "@heroicons/react/20/solid",
42
+ "@heroicons/react/24/solid",
43
+ "@heroicons/react/24/outline",
44
+ "@visx/visx",
45
+ "@tremor/react",
46
+ "rxjs",
47
+ "@mui/material",
48
+ "@mui/icons-material",
49
+ "recharts",
50
+ "react-use",
51
+ "effect",
52
+ "@effect/schema",
53
+ "@effect/platform",
54
+ "@effect/platform-node",
55
+ "@effect/platform-browser",
56
+ "@effect/platform-bun",
57
+ "@effect/sql",
58
+ "@effect/sql-mssql",
59
+ "@effect/sql-mysql2",
60
+ "@effect/sql-pg",
61
+ "@effect/sql-sqlite-node",
62
+ "@effect/sql-sqlite-bun",
63
+ "@effect/sql-sqlite-wasm",
64
+ "@effect/sql-sqlite-react-native",
65
+ "@effect/rpc",
66
+ "@effect/rpc-http",
67
+ "@effect/typeclass",
68
+ "@effect/experimental",
69
+ "@effect/opentelemetry",
70
+ "@material-ui/core",
71
+ "@material-ui/icons",
72
+ "@tabler/icons-react",
73
+ "mui-core",
74
+ "react-icons/ai",
75
+ "react-icons/bi",
76
+ "react-icons/bs",
77
+ "react-icons/cg",
78
+ "react-icons/ci",
79
+ "react-icons/di",
80
+ "react-icons/fa",
81
+ "react-icons/fa6",
82
+ "react-icons/fc",
83
+ "react-icons/fi",
84
+ "react-icons/gi",
85
+ "react-icons/go",
86
+ "react-icons/gr",
87
+ "react-icons/hi",
88
+ "react-icons/hi2",
89
+ "react-icons/im",
90
+ "react-icons/io",
91
+ "react-icons/io5",
92
+ "react-icons/lia",
93
+ "react-icons/lib",
94
+ "react-icons/lu",
95
+ "react-icons/md",
96
+ "react-icons/pi",
97
+ "react-icons/ri",
98
+ "react-icons/rx",
99
+ "react-icons/si",
100
+ "react-icons/sl",
101
+ "react-icons/tb",
102
+ "react-icons/tfi",
103
+ "react-icons/ti",
104
+ "react-icons/vsc",
105
+ "react-icons/wi",
106
+ "radix-ui"
107
+ ];
108
+ /**
109
+ * Resolve a package.json exports value to a string entry path.
110
+ * Prefers node → import → module → default conditions, recursing into nested objects.
111
+ * When `preferReactServer` is true (RSC environment), "react-server" is checked first
112
+ * so that packages like `react` and `react-dom` resolve their RSC-compatible entry points.
113
+ */
114
+ function resolveExportsValue(value, preferReactServer) {
115
+ if (typeof value === "string") return value;
116
+ if (typeof value === "object" && value !== null) {
117
+ const conditions = preferReactServer ? [
118
+ "react-server",
119
+ "node",
120
+ "import",
121
+ "module",
122
+ "default"
123
+ ] : [
124
+ "node",
125
+ "import",
126
+ "module",
127
+ "default"
128
+ ];
129
+ for (const key of conditions) {
130
+ const nested = value[key];
131
+ if (nested !== void 0) {
132
+ const resolved = resolveExportsValue(nested, preferReactServer);
133
+ if (resolved) return resolved;
134
+ }
135
+ }
136
+ }
137
+ return null;
138
+ }
139
+ /**
140
+ * Resolve a package name to its directory and parsed package.json.
141
+ * Handles packages with strict `exports` fields that don't expose `./package.json`
142
+ * by first resolving the main entry, then walking up to find the package root.
143
+ */
144
+ async function resolvePackageInfo(packageName, projectRoot) {
145
+ try {
146
+ const req = createRequire(path.join(projectRoot, "package.json"));
147
+ try {
148
+ const pkgJsonPath = req.resolve(`${packageName}/package.json`);
149
+ return {
150
+ pkgDir: path.dirname(pkgJsonPath),
151
+ pkgJson: JSON.parse(await fs.readFile(pkgJsonPath, "utf-8"))
152
+ };
153
+ } catch {
154
+ try {
155
+ const mainEntry = req.resolve(packageName);
156
+ let dir = path.dirname(mainEntry);
157
+ for (let i = 0; i < 10; i++) {
158
+ const candidate = path.join(dir, "package.json");
159
+ try {
160
+ const parsed = JSON.parse(await fs.readFile(candidate, "utf-8"));
161
+ if (parsed.name === packageName) return {
162
+ pkgDir: dir,
163
+ pkgJson: parsed
164
+ };
165
+ } catch {}
166
+ const parent = path.dirname(dir);
167
+ if (parent === dir) break;
168
+ dir = parent;
169
+ }
170
+ } catch {
171
+ return null;
172
+ }
173
+ }
174
+ return null;
175
+ } catch {
176
+ return null;
177
+ }
178
+ }
179
+ /**
180
+ * Resolve a package name to its ESM entry file path.
181
+ * Checks `exports["."]` → `module` → `main`, then falls back to require.resolve.
182
+ * Pass `preferReactServer: true` in the RSC environment to prefer the "react-server"
183
+ * export condition over "node"/"import" when resolving the barrel entry.
184
+ */
185
+ async function resolvePackageEntry(packageName, projectRoot, preferReactServer) {
186
+ try {
187
+ const info = await resolvePackageInfo(packageName, projectRoot);
188
+ if (!info) return null;
189
+ const { pkgDir, pkgJson } = info;
190
+ if (pkgJson.exports) {
191
+ const dotExport = pkgJson.exports["."];
192
+ if (dotExport) {
193
+ const entryPath = resolveExportsValue(dotExport, preferReactServer);
194
+ if (entryPath) return path.resolve(pkgDir, entryPath).split(path.sep).join("/");
195
+ }
196
+ }
197
+ const entryField = pkgJson.module ?? pkgJson.main;
198
+ if (typeof entryField === "string") return path.resolve(pkgDir, entryField).split(path.sep).join("/");
199
+ return createRequire(path.join(projectRoot, "package.json")).resolve(packageName).split(path.sep).join("/");
200
+ } catch {
201
+ return null;
202
+ }
203
+ }
204
+ /**
205
+ * Build a map of exported names → source sub-module for a barrel file.
206
+ *
207
+ * Internal recursive helper used by buildBarrelExportMap. Parses a single file's
208
+ * AST and populates `exportMap` with resolved entries. Handles:
209
+ * - `export * as Name from "sub-pkg"` — namespace re-export
210
+ * - `export { A, B } from "sub-pkg"` — named re-export
211
+ * - `import * as X; export { X }` — indirect namespace re-export
212
+ * - `export * from "./sub"` — wildcard: recursively parse sub-module and merge exports
213
+ *
214
+ * Returns an empty map when the file cannot be read or has a parse error, so that
215
+ * recursive wildcard calls degrade gracefully without aborting the whole barrel walk.
216
+ *
217
+ * @param initialContent - Pre-read file content for `filePath`. If provided, skips the
218
+ * `readFile` call for the entry file — avoids a redundant read when the caller
219
+ * already has the content in hand.
220
+ */
221
+ async function buildExportMapFromFile(filePath, readFile, cache, visited, initialContent) {
222
+ if (visited.has(filePath)) return /* @__PURE__ */ new Map();
223
+ visited.add(filePath);
224
+ const cached = cache.get(filePath);
225
+ if (cached) return cached;
226
+ const content = initialContent ?? await readFile(filePath);
227
+ if (!content) return /* @__PURE__ */ new Map();
228
+ let ast;
229
+ try {
230
+ ast = parseAst(content);
231
+ } catch {
232
+ return /* @__PURE__ */ new Map();
233
+ }
234
+ const exportMap = /* @__PURE__ */ new Map();
235
+ const importBindings = /* @__PURE__ */ new Map();
236
+ const fileDir = path.dirname(filePath);
237
+ /**
238
+ * Normalize a source specifier: resolve relative paths to absolute so that
239
+ * entries in the export map always store absolute paths for file references.
240
+ * Bare package specifiers (e.g. "@radix-ui/react-slot") are returned unchanged.
241
+ */
242
+ function normalizeSource(source) {
243
+ return source.startsWith(".") ? path.resolve(fileDir, source).split(path.sep).join("/") : source;
244
+ }
245
+ for (const node of ast.body) switch (node.type) {
246
+ case "ImportDeclaration": {
247
+ const rawSource = typeof node.source?.value === "string" ? node.source.value : null;
248
+ if (!rawSource) break;
249
+ const source = normalizeSource(rawSource);
250
+ for (const spec of node.specifiers ?? []) switch (spec.type) {
251
+ case "ImportNamespaceSpecifier":
252
+ importBindings.set(spec.local.name, {
253
+ source,
254
+ isNamespace: true
255
+ });
256
+ break;
257
+ case "ImportSpecifier":
258
+ if (spec.imported) {
259
+ const name = astName(spec.imported);
260
+ if (name !== null) importBindings.set(spec.local.name, {
261
+ source,
262
+ isNamespace: false,
263
+ originalName: name
264
+ });
265
+ }
266
+ break;
267
+ case "ImportDefaultSpecifier":
268
+ importBindings.set(spec.local.name, {
269
+ source,
270
+ isNamespace: false,
271
+ originalName: "default"
272
+ });
273
+ break;
274
+ }
275
+ break;
276
+ }
277
+ case "ExportAllDeclaration": {
278
+ const rawSource = typeof node.source?.value === "string" ? node.source.value : null;
279
+ if (!rawSource) break;
280
+ if (node.exported) {
281
+ const name = astName(node.exported);
282
+ if (name !== null) exportMap.set(name, {
283
+ source: normalizeSource(rawSource),
284
+ isNamespace: true
285
+ });
286
+ } else if (rawSource.startsWith(".")) {
287
+ const subPath = path.resolve(fileDir, rawSource).split(path.sep).join("/");
288
+ const candidates = [
289
+ subPath,
290
+ `${subPath}.js`,
291
+ `${subPath}.mjs`,
292
+ `${subPath}.cjs`,
293
+ `${subPath}.ts`,
294
+ `${subPath}.tsx`,
295
+ `${subPath}.jsx`,
296
+ `${subPath}.mts`,
297
+ `${subPath}.cts`,
298
+ `${subPath}/index.js`,
299
+ `${subPath}/index.mjs`,
300
+ `${subPath}/index.cjs`,
301
+ `${subPath}/index.ts`,
302
+ `${subPath}/index.tsx`,
303
+ `${subPath}/index.jsx`,
304
+ `${subPath}/index.mts`,
305
+ `${subPath}/index.cts`
306
+ ];
307
+ for (const candidate of candidates) {
308
+ const candidateContent = await readFile(candidate);
309
+ if (candidateContent !== null) {
310
+ const subMap = await buildExportMapFromFile(candidate, readFile, cache, visited, candidateContent);
311
+ for (const [name, entry] of subMap) if (!exportMap.has(name)) exportMap.set(name, entry);
312
+ break;
313
+ }
314
+ }
315
+ }
316
+ break;
317
+ }
318
+ case "ExportNamedDeclaration": {
319
+ const rawSource = typeof node.source?.value === "string" ? node.source.value : null;
320
+ if (rawSource) {
321
+ const source = normalizeSource(rawSource);
322
+ for (const spec of node.specifiers ?? []) if (spec.exported) {
323
+ const exported = astName(spec.exported);
324
+ const local = astName(spec.local);
325
+ if (exported !== null) exportMap.set(exported, {
326
+ source,
327
+ isNamespace: false,
328
+ originalName: local ?? void 0
329
+ });
330
+ }
331
+ } else if (node.specifiers && node.specifiers.length > 0) for (const spec of node.specifiers) {
332
+ if (!spec.exported) continue;
333
+ const exported = astName(spec.exported);
334
+ const local = astName(spec.local);
335
+ if (exported === null || local === null) continue;
336
+ const binding = importBindings.get(local);
337
+ if (binding) exportMap.set(exported, {
338
+ source: binding.source,
339
+ isNamespace: binding.isNamespace,
340
+ originalName: binding.isNamespace ? void 0 : binding.originalName
341
+ });
342
+ }
343
+ else if (node.declaration) {
344
+ const decl = node.declaration;
345
+ if (decl.id?.name) exportMap.set(decl.id.name, {
346
+ source: filePath,
347
+ isNamespace: false
348
+ });
349
+ else if (decl.declarations) {
350
+ for (const d of decl.declarations) if (d.id?.name) exportMap.set(d.id.name, {
351
+ source: filePath,
352
+ isNamespace: false
353
+ });
354
+ }
355
+ }
356
+ break;
357
+ }
358
+ }
359
+ cache.set(filePath, exportMap);
360
+ return exportMap;
361
+ }
362
+ /**
363
+ * Build a map of exported names → source sub-module for a barrel package.
364
+ *
365
+ * Parses the barrel entry file AST and extracts the export map.
366
+ * Handles: `export * as X from`, `export { A } from`, `import * as X; export { X }`,
367
+ * and `export * from "./sub"` (recursively resolves wildcard re-exports).
368
+ *
369
+ * Returns null if the entry cannot be resolved, the file cannot be read, or
370
+ * the file has a parse error. Returns an empty map if the file is valid but
371
+ * exports nothing.
372
+ */
373
+ async function buildBarrelExportMap(packageName, resolveEntry, readFile, cache) {
374
+ const entryPath = resolveEntry(packageName);
375
+ if (!entryPath) return null;
376
+ const exportMapCache = cache ?? /* @__PURE__ */ new Map();
377
+ const cached = exportMapCache.get(entryPath);
378
+ if (cached) return cached;
379
+ const content = await readFile(entryPath);
380
+ if (!content) return null;
381
+ return await buildExportMapFromFile(entryPath, readFile, exportMapCache, /* @__PURE__ */ new Set(), content);
382
+ }
383
+ /**
384
+ * Creates the vinext:optimize-imports Vite plugin.
385
+ *
386
+ * @param nextConfig - Resolved Next.js config (may be undefined before config hook runs).
387
+ * @param getRoot - Returns the current project root (set by the vinext:config hook).
388
+ */
389
+ function createOptimizeImportsPlugin(getNextConfig, getRoot) {
390
+ const barrelCaches = {
391
+ exportMapCache: /* @__PURE__ */ new Map(),
392
+ subpkgOrigin: /* @__PURE__ */ new Map()
393
+ };
394
+ const entryPathCache = /* @__PURE__ */ new Map();
395
+ let optimizedPackages = /* @__PURE__ */ new Set();
396
+ let quotedPackages = [];
397
+ const registeredBarrels = /* @__PURE__ */ new Set();
398
+ return {
399
+ name: "vinext:optimize-imports",
400
+ buildStart() {
401
+ const nextConfig = getNextConfig();
402
+ optimizedPackages = new Set([...DEFAULT_OPTIMIZE_PACKAGES, ...nextConfig?.optimizePackageImports ?? []]);
403
+ quotedPackages = [...optimizedPackages].flatMap((pkg) => [`"${pkg}"`, `'${pkg}'`]);
404
+ entryPathCache.clear();
405
+ barrelCaches.exportMapCache.clear();
406
+ barrelCaches.subpkgOrigin.clear();
407
+ registeredBarrels.clear();
408
+ },
409
+ async resolveId(source) {
410
+ if (this.environment?.name === "client") return;
411
+ const envName = this.environment?.name ?? "ssr";
412
+ const barrelEntry = barrelCaches.subpkgOrigin.get(envName)?.get(source) ?? barrelCaches.subpkgOrigin.get(envName === "rsc" ? "ssr" : "rsc")?.get(source);
413
+ if (!barrelEntry) return;
414
+ return await this.resolve(source, barrelEntry, { skipSelf: true }) ?? void 0;
415
+ },
416
+ transform: {
417
+ filter: { id: { include: /\.(tsx?|jsx?|mjs)$/ } },
418
+ async handler(code, id) {
419
+ const env = this.environment;
420
+ if (env?.name === "client") return null;
421
+ const preferReactServer = env?.name === "rsc";
422
+ if (id.startsWith("\0")) return null;
423
+ const packages = optimizedPackages;
424
+ let hasBarrelImport = false;
425
+ for (const quoted of quotedPackages) if (code.includes(quoted)) {
426
+ hasBarrelImport = true;
427
+ break;
428
+ }
429
+ if (!hasBarrelImport) return null;
430
+ let ast;
431
+ try {
432
+ ast = parseAst(code);
433
+ } catch {
434
+ return null;
435
+ }
436
+ const s = new MagicString(code);
437
+ let hasChanges = false;
438
+ const root = getRoot();
439
+ for (const node of ast.body) {
440
+ if (node.type !== "ImportDeclaration") continue;
441
+ const importSource = typeof node.source?.value === "string" ? node.source.value : null;
442
+ if (!importSource || !packages.has(importSource)) continue;
443
+ const cacheKey = `${preferReactServer ? "rsc" : "ssr"}:${importSource}`;
444
+ let barrelEntry = entryPathCache.get(cacheKey);
445
+ if (barrelEntry === void 0) {
446
+ barrelEntry = await resolvePackageEntry(importSource, root, preferReactServer);
447
+ entryPathCache.set(cacheKey, barrelEntry ?? null);
448
+ }
449
+ const exportMap = await buildBarrelExportMap(importSource, () => barrelEntry ?? null, readFileSafe, barrelCaches.exportMapCache);
450
+ if (!exportMap || !barrelEntry) continue;
451
+ const envKey = preferReactServer ? "rsc" : "ssr";
452
+ const registeredKey = `${envKey}:${barrelEntry}`;
453
+ if (!registeredBarrels.has(registeredKey)) {
454
+ registeredBarrels.add(registeredKey);
455
+ let envOriginMap = barrelCaches.subpkgOrigin.get(envKey);
456
+ if (!envOriginMap) {
457
+ envOriginMap = /* @__PURE__ */ new Map();
458
+ barrelCaches.subpkgOrigin.set(envKey, envOriginMap);
459
+ }
460
+ for (const entry of exportMap.values()) if (!entry.source.startsWith("/") && !entry.source.startsWith(".") && !envOriginMap.has(entry.source)) envOriginMap.set(entry.source, barrelEntry);
461
+ }
462
+ const specifiers = [];
463
+ let allResolved = true;
464
+ for (const spec of node.specifiers ?? []) {
465
+ switch (spec.type) {
466
+ case "ImportSpecifier": {
467
+ if (!spec.imported) {
468
+ allResolved = false;
469
+ break;
470
+ }
471
+ const imported = astName(spec.imported);
472
+ if (imported === null) {
473
+ allResolved = false;
474
+ break;
475
+ }
476
+ specifiers.push({
477
+ local: spec.local.name,
478
+ imported
479
+ });
480
+ if (!exportMap.has(imported)) allResolved = false;
481
+ break;
482
+ }
483
+ case "ImportDefaultSpecifier":
484
+ specifiers.push({
485
+ local: spec.local.name,
486
+ imported: "default"
487
+ });
488
+ if (!exportMap.has("default")) allResolved = false;
489
+ break;
490
+ case "ImportNamespaceSpecifier":
491
+ allResolved = false;
492
+ break;
493
+ }
494
+ if (!allResolved) break;
495
+ }
496
+ if (!allResolved || specifiers.length === 0) {
497
+ if (allResolved === false) {
498
+ for (const spec of node.specifiers ?? []) if (spec.type === "ImportSpecifier" && spec.imported) {
499
+ const imported = astName(spec.imported);
500
+ if (imported !== null && !exportMap.has(imported)) {
501
+ console.debug(`[vinext:optimize-imports] skipping "${importSource}": could not resolve specifier "${imported}" in barrel export map`);
502
+ break;
503
+ }
504
+ } else if (spec.type === "ImportDefaultSpecifier" && !exportMap.has("default")) {
505
+ console.debug(`[vinext:optimize-imports] skipping "${importSource}": default export not found in barrel export map`);
506
+ break;
507
+ } else if (spec.type === "ImportNamespaceSpecifier") break;
508
+ }
509
+ continue;
510
+ }
511
+ const bySource = /* @__PURE__ */ new Map();
512
+ for (const { local, imported } of specifiers) {
513
+ const entry = exportMap.get(imported);
514
+ if (!entry) continue;
515
+ const resolvedSource = entry.source;
516
+ const key = `${resolvedSource}::${entry.isNamespace}`;
517
+ let group = bySource.get(key);
518
+ if (!group) {
519
+ group = {
520
+ source: resolvedSource,
521
+ locals: [],
522
+ isNamespace: entry.isNamespace
523
+ };
524
+ bySource.set(key, group);
525
+ }
526
+ group.locals.push({
527
+ local,
528
+ originalName: entry.isNamespace ? void 0 : entry.originalName
529
+ });
530
+ }
531
+ const replacements = [];
532
+ for (const { source, locals, isNamespace } of bySource.values()) if (isNamespace) for (const { local } of locals) replacements.push(`import * as ${local} from ${JSON.stringify(source)}`);
533
+ else {
534
+ const defaultLocals = [];
535
+ const namedSpecs = [];
536
+ for (const { local, originalName } of locals) if (originalName === "default") defaultLocals.push(local);
537
+ else if (originalName !== void 0 && originalName !== local) namedSpecs.push(`${originalName} as ${local}`);
538
+ else namedSpecs.push(local);
539
+ for (const local of defaultLocals) replacements.push(`import ${local} from ${JSON.stringify(source)}`);
540
+ if (namedSpecs.length > 0) replacements.push(`import { ${namedSpecs.join(", ")} } from ${JSON.stringify(source)}`);
541
+ }
542
+ s.overwrite(node.start, node.end, replacements.join(";\n") + ";");
543
+ hasChanges = true;
544
+ }
545
+ if (!hasChanges) return null;
546
+ return {
547
+ code: s.toString(),
548
+ map: s.generateMap({ hires: "boundary" })
549
+ };
550
+ }
551
+ }
552
+ };
553
+ }
554
+ //#endregion
555
+ export { DEFAULT_OPTIMIZE_PACKAGES, buildBarrelExportMap, createOptimizeImportsPlugin };
556
+
557
+ //# sourceMappingURL=optimize-imports.js.map