angular-rust-plugins 0.4.0 → 0.6.0

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/compiler/index.js CHANGED
@@ -3,6 +3,49 @@ import { createRequire } from "module";
3
3
  import { dirname, join } from "path";
4
4
  import { fileURLToPath } from "url";
5
5
  var compilerInstance = null;
6
+ var RED = "\x1B[31m";
7
+ var YELLOW = "\x1B[33m";
8
+ var CYAN = "\x1B[36m";
9
+ var BOLD = "\x1B[1m";
10
+ var RESET = "\x1B[0m";
11
+ function formatDiagnostic(diag, sourceCode) {
12
+ const level = "WARNING";
13
+ const codeStr = `NG${diag.code}`;
14
+ const file = diag.file || "unknown";
15
+ let line = 1;
16
+ let col = 0;
17
+ let lineStartPos = 0;
18
+ if (diag.start !== void 0 && diag.start !== null) {
19
+ for (let i = 0; i < diag.start && i < sourceCode.length; i++) {
20
+ if (sourceCode[i] === "\n") {
21
+ line++;
22
+ col = 0;
23
+ lineStartPos = i + 1;
24
+ } else {
25
+ col++;
26
+ }
27
+ }
28
+ }
29
+ let output = `
30
+ ${BOLD}${YELLOW}\u25B2 [${level}] ${RED}${codeStr}${RESET}${BOLD}: ${diag.message}${RESET} ${YELLOW}[plugin rust-ngc-plugin]${RESET}
31
+ `;
32
+ const lineStr = line.toString();
33
+ const colStr = (col + 1).toString();
34
+ output += `
35
+ ${CYAN}${file}:${lineStr}:${colStr}:${RESET}
36
+ `;
37
+ let lineEndPos = sourceCode.indexOf("\n", lineStartPos);
38
+ if (lineEndPos === -1) lineEndPos = sourceCode.length;
39
+ const lineContent = sourceCode.substring(lineStartPos, lineEndPos);
40
+ output += ` ${BOLD}${lineStr} \u2502 ${RESET}${lineContent}
41
+ `;
42
+ const gutterWidth = lineStr.length + 3;
43
+ const gutterEmpty = " ".repeat(gutterWidth);
44
+ const length = diag.length || 1;
45
+ const underline = "~".repeat(length);
46
+ output += ` ${gutterEmpty}${" ".repeat(col)}${RED}${underline}${RESET}`;
47
+ return output;
48
+ }
6
49
  function getCompiler(options) {
7
50
  if (compilerInstance) {
8
51
  return compilerInstance;
@@ -57,9 +100,26 @@ function angularCompilerVitePlugin(options) {
57
100
  compiler = getCompiler(options);
58
101
  }
59
102
  if (id.includes("node_modules")) {
103
+ if (id.includes("@angular") && code.includes("\u0275\u0275ngDeclare")) {
104
+ const cleanId2 = id.split("?")[0];
105
+ if (cleanId2.endsWith(".mjs") || cleanId2.endsWith(".js")) {
106
+ try {
107
+ const result = compiler.linkFile(id, code);
108
+ if (result.startsWith("/* Linker Error")) {
109
+ if (debug) console.error(`[Linker Error] ${id}: ${result}`);
110
+ return null;
111
+ }
112
+ return { code: result, map: null };
113
+ } catch (e) {
114
+ if (debug) console.error(`Linker failed for ${id}:`, e);
115
+ return null;
116
+ }
117
+ }
118
+ }
60
119
  return null;
61
120
  }
62
- if (!id.endsWith(".ts") || id.endsWith(".d.ts")) {
121
+ const cleanId = id.split("?")[0];
122
+ if (!cleanId.endsWith(".ts") || cleanId.endsWith(".d.ts")) {
63
123
  return null;
64
124
  }
65
125
  if (debug) {
@@ -67,15 +127,21 @@ function angularCompilerVitePlugin(options) {
67
127
  }
68
128
  try {
69
129
  const result = compiler.compile(id, code);
70
- if (result.startsWith("/* Error")) {
130
+ const { code: compiledCode, diagnostics } = result;
131
+ if (compiledCode.startsWith("/* Error")) {
71
132
  console.error(`[Angular Compiler Error] ${id}:
72
- ${result}`);
133
+ ${compiledCode}`);
73
134
  throw new Error(`Rust Compilation Failed for ${id}`);
74
135
  }
136
+ if (diagnostics && diagnostics.length > 0) {
137
+ diagnostics.forEach((diag) => {
138
+ console.warn(formatDiagnostic(diag, code));
139
+ });
140
+ }
75
141
  if (debug) {
76
142
  console.log(`[Angular Compiler] Successfully compiled: ${id}`);
77
143
  }
78
- return { code: result, map: null };
144
+ return { code: compiledCode, map: null };
79
145
  } catch (e) {
80
146
  console.error(`[Angular Compiler Failed] ${id}:`, e);
81
147
  throw e;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/compiler/vite.ts"],"sourcesContent":["/**\n * Angular Compiler Plugin for Vite\n *\n * This plugin compiles Angular TypeScript files using the Rust-based Angular compiler.\n * Use with the linker plugin for a complete Angular build solution.\n *\n * @example\n * ```js\n * import { angularCompilerVitePlugin } from 'angular-rust-plugins/compiler/vite';\n * import { angularLinkerVitePlugin } from 'angular-rust-plugins/linker/vite';\n * import { defineConfig } from 'vite';\n *\n * export default defineConfig({\n * plugins: [\n * angularLinkerVitePlugin(),\n * angularCompilerVitePlugin(),\n * ],\n * });\n * ```\n */\n\nimport type { Plugin, HmrContext } from \"vite\";\nimport { createRequire } from \"module\";\nimport { dirname, join } from \"path\";\nimport { fileURLToPath } from \"url\";\nimport type { CompilerBinding } from \"./types\";\n\nlet compilerInstance: CompilerBinding | null = null;\n\nexport interface CompilerOptions {\n /**\n * Enable debug logging\n * @default false\n */\n debug?: boolean;\n\n /**\n * Custom path to the Angular Rust binding package\n */\n bindingPath?: string;\n}\n\nfunction getCompiler(options?: CompilerOptions): CompilerBinding {\n if (compilerInstance) {\n return compilerInstance;\n }\n\n try {\n let binding: { Compiler: new () => CompilerBinding };\n\n if (options?.bindingPath) {\n const require = createRequire(import.meta.url);\n binding = require(options.bindingPath);\n } else {\n // Load from bundled binding directory\n // Use import.meta.url to get the actual location of this file\n const currentFileUrl = import.meta.url;\n const currentFilePath = fileURLToPath(currentFileUrl);\n const currentDir = dirname(currentFilePath);\n const require = createRequire(currentFileUrl);\n\n // Try multiple possible binding locations\n const possiblePaths = [\n join(currentDir, \"..\", \"binding\"), // dist/compiler/../binding\n join(currentDir, \"..\", \"..\", \"binding\"), // in case of deeper nesting\n join(currentDir, \"binding\"), // same directory\n ];\n\n let loadedBinding: { Compiler: new () => CompilerBinding } | null = null;\n let lastError: unknown = null;\n\n for (const bindingPath of possiblePaths) {\n try {\n loadedBinding = require(bindingPath);\n break;\n } catch (e) {\n lastError = e;\n }\n }\n\n if (!loadedBinding) {\n throw (\n lastError ||\n new Error(\"Could not find binding in any expected location\")\n );\n }\n\n binding = loadedBinding;\n }\n\n compilerInstance = new binding.Compiler();\n return compilerInstance;\n } catch (e) {\n throw new Error(`Failed to load Angular Rust binding. Error: ${e}`);\n }\n}\n\n/**\n * Creates a Vite plugin for Angular Rust compiler\n * Compiles .ts files (except .d.ts) using the Rust compiler\n */\nexport function angularCompilerVitePlugin(options?: CompilerOptions): Plugin {\n const debug = options?.debug ?? false;\n let compiler: CompilerBinding;\n\n return {\n name: \"angular-rust-compiler\",\n enforce: \"pre\",\n\n transform(code: string, id: string) {\n // Lazy initialize compiler\n if (!compiler) {\n compiler = getCompiler(options);\n }\n\n // Skip node_modules - those are handled by linker, not compiler\n if (id.includes(\"node_modules\")) {\n return null;\n }\n\n // Only process TypeScript files, skip declaration files\n if (!id.endsWith(\".ts\") || id.endsWith(\".d.ts\")) {\n return null;\n }\n\n if (debug) {\n console.log(`[Angular Compiler] Compiling: ${id}`);\n }\n\n try {\n const result = compiler.compile(id, code);\n\n if (result.startsWith(\"/* Error\")) {\n console.error(`[Angular Compiler Error] ${id}:\\n${result}`);\n throw new Error(`Rust Compilation Failed for ${id}`);\n }\n\n if (debug) {\n console.log(`[Angular Compiler] Successfully compiled: ${id}`);\n }\n\n return { code: result, map: null };\n } catch (e) {\n console.error(`[Angular Compiler Failed] ${id}:`, e);\n throw e;\n }\n },\n\n handleHotUpdate({ file, server }: HmrContext) {\n // When HTML template changes, invalidate the corresponding TS file\n if (file.endsWith(\".html\")) {\n const tsFile = file.replace(/\\.html$/, \".ts\");\n\n if (debug) {\n console.log(`[HMR] HTML changed: ${file}`);\n console.log(`[HMR] Invalidating TS: ${tsFile}`);\n }\n\n const mod = server.moduleGraph.getModuleById(tsFile);\n if (mod) {\n server.moduleGraph.invalidateModule(mod);\n server.ws.send({ type: \"full-reload\", path: \"*\" });\n return [];\n } else {\n server.ws.send({ type: \"full-reload\", path: \"*\" });\n return [];\n }\n }\n },\n };\n}\n\nexport default angularCompilerVitePlugin;\n"],"mappings":"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","names":["require"]}
1
+ {"version":3,"sources":["../../src/compiler/vite.ts"],"sourcesContent":["/**\n * Angular Compiler Plugin for Vite\n *\n * This plugin compiles Angular TypeScript files using the Rust-based Angular compiler.\n * Use with the linker plugin for a complete Angular build solution.\n *\n * @example\n * ```js\n * import { angularCompilerVitePlugin } from 'angular-rust-plugins/compiler/vite';\n * import { angularLinkerVitePlugin } from 'angular-rust-plugins/linker/vite';\n * import { defineConfig } from 'vite';\n *\n * export default defineConfig({\n * plugins: [\n * angularLinkerVitePlugin(),\n * angularCompilerVitePlugin(),\n * ],\n * });\n * ```\n */\n\nimport type { Plugin, HmrContext } from \"vite\";\nimport { createRequire } from \"module\";\nimport { dirname, join } from \"path\";\nimport { fileURLToPath } from \"url\";\nimport { Compiler } from \"../binding\";\n\nlet compilerInstance: Compiler | null = null;\n\nexport interface CompilerOptions {\n /**\n * Enable debug logging\n * @default false\n */\n debug?: boolean;\n\n /**\n * Custom path to the Angular Rust binding package\n */\n bindingPath?: string;\n}\n\n// ============ Diagnostic Formatting ============\nconst RED = '\\x1b[31m';\nconst YELLOW = '\\x1b[33m';\nconst CYAN = '\\x1b[36m';\nconst BOLD = '\\x1b[1m';\nconst RESET = '\\x1b[0m';\n\nfunction formatDiagnostic(diag: any, sourceCode: string): string {\n const level = 'WARNING';\n const codeStr = `NG${diag.code}`;\n const file = diag.file || 'unknown';\n\n let line = 1;\n let col = 0;\n let lineStartPos = 0;\n\n if (diag.start !== undefined && diag.start !== null) {\n for (let i = 0; i < diag.start && i < sourceCode.length; i++) {\n if (sourceCode[i] === '\\n') {\n line++;\n col = 0;\n lineStartPos = i + 1;\n } else {\n col++;\n }\n }\n }\n\n let output = `\\n${BOLD}${YELLOW}▲ [${level}] ${RED}${codeStr}${RESET}${BOLD}: ${diag.message}${RESET} ${YELLOW}[plugin rust-ngc-plugin]${RESET}\\n`;\n\n const lineStr = line.toString();\n const colStr = (col + 1).toString();\n output += `\\n ${CYAN}${file}:${lineStr}:${colStr}:${RESET}\\n`;\n\n let lineEndPos = sourceCode.indexOf('\\n', lineStartPos);\n if (lineEndPos === -1) lineEndPos = sourceCode.length;\n const lineContent = sourceCode.substring(lineStartPos, lineEndPos);\n\n output += ` ${BOLD}${lineStr} │ ${RESET}${lineContent}\\n`;\n\n const gutterWidth = lineStr.length + 3;\n const gutterEmpty = ' '.repeat(gutterWidth);\n const length = diag.length || 1;\n const underline = '~'.repeat(length);\n\n output += ` ${gutterEmpty}${' '.repeat(col)}${RED}${underline}${RESET}`;\n\n return output;\n}\n\nfunction getCompiler(options?: CompilerOptions): Compiler {\n if (compilerInstance) {\n return compilerInstance;\n }\n\n try {\n let binding: { Compiler: new () => Compiler };\n\n if (options?.bindingPath) {\n const require = createRequire(import.meta.url);\n binding = require(options.bindingPath);\n } else {\n // Load from bundled binding directory\n // Use import.meta.url to get the actual location of this file\n const currentFileUrl = import.meta.url;\n const currentFilePath = fileURLToPath(currentFileUrl);\n const currentDir = dirname(currentFilePath);\n const require = createRequire(currentFileUrl);\n\n // Try multiple possible binding locations\n const possiblePaths = [\n join(currentDir, \"..\", \"binding\"), // dist/compiler/../binding\n join(currentDir, \"..\", \"..\", \"binding\"), // in case of deeper nesting\n join(currentDir, \"binding\"), // same directory\n ];\n\n let loadedBinding: { Compiler: new () => Compiler } | null = null;\n let lastError: unknown = null;\n\n for (const bindingPath of possiblePaths) {\n try {\n loadedBinding = require(bindingPath);\n break;\n } catch (e) {\n lastError = e;\n }\n }\n\n if (!loadedBinding) {\n throw (\n lastError ||\n new Error(\"Could not find binding in any expected location\")\n );\n }\n\n binding = loadedBinding;\n }\n\n compilerInstance = new binding.Compiler();\n return compilerInstance;\n } catch (e) {\n throw new Error(`Failed to load Angular Rust binding. Error: ${e}`);\n }\n}\n\n/**\n * Creates a Vite plugin for Angular Rust compiler\n * Compiles .ts files (except .d.ts) using the Rust compiler\n */\nexport function angularCompilerVitePlugin(options?: CompilerOptions): Plugin {\n const debug = options?.debug ?? false;\n let compiler: Compiler;\n\n return {\n name: \"angular-rust-compiler\",\n enforce: \"pre\",\n\n transform(code: string, id: string) {\n // Lazy initialize compiler\n if (!compiler) {\n compiler = getCompiler(options);\n }\n\n // Skip node_modules but check for Angular packages that need linking\n if (id.includes('node_modules')) {\n if (id.includes('@angular') && code.includes('ɵɵngDeclare')) {\n const cleanId = id.split('?')[0];\n if (cleanId.endsWith('.mjs') || cleanId.endsWith('.js')) {\n try {\n const result = compiler.linkFile(id, code);\n if (result.startsWith('/* Linker Error')) {\n if (debug) console.error(`[Linker Error] ${id}: ${result}`);\n return null;\n }\n return { code: result, map: null };\n } catch (e) {\n if (debug) console.error(`Linker failed for ${id}:`, e);\n return null;\n }\n }\n }\n return null;\n }\n\n // Only process TypeScript files, skip declaration files\n const cleanId = id.split('?')[0];\n if (!cleanId.endsWith('.ts') || cleanId.endsWith('.d.ts')) {\n return null;\n }\n\n if (debug) {\n console.log(`[Angular Compiler] Compiling: ${id}`);\n }\n\n try {\n const result = compiler.compile(id, code);\n\n // Handle structured result\n const { code: compiledCode, diagnostics } = result;\n\n if (compiledCode.startsWith('/* Error')) {\n console.error(`[Angular Compiler Error] ${id}:\\n${compiledCode}`);\n throw new Error(`Rust Compilation Failed for ${id}`);\n }\n\n if (diagnostics && diagnostics.length > 0) {\n diagnostics.forEach((diag: any) => {\n console.warn(formatDiagnostic(diag, code));\n });\n }\n\n if (debug) {\n console.log(`[Angular Compiler] Successfully compiled: ${id}`);\n }\n\n return { code: compiledCode, map: null };\n } catch (e) {\n console.error(`[Angular Compiler Failed] ${id}:`, e);\n throw e;\n }\n },\n\n handleHotUpdate({ file, server }: HmrContext) {\n // When HTML template changes, invalidate the corresponding TS file\n if (file.endsWith(\".html\")) {\n const tsFile = file.replace(/\\.html$/, \".ts\");\n\n if (debug) {\n console.log(`[HMR] HTML changed: ${file}`);\n console.log(`[HMR] Invalidating TS: ${tsFile}`);\n }\n\n const mod = server.moduleGraph.getModuleById(tsFile);\n if (mod) {\n server.moduleGraph.invalidateModule(mod);\n server.ws.send({ type: \"full-reload\", path: \"*\" });\n return [];\n } else {\n server.ws.send({ type: \"full-reload\", path: \"*\" });\n return [];\n }\n }\n },\n };\n}\n\nexport default angularCompilerVitePlugin;\n"],"mappings":"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","names":["require","cleanId"]}
package/compiler/vite.cjs CHANGED
@@ -29,6 +29,49 @@ var import_path = require("path");
29
29
  var import_url = require("url");
30
30
  var import_meta = {};
31
31
  var compilerInstance = null;
32
+ var RED = "\x1B[31m";
33
+ var YELLOW = "\x1B[33m";
34
+ var CYAN = "\x1B[36m";
35
+ var BOLD = "\x1B[1m";
36
+ var RESET = "\x1B[0m";
37
+ function formatDiagnostic(diag, sourceCode) {
38
+ const level = "WARNING";
39
+ const codeStr = `NG${diag.code}`;
40
+ const file = diag.file || "unknown";
41
+ let line = 1;
42
+ let col = 0;
43
+ let lineStartPos = 0;
44
+ if (diag.start !== void 0 && diag.start !== null) {
45
+ for (let i = 0; i < diag.start && i < sourceCode.length; i++) {
46
+ if (sourceCode[i] === "\n") {
47
+ line++;
48
+ col = 0;
49
+ lineStartPos = i + 1;
50
+ } else {
51
+ col++;
52
+ }
53
+ }
54
+ }
55
+ let output = `
56
+ ${BOLD}${YELLOW}\u25B2 [${level}] ${RED}${codeStr}${RESET}${BOLD}: ${diag.message}${RESET} ${YELLOW}[plugin rust-ngc-plugin]${RESET}
57
+ `;
58
+ const lineStr = line.toString();
59
+ const colStr = (col + 1).toString();
60
+ output += `
61
+ ${CYAN}${file}:${lineStr}:${colStr}:${RESET}
62
+ `;
63
+ let lineEndPos = sourceCode.indexOf("\n", lineStartPos);
64
+ if (lineEndPos === -1) lineEndPos = sourceCode.length;
65
+ const lineContent = sourceCode.substring(lineStartPos, lineEndPos);
66
+ output += ` ${BOLD}${lineStr} \u2502 ${RESET}${lineContent}
67
+ `;
68
+ const gutterWidth = lineStr.length + 3;
69
+ const gutterEmpty = " ".repeat(gutterWidth);
70
+ const length = diag.length || 1;
71
+ const underline = "~".repeat(length);
72
+ output += ` ${gutterEmpty}${" ".repeat(col)}${RED}${underline}${RESET}`;
73
+ return output;
74
+ }
32
75
  function getCompiler(options) {
33
76
  if (compilerInstance) {
34
77
  return compilerInstance;
@@ -83,9 +126,26 @@ function angularCompilerVitePlugin(options) {
83
126
  compiler = getCompiler(options);
84
127
  }
85
128
  if (id.includes("node_modules")) {
129
+ if (id.includes("@angular") && code.includes("\u0275\u0275ngDeclare")) {
130
+ const cleanId2 = id.split("?")[0];
131
+ if (cleanId2.endsWith(".mjs") || cleanId2.endsWith(".js")) {
132
+ try {
133
+ const result = compiler.linkFile(id, code);
134
+ if (result.startsWith("/* Linker Error")) {
135
+ if (debug) console.error(`[Linker Error] ${id}: ${result}`);
136
+ return null;
137
+ }
138
+ return { code: result, map: null };
139
+ } catch (e) {
140
+ if (debug) console.error(`Linker failed for ${id}:`, e);
141
+ return null;
142
+ }
143
+ }
144
+ }
86
145
  return null;
87
146
  }
88
- if (!id.endsWith(".ts") || id.endsWith(".d.ts")) {
147
+ const cleanId = id.split("?")[0];
148
+ if (!cleanId.endsWith(".ts") || cleanId.endsWith(".d.ts")) {
89
149
  return null;
90
150
  }
91
151
  if (debug) {
@@ -93,15 +153,21 @@ function angularCompilerVitePlugin(options) {
93
153
  }
94
154
  try {
95
155
  const result = compiler.compile(id, code);
96
- if (result.startsWith("/* Error")) {
156
+ const { code: compiledCode, diagnostics } = result;
157
+ if (compiledCode.startsWith("/* Error")) {
97
158
  console.error(`[Angular Compiler Error] ${id}:
98
- ${result}`);
159
+ ${compiledCode}`);
99
160
  throw new Error(`Rust Compilation Failed for ${id}`);
100
161
  }
162
+ if (diagnostics && diagnostics.length > 0) {
163
+ diagnostics.forEach((diag) => {
164
+ console.warn(formatDiagnostic(diag, code));
165
+ });
166
+ }
101
167
  if (debug) {
102
168
  console.log(`[Angular Compiler] Successfully compiled: ${id}`);
103
169
  }
104
- return { code: result, map: null };
170
+ return { code: compiledCode, map: null };
105
171
  } catch (e) {
106
172
  console.error(`[Angular Compiler Failed] ${id}:`, e);
107
173
  throw e;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/compiler/vite.ts"],"sourcesContent":["/**\n * Angular Compiler Plugin for Vite\n *\n * This plugin compiles Angular TypeScript files using the Rust-based Angular compiler.\n * Use with the linker plugin for a complete Angular build solution.\n *\n * @example\n * ```js\n * import { angularCompilerVitePlugin } from 'angular-rust-plugins/compiler/vite';\n * import { angularLinkerVitePlugin } from 'angular-rust-plugins/linker/vite';\n * import { defineConfig } from 'vite';\n *\n * export default defineConfig({\n * plugins: [\n * angularLinkerVitePlugin(),\n * angularCompilerVitePlugin(),\n * ],\n * });\n * ```\n */\n\nimport type { Plugin, HmrContext } from \"vite\";\nimport { createRequire } from \"module\";\nimport { dirname, join } from \"path\";\nimport { fileURLToPath } from \"url\";\nimport type { CompilerBinding } from \"./types\";\n\nlet compilerInstance: CompilerBinding | null = null;\n\nexport interface CompilerOptions {\n /**\n * Enable debug logging\n * @default false\n */\n debug?: boolean;\n\n /**\n * Custom path to the Angular Rust binding package\n */\n bindingPath?: string;\n}\n\nfunction getCompiler(options?: CompilerOptions): CompilerBinding {\n if (compilerInstance) {\n return compilerInstance;\n }\n\n try {\n let binding: { Compiler: new () => CompilerBinding };\n\n if (options?.bindingPath) {\n const require = createRequire(import.meta.url);\n binding = require(options.bindingPath);\n } else {\n // Load from bundled binding directory\n // Use import.meta.url to get the actual location of this file\n const currentFileUrl = import.meta.url;\n const currentFilePath = fileURLToPath(currentFileUrl);\n const currentDir = dirname(currentFilePath);\n const require = createRequire(currentFileUrl);\n\n // Try multiple possible binding locations\n const possiblePaths = [\n join(currentDir, \"..\", \"binding\"), // dist/compiler/../binding\n join(currentDir, \"..\", \"..\", \"binding\"), // in case of deeper nesting\n join(currentDir, \"binding\"), // same directory\n ];\n\n let loadedBinding: { Compiler: new () => CompilerBinding } | null = null;\n let lastError: unknown = null;\n\n for (const bindingPath of possiblePaths) {\n try {\n loadedBinding = require(bindingPath);\n break;\n } catch (e) {\n lastError = e;\n }\n }\n\n if (!loadedBinding) {\n throw (\n lastError ||\n new Error(\"Could not find binding in any expected location\")\n );\n }\n\n binding = loadedBinding;\n }\n\n compilerInstance = new binding.Compiler();\n return compilerInstance;\n } catch (e) {\n throw new Error(`Failed to load Angular Rust binding. Error: ${e}`);\n }\n}\n\n/**\n * Creates a Vite plugin for Angular Rust compiler\n * Compiles .ts files (except .d.ts) using the Rust compiler\n */\nexport function angularCompilerVitePlugin(options?: CompilerOptions): Plugin {\n const debug = options?.debug ?? false;\n let compiler: CompilerBinding;\n\n return {\n name: \"angular-rust-compiler\",\n enforce: \"pre\",\n\n transform(code: string, id: string) {\n // Lazy initialize compiler\n if (!compiler) {\n compiler = getCompiler(options);\n }\n\n // Skip node_modules - those are handled by linker, not compiler\n if (id.includes(\"node_modules\")) {\n return null;\n }\n\n // Only process TypeScript files, skip declaration files\n if (!id.endsWith(\".ts\") || id.endsWith(\".d.ts\")) {\n return null;\n }\n\n if (debug) {\n console.log(`[Angular Compiler] Compiling: ${id}`);\n }\n\n try {\n const result = compiler.compile(id, code);\n\n if (result.startsWith(\"/* Error\")) {\n console.error(`[Angular Compiler Error] ${id}:\\n${result}`);\n throw new Error(`Rust Compilation Failed for ${id}`);\n }\n\n if (debug) {\n console.log(`[Angular Compiler] Successfully compiled: ${id}`);\n }\n\n return { code: result, map: null };\n } catch (e) {\n console.error(`[Angular Compiler Failed] ${id}:`, e);\n throw e;\n }\n },\n\n handleHotUpdate({ file, server }: HmrContext) {\n // When HTML template changes, invalidate the corresponding TS file\n if (file.endsWith(\".html\")) {\n const tsFile = file.replace(/\\.html$/, \".ts\");\n\n if (debug) {\n console.log(`[HMR] HTML changed: ${file}`);\n console.log(`[HMR] Invalidating TS: ${tsFile}`);\n }\n\n const mod = server.moduleGraph.getModuleById(tsFile);\n if (mod) {\n server.moduleGraph.invalidateModule(mod);\n server.ws.send({ type: \"full-reload\", path: \"*\" });\n return [];\n } else {\n server.ws.send({ type: \"full-reload\", path: \"*\" });\n return [];\n }\n }\n },\n };\n}\n\nexport default angularCompilerVitePlugin;\n"],"mappings":"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","names":["require"]}
1
+ {"version":3,"sources":["../../src/compiler/vite.ts"],"sourcesContent":["/**\n * Angular Compiler Plugin for Vite\n *\n * This plugin compiles Angular TypeScript files using the Rust-based Angular compiler.\n * Use with the linker plugin for a complete Angular build solution.\n *\n * @example\n * ```js\n * import { angularCompilerVitePlugin } from 'angular-rust-plugins/compiler/vite';\n * import { angularLinkerVitePlugin } from 'angular-rust-plugins/linker/vite';\n * import { defineConfig } from 'vite';\n *\n * export default defineConfig({\n * plugins: [\n * angularLinkerVitePlugin(),\n * angularCompilerVitePlugin(),\n * ],\n * });\n * ```\n */\n\nimport type { Plugin, HmrContext } from \"vite\";\nimport { createRequire } from \"module\";\nimport { dirname, join } from \"path\";\nimport { fileURLToPath } from \"url\";\nimport { Compiler } from \"../binding\";\n\nlet compilerInstance: Compiler | null = null;\n\nexport interface CompilerOptions {\n /**\n * Enable debug logging\n * @default false\n */\n debug?: boolean;\n\n /**\n * Custom path to the Angular Rust binding package\n */\n bindingPath?: string;\n}\n\n// ============ Diagnostic Formatting ============\nconst RED = '\\x1b[31m';\nconst YELLOW = '\\x1b[33m';\nconst CYAN = '\\x1b[36m';\nconst BOLD = '\\x1b[1m';\nconst RESET = '\\x1b[0m';\n\nfunction formatDiagnostic(diag: any, sourceCode: string): string {\n const level = 'WARNING';\n const codeStr = `NG${diag.code}`;\n const file = diag.file || 'unknown';\n\n let line = 1;\n let col = 0;\n let lineStartPos = 0;\n\n if (diag.start !== undefined && diag.start !== null) {\n for (let i = 0; i < diag.start && i < sourceCode.length; i++) {\n if (sourceCode[i] === '\\n') {\n line++;\n col = 0;\n lineStartPos = i + 1;\n } else {\n col++;\n }\n }\n }\n\n let output = `\\n${BOLD}${YELLOW}▲ [${level}] ${RED}${codeStr}${RESET}${BOLD}: ${diag.message}${RESET} ${YELLOW}[plugin rust-ngc-plugin]${RESET}\\n`;\n\n const lineStr = line.toString();\n const colStr = (col + 1).toString();\n output += `\\n ${CYAN}${file}:${lineStr}:${colStr}:${RESET}\\n`;\n\n let lineEndPos = sourceCode.indexOf('\\n', lineStartPos);\n if (lineEndPos === -1) lineEndPos = sourceCode.length;\n const lineContent = sourceCode.substring(lineStartPos, lineEndPos);\n\n output += ` ${BOLD}${lineStr} │ ${RESET}${lineContent}\\n`;\n\n const gutterWidth = lineStr.length + 3;\n const gutterEmpty = ' '.repeat(gutterWidth);\n const length = diag.length || 1;\n const underline = '~'.repeat(length);\n\n output += ` ${gutterEmpty}${' '.repeat(col)}${RED}${underline}${RESET}`;\n\n return output;\n}\n\nfunction getCompiler(options?: CompilerOptions): Compiler {\n if (compilerInstance) {\n return compilerInstance;\n }\n\n try {\n let binding: { Compiler: new () => Compiler };\n\n if (options?.bindingPath) {\n const require = createRequire(import.meta.url);\n binding = require(options.bindingPath);\n } else {\n // Load from bundled binding directory\n // Use import.meta.url to get the actual location of this file\n const currentFileUrl = import.meta.url;\n const currentFilePath = fileURLToPath(currentFileUrl);\n const currentDir = dirname(currentFilePath);\n const require = createRequire(currentFileUrl);\n\n // Try multiple possible binding locations\n const possiblePaths = [\n join(currentDir, \"..\", \"binding\"), // dist/compiler/../binding\n join(currentDir, \"..\", \"..\", \"binding\"), // in case of deeper nesting\n join(currentDir, \"binding\"), // same directory\n ];\n\n let loadedBinding: { Compiler: new () => Compiler } | null = null;\n let lastError: unknown = null;\n\n for (const bindingPath of possiblePaths) {\n try {\n loadedBinding = require(bindingPath);\n break;\n } catch (e) {\n lastError = e;\n }\n }\n\n if (!loadedBinding) {\n throw (\n lastError ||\n new Error(\"Could not find binding in any expected location\")\n );\n }\n\n binding = loadedBinding;\n }\n\n compilerInstance = new binding.Compiler();\n return compilerInstance;\n } catch (e) {\n throw new Error(`Failed to load Angular Rust binding. Error: ${e}`);\n }\n}\n\n/**\n * Creates a Vite plugin for Angular Rust compiler\n * Compiles .ts files (except .d.ts) using the Rust compiler\n */\nexport function angularCompilerVitePlugin(options?: CompilerOptions): Plugin {\n const debug = options?.debug ?? false;\n let compiler: Compiler;\n\n return {\n name: \"angular-rust-compiler\",\n enforce: \"pre\",\n\n transform(code: string, id: string) {\n // Lazy initialize compiler\n if (!compiler) {\n compiler = getCompiler(options);\n }\n\n // Skip node_modules but check for Angular packages that need linking\n if (id.includes('node_modules')) {\n if (id.includes('@angular') && code.includes('ɵɵngDeclare')) {\n const cleanId = id.split('?')[0];\n if (cleanId.endsWith('.mjs') || cleanId.endsWith('.js')) {\n try {\n const result = compiler.linkFile(id, code);\n if (result.startsWith('/* Linker Error')) {\n if (debug) console.error(`[Linker Error] ${id}: ${result}`);\n return null;\n }\n return { code: result, map: null };\n } catch (e) {\n if (debug) console.error(`Linker failed for ${id}:`, e);\n return null;\n }\n }\n }\n return null;\n }\n\n // Only process TypeScript files, skip declaration files\n const cleanId = id.split('?')[0];\n if (!cleanId.endsWith('.ts') || cleanId.endsWith('.d.ts')) {\n return null;\n }\n\n if (debug) {\n console.log(`[Angular Compiler] Compiling: ${id}`);\n }\n\n try {\n const result = compiler.compile(id, code);\n\n // Handle structured result\n const { code: compiledCode, diagnostics } = result;\n\n if (compiledCode.startsWith('/* Error')) {\n console.error(`[Angular Compiler Error] ${id}:\\n${compiledCode}`);\n throw new Error(`Rust Compilation Failed for ${id}`);\n }\n\n if (diagnostics && diagnostics.length > 0) {\n diagnostics.forEach((diag: any) => {\n console.warn(formatDiagnostic(diag, code));\n });\n }\n\n if (debug) {\n console.log(`[Angular Compiler] Successfully compiled: ${id}`);\n }\n\n return { code: compiledCode, map: null };\n } catch (e) {\n console.error(`[Angular Compiler Failed] ${id}:`, e);\n throw e;\n }\n },\n\n handleHotUpdate({ file, server }: HmrContext) {\n // When HTML template changes, invalidate the corresponding TS file\n if (file.endsWith(\".html\")) {\n const tsFile = file.replace(/\\.html$/, \".ts\");\n\n if (debug) {\n console.log(`[HMR] HTML changed: ${file}`);\n console.log(`[HMR] Invalidating TS: ${tsFile}`);\n }\n\n const mod = server.moduleGraph.getModuleById(tsFile);\n if (mod) {\n server.moduleGraph.invalidateModule(mod);\n server.ws.send({ type: \"full-reload\", path: \"*\" });\n return [];\n } else {\n server.ws.send({ type: \"full-reload\", path: \"*\" });\n return [];\n }\n }\n },\n };\n}\n\nexport default angularCompilerVitePlugin;\n"],"mappings":"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","names":["require","cleanId"]}
package/compiler/vite.js CHANGED
@@ -3,6 +3,49 @@ import { createRequire } from "module";
3
3
  import { dirname, join } from "path";
4
4
  import { fileURLToPath } from "url";
5
5
  var compilerInstance = null;
6
+ var RED = "\x1B[31m";
7
+ var YELLOW = "\x1B[33m";
8
+ var CYAN = "\x1B[36m";
9
+ var BOLD = "\x1B[1m";
10
+ var RESET = "\x1B[0m";
11
+ function formatDiagnostic(diag, sourceCode) {
12
+ const level = "WARNING";
13
+ const codeStr = `NG${diag.code}`;
14
+ const file = diag.file || "unknown";
15
+ let line = 1;
16
+ let col = 0;
17
+ let lineStartPos = 0;
18
+ if (diag.start !== void 0 && diag.start !== null) {
19
+ for (let i = 0; i < diag.start && i < sourceCode.length; i++) {
20
+ if (sourceCode[i] === "\n") {
21
+ line++;
22
+ col = 0;
23
+ lineStartPos = i + 1;
24
+ } else {
25
+ col++;
26
+ }
27
+ }
28
+ }
29
+ let output = `
30
+ ${BOLD}${YELLOW}\u25B2 [${level}] ${RED}${codeStr}${RESET}${BOLD}: ${diag.message}${RESET} ${YELLOW}[plugin rust-ngc-plugin]${RESET}
31
+ `;
32
+ const lineStr = line.toString();
33
+ const colStr = (col + 1).toString();
34
+ output += `
35
+ ${CYAN}${file}:${lineStr}:${colStr}:${RESET}
36
+ `;
37
+ let lineEndPos = sourceCode.indexOf("\n", lineStartPos);
38
+ if (lineEndPos === -1) lineEndPos = sourceCode.length;
39
+ const lineContent = sourceCode.substring(lineStartPos, lineEndPos);
40
+ output += ` ${BOLD}${lineStr} \u2502 ${RESET}${lineContent}
41
+ `;
42
+ const gutterWidth = lineStr.length + 3;
43
+ const gutterEmpty = " ".repeat(gutterWidth);
44
+ const length = diag.length || 1;
45
+ const underline = "~".repeat(length);
46
+ output += ` ${gutterEmpty}${" ".repeat(col)}${RED}${underline}${RESET}`;
47
+ return output;
48
+ }
6
49
  function getCompiler(options) {
7
50
  if (compilerInstance) {
8
51
  return compilerInstance;
@@ -57,9 +100,26 @@ function angularCompilerVitePlugin(options) {
57
100
  compiler = getCompiler(options);
58
101
  }
59
102
  if (id.includes("node_modules")) {
103
+ if (id.includes("@angular") && code.includes("\u0275\u0275ngDeclare")) {
104
+ const cleanId2 = id.split("?")[0];
105
+ if (cleanId2.endsWith(".mjs") || cleanId2.endsWith(".js")) {
106
+ try {
107
+ const result = compiler.linkFile(id, code);
108
+ if (result.startsWith("/* Linker Error")) {
109
+ if (debug) console.error(`[Linker Error] ${id}: ${result}`);
110
+ return null;
111
+ }
112
+ return { code: result, map: null };
113
+ } catch (e) {
114
+ if (debug) console.error(`Linker failed for ${id}:`, e);
115
+ return null;
116
+ }
117
+ }
118
+ }
60
119
  return null;
61
120
  }
62
- if (!id.endsWith(".ts") || id.endsWith(".d.ts")) {
121
+ const cleanId = id.split("?")[0];
122
+ if (!cleanId.endsWith(".ts") || cleanId.endsWith(".d.ts")) {
63
123
  return null;
64
124
  }
65
125
  if (debug) {
@@ -67,15 +127,21 @@ function angularCompilerVitePlugin(options) {
67
127
  }
68
128
  try {
69
129
  const result = compiler.compile(id, code);
70
- if (result.startsWith("/* Error")) {
130
+ const { code: compiledCode, diagnostics } = result;
131
+ if (compiledCode.startsWith("/* Error")) {
71
132
  console.error(`[Angular Compiler Error] ${id}:
72
- ${result}`);
133
+ ${compiledCode}`);
73
134
  throw new Error(`Rust Compilation Failed for ${id}`);
74
135
  }
136
+ if (diagnostics && diagnostics.length > 0) {
137
+ diagnostics.forEach((diag) => {
138
+ console.warn(formatDiagnostic(diag, code));
139
+ });
140
+ }
75
141
  if (debug) {
76
142
  console.log(`[Angular Compiler] Successfully compiled: ${id}`);
77
143
  }
78
- return { code: result, map: null };
144
+ return { code: compiledCode, map: null };
79
145
  } catch (e) {
80
146
  console.error(`[Angular Compiler Failed] ${id}:`, e);
81
147
  throw e;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/compiler/vite.ts"],"sourcesContent":["/**\n * Angular Compiler Plugin for Vite\n *\n * This plugin compiles Angular TypeScript files using the Rust-based Angular compiler.\n * Use with the linker plugin for a complete Angular build solution.\n *\n * @example\n * ```js\n * import { angularCompilerVitePlugin } from 'angular-rust-plugins/compiler/vite';\n * import { angularLinkerVitePlugin } from 'angular-rust-plugins/linker/vite';\n * import { defineConfig } from 'vite';\n *\n * export default defineConfig({\n * plugins: [\n * angularLinkerVitePlugin(),\n * angularCompilerVitePlugin(),\n * ],\n * });\n * ```\n */\n\nimport type { Plugin, HmrContext } from \"vite\";\nimport { createRequire } from \"module\";\nimport { dirname, join } from \"path\";\nimport { fileURLToPath } from \"url\";\nimport type { CompilerBinding } from \"./types\";\n\nlet compilerInstance: CompilerBinding | null = null;\n\nexport interface CompilerOptions {\n /**\n * Enable debug logging\n * @default false\n */\n debug?: boolean;\n\n /**\n * Custom path to the Angular Rust binding package\n */\n bindingPath?: string;\n}\n\nfunction getCompiler(options?: CompilerOptions): CompilerBinding {\n if (compilerInstance) {\n return compilerInstance;\n }\n\n try {\n let binding: { Compiler: new () => CompilerBinding };\n\n if (options?.bindingPath) {\n const require = createRequire(import.meta.url);\n binding = require(options.bindingPath);\n } else {\n // Load from bundled binding directory\n // Use import.meta.url to get the actual location of this file\n const currentFileUrl = import.meta.url;\n const currentFilePath = fileURLToPath(currentFileUrl);\n const currentDir = dirname(currentFilePath);\n const require = createRequire(currentFileUrl);\n\n // Try multiple possible binding locations\n const possiblePaths = [\n join(currentDir, \"..\", \"binding\"), // dist/compiler/../binding\n join(currentDir, \"..\", \"..\", \"binding\"), // in case of deeper nesting\n join(currentDir, \"binding\"), // same directory\n ];\n\n let loadedBinding: { Compiler: new () => CompilerBinding } | null = null;\n let lastError: unknown = null;\n\n for (const bindingPath of possiblePaths) {\n try {\n loadedBinding = require(bindingPath);\n break;\n } catch (e) {\n lastError = e;\n }\n }\n\n if (!loadedBinding) {\n throw (\n lastError ||\n new Error(\"Could not find binding in any expected location\")\n );\n }\n\n binding = loadedBinding;\n }\n\n compilerInstance = new binding.Compiler();\n return compilerInstance;\n } catch (e) {\n throw new Error(`Failed to load Angular Rust binding. Error: ${e}`);\n }\n}\n\n/**\n * Creates a Vite plugin for Angular Rust compiler\n * Compiles .ts files (except .d.ts) using the Rust compiler\n */\nexport function angularCompilerVitePlugin(options?: CompilerOptions): Plugin {\n const debug = options?.debug ?? false;\n let compiler: CompilerBinding;\n\n return {\n name: \"angular-rust-compiler\",\n enforce: \"pre\",\n\n transform(code: string, id: string) {\n // Lazy initialize compiler\n if (!compiler) {\n compiler = getCompiler(options);\n }\n\n // Skip node_modules - those are handled by linker, not compiler\n if (id.includes(\"node_modules\")) {\n return null;\n }\n\n // Only process TypeScript files, skip declaration files\n if (!id.endsWith(\".ts\") || id.endsWith(\".d.ts\")) {\n return null;\n }\n\n if (debug) {\n console.log(`[Angular Compiler] Compiling: ${id}`);\n }\n\n try {\n const result = compiler.compile(id, code);\n\n if (result.startsWith(\"/* Error\")) {\n console.error(`[Angular Compiler Error] ${id}:\\n${result}`);\n throw new Error(`Rust Compilation Failed for ${id}`);\n }\n\n if (debug) {\n console.log(`[Angular Compiler] Successfully compiled: ${id}`);\n }\n\n return { code: result, map: null };\n } catch (e) {\n console.error(`[Angular Compiler Failed] ${id}:`, e);\n throw e;\n }\n },\n\n handleHotUpdate({ file, server }: HmrContext) {\n // When HTML template changes, invalidate the corresponding TS file\n if (file.endsWith(\".html\")) {\n const tsFile = file.replace(/\\.html$/, \".ts\");\n\n if (debug) {\n console.log(`[HMR] HTML changed: ${file}`);\n console.log(`[HMR] Invalidating TS: ${tsFile}`);\n }\n\n const mod = server.moduleGraph.getModuleById(tsFile);\n if (mod) {\n server.moduleGraph.invalidateModule(mod);\n server.ws.send({ type: \"full-reload\", path: \"*\" });\n return [];\n } else {\n server.ws.send({ type: \"full-reload\", path: \"*\" });\n return [];\n }\n }\n },\n };\n}\n\nexport default angularCompilerVitePlugin;\n"],"mappings":"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","names":["require"]}
1
+ {"version":3,"sources":["../../src/compiler/vite.ts"],"sourcesContent":["/**\n * Angular Compiler Plugin for Vite\n *\n * This plugin compiles Angular TypeScript files using the Rust-based Angular compiler.\n * Use with the linker plugin for a complete Angular build solution.\n *\n * @example\n * ```js\n * import { angularCompilerVitePlugin } from 'angular-rust-plugins/compiler/vite';\n * import { angularLinkerVitePlugin } from 'angular-rust-plugins/linker/vite';\n * import { defineConfig } from 'vite';\n *\n * export default defineConfig({\n * plugins: [\n * angularLinkerVitePlugin(),\n * angularCompilerVitePlugin(),\n * ],\n * });\n * ```\n */\n\nimport type { Plugin, HmrContext } from \"vite\";\nimport { createRequire } from \"module\";\nimport { dirname, join } from \"path\";\nimport { fileURLToPath } from \"url\";\nimport { Compiler } from \"../binding\";\n\nlet compilerInstance: Compiler | null = null;\n\nexport interface CompilerOptions {\n /**\n * Enable debug logging\n * @default false\n */\n debug?: boolean;\n\n /**\n * Custom path to the Angular Rust binding package\n */\n bindingPath?: string;\n}\n\n// ============ Diagnostic Formatting ============\nconst RED = '\\x1b[31m';\nconst YELLOW = '\\x1b[33m';\nconst CYAN = '\\x1b[36m';\nconst BOLD = '\\x1b[1m';\nconst RESET = '\\x1b[0m';\n\nfunction formatDiagnostic(diag: any, sourceCode: string): string {\n const level = 'WARNING';\n const codeStr = `NG${diag.code}`;\n const file = diag.file || 'unknown';\n\n let line = 1;\n let col = 0;\n let lineStartPos = 0;\n\n if (diag.start !== undefined && diag.start !== null) {\n for (let i = 0; i < diag.start && i < sourceCode.length; i++) {\n if (sourceCode[i] === '\\n') {\n line++;\n col = 0;\n lineStartPos = i + 1;\n } else {\n col++;\n }\n }\n }\n\n let output = `\\n${BOLD}${YELLOW}▲ [${level}] ${RED}${codeStr}${RESET}${BOLD}: ${diag.message}${RESET} ${YELLOW}[plugin rust-ngc-plugin]${RESET}\\n`;\n\n const lineStr = line.toString();\n const colStr = (col + 1).toString();\n output += `\\n ${CYAN}${file}:${lineStr}:${colStr}:${RESET}\\n`;\n\n let lineEndPos = sourceCode.indexOf('\\n', lineStartPos);\n if (lineEndPos === -1) lineEndPos = sourceCode.length;\n const lineContent = sourceCode.substring(lineStartPos, lineEndPos);\n\n output += ` ${BOLD}${lineStr} │ ${RESET}${lineContent}\\n`;\n\n const gutterWidth = lineStr.length + 3;\n const gutterEmpty = ' '.repeat(gutterWidth);\n const length = diag.length || 1;\n const underline = '~'.repeat(length);\n\n output += ` ${gutterEmpty}${' '.repeat(col)}${RED}${underline}${RESET}`;\n\n return output;\n}\n\nfunction getCompiler(options?: CompilerOptions): Compiler {\n if (compilerInstance) {\n return compilerInstance;\n }\n\n try {\n let binding: { Compiler: new () => Compiler };\n\n if (options?.bindingPath) {\n const require = createRequire(import.meta.url);\n binding = require(options.bindingPath);\n } else {\n // Load from bundled binding directory\n // Use import.meta.url to get the actual location of this file\n const currentFileUrl = import.meta.url;\n const currentFilePath = fileURLToPath(currentFileUrl);\n const currentDir = dirname(currentFilePath);\n const require = createRequire(currentFileUrl);\n\n // Try multiple possible binding locations\n const possiblePaths = [\n join(currentDir, \"..\", \"binding\"), // dist/compiler/../binding\n join(currentDir, \"..\", \"..\", \"binding\"), // in case of deeper nesting\n join(currentDir, \"binding\"), // same directory\n ];\n\n let loadedBinding: { Compiler: new () => Compiler } | null = null;\n let lastError: unknown = null;\n\n for (const bindingPath of possiblePaths) {\n try {\n loadedBinding = require(bindingPath);\n break;\n } catch (e) {\n lastError = e;\n }\n }\n\n if (!loadedBinding) {\n throw (\n lastError ||\n new Error(\"Could not find binding in any expected location\")\n );\n }\n\n binding = loadedBinding;\n }\n\n compilerInstance = new binding.Compiler();\n return compilerInstance;\n } catch (e) {\n throw new Error(`Failed to load Angular Rust binding. Error: ${e}`);\n }\n}\n\n/**\n * Creates a Vite plugin for Angular Rust compiler\n * Compiles .ts files (except .d.ts) using the Rust compiler\n */\nexport function angularCompilerVitePlugin(options?: CompilerOptions): Plugin {\n const debug = options?.debug ?? false;\n let compiler: Compiler;\n\n return {\n name: \"angular-rust-compiler\",\n enforce: \"pre\",\n\n transform(code: string, id: string) {\n // Lazy initialize compiler\n if (!compiler) {\n compiler = getCompiler(options);\n }\n\n // Skip node_modules but check for Angular packages that need linking\n if (id.includes('node_modules')) {\n if (id.includes('@angular') && code.includes('ɵɵngDeclare')) {\n const cleanId = id.split('?')[0];\n if (cleanId.endsWith('.mjs') || cleanId.endsWith('.js')) {\n try {\n const result = compiler.linkFile(id, code);\n if (result.startsWith('/* Linker Error')) {\n if (debug) console.error(`[Linker Error] ${id}: ${result}`);\n return null;\n }\n return { code: result, map: null };\n } catch (e) {\n if (debug) console.error(`Linker failed for ${id}:`, e);\n return null;\n }\n }\n }\n return null;\n }\n\n // Only process TypeScript files, skip declaration files\n const cleanId = id.split('?')[0];\n if (!cleanId.endsWith('.ts') || cleanId.endsWith('.d.ts')) {\n return null;\n }\n\n if (debug) {\n console.log(`[Angular Compiler] Compiling: ${id}`);\n }\n\n try {\n const result = compiler.compile(id, code);\n\n // Handle structured result\n const { code: compiledCode, diagnostics } = result;\n\n if (compiledCode.startsWith('/* Error')) {\n console.error(`[Angular Compiler Error] ${id}:\\n${compiledCode}`);\n throw new Error(`Rust Compilation Failed for ${id}`);\n }\n\n if (diagnostics && diagnostics.length > 0) {\n diagnostics.forEach((diag: any) => {\n console.warn(formatDiagnostic(diag, code));\n });\n }\n\n if (debug) {\n console.log(`[Angular Compiler] Successfully compiled: ${id}`);\n }\n\n return { code: compiledCode, map: null };\n } catch (e) {\n console.error(`[Angular Compiler Failed] ${id}:`, e);\n throw e;\n }\n },\n\n handleHotUpdate({ file, server }: HmrContext) {\n // When HTML template changes, invalidate the corresponding TS file\n if (file.endsWith(\".html\")) {\n const tsFile = file.replace(/\\.html$/, \".ts\");\n\n if (debug) {\n console.log(`[HMR] HTML changed: ${file}`);\n console.log(`[HMR] Invalidating TS: ${tsFile}`);\n }\n\n const mod = server.moduleGraph.getModuleById(tsFile);\n if (mod) {\n server.moduleGraph.invalidateModule(mod);\n server.ws.send({ type: \"full-reload\", path: \"*\" });\n return [];\n } else {\n server.ws.send({ type: \"full-reload\", path: \"*\" });\n return [];\n }\n }\n },\n };\n}\n\nexport default angularCompilerVitePlugin;\n"],"mappings":"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","names":["require","cleanId"]}
package/index.cjs CHANGED
@@ -209,12 +209,14 @@ function angularLinkerRolldownPlugin(options) {
209
209
  if (!compiler) {
210
210
  compiler = getCompiler2(options);
211
211
  }
212
- const isInNodeModules = id.includes("node_modules");
212
+ const isAngularPackage2 = id.includes("@angular") || id.includes("/@angular/");
213
+ const isNodeModules = id.includes("node_modules");
213
214
  const cleanId = cleanModuleId(id);
214
- if (!isAngularPackage(id) || !isInNodeModules || !isJsFile(id)) {
215
+ const isJsFile2 = cleanId.endsWith(".mjs") || cleanId.endsWith(".js");
216
+ if (!isAngularPackage2 || !isNodeModules || !isJsFile2) {
215
217
  return null;
216
218
  }
217
- if (!needsLinking(code)) {
219
+ if (!code.includes("\u0275\u0275ngDeclare")) {
218
220
  return null;
219
221
  }
220
222
  if (debug) {
@@ -223,7 +225,7 @@ function angularLinkerRolldownPlugin(options) {
223
225
  try {
224
226
  const result = compiler.linkFile(cleanId, code);
225
227
  if (result.startsWith("/* Linker Error")) {
226
- console.error(`[Angular Linker Error] ${id}:
228
+ console.error(`[Rolldown Linker Error] ${id}:
227
229
  ${result}`);
228
230
  return null;
229
231
  }
@@ -232,7 +234,7 @@ ${result}`);
232
234
  }
233
235
  return { code: result, map: null };
234
236
  } catch (e) {
235
- console.error(`[Angular Linker Failed] ${id}:`, e);
237
+ console.error(`[Rolldown Linker Failed] ${id}:`, e);
236
238
  return null;
237
239
  }
238
240
  }
@@ -314,19 +316,16 @@ function angularLinkerVitePlugin(options) {
314
316
  if (!compiler) {
315
317
  compiler = getCompiler3(options);
316
318
  }
317
- if (!id.includes("node_modules")) {
318
- return null;
319
- }
320
- if (!isAngularPackage(id)) {
321
- return null;
322
- }
323
- if (!isJsFile(id)) {
319
+ const isAngularPackage2 = id.includes("@angular") || id.includes("/@angular/");
320
+ const isNodeModules = id.includes("node_modules");
321
+ const cleanId = cleanModuleId(id);
322
+ const isJsFile2 = cleanId.endsWith(".mjs") || cleanId.endsWith(".js");
323
+ if (!isAngularPackage2 || !isNodeModules || !isJsFile2) {
324
324
  return null;
325
325
  }
326
- if (!needsLinking(code)) {
326
+ if (!code.includes("\u0275\u0275ngDeclare")) {
327
327
  return null;
328
328
  }
329
- const cleanId = cleanModuleId(id);
330
329
  if (debug) {
331
330
  console.log(`[Angular Linker] Linking: ${cleanId}`);
332
331
  }
@@ -364,6 +363,49 @@ var import_path4 = require("path");
364
363
  var import_url4 = require("url");
365
364
  var import_meta4 = {};
366
365
  var compilerInstance4 = null;
366
+ var RED = "\x1B[31m";
367
+ var YELLOW = "\x1B[33m";
368
+ var CYAN = "\x1B[36m";
369
+ var BOLD = "\x1B[1m";
370
+ var RESET = "\x1B[0m";
371
+ function formatDiagnostic(diag, sourceCode) {
372
+ const level = "WARNING";
373
+ const codeStr = `NG${diag.code}`;
374
+ const file = diag.file || "unknown";
375
+ let line = 1;
376
+ let col = 0;
377
+ let lineStartPos = 0;
378
+ if (diag.start !== void 0 && diag.start !== null) {
379
+ for (let i = 0; i < diag.start && i < sourceCode.length; i++) {
380
+ if (sourceCode[i] === "\n") {
381
+ line++;
382
+ col = 0;
383
+ lineStartPos = i + 1;
384
+ } else {
385
+ col++;
386
+ }
387
+ }
388
+ }
389
+ let output = `
390
+ ${BOLD}${YELLOW}\u25B2 [${level}] ${RED}${codeStr}${RESET}${BOLD}: ${diag.message}${RESET} ${YELLOW}[plugin rust-ngc-plugin]${RESET}
391
+ `;
392
+ const lineStr = line.toString();
393
+ const colStr = (col + 1).toString();
394
+ output += `
395
+ ${CYAN}${file}:${lineStr}:${colStr}:${RESET}
396
+ `;
397
+ let lineEndPos = sourceCode.indexOf("\n", lineStartPos);
398
+ if (lineEndPos === -1) lineEndPos = sourceCode.length;
399
+ const lineContent = sourceCode.substring(lineStartPos, lineEndPos);
400
+ output += ` ${BOLD}${lineStr} \u2502 ${RESET}${lineContent}
401
+ `;
402
+ const gutterWidth = lineStr.length + 3;
403
+ const gutterEmpty = " ".repeat(gutterWidth);
404
+ const length = diag.length || 1;
405
+ const underline = "~".repeat(length);
406
+ output += ` ${gutterEmpty}${" ".repeat(col)}${RED}${underline}${RESET}`;
407
+ return output;
408
+ }
367
409
  function getCompiler4(options) {
368
410
  if (compilerInstance4) {
369
411
  return compilerInstance4;
@@ -418,9 +460,26 @@ function angularCompilerVitePlugin(options) {
418
460
  compiler = getCompiler4(options);
419
461
  }
420
462
  if (id.includes("node_modules")) {
463
+ if (id.includes("@angular") && code.includes("\u0275\u0275ngDeclare")) {
464
+ const cleanId2 = id.split("?")[0];
465
+ if (cleanId2.endsWith(".mjs") || cleanId2.endsWith(".js")) {
466
+ try {
467
+ const result = compiler.linkFile(id, code);
468
+ if (result.startsWith("/* Linker Error")) {
469
+ if (debug) console.error(`[Linker Error] ${id}: ${result}`);
470
+ return null;
471
+ }
472
+ return { code: result, map: null };
473
+ } catch (e) {
474
+ if (debug) console.error(`Linker failed for ${id}:`, e);
475
+ return null;
476
+ }
477
+ }
478
+ }
421
479
  return null;
422
480
  }
423
- if (!id.endsWith(".ts") || id.endsWith(".d.ts")) {
481
+ const cleanId = id.split("?")[0];
482
+ if (!cleanId.endsWith(".ts") || cleanId.endsWith(".d.ts")) {
424
483
  return null;
425
484
  }
426
485
  if (debug) {
@@ -428,15 +487,21 @@ function angularCompilerVitePlugin(options) {
428
487
  }
429
488
  try {
430
489
  const result = compiler.compile(id, code);
431
- if (result.startsWith("/* Error")) {
490
+ const { code: compiledCode, diagnostics } = result;
491
+ if (compiledCode.startsWith("/* Error")) {
432
492
  console.error(`[Angular Compiler Error] ${id}:
433
- ${result}`);
493
+ ${compiledCode}`);
434
494
  throw new Error(`Rust Compilation Failed for ${id}`);
435
495
  }
496
+ if (diagnostics && diagnostics.length > 0) {
497
+ diagnostics.forEach((diag) => {
498
+ console.warn(formatDiagnostic(diag, code));
499
+ });
500
+ }
436
501
  if (debug) {
437
502
  console.log(`[Angular Compiler] Successfully compiled: ${id}`);
438
503
  }
439
- return { code: result, map: null };
504
+ return { code: compiledCode, map: null };
440
505
  } catch (e) {
441
506
  console.error(`[Angular Compiler Failed] ${id}:`, e);
442
507
  throw e;