@analogjs/vite-plugin-angular 3.0.0-alpha.9 → 3.0.0-alpha.90
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 +774 -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 +547 -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 +433 -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,37 @@ 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",
|
|
116
189
|
async config(config, { command }) {
|
|
190
|
+
activateDeferredDebug(command);
|
|
117
191
|
watchMode = command === "serve";
|
|
118
|
-
isProd = config.mode
|
|
192
|
+
isProd = isProdMode(config.mode);
|
|
119
193
|
tsConfigResolutionContext = {
|
|
120
194
|
root: config.root || ".",
|
|
121
195
|
isProd,
|
|
122
196
|
isLib: !!config?.build?.lib
|
|
123
197
|
};
|
|
124
198
|
const preliminaryTsConfigPath = resolveTsConfigPath();
|
|
125
|
-
const esbuild =
|
|
126
|
-
const oxc =
|
|
199
|
+
const esbuild = config.esbuild ?? false;
|
|
200
|
+
const oxc = config.oxc ?? false;
|
|
127
201
|
const defineOptions = {
|
|
128
202
|
ngJitMode: "false",
|
|
129
203
|
ngI18nClosureMode: "false",
|
|
@@ -138,7 +212,7 @@ function angular(options) {
|
|
|
138
212
|
advancedOptimizations: isProd,
|
|
139
213
|
jit,
|
|
140
214
|
incremental: watchMode
|
|
141
|
-
})] };
|
|
215
|
+
}, isTest, !isAstroIntegration)] };
|
|
142
216
|
const esbuildOptions = {
|
|
143
217
|
plugins: [createCompilerPlugin({
|
|
144
218
|
tsconfig: preliminaryTsConfigPath,
|
|
@@ -152,18 +226,24 @@ function angular(options) {
|
|
|
152
226
|
return {
|
|
153
227
|
[jsTransformConfigKey]: jsTransformConfigValue,
|
|
154
228
|
optimizeDeps: {
|
|
155
|
-
include: [
|
|
229
|
+
include: [
|
|
230
|
+
"rxjs/operators",
|
|
231
|
+
"rxjs",
|
|
232
|
+
"tslib"
|
|
233
|
+
],
|
|
156
234
|
exclude: ["@angular/platform-server"],
|
|
157
235
|
...useRolldown ? { rolldownOptions } : { esbuildOptions }
|
|
158
|
-
}
|
|
159
|
-
resolve: { conditions: ["style", ...config.resolve?.conditions || defaultClientConditions] }
|
|
236
|
+
}
|
|
160
237
|
};
|
|
161
238
|
},
|
|
162
239
|
configResolved(config) {
|
|
163
240
|
resolvedConfig = config;
|
|
164
|
-
if (
|
|
165
|
-
|
|
166
|
-
|
|
241
|
+
if (config.logger?.warnOnce) {
|
|
242
|
+
const originalWarnOnce = config.logger.warnOnce;
|
|
243
|
+
config.logger.warnOnce = (msg, options) => {
|
|
244
|
+
if (typeof msg === "string" && msg.includes("Sourcemap") && msg.includes("node_modules")) return;
|
|
245
|
+
originalWarnOnce(msg, options);
|
|
246
|
+
};
|
|
167
247
|
}
|
|
168
248
|
if (!jit) styleTransform = (code, filename) => preprocessCSS(code, filename, config);
|
|
169
249
|
if (isTest) testWatchMode = !(config.server.watch === null) || config.test?.watch === true || testWatchMode;
|
|
@@ -172,30 +252,90 @@ function angular(options) {
|
|
|
172
252
|
viteServer = server;
|
|
173
253
|
const invalidateCompilationOnFsChange = createFsWatcherCacheInvalidator(invalidateFsCaches, invalidateTsconfigCaches, () => performCompilation(resolvedConfig));
|
|
174
254
|
server.watcher.on("add", invalidateCompilationOnFsChange);
|
|
175
|
-
server.watcher.on("unlink",
|
|
255
|
+
server.watcher.on("unlink", (file) => {
|
|
256
|
+
const id = normalizePath(file);
|
|
257
|
+
outputFiles.delete(id);
|
|
258
|
+
tsSourceFileCache.delete(id);
|
|
259
|
+
sourceFileCache$1.invalidate(new Set([id]));
|
|
260
|
+
evictDeletedFileMetadata(file, {
|
|
261
|
+
classNamesMap: classNames,
|
|
262
|
+
fileTransformMap
|
|
263
|
+
});
|
|
264
|
+
return invalidateCompilationOnFsChange();
|
|
265
|
+
});
|
|
176
266
|
server.watcher.on("change", (file) => {
|
|
177
267
|
if (file.includes("tsconfig")) invalidateTsconfigCaches();
|
|
178
268
|
});
|
|
179
269
|
},
|
|
180
270
|
async buildStart() {
|
|
181
271
|
if (!isVitestVscode) {
|
|
182
|
-
|
|
272
|
+
pendingCompilation = performCompilation(this.environment?.config ?? resolvedConfig);
|
|
273
|
+
await pendingCompilation;
|
|
183
274
|
pendingCompilation = null;
|
|
184
275
|
initialCompilation = true;
|
|
185
276
|
}
|
|
186
277
|
},
|
|
278
|
+
buildEnd() {
|
|
279
|
+
if (watchMode) return;
|
|
280
|
+
nextProgram = void 0;
|
|
281
|
+
cachedHost = void 0;
|
|
282
|
+
cachedHostKey = void 0;
|
|
283
|
+
outputFile = void 0;
|
|
284
|
+
outputFiles.clear();
|
|
285
|
+
fileTransformMap.clear();
|
|
286
|
+
tsSourceFileCache.clear();
|
|
287
|
+
sourceFileCache$1.clear();
|
|
288
|
+
sourceFileCache$1.modifiedFiles.clear();
|
|
289
|
+
sourceFileCache$1.babelFileCache?.clear();
|
|
290
|
+
sourceFileCache$1.typeScriptFileCache?.clear();
|
|
291
|
+
sourceFileCache$1.referencedFiles = void 0;
|
|
292
|
+
tsconfigResolver.invalidateAll();
|
|
293
|
+
releaseCssPreprocessorWorkers();
|
|
294
|
+
},
|
|
187
295
|
async handleHotUpdate(ctx) {
|
|
296
|
+
if (isIgnoredHmrFile(ctx.file)) {
|
|
297
|
+
debugHmr("ignored file change", { file: ctx.file });
|
|
298
|
+
return [];
|
|
299
|
+
}
|
|
188
300
|
if (TS_EXT_REGEX.test(ctx.file)) {
|
|
189
301
|
const [fileId] = ctx.file.split("?");
|
|
302
|
+
debugHmr("TS file changed", {
|
|
303
|
+
file: ctx.file,
|
|
304
|
+
fileId
|
|
305
|
+
});
|
|
190
306
|
pendingCompilation = performCompilation(resolvedConfig, [fileId]);
|
|
191
307
|
let result;
|
|
192
|
-
if (
|
|
308
|
+
if (shouldEnableLiveReload()) {
|
|
193
309
|
await pendingCompilation;
|
|
194
310
|
pendingCompilation = null;
|
|
195
311
|
result = fileEmitter(fileId);
|
|
312
|
+
debugHmr("TS file emitted", {
|
|
313
|
+
fileId,
|
|
314
|
+
hmrEligible: !!result?.hmrEligible,
|
|
315
|
+
hasClassName: !!classNames.get(fileId)
|
|
316
|
+
});
|
|
317
|
+
debugHmrV("ts hmr evaluation", {
|
|
318
|
+
file: ctx.file,
|
|
319
|
+
fileId,
|
|
320
|
+
hasResult: !!result,
|
|
321
|
+
hmrEligible: !!result?.hmrEligible,
|
|
322
|
+
hasClassName: !!classNames.get(fileId),
|
|
323
|
+
className: classNames.get(fileId),
|
|
324
|
+
updateCode: result?.hmrUpdateCode ? describeStylesheetContent(result.hmrUpdateCode) : void 0,
|
|
325
|
+
errors: result?.errors?.length ?? 0,
|
|
326
|
+
warnings: result?.warnings?.length ?? 0,
|
|
327
|
+
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."
|
|
328
|
+
});
|
|
196
329
|
}
|
|
197
|
-
if (
|
|
330
|
+
if (shouldEnableLiveReload() && result?.hmrEligible && classNames.get(fileId)) {
|
|
198
331
|
const relativeFileId = `${normalizePath(relative(process.cwd(), fileId))}@${classNames.get(fileId)}`;
|
|
332
|
+
debugHmr("sending component update", { relativeFileId });
|
|
333
|
+
debugHmrV("ts hmr component update payload", {
|
|
334
|
+
file: ctx.file,
|
|
335
|
+
fileId,
|
|
336
|
+
relativeFileId,
|
|
337
|
+
className: classNames.get(fileId)
|
|
338
|
+
});
|
|
199
339
|
sendHMRComponentUpdate(ctx.server, relativeFileId);
|
|
200
340
|
return ctx.modules.map((mod) => {
|
|
201
341
|
if (mod.id === ctx.file) return markModuleSelfAccepting(mod);
|
|
@@ -204,79 +344,260 @@ function angular(options) {
|
|
|
204
344
|
}
|
|
205
345
|
}
|
|
206
346
|
if (/\.(html|htm|css|less|sass|scss)$/.test(ctx.file)) {
|
|
347
|
+
debugHmr("resource file changed", { file: ctx.file });
|
|
207
348
|
fileTransformMap.delete(ctx.file.split("?")[0]);
|
|
349
|
+
const fileModules = await getModulesForChangedFile(ctx.server, ctx.file, ctx.modules, stylesheetRegistry);
|
|
208
350
|
/**
|
|
209
351
|
* Check to see if this was a direct request
|
|
210
352
|
* for an external resource (styles, html).
|
|
211
353
|
*/
|
|
212
|
-
const isDirect =
|
|
213
|
-
const isInline =
|
|
354
|
+
const isDirect = fileModules.find((mod) => !!mod.id && mod.id.includes("?direct") && isModuleForChangedResource(mod, ctx.file, stylesheetRegistry));
|
|
355
|
+
const isInline = fileModules.find((mod) => !!mod.id && mod.id.includes("?inline") && isModuleForChangedResource(mod, ctx.file, stylesheetRegistry));
|
|
356
|
+
debugHmrV("resource direct/inline detection", {
|
|
357
|
+
file: ctx.file,
|
|
358
|
+
hasDirect: !!isDirect,
|
|
359
|
+
directId: isDirect?.id,
|
|
360
|
+
hasInline: !!isInline,
|
|
361
|
+
inlineId: isInline?.id
|
|
362
|
+
});
|
|
214
363
|
if (isDirect || isInline) {
|
|
215
|
-
if (
|
|
216
|
-
|
|
364
|
+
if (shouldExternalizeStyles() && isDirect?.id && isDirect.file) {
|
|
365
|
+
const isComponentStyle = isDirect.type === "css" && isComponentStyleSheet(isDirect.id);
|
|
366
|
+
debugHmrV("resource direct branch", {
|
|
367
|
+
file: ctx.file,
|
|
368
|
+
directId: isDirect.id,
|
|
369
|
+
directType: isDirect.type,
|
|
370
|
+
shouldExternalize: shouldExternalizeStyles(),
|
|
371
|
+
isComponentStyle
|
|
372
|
+
});
|
|
373
|
+
if (isComponentStyle) {
|
|
217
374
|
const { encapsulation } = getComponentStyleSheetMeta(isDirect.id);
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
375
|
+
const wrapperModules = await findComponentStylesheetWrapperModules(ctx.server, ctx.file, isDirect, fileModules, stylesheetRegistry);
|
|
376
|
+
const stylesheetDiagnosis = diagnoseComponentStylesheetPipeline(ctx.file, isDirect, stylesheetRegistry, wrapperModules, pluginOptions.stylePreprocessor);
|
|
377
|
+
debugStylesV("HMR: component stylesheet changed", {
|
|
378
|
+
file: isDirect.file,
|
|
379
|
+
encapsulation
|
|
380
|
+
});
|
|
381
|
+
debugHmrV("component stylesheet wrapper modules", {
|
|
382
|
+
file: ctx.file,
|
|
383
|
+
wrapperCount: wrapperModules.length,
|
|
384
|
+
wrapperIds: wrapperModules.map((mod) => mod.id),
|
|
385
|
+
availableModuleIds: fileModules.map((mod) => mod.id)
|
|
386
|
+
});
|
|
387
|
+
debugHmrV("component stylesheet pipeline diagnosis", stylesheetDiagnosis);
|
|
388
|
+
ctx.server.moduleGraph.invalidateModule(isDirect);
|
|
389
|
+
debugHmrV("component stylesheet direct module invalidated", {
|
|
390
|
+
file: ctx.file,
|
|
391
|
+
directModuleId: isDirect.id,
|
|
392
|
+
directModuleUrl: isDirect.url,
|
|
393
|
+
reason: "Ensure Vite drops stale direct CSS transform results before wrapper or fallback handling continues."
|
|
394
|
+
});
|
|
395
|
+
const trackedWrapperRequestIds = stylesheetDiagnosis.trackedRequestIds.filter((id) => id.includes("?ngcomp="));
|
|
396
|
+
if (encapsulation !== "shadow" && (wrapperModules.length > 0 || trackedWrapperRequestIds.length > 0)) {
|
|
397
|
+
wrapperModules.forEach((mod) => ctx.server.moduleGraph.invalidateModule(mod));
|
|
398
|
+
debugHmrV("sending css-update for component stylesheet", {
|
|
399
|
+
file: ctx.file,
|
|
400
|
+
path: isDirect.url,
|
|
401
|
+
acceptedPath: isDirect.file,
|
|
402
|
+
wrapperCount: wrapperModules.length,
|
|
403
|
+
trackedWrapperRequestIds,
|
|
404
|
+
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
405
|
});
|
|
228
|
-
|
|
406
|
+
sendCssUpdate(ctx.server, {
|
|
407
|
+
path: isDirect.url,
|
|
408
|
+
acceptedPath: isDirect.file
|
|
409
|
+
});
|
|
410
|
+
logComponentStylesheetHmrOutcome({
|
|
411
|
+
file: ctx.file,
|
|
412
|
+
encapsulation,
|
|
413
|
+
diagnosis: stylesheetDiagnosis,
|
|
414
|
+
outcome: "css-update",
|
|
415
|
+
directModuleId: isDirect.id,
|
|
416
|
+
wrapperIds: wrapperModules.map((mod) => mod.id)
|
|
417
|
+
});
|
|
418
|
+
return union(fileModules.filter((mod) => {
|
|
229
419
|
return mod.file !== ctx.file || mod.id !== isDirect.id;
|
|
230
420
|
}).map((mod) => {
|
|
231
421
|
if (mod.file === ctx.file) return markModuleSelfAccepting(mod);
|
|
232
422
|
return mod;
|
|
233
|
-
});
|
|
423
|
+
}), wrapperModules.map((mod) => markModuleSelfAccepting(mod)));
|
|
234
424
|
}
|
|
425
|
+
debugHmrV("component stylesheet hmr fallback: full reload", {
|
|
426
|
+
file: ctx.file,
|
|
427
|
+
encapsulation,
|
|
428
|
+
reason: trackedWrapperRequestIds.length === 0 ? "missing-wrapper-module" : encapsulation === "shadow" ? "shadow-encapsulation" : "tracked-wrapper-still-not-patchable",
|
|
429
|
+
directId: isDirect.id,
|
|
430
|
+
trackedRequestIds: stylesheetRegistry?.getRequestIdsForSource(ctx.file) ?? []
|
|
431
|
+
});
|
|
432
|
+
logComponentStylesheetHmrOutcome({
|
|
433
|
+
file: ctx.file,
|
|
434
|
+
encapsulation,
|
|
435
|
+
diagnosis: stylesheetDiagnosis,
|
|
436
|
+
outcome: "full-reload",
|
|
437
|
+
directModuleId: isDirect.id,
|
|
438
|
+
wrapperIds: wrapperModules.map((mod) => mod.id)
|
|
439
|
+
});
|
|
440
|
+
sendFullReload(ctx.server, {
|
|
441
|
+
file: ctx.file,
|
|
442
|
+
encapsulation,
|
|
443
|
+
reason: wrapperModules.length === 0 ? "missing-wrapper-module" : "shadow-encapsulation",
|
|
444
|
+
directId: isDirect.id,
|
|
445
|
+
trackedRequestIds: stylesheetRegistry?.getRequestIdsForSource(ctx.file) ?? []
|
|
446
|
+
});
|
|
447
|
+
return [];
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
return fileModules;
|
|
451
|
+
}
|
|
452
|
+
if (shouldEnableLiveReload() && /\.(html|htm)$/.test(ctx.file) && fileModules.length === 0) {
|
|
453
|
+
const ownerModules = findTemplateOwnerModules(ctx.server, ctx.file);
|
|
454
|
+
debugHmrV("template owner lookup", {
|
|
455
|
+
file: ctx.file,
|
|
456
|
+
ownerCount: ownerModules.length,
|
|
457
|
+
ownerIds: ownerModules.map((mod) => mod.id),
|
|
458
|
+
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."
|
|
459
|
+
});
|
|
460
|
+
if (ownerModules.length > 0) {
|
|
461
|
+
const ownerIds = ownerModules.map((mod) => mod.id).filter(Boolean);
|
|
462
|
+
ownerModules.forEach((mod) => ctx.server.moduleGraph.invalidateModule(mod));
|
|
463
|
+
pendingCompilation = performCompilation(resolvedConfig, ownerIds);
|
|
464
|
+
await pendingCompilation;
|
|
465
|
+
pendingCompilation = null;
|
|
466
|
+
const updates = ownerIds.filter((id) => classNames.get(id));
|
|
467
|
+
debugHmrV("template owner recompilation result", {
|
|
468
|
+
file: ctx.file,
|
|
469
|
+
ownerIds,
|
|
470
|
+
updates,
|
|
471
|
+
updateClassNames: updates.map((id) => ({
|
|
472
|
+
id,
|
|
473
|
+
className: classNames.get(id)
|
|
474
|
+
})),
|
|
475
|
+
hint: updates.length > 0 ? "External template recompilation produced Angular component update targets." : "External template recompilation completed, but no Angular component update targets were surfaced."
|
|
476
|
+
});
|
|
477
|
+
if (updates.length > 0) {
|
|
478
|
+
debugHmr("template owner module invalidation", {
|
|
479
|
+
file: ctx.file,
|
|
480
|
+
ownerIds,
|
|
481
|
+
updateCount: updates.length
|
|
482
|
+
});
|
|
483
|
+
updates.forEach((updateId) => {
|
|
484
|
+
const relativeFileId = `${normalizePath(relative(process.cwd(), updateId))}@${classNames.get(updateId)}`;
|
|
485
|
+
sendHMRComponentUpdate(ctx.server, relativeFileId);
|
|
486
|
+
});
|
|
487
|
+
return ownerModules.map((mod) => markModuleSelfAccepting(mod));
|
|
235
488
|
}
|
|
236
489
|
}
|
|
237
|
-
return ctx.modules;
|
|
238
490
|
}
|
|
239
491
|
const mods = [];
|
|
240
492
|
const updates = [];
|
|
241
|
-
|
|
493
|
+
fileModules.forEach((mod) => {
|
|
242
494
|
mod.importers.forEach((imp) => {
|
|
243
495
|
ctx.server.moduleGraph.invalidateModule(imp);
|
|
244
|
-
if (
|
|
496
|
+
if (shouldExternalizeStyles() && classNames.get(imp.id)) updates.push(imp.id);
|
|
245
497
|
else mods.push(imp);
|
|
246
498
|
});
|
|
247
499
|
});
|
|
248
|
-
|
|
500
|
+
debugHmrV("resource importer analysis", {
|
|
501
|
+
file: ctx.file,
|
|
502
|
+
fileModuleCount: fileModules.length,
|
|
503
|
+
importerCount: fileModules.reduce((count, mod) => count + mod.importers.size, 0),
|
|
504
|
+
updates,
|
|
505
|
+
mods: mods.map((mod) => mod.id)
|
|
506
|
+
});
|
|
507
|
+
pendingCompilation = performCompilation(resolvedConfig, [...mods.map((mod) => mod.id).filter(Boolean), ...updates]);
|
|
249
508
|
if (updates.length > 0) {
|
|
250
509
|
await pendingCompilation;
|
|
251
510
|
pendingCompilation = null;
|
|
511
|
+
debugHmr("resource importer component updates", {
|
|
512
|
+
file: ctx.file,
|
|
513
|
+
updateCount: updates.length
|
|
514
|
+
});
|
|
252
515
|
updates.forEach((updateId) => {
|
|
253
516
|
const impRelativeFileId = `${normalizePath(relative(process.cwd(), updateId))}@${classNames.get(updateId)}`;
|
|
254
517
|
sendHMRComponentUpdate(ctx.server, impRelativeFileId);
|
|
255
518
|
});
|
|
256
|
-
return
|
|
519
|
+
return fileModules.map((mod) => {
|
|
257
520
|
if (mod.id === ctx.file) return markModuleSelfAccepting(mod);
|
|
258
521
|
return mod;
|
|
259
522
|
});
|
|
260
523
|
}
|
|
261
524
|
return mods;
|
|
262
525
|
}
|
|
526
|
+
debugHmr("full reload — unrecognized file type", { file: ctx.file });
|
|
263
527
|
classNames.clear();
|
|
264
528
|
return ctx.modules;
|
|
265
529
|
},
|
|
266
530
|
resolveId(id, importer) {
|
|
531
|
+
if (id.startsWith("virtual:@analogjs/vite-plugin-angular:raw:")) return `\0${id}`;
|
|
267
532
|
if (jit && id.startsWith("angular:jit:")) {
|
|
268
|
-
const
|
|
269
|
-
|
|
533
|
+
const filePath = normalizePath(resolve(dirname(importer), id.split(";")[1]));
|
|
534
|
+
if (id.includes(":style")) {
|
|
535
|
+
markStylePathSafe(resolvedConfig, filePath);
|
|
536
|
+
return filePath + "?inline";
|
|
537
|
+
}
|
|
538
|
+
return toVirtualRawId(filePath);
|
|
539
|
+
}
|
|
540
|
+
const rawRewrite = rewriteHtmlRawImport(id, importer);
|
|
541
|
+
if (rawRewrite) return rawRewrite;
|
|
542
|
+
if (/\.(css|scss|sass|less)\?inline$/.test(id) && importer) {
|
|
543
|
+
const filePath = id.split("?")[0];
|
|
544
|
+
const resolved = isAbsolute(filePath) ? normalizePath(filePath) : normalizePath(resolve(dirname(importer), filePath));
|
|
545
|
+
markStylePathSafe(resolvedConfig, resolved);
|
|
546
|
+
return resolved + "?inline";
|
|
270
547
|
}
|
|
271
548
|
if (isComponentStyleSheet(id)) {
|
|
272
|
-
const
|
|
273
|
-
|
|
549
|
+
const filename = getFilenameFromPath(id);
|
|
550
|
+
const search = new URL(id, "http://localhost").search;
|
|
551
|
+
const servedSourcePath = stylesheetRegistry?.getServedSourcePath(filename);
|
|
552
|
+
if (servedSourcePath) {
|
|
553
|
+
debugStylesV("resolveId: mapped served stylesheet to source", {
|
|
554
|
+
filename,
|
|
555
|
+
resolvedPath: servedSourcePath
|
|
556
|
+
});
|
|
557
|
+
return servedSourcePath + search;
|
|
558
|
+
}
|
|
559
|
+
if (stylesheetRegistry?.hasServed(filename)) {
|
|
560
|
+
debugStylesV("resolveId: kept preprocessed ID", { filename });
|
|
561
|
+
return id;
|
|
562
|
+
}
|
|
563
|
+
const componentStyles = stylesheetRegistry?.resolveExternalSource(filename);
|
|
564
|
+
if (componentStyles) {
|
|
565
|
+
debugStylesV("resolveId: mapped external stylesheet", {
|
|
566
|
+
filename,
|
|
567
|
+
resolvedPath: componentStyles
|
|
568
|
+
});
|
|
569
|
+
return componentStyles + new URL(id, "http://localhost").search;
|
|
570
|
+
}
|
|
571
|
+
debugStyles("resolveId: component stylesheet NOT FOUND in either map", {
|
|
572
|
+
filename,
|
|
573
|
+
inlineMapSize: stylesheetRegistry?.servedCount ?? 0,
|
|
574
|
+
externalMapSize: stylesheetRegistry?.externalCount ?? 0
|
|
575
|
+
});
|
|
274
576
|
}
|
|
275
577
|
},
|
|
276
578
|
async load(id) {
|
|
579
|
+
const rawModule = await loadVirtualRawModule(this, id);
|
|
580
|
+
if (rawModule !== void 0) return rawModule;
|
|
581
|
+
if (/\.(css|scss|sass|less)\?inline$/.test(id)) markStylePathSafe(resolvedConfig, id.split("?")[0]);
|
|
277
582
|
if (isComponentStyleSheet(id)) {
|
|
278
|
-
const
|
|
279
|
-
|
|
583
|
+
const filename = getFilenameFromPath(id);
|
|
584
|
+
const componentStyles = stylesheetRegistry?.getServedContent(filename);
|
|
585
|
+
if (componentStyles) {
|
|
586
|
+
stylesheetRegistry?.registerActiveRequest(id);
|
|
587
|
+
debugHmrV("stylesheet active request registered", {
|
|
588
|
+
requestId: id,
|
|
589
|
+
filename,
|
|
590
|
+
sourcePath: stylesheetRegistry?.resolveExternalSource(filename) ?? stylesheetRegistry?.resolveExternalSource(filename.replace(/^\//, "")) ?? stylesheetRegistry?.getServedSourcePath(filename) ?? stylesheetRegistry?.getServedSourcePath(filename.replace(/^\//, "")),
|
|
591
|
+
trackedRequestIds: stylesheetRegistry?.getRequestIdsForSource(stylesheetRegistry?.resolveExternalSource(filename) ?? stylesheetRegistry?.resolveExternalSource(filename.replace(/^\//, "")) ?? stylesheetRegistry?.getServedSourcePath(filename) ?? stylesheetRegistry?.getServedSourcePath(filename.replace(/^\//, "")) ?? "") ?? []
|
|
592
|
+
});
|
|
593
|
+
debugStylesV("load: served inline component stylesheet", {
|
|
594
|
+
filename,
|
|
595
|
+
length: componentStyles.length,
|
|
596
|
+
requestId: id,
|
|
597
|
+
...describeStylesheetContent(componentStyles)
|
|
598
|
+
});
|
|
599
|
+
return componentStyles;
|
|
600
|
+
}
|
|
280
601
|
}
|
|
281
602
|
},
|
|
282
603
|
transform: {
|
|
@@ -289,27 +610,7 @@ function angular(options) {
|
|
|
289
610
|
]
|
|
290
611
|
} },
|
|
291
612
|
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
|
-
}
|
|
613
|
+
if (transformFilter && !transformFilter(code, id)) return;
|
|
313
614
|
if (id.includes(".ts?")) id = id.replace(/\?(.*)/, "");
|
|
314
615
|
fileTransformMap.set(id, code);
|
|
315
616
|
/**
|
|
@@ -318,19 +619,25 @@ function angular(options) {
|
|
|
318
619
|
*/
|
|
319
620
|
if (isTest) {
|
|
320
621
|
if (isVitestVscode && !initialCompilation) {
|
|
321
|
-
pendingCompilation = performCompilation(resolvedConfig);
|
|
622
|
+
pendingCompilation = performCompilation(this.environment?.config ?? resolvedConfig);
|
|
322
623
|
initialCompilation = true;
|
|
323
624
|
}
|
|
324
625
|
const tsMod = viteServer?.moduleGraph.getModuleById(id);
|
|
325
626
|
if (tsMod) {
|
|
326
627
|
const invalidated = tsMod.lastInvalidationTimestamp;
|
|
327
|
-
if (testWatchMode && invalidated) pendingCompilation = performCompilation(resolvedConfig, [id]);
|
|
628
|
+
if (testWatchMode && invalidated) pendingCompilation = performCompilation(this.environment?.config ?? resolvedConfig, [id]);
|
|
328
629
|
}
|
|
329
630
|
}
|
|
330
631
|
const hasComponent = code.includes("@Component");
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
632
|
+
debugCompilerV("transform", {
|
|
633
|
+
id,
|
|
634
|
+
codeLength: code.length,
|
|
635
|
+
hasComponent
|
|
636
|
+
});
|
|
637
|
+
const resolveResourceUrls = hasComponent && (watchMode || jit);
|
|
638
|
+
const templateUrls = resolveResourceUrls ? templateUrlsResolver.resolve(code, id) : [];
|
|
639
|
+
const styleUrls = resolveResourceUrls ? styleUrlsResolver.resolve(code, id) : [];
|
|
640
|
+
if (resolveResourceUrls && watchMode) for (const urlSet of [...templateUrls, ...styleUrls]) {
|
|
334
641
|
const [, absoluteFileUrl] = urlSet.split("|");
|
|
335
642
|
this.addWatchFile(absoluteFileUrl);
|
|
336
643
|
}
|
|
@@ -339,23 +646,58 @@ function angular(options) {
|
|
|
339
646
|
pendingCompilation = null;
|
|
340
647
|
}
|
|
341
648
|
const typescriptResult = fileEmitter(id);
|
|
342
|
-
if (typescriptResult
|
|
343
|
-
|
|
344
|
-
|
|
649
|
+
if (!typescriptResult) {
|
|
650
|
+
debugCompilerV("transform skip (file not emitted by Angular)", { id });
|
|
651
|
+
const isAngular = !id.includes("@ng/component") && /(Component|Directive|Pipe|Injectable|NgModule)\(/.test(code);
|
|
652
|
+
debugEmit("transform emit miss", {
|
|
653
|
+
id,
|
|
654
|
+
normalizedId: normalizeEmitterLookupId(id),
|
|
655
|
+
knownOutputCount: outputFiles.size,
|
|
656
|
+
hasOutputFileHook: !!outputFile,
|
|
657
|
+
isAngular
|
|
658
|
+
});
|
|
659
|
+
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.`);
|
|
660
|
+
return;
|
|
661
|
+
}
|
|
662
|
+
if (typescriptResult.warnings && typescriptResult.warnings.length > 0) this.warn(`${typescriptResult.warnings.join("\n")}`);
|
|
663
|
+
if (typescriptResult.errors && typescriptResult.errors.length > 0) this.error(`${typescriptResult.errors.join("\n")}`);
|
|
664
|
+
let data = typescriptResult.content ?? "";
|
|
665
|
+
debugEmitV("transform emit hit", {
|
|
666
|
+
id,
|
|
667
|
+
normalizedId: normalizeEmitterLookupId(id),
|
|
668
|
+
...describeEmitMarkers(data),
|
|
669
|
+
errorCount: typescriptResult.errors?.length ?? 0,
|
|
670
|
+
warningCount: typescriptResult.warnings?.length ?? 0
|
|
671
|
+
});
|
|
345
672
|
if (jit && data.includes("angular:jit:")) {
|
|
346
|
-
data = data.replace(/angular:jit:style:inline
|
|
673
|
+
data = data.replace(/angular:jit:style:inline;([A-Za-z0-9+/=]*)/g, (_match, encodedStyles) => toJitInlineStyleId(encodedStyles));
|
|
347
674
|
templateUrls.forEach((templateUrlSet) => {
|
|
348
675
|
const [templateFile, resolvedTemplateUrl] = templateUrlSet.split("|");
|
|
349
|
-
data = data.replace(`angular:jit:template:file;${templateFile}`,
|
|
676
|
+
data = data.replace(`angular:jit:template:file;${templateFile}`, toVirtualRawId(resolvedTemplateUrl));
|
|
350
677
|
});
|
|
351
678
|
styleUrls.forEach((styleUrlSet) => {
|
|
352
679
|
const [styleFile, resolvedStyleUrl] = styleUrlSet.split("|");
|
|
353
|
-
|
|
680
|
+
markStylePathSafe(resolvedConfig, resolvedStyleUrl);
|
|
681
|
+
data = data.replace(`angular:jit:style:file;${styleFile}`, resolvedStyleUrl + "?inline");
|
|
354
682
|
});
|
|
355
683
|
}
|
|
684
|
+
if (data.includes("HmrLoad")) {
|
|
685
|
+
const hasMetaUrl = data.includes("getReplaceMetadataURL");
|
|
686
|
+
debugHmrV("vite-ignore injection", {
|
|
687
|
+
id,
|
|
688
|
+
dataLength: data.length,
|
|
689
|
+
hasMetaUrl
|
|
690
|
+
});
|
|
691
|
+
if (hasMetaUrl) {
|
|
692
|
+
const patched = injectViteIgnoreForHmrMetadata(data);
|
|
693
|
+
if (patched !== data && !patched.includes("@vite-ignore")) debugHmrV("vite-ignore regex fallback", { id });
|
|
694
|
+
data = patched;
|
|
695
|
+
}
|
|
696
|
+
}
|
|
697
|
+
if (typescriptResult.map) data = data.replace(/\s*\/\/# sourceMappingURL=[^\r\n]*\s*$/, "");
|
|
356
698
|
return {
|
|
357
699
|
code: data,
|
|
358
|
-
map: null
|
|
700
|
+
map: typescriptResult.map ? normalizeSourceMapSources(typescriptResult.map, id) : null
|
|
359
701
|
};
|
|
360
702
|
}
|
|
361
703
|
},
|
|
@@ -364,19 +706,47 @@ function angular(options) {
|
|
|
364
706
|
mkdirSync(declarationFileDir, { recursive: true });
|
|
365
707
|
writeFileSync(declarationPath, data, "utf-8");
|
|
366
708
|
});
|
|
367
|
-
|
|
368
|
-
|
|
709
|
+
declarationFiles.length = 0;
|
|
710
|
+
if (!watchMode) releaseCssPreprocessorWorkers();
|
|
369
711
|
}
|
|
370
712
|
};
|
|
371
713
|
}
|
|
714
|
+
function normalizeSourceMapSources(map, id) {
|
|
715
|
+
const sourceMap = JSON.parse(map);
|
|
716
|
+
const sourceDirectory = dirname(id);
|
|
717
|
+
const sourceRoot = sourceMap.sourceRoot ?? "";
|
|
718
|
+
sourceMap.sources = sourceMap.sources?.map((source) => {
|
|
719
|
+
if (isAbsolute(source) || /^[a-z][a-z\d+.-]*:/i.test(source)) return normalizePath(source);
|
|
720
|
+
return normalizePath(resolve(sourceDirectory, sourceRoot, source));
|
|
721
|
+
});
|
|
722
|
+
delete sourceMap.sourceRoot;
|
|
723
|
+
return JSON.stringify(sourceMap);
|
|
724
|
+
}
|
|
725
|
+
const compilationPlugin = pluginOptions.fastCompile ? fastCompilePlugin({
|
|
726
|
+
tsconfigGetter: pluginOptions.tsconfigGetter,
|
|
727
|
+
workspaceRoot: pluginOptions.workspaceRoot,
|
|
728
|
+
inlineStylesExtension: pluginOptions.inlineStylesExtension,
|
|
729
|
+
jit,
|
|
730
|
+
liveReload: pluginOptions.liveReload,
|
|
731
|
+
supportedBrowsers: pluginOptions.supportedBrowsers,
|
|
732
|
+
isTest,
|
|
733
|
+
isAstroIntegration,
|
|
734
|
+
fastCompileMode: pluginOptions.fastCompileMode
|
|
735
|
+
}) : angularPlugin();
|
|
372
736
|
return [
|
|
737
|
+
cssExtensionStyleResolverPlugin(),
|
|
373
738
|
replaceFiles(pluginOptions.fileReplacements, pluginOptions.workspaceRoot),
|
|
374
|
-
|
|
739
|
+
virtualModulesPlugin({ jit }),
|
|
375
740
|
pluginOptions.liveReload && liveReloadPlugin({
|
|
376
741
|
classNames,
|
|
377
742
|
fileEmitter
|
|
378
743
|
}),
|
|
379
|
-
|
|
744
|
+
compilationPlugin,
|
|
745
|
+
!pluginOptions.fastCompile && pluginOptions.liveReload && liveReloadPlugin({
|
|
746
|
+
classNames,
|
|
747
|
+
fileEmitter
|
|
748
|
+
}),
|
|
749
|
+
...isTest && !isStackBlitz ? angularVitestPlugins((id) => outputFiles.get(normalizePath(id))?.map) : [],
|
|
380
750
|
jit && jitPlugin({ inlineStylesExtension: pluginOptions.inlineStylesExtension }),
|
|
381
751
|
buildOptimizerPlugin({
|
|
382
752
|
supportedBrowsers: pluginOptions.supportedBrowsers,
|
|
@@ -384,116 +754,12 @@ function angular(options) {
|
|
|
384
754
|
}),
|
|
385
755
|
routerPlugin(),
|
|
386
756
|
angularFullVersion < 190004 && pendingTasksPlugin(),
|
|
387
|
-
nxFolderPlugin()
|
|
757
|
+
nxFolderPlugin(),
|
|
758
|
+
encapsulationPlugin()
|
|
388
759
|
].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
760
|
function resolveTsConfigPath() {
|
|
414
761
|
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
|
-
}
|
|
762
|
+
return getTsConfigPath(tsConfigResolutionContext.root, tsconfigValue, tsConfigResolutionContext.isProd, isTest, tsConfigResolutionContext.isLib, pluginOptions.workspaceRoot);
|
|
497
763
|
}
|
|
498
764
|
async function performCompilation(config, ids) {
|
|
499
765
|
let resolve;
|
|
@@ -503,6 +769,12 @@ function angular(options) {
|
|
|
503
769
|
});
|
|
504
770
|
try {
|
|
505
771
|
await previousLock;
|
|
772
|
+
const integrations = await discoverAnalogIntegrations(config);
|
|
773
|
+
pluginOptions.stylePreprocessor = integrations.stylePreprocessor;
|
|
774
|
+
externalizeStylesRequested = integrations.externalizeStyles;
|
|
775
|
+
configureStylesheetRegistry = integrations.configureStylesheetRegistry;
|
|
776
|
+
transformFilter = integrations.transformFilter;
|
|
777
|
+
tsconfigResolver.setIntegrationIncludes(integrations.include);
|
|
506
778
|
await _doPerformCompilation(config, ids);
|
|
507
779
|
} finally {
|
|
508
780
|
resolve();
|
|
@@ -513,54 +785,27 @@ function angular(options) {
|
|
|
513
785
|
* 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
786
|
*/
|
|
515
787
|
async function _doPerformCompilation(config, ids) {
|
|
516
|
-
if (
|
|
517
|
-
await performAngularCompilation(config, ids);
|
|
518
|
-
return;
|
|
519
|
-
}
|
|
788
|
+
if (!jit) styleTransform = (code, filename) => preprocessCSS(code, filename, config);
|
|
520
789
|
const isProd = config.mode === "production";
|
|
521
|
-
|
|
522
|
-
sourceFileCache$1.invalidate(modifiedFiles);
|
|
790
|
+
invalidateSourceFiles(new Set(ids ?? []));
|
|
523
791
|
if (ids?.length) for (const id of ids || []) fileTransformMap.delete(id);
|
|
524
|
-
if (pluginOptions.include.length > 0 && includeCache.length === 0) includeCache = findIncludes();
|
|
525
792
|
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
|
-
}
|
|
793
|
+
const cached = tsconfigResolver.getCachedTsconfigOptions(resolvedTsConfigPath, config);
|
|
557
794
|
const tsCompilerOptions = { ...cached.options };
|
|
558
795
|
let rootNames = [...cached.rootNames];
|
|
559
|
-
if (
|
|
796
|
+
if (shouldExternalizeStyles()) tsCompilerOptions["externalRuntimeStyles"] = true;
|
|
797
|
+
if (shouldEnableLiveReload()) {
|
|
560
798
|
tsCompilerOptions["_enableHmr"] = true;
|
|
561
|
-
tsCompilerOptions["externalRuntimeStyles"] = true;
|
|
562
799
|
tsCompilerOptions["supportTestBed"] = true;
|
|
563
800
|
}
|
|
801
|
+
debugCompiler("tsCompilerOptions (NgtscProgram path)", {
|
|
802
|
+
liveReload: pluginOptions.liveReload,
|
|
803
|
+
viteHmr: hasViteHmrTransport(),
|
|
804
|
+
externalizeStylesRequested,
|
|
805
|
+
shouldExternalize: shouldExternalizeStyles(),
|
|
806
|
+
externalRuntimeStyles: !!tsCompilerOptions["externalRuntimeStyles"],
|
|
807
|
+
hmrEnabled: !!tsCompilerOptions["_enableHmr"]
|
|
808
|
+
});
|
|
564
809
|
if (tsCompilerOptions["compilationMode"] === "partial") {
|
|
565
810
|
tsCompilerOptions["supportTestBed"] = true;
|
|
566
811
|
tsCompilerOptions["supportJitMode"] = true;
|
|
@@ -572,11 +817,7 @@ function angular(options) {
|
|
|
572
817
|
}
|
|
573
818
|
if (isTest) tsCompilerOptions["supportTestBed"] = true;
|
|
574
819
|
const replacements = pluginOptions.fileReplacements.map((rp) => join(pluginOptions.workspaceRoot, rp.ssr || rp.with));
|
|
575
|
-
rootNames =
|
|
576
|
-
...rootNames,
|
|
577
|
-
...includeCache,
|
|
578
|
-
...replacements
|
|
579
|
-
])];
|
|
820
|
+
rootNames = union(rootNames, tsconfigResolver.ensureIncludeCache(), replacements);
|
|
580
821
|
const hostKey = JSON.stringify(tsCompilerOptions);
|
|
581
822
|
let host;
|
|
582
823
|
if (cachedHost && cachedHostKey === hostKey) host = cachedHost;
|
|
@@ -592,17 +833,19 @@ function angular(options) {
|
|
|
592
833
|
});
|
|
593
834
|
cachedHost = host;
|
|
594
835
|
cachedHostKey = hostKey;
|
|
595
|
-
if (watchMode) augmentHostWithCaching(host,
|
|
836
|
+
if (watchMode) augmentHostWithCaching(host, tsSourceFileCache);
|
|
596
837
|
}
|
|
597
838
|
if (!jit) {
|
|
598
|
-
|
|
599
|
-
|
|
839
|
+
const externalizeStyles = !!tsCompilerOptions["externalRuntimeStyles"];
|
|
840
|
+
stylesheetRegistry = externalizeStyles ? new AnalogStylesheetRegistry() : void 0;
|
|
841
|
+
if (stylesheetRegistry) configureStylesheetRegistry?.(stylesheetRegistry, { workspaceRoot: pluginOptions.workspaceRoot });
|
|
842
|
+
debugStyles("stylesheet registry initialized (NgtscProgram path)", { externalizeStyles });
|
|
600
843
|
augmentHostWithResources(host, styleTransform, {
|
|
601
844
|
inlineStylesExtension: pluginOptions.inlineStylesExtension,
|
|
602
845
|
isProd,
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
846
|
+
stylesheetRegistry,
|
|
847
|
+
sourceFileCache: sourceFileCache$1,
|
|
848
|
+
stylePreprocessor: pluginOptions.stylePreprocessor
|
|
606
849
|
});
|
|
607
850
|
}
|
|
608
851
|
/**
|
|
@@ -631,9 +874,19 @@ function angular(options) {
|
|
|
631
874
|
const writeFileCallback = (_filename, content, _a, _b, sourceFiles) => {
|
|
632
875
|
if (!sourceFiles?.length) return;
|
|
633
876
|
const filename = normalizePath(sourceFiles[0].fileName);
|
|
634
|
-
if (filename.includes("ngtypecheck.ts") || filename.includes(".d.")) return;
|
|
877
|
+
if (filename.includes("ngtypecheck.ts") || filename.includes(".d.") || _filename.endsWith(".d.ts") || _filename.endsWith(".d.mts") || _filename.endsWith(".d.cts")) return;
|
|
878
|
+
if (/\.[cm]?js\.map$/.test(_filename)) {
|
|
879
|
+
const existing = outputFiles.get(filename);
|
|
880
|
+
outputFiles.set(filename, {
|
|
881
|
+
...existing ?? { dependencies: [] },
|
|
882
|
+
map: content
|
|
883
|
+
});
|
|
884
|
+
return;
|
|
885
|
+
}
|
|
635
886
|
const metadata = watchMode ? fileMetadata(filename) : {};
|
|
887
|
+
const existing = outputFiles.get(filename);
|
|
636
888
|
outputFiles.set(filename, {
|
|
889
|
+
...existing ?? {},
|
|
637
890
|
content,
|
|
638
891
|
dependencies: [],
|
|
639
892
|
errors: metadata.errors,
|
|
@@ -641,13 +894,27 @@ function angular(options) {
|
|
|
641
894
|
hmrUpdateCode: metadata.hmrUpdateCode,
|
|
642
895
|
hmrEligible: metadata.hmrEligible
|
|
643
896
|
});
|
|
897
|
+
debugEmitV("registered ngtsc output", {
|
|
898
|
+
filename,
|
|
899
|
+
...describeEmitMarkers(content),
|
|
900
|
+
errorCount: metadata.errors?.length ?? 0,
|
|
901
|
+
warningCount: metadata.warnings?.length ?? 0,
|
|
902
|
+
hmrEligible: !!metadata.hmrEligible,
|
|
903
|
+
knownOutputCount: outputFiles.size
|
|
904
|
+
});
|
|
644
905
|
};
|
|
645
906
|
const writeOutputFile = (id) => {
|
|
646
907
|
const sourceFile = builder.getSourceFile(id);
|
|
647
908
|
if (!sourceFile) return;
|
|
648
909
|
let content = "";
|
|
910
|
+
let map;
|
|
911
|
+
let mapFilename;
|
|
649
912
|
builder.emit(sourceFile, (filename, data) => {
|
|
650
913
|
if (/\.[cm]?js$/.test(filename)) content = data;
|
|
914
|
+
if (/\.[cm]?js\.map$/.test(filename)) {
|
|
915
|
+
map = data;
|
|
916
|
+
mapFilename = filename;
|
|
917
|
+
}
|
|
651
918
|
if (!watchMode && !isTest && /\.d\.ts/.test(filename) && !filename.includes(".ngtypecheck.")) {
|
|
652
919
|
const declarationPath = resolve(config.root, config.build.outDir, relative(config.root, filename)).replace("/src/", "/");
|
|
653
920
|
const declarationFileDir = declarationPath.replace(basename(filename), "").replace("/src/", "/");
|
|
@@ -659,6 +926,7 @@ function angular(options) {
|
|
|
659
926
|
}
|
|
660
927
|
}, void 0, void 0, transformers);
|
|
661
928
|
writeFileCallback(id, content, false, void 0, [sourceFile]);
|
|
929
|
+
if (map !== void 0 && mapFilename !== void 0) writeFileCallback(mapFilename, map, false, void 0, [sourceFile]);
|
|
662
930
|
if (angularCompiler) angularCompiler.incrementalCompilation.recordSuccessfulEmit(sourceFile);
|
|
663
931
|
};
|
|
664
932
|
if (watchMode) {
|
|
@@ -681,54 +949,225 @@ function createFsWatcherCacheInvalidator(invalidateFsCaches, invalidateTsconfigC
|
|
|
681
949
|
};
|
|
682
950
|
}
|
|
683
951
|
/**
|
|
684
|
-
*
|
|
685
|
-
*
|
|
952
|
+
* Returns every live Vite module that can legitimately represent a changed
|
|
953
|
+
* Angular resource file.
|
|
686
954
|
*
|
|
687
|
-
*
|
|
688
|
-
*
|
|
689
|
-
*
|
|
690
|
-
*
|
|
691
|
-
*
|
|
692
|
-
*
|
|
693
|
-
*
|
|
955
|
+
* For normal files, `getModulesByFile()` is enough. For Angular component
|
|
956
|
+
* stylesheets, it is not: the browser often holds virtual hashed requests
|
|
957
|
+
* (`/abc123.css?direct&ngcomp=...` and `/abc123.css?ngcomp=...`) that are no
|
|
958
|
+
* longer discoverable from the original source path alone. We therefore merge:
|
|
959
|
+
* - watcher event modules
|
|
960
|
+
* - module-graph modules by source file
|
|
961
|
+
* - registry-tracked live request ids resolved back through the module graph
|
|
694
962
|
*/
|
|
695
|
-
function
|
|
696
|
-
const
|
|
697
|
-
|
|
698
|
-
|
|
963
|
+
async function getModulesForChangedFile(server, file, eventModules = [], stylesheetRegistry) {
|
|
964
|
+
const normalizedFile = normalizePath(file.split("?")[0]);
|
|
965
|
+
const modules = /* @__PURE__ */ new Map();
|
|
966
|
+
for (const mod of eventModules) if (mod.id) modules.set(mod.id, mod);
|
|
967
|
+
server.moduleGraph.getModulesByFile(normalizedFile)?.forEach((mod) => {
|
|
968
|
+
if (mod.id) modules.set(mod.id, mod);
|
|
969
|
+
});
|
|
970
|
+
const stylesheetRequestIds = stylesheetRegistry?.getRequestIdsForSource(normalizedFile) ?? [];
|
|
971
|
+
const requestIdHits = [];
|
|
972
|
+
for (const requestId of stylesheetRequestIds) {
|
|
973
|
+
const candidates = [requestId, requestId.startsWith("/") ? requestId : `/${requestId}`];
|
|
974
|
+
for (const candidate of candidates) {
|
|
975
|
+
const mod = await server.moduleGraph.getModuleByUrl(candidate) ?? server.moduleGraph.getModuleById(candidate);
|
|
976
|
+
requestIdHits.push({
|
|
977
|
+
requestId,
|
|
978
|
+
candidate,
|
|
979
|
+
via: mod?.url === candidate ? "url" : "id",
|
|
980
|
+
moduleId: mod?.id
|
|
981
|
+
});
|
|
982
|
+
if (mod?.id) modules.set(mod.id, mod);
|
|
983
|
+
}
|
|
984
|
+
}
|
|
985
|
+
debugHmrV("getModulesForChangedFile registry lookup", {
|
|
986
|
+
file: normalizedFile,
|
|
987
|
+
stylesheetRequestIds,
|
|
988
|
+
requestIdHits,
|
|
989
|
+
resolvedModuleIds: [...modules.keys()]
|
|
699
990
|
});
|
|
700
|
-
return
|
|
991
|
+
return [...modules.values()];
|
|
701
992
|
}
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
const
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
993
|
+
function isModuleForChangedResource(mod, changedFile, stylesheetRegistry) {
|
|
994
|
+
const normalizedChangedFile = normalizePath(changedFile.split("?")[0]);
|
|
995
|
+
if (normalizePath((mod.file ?? "").split("?")[0]) === normalizedChangedFile) return true;
|
|
996
|
+
if (!mod.id) return false;
|
|
997
|
+
const requestPath = getFilenameFromPath(mod.id);
|
|
998
|
+
return normalizePath((stylesheetRegistry?.resolveExternalSource(requestPath) ?? stylesheetRegistry?.resolveExternalSource(requestPath.replace(/^\//, "")) ?? stylesheetRegistry?.getServedSourcePath(requestPath) ?? stylesheetRegistry?.getServedSourcePath(requestPath.replace(/^\//, "")) ?? "").split("?")[0]) === normalizedChangedFile;
|
|
999
|
+
}
|
|
1000
|
+
function diagnoseComponentStylesheetPipeline(changedFile, directModule, stylesheetRegistry, wrapperModules, stylePreprocessor) {
|
|
1001
|
+
const normalizedFile = normalizePath(changedFile.split("?")[0]);
|
|
1002
|
+
const sourceExists = existsSync(normalizedFile);
|
|
1003
|
+
const sourceCode = sourceExists ? readFileSync(normalizedFile, "utf-8") : void 0;
|
|
1004
|
+
const directRequestPath = directModule.id ? getFilenameFromPath(directModule.id) : void 0;
|
|
1005
|
+
const sourcePath = directRequestPath ? stylesheetRegistry?.resolveExternalSource(directRequestPath) ?? stylesheetRegistry?.resolveExternalSource(directRequestPath.replace(/^\//, "")) ?? stylesheetRegistry?.getServedSourcePath(directRequestPath) ?? stylesheetRegistry?.getServedSourcePath(directRequestPath.replace(/^\//, "")) : normalizedFile;
|
|
1006
|
+
const registryCode = directRequestPath ? stylesheetRegistry?.getServedContent(directRequestPath) : void 0;
|
|
1007
|
+
const trackedRequestIds = stylesheetRegistry?.getRequestIdsForSource(sourcePath ?? "") ?? [];
|
|
1008
|
+
const dependencies = stylesheetRegistry?.getDependenciesForSource(sourcePath ?? "") ?? [];
|
|
1009
|
+
const diagnostics = stylesheetRegistry?.getDiagnosticsForSource(sourcePath ?? "") ?? [];
|
|
1010
|
+
const tags = stylesheetRegistry?.getTagsForSource(sourcePath ?? "") ?? [];
|
|
1011
|
+
const anomalies = [];
|
|
1012
|
+
const hints = [];
|
|
1013
|
+
if (!sourceExists) {
|
|
1014
|
+
anomalies.push("source_file_missing");
|
|
1015
|
+
hints.push("The stylesheet watcher fired for a file that no longer exists on disk.");
|
|
1016
|
+
}
|
|
1017
|
+
if (!registryCode) {
|
|
1018
|
+
anomalies.push("registry_content_missing");
|
|
1019
|
+
hints.push("The stylesheet registry has no served content for the direct module request path.");
|
|
1020
|
+
}
|
|
1021
|
+
if (sourceCode && registryCode) {
|
|
1022
|
+
let expectedRegistryCode = preprocessStylesheet(sourceCode, normalizedFile, stylePreprocessor);
|
|
1023
|
+
expectedRegistryCode = rewriteRelativeCssImports(expectedRegistryCode, normalizedFile);
|
|
1024
|
+
if (describeStylesheetContent(expectedRegistryCode).digest !== describeStylesheetContent(registryCode).digest) {
|
|
1025
|
+
anomalies.push("source_registry_mismatch");
|
|
1026
|
+
hints.push("The source file changed, but the served stylesheet content in the registry is still stale.");
|
|
1027
|
+
}
|
|
1028
|
+
}
|
|
1029
|
+
if (trackedRequestIds.length === 0) {
|
|
1030
|
+
anomalies.push("no_tracked_requests");
|
|
1031
|
+
hints.push("No live stylesheet requests are tracked for this source file, so HMR has no browser-facing target.");
|
|
1032
|
+
}
|
|
1033
|
+
if (trackedRequestIds.some((id) => id.includes("?ngcomp=")) && wrapperModules.length === 0) {
|
|
1034
|
+
anomalies.push("tracked_wrapper_missing_from_module_graph");
|
|
1035
|
+
hints.push("A wrapper request id is known, but Vite did not expose a live wrapper module during this HMR pass.");
|
|
1036
|
+
}
|
|
1037
|
+
if (trackedRequestIds.every((id) => !id.includes("?ngcomp=")) && wrapperModules.length === 0) {
|
|
1038
|
+
anomalies.push("wrapper_not_yet_tracked");
|
|
1039
|
+
hints.push("Only direct stylesheet requests were tracked during this HMR pass; the wrapper request may be appearing too late.");
|
|
1040
|
+
}
|
|
1041
|
+
return {
|
|
1042
|
+
file: changedFile,
|
|
1043
|
+
sourcePath,
|
|
1044
|
+
source: sourceCode ? describeStylesheetContent(rewriteRelativeCssImports(preprocessStylesheet(sourceCode, normalizedFile, stylePreprocessor), normalizedFile)) : void 0,
|
|
1045
|
+
registry: registryCode ? describeStylesheetContent(registryCode) : void 0,
|
|
1046
|
+
dependencies,
|
|
1047
|
+
diagnostics,
|
|
1048
|
+
tags,
|
|
1049
|
+
directModuleId: directModule.id,
|
|
1050
|
+
directModuleUrl: directModule.url,
|
|
1051
|
+
trackedRequestIds,
|
|
1052
|
+
wrapperCount: wrapperModules.length,
|
|
1053
|
+
anomalies,
|
|
1054
|
+
hints
|
|
1055
|
+
};
|
|
1056
|
+
}
|
|
1057
|
+
async function findComponentStylesheetWrapperModules(server, changedFile, directModule, fileModules, stylesheetRegistry) {
|
|
1058
|
+
const wrapperModules = /* @__PURE__ */ new Map();
|
|
1059
|
+
for (const mod of fileModules) if (mod.id && mod.type === "js" && isComponentStyleSheet(mod.id) && isModuleForChangedResource(mod, changedFile, stylesheetRegistry)) wrapperModules.set(mod.id, mod);
|
|
1060
|
+
const directRequestIds = /* @__PURE__ */ new Set();
|
|
1061
|
+
if (directModule.id) directRequestIds.add(directModule.id);
|
|
1062
|
+
if (directModule.url) directRequestIds.add(directModule.url);
|
|
1063
|
+
const requestPath = directModule.id ? getFilenameFromPath(directModule.id) : void 0;
|
|
1064
|
+
const sourcePath = requestPath ? stylesheetRegistry?.resolveExternalSource(requestPath) ?? stylesheetRegistry?.resolveExternalSource(requestPath.replace(/^\//, "")) ?? stylesheetRegistry?.getServedSourcePath(requestPath) ?? stylesheetRegistry?.getServedSourcePath(requestPath.replace(/^\//, "")) : void 0;
|
|
1065
|
+
for (const requestId of stylesheetRegistry?.getRequestIdsForSource(sourcePath ?? "") ?? []) if (requestId.includes("?ngcomp=")) directRequestIds.add(requestId);
|
|
1066
|
+
const candidateWrapperIds = [...directRequestIds].filter((id) => id.includes("?direct&ngcomp=")).map((id) => id.replace("?direct&ngcomp=", "?ngcomp="));
|
|
1067
|
+
const lookupHits = [];
|
|
1068
|
+
for (const candidate of candidateWrapperIds) {
|
|
1069
|
+
const mod = await server.moduleGraph.getModuleByUrl(candidate) ?? server.moduleGraph.getModuleById(candidate);
|
|
1070
|
+
lookupHits.push({
|
|
1071
|
+
candidate,
|
|
1072
|
+
via: mod?.url === candidate ? "url" : mod ? "id" : void 0,
|
|
1073
|
+
moduleId: mod?.id,
|
|
1074
|
+
moduleType: mod?.type
|
|
720
1075
|
});
|
|
1076
|
+
if (mod?.id && mod.type === "js" && isComponentStyleSheet(mod.id) && isModuleForChangedResource(mod, changedFile, stylesheetRegistry)) wrapperModules.set(mod.id, mod);
|
|
1077
|
+
}
|
|
1078
|
+
debugHmrV("component stylesheet wrapper lookup", {
|
|
1079
|
+
file: changedFile,
|
|
1080
|
+
sourcePath,
|
|
1081
|
+
directModuleId: directModule.id,
|
|
1082
|
+
directModuleUrl: directModule.url,
|
|
1083
|
+
candidateWrapperIds,
|
|
1084
|
+
lookupHits
|
|
721
1085
|
});
|
|
722
|
-
|
|
1086
|
+
if (wrapperModules.size === 0) debugHmrV("component stylesheet wrapper lookup empty", {
|
|
1087
|
+
file: changedFile,
|
|
1088
|
+
sourcePath,
|
|
1089
|
+
directModuleId: directModule.id,
|
|
1090
|
+
directModuleUrl: directModule.url,
|
|
1091
|
+
candidateWrapperIds
|
|
1092
|
+
});
|
|
1093
|
+
return [...wrapperModules.values()];
|
|
723
1094
|
}
|
|
724
1095
|
function sendHMRComponentUpdate(server, id) {
|
|
1096
|
+
debugHmrV("ws send: angular component update", {
|
|
1097
|
+
id,
|
|
1098
|
+
timestamp: Date.now()
|
|
1099
|
+
});
|
|
725
1100
|
server.ws.send("angular:component-update", {
|
|
726
1101
|
id: encodeURIComponent(id),
|
|
727
1102
|
timestamp: Date.now()
|
|
728
1103
|
});
|
|
729
1104
|
classNames.delete(id);
|
|
730
1105
|
}
|
|
731
|
-
function
|
|
1106
|
+
function sendCssUpdate(server, update) {
|
|
1107
|
+
const timestamp = Date.now();
|
|
1108
|
+
debugHmrV("ws send: css-update", {
|
|
1109
|
+
...update,
|
|
1110
|
+
timestamp
|
|
1111
|
+
});
|
|
1112
|
+
server.ws.send({
|
|
1113
|
+
type: "update",
|
|
1114
|
+
updates: [{
|
|
1115
|
+
type: "css-update",
|
|
1116
|
+
timestamp,
|
|
1117
|
+
path: update.path,
|
|
1118
|
+
acceptedPath: update.acceptedPath
|
|
1119
|
+
}]
|
|
1120
|
+
});
|
|
1121
|
+
}
|
|
1122
|
+
function sendFullReload(server, details) {
|
|
1123
|
+
debugHmrV("ws send: full-reload", details);
|
|
1124
|
+
server.ws.send("analog:debug-full-reload", details);
|
|
1125
|
+
server.ws.send({ type: "full-reload" });
|
|
1126
|
+
}
|
|
1127
|
+
function logComponentStylesheetHmrOutcome(details) {
|
|
1128
|
+
const pitfalls = [];
|
|
1129
|
+
const rejectedPreferredPaths = [];
|
|
1130
|
+
const hints = [];
|
|
1131
|
+
if (details.encapsulation === "shadow") {
|
|
1132
|
+
pitfalls.push("shadow-encapsulation");
|
|
1133
|
+
rejectedPreferredPaths.push("css-update");
|
|
1134
|
+
hints.push("Shadow DOM styles cannot rely on Vite CSS patching because Angular applies them inside a shadow root.");
|
|
1135
|
+
}
|
|
1136
|
+
if (details.diagnosis.anomalies.includes("wrapper_not_yet_tracked")) {
|
|
1137
|
+
pitfalls.push("wrapper-not-yet-tracked");
|
|
1138
|
+
rejectedPreferredPaths.push("css-update");
|
|
1139
|
+
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.");
|
|
1140
|
+
}
|
|
1141
|
+
if (details.diagnosis.anomalies.includes("tracked_wrapper_missing_from_module_graph")) {
|
|
1142
|
+
pitfalls.push("tracked-wrapper-missing-from-module-graph");
|
|
1143
|
+
rejectedPreferredPaths.push("css-update");
|
|
1144
|
+
hints.push("A wrapper request id is known, but Vite could not resolve a live wrapper module for targeted CSS HMR.");
|
|
1145
|
+
}
|
|
1146
|
+
debugHmrV("component stylesheet hmr outcome", {
|
|
1147
|
+
file: details.file,
|
|
1148
|
+
outcome: details.outcome,
|
|
1149
|
+
encapsulation: details.encapsulation,
|
|
1150
|
+
directModuleId: details.directModuleId,
|
|
1151
|
+
wrapperIds: details.wrapperIds ?? [],
|
|
1152
|
+
preferredPath: details.encapsulation === "shadow" ? "full-reload" : "css-update",
|
|
1153
|
+
rejectedPreferredPaths: [...new Set(rejectedPreferredPaths)],
|
|
1154
|
+
pitfalls: [...new Set(pitfalls)],
|
|
1155
|
+
anomalies: details.diagnosis.anomalies,
|
|
1156
|
+
hints: [...new Set([...details.diagnosis.hints, ...hints])]
|
|
1157
|
+
});
|
|
1158
|
+
}
|
|
1159
|
+
function findTemplateOwnerModules(server, resourceFile) {
|
|
1160
|
+
const candidateTsFiles = [normalizePath(resourceFile.split("?")[0]).replace(/\.(html|htm)$/i, ".ts")];
|
|
1161
|
+
const modules = /* @__PURE__ */ new Map();
|
|
1162
|
+
for (const candidate of candidateTsFiles) server.moduleGraph.getModulesByFile(candidate)?.forEach((mod) => {
|
|
1163
|
+
if (mod.id) modules.set(mod.id, mod);
|
|
1164
|
+
});
|
|
1165
|
+
return [...modules.values()];
|
|
1166
|
+
}
|
|
1167
|
+
/**
|
|
1168
|
+
* @internal
|
|
1169
|
+
*/
|
|
1170
|
+
function getFileMetadata(program, angularCompiler, hmrEnabled, disableTypeChecking) {
|
|
732
1171
|
const ts = require("typescript");
|
|
733
1172
|
return (file) => {
|
|
734
1173
|
const sourceFile = program.getSourceFile(file);
|
|
@@ -738,12 +1177,17 @@ function getFileMetadata(program, angularCompiler, liveReload, disableTypeChecki
|
|
|
738
1177
|
const warnings = diagnostics.filter((d) => d.category === ts.DiagnosticCategory?.Warning).map((d) => d.messageText);
|
|
739
1178
|
let hmrUpdateCode = void 0;
|
|
740
1179
|
let hmrEligible = false;
|
|
741
|
-
if (
|
|
1180
|
+
if (hmrEnabled) {
|
|
742
1181
|
for (const node of sourceFile.statements) if (ts.isClassDeclaration(node) && node.name != null) {
|
|
743
1182
|
hmrUpdateCode = angularCompiler?.emitHmrUpdateModule(node);
|
|
744
1183
|
if (hmrUpdateCode) {
|
|
745
|
-
|
|
1184
|
+
const className = node.name.getText();
|
|
1185
|
+
classNames.set(file, className);
|
|
746
1186
|
hmrEligible = true;
|
|
1187
|
+
debugHmr("NgtscProgram emitHmrUpdateModule", {
|
|
1188
|
+
file,
|
|
1189
|
+
className
|
|
1190
|
+
});
|
|
747
1191
|
}
|
|
748
1192
|
}
|
|
749
1193
|
}
|
|
@@ -773,40 +1217,18 @@ function markModuleSelfAccepting(mod) {
|
|
|
773
1217
|
isSelfAccepting: true
|
|
774
1218
|
};
|
|
775
1219
|
}
|
|
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
1220
|
/**
|
|
791
1221
|
* Removes leading / and query string from a url path
|
|
792
1222
|
* e.g. /foo.scss?direct&ngcomp=ng-c3153525609&e=0 returns foo.scss
|
|
793
1223
|
* @param id
|
|
794
1224
|
*/
|
|
795
1225
|
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;
|
|
1226
|
+
try {
|
|
1227
|
+
return new URL(id, "http://localhost").pathname.replace(/^\//, "");
|
|
1228
|
+
} catch {
|
|
1229
|
+
const queryIndex = id.indexOf("?");
|
|
1230
|
+
return (queryIndex >= 0 ? id.slice(0, queryIndex) : id).replace(/^\//, "");
|
|
1231
|
+
}
|
|
810
1232
|
}
|
|
811
1233
|
//#endregion
|
|
812
1234
|
export { angular };
|