@analogjs/vite-plugin-angular 3.0.0-alpha.57 → 3.0.0-alpha.59

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,5 @@
1
1
  import "./constants.js";
2
+ import * as path$1 from "node:path";
2
3
  import * as ts from "typescript";
3
4
  //#region packages/vite-plugin-angular/src/lib/compiler/utils.ts
4
5
  /** Recursively find all class declarations in a source file, including nested scopes. */
@@ -29,7 +30,47 @@ function unwrapForwardRefOxc(node) {
29
30
  }
30
31
  return node;
31
32
  }
33
+ /**
34
+ * Resolve the module specifier to use for a synthetic import of a registry
35
+ * declaration referenced from `currentFileName`.
36
+ *
37
+ * Order of preference:
38
+ * 1. `entry.sourcePackage` — external packages scanned from `.d.ts` resolve
39
+ * via their package name (proper barrel exports).
40
+ * 2. A relative path derived from `currentFileName` to `entry.fileName` — for
41
+ * local workspace classes scanned from real source files. This is what
42
+ * NgModule/tuple export expansion must use: the class lives in its own
43
+ * file, not the module/barrel file that re-exports it, so importing from
44
+ * the module specifier fails with
45
+ * `"X" is not exported by ".../the.module.ts"`.
46
+ * 3. `fallbackSpecifier` — the import path of the module/tuple itself, used
47
+ * for `.d.ts` entries (whose file path is not a usable import target) and
48
+ * when the registry has no file location for the class.
49
+ *
50
+ * Returns `undefined` when the class is declared in `currentFileName` itself
51
+ * (already in scope — no synthetic import needed).
52
+ */
53
+ function resolveSyntheticImportSpecifier(currentFileName, entry, fallbackSpecifier) {
54
+ if (entry.sourcePackage) return entry.sourcePackage;
55
+ if (entry.fileName && !entry.fileName.endsWith(".d.ts")) {
56
+ if (entry.fileName === currentFileName) return void 0;
57
+ return deriveRelativeImportPath(currentFileName, entry.fileName);
58
+ }
59
+ return fallbackSpecifier;
60
+ }
61
+ /**
62
+ * Derive a relative module specifier from `fromFile` to `toFile`, suitable for
63
+ * a synthetic `import { … } from '…'` statement: strips the file extension,
64
+ * normalizes to POSIX separators, and ensures an explicit `./` prefix.
65
+ */
66
+ function deriveRelativeImportPath(fromFile, toFile) {
67
+ let rel = path$1.relative(path$1.dirname(fromFile), toFile);
68
+ rel = rel.replace(/\.[cm]?[jt]sx?$/, "");
69
+ rel = rel.split(path$1.sep).join("/");
70
+ if (!rel.startsWith(".")) rel = "./" + rel;
71
+ return rel;
72
+ }
32
73
  //#endregion
33
- export { findAllClasses, unwrapForwardRefOxc };
74
+ export { findAllClasses, resolveSyntheticImportSpecifier, unwrapForwardRefOxc };
34
75
 
35
76
  //# sourceMappingURL=utils.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"utils.js","names":[],"sources":["../../../../src/lib/compiler/utils.ts"],"sourcesContent":["import * as ts from 'typescript';\n\n/** Collect type-only imported names: `import type { X }` and `import { type X }`. */\nexport function collectTypeOnlyImports(sf: ts.SourceFile): Set<string> {\n const result = new Set<string>();\n for (const stmt of sf.statements) {\n if (!ts.isImportDeclaration(stmt) || !stmt.importClause) continue;\n const clause = stmt.importClause;\n if (clause.isTypeOnly) {\n if (clause.namedBindings && ts.isNamedImports(clause.namedBindings)) {\n for (const el of clause.namedBindings.elements)\n result.add(el.name.text);\n }\n if (clause.name) result.add(clause.name.text);\n } else if (\n clause.namedBindings &&\n ts.isNamedImports(clause.namedBindings)\n ) {\n for (const el of clause.namedBindings.elements) {\n if (el.isTypeOnly) result.add(el.name.text);\n }\n }\n }\n return result;\n}\n\n/** Recursively find all class declarations in a source file, including nested scopes. */\nexport function findAllClasses(sf: ts.SourceFile): ts.ClassDeclaration[] {\n const result: ts.ClassDeclaration[] = [];\n function walk(node: ts.Node) {\n if (ts.isClassDeclaration(node)) result.push(node);\n ts.forEachChild(node, walk);\n }\n walk(sf);\n return result;\n}\n\n/** Unwrap forwardRef(() => X) to X. Returns the original node if not a forwardRef call. */\nexport function unwrapForwardRef(node: ts.Expression): ts.Expression {\n if (\n ts.isCallExpression(node) &&\n ts.isIdentifier(node.expression) &&\n node.expression.text === 'forwardRef'\n ) {\n const arg = node.arguments[0];\n if (arg && ts.isArrowFunction(arg)) {\n if (ts.isBlock(arg.body)) {\n const stmt = arg.body.statements[0];\n if (stmt && ts.isReturnStatement(stmt) && stmt.expression)\n return stmt.expression;\n } else {\n return arg.body;\n }\n }\n if (\n arg &&\n ts.isFunctionExpression(arg) &&\n arg.body.statements.length === 1\n ) {\n const stmt = arg.body.statements[0];\n if (ts.isReturnStatement(stmt) && stmt.expression) return stmt.expression;\n }\n }\n return node;\n}\n\n/** Unwrap forwardRef(() => X) to X for OXC AST nodes. Returns the original node if not a forwardRef call. */\nexport function unwrapForwardRefOxc(node: any): any {\n if (\n node?.type === 'CallExpression' &&\n node.callee?.type === 'Identifier' &&\n node.callee.name === 'forwardRef'\n ) {\n const arg = node.arguments?.[0];\n if (arg?.type === 'ArrowFunctionExpression') {\n if (\n arg.body?.type === 'FunctionBody' ||\n arg.body?.type === 'BlockStatement'\n ) {\n const stmts = arg.body.statements || arg.body.body || [];\n const stmt = stmts[0];\n if (stmt?.type === 'ReturnStatement' && stmt.argument)\n return stmt.argument;\n } else {\n // Expression body: forwardRef(() => X)\n return arg.body;\n }\n }\n if (arg?.type === 'FunctionExpression') {\n const stmts = arg.body?.statements || arg.body?.body || [];\n if (stmts.length === 1) {\n const stmt = stmts[0];\n if (stmt?.type === 'ReturnStatement' && stmt.argument)\n return stmt.argument;\n }\n }\n }\n return node;\n}\n\nexport { ANGULAR_DECORATORS } from './constants.js';\n"],"mappings":";;;;AA2BA,SAAgB,eAAe,IAA0C;CACvE,MAAM,SAAgC,EAAE;CACxC,SAAS,KAAK,MAAe;AAC3B,MAAI,GAAG,mBAAmB,KAAK,CAAE,QAAO,KAAK,KAAK;AAClD,KAAG,aAAa,MAAM,KAAK;;AAE7B,MAAK,GAAG;AACR,QAAO;;;AAiCT,SAAgB,oBAAoB,MAAgB;AAClD,KACE,MAAM,SAAS,oBACf,KAAK,QAAQ,SAAS,gBACtB,KAAK,OAAO,SAAS,cACrB;EACA,MAAM,MAAM,KAAK,YAAY;AAC7B,MAAI,KAAK,SAAS,0BAChB,KACE,IAAI,MAAM,SAAS,kBACnB,IAAI,MAAM,SAAS,kBACnB;GAEA,MAAM,QADQ,IAAI,KAAK,cAAc,IAAI,KAAK,QAAQ,EAAE,EACrC;AACnB,OAAI,MAAM,SAAS,qBAAqB,KAAK,SAC3C,QAAO,KAAK;QAGd,QAAO,IAAI;AAGf,MAAI,KAAK,SAAS,sBAAsB;GACtC,MAAM,QAAQ,IAAI,MAAM,cAAc,IAAI,MAAM,QAAQ,EAAE;AAC1D,OAAI,MAAM,WAAW,GAAG;IACtB,MAAM,OAAO,MAAM;AACnB,QAAI,MAAM,SAAS,qBAAqB,KAAK,SAC3C,QAAO,KAAK;;;;AAIpB,QAAO"}
