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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/package.json +1 -1
  2. package/src/lib/angular-vite-plugin.js +9 -3
  3. package/src/lib/angular-vite-plugin.js.map +1 -1
  4. package/src/lib/compiler/compile.d.ts +6 -0
  5. package/src/lib/compiler/compile.js +68 -9
  6. package/src/lib/compiler/compile.js.map +1 -1
  7. package/src/lib/compiler/constants.d.ts +6 -0
  8. package/src/lib/compiler/constants.js +7 -1
  9. package/src/lib/compiler/constants.js.map +1 -1
  10. package/src/lib/compiler/defer.js +1 -1
  11. package/src/lib/compiler/dts-reader.d.ts +13 -3
  12. package/src/lib/compiler/dts-reader.js +38 -8
  13. package/src/lib/compiler/dts-reader.js.map +1 -1
  14. package/src/lib/compiler/index.d.ts +2 -1
  15. package/src/lib/compiler/index.js +1 -0
  16. package/src/lib/compiler/jit-transform.js +1 -1
  17. package/src/lib/compiler/jit-transform.js.map +1 -1
  18. package/src/lib/compiler/js-emitter.js +2 -2
  19. package/src/lib/compiler/js-emitter.js.map +1 -1
  20. package/src/lib/compiler/metadata.d.ts +0 -9
  21. package/src/lib/compiler/metadata.js +67 -6
  22. package/src/lib/compiler/metadata.js.map +1 -1
  23. package/src/lib/compiler/registry.d.ts +8 -1
  24. package/src/lib/compiler/registry.js +15 -3
  25. package/src/lib/compiler/registry.js.map +1 -1
  26. package/src/lib/compiler/resource-inliner.d.ts +27 -5
  27. package/src/lib/compiler/resource-inliner.js +138 -60
  28. package/src/lib/compiler/resource-inliner.js.map +1 -1
  29. package/src/lib/compiler/style-ast.d.ts +2 -1
  30. package/src/lib/compiler/style-ast.js +2 -2
  31. package/src/lib/compiler/style-ast.js.map +1 -1
  32. package/src/lib/compiler/type-elision.d.ts +5 -3
  33. package/src/lib/compiler/type-elision.js +8 -8
  34. package/src/lib/compiler/type-elision.js.map +1 -1
  35. package/src/lib/compiler-plugin.d.ts +3 -2
  36. package/src/lib/compiler-plugin.js +4 -4
  37. package/src/lib/compiler-plugin.js.map +1 -1
  38. package/src/lib/component-resolvers.js +4 -5
  39. package/src/lib/component-resolvers.js.map +1 -1
  40. package/src/lib/fast-compile-plugin.js +136 -23
  41. package/src/lib/fast-compile-plugin.js.map +1 -1
  42. package/src/lib/router-plugin.js +13 -1
  43. package/src/lib/router-plugin.js.map +1 -1
  44. package/src/lib/utils/plugin-config.js +6 -3
  45. package/src/lib/utils/plugin-config.js.map +1 -1
  46. package/src/lib/utils/transform-cache.d.ts +43 -0
  47. package/src/lib/utils/transform-cache.js +97 -0
  48. package/src/lib/utils/transform-cache.js.map +1 -0
@@ -33,13 +33,4 @@ export declare function detectSignals(classNode: any, sourceCode: string): {};
33
33
  * @ContentChild, @ViewChildren, @ContentChildren, @HostBinding, @HostListener.
34
34
  */
35
35
  export declare function detectFieldDecorators(classNode: any, sourceCode: string): {};
36
- /**
37
- * Analyze constructor parameters for dependency injection.
38
- * Returns:
39
- * - R3DependencyMetadata[] for normal constructors
40
- * - null if class extends another without own constructor (use inherited factory)
41
- * - 'invalid' if any parameter has a type-only import token
42
- *
43
- * Accepts an OXC ClassDeclaration node and the original source string.
44
- */
45
36
  export declare function extractConstructorDeps(classNode: any, sourceCode: string, typeOnlyImports: Set<string>): any[] | "invalid" | null;
@@ -210,8 +210,6 @@ function extractMetadata(dec, sourceCode, stringConsts) {
210
210
  }
211
211
  break;
212
212
  case "imports":
213
- case "providers":
214
- case "viewProviders":
215
213
  case "animations":
216
214
  case "rawImports":
217
215
  case "declarations":
