@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 +6 -0
- package/package.json +2 -2
- package/src/lib/angular-vite-plugin.d.ts +7 -7
- package/src/lib/angular-vite-plugin.js +245 -55
- package/src/lib/angular-vite-plugin.js.map +1 -1
- package/src/lib/live-reload-plugin.js +4 -0
- package/src/lib/live-reload-plugin.js.map +1 -1
- package/src/lib/utils/debug.d.ts +3 -1
- package/src/lib/utils/debug.js +6 -2
- package/src/lib/utils/debug.js.map +1 -1
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.
|
|
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.
|
|
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
|
|
35
|
+
* Enables Analog's Angular live-reload/HMR pipeline during development/watch mode.
|
|
36
36
|
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
*
|
|
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
|
-
|
|
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
|
|
166
|
-
return
|
|
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 !!(
|
|
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
|
-
|
|
326
|
-
|
|
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.
|
|
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.
|
|
376
|
+
pluginOptions.liveReload = false;
|
|
344
377
|
}
|
|
345
378
|
if (isTest) {
|
|
346
|
-
pluginOptions.
|
|
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 (
|
|
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 (
|
|
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 (
|
|
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
|
-
|
|
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.
|
|
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
|
-
|
|
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)
|
|
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.
|
|
1139
|
+
pluginOptions.liveReload ? "live-reload" : "no-live-reload",
|
|
1079
1140
|
pluginOptions.hasTailwindCss ? "tw" : "notw"
|
|
1080
1141
|
].join("|");
|
|
1081
1142
|
}
|
|
1082
|
-
function
|
|
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 =
|
|
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
|
|
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 &&
|
|
1316
|
+
if (modifiedFiles?.size && compilation.update) {
|
|
1160
1317
|
debugCompilationApi("incremental update", { files: [...modifiedFiles] });
|
|
1161
|
-
await
|
|
1318
|
+
await compilation.update(modifiedFiles);
|
|
1162
1319
|
}
|
|
1163
|
-
const
|
|
1164
|
-
const
|
|
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 (
|
|
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 (
|
|
1391
|
+
if (shouldEnableLiveReload()) {
|
|
1229
1392
|
tsCompilerOptions["_enableHmr"] = true;
|
|
1230
1393
|
tsCompilerOptions["supportTestBed"] = true;
|
|
1231
1394
|
}
|
|
1232
1395
|
debugCompiler("tsCompilerOptions (compilation API)", {
|
|
1233
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
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 (
|
|
1571
|
+
if (shouldEnableLiveReload()) {
|
|
1390
1572
|
tsCompilerOptions["_enableHmr"] = true;
|
|
1391
1573
|
tsCompilerOptions["supportTestBed"] = true;
|
|
1392
1574
|
}
|
|
1393
1575
|
debugCompiler("tsCompilerOptions (NgtscProgram path)", {
|
|
1394
|
-
|
|
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.
|
|
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);
|