1
+ {"version":3,"file":"utils.js","names":[],"sources":["../../../../src/lib/compiler/utils.ts"],"sourcesContent":["import * as ts from 'typescript';\nimport * as path from 'node:path';\n\n/** Collect type-only imported names: `import type { X }` and `import { type X }`. */\nexport function collectTypeOnlyImports(sf: ts.SourceFile): Set<string> {\n const result = new Set<string>();\n for (const stmt of sf.statements) {\n if (!ts.isImportDeclaration(stmt) || !stmt.importClause) continue;\n const clause = stmt.importClause;\n if (clause.isTypeOnly) {\n if (clause.namedBindings && ts.isNamedImports(clause.namedBindings)) {\n for (const el of clause.namedBindings.elements)\n result.add(el.name.text);\n }\n if (clause.name) result.add(clause.name.text);\n } else if (\n clause.namedBindings &&\n ts.isNamedImports(clause.namedBindings)\n ) {\n for (const el of clause.namedBindings.elements) {\n if (el.isTypeOnly) result.add(el.name.text);\n }\n }\n }\n return result;\n}\n\n/** Recursively find all class declarations in a source file, including nested scopes. */\nexport function findAllClasses(sf: ts.SourceFile): ts.ClassDeclaration[] {\n const result: ts.ClassDeclaration[] = [];\n function walk(node: ts.Node) {\n if (ts.isClassDeclaration(node)) result.push(node);\n ts.forEachChild(node, walk);\n }\n walk(sf);\n return result;\n}\n\n/** Unwrap forwardRef(() => X) to X. Returns the original node if not a forwardRef call. */\nexport function unwrapForwardRef(node: ts.Expression): ts.Expression {\n if (\n ts.isCallExpression(node) &&\n ts.isIdentifier(node.expression) &&\n node.expression.text === 'forwardRef'\n ) {\n const arg = node.arguments[0];\n if (arg && ts.isArrowFunction(arg)) {\n if (ts.isBlock(arg.body)) {\n const stmt = arg.body.statements[0];\n if (stmt && ts.isReturnStatement(stmt) && stmt.expression)\n return stmt.expression;\n } else {\n return arg.body;\n }\n }\n if (\n arg &&\n ts.isFunctionExpression(arg) &&\n arg.body.statements.length === 1\n ) {\n const stmt = arg.body.statements[0];\n if (ts.isReturnStatement(stmt) && stmt.expression) return stmt.expression;\n }\n }\n return node;\n}\n\n/** Unwrap forwardRef(() => X) to X for OXC AST nodes. Returns the original node if not a forwardRef call. */\nexport function unwrapForwardRefOxc(node: any): any {\n if (\n node?.type === 'CallExpression' &&\n node.callee?.type === 'Identifier' &&\n node.callee.name === 'forwardRef'\n ) {\n const arg = node.arguments?.[0];\n if (arg?.type === 'ArrowFunctionExpression') {\n if (\n arg.body?.type === 'FunctionBody' ||\n arg.body?.type === 'BlockStatement'\n ) {\n const stmts = arg.body.statements || arg.body.body || [];\n const stmt = stmts[0];\n if (stmt?.type === 'ReturnStatement' && stmt.argument)\n return stmt.argument;\n } else {\n // Expression body: forwardRef(() => X)\n return arg.body;\n }\n }\n if (arg?.type === 'FunctionExpression') {\n const stmts = arg.body?.statements || arg.body?.body || [];\n if (stmts.length === 1) {\n const stmt = stmts[0];\n if (stmt?.type === 'ReturnStatement' && stmt.argument)\n return stmt.argument;\n }\n }\n }\n return node;\n}\n\n/**\n * Resolve the module specifier to use for a synthetic import of a registry\n * declaration referenced from `currentFileName`.\n *\n * Order of preference:\n * 1. `entry.sourcePackage` — external packages scanned from `.d.ts` resolve\n * via their package name (proper barrel exports).\n * 2. A relative path derived from `currentFileName` to `entry.fileName` — for\n * local workspace classes scanned from real source files. This is what\n * NgModule/tuple export expansion must use: the class lives in its own\n * file, not the module/barrel file that re-exports it, so importing from\n * the module specifier fails with\n * `\"X\" is not exported by \".../the.module.ts\"`.\n * 3. `fallbackSpecifier` — the import path of the module/tuple itself, used\n * for `.d.ts` entries (whose file path is not a usable import target) and\n * when the registry has no file location for the class.\n *\n * Returns `undefined` when the class is declared in `currentFileName` itself\n * (already in scope — no synthetic import needed).\n */\nexport function resolveSyntheticImportSpecifier(\n currentFileName: string,\n entry: { sourcePackage?: string; fileName?: string },\n fallbackSpecifier: string | undefined,\n): string | undefined {\n if (entry.sourcePackage) return entry.sourcePackage;\n // `.d.ts` entries come from scanning external package type declarations;\n // their file path is not a usable relative import target, so defer to the\n // module/tuple specifier the consumer already imports from.\n if (entry.fileName && !entry.fileName.endsWith('.d.ts')) {\n if (entry.fileName === currentFileName) return undefined;\n return deriveRelativeImportPath(currentFileName, entry.fileName);\n }\n return fallbackSpecifier;\n}\n\n/**\n * Derive a relative module specifier from `fromFile` to `toFile`, suitable for\n * a synthetic `import { … } from '…'` statement: strips the file extension,\n * normalizes to POSIX separators, and ensures an explicit `./` prefix.\n */\nexport function deriveRelativeImportPath(\n fromFile: string,\n toFile: string,\n): string {\n let rel = path.relative(path.dirname(fromFile), toFile);\n rel = rel.replace(/\\.[cm]?[jt]sx?$/, '');\n rel = rel.split(path.sep).join('/');\n if (!rel.startsWith('.')) rel = './' + rel;\n return rel;\n}\n\nexport { ANGULAR_DECORATORS } from './constants.js';\n"],"mappings":";;;;;AA4BA,SAAgB,eAAe,IAA0C;CACvE,MAAM,SAAgC,EAAE;CACxC,SAAS,KAAK,MAAe;AAC3B,MAAI,GAAG,mBAAmB,KAAK,CAAE,QAAO,KAAK,KAAK;AAClD,KAAG,aAAa,MAAM,KAAK;;AAE7B,MAAK,GAAG;AACR,QAAO;;;AAiCT,SAAgB,oBAAoB,MAAgB;AAClD,KACE,MAAM,SAAS,oBACf,KAAK,QAAQ,SAAS,gBACtB,KAAK,OAAO,SAAS,cACrB;EACA,MAAM,MAAM,KAAK,YAAY;AAC7B,MAAI,KAAK,SAAS,0BAChB,KACE,IAAI,MAAM,SAAS,kBACnB,IAAI,MAAM,SAAS,kBACnB;GAEA,MAAM,QADQ,IAAI,KAAK,cAAc,IAAI,KAAK,QAAQ,EAAE,EACrC;AACnB,OAAI,MAAM,SAAS,qBAAqB,KAAK,SAC3C,QAAO,KAAK;QAGd,QAAO,IAAI;AAGf,MAAI,KAAK,SAAS,sBAAsB;GACtC,MAAM,QAAQ,IAAI,MAAM,cAAc,IAAI,MAAM,QAAQ,EAAE;AAC1D,OAAI,MAAM,WAAW,GAAG;IACtB,MAAM,OAAO,MAAM;AACnB,QAAI,MAAM,SAAS,qBAAqB,KAAK,SAC3C,QAAO,KAAK;;;;AAIpB,QAAO;;;;;;;;;;;;;;;;;;;;;;AAuBT,SAAgB,gCACd,iBACA,OACA,mBACoB;AACpB,KAAI,MAAM,cAAe,QAAO,MAAM;AAItC,KAAI,MAAM,YAAY,CAAC,MAAM,SAAS,SAAS,QAAQ,EAAE;AACvD,MAAI,MAAM,aAAa,gBAAiB,QAAO,KAAA;AAC/C,SAAO,yBAAyB,iBAAiB,MAAM,SAAS;;AAElE,QAAO;;;;;;;AAQT,SAAgB,yBACd,UACA,QACQ;CACR,IAAI,MAAM,OAAK,SAAS,OAAK,QAAQ,SAAS,EAAE,OAAO;AACvD,OAAM,IAAI,QAAQ,mBAAmB,GAAG;AACxC,OAAM,IAAI,MAAM,OAAK,IAAI,CAAC,KAAK,IAAI;AACnC,KAAI,CAAC,IAAI,WAAW,IAAI,CAAE,OAAM,OAAO;AACvC,QAAO"}
@@ -10,5 +10,5 @@ import { CompilerPluginOptions } from "./utils/devkit.js";
10
10
  type EsbuildOptions = NonNullable<DepOptimizationConfig["esbuildOptions"]>;
11
11
  type EsbuildPlugin = NonNullable<EsbuildOptions["plugins"]>[number];
12
12
  export declare function createCompilerPlugin(pluginOptions: CompilerPluginOptions, isTest: boolean, closeTransformer: boolean): EsbuildPlugin;
13
- export declare function createRolldownCompilerPlugin(pluginOptions: CompilerPluginOptions, closeTransformer: boolean): Rolldown.Plugin;
13
+ export declare function createRolldownCompilerPlugin(pluginOptions: CompilerPluginOptions, isTest: boolean, closeTransformer: boolean): Rolldown.Plugin;
14
14
  export {};
@@ -18,27 +18,24 @@ function createCompilerPlugin(pluginOptions, isTest, closeTransformer) {
18
18
  }
19
19
  };
20
20
  }
