@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 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rolldown.js","names":[],"sources":["
|
|
1
|
+
{"version":3,"file":"rolldown.js","names":[],"sources":["../../../../src/lib/utils/rolldown.ts"],"sourcesContent":["import * as vite from 'vite';\n\nexport function isRolldown(): boolean {\n return !!vite.rolldownVersion;\n}\n\nexport function getJsTransformConfigKey(): 'oxc' | 'esbuild' {\n return isRolldown() ? 'oxc' : 'esbuild';\n}\n"],"mappings":";;AAEA,SAAgB,aAAsB;AACpC,QAAO,CAAC,CAAC,KAAK;;AAGhB,SAAgB,0BAA6C;AAC3D,QAAO,YAAY,GAAG,QAAQ"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { type ResolvedConfig } from "vite";
|
|
2
|
+
/**
|
|
3
|
+
* Mark a style file path as safe in Vite's `safeModulePaths` set so the
|
|
4
|
+
* `?inline` import passes the Denied ID security check without needing
|
|
5
|
+
* the plugin to intercept the load.
|
|
6
|
+
*
|
|
7
|
+
* Vite's own import-analysis transform does the same thing (adds the clean
|
|
8
|
+
* URL to `safeModulePaths` during transform). We additionally add the
|
|
9
|
+
* `?inline` form because `isServerAccessDeniedForTransform` checks *both*
|
|
10
|
+
* `cleanUrl(id)` and the full `id` (with query) against the allow list.
|
|
11
|
+
*
|
|
12
|
+
* This lets `?inline` CSS flow through Vite's native CSS pipeline, which
|
|
13
|
+
* handles preprocessing, `test.css` semantics, and browser-vs-node
|
|
14
|
+
* differences without the plugin having to reimplement any of it.
|
|
15
|
+
*/
|
|
16
|
+
export declare function markStylePathSafe(config: ResolvedConfig | undefined, absPath: string): void;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { normalizePath } from "vite";
|
|
2
|
+
//#region packages/vite-plugin-angular/src/lib/utils/safe-module-paths.ts
|
|
3
|
+
/**
|
|
4
|
+
* Mark a style file path as safe in Vite's `safeModulePaths` set so the
|
|
5
|
+
* `?inline` import passes the Denied ID security check without needing
|
|
6
|
+
* the plugin to intercept the load.
|
|
7
|
+
*
|
|
8
|
+
* Vite's own import-analysis transform does the same thing (adds the clean
|
|
9
|
+
* URL to `safeModulePaths` during transform). We additionally add the
|
|
10
|
+
* `?inline` form because `isServerAccessDeniedForTransform` checks *both*
|
|
11
|
+
* `cleanUrl(id)` and the full `id` (with query) against the allow list.
|
|
12
|
+
*
|
|
13
|
+
* This lets `?inline` CSS flow through Vite's native CSS pipeline, which
|
|
14
|
+
* handles preprocessing, `test.css` semantics, and browser-vs-node
|
|
15
|
+
* differences without the plugin having to reimplement any of it.
|
|
16
|
+
*/
|
|
17
|
+
function markStylePathSafe(config, absPath) {
|
|
18
|
+
if (!config) return;
|
|
19
|
+
const normalized = normalizePath(absPath);
|
|
20
|
+
const safeModulePaths = config.safeModulePaths;
|
|
21
|
+
if (safeModulePaths) {
|
|
22
|
+
safeModulePaths.add(normalized);
|
|
23
|
+
safeModulePaths.add(normalized + "?inline");
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
//#endregion
|
|
27
|
+
export { markStylePathSafe };
|
|
28
|
+
|
|
29
|
+
//# sourceMappingURL=safe-module-paths.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"safe-module-paths.js","names":[],"sources":["../../../../src/lib/utils/safe-module-paths.ts"],"sourcesContent":["import { normalizePath, type ResolvedConfig } from 'vite';\n\n/**\n * Mark a style file path as safe in Vite's `safeModulePaths` set so the\n * `?inline` import passes the Denied ID security check without needing\n * the plugin to intercept the load.\n *\n * Vite's own import-analysis transform does the same thing (adds the clean\n * URL to `safeModulePaths` during transform). We additionally add the\n * `?inline` form because `isServerAccessDeniedForTransform` checks *both*\n * `cleanUrl(id)` and the full `id` (with query) against the allow list.\n *\n * This lets `?inline` CSS flow through Vite's native CSS pipeline, which\n * handles preprocessing, `test.css` semantics, and browser-vs-node\n * differences without the plugin having to reimplement any of it.\n */\nexport function markStylePathSafe(\n config: ResolvedConfig | undefined,\n absPath: string,\n): void {\n if (!config) return;\n const normalized = normalizePath(absPath);\n const safeModulePaths = (config as any).safeModulePaths as\n | Set<string>\n | undefined;\n if (safeModulePaths) {\n safeModulePaths.add(normalized);\n safeModulePaths.add(normalized + '?inline');\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAgBA,SAAgB,kBACd,QACA,SACM;AACN,KAAI,CAAC,OAAQ;CACb,MAAM,aAAa,cAAc,QAAQ;CACzC,MAAM,kBAAmB,OAAe;AAGxC,KAAI,iBAAiB;AACnB,kBAAgB,IAAI,WAAW;AAC/B,kBAAgB,IAAI,aAAa,UAAU"}
|
|
@@ -1,17 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
* @license
|
|
3
|
-
* Copyright Google LLC All Rights Reserved.
|
|
4
|
-
*
|
|
5
|
-
* Use of this source code is governed by an MIT-style license that can be
|
|
6
|
-
* found in the LICENSE file at https://angular.io/license
|
|
7
|
-
*/
|
|
8
|
-
import type ts from 'typescript';
|
|
1
|
+
import type ts from "typescript";
|
|
9
2
|
export declare class SourceFileCache extends Map<string, ts.SourceFile> {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
3
|
+
readonly persistentCachePath?: string | undefined;
|
|
4
|
+
readonly modifiedFiles: Set<string>;
|
|
5
|
+
readonly babelFileCache: Map<string, Uint8Array>;
|
|
6
|
+
readonly typeScriptFileCache: Map<string, string | Uint8Array>;
|
|
7
|
+
referencedFiles?: readonly string[];
|
|
8
|
+
constructor(persistentCachePath?: string | undefined);
|
|
9
|
+
invalidate(files: Iterable<string>): void;
|
|
17
10
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"source-file-cache.js","names":[],"sources":["
|
|
1
|
+
{"version":3,"file":"source-file-cache.js","names":[],"sources":["../../../../src/lib/utils/source-file-cache.ts"],"sourcesContent":["/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport { platform } from 'node:os';\nimport * as path from 'node:path';\nimport { pathToFileURL } from 'node:url';\nimport type ts from 'typescript';\n\nconst USING_WINDOWS = platform() === 'win32';\nconst WINDOWS_SEP_REGEXP = new RegExp(`\\\\${path.win32.sep}`, 'g');\n\nexport class SourceFileCache extends Map<string, ts.SourceFile> {\n readonly modifiedFiles: Set<string> = new Set<string>();\n readonly babelFileCache: Map<string, Uint8Array> = new Map<\n string,\n Uint8Array\n >();\n readonly typeScriptFileCache: Map<string, string | Uint8Array> = new Map<\n string,\n string | Uint8Array\n >();\n\n referencedFiles?: readonly string[];\n\n constructor(readonly persistentCachePath?: string) {\n super();\n }\n\n invalidate(files: Iterable<string>): void {\n if (files !== this.modifiedFiles) {\n this.modifiedFiles.clear();\n }\n for (let file of files) {\n this.babelFileCache.delete(file);\n this.typeScriptFileCache.delete(pathToFileURL(file).href);\n\n // Normalize separators to allow matching TypeScript Host paths\n if (USING_WINDOWS) {\n file = file.replace(WINDOWS_SEP_REGEXP, path.posix.sep);\n }\n\n this.delete(file);\n this.modifiedFiles.add(file);\n }\n }\n}\n"],"mappings":";;;;;;;;;;;AAaA,IAAM,gBAAgB,UAAU,KAAK;AACrC,IAAM,qBAAqB,IAAI,OAAO,KAAK,OAAK,MAAM,OAAO,IAAI;AAEjE,IAAa,kBAAb,cAAqC,IAA2B;CAC9D,gCAAsC,IAAI,KAAa;CACvD,iCAAmD,IAAI,KAGpD;CACH,sCAAiE,IAAI,KAGlE;CAEH;CAEA,YAAY,qBAAuC;AACjD,SAAO;AADY,OAAA,sBAAA;;CAIrB,WAAW,OAA+B;AACxC,MAAI,UAAU,KAAK,cACjB,MAAK,cAAc,OAAO;AAE5B,OAAK,IAAI,QAAQ,OAAO;AACtB,QAAK,eAAe,OAAO,KAAK;AAChC,QAAK,oBAAoB,OAAO,cAAc,KAAK,CAAC,KAAK;AAGzD,OAAI,cACF,QAAO,KAAK,QAAQ,oBAAoB,OAAK,MAAM,IAAI;AAGzD,QAAK,OAAO,KAAK;AACjB,QAAK,cAAc,IAAI,KAAK"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `{ get, put }` shape `@angular/build`'s `JavaScriptTransformer`
|
|
3
|
+
* accepts. Keys are content hashes the
|
|
4
|
+
* transformer derives from the file bytes plus every option that affects
|
|
5
|
+
* output, so entries are immutable and never need invalidation — but the
|
|
6
|
+
* digest does NOT cover the linker version, so stores must be namespaced
|
|
7
|
+
* by Angular version (see {@link resolveTransformCacheDir}).
|
|
8
|
+
*/
|
|
9
|
+
export interface TransformCacheStore {
|
|
10
|
+
get(key: string): Promise<Uint8Array | undefined> | Uint8Array | undefined;
|
|
11
|
+
put(key: string, value: Uint8Array): Promise<void> | void;
|
|
12
|
+
}
|
|
13
|
+
interface TransformCacheStats {
|
|
14
|
+
hits: number;
|
|
15
|
+
misses: number;
|
|
16
|
+
writes: number;
|
|
17
|
+
/** Approximate total ms spent in the linker worker for cache misses. */
|
|
18
|
+
workerMs: number;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Disk-backed content-addressed store for linked/transformed dependency
|
|
22
|
+
* output. Entries are written atomically (temp + rename) so concurrent
|
|
23
|
+
* dev servers can share a directory; all failures degrade to a miss.
|
|
24
|
+
*/
|
|
25
|
+
export declare function createPersistentTransformCache(baseDir: string): TransformCacheStore & {
|
|
26
|
+
stats: TransformCacheStats;
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* Layer an unbounded in-memory map over a persistent store so repeat
|
|
30
|
+
* transforms in the same session never touch the disk.
|
|
31
|
+
*/
|
|
32
|
+
export declare function withMemoryLayer(store: TransformCacheStore): TransformCacheStore;
|
|
33
|
+
/**
|
|
34
|
+
* Resolve the shared on-disk cache directory: `node_modules/.cache` at the
|
|
35
|
+
* nearest `node_modules` above `startDir` — the conventional tool-cache
|
|
36
|
+
* location, so installs and `node_modules` cleans evict it without a
|
|
37
|
+
* separate eviction pass. Namespaced by the installed Angular version
|
|
38
|
+
* because the transformer's cache key does not cover the linker version.
|
|
39
|
+
* Returns `null` (caching disabled) when no `node_modules` exists or the
|
|
40
|
+
* `ANALOG_TRANSFORM_CACHE=0` kill switch is set.
|
|
41
|
+
*/
|
|
42
|
+
export declare function resolveTransformCacheDir(startDir: string): string | null;
|
|
43
|
+
export {};
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import * as crypto from "node:crypto";
|
|
2
|
+
import * as fs from "node:fs";
|
|
3
|
+
import * as path$1 from "node:path";
|
|
4
|
+
import { createDebug } from "obug";
|
|
5
|
+
import { VERSION } from "@angular/compiler";
|
|
6
|
+
//#region packages/vite-plugin-angular/src/lib/utils/transform-cache.ts
|
|
7
|
+
var debugCache = createDebug("analog-transform-cache");
|
|
8
|
+
/**
|
|
9
|
+
* Disk-backed content-addressed store for linked/transformed dependency
|
|
10
|
+
* output. Entries are written atomically (temp + rename) so concurrent
|
|
11
|
+
* dev servers can share a directory; all failures degrade to a miss.
|
|
12
|
+
*/
|
|
13
|
+
function createPersistentTransformCache(baseDir) {
|
|
14
|
+
const stats = {
|
|
15
|
+
hits: 0,
|
|
16
|
+
misses: 0,
|
|
17
|
+
writes: 0,
|
|
18
|
+
workerMs: 0
|
|
19
|
+
};
|
|
20
|
+
const missedAt = /* @__PURE__ */ new Map();
|
|
21
|
+
const entryPath = (key) => path$1.join(baseDir, key.slice(0, 2), key);
|
|
22
|
+
return {
|
|
23
|
+
stats,
|
|
24
|
+
async get(key) {
|
|
25
|
+
try {
|
|
26
|
+
const value = await fs.promises.readFile(entryPath(key));
|
|
27
|
+
stats.hits++;
|
|
28
|
+
debugCache("hit %s (hits=%d misses=%d)", key, stats.hits, stats.misses);
|
|
29
|
+
return value;
|
|
30
|
+
} catch {
|
|
31
|
+
stats.misses++;
|
|
32
|
+
missedAt.set(key, performance.now());
|
|
33
|
+
debugCache("miss %s (hits=%d misses=%d)", key, stats.hits, stats.misses);
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
async put(key, value) {
|
|
38
|
+
const startedAt = missedAt.get(key);
|
|
39
|
+
if (startedAt !== void 0) {
|
|
40
|
+
missedAt.delete(key);
|
|
41
|
+
stats.workerMs += performance.now() - startedAt;
|
|
42
|
+
}
|
|
43
|
+
try {
|
|
44
|
+
const file = entryPath(key);
|
|
45
|
+
await fs.promises.mkdir(path$1.dirname(file), { recursive: true });
|
|
46
|
+
const tmp = `${file}.${process.pid}.${crypto.randomBytes(4).toString("hex")}`;
|
|
47
|
+
await fs.promises.writeFile(tmp, value);
|
|
48
|
+
await fs.promises.rename(tmp, file);
|
|
49
|
+
stats.writes++;
|
|
50
|
+
debugCache("put %s (writes=%d workerMs=%d)", key, stats.writes, Math.round(stats.workerMs));
|
|
51
|
+
} catch (e) {
|
|
52
|
+
debugCache("put failed %s: %s", key, e?.message);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Layer an unbounded in-memory map over a persistent store so repeat
|
|
59
|
+
* transforms in the same session never touch the disk.
|
|
60
|
+
*/
|
|
61
|
+
function withMemoryLayer(store) {
|
|
62
|
+
const memory = /* @__PURE__ */ new Map();
|
|
63
|
+
return {
|
|
64
|
+
async get(key) {
|
|
65
|
+
const cached = memory.get(key) ?? await store.get(key);
|
|
66
|
+
if (cached) memory.set(key, cached);
|
|
67
|
+
return cached;
|
|
68
|
+
},
|
|
69
|
+
async put(key, value) {
|
|
70
|
+
memory.set(key, value);
|
|
71
|
+
await store.put(key, value);
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Resolve the shared on-disk cache directory: `node_modules/.cache` at the
|
|
77
|
+
* nearest `node_modules` above `startDir` — the conventional tool-cache
|
|
78
|
+
* location, so installs and `node_modules` cleans evict it without a
|
|
79
|
+
* separate eviction pass. Namespaced by the installed Angular version
|
|
80
|
+
* because the transformer's cache key does not cover the linker version.
|
|
81
|
+
* Returns `null` (caching disabled) when no `node_modules` exists or the
|
|
82
|
+
* `ANALOG_TRANSFORM_CACHE=0` kill switch is set.
|
|
83
|
+
*/
|
|
84
|
+
function resolveTransformCacheDir(startDir) {
|
|
85
|
+
if (process.env["ANALOG_TRANSFORM_CACHE"] === "0") return null;
|
|
86
|
+
let dir = path$1.resolve(startDir);
|
|
87
|
+
for (;;) {
|
|
88
|
+
if (fs.existsSync(path$1.join(dir, "node_modules"))) return path$1.join(dir, "node_modules", ".cache", "analog", "transform-cache", VERSION.full);
|
|
89
|
+
const parent = path$1.dirname(dir);
|
|
90
|
+
if (parent === dir) return null;
|
|
91
|
+
dir = parent;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
//#endregion
|
|
95
|
+
export { createPersistentTransformCache, resolveTransformCacheDir, withMemoryLayer };
|
|
96
|
+
|
|
97
|
+
//# sourceMappingURL=transform-cache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transform-cache.js","names":[],"sources":["../../../../src/lib/utils/transform-cache.ts"],"sourcesContent":["import * as fs from 'node:fs';\nimport * as path from 'node:path';\nimport * as crypto from 'node:crypto';\nimport { VERSION } from '@angular/compiler';\nimport { createDebug } from 'obug';\n\nconst debugCache = createDebug('analog-transform-cache');\n\n/**\n * The `{ get, put }` shape `@angular/build`'s `JavaScriptTransformer`\n * accepts. Keys are content hashes the\n * transformer derives from the file bytes plus every option that affects\n * output, so entries are immutable and never need invalidation — but the\n * digest does NOT cover the linker version, so stores must be namespaced\n * by Angular version (see {@link resolveTransformCacheDir}).\n */\nexport interface TransformCacheStore {\n get(key: string): Promise<Uint8Array | undefined> | Uint8Array | undefined;\n put(key: string, value: Uint8Array): Promise<void> | void;\n}\n\ninterface TransformCacheStats {\n hits: number;\n misses: number;\n writes: number;\n /** Approximate total ms spent in the linker worker for cache misses. */\n workerMs: number;\n}\n\n/**\n * Disk-backed content-addressed store for linked/transformed dependency\n * output. Entries are written atomically (temp + rename) so concurrent\n * dev servers can share a directory; all failures degrade to a miss.\n */\nexport function createPersistentTransformCache(\n baseDir: string,\n): TransformCacheStore & { stats: TransformCacheStats } {\n const stats: TransformCacheStats = {\n hits: 0,\n misses: 0,\n writes: 0,\n workerMs: 0,\n };\n // Miss timestamps by key: with the transformer's serialized worker, the\n // gap between a missed get and its put approximates linker time per file.\n const missedAt = new Map<string, number>();\n\n const entryPath = (key: string) => path.join(baseDir, key.slice(0, 2), key);\n\n return {\n stats,\n async get(key: string): Promise<Uint8Array | undefined> {\n try {\n const value = await fs.promises.readFile(entryPath(key));\n stats.hits++;\n debugCache('hit %s (hits=%d misses=%d)', key, stats.hits, stats.misses);\n return value;\n } catch {\n stats.misses++;\n missedAt.set(key, performance.now());\n debugCache(\n 'miss %s (hits=%d misses=%d)',\n key,\n stats.hits,\n stats.misses,\n );\n return undefined;\n }\n },\n async put(key: string, value: Uint8Array): Promise<void> {\n const startedAt = missedAt.get(key);\n if (startedAt !== undefined) {\n missedAt.delete(key);\n stats.workerMs += performance.now() - startedAt;\n }\n try {\n const file = entryPath(key);\n await fs.promises.mkdir(path.dirname(file), { recursive: true });\n const tmp = `${file}.${process.pid}.${crypto.randomBytes(4).toString('hex')}`;\n await fs.promises.writeFile(tmp, value);\n await fs.promises.rename(tmp, file);\n stats.writes++;\n debugCache(\n 'put %s (writes=%d workerMs=%d)',\n key,\n stats.writes,\n Math.round(stats.workerMs),\n );\n } catch (e) {\n debugCache('put failed %s: %s', key, (e as Error)?.message);\n }\n },\n };\n}\n\n/**\n * Layer an unbounded in-memory map over a persistent store so repeat\n * transforms in the same session never touch the disk.\n */\nexport function withMemoryLayer(\n store: TransformCacheStore,\n): TransformCacheStore {\n const memory = new Map<string, Uint8Array>();\n return {\n async get(key: string): Promise<Uint8Array | undefined> {\n const cached = memory.get(key) ?? (await store.get(key));\n if (cached) memory.set(key, cached);\n return cached;\n },\n async put(key: string, value: Uint8Array): Promise<void> {\n memory.set(key, value);\n await store.put(key, value);\n },\n };\n}\n\n/**\n * Resolve the shared on-disk cache directory: `node_modules/.cache` at the\n * nearest `node_modules` above `startDir` — the conventional tool-cache\n * location, so installs and `node_modules` cleans evict it without a\n * separate eviction pass. Namespaced by the installed Angular version\n * because the transformer's cache key does not cover the linker version.\n * Returns `null` (caching disabled) when no `node_modules` exists or the\n * `ANALOG_TRANSFORM_CACHE=0` kill switch is set.\n */\nexport function resolveTransformCacheDir(startDir: string): string | null {\n if (process.env['ANALOG_TRANSFORM_CACHE'] === '0') return null;\n let dir = path.resolve(startDir);\n for (;;) {\n if (fs.existsSync(path.join(dir, 'node_modules'))) {\n return path.join(\n dir,\n 'node_modules',\n '.cache',\n 'analog',\n 'transform-cache',\n VERSION.full,\n );\n }\n const parent = path.dirname(dir);\n if (parent === dir) return null;\n dir = parent;\n }\n}\n"],"mappings":";;;;;;AAMA,IAAM,aAAa,YAAY,yBAAyB;;;;;;AA4BxD,SAAgB,+BACd,SACsD;CACtD,MAAM,QAA6B;EACjC,MAAM;EACN,QAAQ;EACR,QAAQ;EACR,UAAU;EACX;CAGD,MAAM,2BAAW,IAAI,KAAqB;CAE1C,MAAM,aAAa,QAAgB,OAAK,KAAK,SAAS,IAAI,MAAM,GAAG,EAAE,EAAE,IAAI;AAE3E,QAAO;EACL;EACA,MAAM,IAAI,KAA8C;AACtD,OAAI;IACF,MAAM,QAAQ,MAAM,GAAG,SAAS,SAAS,UAAU,IAAI,CAAC;AACxD,UAAM;AACN,eAAW,8BAA8B,KAAK,MAAM,MAAM,MAAM,OAAO;AACvE,WAAO;WACD;AACN,UAAM;AACN,aAAS,IAAI,KAAK,YAAY,KAAK,CAAC;AACpC,eACE,+BACA,KACA,MAAM,MACN,MAAM,OACP;AACD;;;EAGJ,MAAM,IAAI,KAAa,OAAkC;GACvD,MAAM,YAAY,SAAS,IAAI,IAAI;AACnC,OAAI,cAAc,KAAA,GAAW;AAC3B,aAAS,OAAO,IAAI;AACpB,UAAM,YAAY,YAAY,KAAK,GAAG;;AAExC,OAAI;IACF,MAAM,OAAO,UAAU,IAAI;AAC3B,UAAM,GAAG,SAAS,MAAM,OAAK,QAAQ,KAAK,EAAE,EAAE,WAAW,MAAM,CAAC;IAChE,MAAM,MAAM,GAAG,KAAK,GAAG,QAAQ,IAAI,GAAG,OAAO,YAAY,EAAE,CAAC,SAAS,MAAM;AAC3E,UAAM,GAAG,SAAS,UAAU,KAAK,MAAM;AACvC,UAAM,GAAG,SAAS,OAAO,KAAK,KAAK;AACnC,UAAM;AACN,eACE,kCACA,KACA,MAAM,QACN,KAAK,MAAM,MAAM,SAAS,CAC3B;YACM,GAAG;AACV,eAAW,qBAAqB,KAAM,GAAa,QAAQ;;;EAGhE;;;;;;AAOH,SAAgB,gBACd,OACqB;CACrB,MAAM,yBAAS,IAAI,KAAyB;AAC5C,QAAO;EACL,MAAM,IAAI,KAA8C;GACtD,MAAM,SAAS,OAAO,IAAI,IAAI,IAAK,MAAM,MAAM,IAAI,IAAI;AACvD,OAAI,OAAQ,QAAO,IAAI,KAAK,OAAO;AACnC,UAAO;;EAET,MAAM,IAAI,KAAa,OAAkC;AACvD,UAAO,IAAI,KAAK,MAAM;AACtB,SAAM,MAAM,IAAI,KAAK,MAAM;;EAE9B;;;;;;;;;;;AAYH,SAAgB,yBAAyB,UAAiC;AACxE,KAAI,QAAQ,IAAI,8BAA8B,IAAK,QAAO;CAC1D,IAAI,MAAM,OAAK,QAAQ,SAAS;AAChC,UAAS;AACP,MAAI,GAAG,WAAW,OAAK,KAAK,KAAK,eAAe,CAAC,CAC/C,QAAO,OAAK,KACV,KACA,gBACA,UACA,UACA,mBACA,QAAQ,KACT;EAEH,MAAM,SAAS,OAAK,QAAQ,IAAI;AAChC,MAAI,WAAW,IAAK,QAAO;AAC3B,QAAM"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { ResolvedConfig } from "vite";
|
|
2
|
+
export interface TsconfigResolverOptions {
|
|
3
|
+
workspaceRoot: string;
|
|
4
|
+
include: string[];
|
|
5
|
+
liveReload: boolean;
|
|
6
|
+
isTest: boolean;
|
|
7
|
+
}
|
|
8
|
+
export declare class TsconfigResolver {
|
|
9
|
+
private options;
|
|
10
|
+
private includeCache;
|
|
11
|
+
private tsconfigOptionsCache;
|
|
12
|
+
private tsconfigGraphRootCache;
|
|
13
|
+
private integrationIncludes;
|
|
14
|
+
constructor(options: TsconfigResolverOptions);
|
|
15
|
+
/**
|
|
16
|
+
* Replaces the include globs contributed by Vite plugins through
|
|
17
|
+
* `analog.setup()`. Invalidates the include cache when the set changes.
|
|
18
|
+
*/
|
|
19
|
+
setIntegrationIncludes(globs: string[]): void;
|
|
20
|
+
private get includeGlobs();
|
|
21
|
+
invalidateIncludeCache(): void;
|
|
22
|
+
invalidateTsconfigCaches(): void;
|
|
23
|
+
invalidateAll(): void;
|
|
24
|
+
ensureIncludeCache(): string[];
|
|
25
|
+
readAngularTsconfigConfiguration(resolvedTsConfigPath: string, config: ResolvedConfig);
|
|
26
|
+
getCachedTsconfigOptions(resolvedTsConfigPath: string, config: ResolvedConfig): {
|
|
27
|
+
options: any;
|
|
28
|
+
rootNames: string[];
|
|
29
|
+
};
|
|
30
|
+
collectExpandedTsconfigRoots(resolvedTsConfigPath: string, config: ResolvedConfig, visited?): string[];
|
|
31
|
+
private getTsconfigCacheKey;
|
|
32
|
+
private findIncludes;
|
|
33
|
+
}
|
|
34
|
+
export declare function normalizeIncludeGlob(workspaceRoot: string, glob: string): string;
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
import { debugEmit, debugEmitV } from "./debug.js";
|
|
2
|
+
import { existsSync, statSync } from "node:fs";
|
|
3
|
+
import { dirname, isAbsolute, join, resolve } from "node:path";
|
|
4
|
+
import { createRequire } from "node:module";
|
|
5
|
+
import { normalizePath } from "vite";
|
|
6
|
+
import * as compilerCli from "@angular/compiler-cli";
|
|
7
|
+
import { globSync } from "tinyglobby";
|
|
8
|
+
//#region packages/vite-plugin-angular/src/lib/utils/tsconfig-resolver.ts
|
|
9
|
+
/**
|
|
10
|
+
* Shared tsconfig resolution logic used by both the ngtsc and compilation-api
|
|
11
|
+
* compilation plugins. Encapsulates the caching, include-glob discovery,
|
|
12
|
+
* tsconfig-graph expansion, and path-root resolution that were previously
|
|
13
|
+
* duplicated across angular-vite-plugin.ts and compilation-api-plugin.ts.
|
|
14
|
+
*/
|
|
15
|
+
var ts = createRequire(import.meta.url)("typescript");
|
|
16
|
+
var TsconfigResolver = class {
|
|
17
|
+
includeCache = [];
|
|
18
|
+
tsconfigOptionsCache = /* @__PURE__ */ new Map();
|
|
19
|
+
tsconfigGraphRootCache = /* @__PURE__ */ new Map();
|
|
20
|
+
integrationIncludes = [];
|
|
21
|
+
constructor(options) {
|
|
22
|
+
this.options = options;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Replaces the include globs contributed by Vite plugins through
|
|
26
|
+
* `analog.setup()`. Invalidates the include cache when the set changes.
|
|
27
|
+
*/
|
|
28
|
+
setIntegrationIncludes(globs) {
|
|
29
|
+
if (globs.length === this.integrationIncludes.length && globs.every((glob, index) => glob === this.integrationIncludes[index])) return;
|
|
30
|
+
this.integrationIncludes = [...globs];
|
|
31
|
+
this.invalidateIncludeCache();
|
|
32
|
+
}
|
|
33
|
+
get includeGlobs() {
|
|
34
|
+
return [...this.options.include, ...this.integrationIncludes];
|
|
35
|
+
}
|
|
36
|
+
invalidateIncludeCache() {
|
|
37
|
+
this.includeCache = [];
|
|
38
|
+
}
|
|
39
|
+
invalidateTsconfigCaches() {
|
|
40
|
+
this.tsconfigOptionsCache.clear();
|
|
41
|
+
this.tsconfigGraphRootCache.clear();
|
|
42
|
+
}
|
|
43
|
+
invalidateAll() {
|
|
44
|
+
this.invalidateIncludeCache();
|
|
45
|
+
this.invalidateTsconfigCaches();
|
|
46
|
+
}
|
|
47
|
+
ensureIncludeCache() {
|
|
48
|
+
if (this.includeGlobs.length > 0 && this.includeCache.length === 0) {
|
|
49
|
+
this.includeCache = this.findIncludes();
|
|
50
|
+
debugEmit("include cache populated", { fileCount: this.includeCache.length });
|
|
51
|
+
}
|
|
52
|
+
return this.includeCache;
|
|
53
|
+
}
|
|
54
|
+
readAngularTsconfigConfiguration(resolvedTsConfigPath, config) {
|
|
55
|
+
const emitSourceMaps = !(config.mode === "production") || !!config.build?.sourcemap;
|
|
56
|
+
return compilerCli.readConfiguration(resolvedTsConfigPath, {
|
|
57
|
+
suppressOutputPathCheck: true,
|
|
58
|
+
outDir: void 0,
|
|
59
|
+
sourceMap: emitSourceMaps,
|
|
60
|
+
inlineSourceMap: false,
|
|
61
|
+
inlineSources: emitSourceMaps,
|
|
62
|
+
declaration: false,
|
|
63
|
+
declarationMap: false,
|
|
64
|
+
allowEmptyCodegenFiles: false,
|
|
65
|
+
annotationsAs: "decorators",
|
|
66
|
+
enableResourceInlining: false,
|
|
67
|
+
noEmitOnError: false,
|
|
68
|
+
mapRoot: "",
|
|
69
|
+
sourceRoot: "",
|
|
70
|
+
supportTestBed: false,
|
|
71
|
+
supportJitMode: false
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
getCachedTsconfigOptions(resolvedTsConfigPath, config) {
|
|
75
|
+
const tsconfigKey = this.getTsconfigCacheKey(resolvedTsConfigPath, config);
|
|
76
|
+
let cached = this.tsconfigOptionsCache.get(tsconfigKey);
|
|
77
|
+
if (!cached) {
|
|
78
|
+
const read = this.readAngularTsconfigConfiguration(resolvedTsConfigPath, config);
|
|
79
|
+
cached = {
|
|
80
|
+
options: read.options,
|
|
81
|
+
rootNames: read.rootNames
|
|
82
|
+
};
|
|
83
|
+
this.tsconfigOptionsCache.set(tsconfigKey, cached);
|
|
84
|
+
debugEmit("tsconfig root names loaded", {
|
|
85
|
+
resolvedTsConfigPath,
|
|
86
|
+
rootNameCount: read.rootNames.length
|
|
87
|
+
});
|
|
88
|
+
debugEmitV("tsconfig root names", {
|
|
89
|
+
resolvedTsConfigPath,
|
|
90
|
+
rootNames: read.rootNames.map((file) => normalizePath(file))
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
return cached;
|
|
94
|
+
}
|
|
95
|
+
collectExpandedTsconfigRoots(resolvedTsConfigPath, config, visited = /* @__PURE__ */ new Set()) {
|
|
96
|
+
const normalizedTsConfigPath = normalizePath(resolvedTsConfigPath);
|
|
97
|
+
if (visited.has(normalizedTsConfigPath)) return [];
|
|
98
|
+
const tsconfigKey = `${this.getTsconfigCacheKey(normalizedTsConfigPath, config)}|graph`;
|
|
99
|
+
const cached = this.tsconfigGraphRootCache.get(tsconfigKey);
|
|
100
|
+
if (cached) return cached;
|
|
101
|
+
visited.add(normalizedTsConfigPath);
|
|
102
|
+
const read = this.readAngularTsconfigConfiguration(normalizedTsConfigPath, config);
|
|
103
|
+
const rawTsconfig = ts.readConfigFile(normalizedTsConfigPath, ts.sys.readFile).config ?? {};
|
|
104
|
+
const expandedRoots = new Set(read.rootNames.map((file) => normalizePath(file)));
|
|
105
|
+
const pathRoots = collectTsconfigPathRoots(normalizedTsConfigPath, read.options, rawTsconfig);
|
|
106
|
+
for (const pathRoot of pathRoots) expandedRoots.add(pathRoot);
|
|
107
|
+
const referenceConfigs = (rawTsconfig.references ?? []).flatMap((reference) => typeof reference.path === "string" ? [resolveReferenceTsconfigPath(reference.path, normalizedTsConfigPath)] : []).filter((reference) => !!reference);
|
|
108
|
+
for (const referenceConfig of referenceConfigs) for (const referenceRoot of this.collectExpandedTsconfigRoots(referenceConfig, config, visited)) expandedRoots.add(referenceRoot);
|
|
109
|
+
const expandedRootList = [...expandedRoots];
|
|
110
|
+
this.tsconfigGraphRootCache.set(tsconfigKey, expandedRootList);
|
|
111
|
+
debugEmit("expanded tsconfig graph roots", {
|
|
112
|
+
resolvedTsConfigPath: normalizedTsConfigPath,
|
|
113
|
+
directRootNameCount: read.rootNames.length,
|
|
114
|
+
pathRootCount: pathRoots.length,
|
|
115
|
+
referenceConfigCount: referenceConfigs.length,
|
|
116
|
+
expandedRootCount: expandedRootList.length
|
|
117
|
+
});
|
|
118
|
+
debugEmitV("expanded tsconfig graph root files", {
|
|
119
|
+
resolvedTsConfigPath: normalizedTsConfigPath,
|
|
120
|
+
pathRoots,
|
|
121
|
+
referenceConfigs,
|
|
122
|
+
rootNames: expandedRootList
|
|
123
|
+
});
|
|
124
|
+
return expandedRootList;
|
|
125
|
+
}
|
|
126
|
+
getTsconfigCacheKey(resolvedTsConfigPath, config) {
|
|
127
|
+
const isProd = config.mode === "production";
|
|
128
|
+
return [
|
|
129
|
+
resolvedTsConfigPath,
|
|
130
|
+
isProd ? "prod" : "dev",
|
|
131
|
+
this.options.isTest ? "test" : "app",
|
|
132
|
+
config.build?.lib ? "lib" : "nolib",
|
|
133
|
+
!isProd || config.build?.sourcemap ? "maps" : "nomaps",
|
|
134
|
+
this.options.liveReload ? "live-reload" : "no-live-reload"
|
|
135
|
+
].join("|");
|
|
136
|
+
}
|
|
137
|
+
findIncludes() {
|
|
138
|
+
const globs = this.includeGlobs.map((glob) => normalizeIncludeGlob(this.options.workspaceRoot, glob));
|
|
139
|
+
const files = globSync(globs, {
|
|
140
|
+
dot: true,
|
|
141
|
+
absolute: true
|
|
142
|
+
});
|
|
143
|
+
debugEmit("include discovery", {
|
|
144
|
+
patternCount: globs.length,
|
|
145
|
+
fileCount: files.length
|
|
146
|
+
});
|
|
147
|
+
debugEmitV("include discovery files", {
|
|
148
|
+
globs,
|
|
149
|
+
files: files.map((file) => normalizePath(file))
|
|
150
|
+
});
|
|
151
|
+
return files;
|
|
152
|
+
}
|
|
153
|
+
};
|
|
154
|
+
function normalizeIncludeGlob(workspaceRoot, glob) {
|
|
155
|
+
const normalizedWorkspaceRoot = normalizePath(resolve(workspaceRoot));
|
|
156
|
+
const normalizedGlob = normalizePath(glob);
|
|
157
|
+
if (normalizedGlob === normalizedWorkspaceRoot || normalizedGlob.startsWith(`${normalizedWorkspaceRoot}/`)) return normalizedGlob;
|
|
158
|
+
if (normalizedGlob.startsWith("/")) return `${normalizedWorkspaceRoot}${normalizedGlob}`;
|
|
159
|
+
return normalizePath(resolve(normalizedWorkspaceRoot, normalizedGlob));
|
|
160
|
+
}
|
|
161
|
+
function resolveReferenceTsconfigPath(referencePath, ownerTsconfigPath) {
|
|
162
|
+
const ownerDir = dirname(ownerTsconfigPath);
|
|
163
|
+
const resolvedReference = normalizePath(isAbsolute(referencePath) ? referencePath : resolve(ownerDir, referencePath));
|
|
164
|
+
if (existsSync(resolvedReference)) {
|
|
165
|
+
try {
|
|
166
|
+
if (statSync(resolvedReference).isDirectory()) {
|
|
167
|
+
const nestedTsconfig = join(resolvedReference, "tsconfig.json");
|
|
168
|
+
return existsSync(nestedTsconfig) ? normalizePath(nestedTsconfig) : void 0;
|
|
169
|
+
}
|
|
170
|
+
} catch {
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
return resolvedReference;
|
|
174
|
+
}
|
|
175
|
+
if (!resolvedReference.endsWith(".json")) {
|
|
176
|
+
const asJson = `${resolvedReference}.json`;
|
|
177
|
+
if (existsSync(asJson)) return normalizePath(asJson);
|
|
178
|
+
const nestedTsconfig = join(resolvedReference, "tsconfig.json");
|
|
179
|
+
if (existsSync(nestedTsconfig)) return normalizePath(nestedTsconfig);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
function collectTsconfigPathRoots(resolvedTsConfigPath, options, rawTsconfig) {
|
|
183
|
+
const tsPaths = rawTsconfig.compilerOptions?.paths ?? options.paths;
|
|
184
|
+
if (!tsPaths) return [];
|
|
185
|
+
const tsconfigDir = dirname(resolvedTsConfigPath);
|
|
186
|
+
const configuredBaseUrl = typeof options.baseUrl === "string" ? options.baseUrl : typeof rawTsconfig.compilerOptions?.baseUrl === "string" ? rawTsconfig.compilerOptions.baseUrl : void 0;
|
|
187
|
+
const resolvedBaseUrl = configuredBaseUrl ? isAbsolute(configuredBaseUrl) ? configuredBaseUrl : resolve(tsconfigDir, configuredBaseUrl) : tsconfigDir;
|
|
188
|
+
const discoveredRoots = /* @__PURE__ */ new Set();
|
|
189
|
+
for (const targets of Object.values(tsPaths)) for (const target of targets) {
|
|
190
|
+
const resolvedTarget = normalizePath(isAbsolute(target) ? target : resolve(resolvedBaseUrl, target));
|
|
191
|
+
if (target.includes("*")) {
|
|
192
|
+
for (const match of globSync(resolvedTarget, {
|
|
193
|
+
dot: true,
|
|
194
|
+
absolute: true
|
|
195
|
+
})) discoveredRoots.add(normalizePath(match));
|
|
196
|
+
continue;
|
|
197
|
+
}
|
|
198
|
+
if (existsSync(resolvedTarget)) discoveredRoots.add(resolvedTarget);
|
|
199
|
+
}
|
|
200
|
+
return [...discoveredRoots];
|
|
201
|
+
}
|
|
202
|
+
//#endregion
|
|
203
|
+
export { TsconfigResolver };
|
|
204
|
+
|
|
205
|
+
//# sourceMappingURL=tsconfig-resolver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tsconfig-resolver.js","names":[],"sources":["../../../../src/lib/utils/tsconfig-resolver.ts"],"sourcesContent":["/**\n * Shared tsconfig resolution logic used by both the ngtsc and compilation-api\n * compilation plugins. Encapsulates the caching, include-glob discovery,\n * tsconfig-graph expansion, and path-root resolution that were previously\n * duplicated across angular-vite-plugin.ts and compilation-api-plugin.ts.\n */\n\nimport * as compilerCli from '@angular/compiler-cli';\nimport { existsSync, statSync } from 'node:fs';\nimport { dirname, isAbsolute, join, resolve } from 'node:path';\nimport { createRequire } from 'node:module';\nimport { normalizePath, ResolvedConfig } from 'vite';\nimport { globSync } from 'tinyglobby';\nimport { debugEmit, debugEmitV } from './debug.js';\n\nconst require = createRequire(import.meta.url);\nconst ts = require('typescript');\n\nexport interface TsconfigResolverOptions {\n workspaceRoot: string;\n include: string[];\n liveReload: boolean;\n isTest: boolean;\n}\n\nexport class TsconfigResolver {\n private includeCache: string[] = [];\n private tsconfigOptionsCache = new Map<\n string,\n { options: any; rootNames: string[] }\n >();\n private tsconfigGraphRootCache = new Map<string, string[]>();\n private integrationIncludes: string[] = [];\n\n constructor(private options: TsconfigResolverOptions) {}\n\n /**\n * Replaces the include globs contributed by Vite plugins through\n * `analog.setup()`. Invalidates the include cache when the set changes.\n */\n setIntegrationIncludes(globs: string[]): void {\n if (\n globs.length === this.integrationIncludes.length &&\n globs.every((glob, index) => glob === this.integrationIncludes[index])\n ) {\n return;\n }\n this.integrationIncludes = [...globs];\n this.invalidateIncludeCache();\n }\n\n private get includeGlobs(): string[] {\n return [...this.options.include, ...this.integrationIncludes];\n }\n\n invalidateIncludeCache(): void {\n this.includeCache = [];\n }\n\n invalidateTsconfigCaches(): void {\n this.tsconfigOptionsCache.clear();\n this.tsconfigGraphRootCache.clear();\n }\n\n invalidateAll(): void {\n this.invalidateIncludeCache();\n this.invalidateTsconfigCaches();\n }\n\n ensureIncludeCache(): string[] {\n if (this.includeGlobs.length > 0 && this.includeCache.length === 0) {\n this.includeCache = this.findIncludes();\n debugEmit('include cache populated', {\n fileCount: this.includeCache.length,\n });\n }\n return this.includeCache;\n }\n\n readAngularTsconfigConfiguration(\n resolvedTsConfigPath: string,\n config: ResolvedConfig,\n ) {\n const isProd = config.mode === 'production';\n const emitSourceMaps = !isProd || !!config.build?.sourcemap;\n return compilerCli.readConfiguration(resolvedTsConfigPath, {\n suppressOutputPathCheck: true,\n outDir: undefined,\n sourceMap: emitSourceMaps,\n inlineSourceMap: false,\n inlineSources: emitSourceMaps,\n declaration: false,\n declarationMap: false,\n allowEmptyCodegenFiles: false,\n annotationsAs: 'decorators',\n enableResourceInlining: false,\n noEmitOnError: false,\n mapRoot: '',\n sourceRoot: '',\n supportTestBed: false,\n supportJitMode: false,\n });\n }\n\n getCachedTsconfigOptions(\n resolvedTsConfigPath: string,\n config: ResolvedConfig,\n ): { options: any; rootNames: string[] } {\n const tsconfigKey = this.getTsconfigCacheKey(resolvedTsConfigPath, config);\n let cached = this.tsconfigOptionsCache.get(tsconfigKey);\n\n if (!cached) {\n const read = this.readAngularTsconfigConfiguration(\n resolvedTsConfigPath,\n config,\n );\n cached = { options: read.options, rootNames: read.rootNames };\n this.tsconfigOptionsCache.set(tsconfigKey, cached);\n debugEmit('tsconfig root names loaded', {\n resolvedTsConfigPath,\n rootNameCount: read.rootNames.length,\n });\n debugEmitV('tsconfig root names', {\n resolvedTsConfigPath,\n rootNames: read.rootNames.map((file: string) => normalizePath(file)),\n });\n }\n\n return cached;\n }\n\n collectExpandedTsconfigRoots(\n resolvedTsConfigPath: string,\n config: ResolvedConfig,\n visited = new Set<string>(),\n ): string[] {\n const normalizedTsConfigPath = normalizePath(resolvedTsConfigPath);\n if (visited.has(normalizedTsConfigPath)) {\n return [];\n }\n\n const tsconfigKey = `${this.getTsconfigCacheKey(normalizedTsConfigPath, config)}|graph`;\n const cached = this.tsconfigGraphRootCache.get(tsconfigKey);\n if (cached) {\n return cached;\n }\n\n visited.add(normalizedTsConfigPath);\n\n const read = this.readAngularTsconfigConfiguration(\n normalizedTsConfigPath,\n config,\n );\n const rawTsconfig = (ts.readConfigFile(\n normalizedTsConfigPath,\n ts.sys.readFile,\n ).config ?? {}) as {\n compilerOptions?: {\n baseUrl?: unknown;\n paths?: Record<string, string[]>;\n };\n references?: Array<{ path?: unknown }>;\n };\n\n const expandedRoots = new Set(\n read.rootNames.map((file: string) => normalizePath(file)),\n );\n const pathRoots = collectTsconfigPathRoots(\n normalizedTsConfigPath,\n read.options,\n rawTsconfig,\n );\n for (const pathRoot of pathRoots) {\n expandedRoots.add(pathRoot);\n }\n\n const referenceConfigs = (rawTsconfig.references ?? [])\n .flatMap((reference) =>\n typeof reference.path === 'string'\n ? [\n resolveReferenceTsconfigPath(\n reference.path,\n normalizedTsConfigPath,\n ),\n ]\n : [],\n )\n .filter((reference): reference is string => !!reference);\n\n for (const referenceConfig of referenceConfigs) {\n for (const referenceRoot of this.collectExpandedTsconfigRoots(\n referenceConfig,\n config,\n visited,\n )) {\n expandedRoots.add(referenceRoot);\n }\n }\n\n const expandedRootList = [...expandedRoots];\n this.tsconfigGraphRootCache.set(tsconfigKey, expandedRootList);\n debugEmit('expanded tsconfig graph roots', {\n resolvedTsConfigPath: normalizedTsConfigPath,\n directRootNameCount: read.rootNames.length,\n pathRootCount: pathRoots.length,\n referenceConfigCount: referenceConfigs.length,\n expandedRootCount: expandedRootList.length,\n });\n debugEmitV('expanded tsconfig graph root files', {\n resolvedTsConfigPath: normalizedTsConfigPath,\n pathRoots,\n referenceConfigs,\n rootNames: expandedRootList,\n });\n\n return expandedRootList;\n }\n\n private getTsconfigCacheKey(\n resolvedTsConfigPath: string,\n config: ResolvedConfig,\n ): string {\n const isProd = config.mode === 'production';\n return [\n resolvedTsConfigPath,\n isProd ? 'prod' : 'dev',\n this.options.isTest ? 'test' : 'app',\n config.build?.lib ? 'lib' : 'nolib',\n !isProd || config.build?.sourcemap ? 'maps' : 'nomaps',\n this.options.liveReload ? 'live-reload' : 'no-live-reload',\n ].join('|');\n }\n\n private findIncludes(): string[] {\n const globs = this.includeGlobs.map((glob) =>\n normalizeIncludeGlob(this.options.workspaceRoot, glob),\n );\n const files = globSync(globs, { dot: true, absolute: true });\n debugEmit('include discovery', {\n patternCount: globs.length,\n fileCount: files.length,\n });\n debugEmitV('include discovery files', {\n globs,\n files: files.map((file) => normalizePath(file)),\n });\n return files;\n }\n}\n\nexport function normalizeIncludeGlob(\n workspaceRoot: string,\n glob: string,\n): string {\n const normalizedWorkspaceRoot = normalizePath(resolve(workspaceRoot));\n const normalizedGlob = normalizePath(glob);\n\n if (\n normalizedGlob === normalizedWorkspaceRoot ||\n normalizedGlob.startsWith(`${normalizedWorkspaceRoot}/`)\n ) {\n return normalizedGlob;\n }\n\n if (normalizedGlob.startsWith('/')) {\n return `${normalizedWorkspaceRoot}${normalizedGlob}`;\n }\n\n return normalizePath(resolve(normalizedWorkspaceRoot, normalizedGlob));\n}\n\nfunction resolveReferenceTsconfigPath(\n referencePath: string,\n ownerTsconfigPath: string,\n): string | undefined {\n const ownerDir = dirname(ownerTsconfigPath);\n const resolvedReference = normalizePath(\n isAbsolute(referencePath)\n ? referencePath\n : resolve(ownerDir, referencePath),\n );\n\n if (existsSync(resolvedReference)) {\n try {\n if (statSync(resolvedReference).isDirectory()) {\n const nestedTsconfig = join(resolvedReference, 'tsconfig.json');\n return existsSync(nestedTsconfig)\n ? normalizePath(nestedTsconfig)\n : undefined;\n }\n } catch {\n return undefined;\n }\n return resolvedReference;\n }\n\n if (!resolvedReference.endsWith('.json')) {\n const asJson = `${resolvedReference}.json`;\n if (existsSync(asJson)) {\n return normalizePath(asJson);\n }\n const nestedTsconfig = join(resolvedReference, 'tsconfig.json');\n if (existsSync(nestedTsconfig)) {\n return normalizePath(nestedTsconfig);\n }\n }\n\n return undefined;\n}\n\nfunction collectTsconfigPathRoots(\n resolvedTsConfigPath: string,\n options: any,\n rawTsconfig: {\n compilerOptions?: {\n baseUrl?: unknown;\n paths?: Record<string, string[]>;\n };\n },\n): string[] {\n const tsPaths = rawTsconfig.compilerOptions?.paths ?? options.paths;\n if (!tsPaths) {\n return [];\n }\n\n const tsconfigDir = dirname(resolvedTsConfigPath);\n const configuredBaseUrl =\n typeof options.baseUrl === 'string'\n ? options.baseUrl\n : typeof rawTsconfig.compilerOptions?.baseUrl === 'string'\n ? rawTsconfig.compilerOptions.baseUrl\n : undefined;\n const resolvedBaseUrl = configuredBaseUrl\n ? isAbsolute(configuredBaseUrl)\n ? configuredBaseUrl\n : resolve(tsconfigDir, configuredBaseUrl)\n : tsconfigDir;\n const discoveredRoots = new Set<string>();\n\n for (const targets of Object.values(tsPaths)) {\n for (const target of targets as string[]) {\n const resolvedTarget = normalizePath(\n isAbsolute(target) ? target : resolve(resolvedBaseUrl, target),\n );\n\n if (target.includes('*')) {\n for (const match of globSync(resolvedTarget, {\n dot: true,\n absolute: true,\n })) {\n discoveredRoots.add(normalizePath(match));\n }\n continue;\n }\n\n if (existsSync(resolvedTarget)) {\n discoveredRoots.add(resolvedTarget);\n }\n }\n }\n\n return [...discoveredRoots];\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export declare const VIRTUAL_RAW_PREFIX = "virtual:@analogjs/vite-plugin-angular:raw:";
|
|
2
|
+
export declare function toVirtualRawId(absPath: string): string;
|
|
3
|
+
export declare function isVirtualRawId(id: string): boolean;
|
|
4
|
+
export declare function fromVirtualRawId(id: string): string;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
//#region packages/vite-plugin-angular/src/lib/utils/virtual-ids.ts
|
|
2
|
+
var VIRTUAL_RAW_PREFIX = "virtual:@analogjs/vite-plugin-angular:raw:";
|
|
3
|
+
function encode(absPath) {
|
|
4
|
+
return Buffer.from(absPath, "utf-8").toString("base64url");
|
|
5
|
+
}
|
|
6
|
+
function decode(encoded) {
|
|
7
|
+
return Buffer.from(encoded, "base64url").toString("utf-8");
|
|
8
|
+
}
|
|
9
|
+
function toVirtualRawId(absPath) {
|
|
10
|
+
return `${VIRTUAL_RAW_PREFIX}${encode(absPath)}`;
|
|
11
|
+
}
|
|
12
|
+
function isVirtualRawId(id) {
|
|
13
|
+
return (id.startsWith("\0") ? id.slice(1) : id).startsWith(VIRTUAL_RAW_PREFIX);
|
|
14
|
+
}
|
|
15
|
+
function fromVirtualRawId(id) {
|
|
16
|
+
const normalizedId = id.startsWith("\0") ? id.slice(1) : id;
|
|
17
|
+
if (!normalizedId.startsWith("virtual:@analogjs/vite-plugin-angular:raw:")) throw new Error(`Invalid virtual raw id: ${id}`);
|
|
18
|
+
return decode(normalizedId.slice(42));
|
|
19
|
+
}
|
|
20
|
+
//#endregion
|
|
21
|
+
export { VIRTUAL_RAW_PREFIX, fromVirtualRawId, isVirtualRawId, toVirtualRawId };
|
|
22
|
+
|
|
23
|
+
//# sourceMappingURL=virtual-ids.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"virtual-ids.js","names":[],"sources":["../../../../src/lib/utils/virtual-ids.ts"],"sourcesContent":["// Virtual module id helpers for external component resources (template files).\n// Routing through virtual ids keeps Vite's built-in plugins (vite:asset, the\n// server.fs Denied ID check) out of the picture: the id Vite sees has no\n// file extension, so extension-based matchers never fire, and it does not\n// match the /[?&](raw|inline)\\b/ security regex.\n//\n// Style ?inline imports now flow through Vite's native CSS pipeline via\n// safeModulePaths (see safe-module-paths.ts). Only template ?raw imports\n// still use virtual ids. See #2263 / #2283 / #2310.\n\nexport const VIRTUAL_RAW_PREFIX = 'virtual:@analogjs/vite-plugin-angular:raw:';\n\nfunction encode(absPath: string): string {\n return Buffer.from(absPath, 'utf-8').toString('base64url');\n}\n\nfunction decode(encoded: string): string {\n return Buffer.from(encoded, 'base64url').toString('utf-8');\n}\n\nexport function toVirtualRawId(absPath: string): string {\n return `${VIRTUAL_RAW_PREFIX}${encode(absPath)}`;\n}\n\nexport function isVirtualRawId(id: string): boolean {\n const stripped = id.startsWith('\\0') ? id.slice(1) : id;\n return stripped.startsWith(VIRTUAL_RAW_PREFIX);\n}\n\nexport function fromVirtualRawId(id: string): string {\n const normalizedId = id.startsWith('\\0') ? id.slice(1) : id;\n if (!normalizedId.startsWith(VIRTUAL_RAW_PREFIX)) {\n throw new Error(`Invalid virtual raw id: ${id}`);\n }\n return decode(normalizedId.slice(VIRTUAL_RAW_PREFIX.length));\n}\n"],"mappings":";AAUA,IAAa,qBAAqB;AAElC,SAAS,OAAO,SAAyB;AACvC,QAAO,OAAO,KAAK,SAAS,QAAQ,CAAC,SAAS,YAAY;;AAG5D,SAAS,OAAO,SAAyB;AACvC,QAAO,OAAO,KAAK,SAAS,YAAY,CAAC,SAAS,QAAQ;;AAG5D,SAAgB,eAAe,SAAyB;AACtD,QAAO,GAAG,qBAAqB,OAAO,QAAQ;;AAGhD,SAAgB,eAAe,IAAqB;AAElD,SADiB,GAAG,WAAW,KAAK,GAAG,GAAG,MAAM,EAAE,GAAG,IACrC,WAAW,mBAAmB;;AAGhD,SAAgB,iBAAiB,IAAoB;CACnD,MAAM,eAAe,GAAG,WAAW,KAAK,GAAG,GAAG,MAAM,EAAE,GAAG;AACzD,KAAI,CAAC,aAAa,WAAA,6CAA8B,CAC9C,OAAM,IAAI,MAAM,2BAA2B,KAAK;AAElD,QAAO,OAAO,aAAa,MAAM,GAA0B,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
interface PluginContextLike {
|
|
2
|
+
addWatchFile(path: string): void;
|
|
3
|
+
}
|
|
4
|
+
/**
|
|
5
|
+
* Rewrite a user `.html?raw` import to a virtual raw id. Returns undefined
|
|
6
|
+
* when the id doesn't match, so callers can fall through to the next check.
|
|
7
|
+
*
|
|
8
|
+
* Routed through a virtual id (rather than `?analog-raw`) so the path Vite
|
|
9
|
+
* sees has no file extension — keeps vite:asset / vite:css from re-tagging
|
|
10
|
+
* the id before our load hook runs.
|
|
11
|
+
*/
|
|
12
|
+
export declare function rewriteHtmlRawImport(id: string, importer: string | undefined): string | undefined;
|
|
13
|
+
/**
|
|
14
|
+
* Load a virtual raw module: reads the backing file, registers it for HMR
|
|
15
|
+
* watching, and returns its content as a default-exported string. Returns
|
|
16
|
+
* undefined when the id is not a virtual raw id.
|
|
17
|
+
*/
|
|
18
|
+
export declare function loadVirtualRawModule(ctx: PluginContextLike, id: string): Promise<string | undefined>;
|
|
19
|
+
export {};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { fromVirtualRawId, isVirtualRawId, toVirtualRawId } from "./virtual-ids.js";
|
|
2
|
+
import { promises } from "node:fs";
|
|
3
|
+
import { dirname, isAbsolute, resolve } from "node:path";
|
|
4
|
+
import { normalizePath } from "vite";
|
|
5
|
+
//#region packages/vite-plugin-angular/src/lib/utils/virtual-resources.ts
|
|
6
|
+
function resolveImportPath(id, importer) {
|
|
7
|
+
const filePath = id.split("?")[0];
|
|
8
|
+
return isAbsolute(filePath) ? normalizePath(filePath) : importer ? normalizePath(resolve(dirname(importer), filePath)) : void 0;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Rewrite a user `.html?raw` import to a virtual raw id. Returns undefined
|
|
12
|
+
* when the id doesn't match, so callers can fall through to the next check.
|
|
13
|
+
*
|
|
14
|
+
* Routed through a virtual id (rather than `?analog-raw`) so the path Vite
|
|
15
|
+
* sees has no file extension — keeps vite:asset / vite:css from re-tagging
|
|
16
|
+
* the id before our load hook runs.
|
|
17
|
+
*/
|
|
18
|
+
function rewriteHtmlRawImport(id, importer) {
|
|
19
|
+
if (!id.includes(".html?raw")) return void 0;
|
|
20
|
+
const resolved = resolveImportPath(id, importer);
|
|
21
|
+
return resolved ? toVirtualRawId(resolved) : void 0;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Load a virtual raw module: reads the backing file, registers it for HMR
|
|
25
|
+
* watching, and returns its content as a default-exported string. Returns
|
|
26
|
+
* undefined when the id is not a virtual raw id.
|
|
27
|
+
*/
|
|
28
|
+
async function loadVirtualRawModule(ctx, id) {
|
|
29
|
+
if (!isVirtualRawId(id)) return void 0;
|
|
30
|
+
const filePath = fromVirtualRawId(id);
|
|
31
|
+
ctx.addWatchFile(filePath);
|
|
32
|
+
const content = await promises.readFile(filePath, "utf-8");
|
|
33
|
+
return `export default ${JSON.stringify(content)}`;
|
|
34
|
+
}
|
|
35
|
+
//#endregion
|
|
36
|
+
export { loadVirtualRawModule, rewriteHtmlRawImport };
|
|
37
|
+
|
|
38
|
+
//# sourceMappingURL=virtual-resources.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"virtual-resources.js","names":[],"sources":["../../../../src/lib/utils/virtual-resources.ts"],"sourcesContent":["// Shared Vite plugin helpers for routing component resources (templates)\n// through virtual module ids. Both angular-vite-plugin and fast-compile-plugin\n// use these so the rewriting + loading behavior stays in sync between them.\n//\n// Style ?inline imports now flow through Vite's native CSS pipeline via\n// safeModulePaths (see safe-module-paths.ts). Only template ?raw imports\n// still use virtual ids.\n\nimport { promises as fsPromises } from 'node:fs';\nimport { dirname, isAbsolute, resolve } from 'node:path';\nimport { normalizePath } from 'vite';\n\nimport {\n fromVirtualRawId,\n isVirtualRawId,\n toVirtualRawId,\n} from './virtual-ids.js';\n\ninterface PluginContextLike {\n addWatchFile(path: string): void;\n}\n\nfunction resolveImportPath(\n id: string,\n importer: string | undefined,\n): string | undefined {\n const filePath = id.split('?')[0];\n return isAbsolute(filePath)\n ? normalizePath(filePath)\n : importer\n ? normalizePath(resolve(dirname(importer), filePath))\n : undefined;\n}\n\n/**\n * Rewrite a user `.html?raw` import to a virtual raw id. Returns undefined\n * when the id doesn't match, so callers can fall through to the next check.\n *\n * Routed through a virtual id (rather than `?analog-raw`) so the path Vite\n * sees has no file extension — keeps vite:asset / vite:css from re-tagging\n * the id before our load hook runs.\n */\nexport function rewriteHtmlRawImport(\n id: string,\n importer: string | undefined,\n): string | undefined {\n if (!id.includes('.html?raw')) return undefined;\n const resolved = resolveImportPath(id, importer);\n return resolved ? toVirtualRawId(resolved) : undefined;\n}\n\n/**\n * Load a virtual raw module: reads the backing file, registers it for HMR\n * watching, and returns its content as a default-exported string. Returns\n * undefined when the id is not a virtual raw id.\n */\nexport async function loadVirtualRawModule(\n ctx: PluginContextLike,\n id: string,\n): Promise<string | undefined> {\n if (!isVirtualRawId(id)) return undefined;\n const filePath = fromVirtualRawId(id);\n ctx.addWatchFile(filePath);\n const content = await fsPromises.readFile(filePath, 'utf-8');\n return `export default ${JSON.stringify(content)}`;\n}\n"],"mappings":";;;;;AAsBA,SAAS,kBACP,IACA,UACoB;CACpB,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC;AAC/B,QAAO,WAAW,SAAS,GACvB,cAAc,SAAS,GACvB,WACE,cAAc,QAAQ,QAAQ,SAAS,EAAE,SAAS,CAAC,GACnD,KAAA;;;;;;;;;;AAWR,SAAgB,qBACd,IACA,UACoB;AACpB,KAAI,CAAC,GAAG,SAAS,YAAY,CAAE,QAAO,KAAA;CACtC,MAAM,WAAW,kBAAkB,IAAI,SAAS;AAChD,QAAO,WAAW,eAAe,SAAS,GAAG,KAAA;;;;;;;AAQ/C,eAAsB,qBACpB,KACA,IAC6B;AAC7B,KAAI,CAAC,eAAe,GAAG,CAAE,QAAO,KAAA;CAChC,MAAM,WAAW,iBAAiB,GAAG;AACrC,KAAI,aAAa,SAAS;CAC1B,MAAM,UAAU,MAAM,SAAW,SAAS,UAAU,QAAQ;AAC5D,QAAO,kBAAkB,KAAK,UAAU,QAAQ"}
|