@analogjs/vite-plugin-angular 3.0.0-alpha.9 → 3.0.0-alpha.91
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 +121 -0
- package/migrations/migrate-setup-vitest/migrate-setup-vitest.d.ts +2 -0
- package/migrations/migrate-setup-vitest/migrate-setup-vitest.js +49 -0
- package/migrations/migrate-setup-vitest/migrate-setup-vitest.js.map +1 -0
- package/migrations/migration.json +7 -1
- package/migrations/migrations.json +9 -0
- package/migrations/update-3-0-0/migrate-setup-vitest.d.ts +2 -0
- package/migrations/update-3-0-0/migrate-setup-vitest.js +36 -0
- package/migrations/update-3-0-0/migrate-setup-vitest.js.map +1 -0
- package/package.json +49 -8
- package/src/index.d.ts +7 -2
- package/src/index.js +3 -1
- package/src/index.js.map +1 -1
- package/src/lib/analog-plugin-interop.d.ts +78 -0
- package/src/lib/analog-plugin-interop.js +97 -0
- package/src/lib/analog-plugin-interop.js.map +1 -0
- package/src/lib/angular-build-optimizer-plugin.d.ts +8 -4
- package/src/lib/angular-build-optimizer-plugin.js +66 -31
- package/src/lib/angular-build-optimizer-plugin.js.map +1 -1
- package/src/lib/angular-jit-plugin.d.ts +3 -3
- package/src/lib/angular-jit-plugin.js +28 -6
- package/src/lib/angular-jit-plugin.js.map +1 -1
- package/src/lib/angular-pending-tasks.plugin.d.ts +7 -7
- package/src/lib/angular-pending-tasks.plugin.js.map +1 -1
- package/src/lib/angular-vite-plugin.d.ts +79 -69
- package/src/lib/angular-vite-plugin.js +775 -352
- package/src/lib/angular-vite-plugin.js.map +1 -1
- package/src/lib/angular-vitest-plugin.d.ts +26 -21
- package/src/lib/angular-vitest-plugin.js +34 -25
- package/src/lib/angular-vitest-plugin.js.map +1 -1
- package/src/lib/compilation-api/compilation-api-plugin.d.ts +24 -0
- package/src/lib/compilation-api/compilation-api-plugin.js +548 -0
- package/src/lib/compilation-api/compilation-api-plugin.js.map +1 -0
- package/src/lib/compilation-api/index.d.ts +1 -0
- package/src/lib/compilation-api/index.js +1 -0
- package/src/lib/compiler/angular-version.d.ts +19 -0
- package/src/lib/compiler/angular-version.js +31 -0
- package/src/lib/compiler/angular-version.js.map +1 -0
- package/src/lib/compiler/class-field-lowering.d.ts +23 -0
- package/src/lib/compiler/class-field-lowering.js +131 -0
- package/src/lib/compiler/class-field-lowering.js.map +1 -0
- package/src/lib/compiler/compile.d.ts +50 -0
- package/src/lib/compiler/compile.js +814 -0
- package/src/lib/compiler/compile.js.map +1 -0
- package/src/lib/compiler/constants.d.ts +24 -0
- package/src/lib/compiler/constants.js +59 -0
- package/src/lib/compiler/constants.js.map +1 -0
- package/src/lib/compiler/debug.d.ts +22 -0
- package/src/lib/compiler/debug.js +20 -0
- package/src/lib/compiler/debug.js.map +1 -0
- package/src/lib/compiler/defer.d.ts +57 -0
- package/src/lib/compiler/defer.js +154 -0
- package/src/lib/compiler/defer.js.map +1 -0
- package/src/lib/compiler/dts-reader.d.ts +45 -0
- package/src/lib/compiler/dts-reader.js +395 -0
- package/src/lib/compiler/dts-reader.js.map +1 -0
- package/src/lib/compiler/hmr.d.ts +16 -0
- package/src/lib/compiler/hmr.js +69 -0
- package/src/lib/compiler/hmr.js.map +1 -0
- package/src/lib/compiler/index.d.ts +8 -0
- package/src/lib/compiler/index.js +8 -0
- package/src/lib/compiler/jit-metadata.d.ts +14 -0
- package/src/lib/compiler/jit-metadata.js +168 -0
- package/src/lib/compiler/jit-metadata.js.map +1 -0
- package/src/lib/compiler/jit-transform.d.ts +24 -0
- package/src/lib/compiler/jit-transform.js +204 -0
- package/src/lib/compiler/jit-transform.js.map +1 -0
- package/src/lib/compiler/js-emitter.d.ts +10 -0
- package/src/lib/compiler/js-emitter.js +446 -0
- package/src/lib/compiler/js-emitter.js.map +1 -0
- package/src/lib/compiler/metadata.d.ts +36 -0
- package/src/lib/compiler/metadata.js +710 -0
- package/src/lib/compiler/metadata.js.map +1 -0
- package/src/lib/compiler/registry.d.ts +56 -0
- package/src/lib/compiler/registry.js +176 -0
- package/src/lib/compiler/registry.js.map +1 -0
- package/src/lib/compiler/resource-inliner.d.ts +43 -0
- package/src/lib/compiler/resource-inliner.js +230 -0
- package/src/lib/compiler/resource-inliner.js.map +1 -0
- package/src/lib/compiler/style-ast.d.ts +9 -0
- package/src/lib/compiler/style-ast.js +54 -0
- package/src/lib/compiler/style-ast.js.map +1 -0
- package/src/lib/compiler/styles.d.ts +13 -0
- package/src/lib/compiler/test-helpers.d.ts +7 -0
- package/src/lib/compiler/type-elision.d.ts +28 -0
- package/src/lib/compiler/type-elision.js +211 -0
- package/src/lib/compiler/type-elision.js.map +1 -0
- package/src/lib/compiler/utils.d.ts +40 -0
- package/src/lib/compiler/utils.js +76 -0
- package/src/lib/compiler/utils.js.map +1 -0
- package/src/lib/compiler-plugin.d.ts +13 -12
- package/src/lib/compiler-plugin.js +18 -18
- package/src/lib/compiler-plugin.js.map +1 -1
- package/src/lib/component-resolvers.d.ts +20 -4
- package/src/lib/component-resolvers.js +34 -20
- package/src/lib/component-resolvers.js.map +1 -1
- package/src/lib/encapsulation-plugin.d.ts +23 -0
- package/src/lib/encapsulation-plugin.js +68 -0
- package/src/lib/encapsulation-plugin.js.map +1 -0
- package/src/lib/fast-compile-plugin.d.ts +23 -0
- package/src/lib/fast-compile-plugin.js +434 -0
- package/src/lib/fast-compile-plugin.js.map +1 -0
- package/src/lib/host.d.ts +10 -8
- package/src/lib/host.js +59 -17
- package/src/lib/host.js.map +1 -1
- package/src/lib/live-reload-plugin.d.ts +5 -5
- package/src/lib/live-reload-plugin.js +10 -0
- package/src/lib/live-reload-plugin.js.map +1 -1
- package/src/lib/models.d.ts +9 -9
- package/src/lib/nx-folder-plugin.d.ts +5 -5
- package/src/lib/nx-folder-plugin.js.map +1 -1
- package/src/lib/plugins/file-replacements.plugin.d.ts +4 -4
- package/src/lib/plugins/file-replacements.plugin.js +6 -1
- package/src/lib/plugins/file-replacements.plugin.js.map +1 -1
- package/src/lib/router-plugin.d.ts +1 -1
- package/src/lib/router-plugin.js +14 -2
- package/src/lib/router-plugin.js.map +1 -1
- package/src/lib/style-preprocessor.d.ts +35 -0
- package/src/lib/style-preprocessor.js +35 -0
- package/src/lib/style-preprocessor.js.map +1 -0
- package/src/lib/stylesheet-registry.d.ts +74 -0
- package/src/lib/stylesheet-registry.js +174 -0
- package/src/lib/stylesheet-registry.js.map +1 -0
- package/src/lib/tools/package.json +1 -3
- package/src/lib/tools/src/builders/vite/vite-build.impl.js +7 -5
- package/src/lib/tools/src/builders/vite/vite-build.impl.js.map +1 -1
- package/src/lib/tools/src/builders/vite-dev-server/dev-server.impl.js +16 -19
- package/src/lib/tools/src/builders/vite-dev-server/dev-server.impl.js.map +1 -1
- package/src/lib/utils/compilation-shared.d.ts +62 -0
- package/src/lib/utils/compilation-shared.js +138 -0
- package/src/lib/utils/compilation-shared.js.map +1 -0
- package/src/lib/utils/compiler-plugin-options.d.ts +11 -11
- package/src/lib/utils/css-extension-resolver.d.ts +32 -0
- package/src/lib/utils/css-extension-resolver.js +73 -0
- package/src/lib/utils/css-extension-resolver.js.map +1 -0
- package/src/lib/utils/css-preprocessor-workers.d.ts +6 -0
- package/src/lib/utils/css-preprocessor-workers.js +29 -0
- package/src/lib/utils/css-preprocessor-workers.js.map +1 -0
- package/src/lib/utils/debug-harness.d.ts +23 -0
- package/src/lib/utils/debug-harness.js +88 -0
- package/src/lib/utils/debug-harness.js.map +1 -0
- package/src/lib/utils/debug-log-file.d.ts +5 -0
- package/src/lib/utils/debug-log-file.js +56 -0
- package/src/lib/utils/debug-log-file.js.map +1 -0
- package/src/lib/utils/debug.d.ts +26 -0
- package/src/lib/utils/debug.js +35 -0
- package/src/lib/utils/debug.js.map +1 -0
- package/src/lib/utils/devkit.d.ts +14 -6
- package/src/lib/utils/devkit.js +40 -2
- package/src/lib/utils/devkit.js.map +1 -1
- package/src/lib/utils/hmr-candidates.d.ts +28 -28
- package/src/lib/utils/jit-inline-styles.d.ts +3 -0
- package/src/lib/utils/jit-inline-styles.js +16 -0
- package/src/lib/utils/jit-inline-styles.js.map +1 -0
- package/src/lib/utils/plugin-config.d.ts +41 -0
- package/src/lib/utils/plugin-config.js +85 -0
- package/src/lib/utils/plugin-config.js.map +1 -0
- package/src/lib/utils/rolldown.d.ts +1 -1
- package/src/lib/utils/rolldown.js.map +1 -1
- package/src/lib/utils/safe-module-paths.d.ts +16 -0
- package/src/lib/utils/safe-module-paths.js +29 -0
- package/src/lib/utils/safe-module-paths.js.map +1 -0
- package/src/lib/utils/source-file-cache.d.ts +8 -15
- package/src/lib/utils/source-file-cache.js.map +1 -1
- package/src/lib/utils/transform-cache.d.ts +43 -0
- package/src/lib/utils/transform-cache.js +97 -0
- package/src/lib/utils/transform-cache.js.map +1 -0
- package/src/lib/utils/tsconfig-resolver.d.ts +34 -0
- package/src/lib/utils/tsconfig-resolver.js +205 -0
- package/src/lib/utils/tsconfig-resolver.js.map +1 -0
- package/src/lib/utils/virtual-ids.d.ts +4 -0
- package/src/lib/utils/virtual-ids.js +23 -0
- package/src/lib/utils/virtual-ids.js.map +1 -0
- package/src/lib/utils/virtual-resources.d.ts +19 -0
- package/src/lib/utils/virtual-resources.js +38 -0
- package/src/lib/utils/virtual-resources.js.map +1 -0
- package/src/lib/virtual-modules-plugin.d.ts +5 -0
- package/src/lib/virtual-modules-plugin.js +23 -0
- package/src/lib/virtual-modules-plugin.js.map +1 -0
- package/src/test-setup.d.ts +2 -0
- package/setup-vitest.d.ts +0 -4
- package/setup-vitest.js +0 -176
- package/setup-vitest.js.map +0 -1
- package/src/lib/tools/src/index.d.ts +0 -0
|
@@ -1,87 +1,126 @@
|
|
|
1
|
-
import { angularFullVersion, cjt,
|
|
1
|
+
import { angularFullVersion, cjt, sourceFileCache } from "./utils/devkit.js";
|
|
2
|
+
import { activateDeferredDebug, applyDebugOption, debugCompiler, debugCompilerV, debugEmit, debugEmitV, debugHmr, debugHmrV, debugStyles, debugStylesV } from "./utils/debug.js";
|
|
3
|
+
import { createCompilerPlugin, createRolldownCompilerPlugin } from "./compiler-plugin.js";
|
|
4
|
+
import { TS_EXT_REGEX, createTsConfigGetter, getTsConfigPath, isProdMode } from "./utils/plugin-config.js";
|
|
5
|
+
import { TsconfigResolver } from "./utils/tsconfig-resolver.js";
|
|
2
6
|
import { getJsTransformConfigKey, isRolldown } from "./utils/rolldown.js";
|
|
7
|
+
import { AnalogStylesheetRegistry, preprocessStylesheet, rewriteRelativeCssImports } from "./stylesheet-registry.js";
|
|
8
|
+
import { discoverAnalogIntegrations } from "./analog-plugin-interop.js";
|
|
9
|
+
import { describeStylesheetContent, injectViteIgnoreForHmrMetadata, isIgnoredHmrFile, isTestWatchMode } from "./utils/compilation-shared.js";
|
|
10
|
+
import { angularVitestPlugins } from "./angular-vitest-plugin.js";
|
|
3
11
|
import { buildOptimizerPlugin } from "./angular-build-optimizer-plugin.js";
|
|
12
|
+
import { toJitInlineStyleId } from "./utils/jit-inline-styles.js";
|
|
13
|
+
import { releaseCssPreprocessorWorkers } from "./utils/css-preprocessor-workers.js";
|
|
4
14
|
import { jitPlugin } from "./angular-jit-plugin.js";
|
|
5
|
-
import { createCompilerPlugin, createRolldownCompilerPlugin } from "./compiler-plugin.js";
|
|
6
|
-
import { StyleUrlsResolver, TemplateUrlsResolver } from "./component-resolvers.js";
|
|
7
|
-
import { augmentHostWithCaching, augmentHostWithResources, augmentProgramWithVersioning, mergeTransformers } from "./host.js";
|
|
8
|
-
import { angularVitestPlugins } from "./angular-vitest-plugin.js";
|
|
9
|
-
import { pendingTasksPlugin } from "./angular-pending-tasks.plugin.js";
|
|
10
15
|
import { liveReloadPlugin } from "./live-reload-plugin.js";
|
|
16
|
+
import { toVirtualRawId } from "./utils/virtual-ids.js";
|
|
17
|
+
import { virtualModulesPlugin } from "./virtual-modules-plugin.js";
|
|
18
|
+
import { encapsulationPlugin, getComponentStyleSheetMeta, isComponentStyleSheet } from "./encapsulation-plugin.js";
|
|
11
19
|
import { nxFolderPlugin } from "./nx-folder-plugin.js";
|
|
12
|
-
import { replaceFiles } from "./plugins/file-replacements.plugin.js";
|
|
13
20
|
import { routerPlugin } from "./router-plugin.js";
|
|
14
|
-
import {
|
|
21
|
+
import { replaceFiles } from "./plugins/file-replacements.plugin.js";
|
|
22
|
+
import { cssExtensionStyleResolverPlugin } from "./utils/css-extension-resolver.js";
|
|
23
|
+
import { loadVirtualRawModule, rewriteHtmlRawImport } from "./utils/virtual-resources.js";
|
|
24
|
+
import { StyleUrlsResolver, TemplateUrlsResolver } from "./component-resolvers.js";
|
|
25
|
+
import { augmentHostWithCaching, augmentHostWithResources, augmentProgramWithVersioning, mergeTransformers } from "./host.js";
|
|
26
|
+
import { markStylePathSafe } from "./utils/safe-module-paths.js";
|
|
27
|
+
import { fastCompilePlugin } from "./fast-compile-plugin.js";
|
|
28
|
+
import { pendingTasksPlugin } from "./angular-pending-tasks.plugin.js";
|
|
29
|
+
import { union } from "es-toolkit";
|
|
30
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
15
31
|
import { basename, dirname, isAbsolute, join, relative, resolve } from "node:path";
|
|
16
|
-
import * as compilerCli from "@angular/compiler-cli";
|
|
17
32
|
import { createRequire } from "node:module";
|
|
18
|
-
import
|
|
19
|
-
import
|
|
20
|
-
import { defaultClientConditions, normalizePath, preprocessCSS } from "vite";
|
|
21
|
-
import { createHash } from "node:crypto";
|
|
33
|
+
import { normalizePath, preprocessCSS } from "vite";
|
|
34
|
+
import * as compilerCli from "@angular/compiler-cli";
|
|
22
35
|
//#region packages/vite-plugin-angular/src/lib/angular-vite-plugin.ts
|
|
23
36
|
var require = createRequire(import.meta.url);
|
|
24
|
-
var DiagnosticModes = /* @__PURE__ */ function(DiagnosticModes) {
|
|
25
|
-
DiagnosticModes[DiagnosticModes["None"] = 0] = "None";
|
|
26
|
-
DiagnosticModes[DiagnosticModes["Option"] = 1] = "Option";
|
|
27
|
-
DiagnosticModes[DiagnosticModes["Syntactic"] = 2] = "Syntactic";
|
|
28
|
-
DiagnosticModes[DiagnosticModes["Semantic"] = 4] = "Semantic";
|
|
29
|
-
DiagnosticModes[DiagnosticModes["All"] = 7] = "All";
|
|
30
|
-
return DiagnosticModes;
|
|
31
|
-
}({});
|
|
32
|
-
/**
|
|
33
|
-
* TypeScript file extension regex
|
|
34
|
-
* Match .(c or m)ts, .ts extensions with an optional ? for query params
|
|
35
|
-
* Ignore .tsx extensions
|
|
36
|
-
*/
|
|
37
|
-
var TS_EXT_REGEX = /\.[cm]?(ts)[^x]?\??/;
|
|
38
37
|
var classNames = /* @__PURE__ */ new Map();
|
|
38
|
+
function evictDeletedFileMetadata(file, { classNamesMap, fileTransformMap }) {
|
|
39
|
+
const normalizedFile = normalizePath(file.split("?")[0]);
|
|
40
|
+
classNamesMap.delete(normalizedFile);
|
|
41
|
+
fileTransformMap.delete(normalizedFile);
|
|
42
|
+
}
|
|
39
43
|
function angular(options) {
|
|
44
|
+
applyDebugOption(options?.debug, options?.workspaceRoot);
|
|
45
|
+
const liveReload = options?.liveReload ?? true;
|
|
46
|
+
let externalizeStylesRequested = false;
|
|
47
|
+
let configureStylesheetRegistry;
|
|
48
|
+
let transformFilter;
|
|
40
49
|
/**
|
|
41
50
|
* Normalize plugin options so defaults
|
|
42
51
|
* are used for values not provided.
|
|
43
52
|
*/
|
|
44
53
|
const pluginOptions = {
|
|
45
54
|
tsconfigGetter: createTsConfigGetter(options?.tsconfig),
|
|
46
|
-
workspaceRoot: options?.workspaceRoot ?? process.cwd(),
|
|
55
|
+
workspaceRoot: options?.workspaceRoot ?? process.env["NX_WORKSPACE_ROOT"] ?? process.cwd(),
|
|
47
56
|
inlineStylesExtension: options?.inlineStylesExtension ?? "css",
|
|
48
|
-
advanced: { tsTransformers: {
|
|
49
|
-
before: options?.advanced?.tsTransformers?.before ?? [],
|
|
50
|
-
after: options?.advanced?.tsTransformers?.after ?? [],
|
|
51
|
-
afterDeclarations: options?.advanced?.tsTransformers?.afterDeclarations ?? []
|
|
52
|
-
} },
|
|
53
57
|
supportedBrowsers: options?.supportedBrowsers ?? ["safari 15"],
|
|
54
58
|
jit: options?.jit,
|
|
55
59
|
include: options?.include ?? [],
|
|
56
|
-
|
|
57
|
-
liveReload: options?.liveReload ?? false,
|
|
60
|
+
liveReload,
|
|
58
61
|
disableTypeChecking: options?.disableTypeChecking ?? true,
|
|
59
62
|
fileReplacements: options?.fileReplacements ?? [],
|
|
60
|
-
|
|
63
|
+
fastCompile: options?.fastCompile ?? false,
|
|
64
|
+
fastCompileMode: options?.fastCompileMode ?? "full",
|
|
65
|
+
stylePreprocessor: void 0
|
|
61
66
|
};
|
|
62
67
|
let resolvedConfig;
|
|
63
68
|
let tsConfigResolutionContext = null;
|
|
64
69
|
const ts = require("typescript");
|
|
65
70
|
let builder;
|
|
66
71
|
let nextProgram;
|
|
67
|
-
const tsconfigOptionsCache = /* @__PURE__ */ new Map();
|
|
68
72
|
let cachedHost;
|
|
69
73
|
let cachedHostKey;
|
|
70
|
-
|
|
74
|
+
const isTest = process.env.NODE_ENV === "test" || !!process.env["VITEST"];
|
|
75
|
+
const tsconfigResolver = new TsconfigResolver({
|
|
76
|
+
workspaceRoot: pluginOptions.workspaceRoot,
|
|
77
|
+
include: pluginOptions.include,
|
|
78
|
+
liveReload: pluginOptions.liveReload,
|
|
79
|
+
isTest
|
|
80
|
+
});
|
|
71
81
|
function invalidateFsCaches() {
|
|
72
|
-
|
|
82
|
+
tsconfigResolver.invalidateIncludeCache();
|
|
73
83
|
}
|
|
74
84
|
function invalidateTsconfigCaches() {
|
|
75
|
-
|
|
85
|
+
tsconfigResolver.invalidateTsconfigCaches();
|
|
76
86
|
cachedHost = void 0;
|
|
77
87
|
cachedHostKey = void 0;
|
|
78
88
|
}
|
|
79
89
|
let watchMode = false;
|
|
80
90
|
let testWatchMode = isTestWatchMode();
|
|
81
|
-
|
|
82
|
-
|
|
91
|
+
function hasViteHmrTransport() {
|
|
92
|
+
return resolvedConfig ? resolvedConfig.server.hmr !== false : true;
|
|
93
|
+
}
|
|
94
|
+
function shouldEnableLiveReload() {
|
|
95
|
+
return !!((isTest ? testWatchMode : watchMode) && pluginOptions.liveReload && hasViteHmrTransport());
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Determines whether Angular should externalize component styles.
|
|
99
|
+
*
|
|
100
|
+
* When true, Angular emits style references (hash-based IDs) instead of
|
|
101
|
+
* inlining CSS strings. Vite's resolveId → load → transform pipeline
|
|
102
|
+
* then serves these virtual modules, allowing @tailwindcss/vite to
|
|
103
|
+
* process @reference directives.
|
|
104
|
+
*
|
|
105
|
+
* Required for TWO independent use-cases:
|
|
106
|
+
* 1. HMR — Vite needs external modules for hot replacement
|
|
107
|
+
* 2. A Vite plugin asked for it through `analog.setup()` so its styles
|
|
108
|
+
* pass through Vite's CSS pipeline (e.g. @tailwindcss/vite)
|
|
109
|
+
*
|
|
110
|
+
* In production builds (!watchMode), styles are NOT externalized — they
|
|
111
|
+
* are inlined after preprocessCSS runs eagerly in transformStylesheet.
|
|
112
|
+
*/
|
|
113
|
+
function shouldExternalizeStyles() {
|
|
114
|
+
if (!(isTest ? testWatchMode : watchMode)) return false;
|
|
115
|
+
return !!(shouldEnableLiveReload() || externalizeStylesRequested);
|
|
116
|
+
}
|
|
117
|
+
let stylesheetRegistry;
|
|
83
118
|
const sourceFileCache$1 = new sourceFileCache();
|
|
84
|
-
const
|
|
119
|
+
const tsSourceFileCache = /* @__PURE__ */ new Map();
|
|
120
|
+
function invalidateSourceFiles(files) {
|
|
121
|
+
for (const file of files) tsSourceFileCache.delete(normalizePath(file));
|
|
122
|
+
sourceFileCache$1.invalidate(files);
|
|
123
|
+
}
|
|
85
124
|
const isVitestVscode = !!process.env["VITEST_VSCODE"];
|
|
86
125
|
const isStackBlitz = !!process.versions["webcontainer"];
|
|
87
126
|
const isAstroIntegration = process.env["ANALOG_ASTRO"] === "true";
|
|
@@ -91,9 +130,36 @@ function angular(options) {
|
|
|
91
130
|
const templateUrlsResolver = new TemplateUrlsResolver();
|
|
92
131
|
let outputFile;
|
|
93
132
|
const outputFiles = /* @__PURE__ */ new Map();
|
|
133
|
+
const normalizeEmitterLookupId = (file) => {
|
|
134
|
+
const normalizedFile = normalizePath(file);
|
|
135
|
+
if (!normalizedFile.startsWith("/@fs/")) return normalizedFile;
|
|
136
|
+
return normalizePath(normalizedFile.slice(4).replace(/^\/([A-Za-z]:\/)/, "$1"));
|
|
137
|
+
};
|
|
138
|
+
const describeEmitMarkers = (content) => ({
|
|
139
|
+
contentLength: content.length,
|
|
140
|
+
hasCmp: content.includes("ɵcmp"),
|
|
141
|
+
hasFac: content.includes("ɵfac"),
|
|
142
|
+
hasProv: content.includes("ɵprov"),
|
|
143
|
+
hasDecorate: content.includes("__decorate"),
|
|
144
|
+
hasMetadata: content.includes("__metadata")
|
|
145
|
+
});
|
|
94
146
|
const fileEmitter = (file) => {
|
|
95
|
-
|
|
96
|
-
|
|
147
|
+
const normalizedFile = normalizeEmitterLookupId(file);
|
|
148
|
+
const hadCachedEmit = outputFiles.has(normalizedFile);
|
|
149
|
+
outputFile?.(normalizedFile);
|
|
150
|
+
const emittedResult = outputFiles.get(normalizedFile);
|
|
151
|
+
debugEmitV("fileEmitter lookup", {
|
|
152
|
+
requestFile: file,
|
|
153
|
+
normalizedFile,
|
|
154
|
+
hadCachedEmit,
|
|
155
|
+
hasOutputFileHook: !!outputFile,
|
|
156
|
+
emitted: !!emittedResult,
|
|
157
|
+
knownOutputCount: outputFiles.size,
|
|
158
|
+
contentLength: emittedResult?.content?.length ?? 0,
|
|
159
|
+
errorCount: emittedResult?.errors?.length ?? 0,
|
|
160
|
+
warningCount: emittedResult?.warnings?.length ?? 0
|
|
161
|
+
});
|
|
162
|
+
return emittedResult;
|
|
97
163
|
};
|
|
98
164
|
let initialCompilation = false;
|
|
99
165
|
const declarationFiles = [];
|
|
@@ -101,29 +167,38 @@ function angular(options) {
|
|
|
101
167
|
let styleTransform;
|
|
102
168
|
let pendingCompilation;
|
|
103
169
|
let compilationLock = Promise.resolve();
|
|
104
|
-
let angularCompilation;
|
|
105
170
|
function angularPlugin() {
|
|
106
171
|
let isProd = false;
|
|
107
|
-
if (angularFullVersion < 19e4
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
172
|
+
if (angularFullVersion < 19e4 && pluginOptions.liveReload) {
|
|
173
|
+
debugHmr("hmr disabled: Angular version does not support HMR APIs", {
|
|
174
|
+
angularVersion: angularFullVersion,
|
|
175
|
+
isTest
|
|
176
|
+
});
|
|
177
|
+
console.warn("[@analogjs/vite-plugin-angular]: HMR was disabled because Angular v19+ is required for externalRuntimeStyles/_enableHmr support. Detected Angular version: %s.", angularFullVersion);
|
|
178
|
+
pluginOptions.liveReload = false;
|
|
179
|
+
}
|
|
180
|
+
if (isTest) {
|
|
181
|
+
pluginOptions.liveReload = false;
|
|
182
|
+
debugHmr("hmr disabled", {
|
|
183
|
+
angularVersion: angularFullVersion,
|
|
184
|
+
isTest
|
|
185
|
+
});
|
|
113
186
|
}
|
|
114
187
|
return {
|
|
115
188
|
name: "@analogjs/vite-plugin-angular",
|
|
189
|
+
api: { getTsConfigPath: resolveTsConfigPath },
|
|
116
190
|
async config(config, { command }) {
|
|
191
|
+
activateDeferredDebug(command);
|
|
117
192
|
watchMode = command === "serve";
|
|
118
|
-
isProd = config.mode
|
|
193
|
+
isProd = isProdMode(config.mode);
|
|
119
194
|
tsConfigResolutionContext = {
|
|
120
195
|
root: config.root || ".",
|
|
121
196
|
isProd,
|
|
122
197
|
isLib: !!config?.build?.lib
|
|
123
198
|
};
|
|
124
199
|
const preliminaryTsConfigPath = resolveTsConfigPath();
|
|
125
|
-
const esbuild =
|
|
126
|
-
const oxc =
|
|
200
|
+
const esbuild = config.esbuild ?? false;
|
|
201
|
+
const oxc = config.oxc ?? false;
|
|
127
202
|
const defineOptions = {
|
|
128
203
|
ngJitMode: "false",
|
|
129
204
|
ngI18nClosureMode: "false",
|
|
@@ -138,7 +213,7 @@ function angular(options) {
|
|
|
138
213
|
advancedOptimizations: isProd,
|
|
139
214
|
jit,
|
|
140
215
|
incremental: watchMode
|
|
141
|
-
})] };
|
|
216
|
+
}, isTest, !isAstroIntegration)] };
|
|
142
217
|
const esbuildOptions = {
|
|
143
218
|
plugins: [createCompilerPlugin({
|
|
144
219
|
tsconfig: preliminaryTsConfigPath,
|
|
@@ -152,18 +227,24 @@ function angular(options) {
|
|
|
152
227
|
return {
|
|
153
228
|
[jsTransformConfigKey]: jsTransformConfigValue,
|
|
154
229
|
optimizeDeps: {
|
|
155
|
-
include: [
|
|
230
|
+
include: [
|
|
231
|
+
"rxjs/operators",
|
|
232
|
+
"rxjs",
|
|
233
|
+
"tslib"
|
|
234
|
+
],
|
|
156
235
|
exclude: ["@angular/platform-server"],
|
|
157
236
|
...useRolldown ? { rolldownOptions } : { esbuildOptions }
|
|
158
|
-
}
|
|
159
|
-
resolve: { conditions: ["style", ...config.resolve?.conditions || defaultClientConditions] }
|
|
237
|
+
}
|
|
160
238
|
};
|
|
161
239
|
},
|
|
162
240
|
configResolved(config) {
|
|
163
241
|
resolvedConfig = config;
|
|
164
|
-
if (
|
|
165
|
-
|
|
166
|
-
|
|
242
|
+
if (config.logger?.warnOnce) {
|
|
243
|
+
const originalWarnOnce = config.logger.warnOnce;
|
|
244
|
+
config.logger.warnOnce = (msg, options) => {
|
|
245
|
+
if (typeof msg === "string" && msg.includes("Sourcemap") && msg.includes("node_modules")) return;
|
|
246
|
+
originalWarnOnce(msg, options);
|
|
247
|
+
};
|
|
167
248
|
}
|
|
168
249
|
if (!jit) styleTransform = (code, filename) => preprocessCSS(code, filename, config);
|
|
169
250
|
if (isTest) testWatchMode = !(config.server.watch === null) || config.test?.watch === true || testWatchMode;
|
|
@@ -172,30 +253,90 @@ function angular(options) {
|
|
|
172
253
|
viteServer = server;
|
|
173
254
|
const invalidateCompilationOnFsChange = createFsWatcherCacheInvalidator(invalidateFsCaches, invalidateTsconfigCaches, () => performCompilation(resolvedConfig));
|
|
174
255
|
server.watcher.on("add", invalidateCompilationOnFsChange);
|
|
175
|
-
server.watcher.on("unlink",
|
|
256
|
+
server.watcher.on("unlink", (file) => {
|
|
257
|
+
const id = normalizePath(file);
|
|
258
|
+
outputFiles.delete(id);
|
|
259
|
+
tsSourceFileCache.delete(id);
|
|
260
|
+
sourceFileCache$1.invalidate(new Set([id]));
|
|
261
|
+
evictDeletedFileMetadata(file, {
|
|
262
|
+
classNamesMap: classNames,
|
|
263
|
+
fileTransformMap
|
|
264
|
+
});
|
|
265
|
+
return invalidateCompilationOnFsChange();
|
|
266
|
+
});
|
|
176
267
|
server.watcher.on("change", (file) => {
|
|
177
268
|
if (file.includes("tsconfig")) invalidateTsconfigCaches();
|
|
178
269
|
});
|
|
179
270
|
},
|
|
180
271
|
async buildStart() {
|
|
181
272
|
if (!isVitestVscode) {
|
|
182
|
-
|
|
273
|
+
pendingCompilation = performCompilation(this.environment?.config ?? resolvedConfig);
|
|
274
|
+
await pendingCompilation;
|
|
183
275
|
pendingCompilation = null;
|
|
184
276
|
initialCompilation = true;
|
|
185
277
|
}
|
|
186
278
|
},
|
|
279
|
+
buildEnd() {
|
|
280
|
+
if (watchMode) return;
|
|
281
|
+
nextProgram = void 0;
|
|
282
|
+
cachedHost = void 0;
|
|
283
|
+
cachedHostKey = void 0;
|
|
284
|
+
outputFile = void 0;
|
|
285
|
+
outputFiles.clear();
|
|
286
|
+
fileTransformMap.clear();
|
|
287
|
+
tsSourceFileCache.clear();
|
|
288
|
+
sourceFileCache$1.clear();
|
|
289
|
+
sourceFileCache$1.modifiedFiles.clear();
|
|
290
|
+
sourceFileCache$1.babelFileCache?.clear();
|
|
291
|
+
sourceFileCache$1.typeScriptFileCache?.clear();
|
|
292
|
+
sourceFileCache$1.referencedFiles = void 0;
|
|
293
|
+
tsconfigResolver.invalidateAll();
|
|
294
|
+
releaseCssPreprocessorWorkers();
|
|
295
|
+
},
|
|
187
296
|
async handleHotUpdate(ctx) {
|
|
297
|
+
if (isIgnoredHmrFile(ctx.file)) {
|
|
298
|
+
debugHmr("ignored file change", { file: ctx.file });
|
|
299
|
+
return [];
|
|
300
|
+
}
|
|
188
301
|
if (TS_EXT_REGEX.test(ctx.file)) {
|
|
189
302
|
const [fileId] = ctx.file.split("?");
|
|
303
|
+
debugHmr("TS file changed", {
|
|
304
|
+
file: ctx.file,
|
|
305
|
+
fileId
|
|
306
|
+
});
|
|
190
307
|
pendingCompilation = performCompilation(resolvedConfig, [fileId]);
|
|
191
308
|
let result;
|
|
192
|
-
if (
|
|
309
|
+
if (shouldEnableLiveReload()) {
|
|
193
310
|
await pendingCompilation;
|
|
194
311
|
pendingCompilation = null;
|
|
195
312
|
result = fileEmitter(fileId);
|
|
313
|
+
debugHmr("TS file emitted", {
|
|
314
|
+
fileId,
|
|
315
|
+
hmrEligible: !!result?.hmrEligible,
|
|
316
|
+
hasClassName: !!classNames.get(fileId)
|
|
317
|
+
});
|
|
318
|
+
debugHmrV("ts hmr evaluation", {
|
|
319
|
+
file: ctx.file,
|
|
320
|
+
fileId,
|
|
321
|
+
hasResult: !!result,
|
|
322
|
+
hmrEligible: !!result?.hmrEligible,
|
|
323
|
+
hasClassName: !!classNames.get(fileId),
|
|
324
|
+
className: classNames.get(fileId),
|
|
325
|
+
updateCode: result?.hmrUpdateCode ? describeStylesheetContent(result.hmrUpdateCode) : void 0,
|
|
326
|
+
errors: result?.errors?.length ?? 0,
|
|
327
|
+
warnings: result?.warnings?.length ?? 0,
|
|
328
|
+
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."
|
|
329
|
+
});
|
|
196
330
|
}
|
|
197
|
-
if (
|
|
331
|
+
if (shouldEnableLiveReload() && result?.hmrEligible && classNames.get(fileId)) {
|
|
198
332
|
const relativeFileId = `${normalizePath(relative(process.cwd(), fileId))}@${classNames.get(fileId)}`;
|
|
333
|
+
debugHmr("sending component update", { relativeFileId });
|
|
334
|
+
debugHmrV("ts hmr component update payload", {
|
|
335
|
+
file: ctx.file,
|
|
336
|
+
fileId,
|
|
337
|
+
relativeFileId,
|
|
338
|
+
className: classNames.get(fileId)
|
|
339
|
+
});
|
|
199
340
|
sendHMRComponentUpdate(ctx.server, relativeFileId);
|
|
200
341
|
return ctx.modules.map((mod) => {
|
|
201
342
|
if (mod.id === ctx.file) return markModuleSelfAccepting(mod);
|
|
@@ -204,79 +345,260 @@ function angular(options) {
|
|
|
204
345
|
}
|
|
205
346
|
}
|
|
206
347
|
if (/\.(html|htm|css|less|sass|scss)$/.test(ctx.file)) {
|
|
348
|
+
debugHmr("resource file changed", { file: ctx.file });
|
|
207
349
|
fileTransformMap.delete(ctx.file.split("?")[0]);
|
|
350
|
+
const fileModules = await getModulesForChangedFile(ctx.server, ctx.file, ctx.modules, stylesheetRegistry);
|
|
208
351
|
/**
|
|
209
352
|
* Check to see if this was a direct request
|
|
210
353
|
* for an external resource (styles, html).
|
|
211
354
|
*/
|
|
212
|
-
const isDirect =
|
|
213
|
-
const isInline =
|
|
355
|
+
const isDirect = fileModules.find((mod) => !!mod.id && mod.id.includes("?direct") && isModuleForChangedResource(mod, ctx.file, stylesheetRegistry));
|
|
356
|
+
const isInline = fileModules.find((mod) => !!mod.id && mod.id.includes("?inline") && isModuleForChangedResource(mod, ctx.file, stylesheetRegistry));
|
|
357
|
+
debugHmrV("resource direct/inline detection", {
|
|
358
|
+
file: ctx.file,
|
|
359
|
+
hasDirect: !!isDirect,
|
|
360
|
+
directId: isDirect?.id,
|
|
361
|
+
hasInline: !!isInline,
|
|
362
|
+
inlineId: isInline?.id
|
|
363
|
+
});
|
|
214
364
|
if (isDirect || isInline) {
|
|
215
|
-
if (
|
|
216
|
-
|
|
365
|
+
if (shouldExternalizeStyles() && isDirect?.id && isDirect.file) {
|
|
366
|
+
const isComponentStyle = isDirect.type === "css" && isComponentStyleSheet(isDirect.id);
|
|
367
|
+
debugHmrV("resource direct branch", {
|
|
368
|
+
file: ctx.file,
|
|
369
|
+
directId: isDirect.id,
|
|
370
|
+
directType: isDirect.type,
|
|
371
|
+
shouldExternalize: shouldExternalizeStyles(),
|
|
372
|
+
isComponentStyle
|
|
373
|
+
});
|
|
374
|
+
if (isComponentStyle) {
|
|
217
375
|
const { encapsulation } = getComponentStyleSheetMeta(isDirect.id);
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
376
|
+
const wrapperModules = await findComponentStylesheetWrapperModules(ctx.server, ctx.file, isDirect, fileModules, stylesheetRegistry);
|
|
377
|
+
const stylesheetDiagnosis = diagnoseComponentStylesheetPipeline(ctx.file, isDirect, stylesheetRegistry, wrapperModules, pluginOptions.stylePreprocessor);
|
|
378
|
+
debugStylesV("HMR: component stylesheet changed", {
|
|
379
|
+
file: isDirect.file,
|
|
380
|
+
encapsulation
|
|
381
|
+
});
|
|
382
|
+
debugHmrV("component stylesheet wrapper modules", {
|
|
383
|
+
file: ctx.file,
|
|
384
|
+
wrapperCount: wrapperModules.length,
|
|
385
|
+
wrapperIds: wrapperModules.map((mod) => mod.id),
|
|
386
|
+
availableModuleIds: fileModules.map((mod) => mod.id)
|
|
387
|
+
});
|
|
388
|
+
debugHmrV("component stylesheet pipeline diagnosis", stylesheetDiagnosis);
|
|
389
|
+
ctx.server.moduleGraph.invalidateModule(isDirect);
|
|
390
|
+
debugHmrV("component stylesheet direct module invalidated", {
|
|
391
|
+
file: ctx.file,
|
|
392
|
+
directModuleId: isDirect.id,
|
|
393
|
+
directModuleUrl: isDirect.url,
|
|
394
|
+
reason: "Ensure Vite drops stale direct CSS transform results before wrapper or fallback handling continues."
|
|
395
|
+
});
|
|
396
|
+
const trackedWrapperRequestIds = stylesheetDiagnosis.trackedRequestIds.filter((id) => id.includes("?ngcomp="));
|
|
397
|
+
if (encapsulation !== "shadow" && (wrapperModules.length > 0 || trackedWrapperRequestIds.length > 0)) {
|
|
398
|
+
wrapperModules.forEach((mod) => ctx.server.moduleGraph.invalidateModule(mod));
|
|
399
|
+
debugHmrV("sending css-update for component stylesheet", {
|
|
400
|
+
file: ctx.file,
|
|
401
|
+
path: isDirect.url,
|
|
402
|
+
acceptedPath: isDirect.file,
|
|
403
|
+
wrapperCount: wrapperModules.length,
|
|
404
|
+
trackedWrapperRequestIds,
|
|
405
|
+
hint: wrapperModules.length > 0 ? "Live wrapper modules were found and invalidated before sending the CSS update." : "No live wrapper ModuleNode was available, but the wrapper request id is already tracked, so Analog is trusting the browser-visible wrapper identity and patching the direct stylesheet instead of forcing a reload."
|
|
227
406
|
});
|
|
228
|
-
|
|
407
|
+
sendCssUpdate(ctx.server, {
|
|
408
|
+
path: isDirect.url,
|
|
409
|
+
acceptedPath: isDirect.file
|
|
410
|
+
});
|
|
411
|
+
logComponentStylesheetHmrOutcome({
|
|
412
|
+
file: ctx.file,
|
|
413
|
+
encapsulation,
|
|
414
|
+
diagnosis: stylesheetDiagnosis,
|
|
415
|
+
outcome: "css-update",
|
|
416
|
+
directModuleId: isDirect.id,
|
|
417
|
+
wrapperIds: wrapperModules.map((mod) => mod.id)
|
|
418
|
+
});
|
|
419
|
+
return union(fileModules.filter((mod) => {
|
|
229
420
|
return mod.file !== ctx.file || mod.id !== isDirect.id;
|
|
230
421
|
}).map((mod) => {
|
|
231
422
|
if (mod.file === ctx.file) return markModuleSelfAccepting(mod);
|
|
232
423
|
return mod;
|
|
233
|
-
});
|
|
424
|
+
}), wrapperModules.map((mod) => markModuleSelfAccepting(mod)));
|
|
234
425
|
}
|
|
426
|
+
debugHmrV("component stylesheet hmr fallback: full reload", {
|
|
427
|
+
file: ctx.file,
|
|
428
|
+
encapsulation,
|
|
429
|
+
reason: trackedWrapperRequestIds.length === 0 ? "missing-wrapper-module" : encapsulation === "shadow" ? "shadow-encapsulation" : "tracked-wrapper-still-not-patchable",
|
|
430
|
+
directId: isDirect.id,
|
|
431
|
+
trackedRequestIds: stylesheetRegistry?.getRequestIdsForSource(ctx.file) ?? []
|
|
432
|
+
});
|
|
433
|
+
logComponentStylesheetHmrOutcome({
|
|
434
|
+
file: ctx.file,
|
|
435
|
+
encapsulation,
|
|
436
|
+
diagnosis: stylesheetDiagnosis,
|
|
437
|
+
outcome: "full-reload",
|
|
438
|
+
directModuleId: isDirect.id,
|
|
439
|
+
wrapperIds: wrapperModules.map((mod) => mod.id)
|
|
440
|
+
});
|
|
441
|
+
sendFullReload(ctx.server, {
|
|
442
|
+
file: ctx.file,
|
|
443
|
+
encapsulation,
|
|
444
|
+
reason: wrapperModules.length === 0 ? "missing-wrapper-module" : "shadow-encapsulation",
|
|
445
|
+
directId: isDirect.id,
|
|
446
|
+
trackedRequestIds: stylesheetRegistry?.getRequestIdsForSource(ctx.file) ?? []
|
|
447
|
+
});
|
|
448
|
+
return [];
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
return fileModules;
|
|
452
|
+
}
|
|
453
|
+
if (shouldEnableLiveReload() && /\.(html|htm)$/.test(ctx.file) && fileModules.length === 0) {
|
|
454
|
+
const ownerModules = findTemplateOwnerModules(ctx.server, ctx.file);
|
|
455
|
+
debugHmrV("template owner lookup", {
|
|
456
|
+
file: ctx.file,
|
|
457
|
+
ownerCount: ownerModules.length,
|
|
458
|
+
ownerIds: ownerModules.map((mod) => mod.id),
|
|
459
|
+
hint: ownerModules.length > 0 ? "The external template has candidate TS owner modules that can be recompiled for HMR." : "No TS owner modules were visible for this external template change; HMR will fall through to the generic importer path."
|
|
460
|
+
});
|
|
461
|
+
if (ownerModules.length > 0) {
|
|
462
|
+
const ownerIds = ownerModules.map((mod) => mod.id).filter(Boolean);
|
|
463
|
+
ownerModules.forEach((mod) => ctx.server.moduleGraph.invalidateModule(mod));
|
|
464
|
+
pendingCompilation = performCompilation(resolvedConfig, ownerIds);
|
|
465
|
+
await pendingCompilation;
|
|
466
|
+
pendingCompilation = null;
|
|
467
|
+
const updates = ownerIds.filter((id) => classNames.get(id));
|
|
468
|
+
debugHmrV("template owner recompilation result", {
|
|
469
|
+
file: ctx.file,
|
|
470
|
+
ownerIds,
|
|
471
|
+
updates,
|
|
472
|
+
updateClassNames: updates.map((id) => ({
|
|
473
|
+
id,
|
|
474
|
+
className: classNames.get(id)
|
|
475
|
+
})),
|
|
476
|
+
hint: updates.length > 0 ? "External template recompilation produced Angular component update targets." : "External template recompilation completed, but no Angular component update targets were surfaced."
|
|
477
|
+
});
|
|
478
|
+
if (updates.length > 0) {
|
|
479
|
+
debugHmr("template owner module invalidation", {
|
|
480
|
+
file: ctx.file,
|
|
481
|
+
ownerIds,
|
|
482
|
+
updateCount: updates.length
|
|
483
|
+
});
|
|
484
|
+
updates.forEach((updateId) => {
|
|
485
|
+
const relativeFileId = `${normalizePath(relative(process.cwd(), updateId))}@${classNames.get(updateId)}`;
|
|
486
|
+
sendHMRComponentUpdate(ctx.server, relativeFileId);
|
|
487
|
+
});
|
|
488
|
+
return ownerModules.map((mod) => markModuleSelfAccepting(mod));
|
|
235
489
|
}
|
|
236
490
|
}
|
|
237
|
-
return ctx.modules;
|
|
238
491
|
}
|
|
239
492
|
const mods = [];
|
|
240
493
|
const updates = [];
|
|
241
|
-
|
|
494
|
+
fileModules.forEach((mod) => {
|
|
242
495
|
mod.importers.forEach((imp) => {
|
|
243
496
|
ctx.server.moduleGraph.invalidateModule(imp);
|
|
244
|
-
if (
|
|
497
|
+
if (shouldExternalizeStyles() && classNames.get(imp.id)) updates.push(imp.id);
|
|
245
498
|
else mods.push(imp);
|
|
246
499
|
});
|
|
247
500
|
});
|
|
248
|
-
|
|
501
|
+
debugHmrV("resource importer analysis", {
|
|
502
|
+
file: ctx.file,
|
|
503
|
+
fileModuleCount: fileModules.length,
|
|
504
|
+
importerCount: fileModules.reduce((count, mod) => count + mod.importers.size, 0),
|
|
505
|
+
updates,
|
|
506
|
+
mods: mods.map((mod) => mod.id)
|
|
507
|
+
});
|
|
508
|
+
pendingCompilation = performCompilation(resolvedConfig, [...mods.map((mod) => mod.id).filter(Boolean), ...updates]);
|
|
249
509
|
if (updates.length > 0) {
|
|
250
510
|
await pendingCompilation;
|
|
251
511
|
pendingCompilation = null;
|
|
512
|
+
debugHmr("resource importer component updates", {
|
|
513
|
+
file: ctx.file,
|
|
514
|
+
updateCount: updates.length
|
|
515
|
+
});
|
|
252
516
|
updates.forEach((updateId) => {
|
|
253
517
|
const impRelativeFileId = `${normalizePath(relative(process.cwd(), updateId))}@${classNames.get(updateId)}`;
|
|
254
518
|
sendHMRComponentUpdate(ctx.server, impRelativeFileId);
|
|
255
519
|
});
|
|
256
|
-
return
|
|
520
|
+
return fileModules.map((mod) => {
|
|
257
521
|
if (mod.id === ctx.file) return markModuleSelfAccepting(mod);
|
|
258
522
|
return mod;
|
|
259
523
|
});
|
|
260
524
|
}
|
|
261
525
|
return mods;
|
|
262
526
|
}
|
|
527
|
+
debugHmr("full reload — unrecognized file type", { file: ctx.file });
|
|
263
528
|
classNames.clear();
|
|
264
529
|
return ctx.modules;
|
|
265
530
|
},
|
|
266
531
|
resolveId(id, importer) {
|
|
532
|
+
if (id.startsWith("virtual:@analogjs/vite-plugin-angular:raw:")) return `\0${id}`;
|
|
267
533
|
if (jit && id.startsWith("angular:jit:")) {
|
|
268
|
-
const
|
|
269
|
-
|
|
534
|
+
const filePath = normalizePath(resolve(dirname(importer), id.split(";")[1]));
|
|
535
|
+
if (id.includes(":style")) {
|
|
536
|
+
markStylePathSafe(resolvedConfig, filePath);
|
|
537
|
+
return filePath + "?inline";
|
|
538
|
+
}
|
|
539
|
+
return toVirtualRawId(filePath);
|
|
540
|
+
}
|
|
541
|
+
const rawRewrite = rewriteHtmlRawImport(id, importer);
|
|
542
|
+
if (rawRewrite) return rawRewrite;
|
|
543
|
+
if (/\.(css|scss|sass|less)\?inline$/.test(id) && importer) {
|
|
544
|
+
const filePath = id.split("?")[0];
|
|
545
|
+
const resolved = isAbsolute(filePath) ? normalizePath(filePath) : normalizePath(resolve(dirname(importer), filePath));
|
|
546
|
+
markStylePathSafe(resolvedConfig, resolved);
|
|
547
|
+
return resolved + "?inline";
|
|
270
548
|
}
|
|
271
549
|
if (isComponentStyleSheet(id)) {
|
|
272
|
-
const
|
|
273
|
-
|
|
550
|
+
const filename = getFilenameFromPath(id);
|
|
551
|
+
const search = new URL(id, "http://localhost").search;
|
|
552
|
+
const servedSourcePath = stylesheetRegistry?.getServedSourcePath(filename);
|
|
553
|
+
if (servedSourcePath) {
|
|
554
|
+
debugStylesV("resolveId: mapped served stylesheet to source", {
|
|
555
|
+
filename,
|
|
556
|
+
resolvedPath: servedSourcePath
|
|
557
|
+
});
|
|
558
|
+
return servedSourcePath + search;
|
|
559
|
+
}
|
|
560
|
+
if (stylesheetRegistry?.hasServed(filename)) {
|
|
561
|
+
debugStylesV("resolveId: kept preprocessed ID", { filename });
|
|
562
|
+
return id;
|
|
563
|
+
}
|
|
564
|
+
const componentStyles = stylesheetRegistry?.resolveExternalSource(filename);
|
|
565
|
+
if (componentStyles) {
|
|
566
|
+
debugStylesV("resolveId: mapped external stylesheet", {
|
|
567
|
+
filename,
|
|
568
|
+
resolvedPath: componentStyles
|
|
569
|
+
});
|
|
570
|
+
return componentStyles + new URL(id, "http://localhost").search;
|
|
571
|
+
}
|
|
572
|
+
debugStyles("resolveId: component stylesheet NOT FOUND in either map", {
|
|
573
|
+
filename,
|
|
574
|
+
inlineMapSize: stylesheetRegistry?.servedCount ?? 0,
|
|
575
|
+
externalMapSize: stylesheetRegistry?.externalCount ?? 0
|
|
576
|
+
});
|
|
274
577
|
}
|
|
275
578
|
},
|
|
276
579
|
async load(id) {
|
|
580
|
+
const rawModule = await loadVirtualRawModule(this, id);
|
|
581
|
+
if (rawModule !== void 0) return rawModule;
|
|
582
|
+
if (/\.(css|scss|sass|less)\?inline$/.test(id)) markStylePathSafe(resolvedConfig, id.split("?")[0]);
|
|
277
583
|
if (isComponentStyleSheet(id)) {
|
|
278
|
-
const
|
|
279
|
-
|
|
584
|
+
const filename = getFilenameFromPath(id);
|
|
585
|
+
const componentStyles = stylesheetRegistry?.getServedContent(filename);
|
|
586
|
+
if (componentStyles) {
|
|
587
|
+
stylesheetRegistry?.registerActiveRequest(id);
|
|
588
|
+
debugHmrV("stylesheet active request registered", {
|
|
589
|
+
requestId: id,
|
|
590
|
+
filename,
|
|
591
|
+
sourcePath: stylesheetRegistry?.resolveExternalSource(filename) ?? stylesheetRegistry?.resolveExternalSource(filename.replace(/^\//, "")) ?? stylesheetRegistry?.getServedSourcePath(filename) ?? stylesheetRegistry?.getServedSourcePath(filename.replace(/^\//, "")),
|
|
592
|
+
trackedRequestIds: stylesheetRegistry?.getRequestIdsForSource(stylesheetRegistry?.resolveExternalSource(filename) ?? stylesheetRegistry?.resolveExternalSource(filename.replace(/^\//, "")) ?? stylesheetRegistry?.getServedSourcePath(filename) ?? stylesheetRegistry?.getServedSourcePath(filename.replace(/^\//, "")) ?? "") ?? []
|
|
593
|
+
});
|
|
594
|
+
debugStylesV("load: served inline component stylesheet", {
|
|
595
|
+
filename,
|
|
596
|
+
length: componentStyles.length,
|
|
597
|
+
requestId: id,
|
|
598
|
+
...describeStylesheetContent(componentStyles)
|
|
599
|
+
});
|
|
600
|
+
return componentStyles;
|
|
601
|
+
}
|
|
280
602
|
}
|
|
281
603
|
},
|
|
282
604
|
transform: {
|
|
@@ -289,27 +611,7 @@ function angular(options) {
|
|
|
289
611
|
]
|
|
290
612
|
} },
|
|
291
613
|
async handler(code, id) {
|
|
292
|
-
|
|
293
|
-
* Check for options.transformFilter
|
|
294
|
-
*/
|
|
295
|
-
if (options?.transformFilter && !(options?.transformFilter(code, id) ?? true)) return;
|
|
296
|
-
if (pluginOptions.useAngularCompilationAPI) {
|
|
297
|
-
if (!/(Component|Directive|Pipe|Injectable|NgModule)\(/.test(code)) return;
|
|
298
|
-
}
|
|
299
|
-
/**
|
|
300
|
-
* Skip transforming content files
|
|
301
|
-
*/
|
|
302
|
-
if (id.includes("?") && id.includes("analog-content-")) return;
|
|
303
|
-
/**
|
|
304
|
-
* Encapsulate component stylesheets that use emulated encapsulation
|
|
305
|
-
*/
|
|
306
|
-
if (pluginOptions.liveReload && isComponentStyleSheet(id)) {
|
|
307
|
-
const { encapsulation, componentId } = getComponentStyleSheetMeta(id);
|
|
308
|
-
if (encapsulation === "emulated" && componentId) return {
|
|
309
|
-
code: ngCompiler.encapsulateStyle(code, componentId),
|
|
310
|
-
map: null
|
|
311
|
-
};
|
|
312
|
-
}
|
|
614
|
+
if (transformFilter && !transformFilter(code, id)) return;
|
|
313
615
|
if (id.includes(".ts?")) id = id.replace(/\?(.*)/, "");
|
|
314
616
|
fileTransformMap.set(id, code);
|
|
315
617
|
/**
|
|
@@ -318,19 +620,25 @@ function angular(options) {
|
|
|
318
620
|
*/
|
|
319
621
|
if (isTest) {
|
|
320
622
|
if (isVitestVscode && !initialCompilation) {
|
|
321
|
-
pendingCompilation = performCompilation(resolvedConfig);
|
|
623
|
+
pendingCompilation = performCompilation(this.environment?.config ?? resolvedConfig);
|
|
322
624
|
initialCompilation = true;
|
|
323
625
|
}
|
|
324
626
|
const tsMod = viteServer?.moduleGraph.getModuleById(id);
|
|
325
627
|
if (tsMod) {
|
|
326
628
|
const invalidated = tsMod.lastInvalidationTimestamp;
|
|
327
|
-
if (testWatchMode && invalidated) pendingCompilation = performCompilation(resolvedConfig, [id]);
|
|
629
|
+
if (testWatchMode && invalidated) pendingCompilation = performCompilation(this.environment?.config ?? resolvedConfig, [id]);
|
|
328
630
|
}
|
|
329
631
|
}
|
|
330
632
|
const hasComponent = code.includes("@Component");
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
633
|
+
debugCompilerV("transform", {
|
|
634
|
+
id,
|
|
635
|
+
codeLength: code.length,
|
|
636
|
+
hasComponent
|
|
637
|
+
});
|
|
638
|
+
const resolveResourceUrls = hasComponent && (watchMode || jit);
|
|
639
|
+
const templateUrls = resolveResourceUrls ? templateUrlsResolver.resolve(code, id) : [];
|
|
640
|
+
const styleUrls = resolveResourceUrls ? styleUrlsResolver.resolve(code, id) : [];
|
|
641
|
+
if (resolveResourceUrls && watchMode) for (const urlSet of [...templateUrls, ...styleUrls]) {
|
|
334
642
|
const [, absoluteFileUrl] = urlSet.split("|");
|
|
335
643
|
this.addWatchFile(absoluteFileUrl);
|
|
336
644
|
}
|
|
@@ -339,23 +647,58 @@ function angular(options) {
|
|
|
339
647
|
pendingCompilation = null;
|
|
340
648
|
}
|
|
341
649
|
const typescriptResult = fileEmitter(id);
|
|
342
|
-
if (typescriptResult
|
|
343
|
-
|
|
344
|
-
|
|
650
|
+
if (!typescriptResult) {
|
|
651
|
+
debugCompilerV("transform skip (file not emitted by Angular)", { id });
|
|
652
|
+
const isAngular = !id.includes("@ng/component") && /(Component|Directive|Pipe|Injectable|NgModule)\(/.test(code);
|
|
653
|
+
debugEmit("transform emit miss", {
|
|
654
|
+
id,
|
|
655
|
+
normalizedId: normalizeEmitterLookupId(id),
|
|
656
|
+
knownOutputCount: outputFiles.size,
|
|
657
|
+
hasOutputFileHook: !!outputFile,
|
|
658
|
+
isAngular
|
|
659
|
+
});
|
|
660
|
+
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.`);
|
|
661
|
+
return;
|
|
662
|
+
}
|
|
663
|
+
if (typescriptResult.warnings && typescriptResult.warnings.length > 0) this.warn(`${typescriptResult.warnings.join("\n")}`);
|
|
664
|
+
if (typescriptResult.errors && typescriptResult.errors.length > 0) this.error(`${typescriptResult.errors.join("\n")}`);
|
|
665
|
+
let data = typescriptResult.content ?? "";
|
|
666
|
+
debugEmitV("transform emit hit", {
|
|
667
|
+
id,
|
|
668
|
+
normalizedId: normalizeEmitterLookupId(id),
|
|
669
|
+
...describeEmitMarkers(data),
|
|
670
|
+
errorCount: typescriptResult.errors?.length ?? 0,
|
|
671
|
+
warningCount: typescriptResult.warnings?.length ?? 0
|
|
672
|
+
});
|
|
345
673
|
if (jit && data.includes("angular:jit:")) {
|
|
346
|
-
data = data.replace(/angular:jit:style:inline
|
|
674
|
+
data = data.replace(/angular:jit:style:inline;([A-Za-z0-9+/=]*)/g, (_match, encodedStyles) => toJitInlineStyleId(encodedStyles));
|
|
347
675
|
templateUrls.forEach((templateUrlSet) => {
|
|
348
676
|
const [templateFile, resolvedTemplateUrl] = templateUrlSet.split("|");
|
|
349
|
-
data = data.replace(`angular:jit:template:file;${templateFile}`,
|
|
677
|
+
data = data.replace(`angular:jit:template:file;${templateFile}`, toVirtualRawId(resolvedTemplateUrl));
|
|
350
678
|
});
|
|
351
679
|
styleUrls.forEach((styleUrlSet) => {
|
|
352
680
|
const [styleFile, resolvedStyleUrl] = styleUrlSet.split("|");
|
|
353
|
-
|
|
681
|
+
markStylePathSafe(resolvedConfig, resolvedStyleUrl);
|
|
682
|
+
data = data.replace(`angular:jit:style:file;${styleFile}`, resolvedStyleUrl + "?inline");
|
|
354
683
|
});
|
|
355
684
|
}
|
|
685
|
+
if (data.includes("HmrLoad")) {
|
|
686
|
+
const hasMetaUrl = data.includes("getReplaceMetadataURL");
|
|
687
|
+
debugHmrV("vite-ignore injection", {
|
|
688
|
+
id,
|
|
689
|
+
dataLength: data.length,
|
|
690
|
+
hasMetaUrl
|
|
691
|
+
});
|
|
692
|
+
if (hasMetaUrl) {
|
|
693
|
+
const patched = injectViteIgnoreForHmrMetadata(data);
|
|
694
|
+
if (patched !== data && !patched.includes("@vite-ignore")) debugHmrV("vite-ignore regex fallback", { id });
|
|
695
|
+
data = patched;
|
|
696
|
+
}
|
|
697
|
+
}
|
|
698
|
+
if (typescriptResult.map) data = data.replace(/\s*\/\/# sourceMappingURL=[^\r\n]*\s*$/, "");
|
|
356
699
|
return {
|
|
357
700
|
code: data,
|
|
358
|
-
map: null
|
|
701
|
+
map: typescriptResult.map ? normalizeSourceMapSources(typescriptResult.map, id) : null
|
|
359
702
|
};
|
|
360
703
|
}
|
|
361
704
|
},
|
|
@@ -364,19 +707,47 @@ function angular(options) {
|
|
|
364
707
|
mkdirSync(declarationFileDir, { recursive: true });
|
|
365
708
|
writeFileSync(declarationPath, data, "utf-8");
|
|
366
709
|
});
|
|
367
|
-
|
|
368
|
-
|
|
710
|
+
declarationFiles.length = 0;
|
|
711
|
+
if (!watchMode) releaseCssPreprocessorWorkers();
|
|
369
712
|
}
|
|
370
713
|
};
|
|
371
714
|
}
|
|
715
|
+
function normalizeSourceMapSources(map, id) {
|
|
716
|
+
const sourceMap = JSON.parse(map);
|
|
717
|
+
const sourceDirectory = dirname(id);
|
|
718
|
+
const sourceRoot = sourceMap.sourceRoot ?? "";
|
|
719
|
+
sourceMap.sources = sourceMap.sources?.map((source) => {
|
|
720
|
+
if (isAbsolute(source) || /^[a-z][a-z\d+.-]*:/i.test(source)) return normalizePath(source);
|
|
721
|
+
return normalizePath(resolve(sourceDirectory, sourceRoot, source));
|
|
722
|
+
});
|
|
723
|
+
delete sourceMap.sourceRoot;
|
|
724
|
+
return JSON.stringify(sourceMap);
|
|
725
|
+
}
|
|
726
|
+
const compilationPlugin = pluginOptions.fastCompile ? fastCompilePlugin({
|
|
727
|
+
tsconfigGetter: pluginOptions.tsconfigGetter,
|
|
728
|
+
workspaceRoot: pluginOptions.workspaceRoot,
|
|
729
|
+
inlineStylesExtension: pluginOptions.inlineStylesExtension,
|
|
730
|
+
jit,
|
|
731
|
+
liveReload: pluginOptions.liveReload,
|
|
732
|
+
supportedBrowsers: pluginOptions.supportedBrowsers,
|
|
733
|
+
isTest,
|
|
734
|
+
isAstroIntegration,
|
|
735
|
+
fastCompileMode: pluginOptions.fastCompileMode
|
|
736
|
+
}) : angularPlugin();
|
|
372
737
|
return [
|
|
738
|
+
cssExtensionStyleResolverPlugin(),
|
|
373
739
|
replaceFiles(pluginOptions.fileReplacements, pluginOptions.workspaceRoot),
|
|
374
|
-
|
|
740
|
+
virtualModulesPlugin({ jit }),
|
|
375
741
|
pluginOptions.liveReload && liveReloadPlugin({
|
|
376
742
|
classNames,
|
|
377
743
|
fileEmitter
|
|
378
744
|
}),
|
|
379
|
-
|
|
745
|
+
compilationPlugin,
|
|
746
|
+
!pluginOptions.fastCompile && pluginOptions.liveReload && liveReloadPlugin({
|
|
747
|
+
classNames,
|
|
748
|
+
fileEmitter
|
|
749
|
+
}),
|
|
750
|
+
...isTest && !isStackBlitz ? angularVitestPlugins((id) => outputFiles.get(normalizePath(id))?.map) : [],
|
|
380
751
|
jit && jitPlugin({ inlineStylesExtension: pluginOptions.inlineStylesExtension }),
|
|
381
752
|
buildOptimizerPlugin({
|
|
382
753
|
supportedBrowsers: pluginOptions.supportedBrowsers,
|
|
@@ -384,116 +755,12 @@ function angular(options) {
|
|
|
384
755
|
}),
|
|
385
756
|
routerPlugin(),
|
|
386
757
|
angularFullVersion < 190004 && pendingTasksPlugin(),
|
|
387
|
-
nxFolderPlugin()
|
|
758
|
+
nxFolderPlugin(),
|
|
759
|
+
encapsulationPlugin()
|
|
388
760
|
].filter(Boolean);
|
|
389
|
-
function findIncludes() {
|
|
390
|
-
const workspaceRoot = normalizePath(resolve(pluginOptions.workspaceRoot));
|
|
391
|
-
return globSync([...pluginOptions.include.map((glob) => `${workspaceRoot}${glob}`)], {
|
|
392
|
-
dot: true,
|
|
393
|
-
absolute: true
|
|
394
|
-
});
|
|
395
|
-
}
|
|
396
|
-
function createTsConfigGetter(tsconfigOrGetter) {
|
|
397
|
-
if (typeof tsconfigOrGetter === "function") return tsconfigOrGetter;
|
|
398
|
-
return () => tsconfigOrGetter || "";
|
|
399
|
-
}
|
|
400
|
-
function getTsConfigPath(root, tsconfig, isProd, isTest, isLib) {
|
|
401
|
-
if (tsconfig && isAbsolute(tsconfig)) {
|
|
402
|
-
if (!existsSync(tsconfig)) console.error(`[@analogjs/vite-plugin-angular]: Unable to resolve tsconfig at ${tsconfig}. This causes compilation issues. Check the path or set the "tsconfig" property with an absolute path.`);
|
|
403
|
-
return tsconfig;
|
|
404
|
-
}
|
|
405
|
-
let tsconfigFilePath = "./tsconfig.app.json";
|
|
406
|
-
if (isLib) tsconfigFilePath = isProd ? "./tsconfig.lib.prod.json" : "./tsconfig.lib.json";
|
|
407
|
-
if (isTest) tsconfigFilePath = "./tsconfig.spec.json";
|
|
408
|
-
if (tsconfig) tsconfigFilePath = tsconfig;
|
|
409
|
-
const resolvedPath = resolve(root, tsconfigFilePath);
|
|
410
|
-
if (!existsSync(resolvedPath)) console.error(`[@analogjs/vite-plugin-angular]: Unable to resolve tsconfig at ${resolvedPath}. This causes compilation issues. Check the path or set the "tsconfig" property with an absolute path.`);
|
|
411
|
-
return resolvedPath;
|
|
412
|
-
}
|
|
413
761
|
function resolveTsConfigPath() {
|
|
414
762
|
const tsconfigValue = pluginOptions.tsconfigGetter();
|
|
415
|
-
return getTsConfigPath(tsConfigResolutionContext.root, tsconfigValue, tsConfigResolutionContext.isProd, isTest, tsConfigResolutionContext.isLib);
|
|
416
|
-
}
|
|
417
|
-
/**
|
|
418
|
-
* Perform compilation using Angular's private Compilation API.
|
|
419
|
-
*
|
|
420
|
-
* Key differences from the standard `performCompilation` path:
|
|
421
|
-
* 1. The compilation instance is reused across rebuilds (nullish-coalescing
|
|
422
|
-
* assignment below) so Angular retains prior state and can diff it to
|
|
423
|
-
* produce `templateUpdates` for HMR.
|
|
424
|
-
* 2. `ids` (modified files) are forwarded to both the source-file cache and
|
|
425
|
-
* `angularCompilation.update()` so that incremental re-analysis is
|
|
426
|
-
* scoped to what actually changed.
|
|
427
|
-
* 3. `fileReplacements` are converted and passed into Angular's host via
|
|
428
|
-
* `toAngularCompilationFileReplacements`.
|
|
429
|
-
* 4. `templateUpdates` from the compilation result are mapped back to
|
|
430
|
-
* file-level HMR metadata (`hmrUpdateCode`, `hmrEligible`, `classNames`).
|
|
431
|
-
*/
|
|
432
|
-
async function performAngularCompilation(config, ids) {
|
|
433
|
-
angularCompilation ??= await createAngularCompilation(!!pluginOptions.jit, false);
|
|
434
|
-
const modifiedFiles = ids?.length ? new Set(ids.map((file) => normalizePath(file))) : void 0;
|
|
435
|
-
if (modifiedFiles?.size) sourceFileCache$1.invalidate(modifiedFiles);
|
|
436
|
-
if (modifiedFiles?.size && angularCompilation.update) await angularCompilation.update(modifiedFiles);
|
|
437
|
-
const resolvedTsConfigPath = resolveTsConfigPath();
|
|
438
|
-
const compilationResult = await angularCompilation.initialize(resolvedTsConfigPath, {
|
|
439
|
-
fileReplacements: toAngularCompilationFileReplacements(pluginOptions.fileReplacements, pluginOptions.workspaceRoot),
|
|
440
|
-
modifiedFiles,
|
|
441
|
-
async transformStylesheet(data, containingFile, resourceFile, order, className) {
|
|
442
|
-
if (pluginOptions.liveReload) {
|
|
443
|
-
const filename = createHash("sha256").update(containingFile).update(className).update(String(order)).update(data).digest("hex") + "." + pluginOptions.inlineStylesExtension;
|
|
444
|
-
inlineComponentStyles.set(filename, data);
|
|
445
|
-
return filename;
|
|
446
|
-
}
|
|
447
|
-
const filename = resourceFile ?? containingFile.replace(".ts", `.${options?.inlineStylesExtension}`);
|
|
448
|
-
let stylesheetResult;
|
|
449
|
-
try {
|
|
450
|
-
stylesheetResult = await preprocessCSS(data, `${filename}?direct`, resolvedConfig);
|
|
451
|
-
} catch (e) {
|
|
452
|
-
console.error(`${e}`);
|
|
453
|
-
}
|
|
454
|
-
return stylesheetResult?.code || "";
|
|
455
|
-
},
|
|
456
|
-
processWebWorker(workerFile, containingFile) {
|
|
457
|
-
return "";
|
|
458
|
-
}
|
|
459
|
-
}, (tsCompilerOptions) => {
|
|
460
|
-
if (pluginOptions.liveReload && watchMode) {
|
|
461
|
-
tsCompilerOptions["_enableHmr"] = true;
|
|
462
|
-
tsCompilerOptions["externalRuntimeStyles"] = true;
|
|
463
|
-
tsCompilerOptions["supportTestBed"] = true;
|
|
464
|
-
}
|
|
465
|
-
if (tsCompilerOptions.compilationMode === "partial") {
|
|
466
|
-
tsCompilerOptions["supportTestBed"] = true;
|
|
467
|
-
tsCompilerOptions["supportJitMode"] = true;
|
|
468
|
-
}
|
|
469
|
-
if (!isTest && config.build?.lib) {
|
|
470
|
-
tsCompilerOptions["declaration"] = true;
|
|
471
|
-
tsCompilerOptions["declarationMap"] = watchMode;
|
|
472
|
-
tsCompilerOptions["inlineSources"] = true;
|
|
473
|
-
}
|
|
474
|
-
if (isTest) tsCompilerOptions["supportTestBed"] = true;
|
|
475
|
-
return tsCompilerOptions;
|
|
476
|
-
});
|
|
477
|
-
compilationResult.externalStylesheets?.forEach((value, key) => {
|
|
478
|
-
externalComponentStyles?.set(`${value}.css`, key);
|
|
479
|
-
});
|
|
480
|
-
const diagnostics = await angularCompilation.diagnoseFiles(pluginOptions.disableTypeChecking ? DiagnosticModes.All & ~DiagnosticModes.Semantic : DiagnosticModes.All);
|
|
481
|
-
const errors = diagnostics.errors?.length ? diagnostics.errors : [];
|
|
482
|
-
const warnings = diagnostics.warnings?.length ? diagnostics.warnings : [];
|
|
483
|
-
const templateUpdates = mapTemplateUpdatesToFiles(compilationResult.templateUpdates);
|
|
484
|
-
for (const file of await angularCompilation.emitAffectedFiles()) {
|
|
485
|
-
const normalizedFilename = normalizePath(file.filename);
|
|
486
|
-
const templateUpdate = templateUpdates.get(normalizedFilename);
|
|
487
|
-
if (templateUpdate) classNames.set(normalizedFilename, templateUpdate.className);
|
|
488
|
-
outputFiles.set(normalizedFilename, {
|
|
489
|
-
content: file.contents,
|
|
490
|
-
dependencies: [],
|
|
491
|
-
errors: errors.map((error) => error.text || ""),
|
|
492
|
-
warnings: warnings.map((warning) => warning.text || ""),
|
|
493
|
-
hmrUpdateCode: templateUpdate?.code,
|
|
494
|
-
hmrEligible: !!templateUpdate?.code
|
|
495
|
-
});
|
|
496
|
-
}
|
|
763
|
+
return getTsConfigPath(tsConfigResolutionContext.root, tsconfigValue, tsConfigResolutionContext.isProd, isTest, tsConfigResolutionContext.isLib, pluginOptions.workspaceRoot);
|
|
497
764
|
}
|
|
498
765
|
async function performCompilation(config, ids) {
|
|
499
766
|
let resolve;
|
|
@@ -503,6 +770,12 @@ function angular(options) {
|
|
|
503
770
|
});
|
|
504
771
|
try {
|
|
505
772
|
await previousLock;
|
|
773
|
+
const integrations = await discoverAnalogIntegrations(config);
|
|
774
|
+
pluginOptions.stylePreprocessor = integrations.stylePreprocessor;
|
|
775
|
+
externalizeStylesRequested = integrations.externalizeStyles;
|
|
776
|
+
configureStylesheetRegistry = integrations.configureStylesheetRegistry;
|
|
777
|
+
transformFilter = integrations.transformFilter;
|
|
778
|
+
tsconfigResolver.setIntegrationIncludes(integrations.include);
|
|
506
779
|
await _doPerformCompilation(config, ids);
|
|
507
780
|
} finally {
|
|
508
781
|
resolve();
|
|
@@ -513,54 +786,27 @@ function angular(options) {
|
|
|
513
786
|
* It should not be called concurrently. Use `performCompilation` which wraps this method in a lock to ensure only one compilation runs at a time.
|
|
514
787
|
*/
|
|
515
788
|
async function _doPerformCompilation(config, ids) {
|
|
516
|
-
if (
|
|
517
|
-
await performAngularCompilation(config, ids);
|
|
518
|
-
return;
|
|
519
|
-
}
|
|
789
|
+
if (!jit) styleTransform = (code, filename) => preprocessCSS(code, filename, config);
|
|
520
790
|
const isProd = config.mode === "production";
|
|
521
|
-
|
|
522
|
-
sourceFileCache$1.invalidate(modifiedFiles);
|
|
791
|
+
invalidateSourceFiles(new Set(ids ?? []));
|
|
523
792
|
if (ids?.length) for (const id of ids || []) fileTransformMap.delete(id);
|
|
524
|
-
if (pluginOptions.include.length > 0 && includeCache.length === 0) includeCache = findIncludes();
|
|
525
793
|
const resolvedTsConfigPath = resolveTsConfigPath();
|
|
526
|
-
const
|
|
527
|
-
resolvedTsConfigPath,
|
|
528
|
-
isProd ? "prod" : "dev",
|
|
529
|
-
isTest ? "test" : "app",
|
|
530
|
-
config.build?.lib ? "lib" : "nolib"
|
|
531
|
-
].join("|");
|
|
532
|
-
let cached = tsconfigOptionsCache.get(tsconfigKey);
|
|
533
|
-
if (!cached) {
|
|
534
|
-
const read = compilerCli.readConfiguration(resolvedTsConfigPath, {
|
|
535
|
-
suppressOutputPathCheck: true,
|
|
536
|
-
outDir: void 0,
|
|
537
|
-
sourceMap: false,
|
|
538
|
-
inlineSourceMap: !isProd,
|
|
539
|
-
inlineSources: !isProd,
|
|
540
|
-
declaration: false,
|
|
541
|
-
declarationMap: false,
|
|
542
|
-
allowEmptyCodegenFiles: false,
|
|
543
|
-
annotationsAs: "decorators",
|
|
544
|
-
enableResourceInlining: false,
|
|
545
|
-
noEmitOnError: false,
|
|
546
|
-
mapRoot: void 0,
|
|
547
|
-
sourceRoot: void 0,
|
|
548
|
-
supportTestBed: false,
|
|
549
|
-
supportJitMode: false
|
|
550
|
-
});
|
|
551
|
-
cached = {
|
|
552
|
-
options: read.options,
|
|
553
|
-
rootNames: read.rootNames
|
|
554
|
-
};
|
|
555
|
-
tsconfigOptionsCache.set(tsconfigKey, cached);
|
|
556
|
-
}
|
|
794
|
+
const cached = tsconfigResolver.getCachedTsconfigOptions(resolvedTsConfigPath, config);
|
|
557
795
|
const tsCompilerOptions = { ...cached.options };
|
|
558
796
|
let rootNames = [...cached.rootNames];
|
|
559
|
-
if (
|
|
797
|
+
if (shouldExternalizeStyles()) tsCompilerOptions["externalRuntimeStyles"] = true;
|
|
798
|
+
if (shouldEnableLiveReload()) {
|
|
560
799
|
tsCompilerOptions["_enableHmr"] = true;
|
|
561
|
-
tsCompilerOptions["externalRuntimeStyles"] = true;
|
|
562
800
|
tsCompilerOptions["supportTestBed"] = true;
|
|
563
801
|
}
|
|
802
|
+
debugCompiler("tsCompilerOptions (NgtscProgram path)", {
|
|
803
|
+
liveReload: pluginOptions.liveReload,
|
|
804
|
+
viteHmr: hasViteHmrTransport(),
|
|
805
|
+
externalizeStylesRequested,
|
|
806
|
+
shouldExternalize: shouldExternalizeStyles(),
|
|
807
|
+
externalRuntimeStyles: !!tsCompilerOptions["externalRuntimeStyles"],
|
|
808
|
+
hmrEnabled: !!tsCompilerOptions["_enableHmr"]
|
|
809
|
+
});
|
|
564
810
|
if (tsCompilerOptions["compilationMode"] === "partial") {
|
|
565
811
|
tsCompilerOptions["supportTestBed"] = true;
|
|
566
812
|
tsCompilerOptions["supportJitMode"] = true;
|
|
@@ -572,11 +818,7 @@ function angular(options) {
|
|
|
572
818
|
}
|
|
573
819
|
if (isTest) tsCompilerOptions["supportTestBed"] = true;
|
|
574
820
|
const replacements = pluginOptions.fileReplacements.map((rp) => join(pluginOptions.workspaceRoot, rp.ssr || rp.with));
|
|
575
|
-
rootNames =
|
|
576
|
-
...rootNames,
|
|
577
|
-
...includeCache,
|
|
578
|
-
...replacements
|
|
579
|
-
])];
|
|
821
|
+
rootNames = union(rootNames, tsconfigResolver.ensureIncludeCache(), replacements);
|
|
580
822
|
const hostKey = JSON.stringify(tsCompilerOptions);
|
|
581
823
|
let host;
|
|
582
824
|
if (cachedHost && cachedHostKey === hostKey) host = cachedHost;
|
|
@@ -592,17 +834,19 @@ function angular(options) {
|
|
|
592
834
|
});
|
|
593
835
|
cachedHost = host;
|
|
594
836
|
cachedHostKey = hostKey;
|
|
595
|
-
if (watchMode) augmentHostWithCaching(host,
|
|
837
|
+
if (watchMode) augmentHostWithCaching(host, tsSourceFileCache);
|
|
596
838
|
}
|
|
597
839
|
if (!jit) {
|
|
598
|
-
|
|
599
|
-
|
|
840
|
+
const externalizeStyles = !!tsCompilerOptions["externalRuntimeStyles"];
|
|
841
|
+
stylesheetRegistry = externalizeStyles ? new AnalogStylesheetRegistry() : void 0;
|
|
842
|
+
if (stylesheetRegistry) configureStylesheetRegistry?.(stylesheetRegistry, { workspaceRoot: pluginOptions.workspaceRoot });
|
|
843
|
+
debugStyles("stylesheet registry initialized (NgtscProgram path)", { externalizeStyles });
|
|
600
844
|
augmentHostWithResources(host, styleTransform, {
|
|
601
845
|
inlineStylesExtension: pluginOptions.inlineStylesExtension,
|
|
602
846
|
isProd,
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
847
|
+
stylesheetRegistry,
|
|
848
|
+
sourceFileCache: sourceFileCache$1,
|
|
849
|
+
stylePreprocessor: pluginOptions.stylePreprocessor
|
|
606
850
|
});
|
|
607
851
|
}
|
|
608
852
|
/**
|
|
@@ -631,9 +875,19 @@ function angular(options) {
|
|
|
631
875
|
const writeFileCallback = (_filename, content, _a, _b, sourceFiles) => {
|
|
632
876
|
if (!sourceFiles?.length) return;
|
|
633
877
|
const filename = normalizePath(sourceFiles[0].fileName);
|
|
634
|
-
if (filename.includes("ngtypecheck.ts") || filename.includes(".d.")) return;
|
|
878
|
+
if (filename.includes("ngtypecheck.ts") || filename.includes(".d.") || _filename.endsWith(".d.ts") || _filename.endsWith(".d.mts") || _filename.endsWith(".d.cts")) return;
|
|
879
|
+
if (/\.[cm]?js\.map$/.test(_filename)) {
|
|
880
|
+
const existing = outputFiles.get(filename);
|
|
881
|
+
outputFiles.set(filename, {
|
|
882
|
+
...existing ?? { dependencies: [] },
|
|
883
|
+
map: content
|
|
884
|
+
});
|
|
885
|
+
return;
|
|
886
|
+
}
|
|
635
887
|
const metadata = watchMode ? fileMetadata(filename) : {};
|
|
888
|
+
const existing = outputFiles.get(filename);
|
|
636
889
|
outputFiles.set(filename, {
|
|
890
|
+
...existing ?? {},
|
|
637
891
|
content,
|
|
638
892
|
dependencies: [],
|
|
639
893
|
errors: metadata.errors,
|
|
@@ -641,13 +895,27 @@ function angular(options) {
|
|
|
641
895
|
hmrUpdateCode: metadata.hmrUpdateCode,
|
|
642
896
|
hmrEligible: metadata.hmrEligible
|
|
643
897
|
});
|
|
898
|
+
debugEmitV("registered ngtsc output", {
|
|
899
|
+
filename,
|
|
900
|
+
...describeEmitMarkers(content),
|
|
901
|
+
errorCount: metadata.errors?.length ?? 0,
|
|
902
|
+
warningCount: metadata.warnings?.length ?? 0,
|
|
903
|
+
hmrEligible: !!metadata.hmrEligible,
|
|
904
|
+
knownOutputCount: outputFiles.size
|
|
905
|
+
});
|
|
644
906
|
};
|
|
645
907
|
const writeOutputFile = (id) => {
|
|
646
908
|
const sourceFile = builder.getSourceFile(id);
|
|
647
909
|
if (!sourceFile) return;
|
|
648
910
|
let content = "";
|
|
911
|
+
let map;
|
|
912
|
+
let mapFilename;
|
|
649
913
|
builder.emit(sourceFile, (filename, data) => {
|
|
650
914
|
if (/\.[cm]?js$/.test(filename)) content = data;
|
|
915
|
+
if (/\.[cm]?js\.map$/.test(filename)) {
|
|
916
|
+
map = data;
|
|
917
|
+
mapFilename = filename;
|
|
918
|
+
}
|
|
651
919
|
if (!watchMode && !isTest && /\.d\.ts/.test(filename) && !filename.includes(".ngtypecheck.")) {
|
|
652
920
|
const declarationPath = resolve(config.root, config.build.outDir, relative(config.root, filename)).replace("/src/", "/");
|
|
653
921
|
const declarationFileDir = declarationPath.replace(basename(filename), "").replace("/src/", "/");
|
|
@@ -659,6 +927,7 @@ function angular(options) {
|
|
|
659
927
|
}
|
|
660
928
|
}, void 0, void 0, transformers);
|
|
661
929
|
writeFileCallback(id, content, false, void 0, [sourceFile]);
|
|
930
|
+
if (map !== void 0 && mapFilename !== void 0) writeFileCallback(mapFilename, map, false, void 0, [sourceFile]);
|
|
662
931
|
if (angularCompiler) angularCompiler.incrementalCompilation.recordSuccessfulEmit(sourceFile);
|
|
663
932
|
};
|
|
664
933
|
if (watchMode) {
|
|
@@ -681,54 +950,225 @@ function createFsWatcherCacheInvalidator(invalidateFsCaches, invalidateTsconfigC
|
|
|
681
950
|
};
|
|
682
951
|
}
|
|
683
952
|
/**
|
|
684
|
-
*
|
|
685
|
-
*
|
|
953
|
+
* Returns every live Vite module that can legitimately represent a changed
|
|
954
|
+
* Angular resource file.
|
|
686
955
|
*
|
|
687
|
-
*
|
|
688
|
-
*
|
|
689
|
-
*
|
|
690
|
-
*
|
|
691
|
-
*
|
|
692
|
-
*
|
|
693
|
-
*
|
|
956
|
+
* For normal files, `getModulesByFile()` is enough. For Angular component
|
|
957
|
+
* stylesheets, it is not: the browser often holds virtual hashed requests
|
|
958
|
+
* (`/abc123.css?direct&ngcomp=...` and `/abc123.css?ngcomp=...`) that are no
|
|
959
|
+
* longer discoverable from the original source path alone. We therefore merge:
|
|
960
|
+
* - watcher event modules
|
|
961
|
+
* - module-graph modules by source file
|
|
962
|
+
* - registry-tracked live request ids resolved back through the module graph
|
|
694
963
|
*/
|
|
695
|
-
function
|
|
696
|
-
const
|
|
697
|
-
|
|
698
|
-
|
|
964
|
+
async function getModulesForChangedFile(server, file, eventModules = [], stylesheetRegistry) {
|
|
965
|
+
const normalizedFile = normalizePath(file.split("?")[0]);
|
|
966
|
+
const modules = /* @__PURE__ */ new Map();
|
|
967
|
+
for (const mod of eventModules) if (mod.id) modules.set(mod.id, mod);
|
|
968
|
+
server.moduleGraph.getModulesByFile(normalizedFile)?.forEach((mod) => {
|
|
969
|
+
if (mod.id) modules.set(mod.id, mod);
|
|
970
|
+
});
|
|
971
|
+
const stylesheetRequestIds = stylesheetRegistry?.getRequestIdsForSource(normalizedFile) ?? [];
|
|
972
|
+
const requestIdHits = [];
|
|
973
|
+
for (const requestId of stylesheetRequestIds) {
|
|
974
|
+
const candidates = [requestId, requestId.startsWith("/") ? requestId : `/${requestId}`];
|
|
975
|
+
for (const candidate of candidates) {
|
|
976
|
+
const mod = await server.moduleGraph.getModuleByUrl(candidate) ?? server.moduleGraph.getModuleById(candidate);
|
|
977
|
+
requestIdHits.push({
|
|
978
|
+
requestId,
|
|
979
|
+
candidate,
|
|
980
|
+
via: mod?.url === candidate ? "url" : "id",
|
|
981
|
+
moduleId: mod?.id
|
|
982
|
+
});
|
|
983
|
+
if (mod?.id) modules.set(mod.id, mod);
|
|
984
|
+
}
|
|
985
|
+
}
|
|
986
|
+
debugHmrV("getModulesForChangedFile registry lookup", {
|
|
987
|
+
file: normalizedFile,
|
|
988
|
+
stylesheetRequestIds,
|
|
989
|
+
requestIdHits,
|
|
990
|
+
resolvedModuleIds: [...modules.keys()]
|
|
699
991
|
});
|
|
700
|
-
return
|
|
992
|
+
return [...modules.values()];
|
|
701
993
|
}
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
const
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
994
|
+
function isModuleForChangedResource(mod, changedFile, stylesheetRegistry) {
|
|
995
|
+
const normalizedChangedFile = normalizePath(changedFile.split("?")[0]);
|
|
996
|
+
if (normalizePath((mod.file ?? "").split("?")[0]) === normalizedChangedFile) return true;
|
|
997
|
+
if (!mod.id) return false;
|
|
998
|
+
const requestPath = getFilenameFromPath(mod.id);
|
|
999
|
+
return normalizePath((stylesheetRegistry?.resolveExternalSource(requestPath) ?? stylesheetRegistry?.resolveExternalSource(requestPath.replace(/^\//, "")) ?? stylesheetRegistry?.getServedSourcePath(requestPath) ?? stylesheetRegistry?.getServedSourcePath(requestPath.replace(/^\//, "")) ?? "").split("?")[0]) === normalizedChangedFile;
|
|
1000
|
+
}
|
|
1001
|
+
function diagnoseComponentStylesheetPipeline(changedFile, directModule, stylesheetRegistry, wrapperModules, stylePreprocessor) {
|
|
1002
|
+
const normalizedFile = normalizePath(changedFile.split("?")[0]);
|
|
1003
|
+
const sourceExists = existsSync(normalizedFile);
|
|
1004
|
+
const sourceCode = sourceExists ? readFileSync(normalizedFile, "utf-8") : void 0;
|
|
1005
|
+
const directRequestPath = directModule.id ? getFilenameFromPath(directModule.id) : void 0;
|
|
1006
|
+
const sourcePath = directRequestPath ? stylesheetRegistry?.resolveExternalSource(directRequestPath) ?? stylesheetRegistry?.resolveExternalSource(directRequestPath.replace(/^\//, "")) ?? stylesheetRegistry?.getServedSourcePath(directRequestPath) ?? stylesheetRegistry?.getServedSourcePath(directRequestPath.replace(/^\//, "")) : normalizedFile;
|
|
1007
|
+
const registryCode = directRequestPath ? stylesheetRegistry?.getServedContent(directRequestPath) : void 0;
|
|
1008
|
+
const trackedRequestIds = stylesheetRegistry?.getRequestIdsForSource(sourcePath ?? "") ?? [];
|
|
1009
|
+
const dependencies = stylesheetRegistry?.getDependenciesForSource(sourcePath ?? "") ?? [];
|
|
1010
|
+
const diagnostics = stylesheetRegistry?.getDiagnosticsForSource(sourcePath ?? "") ?? [];
|
|
1011
|
+
const tags = stylesheetRegistry?.getTagsForSource(sourcePath ?? "") ?? [];
|
|
1012
|
+
const anomalies = [];
|
|
1013
|
+
const hints = [];
|
|
1014
|
+
if (!sourceExists) {
|
|
1015
|
+
anomalies.push("source_file_missing");
|
|
1016
|
+
hints.push("The stylesheet watcher fired for a file that no longer exists on disk.");
|
|
1017
|
+
}
|
|
1018
|
+
if (!registryCode) {
|
|
1019
|
+
anomalies.push("registry_content_missing");
|
|
1020
|
+
hints.push("The stylesheet registry has no served content for the direct module request path.");
|
|
1021
|
+
}
|
|
1022
|
+
if (sourceCode && registryCode) {
|
|
1023
|
+
let expectedRegistryCode = preprocessStylesheet(sourceCode, normalizedFile, stylePreprocessor);
|
|
1024
|
+
expectedRegistryCode = rewriteRelativeCssImports(expectedRegistryCode, normalizedFile);
|
|
1025
|
+
if (describeStylesheetContent(expectedRegistryCode).digest !== describeStylesheetContent(registryCode).digest) {
|
|
1026
|
+
anomalies.push("source_registry_mismatch");
|
|
1027
|
+
hints.push("The source file changed, but the served stylesheet content in the registry is still stale.");
|
|
1028
|
+
}
|
|
1029
|
+
}
|
|
1030
|
+
if (trackedRequestIds.length === 0) {
|
|
1031
|
+
anomalies.push("no_tracked_requests");
|
|
1032
|
+
hints.push("No live stylesheet requests are tracked for this source file, so HMR has no browser-facing target.");
|
|
1033
|
+
}
|
|
1034
|
+
if (trackedRequestIds.some((id) => id.includes("?ngcomp=")) && wrapperModules.length === 0) {
|
|
1035
|
+
anomalies.push("tracked_wrapper_missing_from_module_graph");
|
|
1036
|
+
hints.push("A wrapper request id is known, but Vite did not expose a live wrapper module during this HMR pass.");
|
|
1037
|
+
}
|
|
1038
|
+
if (trackedRequestIds.every((id) => !id.includes("?ngcomp=")) && wrapperModules.length === 0) {
|
|
1039
|
+
anomalies.push("wrapper_not_yet_tracked");
|
|
1040
|
+
hints.push("Only direct stylesheet requests were tracked during this HMR pass; the wrapper request may be appearing too late.");
|
|
1041
|
+
}
|
|
1042
|
+
return {
|
|
1043
|
+
file: changedFile,
|
|
1044
|
+
sourcePath,
|
|
1045
|
+
source: sourceCode ? describeStylesheetContent(rewriteRelativeCssImports(preprocessStylesheet(sourceCode, normalizedFile, stylePreprocessor), normalizedFile)) : void 0,
|
|
1046
|
+
registry: registryCode ? describeStylesheetContent(registryCode) : void 0,
|
|
1047
|
+
dependencies,
|
|
1048
|
+
diagnostics,
|
|
1049
|
+
tags,
|
|
1050
|
+
directModuleId: directModule.id,
|
|
1051
|
+
directModuleUrl: directModule.url,
|
|
1052
|
+
trackedRequestIds,
|
|
1053
|
+
wrapperCount: wrapperModules.length,
|
|
1054
|
+
anomalies,
|
|
1055
|
+
hints
|
|
1056
|
+
};
|
|
1057
|
+
}
|
|
1058
|
+
async function findComponentStylesheetWrapperModules(server, changedFile, directModule, fileModules, stylesheetRegistry) {
|
|
1059
|
+
const wrapperModules = /* @__PURE__ */ new Map();
|
|
1060
|
+
for (const mod of fileModules) if (mod.id && mod.type === "js" && isComponentStyleSheet(mod.id) && isModuleForChangedResource(mod, changedFile, stylesheetRegistry)) wrapperModules.set(mod.id, mod);
|
|
1061
|
+
const directRequestIds = /* @__PURE__ */ new Set();
|
|
1062
|
+
if (directModule.id) directRequestIds.add(directModule.id);
|
|
1063
|
+
if (directModule.url) directRequestIds.add(directModule.url);
|
|
1064
|
+
const requestPath = directModule.id ? getFilenameFromPath(directModule.id) : void 0;
|
|
1065
|
+
const sourcePath = requestPath ? stylesheetRegistry?.resolveExternalSource(requestPath) ?? stylesheetRegistry?.resolveExternalSource(requestPath.replace(/^\//, "")) ?? stylesheetRegistry?.getServedSourcePath(requestPath) ?? stylesheetRegistry?.getServedSourcePath(requestPath.replace(/^\//, "")) : void 0;
|
|
1066
|
+
for (const requestId of stylesheetRegistry?.getRequestIdsForSource(sourcePath ?? "") ?? []) if (requestId.includes("?ngcomp=")) directRequestIds.add(requestId);
|
|
1067
|
+
const candidateWrapperIds = [...directRequestIds].filter((id) => id.includes("?direct&ngcomp=")).map((id) => id.replace("?direct&ngcomp=", "?ngcomp="));
|
|
1068
|
+
const lookupHits = [];
|
|
1069
|
+
for (const candidate of candidateWrapperIds) {
|
|
1070
|
+
const mod = await server.moduleGraph.getModuleByUrl(candidate) ?? server.moduleGraph.getModuleById(candidate);
|
|
1071
|
+
lookupHits.push({
|
|
1072
|
+
candidate,
|
|
1073
|
+
via: mod?.url === candidate ? "url" : mod ? "id" : void 0,
|
|
1074
|
+
moduleId: mod?.id,
|
|
1075
|
+
moduleType: mod?.type
|
|
720
1076
|
});
|
|
1077
|
+
if (mod?.id && mod.type === "js" && isComponentStyleSheet(mod.id) && isModuleForChangedResource(mod, changedFile, stylesheetRegistry)) wrapperModules.set(mod.id, mod);
|
|
1078
|
+
}
|
|
1079
|
+
debugHmrV("component stylesheet wrapper lookup", {
|
|
1080
|
+
file: changedFile,
|
|
1081
|
+
sourcePath,
|
|
1082
|
+
directModuleId: directModule.id,
|
|
1083
|
+
directModuleUrl: directModule.url,
|
|
1084
|
+
candidateWrapperIds,
|
|
1085
|
+
lookupHits
|
|
721
1086
|
});
|
|
722
|
-
|
|
1087
|
+
if (wrapperModules.size === 0) debugHmrV("component stylesheet wrapper lookup empty", {
|
|
1088
|
+
file: changedFile,
|
|
1089
|
+
sourcePath,
|
|
1090
|
+
directModuleId: directModule.id,
|
|
1091
|
+
directModuleUrl: directModule.url,
|
|
1092
|
+
candidateWrapperIds
|
|
1093
|
+
});
|
|
1094
|
+
return [...wrapperModules.values()];
|
|
723
1095
|
}
|
|
724
1096
|
function sendHMRComponentUpdate(server, id) {
|
|
1097
|
+
debugHmrV("ws send: angular component update", {
|
|
1098
|
+
id,
|
|
1099
|
+
timestamp: Date.now()
|
|
1100
|
+
});
|
|
725
1101
|
server.ws.send("angular:component-update", {
|
|
726
1102
|
id: encodeURIComponent(id),
|
|
727
1103
|
timestamp: Date.now()
|
|
728
1104
|
});
|
|
729
1105
|
classNames.delete(id);
|
|
730
1106
|
}
|
|
731
|
-
function
|
|
1107
|
+
function sendCssUpdate(server, update) {
|
|
1108
|
+
const timestamp = Date.now();
|
|
1109
|
+
debugHmrV("ws send: css-update", {
|
|
1110
|
+
...update,
|
|
1111
|
+
timestamp
|
|
1112
|
+
});
|
|
1113
|
+
server.ws.send({
|
|
1114
|
+
type: "update",
|
|
1115
|
+
updates: [{
|
|
1116
|
+
type: "css-update",
|
|
1117
|
+
timestamp,
|
|
1118
|
+
path: update.path,
|
|
1119
|
+
acceptedPath: update.acceptedPath
|
|
1120
|
+
}]
|
|
1121
|
+
});
|
|
1122
|
+
}
|
|
1123
|
+
function sendFullReload(server, details) {
|
|
1124
|
+
debugHmrV("ws send: full-reload", details);
|
|
1125
|
+
server.ws.send("analog:debug-full-reload", details);
|
|
1126
|
+
server.ws.send({ type: "full-reload" });
|
|
1127
|
+
}
|
|
1128
|
+
function logComponentStylesheetHmrOutcome(details) {
|
|
1129
|
+
const pitfalls = [];
|
|
1130
|
+
const rejectedPreferredPaths = [];
|
|
1131
|
+
const hints = [];
|
|
1132
|
+
if (details.encapsulation === "shadow") {
|
|
1133
|
+
pitfalls.push("shadow-encapsulation");
|
|
1134
|
+
rejectedPreferredPaths.push("css-update");
|
|
1135
|
+
hints.push("Shadow DOM styles cannot rely on Vite CSS patching because Angular applies them inside a shadow root.");
|
|
1136
|
+
}
|
|
1137
|
+
if (details.diagnosis.anomalies.includes("wrapper_not_yet_tracked")) {
|
|
1138
|
+
pitfalls.push("wrapper-not-yet-tracked");
|
|
1139
|
+
rejectedPreferredPaths.push("css-update");
|
|
1140
|
+
hints.push("The direct stylesheet module exists, but the browser-visible Angular wrapper module was not available in the live graph during this HMR pass.");
|
|
1141
|
+
}
|
|
1142
|
+
if (details.diagnosis.anomalies.includes("tracked_wrapper_missing_from_module_graph")) {
|
|
1143
|
+
pitfalls.push("tracked-wrapper-missing-from-module-graph");
|
|
1144
|
+
rejectedPreferredPaths.push("css-update");
|
|
1145
|
+
hints.push("A wrapper request id is known, but Vite could not resolve a live wrapper module for targeted CSS HMR.");
|
|
1146
|
+
}
|
|
1147
|
+
debugHmrV("component stylesheet hmr outcome", {
|
|
1148
|
+
file: details.file,
|
|
1149
|
+
outcome: details.outcome,
|
|
1150
|
+
encapsulation: details.encapsulation,
|
|
1151
|
+
directModuleId: details.directModuleId,
|
|
1152
|
+
wrapperIds: details.wrapperIds ?? [],
|
|
1153
|
+
preferredPath: details.encapsulation === "shadow" ? "full-reload" : "css-update",
|
|
1154
|
+
rejectedPreferredPaths: [...new Set(rejectedPreferredPaths)],
|
|
1155
|
+
pitfalls: [...new Set(pitfalls)],
|
|
1156
|
+
anomalies: details.diagnosis.anomalies,
|
|
1157
|
+
hints: [...new Set([...details.diagnosis.hints, ...hints])]
|
|
1158
|
+
});
|
|
1159
|
+
}
|
|
1160
|
+
function findTemplateOwnerModules(server, resourceFile) {
|
|
1161
|
+
const candidateTsFiles = [normalizePath(resourceFile.split("?")[0]).replace(/\.(html|htm)$/i, ".ts")];
|
|
1162
|
+
const modules = /* @__PURE__ */ new Map();
|
|
1163
|
+
for (const candidate of candidateTsFiles) server.moduleGraph.getModulesByFile(candidate)?.forEach((mod) => {
|
|
1164
|
+
if (mod.id) modules.set(mod.id, mod);
|
|
1165
|
+
});
|
|
1166
|
+
return [...modules.values()];
|
|
1167
|
+
}
|
|
1168
|
+
/**
|
|
1169
|
+
* @internal
|
|
1170
|
+
*/
|
|
1171
|
+
function getFileMetadata(program, angularCompiler, hmrEnabled, disableTypeChecking) {
|
|
732
1172
|
const ts = require("typescript");
|
|
733
1173
|
return (file) => {
|
|
734
1174
|
const sourceFile = program.getSourceFile(file);
|
|
@@ -738,12 +1178,17 @@ function getFileMetadata(program, angularCompiler, liveReload, disableTypeChecki
|
|
|
738
1178
|
const warnings = diagnostics.filter((d) => d.category === ts.DiagnosticCategory?.Warning).map((d) => d.messageText);
|
|
739
1179
|
let hmrUpdateCode = void 0;
|
|
740
1180
|
let hmrEligible = false;
|
|
741
|
-
if (
|
|
1181
|
+
if (hmrEnabled) {
|
|
742
1182
|
for (const node of sourceFile.statements) if (ts.isClassDeclaration(node) && node.name != null) {
|
|
743
1183
|
hmrUpdateCode = angularCompiler?.emitHmrUpdateModule(node);
|
|
744
1184
|
if (hmrUpdateCode) {
|
|
745
|
-
|
|
1185
|
+
const className = node.name.getText();
|
|
1186
|
+
classNames.set(file, className);
|
|
746
1187
|
hmrEligible = true;
|
|
1188
|
+
debugHmr("NgtscProgram emitHmrUpdateModule", {
|
|
1189
|
+
file,
|
|
1190
|
+
className
|
|
1191
|
+
});
|
|
747
1192
|
}
|
|
748
1193
|
}
|
|
749
1194
|
}
|
|
@@ -773,40 +1218,18 @@ function markModuleSelfAccepting(mod) {
|
|
|
773
1218
|
isSelfAccepting: true
|
|
774
1219
|
};
|
|
775
1220
|
}
|
|
776
|
-
function isComponentStyleSheet(id) {
|
|
777
|
-
return id.includes("ngcomp=");
|
|
778
|
-
}
|
|
779
|
-
function getComponentStyleSheetMeta(id) {
|
|
780
|
-
const params = new URL(id, "http://localhost").searchParams;
|
|
781
|
-
return {
|
|
782
|
-
componentId: params.get("ngcomp"),
|
|
783
|
-
encapsulation: {
|
|
784
|
-
"0": "emulated",
|
|
785
|
-
"2": "none",
|
|
786
|
-
"3": "shadow"
|
|
787
|
-
}[params.get("e")]
|
|
788
|
-
};
|
|
789
|
-
}
|
|
790
1221
|
/**
|
|
791
1222
|
* Removes leading / and query string from a url path
|
|
792
1223
|
* e.g. /foo.scss?direct&ngcomp=ng-c3153525609&e=0 returns foo.scss
|
|
793
1224
|
* @param id
|
|
794
1225
|
*/
|
|
795
1226
|
function getFilenameFromPath(id) {
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
function isTestWatchMode(args = process.argv) {
|
|
803
|
-
if (args.find((arg) => arg.includes("--run"))) return false;
|
|
804
|
-
if (args.find((arg) => arg.includes("--no-run"))) return true;
|
|
805
|
-
const hasWatch = args.find((arg) => arg.includes("watch"));
|
|
806
|
-
if (hasWatch && ["false", "no"].some((neg) => hasWatch.includes(neg))) return false;
|
|
807
|
-
const watchArg = args[args.findIndex((arg) => arg.includes("watch")) + 1];
|
|
808
|
-
if (watchArg && watchArg === "false") return false;
|
|
809
|
-
return true;
|
|
1227
|
+
try {
|
|
1228
|
+
return new URL(id, "http://localhost").pathname.replace(/^\//, "");
|
|
1229
|
+
} catch {
|
|
1230
|
+
const queryIndex = id.indexOf("?");
|
|
1231
|
+
return (queryIndex >= 0 ? id.slice(0, queryIndex) : id).replace(/^\//, "");
|
|
1232
|
+
}
|
|
810
1233
|
}
|
|
811
1234
|
//#endregion
|
|
812
1235
|
export { angular };
|