@analogjs/vite-plugin-angular 3.0.0-alpha.34 → 3.0.0-alpha.36

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -89,3 +89,9 @@ Create a `tsconfig.app.json` in the root of the project.
89
89
  "include": ["src/**/*.ts"]
90
90
  }
91
91
  ```
92
+
93
+ ## Tailwind CSS v4
94
+
95
+ For Angular component styles that use Tailwind utilities like `@apply`, configure `tailwindCss.rootStylesheet` and follow the Tailwind guide for Analog:
96
+
97
+ - https://analogjs.org/docs/integrations/tailwind
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@analogjs/vite-plugin-angular",
3
- "version": "3.0.0-alpha.34",
3
+ "version": "3.0.0-alpha.36",
4
4
  "description": "Vite Plugin for Angular",
5
5
  "type": "module",
6
6
  "keywords": [
@@ -36,7 +36,7 @@
36
36
  }
37
37
  },
38
38
  "dependencies": {
39
- "@analogjs/angular-compiler": "3.0.0-alpha.34",
39
+ "@analogjs/angular-compiler": "3.0.0-alpha.36",
40
40
  "es-toolkit": "^1.45.1",
41
41
  "obug": "^2.1.1",
42
42
  "oxc-parser": "^0.124.0",
@@ -32,14 +32,14 @@ export interface PluginOptions {
32
32
  include?: string[];
33
33
  additionalContentDirs?: string[];
34
34
  /**
35
- * Enables Angular's HMR during development/watch mode.
35
+ * Enables Analog's Angular live-reload/HMR pipeline during development/watch mode.
36
36
  *
37
- * Defaults to `true` for watch mode. Set to `false` to disable HMR while
38
- * keeping other stylesheet externalization behavior available when needed.
39
- */
40
- hmr?: boolean;
41
- /**
42
- * @deprecated Use `hmr` instead. Kept as a compatibility alias.
37
+ * This is separate from Vite's `server.hmr` option, which configures the
38
+ * HMR client transport.
39
+ *
40
+ * Defaults to `true` for watch mode. Set to `false` to disable Angular
41
+ * reload updates while keeping other stylesheet externalization behavior
42
+ * available when needed.
43
43
  */
44
44
  liveReload?: boolean;
45
45
  disableTypeChecking?: boolean;
@@ -1,7 +1,7 @@
1
1
  import { angularFullVersion, cjt, createAngularCompilation, sourceFileCache } from "./utils/devkit.js";
2
2
  import { getJsTransformConfigKey, isRolldown } from "./utils/rolldown.js";
3
3
  import { buildOptimizerPlugin } from "./angular-build-optimizer-plugin.js";
4
- import { activateDeferredDebug, applyDebugOption, debugCompilationApi, debugCompiler, debugCompilerV, debugHmr, debugHmrV, debugStyles, debugStylesV, debugTailwind, debugTailwindV } from "./utils/debug.js";
4
+ import { activateDeferredDebug, applyDebugOption, debugCompilationApi, debugCompiler, debugCompilerV, debugEmit, debugEmitV, debugHmr, debugHmrV, debugStyles, debugStylesV, debugTailwind, debugTailwindV } from "./utils/debug.js";
5
5
  import { inspectCssTailwindDirectives, isTailwindReferenceError, throwTailwindReferenceTextError } from "./utils/tailwind-reference.js";
6
6
  import { jitPlugin } from "./angular-jit-plugin.js";
7
7
  import { createCompilerPlugin, createRolldownCompilerPlugin } from "./compiler-plugin.js";
@@ -113,6 +113,7 @@ function buildStylePreprocessor(options) {
113
113
  }
114
114
  function angular(options) {
115
115
  applyDebugOption(options?.debug, options?.workspaceRoot);
116
+ const liveReload = options?.liveReload ?? true;
116
117
  /**
117
118
  * Normalize plugin options so defaults
118
119
  * are used for values not provided.
@@ -130,7 +131,7 @@ function angular(options) {
130
131
  jit: options?.jit,
131
132
  include: options?.include ?? [],
132
133
  additionalContentDirs: options?.additionalContentDirs ?? [],
133
- hmr: options?.hmr ?? options?.liveReload ?? true,
134
+ liveReload,
134
135
  disableTypeChecking: options?.disableTypeChecking ?? true,
135
136
  fileReplacements: options?.fileReplacements ?? [],
136
137
  useAngularCompilationAPI: options?.experimental?.useAngularCompilationAPI ?? false,
@@ -144,6 +145,7 @@ function angular(options) {
144
145
  let builder;
145
146
  let nextProgram;
146
147
  const tsconfigOptionsCache = /* @__PURE__ */ new Map();
148
+ const tsconfigGraphRootCache = /* @__PURE__ */ new Map();
147
149
  let cachedHost;
148
150
  let cachedHostKey;
149
151
  let includeCache = [];
@@ -152,6 +154,7 @@ function angular(options) {
152
154
  }
153
155
  function invalidateTsconfigCaches() {
154
156
  tsconfigOptionsCache.clear();
157
+ tsconfigGraphRootCache.clear();
155
158
  cachedHost = void 0;
156
159
  cachedHostKey = void 0;
157
160
  }
@@ -162,8 +165,11 @@ function angular(options) {
162
165
  const classNameOwners = /* @__PURE__ */ new Map();
163
166
  const transformedStyleOwnerMetadata = /* @__PURE__ */ new Map();
164
167
  const styleSourceOwners = /* @__PURE__ */ new Map();
165
- function shouldEnableHmr() {
166
- return !!((isTest ? testWatchMode : watchMode) && pluginOptions.hmr);
168
+ function hasViteHmrTransport() {
169
+ return resolvedConfig ? resolvedConfig.server.hmr !== false : true;
170
+ }
171
+ function shouldEnableLiveReload() {
172
+ return !!((isTest ? testWatchMode : watchMode) && pluginOptions.liveReload && hasViteHmrTransport());
167
173
  }
168
174
  /**
169
175
  * Determines whether Angular should externalize component styles.
@@ -183,7 +189,7 @@ function angular(options) {
183
189
  */
184
190
  function shouldExternalizeStyles() {
185
191
  if (!(isTest ? testWatchMode : watchMode)) return false;
186
- return !!(shouldEnableHmr() || pluginOptions.hasTailwindCss);
192
+ return !!(shouldEnableLiveReload() || pluginOptions.hasTailwindCss);
187
193
  }
188
194
  /**
189
195
  * Validates the Tailwind CSS integration configuration and emits actionable
@@ -321,9 +327,36 @@ function angular(options) {
321
327
  const templateUrlsResolver = new TemplateUrlsResolver();
322
328
  let outputFile;
323
329
  const outputFiles = /* @__PURE__ */ new Map();
330
+ const normalizeEmitterLookupId = (file) => {
331
+ const normalizedFile = normalizePath(file);
332
+ if (!normalizedFile.startsWith("/@fs/")) return normalizedFile;
333
+ return normalizePath(normalizedFile.slice(4).replace(/^\/([A-Za-z]:\/)/, "$1"));
334
+ };
335
+ const describeEmitMarkers = (content) => ({
336
+ contentLength: content.length,
337
+ hasCmp: content.includes("ɵcmp"),
338
+ hasFac: content.includes("ɵfac"),
339
+ hasProv: content.includes("ɵprov"),
340
+ hasDecorate: content.includes("__decorate"),
341
+ hasMetadata: content.includes("__metadata")
342
+ });
324
343
  const fileEmitter = (file) => {
325
- outputFile?.(file);
326
- return outputFiles.get(normalizePath(file));
344
+ const normalizedFile = normalizeEmitterLookupId(file);
345
+ const hadCachedEmit = outputFiles.has(normalizedFile);
346
+ outputFile?.(normalizedFile);
347
+ const emittedResult = outputFiles.get(normalizedFile);
348
+ debugEmitV("fileEmitter lookup", {
349
+ requestFile: file,
350
+ normalizedFile,
351
+ hadCachedEmit,
352
+ hasOutputFileHook: !!outputFile,
353
+ emitted: !!emittedResult,
354
+ knownOutputCount: outputFiles.size,
355
+ contentLength: emittedResult?.content?.length ?? 0,
356
+ errorCount: emittedResult?.errors?.length ?? 0,
357
+ warningCount: emittedResult?.warnings?.length ?? 0
358
+ });
359
+ return emittedResult;
327
360
  };
328
361
  let initialCompilation = false;
329
362
  const declarationFiles = [];
@@ -334,16 +367,16 @@ function angular(options) {
334
367
  let angularCompilation;
335
368
  function angularPlugin() {
336
369
  let isProd = false;
337
- if (angularFullVersion < 19e4 && pluginOptions.hmr) {
370
+ if (angularFullVersion < 19e4 && pluginOptions.liveReload) {
338
371
  debugHmr("hmr disabled: Angular version does not support HMR APIs", {
339
372
  angularVersion: angularFullVersion,
340
373
  isTest
341
374
  });
342
375
  console.warn("[@analogjs/vite-plugin-angular]: HMR was disabled because Angular v19+ is required for externalRuntimeStyles/_enableHmr support. Detected Angular version: %s.", angularFullVersion);
343
- pluginOptions.hmr = false;
376
+ pluginOptions.liveReload = false;
344
377
  }
345
378
  if (isTest) {
346
- pluginOptions.hmr = false;
379
+ pluginOptions.liveReload = false;
347
380
  debugHmr("hmr disabled", {
348
381
  angularVersion: angularFullVersion,
349
382
  isTest
@@ -456,7 +489,7 @@ function angular(options) {
456
489
  });
457
490
  pendingCompilation = performCompilation(resolvedConfig, [fileId]);
458
491
  let result;
459
- if (shouldEnableHmr()) {
492
+ if (shouldEnableLiveReload()) {
460
493
  await pendingCompilation;
461
494
  pendingCompilation = null;
462
495
  result = fileEmitter(fileId);
@@ -478,7 +511,7 @@ function angular(options) {
478
511
  hint: result?.hmrEligible ? "A TS-side component change, including inline template edits, produced an Angular HMR payload." : "No Angular HMR payload was emitted for this TS change; the change may not affect component template state."
479
512
  });
480
513
  }
481
- if (shouldEnableHmr() && result?.hmrEligible && classNames.get(fileId)) {
514
+ if (shouldEnableLiveReload() && result?.hmrEligible && classNames.get(fileId)) {
482
515
  const relativeFileId = `${normalizePath(relative(process.cwd(), fileId))}@${classNames.get(fileId)}`;
483
516
  debugHmr("sending component update", { relativeFileId });
484
517
  debugHmrV("ts hmr component update payload", {
@@ -659,7 +692,7 @@ function angular(options) {
659
692
  }
660
693
  return fileModules;
661
694
  }
662
- if (shouldEnableHmr() && /\.(html|htm)$/.test(ctx.file) && fileModules.length === 0) {
695
+ if (shouldEnableLiveReload() && /\.(html|htm)$/.test(ctx.file) && fileModules.length === 0) {
663
696
  const ownerModules = findTemplateOwnerModules(ctx.server, ctx.file);
664
697
  debugHmrV("template owner lookup", {
665
698
  file: ctx.file,
@@ -886,12 +919,27 @@ function angular(options) {
886
919
  const typescriptResult = fileEmitter(id);
887
920
  if (!typescriptResult) {
888
921
  debugCompilerV("transform skip (file not emitted by Angular)", { id });
889
- if (!id.includes("@ng/component") && /(Component|Directive|Pipe|Injectable|NgModule)\(/.test(code)) this.warn(`[@analogjs/vite-plugin-angular]: "${id}" contains Angular decorators but is not in the TypeScript program. Ensure it is included in your tsconfig.`);
922
+ const isAngular = !id.includes("@ng/component") && /(Component|Directive|Pipe|Injectable|NgModule)\(/.test(code);
923
+ debugEmit("transform emit miss", {
924
+ id,
925
+ normalizedId: normalizeEmitterLookupId(id),
926
+ knownOutputCount: outputFiles.size,
927
+ hasOutputFileHook: !!outputFile,
928
+ isAngular
929
+ });
930
+ if (isAngular) this.warn(`[@analogjs/vite-plugin-angular]: "${id}" contains Angular decorators but is not in the TypeScript program. Ensure it is included in your tsconfig.`);
890
931
  return;
891
932
  }
892
933
  if (typescriptResult.warnings && typescriptResult.warnings.length > 0) this.warn(`${typescriptResult.warnings.join("\n")}`);
893
934
  if (typescriptResult.errors && typescriptResult.errors.length > 0) this.error(`${typescriptResult.errors.join("\n")}`);
894
935
  let data = typescriptResult.content ?? "";
936
+ debugEmitV("transform emit hit", {
937
+ id,
938
+ normalizedId: normalizeEmitterLookupId(id),
939
+ ...describeEmitMarkers(data),
940
+ errorCount: typescriptResult.errors?.length ?? 0,
941
+ warningCount: typescriptResult.warnings?.length ?? 0
942
+ });
895
943
  if (jit && data.includes("angular:jit:")) {
896
944
  data = data.replace(/angular:jit:style:inline;/g, "virtual:angular:jit:style:inline;");
897
945
  templateUrls.forEach((templateUrlSet) => {
@@ -1045,7 +1093,7 @@ function angular(options) {
1045
1093
  }
1046
1094
  },
1047
1095
  angularPlugin(),
1048
- pluginOptions.hmr && liveReloadPlugin({
1096
+ pluginOptions.liveReload && liveReloadPlugin({
1049
1097
  classNames,
1050
1098
  fileEmitter
1051
1099
  }),
@@ -1060,13 +1108,26 @@ function angular(options) {
1060
1108
  nxFolderPlugin()
1061
1109
  ].filter(Boolean);
1062
1110
  function findIncludes() {
1063
- return globSync(pluginOptions.include.map((glob) => normalizeIncludeGlob(pluginOptions.workspaceRoot, glob)), {
1111
+ const globs = pluginOptions.include.map((glob) => normalizeIncludeGlob(pluginOptions.workspaceRoot, glob));
1112
+ const files = globSync(globs, {
1064
1113
  dot: true,
1065
1114
  absolute: true
1066
1115
  });
1116
+ debugEmit("include discovery", {
1117
+ patternCount: globs.length,
1118
+ fileCount: files.length
1119
+ });
1120
+ debugEmitV("include discovery files", {
1121
+ globs,
1122
+ files: files.map((file) => normalizePath(file))
1123
+ });
1124
+ return files;
1067
1125
  }
1068
1126
  function ensureIncludeCache() {
1069
- if (pluginOptions.include.length > 0 && includeCache.length === 0) includeCache = findIncludes();
1127
+ if (pluginOptions.include.length > 0 && includeCache.length === 0) {
1128
+ includeCache = findIncludes();
1129
+ debugEmit("include cache populated", { fileCount: includeCache.length });
1130
+ }
1070
1131
  return includeCache;
1071
1132
  }
1072
1133
  function getTsconfigCacheKey(resolvedTsConfigPath, config) {
@@ -1075,45 +1136,128 @@ function angular(options) {
1075
1136
  config.mode === "production" ? "prod" : "dev",
1076
1137
  isTest ? "test" : "app",
1077
1138
  config.build?.lib ? "lib" : "nolib",
1078
- pluginOptions.hmr ? "hmr" : "nohmr",
1139
+ pluginOptions.liveReload ? "live-reload" : "no-live-reload",
1079
1140
  pluginOptions.hasTailwindCss ? "tw" : "notw"
1080
1141
  ].join("|");
1081
1142
  }
1082
- function getCachedTsconfigOptions(resolvedTsConfigPath, config) {
1143
+ function readAngularTsconfigConfiguration(resolvedTsConfigPath, config) {
1083
1144
  const isProd = config.mode === "production";
1145
+ return compilerCli.readConfiguration(resolvedTsConfigPath, {
1146
+ suppressOutputPathCheck: true,
1147
+ outDir: void 0,
1148
+ sourceMap: false,
1149
+ inlineSourceMap: !isProd,
1150
+ inlineSources: !isProd,
1151
+ declaration: false,
1152
+ declarationMap: false,
1153
+ allowEmptyCodegenFiles: false,
1154
+ annotationsAs: "decorators",
1155
+ enableResourceInlining: false,
1156
+ noEmitOnError: false,
1157
+ mapRoot: void 0,
1158
+ sourceRoot: void 0,
1159
+ supportTestBed: false,
1160
+ supportJitMode: false
1161
+ });
1162
+ }
1163
+ function getCachedTsconfigOptions(resolvedTsConfigPath, config) {
1084
1164
  const tsconfigKey = getTsconfigCacheKey(resolvedTsConfigPath, config);
1085
1165
  let cached = tsconfigOptionsCache.get(tsconfigKey);
1086
1166
  if (!cached) {
1087
- const read = compilerCli.readConfiguration(resolvedTsConfigPath, {
1088
- suppressOutputPathCheck: true,
1089
- outDir: void 0,
1090
- sourceMap: false,
1091
- inlineSourceMap: !isProd,
1092
- inlineSources: !isProd,
1093
- declaration: false,
1094
- declarationMap: false,
1095
- allowEmptyCodegenFiles: false,
1096
- annotationsAs: "decorators",
1097
- enableResourceInlining: false,
1098
- noEmitOnError: false,
1099
- mapRoot: void 0,
1100
- sourceRoot: void 0,
1101
- supportTestBed: false,
1102
- supportJitMode: false
1103
- });
1167
+ const read = readAngularTsconfigConfiguration(resolvedTsConfigPath, config);
1104
1168
  cached = {
1105
1169
  options: read.options,
1106
1170
  rootNames: read.rootNames
1107
1171
  };
1108
1172
  tsconfigOptionsCache.set(tsconfigKey, cached);
1173
+ debugEmit("tsconfig root names loaded", {
1174
+ resolvedTsConfigPath,
1175
+ rootNameCount: read.rootNames.length
1176
+ });
1177
+ debugEmitV("tsconfig root names", {
1178
+ resolvedTsConfigPath,
1179
+ rootNames: read.rootNames.map((file) => normalizePath(file))
1180
+ });
1109
1181
  }
1110
1182
  return cached;
1111
1183
  }
1184
+ function resolveReferenceTsconfigPath(referencePath, ownerTsconfigPath) {
1185
+ const ownerDir = dirname(ownerTsconfigPath);
1186
+ const resolvedReference = normalizePath(isAbsolute(referencePath) ? referencePath : resolve(ownerDir, referencePath));
1187
+ if (existsSync(resolvedReference)) {
1188
+ try {
1189
+ if (statSync(resolvedReference).isDirectory()) {
1190
+ const nestedTsconfig = join(resolvedReference, "tsconfig.json");
1191
+ return existsSync(nestedTsconfig) ? normalizePath(nestedTsconfig) : void 0;
1192
+ }
1193
+ } catch {
1194
+ return;
1195
+ }
1196
+ return resolvedReference;
1197
+ }
1198
+ if (!resolvedReference.endsWith(".json")) {
1199
+ const asJson = `${resolvedReference}.json`;
1200
+ if (existsSync(asJson)) return normalizePath(asJson);
1201
+ const nestedTsconfig = join(resolvedReference, "tsconfig.json");
1202
+ if (existsSync(nestedTsconfig)) return normalizePath(nestedTsconfig);
1203
+ }
1204
+ }
1205
+ function collectTsconfigPathRoots(resolvedTsConfigPath, options, rawTsconfig) {
1206
+ const tsPaths = rawTsconfig.compilerOptions?.paths ?? options.paths;
1207
+ if (!tsPaths) return [];
1208
+ const tsconfigDir = dirname(resolvedTsConfigPath);
1209
+ const configuredBaseUrl = typeof options.baseUrl === "string" ? options.baseUrl : typeof rawTsconfig.compilerOptions?.baseUrl === "string" ? rawTsconfig.compilerOptions.baseUrl : void 0;
1210
+ const resolvedBaseUrl = configuredBaseUrl ? isAbsolute(configuredBaseUrl) ? configuredBaseUrl : resolve(tsconfigDir, configuredBaseUrl) : tsconfigDir;
1211
+ const discoveredRoots = /* @__PURE__ */ new Set();
1212
+ for (const targets of Object.values(tsPaths)) for (const target of targets) {
1213
+ const resolvedTarget = normalizePath(isAbsolute(target) ? target : resolve(resolvedBaseUrl, target));
1214
+ if (target.includes("*")) {
1215
+ for (const match of globSync(resolvedTarget, {
1216
+ dot: true,
1217
+ absolute: true
1218
+ })) discoveredRoots.add(normalizePath(match));
1219
+ continue;
1220
+ }
1221
+ if (existsSync(resolvedTarget)) discoveredRoots.add(resolvedTarget);
1222
+ }
1223
+ return [...discoveredRoots];
1224
+ }
1225
+ function collectExpandedTsconfigRoots(resolvedTsConfigPath, config, visited = /* @__PURE__ */ new Set()) {
1226
+ const normalizedTsConfigPath = normalizePath(resolvedTsConfigPath);
1227
+ if (visited.has(normalizedTsConfigPath)) return [];
1228
+ const tsconfigKey = `${getTsconfigCacheKey(normalizedTsConfigPath, config)}|graph`;
1229
+ const cached = tsconfigGraphRootCache.get(tsconfigKey);
1230
+ if (cached) return cached;
1231
+ visited.add(normalizedTsConfigPath);
1232
+ const read = readAngularTsconfigConfiguration(normalizedTsConfigPath, config);
1233
+ const rawTsconfig = ts.readConfigFile(normalizedTsConfigPath, ts.sys.readFile).config ?? {};
1234
+ const expandedRoots = new Set(read.rootNames.map((file) => normalizePath(file)));
1235
+ const pathRoots = collectTsconfigPathRoots(normalizedTsConfigPath, read.options, rawTsconfig);
1236
+ for (const pathRoot of pathRoots) expandedRoots.add(pathRoot);
1237
+ const referenceConfigs = (rawTsconfig.references ?? []).flatMap((reference) => typeof reference.path === "string" ? [resolveReferenceTsconfigPath(reference.path, normalizedTsConfigPath)] : []).filter((reference) => !!reference);
1238
+ for (const referenceConfig of referenceConfigs) for (const referenceRoot of collectExpandedTsconfigRoots(referenceConfig, config, visited)) expandedRoots.add(referenceRoot);
1239
+ const expandedRootList = [...expandedRoots];
1240
+ tsconfigGraphRootCache.set(tsconfigKey, expandedRootList);
1241
+ debugEmit("expanded tsconfig graph roots", {
1242
+ resolvedTsConfigPath: normalizedTsConfigPath,
1243
+ directRootNameCount: read.rootNames.length,
1244
+ pathRootCount: pathRoots.length,
1245
+ referenceConfigCount: referenceConfigs.length,
1246
+ expandedRootCount: expandedRootList.length
1247
+ });
1248
+ debugEmitV("expanded tsconfig graph root files", {
1249
+ resolvedTsConfigPath: normalizedTsConfigPath,
1250
+ pathRoots,
1251
+ referenceConfigs,
1252
+ rootNames: expandedRootList
1253
+ });
1254
+ return expandedRootList;
1255
+ }
1112
1256
  function resolveCompilationApiTsConfigPath(resolvedTsConfigPath, config) {
1113
1257
  const includedFiles = ensureIncludeCache();
1114
- if (includedFiles.length === 0) return resolvedTsConfigPath;
1115
1258
  const cached = getCachedTsconfigOptions(resolvedTsConfigPath, config);
1116
- const mergedRootNames = union(cached.rootNames, includedFiles).map((file) => normalizePath(file));
1259
+ const expandedGraphRoots = collectExpandedTsconfigRoots(resolvedTsConfigPath, config);
1260
+ const mergedRootNames = union(cached.rootNames, expandedGraphRoots, includedFiles).map((file) => normalizePath(file));
1117
1261
  if (mergedRootNames.length === cached.rootNames.length) return resolvedTsConfigPath;
1118
1262
  const wrapperDir = join(isAbsolute(config.cacheDir) ? config.cacheDir : resolve(config.root, config.cacheDir), "analog-angular", "compilation-api");
1119
1263
  const rawTsconfig = ts.readConfigFile(resolvedTsConfigPath, ts.sys.readFile).config ?? {};
@@ -1131,6 +1275,19 @@ function angular(options) {
1131
1275
  includeCount: includedFiles.length,
1132
1276
  rootNameCount: mergedRootNames.length
1133
1277
  });
1278
+ debugEmit("wrapper tsconfig root merge", {
1279
+ originalTsconfig: resolvedTsConfigPath,
1280
+ wrapperTsconfig: wrapperPath,
1281
+ baseRootNameCount: cached.rootNames.length,
1282
+ expandedGraphRootCount: expandedGraphRoots.length,
1283
+ includeCount: includedFiles.length,
1284
+ mergedRootNameCount: mergedRootNames.length,
1285
+ referenceCount: rawTsconfig.references?.length ?? 0
1286
+ });
1287
+ debugEmitV("wrapper tsconfig root names", {
1288
+ wrapperTsconfig: wrapperPath,
1289
+ rootNames: mergedRootNames
1290
+ });
1134
1291
  return wrapperPath;
1135
1292
  }
1136
1293
  function resolveTsConfigPath() {
@@ -1153,15 +1310,21 @@ function angular(options) {
1153
1310
  * file-level HMR metadata (`hmrUpdateCode`, `hmrEligible`, `classNames`).
1154
1311
  */
1155
1312
  async function performAngularCompilation(config, ids) {
1156
- angularCompilation ??= await createAngularCompilation(!!pluginOptions.jit, false);
1313
+ const compilation = angularCompilation ??= await createAngularCompilation(!!pluginOptions.jit, false);
1157
1314
  const modifiedFiles = ids?.length ? new Set(ids.map((file) => normalizePath(file))) : void 0;
1158
1315
  if (modifiedFiles?.size) sourceFileCache$1.invalidate(modifiedFiles);
1159
- if (modifiedFiles?.size && angularCompilation.update) {
1316
+ if (modifiedFiles?.size && compilation.update) {
1160
1317
  debugCompilationApi("incremental update", { files: [...modifiedFiles] });
1161
- await angularCompilation.update(modifiedFiles);
1318
+ await compilation.update(modifiedFiles);
1162
1319
  }
1163
- const compilationApiTsConfigPath = resolveCompilationApiTsConfigPath(resolveTsConfigPath(), config);
1164
- const compilationResult = await angularCompilation.initialize(compilationApiTsConfigPath, {
1320
+ const resolvedTsConfigPath = resolveTsConfigPath();
1321
+ const compilationApiTsConfigPath = resolveCompilationApiTsConfigPath(resolvedTsConfigPath, config);
1322
+ debugEmit("compilation initialize", {
1323
+ resolvedTsConfigPath,
1324
+ compilationApiTsConfigPath,
1325
+ modifiedFileCount: modifiedFiles?.size ?? 0
1326
+ });
1327
+ const compilationResult = await compilation.initialize(compilationApiTsConfigPath, {
1165
1328
  fileReplacements: toAngularCompilationFileReplacements(pluginOptions.fileReplacements, pluginOptions.workspaceRoot),
1166
1329
  modifiedFiles,
1167
1330
  async transformStylesheet(data, containingFile, resourceFile, order, className) {
@@ -1174,7 +1337,7 @@ function angular(options) {
1174
1337
  order,
1175
1338
  inline: !resourceFile
1176
1339
  });
1177
- if (shouldEnableHmr() && className && containingFile) classNames.set(normalizePath(containingFile), className);
1340
+ if (shouldEnableLiveReload() && className && containingFile) classNames.set(normalizePath(containingFile), className);
1178
1341
  if (shouldExternalizeStyles()) {
1179
1342
  const stylesheetId = registerStylesheetContent(stylesheetRegistry, {
1180
1343
  code: preprocessed.code,
@@ -1225,12 +1388,13 @@ function angular(options) {
1225
1388
  }
1226
1389
  }, (tsCompilerOptions) => {
1227
1390
  if (shouldExternalizeStyles()) tsCompilerOptions["externalRuntimeStyles"] = true;
1228
- if (shouldEnableHmr()) {
1391
+ if (shouldEnableLiveReload()) {
1229
1392
  tsCompilerOptions["_enableHmr"] = true;
1230
1393
  tsCompilerOptions["supportTestBed"] = true;
1231
1394
  }
1232
1395
  debugCompiler("tsCompilerOptions (compilation API)", {
1233
- hmr: pluginOptions.hmr,
1396
+ liveReload: pluginOptions.liveReload,
1397
+ viteHmr: hasViteHmrTransport(),
1234
1398
  hasTailwindCss: pluginOptions.hasTailwindCss,
1235
1399
  watchMode,
1236
1400
  shouldExternalize: shouldExternalizeStyles(),
@@ -1241,7 +1405,6 @@ function angular(options) {
1241
1405
  tsCompilerOptions["supportTestBed"] = true;
1242
1406
  tsCompilerOptions["supportJitMode"] = true;
1243
1407
  }
1244
- if (angularFullVersion >= 2e5) tsCompilerOptions["_enableSelectorless"] = true;
1245
1408
  if (!isTest && config.build?.lib) {
1246
1409
  tsCompilerOptions["declaration"] = true;
1247
1410
  tsCompilerOptions["declarationMap"] = watchMode;
@@ -1261,7 +1424,7 @@ function angular(options) {
1261
1424
  skipped: 0,
1262
1425
  errors: 0
1263
1426
  };
1264
- compilationResult.externalStylesheets?.forEach((value, key) => {
1427
+ for (const [key, value] of compilationResult.externalStylesheets ?? []) {
1265
1428
  preprocessStats.total++;
1266
1429
  const angularHash = `${value}.css`;
1267
1430
  stylesheetRegistry?.registerExternalRequest(angularHash, key);
@@ -1331,17 +1494,28 @@ function angular(options) {
1331
1494
  filename: angularHash,
1332
1495
  resolvedPath: key
1333
1496
  });
1334
- });
1497
+ }
1335
1498
  debugStyles("external stylesheet preprocessing complete", preprocessStats);
1336
- const diagnostics = await angularCompilation.diagnoseFiles(pluginOptions.disableTypeChecking ? DiagnosticModes.All & ~DiagnosticModes.Semantic : DiagnosticModes.All);
1499
+ const diagnostics = await compilation.diagnoseFiles(pluginOptions.disableTypeChecking ? DiagnosticModes.All & ~DiagnosticModes.Semantic : DiagnosticModes.All);
1337
1500
  const errors = diagnostics.errors?.length ? diagnostics.errors : [];
1338
1501
  const warnings = diagnostics.warnings?.length ? diagnostics.warnings : [];
1502
+ debugEmit("compilation diagnostics", {
1503
+ errorCount: errors.length,
1504
+ warningCount: warnings.length
1505
+ });
1339
1506
  const templateUpdates = mapTemplateUpdatesToFiles(compilationResult.templateUpdates);
1340
1507
  if (templateUpdates.size > 0) debugHmr("compilation API template updates", {
1341
1508
  count: templateUpdates.size,
1342
1509
  files: [...templateUpdates.keys()]
1343
1510
  });
1344
- for (const file of await angularCompilation.emitAffectedFiles()) {
1511
+ const affectedFiles = await compilation.emitAffectedFiles();
1512
+ debugEmit("emitAffectedFiles summary", {
1513
+ count: affectedFiles.length,
1514
+ templateUpdateCount: templateUpdates.size,
1515
+ knownOutputCountBefore: outputFiles.size
1516
+ });
1517
+ debugEmitV("emitAffectedFiles files", { files: affectedFiles.map((file) => normalizePath(file.filename)) });
1518
+ for (const file of affectedFiles) {
1345
1519
  const normalizedFilename = normalizePath(file.filename);
1346
1520
  const templateUpdate = templateUpdates.get(normalizedFilename);
1347
1521
  if (templateUpdate) classNames.set(normalizedFilename, templateUpdate.className);
@@ -1353,6 +1527,14 @@ function angular(options) {
1353
1527
  hmrUpdateCode: templateUpdate?.code,
1354
1528
  hmrEligible: !!templateUpdate?.code
1355
1529
  });
1530
+ debugEmitV("registered compilation API output", {
1531
+ filename: normalizedFilename,
1532
+ ...describeEmitMarkers(file.contents),
1533
+ hasTemplateUpdate: !!templateUpdate,
1534
+ errorCount: errors.length,
1535
+ warningCount: warnings.length,
1536
+ knownOutputCount: outputFiles.size
1537
+ });
1356
1538
  }
1357
1539
  }
1358
1540
  async function performCompilation(config, ids) {
@@ -1386,12 +1568,13 @@ function angular(options) {
1386
1568
  const tsCompilerOptions = { ...cached.options };
1387
1569
  let rootNames = [...cached.rootNames];
1388
1570
  if (shouldExternalizeStyles()) tsCompilerOptions["externalRuntimeStyles"] = true;
1389
- if (shouldEnableHmr()) {
1571
+ if (shouldEnableLiveReload()) {
1390
1572
  tsCompilerOptions["_enableHmr"] = true;
1391
1573
  tsCompilerOptions["supportTestBed"] = true;
1392
1574
  }
1393
1575
  debugCompiler("tsCompilerOptions (NgtscProgram path)", {
1394
- hmr: pluginOptions.hmr,
1576
+ liveReload: pluginOptions.liveReload,
1577
+ viteHmr: hasViteHmrTransport(),
1395
1578
  shouldExternalize: shouldExternalizeStyles(),
1396
1579
  externalRuntimeStyles: !!tsCompilerOptions["externalRuntimeStyles"],
1397
1580
  hmrEnabled: !!tsCompilerOptions["_enableHmr"]
@@ -1400,7 +1583,6 @@ function angular(options) {
1400
1583
  tsCompilerOptions["supportTestBed"] = true;
1401
1584
  tsCompilerOptions["supportJitMode"] = true;
1402
1585
  }
1403
- if (angularFullVersion >= 2e5) tsCompilerOptions["_enableSelectorless"] = true;
1404
1586
  if (!isTest && config.build?.lib) {
1405
1587
  tsCompilerOptions["declaration"] = true;
1406
1588
  tsCompilerOptions["declarationMap"] = watchMode;
@@ -1461,7 +1643,7 @@ function angular(options) {
1461
1643
  if (!watchMode) builder = ts.createAbstractBuilder(typeScriptProgram, host, oldBuilder);
1462
1644
  if (angularCompiler) await angularCompiler.analyzeAsync();
1463
1645
  const transformers = mergeTransformers({ before: jit ? [compilerCli.constructorParametersDownlevelTransform(builder.getProgram()), cjt(() => builder.getProgram().getTypeChecker())] : [] }, jit ? {} : angularCompiler.prepareEmit().transformers);
1464
- const fileMetadata = getFileMetadata(builder, angularCompiler, pluginOptions.hmr, pluginOptions.disableTypeChecking);
1646
+ const fileMetadata = getFileMetadata(builder, angularCompiler, pluginOptions.liveReload, pluginOptions.disableTypeChecking);
1465
1647
  const writeFileCallback = (_filename, content, _a, _b, sourceFiles) => {
1466
1648
  if (!sourceFiles?.length) return;
1467
1649
  const filename = normalizePath(sourceFiles[0].fileName);
@@ -1475,6 +1657,14 @@ function angular(options) {
1475
1657
  hmrUpdateCode: metadata.hmrUpdateCode,
1476
1658
  hmrEligible: metadata.hmrEligible
1477
1659
  });
1660
+ debugEmitV("registered ngtsc output", {
1661
+ filename,
1662
+ ...describeEmitMarkers(content),
1663
+ errorCount: metadata.errors?.length ?? 0,
1664
+ warningCount: metadata.warnings?.length ?? 0,
1665
+ hmrEligible: !!metadata.hmrEligible,
1666
+ knownOutputCount: outputFiles.size
1667
+ });
1478
1668
  };
1479
1669
  const writeOutputFile = (id) => {
1480
1670
  const sourceFile = builder.getSourceFile(id);