@caryhu/codemine-forge 0.0.1-alpha.1 → 0.0.1-alpha.3

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,6 +1,6 @@
1
1
  import type { ForgePackageResolutionResult } from "../package-resolution";
2
2
  import { type ForgeVirtualFileSystem } from "../virtual-file-system";
3
- import type { ForgeBrowserBundle, ForgeBuildOutputFile, ForgeBuildPipelineDiagnostic } from "./types";
3
+ import type { ForgeBrowserBundle, ForgeBuildOutputFile, ForgeBuildPipelineDiagnostic, ForgeViteConfigMetadata } from "./types";
4
4
  export interface ForgeBrowserBundleResult {
5
5
  readonly browserBundle?: ForgeBrowserBundle;
6
6
  readonly diagnostics: readonly ForgeBuildPipelineDiagnostic[];
@@ -11,6 +11,7 @@ interface CreateBrowserBundleOptions {
11
11
  readonly fileSystem: ForgeVirtualFileSystem;
12
12
  readonly packageResolution: ForgePackageResolutionResult;
13
13
  readonly scriptTransformer?: ForgeBrowserBundleScriptTransformer;
14
+ readonly viteConfig?: ForgeViteConfigMetadata;
14
15
  }
15
16
  export type ForgeBrowserBundleScriptLoader = "ts" | "tsx";
16
17
  export interface ForgeBrowserBundleScriptTransformRequest {
@@ -24,6 +24,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
24
24
  };
25
25
  Object.defineProperty(exports, "__esModule", { value: true });
26
26
  exports.createBrowserBundle = void 0;
27
+ const compiler_sfc_1 = require("@vue/compiler-sfc");
27
28
  const ts = __importStar(require("typescript"));
28
29
  const virtual_file_system_1 = require("../virtual-file-system");
29
30
  const diagnostics_1 = require("./diagnostics");
@@ -36,6 +37,7 @@ const DEFAULT_RESOLVE_EXTENSIONS = [
36
37
  ".js",
37
38
  ".json",
38
39
  ".css",
40
+ ".vue",
39
41
  ];
40
42
  const INDEX_RESOLVE_EXTENSIONS = [
41
43
  "/index.tsx",
@@ -44,6 +46,7 @@ const INDEX_RESOLVE_EXTENSIONS = [
44
46
  "/index.js",
45
47
  "/index.json",
46
48
  "/index.css",
49
+ "/index.vue",
47
50
  ];
48
51
  const SCRIPT_EXTENSIONS = new Set([".js", ".jsx", ".ts", ".tsx"]);
49
52
  async function createBrowserBundle(options) {
@@ -64,7 +67,8 @@ async function createBrowserBundle(options) {
64
67
  const extension = getExtension(sourcePath);
65
68
  if (!SCRIPT_EXTENSIONS.has(extension) &&
66
69
  extension !== ".css" &&
67
- extension !== ".json") {
70
+ extension !== ".json" &&
71
+ extension !== ".vue") {
68
72
  modules.set(sourcePath, {
69
73
  outputPath: createModuleOutputPath(sourcePath),
70
74
  sourcePath,
@@ -74,12 +78,24 @@ async function createBrowserBundle(options) {
74
78
  return;
75
79
  }
76
80
  const source = await options.fileSystem.readText(sourcePath);
77
- const imports = extractImportReferences(source).map((reference) => reference.specifier);
81
+ const importSource = extension === ".vue" ? createVueSfcModule(sourcePath, source) : source;
82
+ const imports = extractImportReferences(importSource).map((reference) => reference.specifier);
78
83
  const rewrites = new Map();
79
84
  for (const specifier of imports) {
80
85
  if (isExternalUrl(specifier)) {
81
86
  continue;
82
87
  }
88
+ const aliasSpecifier = resolveAliasSpecifier(specifier, options.viteConfig?.aliases ?? {});
89
+ if (aliasSpecifier !== undefined) {
90
+ const resolvedPath = await resolveLocalImport(options.fileSystem, sourcePath, aliasSpecifier);
91
+ if (resolvedPath === undefined) {
92
+ diagnostics.push((0, diagnostics_1.createUnresolvedImportDiagnostic)(specifier, sourcePath));
93
+ continue;
94
+ }
95
+ rewrites.set(specifier, createModuleOutputPath(resolvedPath));
96
+ await visitWorkspaceModule(resolvedPath);
97
+ continue;
98
+ }
83
99
  if (isLocalSpecifier(specifier)) {
84
100
  const resolvedPath = await resolveLocalImport(options.fileSystem, sourcePath, specifier);
85
101
  if (resolvedPath === undefined) {
@@ -102,7 +118,7 @@ async function createBrowserBundle(options) {
102
118
  await visitPackageModule(packageImport.packageRecord, packageImport.filePath);
103
119
  }
104
120
  }
105
- const transformResult = await transformWorkspaceModule(sourcePath, source, options.scriptTransformer);
121
+ const transformResult = await transformWorkspaceModule(sourcePath, source, options.scriptTransformer, options.viteConfig?.define ?? {});
106
122
  if (!transformResult.success) {
107
123
  diagnostics.push(...transformResult.diagnostics);
108
124
  visiting.delete(sourcePath);
@@ -196,6 +212,7 @@ async function createBrowserBundle(options) {
196
212
  const localImports = Object.fromEntries(moduleOutputFiles.map((file) => [file.path, file.path]));
197
213
  const packageImportEntries = Object.fromEntries(Array.from(packageImports.entries()).sort(([left], [right]) => left.localeCompare(right)));
198
214
  const packageEntryImports = createPackageEntryImports(options.packageResolution.packages);
215
+ const bundleModules = createBrowserBundleModules(Array.from(modules.values()), Array.from(packageModules.values()));
199
216
  const importMap = {
200
217
  imports: sortRecord({
201
218
  ...packageEntryImports,
@@ -213,34 +230,60 @@ async function createBrowserBundle(options) {
213
230
  format: "esm",
214
231
  importMap,
215
232
  importMapPath: BROWSER_IMPORT_MAP_PATH,
216
- moduleCount: modules.size + packageModules.size,
233
+ moduleCount: bundleModules.length,
234
+ modules: bundleModules,
217
235
  outputPaths: allOutputFiles.map((file) => file.path),
236
+ viteConfig: options.viteConfig,
218
237
  },
219
238
  diagnostics: [],
220
239
  outputFiles: allOutputFiles,
221
240
  };
222
241
  }
223
242
  exports.createBrowserBundle = createBrowserBundle;
224
- async function transformWorkspaceModule(sourcePath, source, scriptTransformer) {
243
+ function createBrowserBundleModules(workspaceModules, packageModules) {
244
+ return [
245
+ ...workspaceModules.map((moduleRecord) => ({
246
+ origin: "workspace",
247
+ outputPath: moduleRecord.outputPath,
248
+ sourcePath: moduleRecord.sourcePath,
249
+ })),
250
+ ...packageModules.map((moduleRecord) => ({
251
+ origin: "package",
252
+ outputPath: moduleRecord.outputPath,
253
+ sourcePath: createPackageImporterPath(moduleRecord.packageRecord, moduleRecord.filePath),
254
+ })),
255
+ ].sort((left, right) => left.outputPath.localeCompare(right.outputPath));
256
+ }
257
+ async function transformWorkspaceModule(sourcePath, source, scriptTransformer, defineReplacements) {
225
258
  const extension = getExtension(sourcePath);
226
259
  if (extension === ".css") {
227
- return transformSuccess(createCssModule(sourcePath, source));
260
+ return transformSuccess(createWorkspaceCssModule(sourcePath, source));
228
261
  }
229
262
  if (extension === ".json") {
230
263
  return transformSuccess(createJsonModule(source));
231
264
  }
265
+ const applyDefines = (outputText) => applyDefineReplacements(outputText, defineReplacements);
266
+ if (extension === ".vue") {
267
+ return transformSuccess(applyDefines(transpileScript(sourcePath, createVueSfcModule(sourcePath, source))));
268
+ }
232
269
  if (!SCRIPT_EXTENSIONS.has(extension)) {
233
270
  return transformSuccess(source);
234
271
  }
235
272
  const loader = scriptLoaderForExtension(extension);
236
273
  if (loader !== undefined && scriptTransformer !== undefined) {
237
- return scriptTransformer({
274
+ const transformResult = await scriptTransformer({
238
275
  loader,
239
276
  sourcePath,
240
277
  sourceText: source,
241
278
  });
279
+ return transformResult.success
280
+ ? transformSuccess(applyDefines(transformResult.outputText))
281
+ : transformResult;
242
282
  }
243
- return transformSuccess(ts.transpileModule(source, {
283
+ return transformSuccess(applyDefines(transpileScript(sourcePath, source)));
284
+ }
285
+ function transpileScript(sourcePath, source) {
286
+ return ts.transpileModule(source, {
244
287
  compilerOptions: {
245
288
  esModuleInterop: true,
246
289
  importsNotUsedAsValues: ts.ImportsNotUsedAsValues.Remove,
@@ -252,7 +295,7 @@ async function transformWorkspaceModule(sourcePath, source, scriptTransformer) {
252
295
  },
253
296
  fileName: sourcePath,
254
297
  reportDiagnostics: false,
255
- }).outputText);
298
+ }).outputText;
256
299
  }
257
300
  function transformSuccess(outputText) {
258
301
  return {
@@ -271,7 +314,7 @@ function transformPackageModule(importer, filePath, content) {
271
314
  }
272
315
  const source = typeof content === "string" ? content : new TextDecoder().decode(content);
273
316
  if (extension === ".css") {
274
- return transformSuccess(createCssModule(importer, source));
317
+ return transformSuccess(createPlainCssModule(importer, source));
275
318
  }
276
319
  if (extension === ".json") {
277
320
  return transformSuccess(createJsonModule(source));
@@ -279,21 +322,63 @@ function transformPackageModule(importer, filePath, content) {
279
322
  if (!SCRIPT_EXTENSIONS.has(extension)) {
280
323
  return transformSuccess(source);
281
324
  }
282
- return transformSuccess(ts.transpileModule(source, {
283
- compilerOptions: {
284
- esModuleInterop: true,
285
- importsNotUsedAsValues: ts.ImportsNotUsedAsValues.Remove,
286
- jsx: ts.JsxEmit.React,
287
- jsxFactory: "React.createElement",
288
- jsxFragmentFactory: "React.Fragment",
289
- module: ts.ModuleKind.ESNext,
290
- target: ts.ScriptTarget.ES2020,
291
- },
292
- fileName: importer,
293
- reportDiagnostics: false,
294
- }).outputText);
325
+ return transformSuccess(transpileScript(importer, source));
326
+ }
327
+ function createVueSfcModule(sourcePath, source) {
328
+ const filename = sourcePath;
329
+ const id = `forge-vue-${hashText(sourcePath)}`;
330
+ const parseResult = (0, compiler_sfc_1.parse)(source, { filename });
331
+ if (parseResult.errors.length > 0) {
332
+ throw new Error(formatVueCompilerErrors(parseResult.errors));
333
+ }
334
+ const { descriptor } = parseResult;
335
+ const script = descriptor.script === null && descriptor.scriptSetup === null
336
+ ? undefined
337
+ : (0, compiler_sfc_1.compileScript)(descriptor, {
338
+ genDefaultAs: "__forgeVueDefault",
339
+ id,
340
+ });
341
+ const scriptContent = script?.content ?? "const __forgeVueDefault = {};";
342
+ const template = descriptor.template === null
343
+ ? undefined
344
+ : (0, compiler_sfc_1.compileTemplate)({
345
+ compilerOptions: {
346
+ bindingMetadata: script?.bindings ?? {},
347
+ },
348
+ filename,
349
+ id,
350
+ scoped: descriptor.styles.some((style) => style.scoped),
351
+ source: descriptor.template.content,
352
+ });
353
+ if (template?.errors !== undefined && template.errors.length > 0) {
354
+ throw new Error(formatVueCompilerErrors(template.errors));
355
+ }
356
+ const templateContent = template?.code ?? "function render() { return null; }";
357
+ return [
358
+ scriptContent,
359
+ "",
360
+ templateContent,
361
+ "",
362
+ "const __forgeVueComponent = Object.assign(__forgeVueDefault, {",
363
+ ` __file: ${JSON.stringify(sourcePath)},`,
364
+ " render,",
365
+ "});",
366
+ "",
367
+ "export default __forgeVueComponent;",
368
+ "",
369
+ ].join("\n");
295
370
  }
296
- function createCssModule(sourcePath, css) {
371
+ function formatVueCompilerErrors(errors) {
372
+ return errors
373
+ .map((error) => (error instanceof Error ? error.message : String(error)))
374
+ .join("\n");
375
+ }
376
+ function createWorkspaceCssModule(sourcePath, css) {
377
+ return isCssModulePath(sourcePath)
378
+ ? createCssModule(sourcePath, css)
379
+ : createPlainCssModule(sourcePath, css);
380
+ }
381
+ function createPlainCssModule(sourcePath, css) {
297
382
  return [
298
383
  `const css = ${JSON.stringify(css)};`,
299
384
  `const id = ${JSON.stringify(`forge-css:${sourcePath}`)};`,
@@ -306,6 +391,70 @@ function createCssModule(sourcePath, css) {
306
391
  "",
307
392
  ].join("\n");
308
393
  }
394
+ function createCssModule(sourcePath, css) {
395
+ const protectedCss = protectCssModuleGlobalSelectors(css);
396
+ const classMap = createCssModuleClassMap(sourcePath, protectedCss.css);
397
+ const rewrittenCss = restoreCssModuleGlobalSelectors(rewriteCssModuleClassSelectors(protectedCss.css, classMap), protectedCss.globalSelectors);
398
+ return [
399
+ `const css = ${JSON.stringify(rewrittenCss)};`,
400
+ `const id = ${JSON.stringify(`forge-css:${sourcePath}`)};`,
401
+ "const previous = document.querySelector(`style[data-forge-css=\"${id}\"]`);",
402
+ "const style = previous ?? document.createElement('style');",
403
+ "style.setAttribute('data-forge-css', id);",
404
+ "style.textContent = css;",
405
+ "if (previous === null) document.head.append(style);",
406
+ `const classes = ${JSON.stringify(classMap, null, 2)};`,
407
+ "export default classes;",
408
+ "",
409
+ ].join("\n");
410
+ }
411
+ function protectCssModuleGlobalSelectors(css) {
412
+ const globalSelectors = [];
413
+ const protectedCss = css.replace(/:global\(([^()]*)\)/g, (_match, selector) => {
414
+ const placeholder = `/*__forge_css_module_global_${globalSelectors.length}__*/`;
415
+ globalSelectors.push({ placeholder, selector });
416
+ return placeholder;
417
+ });
418
+ return { css: protectedCss, globalSelectors };
419
+ }
420
+ function restoreCssModuleGlobalSelectors(css, globalSelectors) {
421
+ return globalSelectors.reduce((currentCss, globalSelector) => currentCss
422
+ .split(globalSelector.placeholder)
423
+ .join(globalSelector.selector), css);
424
+ }
425
+ function createCssModuleClassMap(sourcePath, css) {
426
+ const classNames = new Set();
427
+ for (const match of css.matchAll(/\.([A-Za-z_][\w-]*)/g)) {
428
+ classNames.add(match[1]);
429
+ }
430
+ return Object.fromEntries(Array.from(classNames)
431
+ .sort((left, right) => left.localeCompare(right))
432
+ .map((className) => [
433
+ className,
434
+ createCssModuleScopedClassName(sourcePath, className),
435
+ ]));
436
+ }
437
+ function rewriteCssModuleClassSelectors(css, classMap) {
438
+ return css.replace(/(^|[\s,{>+~])\.([A-Za-z_][\w-]*)/g, (match, prefix, className) => {
439
+ const scopedClassName = classMap[className];
440
+ return scopedClassName === undefined
441
+ ? match
442
+ : `${prefix}.${scopedClassName}`;
443
+ });
444
+ }
445
+ function createCssModuleScopedClassName(sourcePath, className) {
446
+ const pathParts = sourcePath.split("/");
447
+ const fileName = pathParts[pathParts.length - 1] ?? "style.module.css";
448
+ const baseName = fileName
449
+ .replace(/\.module\.css$/i, "")
450
+ .replace(/[^a-z0-9_-]+/gi, "_");
451
+ const safeClassName = className.replace(/[^a-z0-9_-]+/gi, "_");
452
+ const hash = hashText(`${sourcePath}:${className}`).slice(0, 8);
453
+ return `_${baseName}_${safeClassName}_${hash}`;
454
+ }
455
+ function isCssModulePath(path) {
456
+ return /\.module\.css$/i.test(path);
457
+ }
309
458
  function createJsonModule(json) {
310
459
  return `export default ${json.trim()};\n`;
311
460
  }
@@ -346,6 +495,31 @@ function extractImportReferences(source) {
346
495
  }
347
496
  return references;
348
497
  }
498
+ function resolveAliasSpecifier(specifier, aliases) {
499
+ for (const [find, replacement] of Object.entries(aliases).sort(([left], [right]) => right.length - left.length || left.localeCompare(right))) {
500
+ if (specifier === find) {
501
+ return replacement;
502
+ }
503
+ if (specifier.startsWith(`${find}/`)) {
504
+ const normalizedReplacement = replacement.endsWith("/")
505
+ ? replacement.slice(0, -1)
506
+ : replacement;
507
+ return `${normalizedReplacement}${specifier.slice(find.length)}`;
508
+ }
509
+ }
510
+ return undefined;
511
+ }
512
+ function applyDefineReplacements(source, defineReplacements) {
513
+ let output = source;
514
+ for (const [key, value] of Object.entries(defineReplacements).sort(([left], [right]) => right.length - left.length || left.localeCompare(right))) {
515
+ if (!isSupportedDefineKey(key)) {
516
+ continue;
517
+ }
518
+ const pattern = new RegExp(`(^|[^A-Za-z0-9_$.])${escapeRegExp(key)}(?![A-Za-z0-9_$])`, "g");
519
+ output = output.replace(pattern, (_match, prefix) => `${prefix}${value}`);
520
+ }
521
+ return output;
522
+ }
349
523
  async function resolveLocalImport(fileSystem, importer, specifier) {
350
524
  const basePath = specifier.startsWith("/")
351
525
  ? specifier
@@ -517,6 +691,12 @@ function isLocalSpecifier(specifier) {
517
691
  function isExternalUrl(specifier) {
518
692
  return /^https?:\/\//i.test(specifier) || specifier.startsWith("data:");
519
693
  }
694
+ function isSupportedDefineKey(key) {
695
+ return /^[A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*)*$/.test(key);
696
+ }
697
+ function escapeRegExp(value) {
698
+ return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
699
+ }
520
700
  function dirname(path) {
521
701
  const index = path.lastIndexOf("/");
522
702
  return index <= 0 ? "/" : path.slice(0, index);
@@ -64,7 +64,7 @@ function createViteConfigNotExecutedDiagnostic(path) {
64
64
  code: "vite_config_not_executed",
65
65
  severity: "warning",
66
66
  message: `Forge detected ${path} but did not execute it. ` +
67
- "Config-driven aliases, plugins, defines, and server options are ignored.",
67
+ "Only static aliases, defines, and base are parsed; plugins and dynamic config are ignored.",
68
68
  path,
69
69
  };
70
70
  }
@@ -1,3 +1,3 @@
1
1
  export { createBuildCancelledDiagnostic, createEsbuildWorkerTransformDiagnostic, createMissingBuildScriptDiagnostic, createMissingEntryDiagnostic, createUnresolvedImportDiagnostic, createUnsupportedBuildScriptDiagnostic, createViteConfigNotExecutedDiagnostic, } from "./diagnostics";
2
2
  export { createBuildPipeline, DefaultBuildPipeline, isSupportedViteBuildScript, } from "./pipeline";
3
- export { BUILD_PIPELINE_CAPABILITY, type ForgeBrowserBundle, type ForgeBrowserBundleManifest, type ForgeBuildDiagnostic, type ForgeBuildManifest, type ForgeBuildMode, type ForgeBuildOutputFile, type ForgeBuildPipeline, type ForgeBuildPipelineDiagnostic, type ForgeBuildPipelineDiagnosticCode, type ForgeBuildPipelineOptions, type ForgeBuildRequest, type ForgeBuildResult, type ForgeBuildTiming, } from "./types";
3
+ export { BUILD_PIPELINE_CAPABILITY, type ForgeBrowserBundle, type ForgeBrowserBundleManifest, type ForgeBrowserBundleModule, type ForgeBrowserBundleModuleOrigin, type ForgeBuildDiagnostic, type ForgeBuildManifest, type ForgeBuildMode, type ForgeBuildOutputFile, type ForgeBuildPipeline, type ForgeBuildPipelineDiagnostic, type ForgeBuildPipelineDiagnosticCode, type ForgeBuildPipelineOptions, type ForgeBuildRequest, type ForgeBuildResult, type ForgeBuildTiming, type ForgeViteConfigMetadata, } from "./types";
@@ -7,12 +7,8 @@ const virtual_file_system_1 = require("../virtual-file-system");
7
7
  const diagnostics_1 = require("./diagnostics");
8
8
  const browser_bundle_1 = require("./browser-bundle");
9
9
  const types_1 = require("./types");
10
+ const vite_config_1 = require("./vite-config");
10
11
  const BUILD_MANIFEST_PATH = "/.forge/build/build-manifest.json";
11
- const VITE_CONFIG_PATHS = [
12
- "/vite.config.js",
13
- "/vite.config.mjs",
14
- "/vite.config.ts",
15
- ];
16
12
  const DEFAULT_ENTRY_CANDIDATES = [
17
13
  "/src/main.tsx",
18
14
  "/src/main.jsx",
@@ -32,10 +28,12 @@ class DefaultBuildPipeline {
32
28
  if (initialCancellation !== undefined) {
33
29
  return this.failure(mode, [initialCancellation], timingStart);
34
30
  }
35
- const warningDiagnostics = await detectViteConfigDiagnostics(this.options.fileSystem);
31
+ const viteConfigRead = await (0, vite_config_1.readViteConfigMetadata)(this.options.fileSystem);
32
+ const warningDiagnostics = createViteConfigDiagnostics(viteConfigRead.detectedPaths);
33
+ const viteConfig = viteConfigRead.metadata;
36
34
  const configCancellation = getCancellationDiagnostic(request.signal);
37
35
  if (configCancellation !== undefined) {
38
- return this.failure(mode, [configCancellation, ...warningDiagnostics], timingStart);
36
+ return this.failure(mode, [configCancellation, ...warningDiagnostics], timingStart, viteConfig);
39
37
  }
40
38
  let manifest;
41
39
  try {
@@ -43,34 +41,34 @@ class DefaultBuildPipeline {
43
41
  }
44
42
  catch (error) {
45
43
  if (error instanceof package_resolution_1.ForgePackageResolutionError) {
46
- return this.failure(mode, [error.diagnostic, ...error.warnings, ...warningDiagnostics], timingStart);
44
+ return this.failure(mode, [error.diagnostic, ...error.warnings, ...warningDiagnostics], timingStart, viteConfig);
47
45
  }
48
46
  throw error;
49
47
  }
50
48
  const buildScript = manifest.scripts.build;
51
49
  if (buildScript === undefined) {
52
- return this.failure(mode, [(0, diagnostics_1.createMissingBuildScriptDiagnostic)(), ...warningDiagnostics], timingStart);
50
+ return this.failure(mode, [(0, diagnostics_1.createMissingBuildScriptDiagnostic)(), ...warningDiagnostics], timingStart, viteConfig);
53
51
  }
54
52
  if (!isSupportedViteBuildScript(buildScript)) {
55
53
  return this.failure(mode, [
56
54
  (0, diagnostics_1.createUnsupportedBuildScriptDiagnostic)(buildScript),
57
55
  ...warningDiagnostics,
58
- ], timingStart);
56
+ ], timingStart, viteConfig);
59
57
  }
60
58
  const manifestCancellation = getCancellationDiagnostic(request.signal);
61
59
  if (manifestCancellation !== undefined) {
62
- return this.failure(mode, [manifestCancellation, ...warningDiagnostics], timingStart);
60
+ return this.failure(mode, [manifestCancellation, ...warningDiagnostics], timingStart, viteConfig);
63
61
  }
64
62
  const entry = await this.resolveEntry(request.entry);
65
63
  if (entry === undefined) {
66
- return this.failure(mode, [(0, diagnostics_1.createMissingEntryDiagnostic)(), ...warningDiagnostics], timingStart);
64
+ return this.failure(mode, [(0, diagnostics_1.createMissingEntryDiagnostic)(), ...warningDiagnostics], timingStart, viteConfig);
67
65
  }
68
66
  try {
69
67
  const packageResolution = await this.options.packageResolver.resolve();
70
68
  const packageWarnings = packageResolution.warnings;
71
69
  const packageCancellation = getCancellationDiagnostic(request.signal);
72
70
  if (packageCancellation !== undefined) {
73
- return this.failure(mode, [packageCancellation, ...packageWarnings, ...warningDiagnostics], timingStart);
71
+ return this.failure(mode, [packageCancellation, ...packageWarnings, ...warningDiagnostics], timingStart, viteConfig);
74
72
  }
75
73
  const sourceFiles = await collectSourceFiles(this.options.fileSystem);
76
74
  const browserBundleResult = await (0, browser_bundle_1.createBrowserBundle)({
@@ -78,38 +76,39 @@ class DefaultBuildPipeline {
78
76
  fileSystem: this.options.fileSystem,
79
77
  packageResolution,
80
78
  scriptTransformer: createEsbuildWorkerScriptTransformer(this.options.esbuildWorker),
79
+ viteConfig,
81
80
  });
82
81
  if (browserBundleResult.diagnostics.length > 0) {
83
82
  return this.failure(mode, [
84
83
  ...browserBundleResult.diagnostics,
85
84
  ...packageWarnings,
86
85
  ...warningDiagnostics,
87
- ], timingStart);
86
+ ], timingStart, viteConfig);
88
87
  }
89
88
  if (browserBundleResult.browserBundle === undefined) {
90
89
  throw new Error("Browser bundle output was missing after a successful build.");
91
90
  }
92
91
  const bundleCancellation = getCancellationDiagnostic(request.signal);
93
92
  if (bundleCancellation !== undefined) {
94
- return this.failure(mode, [bundleCancellation, ...packageWarnings, ...warningDiagnostics], timingStart);
93
+ return this.failure(mode, [bundleCancellation, ...packageWarnings, ...warningDiagnostics], timingStart, viteConfig);
95
94
  }
96
- const buildManifest = createBuildManifest(entry, mode, sourceFiles, packageResolution, browserBundleResult.browserBundle);
95
+ const buildManifest = createBuildManifest(entry, mode, sourceFiles, packageResolution, browserBundleResult.browserBundle, viteConfig);
97
96
  const outputFiles = [
98
97
  createBuildManifestOutput(buildManifest),
99
98
  ...browserBundleResult.outputFiles,
100
99
  ];
101
100
  const outputCancellation = getCancellationDiagnostic(request.signal);
102
101
  if (outputCancellation !== undefined) {
103
- return this.failure(mode, [outputCancellation, ...packageWarnings, ...warningDiagnostics], timingStart);
102
+ return this.failure(mode, [outputCancellation, ...packageWarnings, ...warningDiagnostics], timingStart, viteConfig);
104
103
  }
105
104
  const outputWriteDiagnostic = await writeBuildOutputFilesAtomically(this.options.fileSystem, outputFiles);
106
105
  if (outputWriteDiagnostic !== undefined) {
107
- return this.failure(mode, [outputWriteDiagnostic, ...packageWarnings, ...warningDiagnostics], timingStart);
106
+ return this.failure(mode, [outputWriteDiagnostic, ...packageWarnings, ...warningDiagnostics], timingStart, viteConfig);
108
107
  }
109
108
  const buildCacheWarnings = await this.writeBuildCacheRecord(entry, mode, buildManifest, browserBundleResult.browserBundle, outputFiles);
110
109
  const cacheCancellation = getCancellationDiagnostic(request.signal);
111
110
  if (cacheCancellation !== undefined) {
112
- return this.failure(mode, [cacheCancellation, ...packageWarnings, ...buildCacheWarnings, ...warningDiagnostics], timingStart);
111
+ return this.failure(mode, [cacheCancellation, ...packageWarnings, ...buildCacheWarnings, ...warningDiagnostics], timingStart, viteConfig);
113
112
  }
114
113
  return this.complete({
115
114
  success: true,
@@ -124,12 +123,13 @@ class DefaultBuildPipeline {
124
123
  ...warningDiagnostics,
125
124
  ],
126
125
  packageResolution,
126
+ viteConfig,
127
127
  timing: completeTiming(timingStart, this.now()),
128
128
  });
129
129
  }
130
130
  catch (error) {
131
131
  if (error instanceof package_resolution_1.ForgePackageResolutionError) {
132
- return this.failure(mode, [error.diagnostic, ...error.warnings, ...warningDiagnostics], timingStart);
132
+ return this.failure(mode, [error.diagnostic, ...error.warnings, ...warningDiagnostics], timingStart, viteConfig);
133
133
  }
134
134
  throw error;
135
135
  }
@@ -153,12 +153,13 @@ class DefaultBuildPipeline {
153
153
  }
154
154
  return undefined;
155
155
  }
156
- failure(mode, diagnostics, timingStart) {
156
+ failure(mode, diagnostics, timingStart, viteConfig) {
157
157
  return this.complete({
158
158
  success: false,
159
159
  mode,
160
160
  outputFiles: [],
161
161
  diagnostics,
162
+ viteConfig,
162
163
  timing: completeTiming(timingStart, this.now()),
163
164
  });
164
165
  }
@@ -255,14 +256,8 @@ function createEsbuildWorkerScriptTransformer(esbuildWorker) {
255
256
  };
256
257
  };
257
258
  }
258
- async function detectViteConfigDiagnostics(fileSystem) {
259
- const diagnostics = [];
260
- for (const path of VITE_CONFIG_PATHS) {
261
- if (await fileSystem.exists(path)) {
262
- diagnostics.push((0, diagnostics_1.createViteConfigNotExecutedDiagnostic)(path));
263
- }
264
- }
265
- return diagnostics;
259
+ function createViteConfigDiagnostics(paths) {
260
+ return paths.map((path) => (0, diagnostics_1.createViteConfigNotExecutedDiagnostic)(path));
266
261
  }
267
262
  function createBuildPipeline(options) {
268
263
  return new DefaultBuildPipeline(options);
@@ -309,13 +304,14 @@ async function collectSourceFiles(fileSystem, path = "/") {
309
304
  }
310
305
  return files.sort((left, right) => left.localeCompare(right));
311
306
  }
312
- function createBuildManifest(entry, mode, sourceFiles, packageResolution, browserBundle) {
307
+ function createBuildManifest(entry, mode, sourceFiles, packageResolution, browserBundle, viteConfig) {
313
308
  return {
314
309
  entry,
315
310
  mode,
316
311
  sourceFiles,
317
312
  packageNames: packageResolution.packages.map((record) => record.name),
318
313
  packageResolutionMode: packageResolution.lock.resolutionMode,
314
+ viteConfig,
319
315
  browserBundle: browserBundle === undefined
320
316
  ? undefined
321
317
  : {
@@ -323,7 +319,9 @@ function createBuildManifest(entry, mode, sourceFiles, packageResolution, browse
323
319
  format: browserBundle.format,
324
320
  importMapPath: browserBundle.importMapPath,
325
321
  moduleCount: browserBundle.moduleCount,
322
+ modules: browserBundle.modules,
326
323
  outputPaths: browserBundle.outputPaths,
324
+ viteConfig: browserBundle.viteConfig,
327
325
  },
328
326
  };
329
327
  }
@@ -23,6 +23,12 @@ export interface ForgeBuildOutputFile {
23
23
  readonly contentType: string;
24
24
  readonly size: number;
25
25
  }
26
+ export interface ForgeViteConfigMetadata {
27
+ readonly path: string;
28
+ readonly aliases: Readonly<Record<string, string>>;
29
+ readonly define: Readonly<Record<string, string>>;
30
+ readonly base?: string;
31
+ }
26
32
  export interface ForgeBuildManifest {
27
33
  readonly entry: string;
28
34
  readonly mode: ForgeBuildMode;
@@ -30,13 +36,22 @@ export interface ForgeBuildManifest {
30
36
  readonly packageNames: readonly string[];
31
37
  readonly packageResolutionMode: string;
32
38
  readonly browserBundle?: ForgeBrowserBundleManifest;
39
+ readonly viteConfig?: ForgeViteConfigMetadata;
40
+ }
41
+ export type ForgeBrowserBundleModuleOrigin = "package" | "workspace";
42
+ export interface ForgeBrowserBundleModule {
43
+ readonly origin: ForgeBrowserBundleModuleOrigin;
44
+ readonly outputPath: string;
45
+ readonly sourcePath: string;
33
46
  }
34
47
  export interface ForgeBrowserBundleManifest {
35
48
  readonly entryOutputPath: string;
36
49
  readonly format: "esm";
37
50
  readonly importMapPath: string;
38
51
  readonly moduleCount: number;
52
+ readonly modules: readonly ForgeBrowserBundleModule[];
39
53
  readonly outputPaths: readonly string[];
54
+ readonly viteConfig?: ForgeViteConfigMetadata;
40
55
  }
41
56
  export interface ForgeBrowserBundle {
42
57
  readonly entry: string;
@@ -45,7 +60,9 @@ export interface ForgeBrowserBundle {
45
60
  readonly importMap: ForgeImportMap;
46
61
  readonly importMapPath: string;
47
62
  readonly moduleCount: number;
63
+ readonly modules: readonly ForgeBrowserBundleModule[];
48
64
  readonly outputPaths: readonly string[];
65
+ readonly viteConfig?: ForgeViteConfigMetadata;
49
66
  }
50
67
  export interface ForgeBuildTiming {
51
68
  readonly startedAt: string;
@@ -61,6 +78,7 @@ export interface ForgeBuildResult {
61
78
  readonly outputFiles: readonly ForgeBuildOutputFile[];
62
79
  readonly diagnostics: readonly ForgeBuildDiagnostic[];
63
80
  readonly packageResolution?: ForgePackageResolutionResult;
81
+ readonly viteConfig?: ForgeViteConfigMetadata;
64
82
  readonly timing: ForgeBuildTiming;
65
83
  }
66
84
  export interface ForgeBuildPipelineOptions {
@@ -0,0 +1,8 @@
1
+ import { type ForgeVirtualFileSystem } from "../virtual-file-system";
2
+ import type { ForgeViteConfigMetadata } from "./types";
3
+ export declare const VITE_CONFIG_PATHS: readonly ["/vite.config.js", "/vite.config.mjs", "/vite.config.ts"];
4
+ export interface ForgeViteConfigReadResult {
5
+ readonly detectedPaths: readonly string[];
6
+ readonly metadata?: ForgeViteConfigMetadata;
7
+ }
8
+ export declare function readViteConfigMetadata(fileSystem: ForgeVirtualFileSystem): Promise<ForgeViteConfigReadResult>;