@@ -219,6 +217,11 @@ function extractMetadata(dec, sourceCode, stringConsts) {
219
217
  case "bootstrap":
220
218
  if (valNode.type === "ArrayExpression") meta[key] = (valNode.elements || []).map((e) => new o.WrappedNodeExpr(unwrapForwardRefOxc(e)));
221
219
  break;
220
+ case "providers":
221
+ case "viewProviders":
222
+ if (valNode.type === "ArrayExpression") meta[key] = (valNode.elements || []).map((e) => new o.WrappedNodeExpr(unwrapForwardRefOxc(e)));
223
+ else meta[key] = new o.WrappedNodeExpr(valNode);
224
+ break;
222
225
  case "useClass":
223
226
  case "useExisting":
224
227
  case "useValue": {
@@ -233,6 +236,9 @@ function extractMetadata(dec, sourceCode, stringConsts) {
233
236
  case "useFactory":
234
237
  meta[key] = new o.WrappedNodeExpr(valNode);
235
238
  break;
239
+ case "deps":
240
+ if (valNode.type === "ArrayExpression") meta.deps = extractInjectableDeps(valNode, sourceCode);
241
+ break;
236
242
  case "autoProvided":
237
243
  meta.autoProvided = valText === "true";
238
244
  break;
@@ -547,15 +553,66 @@ function detectFieldDecorators(classNode, sourceCode) {
547
553
  *
548
554
  * Accepts an OXC ClassDeclaration node and the original source string.
549
555
  */
556
+ /**
557
+ * Parse an `@Injectable({ deps: [...] })` dependency list into
558
+ * R3DependencyMetadata. Each element is either a bare token expression or a
559
+ * flag array combining DI modifiers with the token, e.g.
560
+ * `[new Optional(), new SkipSelf(), Token]` or `[new Inject(TOKEN)]`.
561
+ */
562
+ function extractInjectableDeps(depsNode, sourceCode) {
563
+ const deps = [];
564
+ for (const el of depsNode.elements || []) {
565
+ if (!el) continue;
566
+ let tokenNode = el;
567
+ let optional = false, self = false, skipSelf = false, host = false;
568
+ if (el.type === "ArrayExpression") {
569
+ tokenNode = null;
570
+ for (const item of el.elements || []) {
571
+ if (!item) continue;
572
+ if (item.type === "NewExpression") switch (item.callee?.name) {
573
+ case "Optional":
574
+ optional = true;
575
+ continue;
576
+ case "Self":
577
+ self = true;
578
+ continue;
579
+ case "SkipSelf":
580
+ skipSelf = true;
581
+ continue;
582
+ case "Host":
583
+ host = true;
584
+ continue;
585
+ case "Inject":
586
+ tokenNode = item.arguments?.[0] ?? null;
587
+ continue;
588
+ }
589
+ tokenNode = item;
590
+ }
591
+ }
592
+ const resolvedToken = tokenNode ? unwrapForwardRefOxc(tokenNode) : null;
593
+ const tokenStr = resolvedToken ? sourceCode.slice(resolvedToken.start, resolvedToken.end) : null;
594
+ deps.push({
595
+ token: tokenStr ? new o.WrappedNodeExpr(tokenStr) : new o.LiteralExpr(null),
596
+ attributeNameType: null,
597
+ host,
598
+ optional,
599
+ self,
600
+ skipSelf
601
+ });
602
+ }
603
+ return deps;
604
+ }
550
605
  function extractConstructorDeps(classNode, sourceCode, typeOnlyImports) {
551
606
  const hasSuper = (classNode.superClass ? [classNode.superClass] : []).length > 0;
552
- const ctor = (classNode.body?.body || []).find((m) => m.type === "MethodDefinition" && m.kind === "constructor");
607
+ const ctors = (classNode.body?.body || []).filter((m) => m.type === "MethodDefinition" && m.kind === "constructor");
608
+ const ctor = ctors.find((m) => m.value?.body != null) ?? ctors[0];
553
609
  if (!ctor) return hasSuper ? null : [];
554
610
  const params = ctor.value?.params?.items || ctor.value?.params || [];
555
611
  const deps = [];
556
612
  let invalid = false;
557
613
  for (const param of params) {
558
614
  let token = null;
615
+ let attributeToken = null;
559
616
  let attributeNameType = null;
560
617
  let host = false, optional = false, self = false, skipSelf = false;
561
618
  const actualParam = param.type === "TSParameterProperty" ? param.parameter : param;
@@ -617,14 +674,18 @@ function extractConstructorDeps(classNode, sourceCode, typeOnlyImports) {
617
674
  if (args.length > 0) {
618
675
  const sv = stringValue(args[0]);
619
676
  if (sv !== null) {
677
+ attributeToken = new o.LiteralExpr(sv);
620
678
  attributeNameType = new o.LiteralExpr(sv);
621
- token = "";
679
+ } else {
680
+ attributeToken = new o.WrappedNodeExpr(args[0]);
681
+ attributeNameType = new o.LiteralExpr("unknown");
622
682
  }
683
+ token = "";
623
684
  }
624
685
  break;
625
686
  }
626
687
  }
627
- if (!token && !attributeNameType) {
688
+ if (!token && !attributeToken) {
628
689
  invalid = true;
629
690
  continue;
630
691
  }
@@ -633,7 +694,7 @@ function extractConstructorDeps(classNode, sourceCode, typeOnlyImports) {
633
694
  continue;
634
695
  }
635
696
  deps.push({
636
- token: token ? new o.WrappedNodeExpr(token) : new o.LiteralExpr(null),
697
+ token: attributeToken ?? (token ? new o.WrappedNodeExpr(token) : new o.LiteralExpr(null)),
637
698
  attributeNameType,
638
699
  host,
639
700
  optional,
@@ -1 +1 @@
1
- {"version":3,"file":"metadata.js","names":[],"sources":["../../../../src/lib/compiler/metadata.ts"],"sourcesContent":["import * as o from '@angular/compiler';\nimport { unwrapForwardRefOxc } from './utils.js';\nimport { FIELD_DECORATORS, SIGNAL_APIS } from './constants.js';\n\nfunction getCallApi(call: any): { api: string; required: boolean } | null {\n const callee = call.callee;\n if (!callee) return null;\n\n if (callee.type === 'Identifier') {\n return { api: callee.name, required: false };\n }\n\n if (\n (callee.type === 'StaticMemberExpression' ||\n callee.type === 'MemberExpression') &&\n callee.object?.type === 'Identifier' &&\n callee.property?.name === 'required'\n ) {\n return { api: callee.object.name, required: true };\n }\n\n return null;\n}\n\n/**\n * Extract the string value from an OXC string literal or template literal node.\n *\n * If `consts` is provided, interpolated template literals (e.g.\n * `\\`hello ${NAME}\\``) are resolved when every `${...}` expression is a bare\n * `Identifier` whose name is present in the map. This lets metadata fields\n * such as `template:` reference module-level string constants via JS\n * template-literal interpolation:\n *\n * const tw = `text-zinc-700 hover:text-zinc-900`;\n * @Component({ template: `<a class=\"${tw}\">x</a>` })\n *\n * Returns `null` if the node is not statically resolvable.\n */\nfunction stringValue(node: any, consts?: Map<string, string>): string | null {\n if (node?.type === 'StringLiteral') return node.value;\n if (node?.type === 'Literal' && typeof node.value === 'string')\n return node.value;\n if (node?.type === 'TemplateLiteral') {\n const quasis = node.quasis ?? [];\n const expressions = node.expressions ?? [];\n if (expressions.length === 0) {\n return quasis[0]?.value?.cooked ?? null;\n }\n if (!consts) return null;\n let result = '';\n for (let i = 0; i < quasis.length; i++) {\n const cooked = quasis[i]?.value?.cooked;\n if (cooked == null) return null;\n result += cooked;\n if (i < expressions.length) {\n const expr = expressions[i];\n if (expr?.type !== 'Identifier') return null;\n const resolved = consts.get(expr.name);\n if (resolved == null) return null;\n result += resolved;\n }\n }\n return result;\n }\n return null;\n}\n\n/** Check if an OXC node is a string-like literal. */\nfunction isStringLike(node: any, consts?: Map<string, string>): boolean {\n return stringValue(node, consts) !== null;\n}\n\n/**\n * Walk the top-level statements of an OXC program and collect a map of\n * statically-resolvable string-valued `const NAME = ...` declarations.\n *\n * Used so decorator metadata fields like `template:` can reference\n * module-level Tailwind class chains (or any other string constants) via\n * JS template-literal interpolation. Resolution is iterative: a const may\n * reference earlier-resolved consts via `${other}` interpolation.\n *\n * Only `const` declarations are considered. Non-string initializers,\n * function calls, member access, and any expression that cannot be reduced\n * to a string at parse time are ignored.\n */\nexport function collectStringConstants(oxcProgram: any): Map<string, string> {\n const rawDecls = new Map<string, any>();\n for (const stmt of oxcProgram?.body || []) {\n const decl =\n stmt.type === 'ExportNamedDeclaration' ? stmt.declaration : stmt;\n if (!decl || decl.type !== 'VariableDeclaration' || decl.kind !== 'const')\n continue;\n for (const d of decl.declarations || []) {\n if (d.id?.type === 'Identifier' && d.init) {\n rawDecls.set(d.id.name, d.init);\n }\n }\n }\n\n const resolved = new Map<string, string>();\n // Iterative fixpoint: each pass resolves consts whose dependencies are\n // already known. Bounded by the number of declarations to prevent cycles.\n for (let pass = 0; pass < rawDecls.size + 1; pass++) {\n let progress = false;\n for (const [name, init] of rawDecls) {\n if (resolved.has(name)) continue;\n const value = stringValue(init, resolved);\n if (value !== null) {\n resolved.set(name, value);\n progress = true;\n }\n }\n if (!progress) break;\n }\n return resolved;\n}\n\n/** Get the property key name from an OXC object property. */\nfunction propKeyName(prop: any): string | null {\n if (!prop.key) return null;\n return prop.key.name ?? prop.key.value ?? null;\n}\n\n/**\n * Extract decorator metadata from an OXC decorator AST node.\n * Parses @Component, @Directive, @Pipe, @Injectable, @Service, @NgModule arguments.\n *\n * `stringConsts`, when provided, lets string-typed metadata fields\n * (`template`, `selector`, `templateUrl`, `styles`, `styleUrl`, `styleUrls`,\n * `name`, `exportAs`, `providedIn`) resolve module-level string constants\n * referenced via template-literal interpolation, e.g.\n * `template: \\`<div class=\"${tw}\">x</div>\\``.\n */\nexport function extractMetadata(\n dec: any | undefined,\n sourceCode: string,\n stringConsts?: Map<string, string>,\n): any {\n if (!dec) return null;\n const call = dec.expression;\n if (!call || call.type !== 'CallExpression') return null;\n const arg = call.arguments?.[0];\n const meta: any = {\n hostRaw: {},\n inputs: {},\n outputs: {},\n standalone: true,\n imports: [],\n providers: null,\n viewProviders: null,\n animations: null,\n changeDetection: null,\n encapsulation: null,\n preserveWhitespaces: false,\n exportAs: null,\n selector: undefined,\n styles: [],\n templateUrl: null,\n styleUrls: [],\n };\n if (!arg || arg.type !== 'ObjectExpression') return meta;\n\n for (const p of arg.properties || []) {\n if (p.type !== 'ObjectProperty' && p.type !== 'Property') continue;\n const key = propKeyName(p);\n if (!key) continue;\n const valNode = p.value;\n const valText = sourceCode.slice(valNode.start, valNode.end);\n\n switch (key) {\n case 'host':\n if (valNode.type === 'ObjectExpression') {\n for (const hp of valNode.properties || []) {\n if (hp.type !== 'ObjectProperty' && hp.type !== 'Property')\n continue;\n const hKey = propKeyName(hp);\n if (!hKey) continue;\n // Prefer the parsed string value so embedded quotes (e.g. the\n // empty `\"\"` in `'expr ? \"\" : null'`) survive. Falling back to\n // the source slice for non-string values keeps prior behavior\n // for unusual host bindings (e.g. references to constants).\n const sv = stringValue(hp.value, stringConsts);\n const hVal =\n sv !== null\n ? sv\n : sourceCode\n .slice(hp.value.start, hp.value.end)\n .replace(/^['\"`]|['\"`]$/g, '');\n meta.hostRaw[hKey.replace(/^['\"`]|['\"`]$/g, '')] = hVal;\n }\n }\n break;\n case 'changeDetection':\n meta.changeDetection = valText.includes('OnPush') ? 0 : 1;\n break;\n case 'encapsulation':\n meta.encapsulation = valText.includes('None')\n ? 2\n : valText.includes('ShadowDom')\n ? 3\n : 0;\n break;\n case 'preserveWhitespaces':\n meta.preserveWhitespaces = valText === 'true';\n break;\n case 'pure':\n case 'standalone':\n meta[key] = valText !== 'false';\n break;\n case 'template':\n case 'selector':\n case 'name':\n case 'exportAs':\n case 'templateUrl':\n case 'providedIn': {\n const sv = stringValue(valNode, stringConsts);\n if (sv !== null) {\n meta[key] = sv;\n } else if (valNode.type === 'TemplateLiteral') {\n // Template literal with `${...}` interpolations that couldn't\n // all be resolved at parse time (e.g. they reference imports\n // or non-string values). The previous fallback stripped every\n // quote character from the source, which silently corrupted\n // templates such as `<a class=\"${cls} foo\">…</a>` into\n // `<a class=${cls} foo>…</a>` — making Angular's HTML parser\n // fail with confusing errors like `Opening tag \"a\" not\n // terminated`. Instead, walk the quasis and substitute each\n // unresolved interpolation with the empty string so the\n // surrounding HTML (including quoted attributes) is preserved.\n const quasis = valNode.quasis ?? [];\n const expressions = valNode.expressions ?? [];\n let result = '';\n for (let i = 0; i < quasis.length; i++) {\n result += quasis[i]?.value?.cooked ?? '';\n if (i < expressions.length) {\n const expr = expressions[i];\n if (expr?.type === 'Identifier') {\n const resolved = stringConsts?.get(expr.name);\n if (resolved != null) {\n result += resolved;\n continue;\n }\n }\n // Unresolvable — substitute empty string. This keeps the\n // surrounding HTML well-formed even if the resulting class\n // list is incomplete.\n }\n }\n meta[key] = result;\n } else {\n // Non-string, non-template-literal expression. Strip only the\n // outermost JS string delimiters, not every embedded quote.\n meta[key] = valText.replace(/^['\"`]|['\"`]$/g, '');\n }\n if (key === 'exportAs') meta.exportAs = [meta.exportAs];\n break;\n }\n case 'styleUrl': {\n const sv = stringValue(valNode, stringConsts);\n meta.styleUrls = [sv !== null ? sv : valText.replace(/['\"`]/g, '')];\n break;\n }\n case 'styleUrls':\n if (valNode.type === 'ArrayExpression') {\n meta.styleUrls = (valNode.elements || []).map((e: any) => {\n const sv = stringValue(e, stringConsts);\n return sv !== null\n ? sv\n : sourceCode.slice(e.start, e.end).replace(/['\"`]/g, '');\n });\n }\n break;\n case 'styles':\n if (valNode.type === 'ArrayExpression') {\n meta.styles = (valNode.elements || []).map((e: any) => {\n const sv = stringValue(e, stringConsts);\n return sv !== null\n ? sv\n : sourceCode.slice(e.start, e.end).replace(/['\"`]/g, '');\n });\n } else {\n const sv = stringValue(valNode, stringConsts);\n if (sv !== null) meta.styles = [sv];\n }\n break;\n case 'imports':\n case 'providers':\n case 'viewProviders':\n case 'animations':\n case 'rawImports':\n case 'declarations':\n case 'exports':\n case 'bootstrap':\n if (valNode.type === 'ArrayExpression') {\n meta[key] = (valNode.elements || []).map(\n (e: any) => new o.WrappedNodeExpr(unwrapForwardRefOxc(e)),\n );\n }\n break;\n // @Injectable provider configuration. Pass these through to\n // compileInjectable so the emitted `ɵprov` reflects the user's\n // intent. `useClass`/`useExisting`/`useValue` are\n // `MaybeForwardRefExpression` (`{ expression, forwardRef }`);\n // `useFactory` is a bare `Expression`.\n case 'useClass':\n case 'useExisting':\n case 'useValue': {\n const unwrapped = unwrapForwardRefOxc(valNode);\n const isForwardRef =\n valNode.type === 'CallExpression' && unwrapped !== valNode;\n meta[key] = {\n expression: new o.WrappedNodeExpr(unwrapped),\n forwardRef: isForwardRef ? 2 : 0,\n };\n break;\n }\n case 'useFactory':\n meta[key] = new o.WrappedNodeExpr(valNode);\n break;\n // `@Service` configuration. `autoProvided` defaults to `true`, so only\n // an explicit `false` is meaningful; `factory` is a bare expression\n // forwarded to compileService.\n case 'autoProvided':\n meta.autoProvided = valText === 'true';\n break;\n case 'factory':\n meta.factory = new o.WrappedNodeExpr(valNode);\n break;\n case 'hostDirectives':\n if (valNode.type === 'ArrayExpression') {\n meta.hostDirectives = (valNode.elements || [])\n .map((el: any) => {\n // Bare identifier: hostDirectives: [MatTooltip]\n if (el.type === 'Identifier' || el.type === 'CallExpression') {\n const unwrapped = unwrapForwardRefOxc(el);\n const ref = {\n value: new o.WrappedNodeExpr(unwrapped),\n type: new o.WrappedNodeExpr(unwrapped),\n };\n return {\n directive: ref,\n isForwardReference: el.type === 'CallExpression',\n inputs: null,\n outputs: null,\n };\n }\n // Object form: { directive: MatTooltip, inputs: [...], outputs: [...] }\n if (el.type === 'ObjectExpression') {\n let directiveNode: any = null;\n let isForwardRef = false;\n let inputs: Record<string, string> | null = null;\n let outputs: Record<string, string> | null = null;\n for (const prop of el.properties || []) {\n if (\n prop.type !== 'ObjectProperty' &&\n prop.type !== 'Property'\n )\n continue;\n const pName = propKeyName(prop);\n if (pName === 'directive') {\n directiveNode = unwrapForwardRefOxc(prop.value);\n isForwardRef =\n prop.value?.type === 'CallExpression' &&\n sourceCode\n .slice(prop.value.start, prop.value.end)\n .includes('forwardRef');\n } else if (\n pName === 'inputs' &&\n prop.value?.type === 'ArrayExpression'\n ) {\n inputs = {};\n for (const e of prop.value.elements || []) {\n const sv = stringValue(e);\n if (sv !== null) {\n const [source, alias = source] = sv\n .split(':')\n .map((part: string) => part.trim());\n if (source) inputs[source] = alias;\n }\n }\n } else if (\n pName === 'outputs' &&\n prop.value?.type === 'ArrayExpression'\n ) {\n outputs = {};\n for (const e of prop.value.elements || []) {\n const sv = stringValue(e);\n if (sv !== null) {\n const [source, alias = source] = sv\n .split(':')\n .map((part: string) => part.trim());\n if (source) outputs[source] = alias;\n }\n }\n }\n }\n if (directiveNode) {\n const ref = {\n value: new o.WrappedNodeExpr(directiveNode),\n type: new o.WrappedNodeExpr(directiveNode),\n };\n return {\n directive: ref,\n isForwardReference: isForwardRef,\n inputs,\n outputs,\n };\n }\n }\n return null;\n })\n .filter(Boolean);\n }\n break;\n default:\n meta[key] = valText.replace(/['\"`]/g, '');\n }\n }\n return meta;\n}\n\n/**\n * Detect signal-based APIs on class members: input(), model(), output(),\n * viewChild(), contentChild(), viewChildren(), contentChildren().\n */\nexport function detectSignals(classNode: any, sourceCode: string) {\n const inputs: any = {},\n outputs: any = {},\n viewQueries: any[] = [],\n contentQueries: any[] = [];\n\n const members: any[] = classNode.body?.body || [];\n\n for (const m of members) {\n if (\n m.type !== 'PropertyDefinition' ||\n !m.key?.name ||\n !m.value ||\n m.value.type !== 'CallExpression'\n )\n continue;\n\n const name: string = m.key.name;\n const signalCall = getCallApi(m.value);\n if (!signalCall) continue;\n\n const { api, required } = signalCall;\n if (!SIGNAL_APIS.has(api)) continue;\n\n // Skip signal synthesis when an explicit Angular decorator already\n // covers the same field. Mirrors Angular's transform behavior\n // (input_function.ts:42-48 et al.) and the JIT fix in\n // jit-metadata.ts. Without this, the downstream merge in compile.ts\n // overwrites decorator-derived metadata or, worse, concats duplicate\n // query entries that fire twice.\n const explicit = new Set<string>();\n for (const dec of m.decorators || []) {\n const decName: string | undefined = dec.expression?.callee?.name;\n if (decName && FIELD_DECORATORS.has(decName)) explicit.add(decName);\n }\n const hasInput = explicit.has('Input');\n const hasOutput = explicit.has('Output');\n const hasQuery =\n explicit.has('ViewChild') ||\n explicit.has('ViewChildren') ||\n explicit.has('ContentChild') ||\n explicit.has('ContentChildren');\n if (api === 'input' && hasInput) continue;\n if (api === 'model' && (hasInput || hasOutput)) continue;\n if ((api === 'output' || api === 'outputFromObservable') && hasOutput) {\n continue;\n }\n if (\n (api === 'viewChild' ||\n api === 'viewChildren' ||\n api === 'contentChild' ||\n api === 'contentChildren') &&\n hasQuery\n ) {\n continue;\n }\n\n const args: any[] = m.value.arguments || [];\n\n // 1. SIGNAL INPUTS (Standard & Required)\n if (api === 'input') {\n let alias: string | null = null;\n const optionsArg = required ? args[0] : args[1];\n if (optionsArg?.type === 'ObjectExpression') {\n for (const prop of optionsArg.properties || []) {\n if (prop.type !== 'ObjectProperty' && prop.type !== 'Property')\n continue;\n if (propKeyName(prop) === 'alias') {\n const sv = stringValue(prop.value);\n if (sv !== null) alias = sv;\n }\n }\n }\n inputs[name] = {\n classPropertyName: name,\n // The binding (public) name is the alias if provided, otherwise\n // the class property name. Without honoring `alias`, host\n // directives that map by public name (e.g.\n // `inputs: ['aria-label']` against `ariaLabel = input(null, {\n // alias: 'aria-label' })`) fail at runtime with NG0311.\n bindingPropertyName: alias ?? name,\n isSignal: true,\n required,\n // Always null for signal inputs. The input() factory already\n // applies the user's transform internally; forwarding it to the\n // directive metadata would make Angular's emitter set the\n // HasDecoratorInputTransform flag, causing the transform to run\n // again via the runtime input setter. Mirrors upstream\n // input_function.ts:74.\n transform: null,\n };\n }\n\n // 2. MODEL SIGNALS (Writable Inputs)\n else if (api === 'model') {\n // model() supports the same options object as input(); honor `alias`\n // for the same reason (host-directive mappings use the public name).\n let alias: string | null = null;\n const optionsArg = required ? args[0] : args[1];\n if (optionsArg?.type === 'ObjectExpression') {\n for (const prop of optionsArg.properties || []) {\n if (prop.type !== 'ObjectProperty' && prop.type !== 'Property')\n continue;\n if (propKeyName(prop) === 'alias') {\n const sv = stringValue(prop.value);\n if (sv !== null) alias = sv;\n }\n }\n }\n inputs[name] = {\n classPropertyName: name,\n bindingPropertyName: alias ?? name,\n isSignal: true,\n // Propagate `.required` so the runtime enforces the unbound-required\n // check. Without this, `model.required(...)` accepts an unbound parent\n // and the model signal stays at its undefined initial value silently.\n required,\n };\n // The compiled `outputs` field is `{ classPropertyName: bindingName }`.\n // Angular inverts this at runtime via\n // `parseAndConvertOutputsForDefinition`, producing the lookup map\n // `{ bindingName: classPropertyName }` used by `listenToOutput`.\n // For a `model()` signal, the class property is `name` and the\n // binding event is `${aliasOrName}Change`, and the model signal\n // itself is the subscribable, so `instance[name]` is what\n // `listenToOutput` needs to resolve.\n outputs[name] = (alias ?? name) + 'Change';\n }\n\n // 3. SIGNAL QUERIES (viewChild, contentChild)\n else if (\n api === 'viewChild' ||\n api === 'viewChildren' ||\n api === 'contentChild' ||\n api === 'contentChildren'\n ) {\n const isViewQuery = api === 'viewChild' || api === 'viewChildren';\n const isChildrenQuery =\n api === 'viewChildren' || api === 'contentChildren';\n\n const firstArg = args[0];\n const sv = stringValue(firstArg);\n\n // Parse the optional second-arg options object for `read` and\n // (content queries only) `descendants`. Without this, queries like\n // `viewChild('ref', { read: ElementRef })` and\n // `contentChildren(Foo, { descendants: false })` silently lose\n // their options at runtime.\n let read: any = null;\n // Defaults match Angular's signal-query API and the decorator\n // path (`isView || isFirst` in detectFieldDecorators):\n // viewChild → true (view queries always traverse)\n // viewChildren → true\n // contentChild → true (single-result content queries\n // traverse by default)\n // contentChildren → false (multi-result content queries are\n // shallow unless explicitly opted in)\n let descendants = isViewQuery || !isChildrenQuery;\n const optArg = args[1];\n if (optArg?.type === 'ObjectExpression') {\n for (const prop of optArg.properties || []) {\n if (prop.type !== 'ObjectProperty' && prop.type !== 'Property')\n continue;\n const k = propKeyName(prop);\n if (k === 'read') {\n read = new o.WrappedNodeExpr(unwrapForwardRefOxc(prop.value));\n } else if (k === 'descendants') {\n const t = prop.value?.type;\n if (\n t === 'BooleanLiteral' ||\n (t === 'Literal' && typeof prop.value.value === 'boolean')\n ) {\n descendants = prop.value.value;\n }\n }\n }\n }\n\n const query = {\n propertyName: name,\n // Class predicates must be wrapped in an `R3QueryReference`\n // (`{ forwardRef, expression }`); Angular's `getQueryPredicate`\n // dispatches on `predicate.forwardRef` and reads\n // `predicate.expression`, so a bare `WrappedNodeExpr` is silently\n // dropped to `undefined` and emitted as `null`, leaving the query\n // with no target. `0 = ForwardRefHandling.None`.\n predicate:\n sv !== null\n ? [sv]\n : { forwardRef: 0, expression: new o.WrappedNodeExpr(firstArg) },\n first: !isChildrenQuery,\n descendants,\n read,\n static: false,\n emitFlags: 0,\n isSignal: true,\n };\n\n if (isViewQuery) viewQueries.push(query);\n else contentQueries.push(query);\n }\n\n // 4. STANDARD OUTPUTS (output() and outputFromObservable())\n else if (api === 'output' || api === 'outputFromObservable') {\n let alias = name;\n // outputFromObservable(observable, options) — options is args[1].\n // output(options) — options is args[0]. Mirrors upstream\n // output_function.ts:81.\n const optArg = api === 'outputFromObservable' ? args[1] : args[0];\n if (optArg?.type === 'ObjectExpression') {\n for (const prop of optArg.properties || []) {\n if (\n (prop.type === 'ObjectProperty' || prop.type === 'Property') &&\n propKeyName(prop) === 'alias'\n ) {\n const sv = stringValue(prop.value);\n if (sv !== null) alias = sv;\n }\n }\n }\n outputs[name] = alias;\n }\n }\n\n return { inputs, outputs, viewQueries, contentQueries };\n}\n\n/**\n * Detect decorator-based field metadata: @Input, @Output, @ViewChild,\n * @ContentChild, @ViewChildren, @ContentChildren, @HostBinding, @HostListener.\n */\nexport function detectFieldDecorators(classNode: any, sourceCode: string) {\n const inputs: any = {};\n const outputs: any = {};\n const viewQueries: any[] = [];\n const contentQueries: any[] = [];\n const hostProperties: Record<string, string> = {};\n const hostListeners: Record<string, string> = {};\n\n const members: any[] = classNode.body?.body || [];\n\n for (const member of members) {\n const decorators: any[] = member.decorators || [];\n if (decorators.length === 0) continue;\n\n const memberName: string = member.key?.name || '';\n\n for (const dec of decorators) {\n const expr = dec.expression;\n if (!expr || expr.type !== 'CallExpression') continue;\n const decName: string | undefined = expr.callee?.name;\n if (!decName) continue;\n const args: any[] = expr.arguments || [];\n\n switch (decName) {\n case 'Input': {\n let bindingName = memberName;\n let required = false;\n let transformFunction: any = null;\n\n if (args.length > 0) {\n const arg = args[0];\n const sv = stringValue(arg);\n if (sv !== null) {\n bindingName = sv;\n } else if (arg.type === 'ObjectExpression') {\n for (const prop of arg.properties || []) {\n if (prop.type !== 'ObjectProperty' && prop.type !== 'Property')\n continue;\n const k = propKeyName(prop);\n if (k === 'alias') {\n const asv = stringValue(prop.value);\n if (asv !== null) bindingName = asv;\n }\n if (k === 'required')\n required =\n sourceCode.slice(prop.value.start, prop.value.end) ===\n 'true';\n if (k === 'transform')\n transformFunction = new o.WrappedNodeExpr(prop.value);\n }\n }\n }\n\n inputs[memberName] = {\n classPropertyName: memberName,\n bindingPropertyName: bindingName,\n isSignal: false,\n required,\n transformFunction,\n };\n break;\n }\n\n case 'Output': {\n const sv = args.length > 0 ? stringValue(args[0]) : null;\n const alias = sv !== null ? sv : memberName;\n outputs[memberName] = alias;\n break;\n }\n\n case 'ViewChild':\n case 'ViewChildren':\n case 'ContentChild':\n case 'ContentChildren': {\n const isView = decName.startsWith('View');\n const isFirst = decName === 'ViewChild' || decName === 'ContentChild';\n\n // Default predicate when no argument is given is the member\n // name. Class predicates (the non-string case) must be wrapped\n // in an `R3QueryReference` (`{ forwardRef, expression }`) so\n // Angular's `getQueryPredicate` can dispatch on `forwardRef`\n // and read `.expression`. A bare `WrappedNodeExpr` is silently\n // dropped to undefined and emitted as `null`.\n let predicate: any = [memberName];\n if (args.length > 0) {\n const pred = args[0];\n const sv = stringValue(pred);\n if (sv !== null) {\n predicate = [sv];\n } else {\n predicate = {\n forwardRef: 0,\n expression: new o.WrappedNodeExpr(unwrapForwardRefOxc(pred)),\n };\n }\n }\n\n let read: any = null;\n let isStatic = false;\n let descendants = isView || isFirst;\n\n if (args.length > 1 && args[1]?.type === 'ObjectExpression') {\n for (const prop of args[1].properties || []) {\n if (prop.type !== 'ObjectProperty' && prop.type !== 'Property')\n continue;\n const k = propKeyName(prop);\n if (k === 'read') read = new o.WrappedNodeExpr(prop.value);\n if (k === 'static')\n isStatic =\n sourceCode.slice(prop.value.start, prop.value.end) === 'true';\n if (k === 'descendants')\n descendants =\n sourceCode.slice(prop.value.start, prop.value.end) === 'true';\n }\n }\n\n const query = {\n propertyName: memberName,\n predicate,\n first: isFirst,\n descendants,\n read,\n static: isStatic,\n emitFlags: 0,\n isSignal: false,\n };\n\n if (isView) viewQueries.push(query);\n else contentQueries.push(query);\n break;\n }\n\n case 'HostBinding': {\n const sv = args.length > 0 ? stringValue(args[0]) : null;\n const target = sv !== null ? sv : memberName;\n hostProperties[target] = memberName;\n break;\n }\n\n case 'HostListener': {\n const sv = args.length > 0 ? stringValue(args[0]) : null;\n if (sv !== null) {\n const event = sv;\n let handler = `${memberName}()`;\n if (args.length > 1 && args[1]?.type === 'ArrayExpression') {\n const handlerArgs = (args[1].elements || [])\n .map((e: any) => stringValue(e))\n .filter((v: string | null): v is string => v !== null)\n .join(', ');\n handler = `${memberName}(${handlerArgs})`;\n }\n hostListeners[event] = handler;\n }\n break;\n }\n }\n }\n }\n\n return {\n inputs,\n outputs,\n viewQueries,\n contentQueries,\n hostProperties,\n hostListeners,\n };\n}\n\n/**\n * Analyze constructor parameters for dependency injection.\n * Returns:\n * - R3DependencyMetadata[] for normal constructors\n * - null if class extends another without own constructor (use inherited factory)\n * - 'invalid' if any parameter has a type-only import token\n *\n * Accepts an OXC ClassDeclaration node and the original source string.\n */\nexport function extractConstructorDeps(\n classNode: any,\n sourceCode: string,\n typeOnlyImports: Set<string>,\n): any[] | 'invalid' | null {\n const heritage: any[] = classNode.superClass ? [classNode.superClass] : [];\n const hasSuper = heritage.length > 0;\n\n const members: any[] = classNode.body?.body || [];\n const ctor = members.find(\n (m: any) => m.type === 'MethodDefinition' && m.kind === 'constructor',\n );\n\n if (!ctor) {\n return hasSuper ? null : [];\n }\n\n const params: any[] = ctor.value?.params?.items || ctor.value?.params || [];\n const deps: any[] = [];\n let invalid = false;\n\n for (const param of params) {\n let token: string | null = null;\n let attributeNameType: any = null;\n let host = false,\n optional = false,\n self = false,\n skipSelf = false;\n\n // Handle TSParameterProperty (e.g., constructor(private foo: Bar))\n const actualParam =\n param.type === 'TSParameterProperty' ? param.parameter : param;\n const typeAnn =\n actualParam?.typeAnnotation?.typeAnnotation ??\n param?.typeAnnotation?.typeAnnotation;\n\n // Extract type annotation as token\n if (typeAnn) {\n if (typeAnn.type === 'TSTypeReference' && typeAnn.typeName) {\n token =\n typeAnn.typeName.name ??\n sourceCode.slice(typeAnn.typeName.start, typeAnn.typeName.end);\n } else if (typeAnn.type === 'TSUnionType') {\n // Filter out null/undefined/void arms — `T | null` and\n // `T | undefined` are common patterns that should resolve to T.\n // Anything else (multiple TypeReference arms, primitives, etc.)\n // is ambiguous and ngtsc rejects it. Mark as invalid so the\n // factory falls through to ɵɵinvalidFactory rather than\n // silently picking the first arm.\n const nonNullTypes = (typeAnn.types || []).filter((t: any) => {\n if (!t) return false;\n if (t.type === 'TSNullKeyword') return false;\n if (t.type === 'TSUndefinedKeyword') return false;\n if (t.type === 'TSVoidKeyword') return false;\n if (\n t.type === 'TSLiteralType' &&\n (t.literal?.type === 'NullLiteral' ||\n (t.literal?.type === 'Literal' && t.literal.value === null))\n ) {\n return false;\n }\n return true;\n });\n if (\n nonNullTypes.length === 1 &&\n nonNullTypes[0].type === 'TSTypeReference' &&\n nonNullTypes[0].typeName\n ) {\n const t = nonNullTypes[0];\n token =\n t.typeName.name ??\n sourceCode.slice(t.typeName.start, t.typeName.end);\n } else {\n // Ambiguous union — no suitable injection token.\n invalid = true;\n continue;\n }\n } else if (typeAnn.type === 'TSIntersectionType') {\n // Intersection types (`A & B`) have no single injection token.\n invalid = true;\n continue;\n }\n }\n\n // Process parameter decorators (may live on TSParameterProperty or inner param)\n const paramDecs: any[] = [\n ...(param.decorators || []),\n ...(param.type === 'TSParameterProperty' && actualParam?.decorators\n ? actualParam.decorators\n : []),\n ];\n for (const dec of paramDecs) {\n const expr = dec.expression;\n if (!expr || expr.type !== 'CallExpression') continue;\n const decName: string | undefined = expr.callee?.name;\n if (!decName) continue;\n const args: any[] = expr.arguments || [];\n\n switch (decName) {\n case 'Inject':\n if (args.length > 0) {\n const sv = stringValue(args[0]);\n if (sv !== null) {\n token = sv;\n } else {\n // Unwrap `@Inject(forwardRef(() => TOKEN))` so the\n // emitted token references TOKEN directly. Without this\n // the raw `forwardRef(() => TOKEN)` source slice would\n // appear in the factory output, producing broken code\n // that calls forwardRef at definition time.\n const unwrapped = unwrapForwardRefOxc(args[0]);\n token = sourceCode.slice(unwrapped.start, unwrapped.end);\n }\n }\n break;\n case 'Optional':\n optional = true;\n break;\n case 'Self':\n self = true;\n break;\n case 'SkipSelf':\n skipSelf = true;\n break;\n case 'Host':\n host = true;\n break;\n case 'Attribute':\n if (args.length > 0) {\n const sv = stringValue(args[0]);\n if (sv !== null) {\n attributeNameType = new o.LiteralExpr(sv);\n token = '';\n }\n }\n break;\n }\n }\n\n if (!token && !attributeNameType) {\n invalid = true;\n continue;\n }\n\n if (token && typeOnlyImports.has(token)) {\n invalid = true;\n continue;\n }\n\n deps.push({\n token: token ? new o.WrappedNodeExpr(token) : new o.LiteralExpr(null),\n attributeNameType,\n host,\n optional,\n self,\n skipSelf,\n });\n }\n\n return invalid ? 'invalid' : deps;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"metadata.js","names":[],"sources":["../../../../src/lib/compiler/metadata.ts"],"sourcesContent":["import * as o from '@angular/compiler';\nimport { unwrapForwardRefOxc } from './utils.js';\nimport { FIELD_DECORATORS, SIGNAL_APIS } from './constants.js';\n\nfunction getCallApi(call: any): { api: string; required: boolean } | null {\n const callee = call.callee;\n if (!callee) return null;\n\n if (callee.type === 'Identifier') {\n return { api: callee.name, required: false };\n }\n\n if (\n (callee.type === 'StaticMemberExpression' ||\n callee.type === 'MemberExpression') &&\n callee.object?.type === 'Identifier' &&\n callee.property?.name === 'required'\n ) {\n return { api: callee.object.name, required: true };\n }\n\n return null;\n}\n\n/**\n * Extract the string value from an OXC string literal or template literal node.\n *\n * If `consts` is provided, interpolated template literals (e.g.\n * `\\`hello ${NAME}\\``) are resolved when every `${...}` expression is a bare\n * `Identifier` whose name is present in the map. This lets metadata fields\n * such as `template:` reference module-level string constants via JS\n * template-literal interpolation:\n *\n * const tw = `text-zinc-700 hover:text-zinc-900`;\n * @Component({ template: `<a class=\"${tw}\">x</a>` })\n *\n * Returns `null` if the node is not statically resolvable.\n */\nfunction stringValue(node: any, consts?: Map<string, string>): string | null {\n if (node?.type === 'StringLiteral') return node.value;\n if (node?.type === 'Literal' && typeof node.value === 'string')\n return node.value;\n if (node?.type === 'TemplateLiteral') {\n const quasis = node.quasis ?? [];\n const expressions = node.expressions ?? [];\n if (expressions.length === 0) {\n return quasis[0]?.value?.cooked ?? null;\n }\n if (!consts) return null;\n let result = '';\n for (let i = 0; i < quasis.length; i++) {\n const cooked = quasis[i]?.value?.cooked;\n if (cooked == null) return null;\n result += cooked;\n if (i < expressions.length) {\n const expr = expressions[i];\n if (expr?.type !== 'Identifier') return null;\n const resolved = consts.get(expr.name);\n if (resolved == null) return null;\n result += resolved;\n }\n }\n return result;\n }\n return null;\n}\n\n/** Check if an OXC node is a string-like literal. */\nfunction isStringLike(node: any, consts?: Map<string, string>): boolean {\n return stringValue(node, consts) !== null;\n}\n\n/**\n * Walk the top-level statements of an OXC program and collect a map of\n * statically-resolvable string-valued `const NAME = ...` declarations.\n *\n * Used so decorator metadata fields like `template:` can reference\n * module-level Tailwind class chains (or any other string constants) via\n * JS template-literal interpolation. Resolution is iterative: a const may\n * reference earlier-resolved consts via `${other}` interpolation.\n *\n * Only `const` declarations are considered. Non-string initializers,\n * function calls, member access, and any expression that cannot be reduced\n * to a string at parse time are ignored.\n */\nexport function collectStringConstants(oxcProgram: any): Map<string, string> {\n const rawDecls = new Map<string, any>();\n for (const stmt of oxcProgram?.body || []) {\n const decl =\n stmt.type === 'ExportNamedDeclaration' ? stmt.declaration : stmt;\n if (!decl || decl.type !== 'VariableDeclaration' || decl.kind !== 'const')\n continue;\n for (const d of decl.declarations || []) {\n if (d.id?.type === 'Identifier' && d.init) {\n rawDecls.set(d.id.name, d.init);\n }\n }\n }\n\n const resolved = new Map<string, string>();\n // Iterative fixpoint: each pass resolves consts whose dependencies are\n // already known. Bounded by the number of declarations to prevent cycles.\n for (let pass = 0; pass < rawDecls.size + 1; pass++) {\n let progress = false;\n for (const [name, init] of rawDecls) {\n if (resolved.has(name)) continue;\n const value = stringValue(init, resolved);\n if (value !== null) {\n resolved.set(name, value);\n progress = true;\n }\n }\n if (!progress) break;\n }\n return resolved;\n}\n\n/** Get the property key name from an OXC object property. */\nfunction propKeyName(prop: any): string | null {\n if (!prop.key) return null;\n return prop.key.name ?? prop.key.value ?? null;\n}\n\n/**\n * Extract decorator metadata from an OXC decorator AST node.\n * Parses @Component, @Directive, @Pipe, @Injectable, @Service, @NgModule arguments.\n *\n * `stringConsts`, when provided, lets string-typed metadata fields\n * (`template`, `selector`, `templateUrl`, `styles`, `styleUrl`, `styleUrls`,\n * `name`, `exportAs`, `providedIn`) resolve module-level string constants\n * referenced via template-literal interpolation, e.g.\n * `template: \\`<div class=\"${tw}\">x</div>\\``.\n */\nexport function extractMetadata(\n dec: any | undefined,\n sourceCode: string,\n stringConsts?: Map<string, string>,\n): any {\n if (!dec) return null;\n const call = dec.expression;\n if (!call || call.type !== 'CallExpression') return null;\n const arg = call.arguments?.[0];\n const meta: any = {\n hostRaw: {},\n inputs: {},\n outputs: {},\n standalone: true,\n imports: [],\n providers: null,\n viewProviders: null,\n animations: null,\n changeDetection: null,\n encapsulation: null,\n preserveWhitespaces: false,\n exportAs: null,\n selector: undefined,\n styles: [],\n templateUrl: null,\n styleUrls: [],\n };\n if (!arg || arg.type !== 'ObjectExpression') return meta;\n\n for (const p of arg.properties || []) {\n if (p.type !== 'ObjectProperty' && p.type !== 'Property') continue;\n const key = propKeyName(p);\n if (!key) continue;\n const valNode = p.value;\n const valText = sourceCode.slice(valNode.start, valNode.end);\n\n switch (key) {\n case 'host':\n if (valNode.type === 'ObjectExpression') {\n for (const hp of valNode.properties || []) {\n if (hp.type !== 'ObjectProperty' && hp.type !== 'Property')\n continue;\n const hKey = propKeyName(hp);\n if (!hKey) continue;\n // Prefer the parsed string value so embedded quotes (e.g. the\n // empty `\"\"` in `'expr ? \"\" : null'`) survive. Falling back to\n // the source slice for non-string values keeps prior behavior\n // for unusual host bindings (e.g. references to constants).\n const sv = stringValue(hp.value, stringConsts);\n const hVal =\n sv !== null\n ? sv\n : sourceCode\n .slice(hp.value.start, hp.value.end)\n .replace(/^['\"`]|['\"`]$/g, '');\n meta.hostRaw[hKey.replace(/^['\"`]|['\"`]$/g, '')] = hVal;\n }\n }\n break;\n case 'changeDetection':\n meta.changeDetection = valText.includes('OnPush') ? 0 : 1;\n break;\n case 'encapsulation':\n meta.encapsulation = valText.includes('None')\n ? 2\n : valText.includes('ShadowDom')\n ? 3\n : 0;\n break;\n case 'preserveWhitespaces':\n meta.preserveWhitespaces = valText === 'true';\n break;\n case 'pure':\n case 'standalone':\n meta[key] = valText !== 'false';\n break;\n case 'template':\n case 'selector':\n case 'name':\n case 'exportAs':\n case 'templateUrl':\n case 'providedIn': {\n const sv = stringValue(valNode, stringConsts);\n if (sv !== null) {\n meta[key] = sv;\n } else if (valNode.type === 'TemplateLiteral') {\n // Template literal with `${...}` interpolations that couldn't\n // all be resolved at parse time (e.g. they reference imports\n // or non-string values). The previous fallback stripped every\n // quote character from the source, which silently corrupted\n // templates such as `<a class=\"${cls} foo\">…</a>` into\n // `<a class=${cls} foo>…</a>` — making Angular's HTML parser\n // fail with confusing errors like `Opening tag \"a\" not\n // terminated`. Instead, walk the quasis and substitute each\n // unresolved interpolation with the empty string so the\n // surrounding HTML (including quoted attributes) is preserved.\n const quasis = valNode.quasis ?? [];\n const expressions = valNode.expressions ?? [];\n let result = '';\n for (let i = 0; i < quasis.length; i++) {\n result += quasis[i]?.value?.cooked ?? '';\n if (i < expressions.length) {\n const expr = expressions[i];\n if (expr?.type === 'Identifier') {\n const resolved = stringConsts?.get(expr.name);\n if (resolved != null) {\n result += resolved;\n continue;\n }\n }\n // Unresolvable — substitute empty string. This keeps the\n // surrounding HTML well-formed even if the resulting class\n // list is incomplete.\n }\n }\n meta[key] = result;\n } else {\n // Non-string, non-template-literal expression. Strip only the\n // outermost JS string delimiters, not every embedded quote.\n meta[key] = valText.replace(/^['\"`]|['\"`]$/g, '');\n }\n if (key === 'exportAs') meta.exportAs = [meta.exportAs];\n break;\n }\n case 'styleUrl': {\n const sv = stringValue(valNode, stringConsts);\n meta.styleUrls = [sv !== null ? sv : valText.replace(/['\"`]/g, '')];\n break;\n }\n case 'styleUrls':\n if (valNode.type === 'ArrayExpression') {\n meta.styleUrls = (valNode.elements || []).map((e: any) => {\n const sv = stringValue(e, stringConsts);\n return sv !== null\n ? sv\n : sourceCode.slice(e.start, e.end).replace(/['\"`]/g, '');\n });\n }\n break;\n case 'styles':\n if (valNode.type === 'ArrayExpression') {\n meta.styles = (valNode.elements || []).map((e: any) => {\n const sv = stringValue(e, stringConsts);\n return sv !== null\n ? sv\n : sourceCode.slice(e.start, e.end).replace(/['\"`]/g, '');\n });\n } else {\n const sv = stringValue(valNode, stringConsts);\n if (sv !== null) meta.styles = [sv];\n }\n break;\n case 'imports':\n case 'animations':\n case 'rawImports':\n case 'declarations':\n case 'exports':\n case 'bootstrap':\n if (valNode.type === 'ArrayExpression') {\n meta[key] = (valNode.elements || []).map(\n (e: any) => new o.WrappedNodeExpr(unwrapForwardRefOxc(e)),\n );\n }\n break;\n case 'providers':\n case 'viewProviders':\n if (valNode.type === 'ArrayExpression') {\n meta[key] = (valNode.elements || []).map(\n (e: any) => new o.WrappedNodeExpr(unwrapForwardRefOxc(e)),\n );\n } else {\n // `providers: safeProviders` / `viewProviders: SHARED_PROVIDERS`\n // — a reference to a module-level const (or any non-literal\n // expression such as a spread or function call) rather than an\n // inline array literal. ngtsc's partial evaluator expands the\n // identifier to its array; fastCompile does no static evaluation,\n // so it cannot. But Angular emits injector/host `providers` as a\n // single Expression and flattens nested arrays at runtime, so the\n // reference can be passed through by value. Storing it as a bare\n // `o.Expression` (not an array) signals the emission sites to emit\n // it directly instead of wrapping it in a `LiteralArrayExpr`.\n // Without this, the whole `providers` list is silently dropped and\n // every token it provides fails at runtime with NG0201.\n meta[key] = new o.WrappedNodeExpr(valNode);\n }\n break;\n // @Injectable provider configuration. Pass these through to\n // compileInjectable so the emitted `ɵprov` reflects the user's\n // intent. `useClass`/`useExisting`/`useValue` are\n // `MaybeForwardRefExpression` (`{ expression, forwardRef }`);\n // `useFactory` is a bare `Expression`.\n case 'useClass':\n case 'useExisting':\n case 'useValue': {\n const unwrapped = unwrapForwardRefOxc(valNode);\n const isForwardRef =\n valNode.type === 'CallExpression' && unwrapped !== valNode;\n meta[key] = {\n expression: new o.WrappedNodeExpr(unwrapped),\n forwardRef: isForwardRef ? 2 : 0,\n };\n break;\n }\n case 'useFactory':\n meta[key] = new o.WrappedNodeExpr(valNode);\n break;\n // `@Injectable({ deps: [...] })` — the dependency list for `useFactory`\n // / `useClass`. Each entry is either a bare token or a flag array such\n // as `[new Optional(), new SkipSelf(), Token]`. Without parsing this the\n // emitted factory ignores the deps and calls the factory/ctor with no\n // arguments.\n case 'deps':\n if (valNode.type === 'ArrayExpression') {\n meta.deps = extractInjectableDeps(valNode, sourceCode);\n }\n break;\n // `@Service` configuration. `autoProvided` defaults to `true`, so only\n // an explicit `false` is meaningful; `factory` is a bare expression\n // forwarded to compileService.\n case 'autoProvided':\n meta.autoProvided = valText === 'true';\n break;\n case 'factory':\n meta.factory = new o.WrappedNodeExpr(valNode);\n break;\n case 'hostDirectives':\n if (valNode.type === 'ArrayExpression') {\n meta.hostDirectives = (valNode.elements || [])\n .map((el: any) => {\n // Bare identifier: hostDirectives: [MatTooltip]\n if (el.type === 'Identifier' || el.type === 'CallExpression') {\n const unwrapped = unwrapForwardRefOxc(el);\n const ref = {\n value: new o.WrappedNodeExpr(unwrapped),\n type: new o.WrappedNodeExpr(unwrapped),\n };\n return {\n directive: ref,\n isForwardReference: el.type === 'CallExpression',\n inputs: null,\n outputs: null,\n };\n }\n // Object form: { directive: MatTooltip, inputs: [...], outputs: [...] }\n if (el.type === 'ObjectExpression') {\n let directiveNode: any = null;\n let isForwardRef = false;\n let inputs: Record<string, string> | null = null;\n let outputs: Record<string, string> | null = null;\n for (const prop of el.properties || []) {\n if (\n prop.type !== 'ObjectProperty' &&\n prop.type !== 'Property'\n )\n continue;\n const pName = propKeyName(prop);\n if (pName === 'directive') {\n directiveNode = unwrapForwardRefOxc(prop.value);\n isForwardRef =\n prop.value?.type === 'CallExpression' &&\n sourceCode\n .slice(prop.value.start, prop.value.end)\n .includes('forwardRef');\n } else if (\n pName === 'inputs' &&\n prop.value?.type === 'ArrayExpression'\n ) {\n inputs = {};\n for (const e of prop.value.elements || []) {\n const sv = stringValue(e);\n if (sv !== null) {\n const [source, alias = source] = sv\n .split(':')\n .map((part: string) => part.trim());\n if (source) inputs[source] = alias;\n }\n }\n } else if (\n pName === 'outputs' &&\n prop.value?.type === 'ArrayExpression'\n ) {\n outputs = {};\n for (const e of prop.value.elements || []) {\n const sv = stringValue(e);\n if (sv !== null) {\n const [source, alias = source] = sv\n .split(':')\n .map((part: string) => part.trim());\n if (source) outputs[source] = alias;\n }\n }\n }\n }\n if (directiveNode) {\n const ref = {\n value: new o.WrappedNodeExpr(directiveNode),\n type: new o.WrappedNodeExpr(directiveNode),\n };\n return {\n directive: ref,\n isForwardReference: isForwardRef,\n inputs,\n outputs,\n };\n }\n }\n return null;\n })\n .filter(Boolean);\n }\n break;\n default:\n meta[key] = valText.replace(/['\"`]/g, '');\n }\n }\n return meta;\n}\n\n/**\n * Detect signal-based APIs on class members: input(), model(), output(),\n * viewChild(), contentChild(), viewChildren(), contentChildren().\n */\nexport function detectSignals(classNode: any, sourceCode: string) {\n const inputs: any = {},\n outputs: any = {},\n viewQueries: any[] = [],\n contentQueries: any[] = [];\n\n const members: any[] = classNode.body?.body || [];\n\n for (const m of members) {\n if (\n m.type !== 'PropertyDefinition' ||\n !m.key?.name ||\n !m.value ||\n m.value.type !== 'CallExpression'\n )\n continue;\n\n const name: string = m.key.name;\n const signalCall = getCallApi(m.value);\n if (!signalCall) continue;\n\n const { api, required } = signalCall;\n if (!SIGNAL_APIS.has(api)) continue;\n\n // Skip signal synthesis when an explicit Angular decorator already\n // covers the same field. Mirrors Angular's transform behavior\n // (input_function.ts:42-48 et al.) and the JIT fix in\n // jit-metadata.ts. Without this, the downstream merge in compile.ts\n // overwrites decorator-derived metadata or, worse, concats duplicate\n // query entries that fire twice.\n const explicit = new Set<string>();\n for (const dec of m.decorators || []) {\n const decName: string | undefined = dec.expression?.callee?.name;\n if (decName && FIELD_DECORATORS.has(decName)) explicit.add(decName);\n }\n const hasInput = explicit.has('Input');\n const hasOutput = explicit.has('Output');\n const hasQuery =\n explicit.has('ViewChild') ||\n explicit.has('ViewChildren') ||\n explicit.has('ContentChild') ||\n explicit.has('ContentChildren');\n if (api === 'input' && hasInput) continue;\n if (api === 'model' && (hasInput || hasOutput)) continue;\n if ((api === 'output' || api === 'outputFromObservable') && hasOutput) {\n continue;\n }\n if (\n (api === 'viewChild' ||\n api === 'viewChildren' ||\n api === 'contentChild' ||\n api === 'contentChildren') &&\n hasQuery\n ) {\n continue;\n }\n\n const args: any[] = m.value.arguments || [];\n\n // 1. SIGNAL INPUTS (Standard & Required)\n if (api === 'input') {\n let alias: string | null = null;\n const optionsArg = required ? args[0] : args[1];\n if (optionsArg?.type === 'ObjectExpression') {\n for (const prop of optionsArg.properties || []) {\n if (prop.type !== 'ObjectProperty' && prop.type !== 'Property')\n continue;\n if (propKeyName(prop) === 'alias') {\n const sv = stringValue(prop.value);\n if (sv !== null) alias = sv;\n }\n }\n }\n inputs[name] = {\n classPropertyName: name,\n // The binding (public) name is the alias if provided, otherwise\n // the class property name. Without honoring `alias`, host\n // directives that map by public name (e.g.\n // `inputs: ['aria-label']` against `ariaLabel = input(null, {\n // alias: 'aria-label' })`) fail at runtime with NG0311.\n bindingPropertyName: alias ?? name,\n isSignal: true,\n required,\n // Always null for signal inputs. The input() factory already\n // applies the user's transform internally; forwarding it to the\n // directive metadata would make Angular's emitter set the\n // HasDecoratorInputTransform flag, causing the transform to run\n // again via the runtime input setter. Mirrors upstream\n // input_function.ts:74.\n transform: null,\n };\n }\n\n // 2. MODEL SIGNALS (Writable Inputs)\n else if (api === 'model') {\n // model() supports the same options object as input(); honor `alias`\n // for the same reason (host-directive mappings use the public name).\n let alias: string | null = null;\n const optionsArg = required ? args[0] : args[1];\n if (optionsArg?.type === 'ObjectExpression') {\n for (const prop of optionsArg.properties || []) {\n if (prop.type !== 'ObjectProperty' && prop.type !== 'Property')\n continue;\n if (propKeyName(prop) === 'alias') {\n const sv = stringValue(prop.value);\n if (sv !== null) alias = sv;\n }\n }\n }\n inputs[name] = {\n classPropertyName: name,\n bindingPropertyName: alias ?? name,\n isSignal: true,\n // Propagate `.required` so the runtime enforces the unbound-required\n // check. Without this, `model.required(...)` accepts an unbound parent\n // and the model signal stays at its undefined initial value silently.\n required,\n };\n // The compiled `outputs` field is `{ classPropertyName: bindingName }`.\n // Angular inverts this at runtime via\n // `parseAndConvertOutputsForDefinition`, producing the lookup map\n // `{ bindingName: classPropertyName }` used by `listenToOutput`.\n // For a `model()` signal, the class property is `name` and the\n // binding event is `${aliasOrName}Change`, and the model signal\n // itself is the subscribable, so `instance[name]` is what\n // `listenToOutput` needs to resolve.\n outputs[name] = (alias ?? name) + 'Change';\n }\n\n // 3. SIGNAL QUERIES (viewChild, contentChild)\n else if (\n api === 'viewChild' ||\n api === 'viewChildren' ||\n api === 'contentChild' ||\n api === 'contentChildren'\n ) {\n const isViewQuery = api === 'viewChild' || api === 'viewChildren';\n const isChildrenQuery =\n api === 'viewChildren' || api === 'contentChildren';\n\n const firstArg = args[0];\n const sv = stringValue(firstArg);\n\n // Parse the optional second-arg options object for `read` and\n // (content queries only) `descendants`. Without this, queries like\n // `viewChild('ref', { read: ElementRef })` and\n // `contentChildren(Foo, { descendants: false })` silently lose\n // their options at runtime.\n let read: any = null;\n // Defaults match Angular's signal-query API and the decorator\n // path (`isView || isFirst` in detectFieldDecorators):\n // viewChild → true (view queries always traverse)\n // viewChildren → true\n // contentChild → true (single-result content queries\n // traverse by default)\n // contentChildren → false (multi-result content queries are\n // shallow unless explicitly opted in)\n let descendants = isViewQuery || !isChildrenQuery;\n const optArg = args[1];\n if (optArg?.type === 'ObjectExpression') {\n for (const prop of optArg.properties || []) {\n if (prop.type !== 'ObjectProperty' && prop.type !== 'Property')\n continue;\n const k = propKeyName(prop);\n if (k === 'read') {\n read = new o.WrappedNodeExpr(unwrapForwardRefOxc(prop.value));\n } else if (k === 'descendants') {\n const t = prop.value?.type;\n if (\n t === 'BooleanLiteral' ||\n (t === 'Literal' && typeof prop.value.value === 'boolean')\n ) {\n descendants = prop.value.value;\n }\n }\n }\n }\n\n const query = {\n propertyName: name,\n // Class predicates must be wrapped in an `R3QueryReference`\n // (`{ forwardRef, expression }`); Angular's `getQueryPredicate`\n // dispatches on `predicate.forwardRef` and reads\n // `predicate.expression`, so a bare `WrappedNodeExpr` is silently\n // dropped to `undefined` and emitted as `null`, leaving the query\n // with no target. `0 = ForwardRefHandling.None`.\n predicate:\n sv !== null\n ? [sv]\n : { forwardRef: 0, expression: new o.WrappedNodeExpr(firstArg) },\n first: !isChildrenQuery,\n descendants,\n read,\n static: false,\n emitFlags: 0,\n isSignal: true,\n };\n\n if (isViewQuery) viewQueries.push(query);\n else contentQueries.push(query);\n }\n\n // 4. STANDARD OUTPUTS (output() and outputFromObservable())\n else if (api === 'output' || api === 'outputFromObservable') {\n let alias = name;\n // outputFromObservable(observable, options) — options is args[1].\n // output(options) — options is args[0]. Mirrors upstream\n // output_function.ts:81.\n const optArg = api === 'outputFromObservable' ? args[1] : args[0];\n if (optArg?.type === 'ObjectExpression') {\n for (const prop of optArg.properties || []) {\n if (\n (prop.type === 'ObjectProperty' || prop.type === 'Property') &&\n propKeyName(prop) === 'alias'\n ) {\n const sv = stringValue(prop.value);\n if (sv !== null) alias = sv;\n }\n }\n }\n outputs[name] = alias;\n }\n }\n\n return { inputs, outputs, viewQueries, contentQueries };\n}\n\n/**\n * Detect decorator-based field metadata: @Input, @Output, @ViewChild,\n * @ContentChild, @ViewChildren, @ContentChildren, @HostBinding, @HostListener.\n */\nexport function detectFieldDecorators(classNode: any, sourceCode: string) {\n const inputs: any = {};\n const outputs: any = {};\n const viewQueries: any[] = [];\n const contentQueries: any[] = [];\n const hostProperties: Record<string, string> = {};\n const hostListeners: Record<string, string> = {};\n\n const members: any[] = classNode.body?.body || [];\n\n for (const member of members) {\n const decorators: any[] = member.decorators || [];\n if (decorators.length === 0) continue;\n\n const memberName: string = member.key?.name || '';\n\n for (const dec of decorators) {\n const expr = dec.expression;\n if (!expr || expr.type !== 'CallExpression') continue;\n const decName: string | undefined = expr.callee?.name;\n if (!decName) continue;\n const args: any[] = expr.arguments || [];\n\n switch (decName) {\n case 'Input': {\n let bindingName = memberName;\n let required = false;\n let transformFunction: any = null;\n\n if (args.length > 0) {\n const arg = args[0];\n const sv = stringValue(arg);\n if (sv !== null) {\n bindingName = sv;\n } else if (arg.type === 'ObjectExpression') {\n for (const prop of arg.properties || []) {\n if (prop.type !== 'ObjectProperty' && prop.type !== 'Property')\n continue;\n const k = propKeyName(prop);\n if (k === 'alias') {\n const asv = stringValue(prop.value);\n if (asv !== null) bindingName = asv;\n }\n if (k === 'required')\n required =\n sourceCode.slice(prop.value.start, prop.value.end) ===\n 'true';\n if (k === 'transform')\n transformFunction = new o.WrappedNodeExpr(prop.value);\n }\n }\n }\n\n inputs[memberName] = {\n classPropertyName: memberName,\n bindingPropertyName: bindingName,\n isSignal: false,\n required,\n transformFunction,\n };\n break;\n }\n\n case 'Output': {\n const sv = args.length > 0 ? stringValue(args[0]) : null;\n const alias = sv !== null ? sv : memberName;\n outputs[memberName] = alias;\n break;\n }\n\n case 'ViewChild':\n case 'ViewChildren':\n case 'ContentChild':\n case 'ContentChildren': {\n const isView = decName.startsWith('View');\n const isFirst = decName === 'ViewChild' || decName === 'ContentChild';\n\n // Default predicate when no argument is given is the member\n // name. Class predicates (the non-string case) must be wrapped\n // in an `R3QueryReference` (`{ forwardRef, expression }`) so\n // Angular's `getQueryPredicate` can dispatch on `forwardRef`\n // and read `.expression`. A bare `WrappedNodeExpr` is silently\n // dropped to undefined and emitted as `null`.\n let predicate: any = [memberName];\n if (args.length > 0) {\n const pred = args[0];\n const sv = stringValue(pred);\n if (sv !== null) {\n predicate = [sv];\n } else {\n predicate = {\n forwardRef: 0,\n expression: new o.WrappedNodeExpr(unwrapForwardRefOxc(pred)),\n };\n }\n }\n\n let read: any = null;\n let isStatic = false;\n let descendants = isView || isFirst;\n\n if (args.length > 1 && args[1]?.type === 'ObjectExpression') {\n for (const prop of args[1].properties || []) {\n if (prop.type !== 'ObjectProperty' && prop.type !== 'Property')\n continue;\n const k = propKeyName(prop);\n if (k === 'read') read = new o.WrappedNodeExpr(prop.value);\n if (k === 'static')\n isStatic =\n sourceCode.slice(prop.value.start, prop.value.end) === 'true';\n if (k === 'descendants')\n descendants =\n sourceCode.slice(prop.value.start, prop.value.end) === 'true';\n }\n }\n\n const query = {\n propertyName: memberName,\n predicate,\n first: isFirst,\n descendants,\n read,\n static: isStatic,\n emitFlags: 0,\n isSignal: false,\n };\n\n if (isView) viewQueries.push(query);\n else contentQueries.push(query);\n break;\n }\n\n case 'HostBinding': {\n const sv = args.length > 0 ? stringValue(args[0]) : null;\n const target = sv !== null ? sv : memberName;\n hostProperties[target] = memberName;\n break;\n }\n\n case 'HostListener': {\n const sv = args.length > 0 ? stringValue(args[0]) : null;\n if (sv !== null) {\n const event = sv;\n let handler = `${memberName}()`;\n if (args.length > 1 && args[1]?.type === 'ArrayExpression') {\n const handlerArgs = (args[1].elements || [])\n .map((e: any) => stringValue(e))\n .filter((v: string | null): v is string => v !== null)\n .join(', ');\n handler = `${memberName}(${handlerArgs})`;\n }\n hostListeners[event] = handler;\n }\n break;\n }\n }\n }\n }\n\n return {\n inputs,\n outputs,\n viewQueries,\n contentQueries,\n hostProperties,\n hostListeners,\n };\n}\n\n/**\n * Analyze constructor parameters for dependency injection.\n * Returns:\n * - R3DependencyMetadata[] for normal constructors\n * - null if class extends another without own constructor (use inherited factory)\n * - 'invalid' if any parameter has a type-only import token\n *\n * Accepts an OXC ClassDeclaration node and the original source string.\n */\n/**\n * Parse an `@Injectable({ deps: [...] })` dependency list into\n * R3DependencyMetadata. Each element is either a bare token expression or a\n * flag array combining DI modifiers with the token, e.g.\n * `[new Optional(), new SkipSelf(), Token]` or `[new Inject(TOKEN)]`.\n */\nfunction extractInjectableDeps(depsNode: any, sourceCode: string): any[] {\n const deps: any[] = [];\n for (const el of depsNode.elements || []) {\n if (!el) continue;\n let tokenNode: any = el;\n let optional = false,\n self = false,\n skipSelf = false,\n host = false;\n\n if (el.type === 'ArrayExpression') {\n // Flag array: zero or more `new <Modifier>()` instances plus the token.\n tokenNode = null;\n for (const item of el.elements || []) {\n if (!item) continue;\n if (item.type === 'NewExpression') {\n switch (item.callee?.name) {\n case 'Optional':\n optional = true;\n continue;\n case 'Self':\n self = true;\n continue;\n case 'SkipSelf':\n skipSelf = true;\n continue;\n case 'Host':\n host = true;\n continue;\n case 'Inject':\n tokenNode = item.arguments?.[0] ?? null;\n continue;\n }\n }\n // Bare token (identifier, member expression, `new InjectionToken()`…)\n tokenNode = item;\n }\n }\n\n // Unwrap `forwardRef(() => TOKEN)` to TOKEN so the emitted factory\n // references the token directly — matching `extractConstructorDeps` and\n // covering every form (`deps: [forwardRef(...)]`,\n // `[new Inject(forwardRef(...))]`, `[[new Optional(), forwardRef(...)]]`).\n const resolvedToken = tokenNode ? unwrapForwardRefOxc(tokenNode) : null;\n const tokenStr = resolvedToken\n ? sourceCode.slice(resolvedToken.start, resolvedToken.end)\n : null;\n deps.push({\n token: tokenStr\n ? new o.WrappedNodeExpr(tokenStr)\n : new o.LiteralExpr(null),\n attributeNameType: null,\n host,\n optional,\n self,\n skipSelf,\n });\n }\n return deps;\n}\n\nexport function extractConstructorDeps(\n classNode: any,\n sourceCode: string,\n typeOnlyImports: Set<string>,\n): any[] | 'invalid' | null {\n const heritage: any[] = classNode.superClass ? [classNode.superClass] : [];\n const hasSuper = heritage.length > 0;\n\n const members: any[] = classNode.body?.body || [];\n const ctors = members.filter(\n (m: any) => m.type === 'MethodDefinition' && m.kind === 'constructor',\n );\n // With overloaded constructors, only the implementation carries the real\n // parameter list and parameter decorators; the overload *signatures* have\n // `value.body === null`. Picking the first constructor would read an\n // overload signature and emit a factory missing the remaining deps.\n const ctor = ctors.find((m: any) => m.value?.body != null) ?? ctors[0];\n\n if (!ctor) {\n return hasSuper ? null : [];\n }\n\n const params: any[] = ctor.value?.params?.items || ctor.value?.params || [];\n const deps: any[] = [];\n let invalid = false;\n\n for (const param of params) {\n let token: string | null = null;\n // For `@Attribute(...)` the injected value is the attribute name itself,\n // not a type token. `attributeToken` holds that name expression (a string\n // literal for `@Attribute('name')`, or the raw expression for a computed\n // name like `@Attribute(dynamicAttrName())`); `attributeNameType` being\n // non-null flags the dep as an attribute injection so the factory emits\n // `ɵɵinjectAttribute(<name>)` instead of `ɵɵdirectiveInject(...)`.\n let attributeToken: any = null;\n let attributeNameType: any = null;\n let host = false,\n optional = false,\n self = false,\n skipSelf = false;\n\n // Handle TSParameterProperty (e.g., constructor(private foo: Bar))\n const actualParam =\n param.type === 'TSParameterProperty' ? param.parameter : param;\n const typeAnn =\n actualParam?.typeAnnotation?.typeAnnotation ??\n param?.typeAnnotation?.typeAnnotation;\n\n // Extract type annotation as token\n if (typeAnn) {\n if (typeAnn.type === 'TSTypeReference' && typeAnn.typeName) {\n token =\n typeAnn.typeName.name ??\n sourceCode.slice(typeAnn.typeName.start, typeAnn.typeName.end);\n } else if (typeAnn.type === 'TSUnionType') {\n // Filter out null/undefined/void arms — `T | null` and\n // `T | undefined` are common patterns that should resolve to T.\n // Anything else (multiple TypeReference arms, primitives, etc.)\n // is ambiguous and ngtsc rejects it. Mark as invalid so the\n // factory falls through to ɵɵinvalidFactory rather than\n // silently picking the first arm.\n const nonNullTypes = (typeAnn.types || []).filter((t: any) => {\n if (!t) return false;\n if (t.type === 'TSNullKeyword') return false;\n if (t.type === 'TSUndefinedKeyword') return false;\n if (t.type === 'TSVoidKeyword') return false;\n if (\n t.type === 'TSLiteralType' &&\n (t.literal?.type === 'NullLiteral' ||\n (t.literal?.type === 'Literal' && t.literal.value === null))\n ) {\n return false;\n }\n return true;\n });\n if (\n nonNullTypes.length === 1 &&\n nonNullTypes[0].type === 'TSTypeReference' &&\n nonNullTypes[0].typeName\n ) {\n const t = nonNullTypes[0];\n token =\n t.typeName.name ??\n sourceCode.slice(t.typeName.start, t.typeName.end);\n } else {\n // Ambiguous union — no suitable injection token.\n invalid = true;\n continue;\n }\n } else if (typeAnn.type === 'TSIntersectionType') {\n // Intersection types (`A & B`) have no single injection token.\n invalid = true;\n continue;\n }\n }\n\n // Process parameter decorators (may live on TSParameterProperty or inner param)\n const paramDecs: any[] = [\n ...(param.decorators || []),\n ...(param.type === 'TSParameterProperty' && actualParam?.decorators\n ? actualParam.decorators\n : []),\n ];\n for (const dec of paramDecs) {\n const expr = dec.expression;\n if (!expr || expr.type !== 'CallExpression') continue;\n const decName: string | undefined = expr.callee?.name;\n if (!decName) continue;\n const args: any[] = expr.arguments || [];\n\n switch (decName) {\n case 'Inject':\n if (args.length > 0) {\n const sv = stringValue(args[0]);\n if (sv !== null) {\n token = sv;\n } else {\n // Unwrap `@Inject(forwardRef(() => TOKEN))` so the\n // emitted token references TOKEN directly. Without this\n // the raw `forwardRef(() => TOKEN)` source slice would\n // appear in the factory output, producing broken code\n // that calls forwardRef at definition time.\n const unwrapped = unwrapForwardRefOxc(args[0]);\n token = sourceCode.slice(unwrapped.start, unwrapped.end);\n }\n }\n break;\n case 'Optional':\n optional = true;\n break;\n case 'Self':\n self = true;\n break;\n case 'SkipSelf':\n skipSelf = true;\n break;\n case 'Host':\n host = true;\n break;\n case 'Attribute':\n if (args.length > 0) {\n const sv = stringValue(args[0]);\n if (sv !== null) {\n attributeToken = new o.LiteralExpr(sv);\n attributeNameType = new o.LiteralExpr(sv);\n } else {\n // Computed attribute name, e.g. `@Attribute(dynamicAttrName())`.\n // ngtsc emits `ɵɵinjectAttribute(<expr>)`; pass the expression\n // through by value. `attributeNameType` only feeds the (unused)\n // `.d.ts` type, so a placeholder is sufficient to flag the dep.\n attributeToken = new o.WrappedNodeExpr(args[0]);\n attributeNameType = new o.LiteralExpr('unknown');\n }\n token = '';\n }\n break;\n }\n }\n\n if (!token && !attributeToken) {\n invalid = true;\n continue;\n }\n\n if (token && typeOnlyImports.has(token)) {\n invalid = true;\n continue;\n }\n\n deps.push({\n token:\n attributeToken ??\n (token ? new o.WrappedNodeExpr(token) : new o.LiteralExpr(null)),\n attributeNameType,\n host,\n optional,\n self,\n skipSelf,\n });\n }\n\n return invalid ? 'invalid' : deps;\n}\n"],"mappings":"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"}
@@ -1,3 +1,4 @@
1
+ import { parseSync } from "oxc-parser";
1
2
  export interface RegistryInput {
2
3
  classPropertyName: string;
3
4
  bindingPropertyName: string;
@@ -20,6 +21,12 @@ export interface RegistryEntry {
20
21
  pipeName?: string;
21
22
  /** Exported class names (only for NgModules) */
22
23
  exports?: string[];
24
+ /** Declared class names (only for NgModules) — used to wire non-standalone
25
+ * component scope from the declaring module. */
26
+ declarations?: string[];
27
+ /** Imported module/class names (only for NgModules) — expanded transitively
28
+ * to compute the directive/pipe scope of declared components. */
29
+ imports?: string[];
23
30
  /**
24
31
  * Member class names (only for `tuple` kind) — produced by top-level
25
32
  * `export const X = [A, B, C] as const` style barrels common in
@@ -46,4 +53,4 @@ export type ComponentRegistry = Map<string, RegistryEntry>;
46
53
  * Lightweight scan of a TypeScript file to extract Angular decorator metadata
47
54
  * without performing full compilation. Uses OXC's native Rust parser for speed.
48
55
  */
49
- export declare function scanFile(code: string, fileName: string): RegistryEntry[];
56
+ export declare function scanFile(code: string, fileName: string, program?: ReturnType<typeof parseSync>["program"]): RegistryEntry[];
@@ -6,10 +6,10 @@ var DECORATOR_RE = new RegExp(`@(${[...COMPILABLE_DECORATORS].join("|")})`);
6
6
  * Lightweight scan of a TypeScript file to extract Angular decorator metadata
7
7
  * without performing full compilation. Uses OXC's native Rust parser for speed.
8
8
  */
9
- function scanFile(code, fileName) {
9
+ function scanFile(code, fileName, program) {
10
10
  const entries = [];
11
11
  if (!DECORATOR_RE.test(code) && !/\bconst\s+\w+\s*=\s*\[/.test(code)) return entries;
12
- const { program } = parseSync(fileName, code);
12
+ program ??= parseSync(fileName, code).program;
13
13
  for (const node of program.body) {
14
14
  const varDecl = node.type === "ExportNamedDeclaration" && node.declaration?.type === "VariableDeclaration" ? node.declaration : node.type === "VariableDeclaration" ? node : null;
15
15
  if (!varDecl || varDecl.kind !== "const") continue;
@@ -54,18 +54,30 @@ function scanFile(code, fileName) {
54
54
  let selector;
55
55
  let pipeName;
56
56
  let moduleExports;
57
+ let moduleDeclarations;
58
+ let moduleImports;
59
+ const classNamesFrom = (val) => (val?.elements ?? []).map((e) => {
60
+ if (e?.type === "Identifier") return e.name;
61
+ if (e?.type === "CallExpression" && (e.callee?.type === "StaticMemberExpression" || e.callee?.type === "MemberExpression") && e.callee.object?.type === "Identifier") return e.callee.object.name;
62
+ }).filter((n) => typeof n === "string");
57
63
  for (const prop of arg.properties) {
58
64
  if (prop.type !== "Property") continue;
59
65
  const key = prop.key?.name || prop.key?.value;
60
66
  const val = prop.value;
61
67
  if (key === "selector" && val?.type === "Literal" && typeof val.value === "string") selector = val.value;
62
68
  if (key === "name" && val?.type === "Literal" && typeof val.value === "string" && decoratorName === "Pipe") pipeName = val.value;
63
- if (key === "exports" && val?.type === "ArrayExpression" && decoratorName === "NgModule") moduleExports = val.elements.filter((e) => e?.type === "Identifier").map((e) => e.name);
69
+ if (val?.type === "ArrayExpression" && decoratorName === "NgModule") {
70
+ if (key === "exports") moduleExports = classNamesFrom(val);
71
+ else if (key === "declarations") moduleDeclarations = classNamesFrom(val);
72
+ else if (key === "imports") moduleImports = classNamesFrom(val);
73
+ }
64
74
  }
65
75
  if (decoratorName === "NgModule") entries.push({
66
76
  selector: className,
67
77
  kind: "ngmodule",
68
78
  exports: moduleExports || [],
79
+ declarations: moduleDeclarations || [],
80
+ imports: moduleImports || [],
69
81
  fileName,
70
82
  className
71
83
  });
@@ -1 +1 @@
1
- {"version":3,"file":"registry.js","names":[],"sources":["../../../../src/lib/compiler/registry.ts"],"sourcesContent":["import { parseSync } from 'oxc-parser';\nimport { COMPILABLE_DECORATORS } from './constants.js';\n\nexport interface RegistryInput {\n classPropertyName: string;\n bindingPropertyName: string;\n isSignal: boolean;\n required: boolean;\n /**\n * `true` when the input declares a `transform` function. The actual\n * transform expression isn't usable cross-file, but downstream tools\n * (template type checking, codegen widening) need to know whether\n * one exists so they can broaden the accepted binding type.\n */\n hasTransform?: boolean;\n}\n\nexport interface RegistryEntry {\n /** CSS selector for components/directives, pipe name for pipes, class name for NgModules */\n selector: string;\n /** What kind of Angular declaration this is */\n kind: 'component' | 'directive' | 'pipe' | 'ngmodule' | 'tuple';\n /** The pipe name (only for pipes) */\n pipeName?: string;\n /** Exported class names (only for NgModules) */\n exports?: string[];\n /**\n * Member class names (only for `tuple` kind) — produced by top-level\n * `export const X = [A, B, C] as const` style barrels common in\n * helm/spartan-style libraries. The compiler expands these into the\n * underlying directives when they appear in another component's\n * `imports` array, mirroring how Angular's official compiler resolves\n * static `imports` references at compile time.\n */\n members?: string[];\n /** The source file this declaration was found in */\n fileName: string;\n /** The class name */\n className: string;\n /** Input bindings (from signal APIs and @Input decorators) */\n inputs?: Record<string, RegistryInput>;\n /** Output bindings (from signal APIs and @Output decorators) */\n outputs?: Record<string, string>;\n /** The package this declaration was scanned from (e.g. \"@angular/cdk\") */\n sourcePackage?: string;\n}\n\n/** Maps class name → registry entry */\nexport type ComponentRegistry = Map<string, RegistryEntry>;\n\nconst DECORATOR_RE = new RegExp(`@(${[...COMPILABLE_DECORATORS].join('|')})`);\n\n/**\n * Lightweight scan of a TypeScript file to extract Angular decorator metadata\n * without performing full compilation. Uses OXC's native Rust parser for speed.\n */\nexport function scanFile(code: string, fileName: string): RegistryEntry[] {\n const entries: RegistryEntry[] = [];\n\n // Fast regex pre-filter — skip files with neither Angular decorators\n // nor a top-level `const X = [...]` that might be a directive tuple\n // barrel re-export.\n if (!DECORATOR_RE.test(code) && !/\\bconst\\s+\\w+\\s*=\\s*\\[/.test(code)) {\n return entries;\n }\n\n const { program } = parseSync(fileName, code);\n\n // First pass: collect tuple barrels — top-level `const X = [A, B, C]`\n // (with or without `export`/`as const`) where every element is a bare\n // class identifier. These are how spartan-style libraries expose a\n // group of directives behind a single import (e.g. `HlmSelectImports`).\n // Without registering them, the fast-compile path treats the bare\n // identifier as an unknown directive and Angular's runtime never\n // matches the underlying classes.\n for (const node of program.body) {\n const varDecl =\n node.type === 'ExportNamedDeclaration' &&\n (node as any).declaration?.type === 'VariableDeclaration'\n ? (node as any).declaration\n : node.type === 'VariableDeclaration'\n ? node\n : null;\n if (!varDecl || varDecl.kind !== 'const') continue;\n for (const declarator of varDecl.declarations || []) {\n if (declarator.id?.type !== 'Identifier') continue;\n // Unwrap `arr as const` → ArrayExpression\n let init = declarator.init;\n if (init?.type === 'TSAsExpression') init = init.expression;\n if (init?.type !== 'ArrayExpression') continue;\n const members: string[] = [];\n let allClassRefs = true;\n for (const el of init.elements || []) {\n if (el?.type !== 'Identifier') {\n allClassRefs = false;\n break;\n }\n members.push(el.name);\n }\n if (!allClassRefs || members.length === 0) continue;\n const tupleName: string = declarator.id.name;\n entries.push({\n selector: tupleName,\n kind: 'tuple',\n members,\n fileName,\n className: tupleName,\n });\n }\n }\n\n for (const node of program.body) {\n // Handle `class Foo {}`, `export class Foo {}`, and `export default class Foo {}`\n const decl =\n node.type === 'ExportNamedDeclaration' ||\n node.type === 'ExportDefaultDeclaration'\n ? (node as any).declaration\n : node;\n if (!decl || decl.type !== 'ClassDeclaration') continue;\n // Skip anonymous default exports (no name to register)\n if (!decl.id?.name) continue;\n\n const className: string = decl.id.name;\n const decorators: any[] = decl.decorators || [];\n\n for (const dec of decorators) {\n const expr = dec.expression;\n if (!expr || expr.type !== 'CallExpression') continue;\n\n const decoratorName: string = expr.callee?.name;\n if (!COMPILABLE_DECORATORS.has(decoratorName)) continue;\n\n const arg = expr.arguments?.[0];\n if (!arg || arg.type !== 'ObjectExpression') continue;\n\n let selector: string | undefined;\n let pipeName: string | undefined;\n let moduleExports: string[] | undefined;\n\n for (const prop of arg.properties) {\n if (prop.type !== 'Property') continue;\n const key: string = prop.key?.name || prop.key?.value;\n const val = prop.value;\n\n if (\n key === 'selector' &&\n val?.type === 'Literal' &&\n typeof val.value === 'string'\n ) {\n selector = val.value;\n }\n if (\n key === 'name' &&\n val?.type === 'Literal' &&\n typeof val.value === 'string' &&\n decoratorName === 'Pipe'\n ) {\n pipeName = val.value;\n }\n if (\n key === 'exports' &&\n val?.type === 'ArrayExpression' &&\n decoratorName === 'NgModule'\n ) {\n moduleExports = val.elements\n .filter((e: any) => e?.type === 'Identifier')\n .map((e: any) => e.name);\n }\n }\n\n if (decoratorName === 'NgModule') {\n entries.push({\n selector: className,\n kind: 'ngmodule',\n exports: moduleExports || [],\n fileName,\n className,\n });\n } else if (decoratorName === 'Pipe' && pipeName) {\n entries.push({\n selector: pipeName,\n kind: 'pipe',\n pipeName,\n fileName,\n className,\n });\n } else if (selector) {\n // Extract inputs/outputs from class members\n const inputs: Record<string, RegistryInput> = {};\n const outputs: Record<string, string> = {};\n const members: any[] = decl.body?.body || [];\n\n for (const member of members) {\n if (member.type !== 'PropertyDefinition' || !member.key?.name)\n continue;\n const name: string = member.key.name;\n const init = member.value;\n\n // Signal APIs: input(), input.required(), model(), output()\n if (init?.type === 'CallExpression') {\n const callee = init.callee;\n let calleeName = '';\n if (callee?.type === 'Identifier') {\n calleeName = callee.name;\n } else if (\n callee?.type === 'StaticMemberExpression' ||\n callee?.type === 'MemberExpression'\n ) {\n calleeName =\n (callee.object?.name || '') +\n '.' +\n (callee.property?.name || '');\n }\n\n // Extract `alias` from an options object at the given\n // argument index. Used for input/model (options at index 1,\n // or 0 for the `.required` variants) and for output (options\n // at index 0). Without this, host-directive mappings that\n // reference the public name (e.g. `inputs: ['aria-label']`,\n // `outputs: ['publicEvent']`) fail to resolve.\n const aliasFromArg = (argIndex: number): string | null => {\n const optionsArg = init.arguments?.[argIndex];\n if (optionsArg?.type !== 'ObjectExpression') return null;\n for (const prop of optionsArg.properties || []) {\n if (prop.type !== 'ObjectProperty' && prop.type !== 'Property')\n continue;\n const k = prop.key?.name ?? prop.key?.value;\n if (k !== 'alias') continue;\n const v = prop.value;\n if (\n v?.type === 'StringLiteral' ||\n (v?.type === 'Literal' && typeof v.value === 'string')\n ) {\n return v.value;\n }\n }\n return null;\n };\n // Detect a `transform: ...` entry in the input options object\n // so cross-file consumers know the binding type is widened.\n const hasTransformAtArg = (argIndex: number): boolean => {\n const optionsArg = init.arguments?.[argIndex];\n if (optionsArg?.type !== 'ObjectExpression') return false;\n for (const prop of optionsArg.properties || []) {\n if (prop.type !== 'ObjectProperty' && prop.type !== 'Property')\n continue;\n const k = prop.key?.name ?? prop.key?.value;\n if (k === 'transform') return true;\n }\n return false;\n };\n const inputAliasIndex =\n calleeName === 'input.required' || calleeName === 'model.required'\n ? 0\n : 1;\n\n if (calleeName === 'input' || calleeName === 'input.required') {\n const alias = aliasFromArg(inputAliasIndex);\n const hasTransform = hasTransformAtArg(inputAliasIndex);\n inputs[name] = {\n classPropertyName: name,\n bindingPropertyName: alias ?? name,\n isSignal: true,\n required: calleeName === 'input.required',\n ...(hasTransform ? { hasTransform: true } : {}),\n };\n } else if (\n calleeName === 'model' ||\n calleeName === 'model.required'\n ) {\n const alias = aliasFromArg(inputAliasIndex);\n inputs[name] = {\n classPropertyName: name,\n bindingPropertyName: alias ?? name,\n isSignal: true,\n required: calleeName === 'model.required',\n };\n // outputs map is `{ classPropertyName: bindingName }` —\n // for a model, the class property is `name` and the\n // binding name is `${aliasOrName}Change`.\n outputs[name] = (alias ?? name) + 'Change';\n } else if (\n calleeName === 'output' ||\n calleeName === 'outputFromObservable'\n ) {\n // output() options at arg[0]; outputFromObservable(source,\n // opts?) options at arg[1].\n const alias = aliasFromArg(\n calleeName === 'outputFromObservable' ? 1 : 0,\n );\n outputs[name] = alias ?? name;\n }\n }\n\n // Decorator-based: @Input(), @Output()\n const memberDecorators: any[] = member.decorators || [];\n for (const mdec of memberDecorators) {\n const mexpr = mdec.expression;\n if (!mexpr) continue;\n const mdecName =\n mexpr.type === 'CallExpression'\n ? mexpr.callee?.name\n : mexpr.type === 'Identifier'\n ? mexpr.name\n : undefined;\n if (mdecName === 'Input') {\n const alias =\n mexpr.arguments?.[0]?.type === 'Literal'\n ? mexpr.arguments[0].value\n : name;\n inputs[name] = {\n classPropertyName: name,\n bindingPropertyName: alias || name,\n isSignal: false,\n required: false,\n };\n } else if (mdecName === 'Output') {\n const alias =\n mexpr.arguments?.[0]?.type === 'Literal'\n ? mexpr.arguments[0].value\n : name;\n outputs[name] = alias || name;\n }\n }\n }\n\n entries.push({\n selector: selector.split(',')[0].trim(),\n kind: decoratorName === 'Component' ? 'component' : 'directive',\n fileName,\n className,\n ...(Object.keys(inputs).length > 0 ? { inputs } : {}),\n ...(Object.keys(outputs).length > 0 ? { outputs } : {}),\n });\n }\n }\n }\n\n return entries;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"registry.js","names":[],"sources":["../../../../src/lib/compiler/registry.ts"],"sourcesContent":["import { parseSync } from 'oxc-parser';\nimport { COMPILABLE_DECORATORS } from './constants.js';\n\nexport interface RegistryInput {\n classPropertyName: string;\n bindingPropertyName: string;\n isSignal: boolean;\n required: boolean;\n /**\n * `true` when the input declares a `transform` function. The actual\n * transform expression isn't usable cross-file, but downstream tools\n * (template type checking, codegen widening) need to know whether\n * one exists so they can broaden the accepted binding type.\n */\n hasTransform?: boolean;\n}\n\nexport interface RegistryEntry {\n /** CSS selector for components/directives, pipe name for pipes, class name for NgModules */\n selector: string;\n /** What kind of Angular declaration this is */\n kind: 'component' | 'directive' | 'pipe' | 'ngmodule' | 'tuple';\n /** The pipe name (only for pipes) */\n pipeName?: string;\n /** Exported class names (only for NgModules) */\n exports?: string[];\n /** Declared class names (only for NgModules) — used to wire non-standalone\n * component scope from the declaring module. */\n declarations?: string[];\n /** Imported module/class names (only for NgModules) — expanded transitively\n * to compute the directive/pipe scope of declared components. */\n imports?: string[];\n /**\n * Member class names (only for `tuple` kind) — produced by top-level\n * `export const X = [A, B, C] as const` style barrels common in\n * helm/spartan-style libraries. The compiler expands these into the\n * underlying directives when they appear in another component's\n * `imports` array, mirroring how Angular's official compiler resolves\n * static `imports` references at compile time.\n */\n members?: string[];\n /** The source file this declaration was found in */\n fileName: string;\n /** The class name */\n className: string;\n /** Input bindings (from signal APIs and @Input decorators) */\n inputs?: Record<string, RegistryInput>;\n /** Output bindings (from signal APIs and @Output decorators) */\n outputs?: Record<string, string>;\n /** The package this declaration was scanned from (e.g. \"@angular/cdk\") */\n sourcePackage?: string;\n}\n\n/** Maps class name → registry entry */\nexport type ComponentRegistry = Map<string, RegistryEntry>;\n\nconst DECORATOR_RE = new RegExp(`@(${[...COMPILABLE_DECORATORS].join('|')})`);\n\n/**\n * Lightweight scan of a TypeScript file to extract Angular decorator metadata\n * without performing full compilation. Uses OXC's native Rust parser for speed.\n */\nexport function scanFile(\n code: string,\n fileName: string,\n program?: ReturnType<typeof parseSync>['program'],\n): RegistryEntry[] {\n const entries: RegistryEntry[] = [];\n\n // Fast regex pre-filter — skip files with neither Angular decorators\n // nor a top-level `const X = [...]` that might be a directive tuple\n // barrel re-export.\n if (!DECORATOR_RE.test(code) && !/\\bconst\\s+\\w+\\s*=\\s*\\[/.test(code)) {\n return entries;\n }\n\n program ??= parseSync(fileName, code).program;\n\n // First pass: collect tuple barrels — top-level `const X = [A, B, C]`\n // (with or without `export`/`as const`) where every element is a bare\n // class identifier. These are how spartan-style libraries expose a\n // group of directives behind a single import (e.g. `HlmSelectImports`).\n // Without registering them, the fast-compile path treats the bare\n // identifier as an unknown directive and Angular's runtime never\n // matches the underlying classes.\n for (const node of program.body) {\n const varDecl =\n node.type === 'ExportNamedDeclaration' &&\n (node as any).declaration?.type === 'VariableDeclaration'\n ? (node as any).declaration\n : node.type === 'VariableDeclaration'\n ? node\n : null;\n if (!varDecl || varDecl.kind !== 'const') continue;\n for (const declarator of varDecl.declarations || []) {\n if (declarator.id?.type !== 'Identifier') continue;\n // Unwrap `arr as const` → ArrayExpression\n let init = declarator.init;\n if (init?.type === 'TSAsExpression') init = init.expression;\n if (init?.type !== 'ArrayExpression') continue;\n const members: string[] = [];\n let allClassRefs = true;\n for (const el of init.elements || []) {\n if (el?.type !== 'Identifier') {\n allClassRefs = false;\n break;\n }\n members.push(el.name);\n }\n if (!allClassRefs || members.length === 0) continue;\n const tupleName: string = declarator.id.name;\n entries.push({\n selector: tupleName,\n kind: 'tuple',\n members,\n fileName,\n className: tupleName,\n });\n }\n }\n\n for (const node of program.body) {\n // Handle `class Foo {}`, `export class Foo {}`, and `export default class Foo {}`\n const decl =\n node.type === 'ExportNamedDeclaration' ||\n node.type === 'ExportDefaultDeclaration'\n ? (node as any).declaration\n : node;\n if (!decl || decl.type !== 'ClassDeclaration') continue;\n // Skip anonymous default exports (no name to register)\n if (!decl.id?.name) continue;\n\n const className: string = decl.id.name;\n const decorators: any[] = decl.decorators || [];\n\n for (const dec of decorators) {\n const expr = dec.expression;\n if (!expr || expr.type !== 'CallExpression') continue;\n\n const decoratorName: string = expr.callee?.name;\n if (!COMPILABLE_DECORATORS.has(decoratorName)) continue;\n\n const arg = expr.arguments?.[0];\n if (!arg || arg.type !== 'ObjectExpression') continue;\n\n let selector: string | undefined;\n let pipeName: string | undefined;\n let moduleExports: string[] | undefined;\n let moduleDeclarations: string[] | undefined;\n let moduleImports: string[] | undefined;\n\n // Class names from an NgModule metadata array: bare `Identifier`s and the\n // module out of `Module.forRoot(...)`/`forChild(...)` ModuleWithProviders.\n const classNamesFrom = (val: any): string[] =>\n (val?.elements ?? [])\n .map((e: any) => {\n if (e?.type === 'Identifier') return e.name;\n if (\n e?.type === 'CallExpression' &&\n // OXC emits `StaticMemberExpression`; the ESTree shape some\n // versions produce uses `MemberExpression`. Accept both (matches\n // the other member-expression checks in this file).\n (e.callee?.type === 'StaticMemberExpression' ||\n e.callee?.type === 'MemberExpression') &&\n e.callee.object?.type === 'Identifier'\n ) {\n return e.callee.object.name;\n }\n return undefined;\n })\n .filter((n: unknown): n is string => typeof n === 'string');\n\n for (const prop of arg.properties) {\n if (prop.type !== 'Property') continue;\n const key: string = prop.key?.name || prop.key?.value;\n const val = prop.value;\n\n if (\n key === 'selector' &&\n val?.type === 'Literal' &&\n typeof val.value === 'string'\n ) {\n selector = val.value;\n }\n if (\n key === 'name' &&\n val?.type === 'Literal' &&\n typeof val.value === 'string' &&\n decoratorName === 'Pipe'\n ) {\n pipeName = val.value;\n }\n if (val?.type === 'ArrayExpression' && decoratorName === 'NgModule') {\n if (key === 'exports') moduleExports = classNamesFrom(val);\n else if (key === 'declarations')\n moduleDeclarations = classNamesFrom(val);\n else if (key === 'imports') moduleImports = classNamesFrom(val);\n }\n }\n\n if (decoratorName === 'NgModule') {\n entries.push({\n selector: className,\n kind: 'ngmodule',\n exports: moduleExports || [],\n declarations: moduleDeclarations || [],\n imports: moduleImports || [],\n fileName,\n className,\n });\n } else if (decoratorName === 'Pipe' && pipeName) {\n entries.push({\n selector: pipeName,\n kind: 'pipe',\n pipeName,\n fileName,\n className,\n });\n } else if (selector) {\n // Extract inputs/outputs from class members\n const inputs: Record<string, RegistryInput> = {};\n const outputs: Record<string, string> = {};\n const members: any[] = decl.body?.body || [];\n\n for (const member of members) {\n if (member.type !== 'PropertyDefinition' || !member.key?.name)\n continue;\n const name: string = member.key.name;\n const init = member.value;\n\n // Signal APIs: input(), input.required(), model(), output()\n if (init?.type === 'CallExpression') {\n const callee = init.callee;\n let calleeName = '';\n if (callee?.type === 'Identifier') {\n calleeName = callee.name;\n } else if (\n callee?.type === 'StaticMemberExpression' ||\n callee?.type === 'MemberExpression'\n ) {\n calleeName =\n (callee.object?.name || '') +\n '.' +\n (callee.property?.name || '');\n }\n\n // Extract `alias` from an options object at the given\n // argument index. Used for input/model (options at index 1,\n // or 0 for the `.required` variants) and for output (options\n // at index 0). Without this, host-directive mappings that\n // reference the public name (e.g. `inputs: ['aria-label']`,\n // `outputs: ['publicEvent']`) fail to resolve.\n const aliasFromArg = (argIndex: number): string | null => {\n const optionsArg = init.arguments?.[argIndex];\n if (optionsArg?.type !== 'ObjectExpression') return null;\n for (const prop of optionsArg.properties || []) {\n if (prop.type !== 'ObjectProperty' && prop.type !== 'Property')\n continue;\n const k = prop.key?.name ?? prop.key?.value;\n if (k !== 'alias') continue;\n const v = prop.value;\n if (\n v?.type === 'StringLiteral' ||\n (v?.type === 'Literal' && typeof v.value === 'string')\n ) {\n return v.value;\n }\n }\n return null;\n };\n // Detect a `transform: ...` entry in the input options object\n // so cross-file consumers know the binding type is widened.\n const hasTransformAtArg = (argIndex: number): boolean => {\n const optionsArg = init.arguments?.[argIndex];\n if (optionsArg?.type !== 'ObjectExpression') return false;\n for (const prop of optionsArg.properties || []) {\n if (prop.type !== 'ObjectProperty' && prop.type !== 'Property')\n continue;\n const k = prop.key?.name ?? prop.key?.value;\n if (k === 'transform') return true;\n }\n return false;\n };\n const inputAliasIndex =\n calleeName === 'input.required' || calleeName === 'model.required'\n ? 0\n : 1;\n\n if (calleeName === 'input' || calleeName === 'input.required') {\n const alias = aliasFromArg(inputAliasIndex);\n const hasTransform = hasTransformAtArg(inputAliasIndex);\n inputs[name] = {\n classPropertyName: name,\n bindingPropertyName: alias ?? name,\n isSignal: true,\n required: calleeName === 'input.required',\n ...(hasTransform ? { hasTransform: true } : {}),\n };\n } else if (\n calleeName === 'model' ||\n calleeName === 'model.required'\n ) {\n const alias = aliasFromArg(inputAliasIndex);\n inputs[name] = {\n classPropertyName: name,\n bindingPropertyName: alias ?? name,\n isSignal: true,\n required: calleeName === 'model.required',\n };\n // outputs map is `{ classPropertyName: bindingName }` —\n // for a model, the class property is `name` and the\n // binding name is `${aliasOrName}Change`.\n outputs[name] = (alias ?? name) + 'Change';\n } else if (\n calleeName === 'output' ||\n calleeName === 'outputFromObservable'\n ) {\n // output() options at arg[0]; outputFromObservable(source,\n // opts?) options at arg[1].\n const alias = aliasFromArg(\n calleeName === 'outputFromObservable' ? 1 : 0,\n );\n outputs[name] = alias ?? name;\n }\n }\n\n // Decorator-based: @Input(), @Output()\n const memberDecorators: any[] = member.decorators || [];\n for (const mdec of memberDecorators) {\n const mexpr = mdec.expression;\n if (!mexpr) continue;\n const mdecName =\n mexpr.type === 'CallExpression'\n ? mexpr.callee?.name\n : mexpr.type === 'Identifier'\n ? mexpr.name\n : undefined;\n if (mdecName === 'Input') {\n const alias =\n mexpr.arguments?.[0]?.type === 'Literal'\n ? mexpr.arguments[0].value\n : name;\n inputs[name] = {\n classPropertyName: name,\n bindingPropertyName: alias || name,\n isSignal: false,\n required: false,\n };\n } else if (mdecName === 'Output') {\n const alias =\n mexpr.arguments?.[0]?.type === 'Literal'\n ? mexpr.arguments[0].value\n : name;\n outputs[name] = alias || name;\n }\n }\n }\n\n entries.push({\n selector: selector.split(',')[0].trim(),\n kind: decoratorName === 'Component' ? 'component' : 'directive',\n fileName,\n className,\n ...(Object.keys(inputs).length > 0 ? { inputs } : {}),\n ...(Object.keys(outputs).length > 0 ? { outputs } : {}),\n });\n }\n }\n }\n\n return entries;\n}\n"],"mappings":"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"}
@@ -1,21 +1,43 @@
1
+ import { parseSync } from "oxc-parser";
2
+ export interface InlineResourceResult {
3
+ /** The modified source code, or the original if no changes were needed. */
4
+ code: string;
5
+ /**
6
+ * Source extension (without the leading dot, lower-cased — e.g. `scss`) of
7
+ * each inlined external style, keyed by its position in the flat per-file
8
+ * style list produced by {@link extractInlineStyles}. Lets the caller run
9
+ * each external `styleUrl` through the right preprocessor by its own file
10
+ * extension, independent of the `inlineStylesExtension` option (which governs
11
+ * truly-inline `styles: [...]` template strings).
12
+ */
13
+ styleExtensions: Map<number, string>;
14
+ /**
15
+ * Absolute paths of every external resource file successfully read and
16
+ * inlined. Callers record these so a later edit to the resource file can
17
+ * invalidate the owning source module — the inlined copy is otherwise
18
+ * invisible to the module graph.
19
+ */
20
+ resourceDependencies: string[];
21
+ }
1
22
  /**
2
23
  * Inline external templateUrl and styleUrl/styleUrls into the source code
3
24
  * using OXC parser for precise AST-based rewriting.
4
25
  *
5
26
  * Replaces:
6
27
  * templateUrl: './file.html' → template: "...file contents..."
7
- * styleUrl: './file.css' → styles: ["...file contents..."]
8
- * styleUrls: ['./a.css'] → styles: ["...contents..."]
28
+ * styleUrl: './file.scss' → styles: ["...file contents..."]
29
+ * styleUrls: ['./a.scss'] → styles: ["...contents..."]
9
30
  *
10
31
  * When the decorator already has a `styles: [...]` array, inlined CSS is
11
32
  * merged into that existing array instead of emitting a second `styles`
12
33
  * property (which would be a duplicate object literal key).
13
34
  *
14
- * Returns the modified source code, or the original if no changes were needed.
35
+ * Returns the modified source code plus the per-style-index extension map
36
+ * (see {@link InlineResourceResult}).
15
37
  */
16
- export declare function inlineResourceUrls(code: string, fileName: string): string;
38
+ export declare function inlineResourceUrls(code: string, fileName: string): Promise<InlineResourceResult>;
17
39
  /**
18
40
  * Extract inline style strings from Angular @Component decorator using OXC parser.
19
41
  * Returns an array of style string values for preprocessing.
20
42
  */
21
- export declare function extractInlineStyles(code: string, fileName: string): string[];
43
+ export declare function extractInlineStyles(code: string, fileName: string, program?: ReturnType<typeof parseSync>["program"]): string[];