21
- function createRolldownCompilerPlugin(pluginOptions, closeTransformer) {
21
+ function createRolldownCompilerPlugin(pluginOptions, isTest, closeTransformer) {
22
22
  const javascriptTransformer = new jt({
23
23
  ...pluginOptions,
24
24
  jit: true
25
25
  }, 1);
26
- return {
27
- name: "analogjs-rolldown-deps-optimizer-plugin",
28
- load: {
29
- filter: { id: /\.[cm]?js$/ },
30
- async handler(id) {
31
- const contents = await javascriptTransformer.transformFile(id);
32
- return {
33
- code: Buffer.from(contents).toString("utf-8"),
34
- loader: "js"
35
- };
36
- }
37
- },
38
- buildEnd() {
39
- if (closeTransformer) javascriptTransformer.close();
26
+ const plugin = { name: "analogjs-rolldown-deps-optimizer-plugin" };
27
+ if (!isTest) plugin.load = {
28
+ filter: { id: /\.[cm]?js$/ },
29
+ async handler(id) {
30
+ const contents = await javascriptTransformer.transformFile(id);
31
+ return {
32
+ code: Buffer.from(contents).toString("utf-8"),
33
+ loader: "js"
34
+ };
40
35
  }
41
36
  };
37
+ if (closeTransformer) plugin.buildEnd = () => javascriptTransformer.close();
38
+ return plugin;
42
39
  }
43
40
  //#endregion
44
41
  export { createCompilerPlugin, createRolldownCompilerPlugin };
@@ -1 +1 @@
1
- {"version":3,"file":"compiler-plugin.js","names":[],"sources":["../../../src/lib/compiler-plugin.ts"],"sourcesContent":["/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.dev/license\n */\n\nimport type { DepOptimizationConfig, Rolldown } from 'vite';\nimport type { PluginBuild } from 'esbuild';\n\nimport {\n CompilerPluginOptions,\n JavaScriptTransformer,\n} from './utils/devkit.js';\n\ntype EsbuildOptions = NonNullable<DepOptimizationConfig['esbuildOptions']>;\ntype EsbuildPlugin = NonNullable<EsbuildOptions['plugins']>[number];\n\nexport function createCompilerPlugin(\n pluginOptions: CompilerPluginOptions,\n isTest: boolean,\n closeTransformer: boolean,\n): EsbuildPlugin {\n const javascriptTransformer = new JavaScriptTransformer(\n { ...pluginOptions, jit: true },\n 1,\n );\n\n return {\n name: 'analogjs-angular-esbuild-deps-optimizer-plugin',\n async setup(build: PluginBuild) {\n if (!isTest) {\n build.onLoad({ filter: /\\.[cm]?js$/ }, async (args) => {\n const contents = await javascriptTransformer.transformFile(args.path);\n\n return {\n contents,\n loader: 'js',\n };\n });\n }\n\n if (closeTransformer) {\n build.onEnd(() => javascriptTransformer.close());\n }\n },\n };\n}\n\nexport function createRolldownCompilerPlugin(\n pluginOptions: CompilerPluginOptions,\n closeTransformer: boolean,\n): Rolldown.Plugin {\n const javascriptTransformer = new JavaScriptTransformer(\n { ...pluginOptions, jit: true },\n 1,\n );\n return {\n name: 'analogjs-rolldown-deps-optimizer-plugin',\n load: {\n filter: {\n id: /\\.[cm]?js$/,\n },\n async handler(id) {\n const contents = await javascriptTransformer.transformFile(id);\n\n return {\n code: Buffer.from(contents).toString('utf-8'),\n loader: 'js',\n } as any;\n },\n },\n // Close the JavaScriptTransformer worker pool when Rolldown finishes to\n // prevent leaked handles. Skipped for Astro, which owns the lifecycle.\n buildEnd() {\n if (closeTransformer) {\n javascriptTransformer.close();\n }\n },\n };\n}\n"],"mappings":";;AAmBA,SAAgB,qBACd,eACA,QACA,kBACe;CACf,MAAM,wBAAwB,IAAI,GAChC;EAAE,GAAG;EAAe,KAAK;EAAM,EAC/B,EACD;AAED,QAAO;EACL,MAAM;EACN,MAAM,MAAM,OAAoB;AAC9B,OAAI,CAAC,OACH,OAAM,OAAO,EAAE,QAAQ,cAAc,EAAE,OAAO,SAAS;AAGrD,WAAO;KACL,UAHe,MAAM,sBAAsB,cAAc,KAAK,KAAK;KAInE,QAAQ;KACT;KACD;AAGJ,OAAI,iBACF,OAAM,YAAY,sBAAsB,OAAO,CAAC;;EAGrD;;AAGH,SAAgB,6BACd,eACA,kBACiB;CACjB,MAAM,wBAAwB,IAAI,GAChC;EAAE,GAAG;EAAe,KAAK;EAAM,EAC/B,EACD;AACD,QAAO;EACL,MAAM;EACN,MAAM;GACJ,QAAQ,EACN,IAAI,cACL;GACD,MAAM,QAAQ,IAAI;IAChB,MAAM,WAAW,MAAM,sBAAsB,cAAc,GAAG;AAE9D,WAAO;KACL,MAAM,OAAO,KAAK,SAAS,CAAC,SAAS,QAAQ;KAC7C,QAAQ;KACT;;GAEJ;EAGD,WAAW;AACT,OAAI,iBACF,uBAAsB,OAAO;;EAGlC"}
1
+ {"version":3,"file":"compiler-plugin.js","names":[],"sources":["../../../src/lib/compiler-plugin.ts"],"sourcesContent":["/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.dev/license\n */\n\nimport type { DepOptimizationConfig, Rolldown } from 'vite';\nimport type { PluginBuild } from 'esbuild';\n\nimport {\n CompilerPluginOptions,\n JavaScriptTransformer,\n} from './utils/devkit.js';\n\ntype EsbuildOptions = NonNullable<DepOptimizationConfig['esbuildOptions']>;\ntype EsbuildPlugin = NonNullable<EsbuildOptions['plugins']>[number];\n\nexport function createCompilerPlugin(\n pluginOptions: CompilerPluginOptions,\n isTest: boolean,\n closeTransformer: boolean,\n): EsbuildPlugin {\n const javascriptTransformer = new JavaScriptTransformer(\n { ...pluginOptions, jit: true },\n 1,\n );\n\n return {\n name: 'analogjs-angular-esbuild-deps-optimizer-plugin',\n async setup(build: PluginBuild) {\n if (!isTest) {\n build.onLoad({ filter: /\\.[cm]?js$/ }, async (args) => {\n const contents = await javascriptTransformer.transformFile(args.path);\n\n return {\n contents,\n loader: 'js',\n };\n });\n }\n\n if (closeTransformer) {\n build.onEnd(() => javascriptTransformer.close());\n }\n },\n };\n}\n\nexport function createRolldownCompilerPlugin(\n pluginOptions: CompilerPluginOptions,\n isTest: boolean,\n closeTransformer: boolean,\n): Rolldown.Plugin {\n const javascriptTransformer = new JavaScriptTransformer(\n { ...pluginOptions, jit: true },\n 1,\n );\n\n const plugin: Rolldown.Plugin = {\n name: 'analogjs-rolldown-deps-optimizer-plugin',\n };\n\n if (!isTest) {\n plugin.load = {\n filter: {\n id: /\\.[cm]?js$/,\n },\n async handler(id) {\n const contents = await javascriptTransformer.transformFile(id);\n\n return {\n code: Buffer.from(contents).toString('utf-8'),\n loader: 'js',\n } as any;\n },\n };\n }\n\n if (closeTransformer) {\n plugin.buildEnd = () => javascriptTransformer.close();\n }\n\n return plugin;\n}\n"],"mappings":";;AAmBA,SAAgB,qBACd,eACA,QACA,kBACe;CACf,MAAM,wBAAwB,IAAI,GAChC;EAAE,GAAG;EAAe,KAAK;EAAM,EAC/B,EACD;AAED,QAAO;EACL,MAAM;EACN,MAAM,MAAM,OAAoB;AAC9B,OAAI,CAAC,OACH,OAAM,OAAO,EAAE,QAAQ,cAAc,EAAE,OAAO,SAAS;AAGrD,WAAO;KACL,UAHe,MAAM,sBAAsB,cAAc,KAAK,KAAK;KAInE,QAAQ;KACT;KACD;AAGJ,OAAI,iBACF,OAAM,YAAY,sBAAsB,OAAO,CAAC;;EAGrD;;AAGH,SAAgB,6BACd,eACA,QACA,kBACiB;CACjB,MAAM,wBAAwB,IAAI,GAChC;EAAE,GAAG;EAAe,KAAK;EAAM,EAC/B,EACD;CAED,MAAM,SAA0B,EAC9B,MAAM,2CACP;AAED,KAAI,CAAC,OACH,QAAO,OAAO;EACZ,QAAQ,EACN,IAAI,cACL;EACD,MAAM,QAAQ,IAAI;GAChB,MAAM,WAAW,MAAM,sBAAsB,cAAc,GAAG;AAE9D,UAAO;IACL,MAAM,OAAO,KAAK,SAAS,CAAC,SAAS,QAAQ;IAC7C,QAAQ;IACT;;EAEJ;AAGH,KAAI,iBACF,QAAO,iBAAiB,sBAAsB,OAAO;AAGvD,QAAO"}
@@ -283,7 +283,8 @@ function fastCompilePlugin(pluginOptions) {
283
283
  exclude: [
284
284
  /node_modules/,
285
285
  "type=script",
286
- "@ng/component"
286
+ "@ng/component",
287
+ /[?&]raw\b/
287
288
  ]
288
289
  } },
289
290
  async handler(code, id) {
@@ -1 +1 @@
1
- {"version":3,"file":"fast-compile-plugin.js","names":[],"sources":["../../../src/lib/fast-compile-plugin.ts"],"sourcesContent":["import { promises as fsPromises } from 'node:fs';\nimport { dirname, isAbsolute, resolve } from 'node:path';\nimport * as vite from 'vite';\n\nimport * as compilerCli from '@angular/compiler-cli';\nimport { normalizePath, Plugin, preprocessCSS, ResolvedConfig } from 'vite';\n\nimport {\n compile,\n scanFile,\n scanPackageDts,\n collectImportedPackages,\n collectRelativeReExports,\n jitTransform,\n inlineResourceUrls,\n extractInlineStyles,\n generateHmrCode,\n debugCompile,\n debugRegistry,\n type ComponentRegistry,\n} from './compiler/index.js';\n\nimport {\n TS_EXT_REGEX,\n getTsConfigPath,\n createDepOptimizerConfig,\n type TsConfigResolutionContext,\n} from './utils/plugin-config.js';\nimport { VIRTUAL_RAW_PREFIX, toVirtualRawId } from './utils/virtual-ids.js';\nimport {\n loadVirtualRawModule,\n rewriteHtmlRawImport,\n} from './utils/virtual-resources.js';\nimport { markStylePathSafe } from './utils/safe-module-paths.js';\n\ndeclare global {\n /**\n * Shared convention for out-of-tree compilers (e.g. `@tsrx/analog`) that\n * produce Angular Ivy definitions from a non-TS source format. Populate\n * this map with directive/component metadata for any class fastCompile\n * can't reach through its own tsconfig-driven scan, and the per-compile\n * registry lookup in `fastCompilePlugin` will merge those entries in —\n * so TS `@Component({ imports: [X] })` references to such classes\n * resolve statically instead of hitting the `_unresolved-${className}`\n * sentinel.\n */\n // eslint-disable-next-line no-var\n var __ANALOG_EXTERNAL_REGISTRY__: ComponentRegistry | undefined;\n}\n\nexport interface FastCompilePluginOptions {\n tsconfigGetter: () => string;\n workspaceRoot: string;\n inlineStylesExtension: string;\n jit: boolean;\n liveReload: boolean;\n supportedBrowsers: string[];\n transformFilter?: (code: string, id: string) => boolean;\n isTest: boolean;\n isAstroIntegration: boolean;\n fastCompileMode?: 'full' | 'partial';\n}\n\nexport function fastCompilePlugin(\n pluginOptions: FastCompilePluginOptions,\n): Plugin {\n let resolvedConfig: ResolvedConfig;\n let tsConfigResolutionContext: TsConfigResolutionContext | null = null;\n let watchMode = false;\n\n // fast-compile plugin state\n const registry: ComponentRegistry = new Map();\n const resourceToSource = new Map<string, string>();\n const scannedDtsPackages = new Set<string>();\n let projectRoot = '';\n let useDefineForClassFields = true;\n\n /**\n * Scan a file into the registry, then recursively walk its relative\n * `export *` / `export { … } from './x'` chain so any underlying\n * directive classes also land in the registry. Used both at\n * `buildStart` (for tsconfig path entries) and at dev time (file\n * `add` and `handleHotUpdate`) so newly added barrels stay in sync\n * without requiring a server restart.\n *\n * The `visited` set prevents infinite recursion within a single\n * top-level call. Each fresh scan should pass an empty set (so HMR\n * re-scans aren't blocked by buildStart's earlier visits).\n */\n async function scanBarrelExports(\n file: string,\n visited: Set<string> = new Set(),\n overwrite = false,\n ): Promise<void> {\n if (visited.has(file)) return;\n visited.add(file);\n let code: string;\n try {\n code = await fsPromises.readFile(file, 'utf-8');\n } catch (e) {\n if (debugRegistry.enabled) {\n debugRegistry(\n 'scanBarrelExports: failed to read %s: %s',\n file,\n (e as Error)?.message,\n );\n }\n return;\n }\n const entries = scanFile(code, file);\n for (const entry of entries) {\n // At buildStart we want stable registry entries (don't overwrite\n // an earlier scan with a barrel re-scan); HMR explicitly asks\n // for overwrite so updated metadata replaces stale entries.\n if (overwrite || !registry.has(entry.className)) {\n registry.set(entry.className, entry);\n }\n }\n // Collect every relative re-export specifier via OXC AST so\n // recursive scans can't trip over each other (a shared `/g` regex\n // would have its `lastIndex` reset by each recursive call and\n // silently skip half of an outer barrel's re-exports, which\n // previously left directives like `HlmRadioGroup` unregistered).\n const dir = dirname(file);\n for (const rel of collectRelativeReExports(code, file)) {\n // NodeNext-style libraries write `export * from './foo.js'`\n // even though the source is `./foo.ts`. Strip the ESM\n // extension before probing or the candidates would be\n // `foo.js.ts` / `foo.js/index.ts`, which never exist.\n const normalizedRel = rel.replace(/\\.(?:js|mjs)$/u, '');\n const reExportCandidates = [\n resolve(dir, normalizedRel + '.ts'),\n resolve(dir, normalizedRel, 'index.ts'),\n ];\n let resolved = false;\n for (const candidate of reExportCandidates) {\n try {\n await fsPromises.access(candidate);\n await scanBarrelExports(candidate, visited, overwrite);\n resolved = true;\n break;\n } catch {\n // try next candidate\n }\n }\n if (!resolved && debugRegistry.enabled) {\n debugRegistry(\n 'scanBarrelExports: %s re-export %s did not resolve to %o',\n file,\n rel,\n reExportCandidates,\n );\n }\n }\n }\n\n async function initFastCompile() {\n if (pluginOptions.jit) return; // JIT: no registry scan needed\n\n // Scan all source files to build the registry\n registry.clear();\n scannedDtsPackages.clear();\n const resolvedTsConfigPath = resolveTsConfigPath();\n projectRoot = dirname(resolvedTsConfigPath);\n const config = compilerCli.readConfiguration(resolvedTsConfigPath);\n useDefineForClassFields = config.options?.useDefineForClassFields ?? true;\n\n // Collect candidate files: tsconfig rootNames PLUS the entry points\n // named in `compilerOptions.paths`. App tsconfigs typically only\n // include the app's own sources, so workspace library entry barrels\n // (e.g. `HlmSelectImports = [HlmSelect, HlmSelectContent, ...] as\n // const`) live outside `rootNames` and would otherwise miss the\n // initial scan. The compiler then can't see that `HlmSelectImports`\n // is a tuple barrel and emits the bare identifier into the parent\n // component's `dependencies()` list, where Angular's runtime\n // silently drops it because arrays don't have a directive def.\n const candidates = new Set<string>(config.rootNames);\n const tsPaths = config.options?.paths;\n const baseUrl = (config.options?.baseUrl ?? projectRoot) as string;\n if (tsPaths) {\n for (const targets of Object.values(tsPaths)) {\n for (const target of targets as string[]) {\n // Skip wildcard patterns — entry barrels are normally exact\n // file paths like \"libs/helm/select/src/index.ts\".\n if (target.includes('*')) continue;\n candidates.add(resolve(baseUrl, target));\n }\n }\n }\n const results = await Promise.all(\n Array.from(candidates).map(async (file) => {\n try {\n const code = await fsPromises.readFile(file, 'utf-8');\n return scanFile(code, file);\n } catch (e) {\n if (debugRegistry.enabled) {\n debugRegistry(\n 'initFastCompile: skipping unreadable %s: %s',\n file,\n (e as Error)?.message,\n );\n }\n return []; // Skip unreadable files\n }\n }),\n );\n\n for (const entries of results) {\n for (const entry of entries) {\n registry.set(entry.className, entry);\n }\n }\n\n // Library barrels typically `export * from './lib/...'` rather than\n // declaring directives directly, so the entry file alone gives us\n // the tuple consts but not the directive classes they reference.\n // Walk the relative `export *` chain so the underlying classes also\n // land in the registry. Use a SHARED visited set across all\n // barrels so recursive walks don't double-scan a file that's\n // re-exported from multiple entry points.\n const buildStartVisited = new Set<string>();\n if (tsPaths) {\n const barrelCandidates: string[] = [];\n for (const targets of Object.values(tsPaths)) {\n for (const target of targets as string[]) {\n if (target.includes('*')) continue;\n barrelCandidates.push(resolve(baseUrl, target));\n }\n }\n await Promise.all(\n barrelCandidates.map((c) => scanBarrelExports(c, buildStartVisited)),\n );\n }\n debugRegistry(\n 'initFastCompile done: %d entries from %d candidate files',\n registry.size,\n candidates.size,\n );\n }\n\n function ensureDtsRegistryForSource(code: string, id: string) {\n for (const pkg of collectImportedPackages(code, id)) {\n if (scannedDtsPackages.has(pkg)) continue;\n scannedDtsPackages.add(pkg);\n\n try {\n const dtsEntries = scanPackageDts(pkg, projectRoot);\n for (const entry of dtsEntries) {\n if (!registry.has(entry.className)) {\n registry.set(entry.className, entry);\n }\n }\n } catch {\n // Package may not have .d.ts files or may not be Angular\n }\n }\n }\n\n async function handleFastCompileTransform(\n code: string,\n id: string,\n ): Promise<{ code: string; map: any } | undefined> {\n if (!/(Component|Directive|Pipe|Injectable|NgModule)\\(/.test(code)) {\n // Non-Angular file — strip TS-only syntax ourselves so barrels\n // like `export { Foo, type Bar } from './x'` and other TS-only\n // forms don't leak unstripped to Rolldown. In rolldown-vite the\n // built-in `vite:oxc` strip is registered as a Rust-side native\n // plugin (`viteTransformPlugin` from `rolldown/experimental`); if\n // its hook-filter treats files our `transform.filter.id.include`\n // claimed as already-handled, no JS-side fallback runs and raw\n // TS reaches the parser → `SyntaxError: Unexpected identifier`.\n const stripped = vite.transformWithOxc\n ? await vite.transformWithOxc(code, id, {\n lang: 'ts',\n sourcemap: true,\n decorator: { legacy: false, emitDecoratorMetadata: false },\n })\n : await vite.transformWithEsbuild(code, id, {\n loader: 'ts',\n sourcemap: true,\n });\n return { code: stripped.code, map: stripped.map };\n }\n\n // JIT mode\n if (pluginOptions.jit) {\n const result = jitTransform(code, id);\n // Strip TypeScript-only syntax (e.g. `readonly`, parameter property\n // modifiers, type annotations on fields) so the output is valid JS\n // for Rolldown. `angularVitestSourcemapPlugin` normally runs this\n // strip downstream in tests, but it is intentionally skipped on\n // StackBlitz / WebContainer — and the production build pipeline\n // does not register it either — so the JIT path must self-strip\n // to stay safe across environments.\n //\n // Pass the jitTransform map as `inMap` so OXC/esbuild emit a map\n // composed with the original `.ts` source — without this, debug\n // stack traces and breakpoints land on the wrong lines once the\n // strip removes any TS-only token. `jitTransform` returns\n // `map: null` for files with no Angular class (no edits made);\n // passing that to OXC/esbuild as `inMap` throws, so coerce to\n // `undefined` in that case.\n const inMap = result.map ?? undefined;\n const stripped = vite.transformWithOxc\n ? await vite.transformWithOxc(\n result.code,\n id,\n {\n lang: 'ts',\n sourcemap: true,\n decorator: { legacy: false, emitDecoratorMetadata: false },\n },\n inMap,\n )\n : await vite.transformWithEsbuild(\n result.code,\n id,\n { loader: 'ts', sourcemap: true },\n inMap,\n );\n return { code: stripped.code, map: stripped.map };\n }\n\n // Inline external templateUrl/styleUrl(s) into the source before compilation\n code = inlineResourceUrls(code, id);\n\n // Pre-resolve inline styles that need preprocessing (SCSS/Sass/Less)\n let resolvedStyles: Map<string, string> | undefined;\n let resolvedInlineStyles: Map<number, string> | undefined;\n\n if (pluginOptions.inlineStylesExtension !== 'css') {\n const styleStrings = extractInlineStyles(code, id);\n\n if (styleStrings.length > 0) {\n resolvedInlineStyles = new Map();\n for (let i = 0; i < styleStrings.length; i++) {\n try {\n const fakePath = id.replace(\n /\\.ts$/,\n `.inline-${i}.${pluginOptions.inlineStylesExtension}`,\n );\n const processed = await preprocessCSS(\n styleStrings[i],\n fakePath,\n resolvedConfig,\n );\n resolvedInlineStyles.set(i, processed.code);\n } catch (e) {\n if (debugCompile.enabled) {\n debugCompile(\n 'inline style #%d preprocessing failed in %s: %s',\n i,\n id,\n (e as Error)?.message,\n );\n }\n // Skip styles that can't be preprocessed\n }\n }\n if (resolvedInlineStyles.size === 0) resolvedInlineStyles = undefined;\n }\n }\n\n ensureDtsRegistryForSource(code, id);\n\n // Merge entries from the shared external-registry global into this\n // compile's lookup view. Convention: out-of-tree compilers populate\n // `globalThis.__ANALOG_EXTERNAL_REGISTRY__` with directive metadata\n // for classes fastCompile can't reach through its tsconfig-driven\n // scan (e.g. `.tsrx` files compiled by `@tsrx/analog`). Without this\n // merge, a TS `@Component({ imports: [X] })` that references such a\n // class hits `_unresolved-${className}` as its selector and the tag\n // never matches at runtime.\n let compileRegistry: ComponentRegistry = registry;\n const externalRegistry = globalThis.__ANALOG_EXTERNAL_REGISTRY__;\n if (externalRegistry && externalRegistry.size > 0) {\n compileRegistry = new Map(registry);\n for (const [k, v] of externalRegistry) compileRegistry.set(k, v);\n }\n\n const result = compile(code, id, {\n registry: compileRegistry,\n resolvedStyles,\n resolvedInlineStyles,\n useDefineForClassFields,\n compilationMode: pluginOptions.fastCompileMode,\n });\n\n // Track resource dependencies for HMR\n for (const dep of result.resourceDependencies) {\n resourceToSource.set(dep, id);\n }\n\n // Strip TypeScript-only syntax\n const stripped = vite.transformWithOxc\n ? await vite.transformWithOxc(result.code, id, {\n lang: 'ts',\n sourcemap: false,\n decorator: { legacy: false, emitDecoratorMetadata: false },\n })\n : await vite.transformWithEsbuild(result.code, id, {\n loader: 'ts',\n sourcemap: false,\n });\n let outputCode = stripped.code;\n\n // Append HMR code in dev mode\n if (watchMode && pluginOptions.liveReload) {\n const fileDeclarations = [...registry.values()].filter(\n (e) => e.fileName === id,\n );\n if (fileDeclarations.length > 0) {\n const localDepClassNames = fileDeclarations.map((e) => e.className);\n outputCode += generateHmrCode(fileDeclarations, localDepClassNames);\n }\n }\n\n return { code: outputCode, map: result.map };\n }\n\n function resolveTsConfigPath() {\n const { root, isProd, isLib } = tsConfigResolutionContext!;\n return getTsConfigPath(\n root,\n pluginOptions.tsconfigGetter(),\n isProd,\n pluginOptions.isTest,\n isLib,\n );\n }\n\n return {\n name: '@analogjs/vite-plugin-angular-fast-compile',\n enforce: 'pre' as const,\n async config(config, { command }) {\n watchMode = command === 'serve';\n const isProd =\n config.mode === 'production' ||\n process.env['NODE_ENV'] === 'production';\n\n tsConfigResolutionContext = {\n root: config.root || '.',\n isProd,\n isLib: !!config?.build?.lib,\n };\n\n const preliminaryTsConfigPath = resolveTsConfigPath();\n\n const depOptimizer = createDepOptimizerConfig({\n tsconfig: preliminaryTsConfigPath,\n isProd,\n jit: pluginOptions.jit,\n watchMode,\n isTest: pluginOptions.isTest,\n isAstroIntegration: pluginOptions.isAstroIntegration,\n });\n\n // No `resolve.conditions` extension here: the `style` condition is\n // scoped to `.css`-extension requests by\n // `cssExtensionStyleResolverPlugin`, registered once at the\n // `angular()` factory level (which is the only public entry point\n // that wires this plugin in).\n return {\n ...(vite.rolldownVersion ? { oxc: {} as any } : { esbuild: false }),\n ...depOptimizer,\n };\n },\n configResolved(config) {\n resolvedConfig = config;\n },\n configureServer(server) {\n // Watch for new .ts files and scan them into the registry. Use\n // the barrel-aware scanner so a newly added re-export entry\n // (`export * from './x'`) also expands its underlying directive\n // classes — otherwise the registry stays stale until restart.\n server.watcher.on('add', async (filePath) => {\n if (\n filePath.endsWith('.ts') &&\n !filePath.endsWith('.spec.ts') &&\n !filePath.endsWith('.d.ts')\n ) {\n await scanBarrelExports(filePath, new Set(), true);\n }\n });\n },\n async buildStart() {\n await initFastCompile();\n },\n async handleHotUpdate(ctx) {\n // Resource file changes → invalidate parent .ts module\n if (resourceToSource.has(ctx.file)) {\n const parentSource = resourceToSource.get(ctx.file)!;\n const parentModule = ctx.server.moduleGraph.getModuleById(parentSource);\n if (parentModule) {\n return [parentModule];\n }\n }\n\n if (TS_EXT_REGEX.test(ctx.file)) {\n const [fileId] = ctx.file.split('?');\n\n // Remove old entries from this file\n const oldEntries = [...registry.entries()]\n .filter(([_, v]) => v.fileName === fileId)\n .map(([k]) => k);\n for (const key of oldEntries) {\n registry.delete(key);\n }\n\n // Rescan the changed file via the barrel-aware scanner so an\n // edited barrel re-export picks up newly-referenced files.\n // Pass overwrite=true so updated metadata replaces stale\n // entries from the previous scan.\n await scanBarrelExports(fileId, new Set(), true);\n }\n\n // Let Vite handle the rest — the transform hook will recompile\n return ctx.modules;\n },\n resolveId(id, importer) {\n if (id.startsWith(VIRTUAL_RAW_PREFIX)) {\n return `\\0${id}`;\n }\n\n if (pluginOptions.jit && id.startsWith('angular:jit:')) {\n const filePath = normalizePath(\n resolve(dirname(importer as string), id.split(';')[1]),\n );\n if (id.includes(':style')) {\n markStylePathSafe(resolvedConfig, filePath);\n return filePath + '?inline';\n }\n return toVirtualRawId(filePath);\n }\n\n const rawRewrite = rewriteHtmlRawImport(id, importer);\n if (rawRewrite) return rawRewrite;\n\n // User `.scss?inline` / `.css?inline` imports: resolve and mark\n // safe so Vite's native CSS pipeline handles them.\n if (/\\.(css|scss|sass|less)\\?inline$/.test(id) && importer) {\n const filePath = id.split('?')[0];\n const resolved = isAbsolute(filePath)\n ? normalizePath(filePath)\n : normalizePath(resolve(dirname(importer), filePath));\n markStylePathSafe(resolvedConfig, resolved);\n return resolved + '?inline';\n }\n\n return undefined;\n },\n async load(id) {\n const rawModule = await loadVirtualRawModule(this, id);\n if (rawModule !== undefined) return rawModule;\n\n // Vitest fallback: module-runner can skip resolveId, so the bare\n // ?inline query reaches load. Mark safe and let Vite handle it.\n if (/\\.(css|scss|sass|less)\\?inline$/.test(id)) {\n markStylePathSafe(resolvedConfig, id.split('?')[0]);\n }\n\n return;\n },\n transform: {\n filter: {\n id: {\n include: [TS_EXT_REGEX],\n exclude: [/node_modules/, 'type=script', '@ng/component'],\n },\n },\n async handler(code, id) {\n if (\n pluginOptions.transformFilter &&\n !(pluginOptions.transformFilter(code, id) ?? true)\n ) {\n return;\n }\n\n if (id.includes('.ts?')) {\n id = id.replace(/\\?(.*)/, '');\n }\n return handleFastCompileTransform(code, id);\n },\n },\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"fast-compile-plugin.js","names":[],"sources":["../../../src/lib/fast-compile-plugin.ts"],"sourcesContent":["import { promises as fsPromises } from 'node:fs';\nimport { dirname, isAbsolute, resolve } from 'node:path';\nimport * as vite from 'vite';\n\nimport * as compilerCli from '@angular/compiler-cli';\nimport { normalizePath, Plugin, preprocessCSS, ResolvedConfig } from 'vite';\n\nimport {\n compile,\n scanFile,\n scanPackageDts,\n collectImportedPackages,\n collectRelativeReExports,\n jitTransform,\n inlineResourceUrls,\n extractInlineStyles,\n generateHmrCode,\n debugCompile,\n debugRegistry,\n type ComponentRegistry,\n} from './compiler/index.js';\n\nimport {\n TS_EXT_REGEX,\n getTsConfigPath,\n createDepOptimizerConfig,\n type TsConfigResolutionContext,\n} from './utils/plugin-config.js';\nimport { VIRTUAL_RAW_PREFIX, toVirtualRawId } from './utils/virtual-ids.js';\nimport {\n loadVirtualRawModule,\n rewriteHtmlRawImport,\n} from './utils/virtual-resources.js';\nimport { markStylePathSafe } from './utils/safe-module-paths.js';\n\ndeclare global {\n /**\n * Shared convention for out-of-tree compilers (e.g. `@tsrx/analog`) that\n * produce Angular Ivy definitions from a non-TS source format. Populate\n * this map with directive/component metadata for any class fastCompile\n * can't reach through its own tsconfig-driven scan, and the per-compile\n * registry lookup in `fastCompilePlugin` will merge those entries in —\n * so TS `@Component({ imports: [X] })` references to such classes\n * resolve statically instead of hitting the `_unresolved-${className}`\n * sentinel.\n */\n // eslint-disable-next-line no-var\n var __ANALOG_EXTERNAL_REGISTRY__: ComponentRegistry | undefined;\n}\n\nexport interface FastCompilePluginOptions {\n tsconfigGetter: () => string;\n workspaceRoot: string;\n inlineStylesExtension: string;\n jit: boolean;\n liveReload: boolean;\n supportedBrowsers: string[];\n transformFilter?: (code: string, id: string) => boolean;\n isTest: boolean;\n isAstroIntegration: boolean;\n fastCompileMode?: 'full' | 'partial';\n}\n\nexport function fastCompilePlugin(\n pluginOptions: FastCompilePluginOptions,\n): Plugin {\n let resolvedConfig: ResolvedConfig;\n let tsConfigResolutionContext: TsConfigResolutionContext | null = null;\n let watchMode = false;\n\n // fast-compile plugin state\n const registry: ComponentRegistry = new Map();\n const resourceToSource = new Map<string, string>();\n const scannedDtsPackages = new Set<string>();\n let projectRoot = '';\n let useDefineForClassFields = true;\n\n /**\n * Scan a file into the registry, then recursively walk its relative\n * `export *` / `export { … } from './x'` chain so any underlying\n * directive classes also land in the registry. Used both at\n * `buildStart` (for tsconfig path entries) and at dev time (file\n * `add` and `handleHotUpdate`) so newly added barrels stay in sync\n * without requiring a server restart.\n *\n * The `visited` set prevents infinite recursion within a single\n * top-level call. Each fresh scan should pass an empty set (so HMR\n * re-scans aren't blocked by buildStart's earlier visits).\n */\n async function scanBarrelExports(\n file: string,\n visited: Set<string> = new Set(),\n overwrite = false,\n ): Promise<void> {\n if (visited.has(file)) return;\n visited.add(file);\n let code: string;\n try {\n code = await fsPromises.readFile(file, 'utf-8');\n } catch (e) {\n if (debugRegistry.enabled) {\n debugRegistry(\n 'scanBarrelExports: failed to read %s: %s',\n file,\n (e as Error)?.message,\n );\n }\n return;\n }\n const entries = scanFile(code, file);\n for (const entry of entries) {\n // At buildStart we want stable registry entries (don't overwrite\n // an earlier scan with a barrel re-scan); HMR explicitly asks\n // for overwrite so updated metadata replaces stale entries.\n if (overwrite || !registry.has(entry.className)) {\n registry.set(entry.className, entry);\n }\n }\n // Collect every relative re-export specifier via OXC AST so\n // recursive scans can't trip over each other (a shared `/g` regex\n // would have its `lastIndex` reset by each recursive call and\n // silently skip half of an outer barrel's re-exports, which\n // previously left directives like `HlmRadioGroup` unregistered).\n const dir = dirname(file);\n for (const rel of collectRelativeReExports(code, file)) {\n // NodeNext-style libraries write `export * from './foo.js'`\n // even though the source is `./foo.ts`. Strip the ESM\n // extension before probing or the candidates would be\n // `foo.js.ts` / `foo.js/index.ts`, which never exist.\n const normalizedRel = rel.replace(/\\.(?:js|mjs)$/u, '');\n const reExportCandidates = [\n resolve(dir, normalizedRel + '.ts'),\n resolve(dir, normalizedRel, 'index.ts'),\n ];\n let resolved = false;\n for (const candidate of reExportCandidates) {\n try {\n await fsPromises.access(candidate);\n await scanBarrelExports(candidate, visited, overwrite);\n resolved = true;\n break;\n } catch {\n // try next candidate\n }\n }\n if (!resolved && debugRegistry.enabled) {\n debugRegistry(\n 'scanBarrelExports: %s re-export %s did not resolve to %o',\n file,\n rel,\n reExportCandidates,\n );\n }\n }\n }\n\n async function initFastCompile() {\n if (pluginOptions.jit) return; // JIT: no registry scan needed\n\n // Scan all source files to build the registry\n registry.clear();\n scannedDtsPackages.clear();\n const resolvedTsConfigPath = resolveTsConfigPath();\n projectRoot = dirname(resolvedTsConfigPath);\n const config = compilerCli.readConfiguration(resolvedTsConfigPath);\n useDefineForClassFields = config.options?.useDefineForClassFields ?? true;\n\n // Collect candidate files: tsconfig rootNames PLUS the entry points\n // named in `compilerOptions.paths`. App tsconfigs typically only\n // include the app's own sources, so workspace library entry barrels\n // (e.g. `HlmSelectImports = [HlmSelect, HlmSelectContent, ...] as\n // const`) live outside `rootNames` and would otherwise miss the\n // initial scan. The compiler then can't see that `HlmSelectImports`\n // is a tuple barrel and emits the bare identifier into the parent\n // component's `dependencies()` list, where Angular's runtime\n // silently drops it because arrays don't have a directive def.\n const candidates = new Set<string>(config.rootNames);\n const tsPaths = config.options?.paths;\n const baseUrl = (config.options?.baseUrl ?? projectRoot) as string;\n if (tsPaths) {\n for (const targets of Object.values(tsPaths)) {\n for (const target of targets as string[]) {\n // Skip wildcard patterns — entry barrels are normally exact\n // file paths like \"libs/helm/select/src/index.ts\".\n if (target.includes('*')) continue;\n candidates.add(resolve(baseUrl, target));\n }\n }\n }\n const results = await Promise.all(\n Array.from(candidates).map(async (file) => {\n try {\n const code = await fsPromises.readFile(file, 'utf-8');\n return scanFile(code, file);\n } catch (e) {\n if (debugRegistry.enabled) {\n debugRegistry(\n 'initFastCompile: skipping unreadable %s: %s',\n file,\n (e as Error)?.message,\n );\n }\n return []; // Skip unreadable files\n }\n }),\n );\n\n for (const entries of results) {\n for (const entry of entries) {\n registry.set(entry.className, entry);\n }\n }\n\n // Library barrels typically `export * from './lib/...'` rather than\n // declaring directives directly, so the entry file alone gives us\n // the tuple consts but not the directive classes they reference.\n // Walk the relative `export *` chain so the underlying classes also\n // land in the registry. Use a SHARED visited set across all\n // barrels so recursive walks don't double-scan a file that's\n // re-exported from multiple entry points.\n const buildStartVisited = new Set<string>();\n if (tsPaths) {\n const barrelCandidates: string[] = [];\n for (const targets of Object.values(tsPaths)) {\n for (const target of targets as string[]) {\n if (target.includes('*')) continue;\n barrelCandidates.push(resolve(baseUrl, target));\n }\n }\n await Promise.all(\n barrelCandidates.map((c) => scanBarrelExports(c, buildStartVisited)),\n );\n }\n debugRegistry(\n 'initFastCompile done: %d entries from %d candidate files',\n registry.size,\n candidates.size,\n );\n }\n\n function ensureDtsRegistryForSource(code: string, id: string) {\n for (const pkg of collectImportedPackages(code, id)) {\n if (scannedDtsPackages.has(pkg)) continue;\n scannedDtsPackages.add(pkg);\n\n try {\n const dtsEntries = scanPackageDts(pkg, projectRoot);\n for (const entry of dtsEntries) {\n if (!registry.has(entry.className)) {\n registry.set(entry.className, entry);\n }\n }\n } catch {\n // Package may not have .d.ts files or may not be Angular\n }\n }\n }\n\n async function handleFastCompileTransform(\n code: string,\n id: string,\n ): Promise<{ code: string; map: any } | undefined> {\n if (!/(Component|Directive|Pipe|Injectable|NgModule)\\(/.test(code)) {\n // Non-Angular file — strip TS-only syntax ourselves so barrels\n // like `export { Foo, type Bar } from './x'` and other TS-only\n // forms don't leak unstripped to Rolldown. In rolldown-vite the\n // built-in `vite:oxc` strip is registered as a Rust-side native\n // plugin (`viteTransformPlugin` from `rolldown/experimental`); if\n // its hook-filter treats files our `transform.filter.id.include`\n // claimed as already-handled, no JS-side fallback runs and raw\n // TS reaches the parser → `SyntaxError: Unexpected identifier`.\n const stripped = vite.transformWithOxc\n ? await vite.transformWithOxc(code, id, {\n lang: 'ts',\n sourcemap: true,\n decorator: { legacy: false, emitDecoratorMetadata: false },\n })\n : await vite.transformWithEsbuild(code, id, {\n loader: 'ts',\n sourcemap: true,\n });\n return { code: stripped.code, map: stripped.map };\n }\n\n // JIT mode\n if (pluginOptions.jit) {\n const result = jitTransform(code, id);\n // Strip TypeScript-only syntax (e.g. `readonly`, parameter property\n // modifiers, type annotations on fields) so the output is valid JS\n // for Rolldown. `angularVitestSourcemapPlugin` normally runs this\n // strip downstream in tests, but it is intentionally skipped on\n // StackBlitz / WebContainer — and the production build pipeline\n // does not register it either — so the JIT path must self-strip\n // to stay safe across environments.\n //\n // Pass the jitTransform map as `inMap` so OXC/esbuild emit a map\n // composed with the original `.ts` source — without this, debug\n // stack traces and breakpoints land on the wrong lines once the\n // strip removes any TS-only token. `jitTransform` returns\n // `map: null` for files with no Angular class (no edits made);\n // passing that to OXC/esbuild as `inMap` throws, so coerce to\n // `undefined` in that case.\n const inMap = result.map ?? undefined;\n const stripped = vite.transformWithOxc\n ? await vite.transformWithOxc(\n result.code,\n id,\n {\n lang: 'ts',\n sourcemap: true,\n decorator: { legacy: false, emitDecoratorMetadata: false },\n },\n inMap,\n )\n : await vite.transformWithEsbuild(\n result.code,\n id,\n { loader: 'ts', sourcemap: true },\n inMap,\n );\n return { code: stripped.code, map: stripped.map };\n }\n\n // Inline external templateUrl/styleUrl(s) into the source before compilation\n code = inlineResourceUrls(code, id);\n\n // Pre-resolve inline styles that need preprocessing (SCSS/Sass/Less)\n let resolvedStyles: Map<string, string> | undefined;\n let resolvedInlineStyles: Map<number, string> | undefined;\n\n if (pluginOptions.inlineStylesExtension !== 'css') {\n const styleStrings = extractInlineStyles(code, id);\n\n if (styleStrings.length > 0) {\n resolvedInlineStyles = new Map();\n for (let i = 0; i < styleStrings.length; i++) {\n try {\n const fakePath = id.replace(\n /\\.ts$/,\n `.inline-${i}.${pluginOptions.inlineStylesExtension}`,\n );\n const processed = await preprocessCSS(\n styleStrings[i],\n fakePath,\n resolvedConfig,\n );\n resolvedInlineStyles.set(i, processed.code);\n } catch (e) {\n if (debugCompile.enabled) {\n debugCompile(\n 'inline style #%d preprocessing failed in %s: %s',\n i,\n id,\n (e as Error)?.message,\n );\n }\n // Skip styles that can't be preprocessed\n }\n }\n if (resolvedInlineStyles.size === 0) resolvedInlineStyles = undefined;\n }\n }\n\n ensureDtsRegistryForSource(code, id);\n\n // Merge entries from the shared external-registry global into this\n // compile's lookup view. Convention: out-of-tree compilers populate\n // `globalThis.__ANALOG_EXTERNAL_REGISTRY__` with directive metadata\n // for classes fastCompile can't reach through its tsconfig-driven\n // scan (e.g. `.tsrx` files compiled by `@tsrx/analog`). Without this\n // merge, a TS `@Component({ imports: [X] })` that references such a\n // class hits `_unresolved-${className}` as its selector and the tag\n // never matches at runtime.\n let compileRegistry: ComponentRegistry = registry;\n const externalRegistry = globalThis.__ANALOG_EXTERNAL_REGISTRY__;\n if (externalRegistry && externalRegistry.size > 0) {\n compileRegistry = new Map(registry);\n for (const [k, v] of externalRegistry) compileRegistry.set(k, v);\n }\n\n const result = compile(code, id, {\n registry: compileRegistry,\n resolvedStyles,\n resolvedInlineStyles,\n useDefineForClassFields,\n compilationMode: pluginOptions.fastCompileMode,\n });\n\n // Track resource dependencies for HMR\n for (const dep of result.resourceDependencies) {\n resourceToSource.set(dep, id);\n }\n\n // Strip TypeScript-only syntax\n const stripped = vite.transformWithOxc\n ? await vite.transformWithOxc(result.code, id, {\n lang: 'ts',\n sourcemap: false,\n decorator: { legacy: false, emitDecoratorMetadata: false },\n })\n : await vite.transformWithEsbuild(result.code, id, {\n loader: 'ts',\n sourcemap: false,\n });\n let outputCode = stripped.code;\n\n // Append HMR code in dev mode\n if (watchMode && pluginOptions.liveReload) {\n const fileDeclarations = [...registry.values()].filter(\n (e) => e.fileName === id,\n );\n if (fileDeclarations.length > 0) {\n const localDepClassNames = fileDeclarations.map((e) => e.className);\n outputCode += generateHmrCode(fileDeclarations, localDepClassNames);\n }\n }\n\n return { code: outputCode, map: result.map };\n }\n\n function resolveTsConfigPath() {\n const { root, isProd, isLib } = tsConfigResolutionContext!;\n return getTsConfigPath(\n root,\n pluginOptions.tsconfigGetter(),\n isProd,\n pluginOptions.isTest,\n isLib,\n );\n }\n\n return {\n name: '@analogjs/vite-plugin-angular-fast-compile',\n enforce: 'pre' as const,\n async config(config, { command }) {\n watchMode = command === 'serve';\n const isProd =\n config.mode === 'production' ||\n process.env['NODE_ENV'] === 'production';\n\n tsConfigResolutionContext = {\n root: config.root || '.',\n isProd,\n isLib: !!config?.build?.lib,\n };\n\n const preliminaryTsConfigPath = resolveTsConfigPath();\n\n const depOptimizer = createDepOptimizerConfig({\n tsconfig: preliminaryTsConfigPath,\n isProd,\n jit: pluginOptions.jit,\n watchMode,\n isTest: pluginOptions.isTest,\n isAstroIntegration: pluginOptions.isAstroIntegration,\n });\n\n // No `resolve.conditions` extension here: the `style` condition is\n // scoped to `.css`-extension requests by\n // `cssExtensionStyleResolverPlugin`, registered once at the\n // `angular()` factory level (which is the only public entry point\n // that wires this plugin in).\n return {\n ...(vite.rolldownVersion ? { oxc: {} as any } : { esbuild: false }),\n ...depOptimizer,\n };\n },\n configResolved(config) {\n resolvedConfig = config;\n },\n configureServer(server) {\n // Watch for new .ts files and scan them into the registry. Use\n // the barrel-aware scanner so a newly added re-export entry\n // (`export * from './x'`) also expands its underlying directive\n // classes — otherwise the registry stays stale until restart.\n server.watcher.on('add', async (filePath) => {\n if (\n filePath.endsWith('.ts') &&\n !filePath.endsWith('.spec.ts') &&\n !filePath.endsWith('.d.ts')\n ) {\n await scanBarrelExports(filePath, new Set(), true);\n }\n });\n },\n async buildStart() {\n await initFastCompile();\n },\n async handleHotUpdate(ctx) {\n // Resource file changes → invalidate parent .ts module\n if (resourceToSource.has(ctx.file)) {\n const parentSource = resourceToSource.get(ctx.file)!;\n const parentModule = ctx.server.moduleGraph.getModuleById(parentSource);\n if (parentModule) {\n return [parentModule];\n }\n }\n\n if (TS_EXT_REGEX.test(ctx.file)) {\n const [fileId] = ctx.file.split('?');\n\n // Remove old entries from this file\n const oldEntries = [...registry.entries()]\n .filter(([_, v]) => v.fileName === fileId)\n .map(([k]) => k);\n for (const key of oldEntries) {\n registry.delete(key);\n }\n\n // Rescan the changed file via the barrel-aware scanner so an\n // edited barrel re-export picks up newly-referenced files.\n // Pass overwrite=true so updated metadata replaces stale\n // entries from the previous scan.\n await scanBarrelExports(fileId, new Set(), true);\n }\n\n // Let Vite handle the rest — the transform hook will recompile\n return ctx.modules;\n },\n resolveId(id, importer) {\n if (id.startsWith(VIRTUAL_RAW_PREFIX)) {\n return `\\0${id}`;\n }\n\n if (pluginOptions.jit && id.startsWith('angular:jit:')) {\n const filePath = normalizePath(\n resolve(dirname(importer as string), id.split(';')[1]),\n );\n if (id.includes(':style')) {\n markStylePathSafe(resolvedConfig, filePath);\n return filePath + '?inline';\n }\n return toVirtualRawId(filePath);\n }\n\n const rawRewrite = rewriteHtmlRawImport(id, importer);\n if (rawRewrite) return rawRewrite;\n\n // User `.scss?inline` / `.css?inline` imports: resolve and mark\n // safe so Vite's native CSS pipeline handles them.\n if (/\\.(css|scss|sass|less)\\?inline$/.test(id) && importer) {\n const filePath = id.split('?')[0];\n const resolved = isAbsolute(filePath)\n ? normalizePath(filePath)\n : normalizePath(resolve(dirname(importer), filePath));\n markStylePathSafe(resolvedConfig, resolved);\n return resolved + '?inline';\n }\n\n return undefined;\n },\n async load(id) {\n const rawModule = await loadVirtualRawModule(this, id);\n if (rawModule !== undefined) return rawModule;\n\n // Vitest fallback: module-runner can skip resolveId, so the bare\n // ?inline query reaches load. Mark safe and let Vite handle it.\n if (/\\.(css|scss|sass|less)\\?inline$/.test(id)) {\n markStylePathSafe(resolvedConfig, id.split('?')[0]);\n }\n\n return;\n },\n transform: {\n filter: {\n id: {\n include: [TS_EXT_REGEX],\n // `?raw` ids already carry Vite's native raw-loader output\n // (`export default \"<source>\"`). Recompiling them as Angular/TS\n // would strip that default export, so leave them to Vite (#2356).\n exclude: [\n /node_modules/,\n 'type=script',\n '@ng/component',\n /[?&]raw\\b/,\n ],\n },\n },\n async handler(code, id) {\n if (\n pluginOptions.transformFilter &&\n !(pluginOptions.transformFilter(code, id) ?? true)\n ) {\n return;\n }\n\n if (id.includes('.ts?')) {\n id = id.replace(/\\?(.*)/, '');\n }\n return handleFastCompileTransform(code, id);\n },\n },\n };\n}\n"],"mappings":"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"}
@@ -55,4 +55,8 @@ export declare function describeStylesheetContent(code: string): {
55
55
  * from disk up front, HMR always pushes the latest source content.
56
56
  */
57
57
  export declare function refreshStylesheetRegistryForFile(file: string, stylesheetRegistry?: AnalogStylesheetRegistry, stylePreprocessor?: StylePreprocessor): void;
58
- export declare function isTestWatchMode(args?: string[]): boolean;
58
+ /**
59
+ * Checks for vitest run from the command line
60
+ * @returns boolean
61
+ */
62
+ export declare function isTestWatchMode(args?): boolean;
@@ -118,8 +118,13 @@ function refreshStylesheetRegistryForFile(file, stylesheetRegistry, stylePreproc
118
118
  served: describeStylesheetContent(servedCss)
119
119
  });
120
120
  }
121
+ /**
122
+ * Checks for vitest run from the command line
123
+ * @returns boolean
124
+ */
121
125
  function isTestWatchMode(args = process.argv) {
122
126
  if (args.find((arg) => arg.includes("--run"))) return false;
127
+ if (args.includes("run")) return false;
123
128
  if (args.find((arg) => arg.includes("--no-run"))) return true;
124
129
  const hasWatch = args.find((arg) => arg.includes("watch"));
125
130
  if (hasWatch && ["false", "no"].some((neg) => hasWatch.includes(neg))) return false;
@@ -1 +1 @@
1
- {"version":3,"file":"compilation-shared.js","names":[],"sources":["../../../../src/lib/utils/compilation-shared.ts"],"sourcesContent":["/**\n * Shared utilities used by both angular-vite-plugin.ts and\n * compilation-api/compilation-api-plugin.ts.\n */\n\nimport { existsSync, readFileSync } from 'node:fs';\nimport { basename, isAbsolute, resolve } from 'node:path';\nimport { createHash } from 'node:crypto';\nimport { normalizePath } from 'vite';\n\nimport {\n AnalogStylesheetRegistry,\n preprocessStylesheetResult,\n rewriteRelativeCssImports,\n} from '../stylesheet-registry.js';\nimport { normalizeStylesheetDependencies } from '../style-preprocessor.js';\nimport type { StylePreprocessor } from '../style-preprocessor.js';\nimport type { FileReplacement } from '../plugins/file-replacements.plugin.js';\nimport { debugStylesV } from './debug.js';\n\nexport enum DiagnosticModes {\n None = 0,\n Option = 1 << 0,\n Syntactic = 1 << 1,\n Semantic = 1 << 2,\n All = Option | Syntactic | Semantic,\n}\n\nexport function injectViteIgnoreForHmrMetadata(code: string): string {\n let patched = code.replace(\n /\\bimport\\(([a-zA-Z_$][\\w$]*\\.\\u0275\\u0275getReplaceMetadataURL)/g,\n 'import(/* @vite-ignore */ $1',\n );\n\n if (patched === code) {\n patched = patched.replace(\n /import\\((\\S+getReplaceMetadataURL)/g,\n 'import(/* @vite-ignore */ $1',\n );\n }\n\n return patched;\n}\n\nexport function isIgnoredHmrFile(file: string): boolean {\n return file.endsWith('.tsbuildinfo');\n}\n\n/**\n * Convert Analog/Angular CLI-style file replacements into the flat record\n * expected by `AngularHostOptions.fileReplacements`.\n *\n * Only browser replacements (`{ replace, with }`) are converted. SSR-only\n * replacements (`{ replace, ssr }`) are left for the Vite runtime plugin to\n * handle — they should not be baked into the Angular compilation host because\n * that would apply them to both browser and server builds.\n *\n * Relative paths are resolved against `workspaceRoot` so that the host\n * receives the same absolute paths it would get from the Angular CLI.\n */\nexport function toAngularCompilationFileReplacements(\n replacements: FileReplacement[],\n workspaceRoot: string,\n): Record<string, string> | undefined {\n const mappedReplacements = replacements.flatMap((replacement) => {\n if (!('with' in replacement)) {\n return [];\n }\n\n return [\n [\n isAbsolute(replacement.replace)\n ? replacement.replace\n : resolve(workspaceRoot, replacement.replace),\n isAbsolute(replacement.with)\n ? replacement.with\n : resolve(workspaceRoot, replacement.with),\n ] as const,\n ];\n });\n\n return mappedReplacements.length\n ? Object.fromEntries(mappedReplacements)\n : undefined;\n}\n\n/**\n * Map Angular's `templateUpdates` (keyed by `encodedFilePath@ClassName`)\n * back to absolute file paths with their associated HMR code and component\n * class name.\n *\n * Angular's private Compilation API emits template update keys in the form\n * `encodeURIComponent(relativePath + '@' + className)`. We decode and resolve\n * them so the caller can look up updates by the same normalized absolute path\n * used elsewhere in the plugin (`outputFiles`, `classNames`, etc.).\n */\nexport function mapTemplateUpdatesToFiles(\n templateUpdates: ReadonlyMap<string, string> | undefined,\n): Map<\n string,\n {\n className: string;\n code: string;\n }\n> {\n const updatesByFile = new Map<string, { className: string; code: string }>();\n\n templateUpdates?.forEach((code, encodedUpdateId) => {\n const [file, className = ''] =\n decodeURIComponent(encodedUpdateId).split('@');\n const resolvedFile = normalizePath(resolve(process.cwd(), file));\n\n updatesByFile.set(resolvedFile, {\n className,\n code,\n });\n });\n\n return updatesByFile;\n}\n\nexport function describeStylesheetContent(code: string): {\n length: number;\n digest: string;\n preview: string;\n} {\n return {\n length: code.length,\n digest: createHash('sha256').update(code).digest('hex').slice(0, 12),\n preview: code.replace(/\\s+/g, ' ').trim().slice(0, 160),\n };\n}\n\n/**\n * Refreshes any already-served stylesheet records that map back to a changed\n * source file.\n *\n * This is the critical bridge for externalized Angular component styles during\n * HMR. Angular's resource watcher can notice that `/src/...component.css`\n * changed before Angular recompilation has had a chance to repopulate the\n * stylesheet registry. If we emit a CSS update against the existing virtual\n * stylesheet id without first refreshing the registry content, the browser gets\n * a hot update containing stale CSS. By rewriting the existing served records\n * from disk up front, HMR always pushes the latest source content.\n */\nexport function refreshStylesheetRegistryForFile(\n file: string,\n stylesheetRegistry?: AnalogStylesheetRegistry,\n stylePreprocessor?: StylePreprocessor,\n): void {\n const normalizedFile = normalizePath(file.split('?')[0]);\n if (!stylesheetRegistry || !existsSync(normalizedFile)) {\n return;\n }\n\n const publicIds = stylesheetRegistry.getPublicIdsForSource(normalizedFile);\n if (publicIds.length === 0) {\n return;\n }\n\n const rawCss = readFileSync(normalizedFile, 'utf-8');\n const preprocessed = preprocessStylesheetResult(\n rawCss,\n normalizedFile,\n stylePreprocessor,\n );\n const servedCss = rewriteRelativeCssImports(\n preprocessed.code,\n normalizedFile,\n );\n\n for (const publicId of publicIds) {\n stylesheetRegistry.registerServedStylesheet(\n {\n publicId,\n sourcePath: normalizedFile,\n originalCode: rawCss,\n normalizedCode: servedCss,\n dependencies: normalizeStylesheetDependencies(\n preprocessed.dependencies,\n ),\n diagnostics: preprocessed.diagnostics,\n tags: preprocessed.tags,\n },\n [\n normalizedFile,\n normalizePath(normalizedFile),\n basename(normalizedFile),\n normalizedFile.replace(/^\\//, ''),\n ],\n );\n }\n\n debugStylesV('stylesheet registry refreshed from source file', {\n file: normalizedFile,\n publicIds,\n dependencies: preprocessed.dependencies,\n diagnostics: preprocessed.diagnostics,\n tags: preprocessed.tags,\n source: describeStylesheetContent(rawCss),\n served: describeStylesheetContent(servedCss),\n });\n}\n\nexport function isTestWatchMode(args: string[] = process.argv): boolean {\n // vitest --run\n const hasRun = args.find((arg) => arg.includes('--run'));\n if (hasRun) {\n return false;\n }\n\n // vitest --no-run\n const hasNoRun = args.find((arg) => arg.includes('--no-run'));\n if (hasNoRun) {\n return true;\n }\n\n // check for --watch=false or --no-watch\n const hasWatch = args.find((arg) => arg.includes('watch'));\n if (hasWatch && ['false', 'no'].some((neg) => hasWatch.includes(neg))) {\n return false;\n }\n\n // check for --watch false\n const watchIndex = args.findIndex((arg) => arg.includes('watch'));\n const watchArg = args[watchIndex + 1];\n if (watchArg && watchArg === 'false') {\n return false;\n }\n\n return true;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"compilation-shared.js","names":[],"sources":["../../../../src/lib/utils/compilation-shared.ts"],"sourcesContent":["/**\n * Shared utilities used by both angular-vite-plugin.ts and\n * compilation-api/compilation-api-plugin.ts.\n */\n\nimport { existsSync, readFileSync } from 'node:fs';\nimport { basename, isAbsolute, resolve } from 'node:path';\nimport { createHash } from 'node:crypto';\nimport { normalizePath } from 'vite';\n\nimport {\n AnalogStylesheetRegistry,\n preprocessStylesheetResult,\n rewriteRelativeCssImports,\n} from '../stylesheet-registry.js';\nimport { normalizeStylesheetDependencies } from '../style-preprocessor.js';\nimport type { StylePreprocessor } from '../style-preprocessor.js';\nimport type { FileReplacement } from '../plugins/file-replacements.plugin.js';\nimport { debugStylesV } from './debug.js';\n\nexport enum DiagnosticModes {\n None = 0,\n Option = 1 << 0,\n Syntactic = 1 << 1,\n Semantic = 1 << 2,\n All = Option | Syntactic | Semantic,\n}\n\nexport function injectViteIgnoreForHmrMetadata(code: string): string {\n let patched = code.replace(\n /\\bimport\\(([a-zA-Z_$][\\w$]*\\.\\u0275\\u0275getReplaceMetadataURL)/g,\n 'import(/* @vite-ignore */ $1',\n );\n\n if (patched === code) {\n patched = patched.replace(\n /import\\((\\S+getReplaceMetadataURL)/g,\n 'import(/* @vite-ignore */ $1',\n );\n }\n\n return patched;\n}\n\nexport function isIgnoredHmrFile(file: string): boolean {\n return file.endsWith('.tsbuildinfo');\n}\n\n/**\n * Convert Analog/Angular CLI-style file replacements into the flat record\n * expected by `AngularHostOptions.fileReplacements`.\n *\n * Only browser replacements (`{ replace, with }`) are converted. SSR-only\n * replacements (`{ replace, ssr }`) are left for the Vite runtime plugin to\n * handle — they should not be baked into the Angular compilation host because\n * that would apply them to both browser and server builds.\n *\n * Relative paths are resolved against `workspaceRoot` so that the host\n * receives the same absolute paths it would get from the Angular CLI.\n */\nexport function toAngularCompilationFileReplacements(\n replacements: FileReplacement[],\n workspaceRoot: string,\n): Record<string, string> | undefined {\n const mappedReplacements = replacements.flatMap((replacement) => {\n if (!('with' in replacement)) {\n return [];\n }\n\n return [\n [\n isAbsolute(replacement.replace)\n ? replacement.replace\n : resolve(workspaceRoot, replacement.replace),\n isAbsolute(replacement.with)\n ? replacement.with\n : resolve(workspaceRoot, replacement.with),\n ] as const,\n ];\n });\n\n return mappedReplacements.length\n ? Object.fromEntries(mappedReplacements)\n : undefined;\n}\n\n/**\n * Map Angular's `templateUpdates` (keyed by `encodedFilePath@ClassName`)\n * back to absolute file paths with their associated HMR code and component\n * class name.\n *\n * Angular's private Compilation API emits template update keys in the form\n * `encodeURIComponent(relativePath + '@' + className)`. We decode and resolve\n * them so the caller can look up updates by the same normalized absolute path\n * used elsewhere in the plugin (`outputFiles`, `classNames`, etc.).\n */\nexport function mapTemplateUpdatesToFiles(\n templateUpdates: ReadonlyMap<string, string> | undefined,\n): Map<\n string,\n {\n className: string;\n code: string;\n }\n> {\n const updatesByFile = new Map<string, { className: string; code: string }>();\n\n templateUpdates?.forEach((code, encodedUpdateId) => {\n const [file, className = ''] =\n decodeURIComponent(encodedUpdateId).split('@');\n const resolvedFile = normalizePath(resolve(process.cwd(), file));\n\n updatesByFile.set(resolvedFile, {\n className,\n code,\n });\n });\n\n return updatesByFile;\n}\n\nexport function describeStylesheetContent(code: string): {\n length: number;\n digest: string;\n preview: string;\n} {\n return {\n length: code.length,\n digest: createHash('sha256').update(code).digest('hex').slice(0, 12),\n preview: code.replace(/\\s+/g, ' ').trim().slice(0, 160),\n };\n}\n\n/**\n * Refreshes any already-served stylesheet records that map back to a changed\n * source file.\n *\n * This is the critical bridge for externalized Angular component styles during\n * HMR. Angular's resource watcher can notice that `/src/...component.css`\n * changed before Angular recompilation has had a chance to repopulate the\n * stylesheet registry. If we emit a CSS update against the existing virtual\n * stylesheet id without first refreshing the registry content, the browser gets\n * a hot update containing stale CSS. By rewriting the existing served records\n * from disk up front, HMR always pushes the latest source content.\n */\nexport function refreshStylesheetRegistryForFile(\n file: string,\n stylesheetRegistry?: AnalogStylesheetRegistry,\n stylePreprocessor?: StylePreprocessor,\n): void {\n const normalizedFile = normalizePath(file.split('?')[0]);\n if (!stylesheetRegistry || !existsSync(normalizedFile)) {\n return;\n }\n\n const publicIds = stylesheetRegistry.getPublicIdsForSource(normalizedFile);\n if (publicIds.length === 0) {\n return;\n }\n\n const rawCss = readFileSync(normalizedFile, 'utf-8');\n const preprocessed = preprocessStylesheetResult(\n rawCss,\n normalizedFile,\n stylePreprocessor,\n );\n const servedCss = rewriteRelativeCssImports(\n preprocessed.code,\n normalizedFile,\n );\n\n for (const publicId of publicIds) {\n stylesheetRegistry.registerServedStylesheet(\n {\n publicId,\n sourcePath: normalizedFile,\n originalCode: rawCss,\n normalizedCode: servedCss,\n dependencies: normalizeStylesheetDependencies(\n preprocessed.dependencies,\n ),\n diagnostics: preprocessed.diagnostics,\n tags: preprocessed.tags,\n },\n [\n normalizedFile,\n normalizePath(normalizedFile),\n basename(normalizedFile),\n normalizedFile.replace(/^\\//, ''),\n ],\n );\n }\n\n debugStylesV('stylesheet registry refreshed from source file', {\n file: normalizedFile,\n publicIds,\n dependencies: preprocessed.dependencies,\n diagnostics: preprocessed.diagnostics,\n tags: preprocessed.tags,\n source: describeStylesheetContent(rawCss),\n served: describeStylesheetContent(servedCss),\n });\n}\n\n/**\n * Checks for vitest run from the command line\n * @returns boolean\n */\nexport function isTestWatchMode(args = process.argv): boolean {\n // vitest --run\n const hasRun = args.find((arg) => arg.includes('--run'));\n if (hasRun) {\n return false;\n }\n\n // vitest run\n if (args.includes('run')) {\n return false;\n }\n\n // vitest --no-run\n const hasNoRun = args.find((arg) => arg.includes('--no-run'));\n if (hasNoRun) {\n return true;\n }\n\n // check for --watch=false or --no-watch\n const hasWatch = args.find((arg) => arg.includes('watch'));\n if (hasWatch && ['false', 'no'].some((neg) => hasWatch.includes(neg))) {\n return false;\n }\n\n // check for --watch false\n const watchIndex = args.findIndex((arg) => arg.includes('watch'));\n const watchArg = args[watchIndex + 1];\n if (watchArg && watchArg === 'false') {\n return false;\n }\n\n return true;\n}\n"],"mappings":"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"}
@@ -45,7 +45,7 @@ function createDepOptimizerConfig(opts) {
45
45
  advancedOptimizations: opts.isProd,
46
46
  jit: opts.jit,
47
47
  incremental: opts.watchMode
48
- })] };
48
+ }, opts.isTest, !opts.isAstroIntegration)] };
49
49
  const esbuildOptions = {
50
50
  plugins: [createCompilerPlugin({
51
51
  tsconfig: opts.tsconfig,
@@ -1 +1 @@
1
- {"version":3,"file":"plugin-config.js","names":[],"sources":["../../../../src/lib/utils/plugin-config.ts"],"sourcesContent":["import { existsSync } from 'node:fs';\nimport { isAbsolute, resolve } from 'node:path';\nimport * as vite from 'vite';\n\nimport {\n createCompilerPlugin,\n createRolldownCompilerPlugin,\n} from '../compiler-plugin.js';\n\n/**\n * TypeScript file extension regex\n * Match .ts / .cts / .mts extensions with an optional ?query suffix.\n * Reject .tsx — and any other `.ts<letter>…` extension like .tsrx — via\n * a negative-lookahead on a following ASCII letter, so only genuine TS\n * files pass.\n *\n * Previous form `/\\.[cm]?(ts)[^x]?\\??/` was intended to exclude `.tsx`\n * specifically (`[^x]?` = not-an-x), but the `?` quantifier also allows\n * zero characters, and any non-`x` letter was admitted — so `.tsrx`\n * and similar extensions matched by accident.\n */\nexport const TS_EXT_REGEX = /\\.[cm]?ts(?![a-z])/;\n\nexport interface TsConfigResolutionContext {\n root: string;\n isProd: boolean;\n isLib: boolean;\n}\n\nexport function getTsConfigPath(\n root: string,\n tsconfig: string,\n isProd: boolean,\n isTest: boolean,\n isLib: boolean,\n) {\n if (tsconfig && isAbsolute(tsconfig)) {\n if (!existsSync(tsconfig)) {\n console.error(\n `[@analogjs/vite-plugin-angular]: Unable to resolve tsconfig at ${tsconfig}. This causes compilation issues. Check the path or set the \"tsconfig\" property with an absolute path.`,\n );\n }\n\n return tsconfig;\n }\n\n let tsconfigFilePath = './tsconfig.app.json';\n\n if (isLib) {\n tsconfigFilePath = isProd\n ? './tsconfig.lib.prod.json'\n : './tsconfig.lib.json';\n }\n\n if (isTest) {\n tsconfigFilePath = './tsconfig.spec.json';\n }\n\n if (tsconfig) {\n tsconfigFilePath = tsconfig;\n }\n\n const resolvedPath = resolve(root, tsconfigFilePath);\n\n if (!existsSync(resolvedPath)) {\n console.error(\n `[@analogjs/vite-plugin-angular]: Unable to resolve tsconfig at ${resolvedPath}. This causes compilation issues. Check the path or set the \"tsconfig\" property with an absolute path.`,\n );\n }\n\n return resolvedPath;\n}\n\nexport function createTsConfigGetter(\n tsconfigOrGetter?: string | (() => string),\n) {\n if (typeof tsconfigOrGetter === 'function') {\n return tsconfigOrGetter;\n }\n\n return () => tsconfigOrGetter || '';\n}\n\nexport interface DepOptimizerOptions {\n tsconfig: string;\n isProd: boolean;\n jit: boolean;\n watchMode: boolean;\n isTest: boolean;\n isAstroIntegration: boolean;\n}\n\nexport function createDepOptimizerConfig(opts: DepOptimizerOptions) {\n const defineOptions = {\n ngJitMode: 'false',\n ngI18nClosureMode: 'false',\n ...(opts.watchMode ? {} : { ngDevMode: 'false' }),\n };\n\n const rolldownOptions: vite.DepOptimizationOptions['rolldownOptions'] = {\n plugins: [\n createRolldownCompilerPlugin({\n tsconfig: opts.tsconfig,\n sourcemap: !opts.isProd,\n advancedOptimizations: opts.isProd,\n jit: opts.jit,\n incremental: opts.watchMode,\n }),\n ],\n };\n\n const esbuildOptions: vite.DepOptimizationOptions['esbuildOptions'] = {\n plugins: [\n createCompilerPlugin(\n {\n tsconfig: opts.tsconfig,\n sourcemap: !opts.isProd,\n advancedOptimizations: opts.isProd,\n jit: opts.jit,\n incremental: opts.watchMode,\n },\n opts.isTest,\n !opts.isAstroIntegration,\n ),\n ],\n define: defineOptions,\n };\n\n // No top-level `resolve` block: the `style` package-export condition\n // is now scoped to `.css`-extension requests via\n // `cssExtensionStyleResolverPlugin`, so this dep optimizer config no\n // longer needs to leak it into Vite's global `resolve.conditions`.\n return {\n optimizeDeps: {\n include: ['rxjs/operators', 'rxjs'],\n exclude: ['@angular/platform-server'],\n ...(vite.rolldownVersion ? { rolldownOptions } : { esbuildOptions }),\n },\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAqBA,IAAa,eAAe;AAQ5B,SAAgB,gBACd,MACA,UACA,QACA,QACA,OACA;AACA,KAAI,YAAY,WAAW,SAAS,EAAE;AACpC,MAAI,CAAC,WAAW,SAAS,CACvB,SAAQ,MACN,kEAAkE,SAAS,wGAC5E;AAGH,SAAO;;CAGT,IAAI,mBAAmB;AAEvB,KAAI,MACF,oBAAmB,SACf,6BACA;AAGN,KAAI,OACF,oBAAmB;AAGrB,KAAI,SACF,oBAAmB;CAGrB,MAAM,eAAe,QAAQ,MAAM,iBAAiB;AAEpD,KAAI,CAAC,WAAW,aAAa,CAC3B,SAAQ,MACN,kEAAkE,aAAa,wGAChF;AAGH,QAAO;;AAGT,SAAgB,qBACd,kBACA;AACA,KAAI,OAAO,qBAAqB,WAC9B,QAAO;AAGT,cAAa,oBAAoB;;AAYnC,SAAgB,yBAAyB,MAA2B;CAClE,MAAM,gBAAgB;EACpB,WAAW;EACX,mBAAmB;EACnB,GAAI,KAAK,YAAY,EAAE,GAAG,EAAE,WAAW,SAAS;EACjD;CAED,MAAM,kBAAkE,EACtE,SAAS,CACP,6BAA6B;EAC3B,UAAU,KAAK;EACf,WAAW,CAAC,KAAK;EACjB,uBAAuB,KAAK;EAC5B,KAAK,KAAK;EACV,aAAa,KAAK;EACnB,CAAC,CACH,EACF;CAED,MAAM,iBAAgE;EACpE,SAAS,CACP,qBACE;GACE,UAAU,KAAK;GACf,WAAW,CAAC,KAAK;GACjB,uBAAuB,KAAK;GAC5B,KAAK,KAAK;GACV,aAAa,KAAK;GACnB,EACD,KAAK,QACL,CAAC,KAAK,mBACP,CACF;EACD,QAAQ;EACT;AAMD,QAAO,EACL,cAAc;EACZ,SAAS,CAAC,kBAAkB,OAAO;EACnC,SAAS,CAAC,2BAA2B;EACrC,GAAI,KAAK,kBAAkB,EAAE,iBAAiB,GAAG,EAAE,gBAAgB;EACpE,EACF"}
1
+ {"version":3,"file":"plugin-config.js","names":[],"sources":["../../../../src/lib/utils/plugin-config.ts"],"sourcesContent":["import { existsSync } from 'node:fs';\nimport { isAbsolute, resolve } from 'node:path';\nimport * as vite from 'vite';\n\nimport {\n createCompilerPlugin,\n createRolldownCompilerPlugin,\n} from '../compiler-plugin.js';\n\n/**\n * TypeScript file extension regex\n * Match .ts / .cts / .mts extensions with an optional ?query suffix.\n * Reject .tsx — and any other `.ts<letter>…` extension like .tsrx — via\n * a negative-lookahead on a following ASCII letter, so only genuine TS\n * files pass.\n *\n * Previous form `/\\.[cm]?(ts)[^x]?\\??/` was intended to exclude `.tsx`\n * specifically (`[^x]?` = not-an-x), but the `?` quantifier also allows\n * zero characters, and any non-`x` letter was admitted — so `.tsrx`\n * and similar extensions matched by accident.\n */\nexport const TS_EXT_REGEX = /\\.[cm]?ts(?![a-z])/;\n\nexport interface TsConfigResolutionContext {\n root: string;\n isProd: boolean;\n isLib: boolean;\n}\n\nexport function getTsConfigPath(\n root: string,\n tsconfig: string,\n isProd: boolean,\n isTest: boolean,\n isLib: boolean,\n) {\n if (tsconfig && isAbsolute(tsconfig)) {\n if (!existsSync(tsconfig)) {\n console.error(\n `[@analogjs/vite-plugin-angular]: Unable to resolve tsconfig at ${tsconfig}. This causes compilation issues. Check the path or set the \"tsconfig\" property with an absolute path.`,\n );\n }\n\n return tsconfig;\n }\n\n let tsconfigFilePath = './tsconfig.app.json';\n\n if (isLib) {\n tsconfigFilePath = isProd\n ? './tsconfig.lib.prod.json'\n : './tsconfig.lib.json';\n }\n\n if (isTest) {\n tsconfigFilePath = './tsconfig.spec.json';\n }\n\n if (tsconfig) {\n tsconfigFilePath = tsconfig;\n }\n\n const resolvedPath = resolve(root, tsconfigFilePath);\n\n if (!existsSync(resolvedPath)) {\n console.error(\n `[@analogjs/vite-plugin-angular]: Unable to resolve tsconfig at ${resolvedPath}. This causes compilation issues. Check the path or set the \"tsconfig\" property with an absolute path.`,\n );\n }\n\n return resolvedPath;\n}\n\nexport function createTsConfigGetter(\n tsconfigOrGetter?: string | (() => string),\n) {\n if (typeof tsconfigOrGetter === 'function') {\n return tsconfigOrGetter;\n }\n\n return () => tsconfigOrGetter || '';\n}\n\nexport interface DepOptimizerOptions {\n tsconfig: string;\n isProd: boolean;\n jit: boolean;\n watchMode: boolean;\n isTest: boolean;\n isAstroIntegration: boolean;\n}\n\nexport function createDepOptimizerConfig(opts: DepOptimizerOptions) {\n const defineOptions = {\n ngJitMode: 'false',\n ngI18nClosureMode: 'false',\n ...(opts.watchMode ? {} : { ngDevMode: 'false' }),\n };\n\n const rolldownOptions: vite.DepOptimizationOptions['rolldownOptions'] = {\n plugins: [\n createRolldownCompilerPlugin(\n {\n tsconfig: opts.tsconfig,\n sourcemap: !opts.isProd,\n advancedOptimizations: opts.isProd,\n jit: opts.jit,\n incremental: opts.watchMode,\n },\n opts.isTest,\n !opts.isAstroIntegration,\n ),\n ],\n };\n\n const esbuildOptions: vite.DepOptimizationOptions['esbuildOptions'] = {\n plugins: [\n createCompilerPlugin(\n {\n tsconfig: opts.tsconfig,\n sourcemap: !opts.isProd,\n advancedOptimizations: opts.isProd,\n jit: opts.jit,\n incremental: opts.watchMode,\n },\n opts.isTest,\n !opts.isAstroIntegration,\n ),\n ],\n define: defineOptions,\n };\n\n // No top-level `resolve` block: the `style` package-export condition\n // is now scoped to `.css`-extension requests via\n // `cssExtensionStyleResolverPlugin`, so this dep optimizer config no\n // longer needs to leak it into Vite's global `resolve.conditions`.\n return {\n optimizeDeps: {\n include: ['rxjs/operators', 'rxjs'],\n exclude: ['@angular/platform-server'],\n ...(vite.rolldownVersion ? { rolldownOptions } : { esbuildOptions }),\n },\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAqBA,IAAa,eAAe;AAQ5B,SAAgB,gBACd,MACA,UACA,QACA,QACA,OACA;AACA,KAAI,YAAY,WAAW,SAAS,EAAE;AACpC,MAAI,CAAC,WAAW,SAAS,CACvB,SAAQ,MACN,kEAAkE,SAAS,wGAC5E;AAGH,SAAO;;CAGT,IAAI,mBAAmB;AAEvB,KAAI,MACF,oBAAmB,SACf,6BACA;AAGN,KAAI,OACF,oBAAmB;AAGrB,KAAI,SACF,oBAAmB;CAGrB,MAAM,eAAe,QAAQ,MAAM,iBAAiB;AAEpD,KAAI,CAAC,WAAW,aAAa,CAC3B,SAAQ,MACN,kEAAkE,aAAa,wGAChF;AAGH,QAAO;;AAGT,SAAgB,qBACd,kBACA;AACA,KAAI,OAAO,qBAAqB,WAC9B,QAAO;AAGT,cAAa,oBAAoB;;AAYnC,SAAgB,yBAAyB,MAA2B;CAClE,MAAM,gBAAgB;EACpB,WAAW;EACX,mBAAmB;EACnB,GAAI,KAAK,YAAY,EAAE,GAAG,EAAE,WAAW,SAAS;EACjD;CAED,MAAM,kBAAkE,EACtE,SAAS,CACP,6BACE;EACE,UAAU,KAAK;EACf,WAAW,CAAC,KAAK;EACjB,uBAAuB,KAAK;EAC5B,KAAK,KAAK;EACV,aAAa,KAAK;EACnB,EACD,KAAK,QACL,CAAC,KAAK,mBACP,CACF,EACF;CAED,MAAM,iBAAgE;EACpE,SAAS,CACP,qBACE;GACE,UAAU,KAAK;GACf,WAAW,CAAC,KAAK;GACjB,uBAAuB,KAAK;GAC5B,KAAK,KAAK;GACV,aAAa,KAAK;GACnB,EACD,KAAK,QACL,CAAC,KAAK,mBACP,CACF;EACD,QAAQ;EACT;AAMD,QAAO,EACL,cAAc;EACZ,SAAS,CAAC,kBAAkB,OAAO;EACnC,SAAS,CAAC,2BAA2B;EACrC,GAAI,KAAK,kBAAkB,EAAE,iBAAiB,GAAG,EAAE,gBAAgB;EACpE,EACF"}