@analogjs/vite-plugin-angular 3.0.0-alpha.87 → 3.0.0-alpha.89
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/package.json +1 -1
- package/src/lib/angular-build-optimizer-plugin.d.ts +4 -0
- package/src/lib/angular-build-optimizer-plugin.js +49 -26
- package/src/lib/angular-build-optimizer-plugin.js.map +1 -1
- package/src/lib/angular-jit-plugin.js +4 -0
- package/src/lib/angular-jit-plugin.js.map +1 -1
- package/src/lib/angular-vite-plugin.js +48 -8
- package/src/lib/angular-vite-plugin.js.map +1 -1
- package/src/lib/compilation-api/compilation-api-plugin.js +2 -2
- package/src/lib/compilation-api/compilation-api-plugin.js.map +1 -1
- package/src/lib/compiler/compile.js +1 -1
- package/src/lib/compiler/compile.js.map +1 -1
- package/src/lib/compiler-plugin.js +3 -3
- package/src/lib/compiler-plugin.js.map +1 -1
- package/src/lib/encapsulation-plugin.d.ts +6 -1
- package/src/lib/encapsulation-plugin.js +24 -9
- package/src/lib/encapsulation-plugin.js.map +1 -1
- package/src/lib/fast-compile-plugin.d.ts +10 -0
- package/src/lib/fast-compile-plugin.js +21 -7
- package/src/lib/fast-compile-plugin.js.map +1 -1
- package/src/lib/router-plugin.js +2 -2
- package/src/lib/router-plugin.js.map +1 -1
- 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/devkit.d.ts +9 -1
- package/src/lib/utils/devkit.js +39 -1
- package/src/lib/utils/devkit.js.map +1 -1
- package/src/lib/utils/transform-cache.d.ts +1 -1
- package/src/lib/utils/transform-cache.js.map +1 -1
- package/src/lib/utils/tsconfig-resolver.js +6 -4
- package/src/lib/utils/tsconfig-resolver.js.map +1 -1
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { TS_EXT_REGEX, createDepOptimizerConfig, getTsConfigPath, isProdMode } from "./utils/plugin-config.js";
|
|
2
2
|
import { discoverAnalogIntegrations } from "./analog-plugin-interop.js";
|
|
3
|
+
import { releaseCssPreprocessorWorkers } from "./utils/css-preprocessor-workers.js";
|
|
3
4
|
import { toVirtualRawId } from "./utils/virtual-ids.js";
|
|
4
5
|
import { loadVirtualRawModule, rewriteHtmlRawImport } from "./utils/virtual-resources.js";
|
|
5
6
|
import { ANGULAR_DECORATOR_CALL_RE } from "./compiler/constants.js";
|
|
@@ -19,6 +20,15 @@ import { normalizePath, preprocessCSS } from "vite";
|
|
|
19
20
|
import * as compilerCli from "@angular/compiler-cli";
|
|
20
21
|
import { parseSync } from "oxc-parser";
|
|
21
22
|
//#region packages/vite-plugin-angular/src/lib/fast-compile-plugin.ts
|
|
23
|
+
/**
|
|
24
|
+
* Directory that `compilerOptions.paths` targets resolve against. Mirrors
|
|
25
|
+
* TypeScript: `baseUrl` when set, otherwise the directory of the config
|
|
26
|
+
* that declares `paths` (`pathsBasePath`, since `baseUrl` is optional
|
|
27
|
+
* from TS 4.1).
|
|
28
|
+
*/
|
|
29
|
+
function getPathsBasePath(options, fallback) {
|
|
30
|
+
return options?.baseUrl ?? options?.pathsBasePath ?? fallback;
|
|
31
|
+
}
|
|
22
32
|
function fastCompilePlugin(pluginOptions) {
|
|
23
33
|
let resolvedConfig;
|
|
24
34
|
let transformFilter;
|
|
@@ -93,7 +103,7 @@ function fastCompilePlugin(pluginOptions) {
|
|
|
93
103
|
useDefineForClassFields = config.options?.useDefineForClassFields ?? true;
|
|
94
104
|
const candidates = new Set(config.rootNames);
|
|
95
105
|
const tsPaths = config.options?.paths;
|
|
96
|
-
const baseUrl = config.options
|
|
106
|
+
const baseUrl = getPathsBasePath(config.options, projectRoot);
|
|
97
107
|
const fileContents = /* @__PURE__ */ new Map();
|
|
98
108
|
const scanResults = /* @__PURE__ */ new Map();
|
|
99
109
|
if (tsPaths) for (const targets of Object.values(tsPaths)) for (const target of targets) {
|
|
@@ -292,17 +302,18 @@ function fastCompilePlugin(pluginOptions) {
|
|
|
292
302
|
oxcProgram
|
|
293
303
|
});
|
|
294
304
|
for (const dep of result.resourceDependencies) resourceToSource.set(dep, id);
|
|
295
|
-
|
|
305
|
+
const stripped = vite.transformWithOxc ? await vite.transformWithOxc(result.code, id, {
|
|
296
306
|
lang: "ts",
|
|
297
|
-
sourcemap:
|
|
307
|
+
sourcemap: true,
|
|
298
308
|
decorator: {
|
|
299
309
|
legacy: false,
|
|
300
310
|
emitDecoratorMetadata: false
|
|
301
311
|
}
|
|
302
|
-
}) : await vite.transformWithEsbuild(result.code, id, {
|
|
312
|
+
}, result.map) : await vite.transformWithEsbuild(result.code, id, {
|
|
303
313
|
loader: "ts",
|
|
304
|
-
sourcemap:
|
|
305
|
-
})
|
|
314
|
+
sourcemap: true
|
|
315
|
+
}, result.map);
|
|
316
|
+
let outputCode = stripped.code;
|
|
306
317
|
if (watchMode && pluginOptions.liveReload) {
|
|
307
318
|
const fileDeclarations = [...registry.values()].filter((e) => e.fileName === id);
|
|
308
319
|
if (fileDeclarations.length > 0) {
|
|
@@ -312,7 +323,7 @@ function fastCompilePlugin(pluginOptions) {
|
|
|
312
323
|
}
|
|
313
324
|
return {
|
|
314
325
|
code: outputCode,
|
|
315
|
-
map:
|
|
326
|
+
map: stripped.map
|
|
316
327
|
};
|
|
317
328
|
}
|
|
318
329
|
function resolveTsConfigPath() {
|
|
@@ -357,6 +368,9 @@ function fastCompilePlugin(pluginOptions) {
|
|
|
357
368
|
async buildStart() {
|
|
358
369
|
await initFastCompile();
|
|
359
370
|
},
|
|
371
|
+
closeBundle() {
|
|
372
|
+
if (!watchMode) releaseCssPreprocessorWorkers();
|
|
373
|
+
},
|
|
360
374
|
async handleHotUpdate(ctx) {
|
|
361
375
|
if (resourceToSource.has(ctx.file)) {
|
|
362
376
|
const parentSource = resourceToSource.get(ctx.file);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fast-compile-plugin.js","names":[],"sources":["../../../src/lib/fast-compile-plugin.ts"],"sourcesContent":["import { promises as fsPromises } from 'node:fs';\nimport { dirname, isAbsolute, resolve } from 'node:path';\nimport { parseSync } from 'oxc-parser';\nimport * as vite from 'vite';\n\nimport * as compilerCli from '@angular/compiler-cli';\nimport { normalizePath, Plugin, preprocessCSS, ResolvedConfig } from 'vite';\n\nimport {\n compile,\n scanFile,\n scanPackageDts,\n collectImportedPackages,\n collectRelativeReExports,\n collectAllImports,\n jitTransform,\n inlineResourceUrls,\n extractInlineStyles,\n generateHmrCode,\n debugCompile,\n debugRegistry,\n ANGULAR_DECORATOR_CALL_RE,\n type ComponentRegistry,\n} from './compiler/index.js';\n\nimport {\n TS_EXT_REGEX,\n getTsConfigPath,\n createDepOptimizerConfig,\n isProdMode,\n type TsConfigResolutionContext,\n} from './utils/plugin-config.js';\nimport { VIRTUAL_RAW_PREFIX, toVirtualRawId } from './utils/virtual-ids.js';\nimport {\n loadVirtualRawModule,\n rewriteHtmlRawImport,\n} from './utils/virtual-resources.js';\nimport { markStylePathSafe } from './utils/safe-module-paths.js';\nimport {\n discoverAnalogIntegrations,\n type ComponentRegistryEntries,\n type TransformFilter,\n} from './analog-plugin-interop.js';\n\nexport interface FastCompilePluginOptions {\n tsconfigGetter: () => string;\n workspaceRoot: string;\n inlineStylesExtension: string;\n jit: boolean;\n liveReload: boolean;\n supportedBrowsers: string[];\n isTest: boolean;\n isAstroIntegration: boolean;\n fastCompileMode?: 'full' | 'partial';\n}\n\nexport function fastCompilePlugin(\n pluginOptions: FastCompilePluginOptions,\n): Plugin {\n let resolvedConfig: ResolvedConfig;\n let transformFilter: TransformFilter | undefined;\n let componentRegistries: ComponentRegistryEntries[] = [];\n let tsConfigResolutionContext: TsConfigResolutionContext | null = null;\n let watchMode = false;\n\n // fast-compile plugin state\n const registry: ComponentRegistry = new Map();\n const resourceToSource = new Map<string, string>();\n const scannedDtsPackages = new Set<string>();\n let projectRoot = '';\n let useDefineForClassFields = true;\n\n /**\n * Scan a file into the registry, then recursively walk its relative\n * `export *` / `export { … } from './x'` chain so any underlying\n * directive classes also land in the registry. Used both at\n * `buildStart` (for tsconfig path entries) and at dev time (file\n * `add` and `handleHotUpdate`) so newly added barrels stay in sync\n * without requiring a server restart.\n *\n * The `visited` set prevents infinite recursion within a single\n * top-level call. Each fresh scan should pass an empty set (so HMR\n * re-scans aren't blocked by buildStart's earlier visits).\n *\n * `fileContents`/`scanResults` are cold-start dedup caches scoped to a\n * single `initFastCompile` call. HMR/watcher callers must omit them so\n * an edited file is always re-read from disk.\n */\n async function scanBarrelExports(\n file: string,\n visited: Set<string> = new Set(),\n overwrite = false,\n fileContents?: Map<string, string>,\n scanResults?: Map<string, ReturnType<typeof scanFile>>,\n ): Promise<void> {\n if (visited.has(file)) return;\n visited.add(file);\n let code: string;\n try {\n code =\n fileContents?.get(file) ?? (await fsPromises.readFile(file, 'utf-8'));\n fileContents?.set(file, code);\n } catch (e) {\n if (debugRegistry.enabled) {\n debugRegistry(\n 'scanBarrelExports: failed to read %s: %s',\n file,\n (e as Error)?.message,\n );\n }\n return;\n }\n // Single parse shared by scanFile and collectRelativeReExports. On a\n // parse error each consumer re-parses on its own, preserving their\n // individual failure semantics (scanFile throws past its pre-filter;\n // collectRelativeReExports swallows and returns []).\n let program: ReturnType<typeof parseSync>['program'] | undefined;\n try {\n program = parseSync(file, code).program;\n } catch {\n program = undefined;\n }\n let entries = scanResults?.get(file);\n if (!entries) {\n entries = scanFile(code, file, program);\n scanResults?.set(file, entries);\n }\n for (const entry of entries) {\n // At buildStart we want stable registry entries (don't overwrite\n // an earlier scan with a barrel re-scan); HMR explicitly asks\n // for overwrite so updated metadata replaces stale entries.\n if (overwrite || !registry.has(entry.className)) {\n registry.set(entry.className, entry);\n }\n }\n // Collect every relative re-export specifier via OXC AST so\n // recursive scans can't trip over each other (a shared `/g` regex\n // would have its `lastIndex` reset by each recursive call and\n // silently skip half of an outer barrel's re-exports, which\n // previously left directives like `HlmRadioGroup` unregistered).\n const dir = dirname(file);\n for (const rel of collectRelativeReExports(code, file, program)) {\n // NodeNext-style libraries write `export * from './foo.js'`\n // even though the source is `./foo.ts`. Strip the ESM\n // extension before probing or the candidates would be\n // `foo.js.ts` / `foo.js/index.ts`, which never exist.\n const normalizedRel = rel.replace(/\\.(?:js|mjs)$/u, '');\n const reExportCandidates = [\n resolve(dir, normalizedRel + '.ts'),\n resolve(dir, normalizedRel, 'index.ts'),\n ];\n let resolved = false;\n for (const candidate of reExportCandidates) {\n try {\n await fsPromises.access(candidate);\n await scanBarrelExports(\n candidate,\n visited,\n overwrite,\n fileContents,\n scanResults,\n );\n resolved = true;\n break;\n } catch {\n // try next candidate\n }\n }\n if (!resolved && debugRegistry.enabled) {\n debugRegistry(\n 'scanBarrelExports: %s re-export %s did not resolve to %o',\n file,\n rel,\n reExportCandidates,\n );\n }\n }\n }\n\n async function initFastCompile() {\n if (pluginOptions.jit) return; // JIT: no registry scan needed\n\n // Scan all source files to build the registry\n registry.clear();\n scannedDtsPackages.clear();\n const resolvedTsConfigPath = resolveTsConfigPath();\n projectRoot = dirname(resolvedTsConfigPath);\n const config = compilerCli.readConfiguration(resolvedTsConfigPath);\n useDefineForClassFields = config.options?.useDefineForClassFields ?? true;\n\n // Collect candidate files: tsconfig rootNames PLUS the entry points\n // named in `compilerOptions.paths`. App tsconfigs typically only\n // include the app's own sources, so workspace library entry barrels\n // (e.g. `HlmSelectImports = [HlmSelect, HlmSelectContent, ...] as\n // const`) live outside `rootNames` and would otherwise miss the\n // initial scan. The compiler then can't see that `HlmSelectImports`\n // is a tuple barrel and emits the bare identifier into the parent\n // component's `dependencies()` list, where Angular's runtime\n // silently drops it because arrays don't have a directive def.\n const candidates = new Set<string>(config.rootNames);\n const tsPaths = config.options?.paths;\n const baseUrl = (config.options?.baseUrl ?? projectRoot) as string;\n // Cold-start dedup caches shared by the three scan phases below\n // (candidates scan, walkImports, scanBarrelExports). Scoped to this\n // init call only — HMR/watcher re-scans must hit disk fresh.\n const fileContents = new Map<string, string>();\n const scanResults = new Map<string, ReturnType<typeof scanFile>>();\n if (tsPaths) {\n for (const targets of Object.values(tsPaths)) {\n for (const target of targets as string[]) {\n // Skip wildcard patterns — entry barrels are normally exact\n // file paths like \"libs/helm/select/src/index.ts\".\n if (target.includes('*')) continue;\n candidates.add(resolve(baseUrl, target));\n }\n }\n }\n const results = await Promise.all(\n Array.from(candidates).map(async (file) => {\n try {\n const code = await fsPromises.readFile(file, 'utf-8');\n fileContents.set(file, code);\n const entries = scanFile(code, file);\n scanResults.set(file, entries);\n return entries;\n } catch (e) {\n if (debugRegistry.enabled) {\n debugRegistry(\n 'initFastCompile: skipping unreadable %s: %s',\n file,\n (e as Error)?.message,\n );\n }\n return []; // Skip unreadable files\n }\n }),\n );\n\n for (const entries of results) {\n for (const entry of entries) {\n registry.set(entry.className, entry);\n }\n }\n\n // Walk the transitive import graph from the root files so the registry also\n // contains declarations that live in files not directly in tsconfig\n // `files`/`include` (transitively-imported app sources) and in workspace\n // libraries reached through wildcard `paths` (e.g. `@bitwarden/*`). Without\n // this, a non-standalone component's owning module can't classify its\n // declarations and `ɵɵsetComponentScope` is never emitted for it. Only\n // relative imports and `paths`-mapped (project/workspace) bare specifiers are\n // followed; true `node_modules` packages are left to the lazy `.d.ts` scanner.\n // Return *all* candidate base paths a bare specifier maps to. A `paths`\n // entry can list several fallback targets (e.g. a built `dist` path first\n // and the workspace `src` second); the caller probes them in order.\n const resolvePathSpecifier = (spec: string): string[] => {\n if (!tsPaths) return [];\n for (const [key, targets] of Object.entries(tsPaths)) {\n const list = targets as string[];\n if (key.endsWith('/*')) {\n const prefix = key.slice(0, -1);\n if (spec.startsWith(prefix)) {\n // `split('*').join(...)` substitutes the single tsconfig `*`\n // wildcard without `String.replace`'s first-match-only behavior or\n // `$`-pattern interpretation of the replacement.\n return list.map((t) =>\n resolve(baseUrl, t.split('*').join(spec.slice(prefix.length))),\n );\n }\n } else if (key === spec) {\n return list.map((t) => resolve(baseUrl, t));\n }\n }\n return [];\n };\n const probeToSource = async (base: string): Promise<string | null> => {\n const candidates = base.endsWith('.ts')\n ? [base]\n : [base + '.ts', resolve(base, 'index.ts')];\n for (const candidate of candidates) {\n try {\n await fsPromises.access(candidate);\n return candidate;\n } catch {\n // try next candidate\n }\n }\n return null;\n };\n // Memoize fs probes per absolute base path. The cache stores the\n // Promise (not the settled value) so concurrent walks racing on the\n // same base collapse into a single probe.\n const baseResolveCache = new Map<string, Promise<string | null>>();\n const resolveToSource = (base: string): Promise<string | null> => {\n let probe = baseResolveCache.get(base);\n if (!probe) {\n probe = probeToSource(base);\n baseResolveCache.set(base, probe);\n }\n return probe;\n };\n // Probe each `paths` target in order; first one that resolves to source wins.\n const resolveFirstSource = async (\n bases: string[],\n ): Promise<string | null> => {\n for (const base of bases) {\n const resolved = await resolveToSource(base);\n if (resolved) return resolved;\n }\n return null;\n };\n const importWalkVisited = new Set<string>();\n // Paths-mapped resolution doesn't depend on the importer, so bare\n // specifiers can be memoized by their raw text. Relative specifiers\n // must NOT be — the same './foo' resolves differently per directory.\n const bareSpecResolveCache = new Map<string, Promise<string | null>>();\n const walkImports = async (file: string): Promise<void> => {\n if (importWalkVisited.has(file)) return;\n importWalkVisited.add(file);\n let code: string;\n try {\n code =\n fileContents.get(file) ?? (await fsPromises.readFile(file, 'utf-8'));\n fileContents.set(file, code);\n } catch {\n return;\n }\n // Single parse shared by scanFile, collectImportedPackages, and\n // collectAllImports. On a parse error each consumer re-parses on\n // its own, preserving their individual failure semantics.\n let program: ReturnType<typeof parseSync>['program'] | undefined;\n try {\n program = parseSync(file, code).program;\n } catch {\n program = undefined;\n }\n let entries = scanResults.get(file);\n if (!entries) {\n entries = scanFile(code, file, program);\n scanResults.set(file, entries);\n }\n for (const entry of entries) {\n if (!registry.has(entry.className))\n registry.set(entry.className, entry);\n }\n // Pre-scan the `.d.ts` of every external package this file imports (and,\n // transitively, packages those packages' NgModules re-export — e.g.\n // BrowserModule → CommonModule → NgIf). Doing this at buildStart means the\n // registry is complete before any component transforms, so non-standalone\n // component scope resolves regardless of file transform order.\n for (const pkg of collectImportedPackages(code, file, program)) {\n if (scannedDtsPackages.has(pkg)) continue;\n scannedDtsPackages.add(pkg);\n try {\n for (const entry of scanPackageDts(\n pkg,\n projectRoot,\n scannedDtsPackages,\n )) {\n if (!registry.has(entry.className))\n registry.set(entry.className, entry);\n }\n } catch {\n // Package may not have .d.ts or not be Angular\n }\n }\n const dir = dirname(file);\n const targets = await Promise.all(\n collectAllImports(code, file, program).map((spec) => {\n if (spec.startsWith('.')) {\n return resolveToSource(\n resolve(dir, spec.replace(/\\.(?:js|mjs)$/u, '')),\n );\n }\n let resolved = bareSpecResolveCache.get(spec);\n if (!resolved) {\n resolved = resolveFirstSource(resolvePathSpecifier(spec));\n bareSpecResolveCache.set(spec, resolved);\n }\n return resolved;\n }),\n );\n await Promise.all(\n targets.filter((t): t is string => !!t).map((t) => walkImports(t)),\n );\n };\n await Promise.all(config.rootNames.map((file) => walkImports(file)));\n\n // Library barrels typically `export * from './lib/...'` rather than\n // declaring directives directly, so the entry file alone gives us\n // the tuple consts but not the directive classes they reference.\n // Walk the relative `export *` chain so the underlying classes also\n // land in the registry. Use a SHARED visited set across all\n // barrels so recursive walks don't double-scan a file that's\n // re-exported from multiple entry points.\n const buildStartVisited = new Set<string>();\n if (tsPaths) {\n const barrelCandidates: string[] = [];\n for (const targets of Object.values(tsPaths)) {\n for (const target of targets as string[]) {\n if (target.includes('*')) continue;\n barrelCandidates.push(resolve(baseUrl, target));\n }\n }\n await Promise.all(\n barrelCandidates.map((c) =>\n scanBarrelExports(\n c,\n buildStartVisited,\n false,\n fileContents,\n scanResults,\n ),\n ),\n );\n }\n debugRegistry(\n 'initFastCompile done: %d entries from %d candidate files',\n registry.size,\n candidates.size,\n );\n }\n\n function ensureDtsRegistryForSource(\n code: string,\n id: string,\n program?: ReturnType<typeof parseSync>['program'],\n ) {\n for (const pkg of collectImportedPackages(code, id, program)) {\n if (scannedDtsPackages.has(pkg)) continue;\n scannedDtsPackages.add(pkg);\n\n try {\n const dtsEntries = scanPackageDts(pkg, projectRoot, scannedDtsPackages);\n for (const entry of dtsEntries) {\n if (!registry.has(entry.className)) {\n registry.set(entry.className, entry);\n }\n }\n } catch {\n // Package may not have .d.ts files or may not be Angular\n }\n }\n }\n\n async function handleFastCompileTransform(\n code: string,\n id: string,\n ): Promise<{ code: string; map: any } | undefined> {\n if (!ANGULAR_DECORATOR_CALL_RE.test(code)) {\n // Non-Angular file — strip TS-only syntax ourselves so barrels\n // like `export { Foo, type Bar } from './x'` and other TS-only\n // forms don't leak unstripped to Rolldown. In rolldown-vite the\n // built-in `vite:oxc` strip is registered as a Rust-side native\n // plugin (`viteTransformPlugin` from `rolldown/experimental`); if\n // its hook-filter treats files our `transform.filter.id.include`\n // claimed as already-handled, no JS-side fallback runs and raw\n // TS reaches the parser → `SyntaxError: Unexpected identifier`.\n const stripped = vite.transformWithOxc\n ? await vite.transformWithOxc(code, id, {\n lang: 'ts',\n sourcemap: true,\n decorator: { legacy: false, emitDecoratorMetadata: false },\n })\n : await vite.transformWithEsbuild(code, id, {\n loader: 'ts',\n sourcemap: true,\n });\n return { code: stripped.code, map: stripped.map };\n }\n\n // JIT mode\n if (pluginOptions.jit) {\n const result = jitTransform(code, id);\n // Strip TypeScript-only syntax (e.g. `readonly`, parameter property\n // modifiers, type annotations on fields) so the output is valid JS\n // for Rolldown. `angularVitestSourcemapPlugin` normally runs this\n // strip downstream in tests, but it is intentionally skipped on\n // StackBlitz / WebContainer — and the production build pipeline\n // does not register it either — so the JIT path must self-strip\n // to stay safe across environments.\n //\n // Pass the jitTransform map as `inMap` so OXC/esbuild emit a map\n // composed with the original `.ts` source — without this, debug\n // stack traces and breakpoints land on the wrong lines once the\n // strip removes any TS-only token. `jitTransform` returns\n // `map: null` for files with no Angular class (no edits made);\n // passing that to OXC/esbuild as `inMap` throws, so coerce to\n // `undefined` in that case.\n const inMap = result.map ?? undefined;\n const stripped = vite.transformWithOxc\n ? await vite.transformWithOxc(\n result.code,\n id,\n {\n lang: 'ts',\n sourcemap: true,\n decorator: { legacy: false, emitDecoratorMetadata: false },\n },\n inMap,\n )\n : await vite.transformWithEsbuild(\n result.code,\n id,\n { loader: 'ts', sourcemap: true },\n inMap,\n );\n return { code: stripped.code, map: stripped.map };\n }\n\n // Inline external templateUrl/styleUrl(s) into the source before compilation.\n // `styleExtensions` carries the source extension of each inlined external\n // style so it can be preprocessed by its own file type (e.g. an external\n // `.scss` styleUrl) regardless of the `inlineStylesExtension` option.\n const inlined = await inlineResourceUrls(code, id);\n code = inlined.code;\n const { styleExtensions } = inlined;\n\n // Track inlined resources for HMR. `compile()` only reports resources it\n // reads through its own fallback (a templateUrl/styleUrl the inliner did\n // NOT already inline), so files inlined here must be recorded here or a\n // later edit to them never invalidates the owning module.\n for (const dep of inlined.resourceDependencies) {\n resourceToSource.set(dep, id);\n }\n\n // Single OXC parse of the post-inline source, shared by every AST\n // consumer below. `inlineResourceUrls` parsed the PRE-inline string,\n // so its program can never be reused here.\n const { program: oxcProgram } = parseSync(id, code);\n\n // Pre-resolve inline styles that need preprocessing (SCSS/Sass/Less). Run\n // whenever a style needs a non-`css` preprocessor — either the configured\n // `inlineStylesExtension` for truly-inline styles, or an external styleUrl's\n // own extension.\n let resolvedStyles: Map<string, string> | undefined;\n let resolvedInlineStyles: Map<number, string> | undefined;\n\n const inlineExt = pluginOptions.inlineStylesExtension;\n const styleNeedsPreprocess = (ext: string) => ext !== '' && ext !== 'css';\n\n if (styleNeedsPreprocess(inlineExt) || styleExtensions.size > 0) {\n const styleStrings = extractInlineStyles(code, id, oxcProgram);\n\n if (styleStrings.length > 0) {\n resolvedInlineStyles = new Map();\n for (let i = 0; i < styleStrings.length; i++) {\n // External styleUrls are preprocessed by their own extension; truly\n // inline `styles: [...]` fall back to `inlineStylesExtension`.\n const ext = styleExtensions.get(i) ?? inlineExt;\n if (!styleNeedsPreprocess(ext)) continue;\n try {\n const fakePath = id.replace(/\\.ts$/, `.inline-${i}.${ext}`);\n const processed = await preprocessCSS(\n styleStrings[i],\n fakePath,\n resolvedConfig,\n );\n resolvedInlineStyles.set(i, processed.code);\n } catch (e) {\n if (debugCompile.enabled) {\n debugCompile(\n 'inline style #%d preprocessing failed in %s: %s',\n i,\n id,\n (e as Error)?.message,\n );\n }\n // Skip styles that can't be preprocessed\n }\n }\n if (resolvedInlineStyles.size === 0) resolvedInlineStyles = undefined;\n }\n }\n\n ensureDtsRegistryForSource(code, id, oxcProgram);\n\n // Merge registries contributed through `analog.setup()` into this\n // compile's lookup view. Out-of-tree compilers register directive\n // metadata for classes fastCompile can't reach through its\n // tsconfig-driven scan (e.g. `.tsrx` files compiled by `@tsrx/analog`).\n // Without this merge, a TS `@Component({ imports: [X] })` that\n // references such a class hits `_unresolved-${className}` as its\n // selector and the tag never matches at runtime.\n let compileRegistry: ComponentRegistry = registry;\n if (componentRegistries.some((external) => external.size > 0)) {\n compileRegistry = new Map(registry);\n for (const external of componentRegistries) {\n for (const [k, v] of external) compileRegistry.set(k, v);\n }\n }\n\n const result = compile(code, id, {\n registry: compileRegistry,\n resolvedStyles,\n resolvedInlineStyles,\n useDefineForClassFields,\n compilationMode: pluginOptions.fastCompileMode,\n oxcProgram,\n });\n\n // Track resource dependencies for HMR\n for (const dep of result.resourceDependencies) {\n resourceToSource.set(dep, id);\n }\n\n // Strip TypeScript-only syntax\n const stripped = vite.transformWithOxc\n ? await vite.transformWithOxc(result.code, id, {\n lang: 'ts',\n sourcemap: false,\n decorator: { legacy: false, emitDecoratorMetadata: false },\n })\n : await vite.transformWithEsbuild(result.code, id, {\n loader: 'ts',\n sourcemap: false,\n });\n let outputCode = stripped.code;\n\n // Append HMR code in dev mode\n if (watchMode && pluginOptions.liveReload) {\n const fileDeclarations = [...registry.values()].filter(\n (e) => e.fileName === id,\n );\n if (fileDeclarations.length > 0) {\n const localDepClassNames = fileDeclarations.map((e) => e.className);\n outputCode += generateHmrCode(fileDeclarations, localDepClassNames);\n }\n }\n\n return { code: outputCode, map: result.map };\n }\n\n function resolveTsConfigPath() {\n const { root, isProd, isLib } = tsConfigResolutionContext!;\n return getTsConfigPath(\n root,\n pluginOptions.tsconfigGetter(),\n isProd,\n pluginOptions.isTest,\n isLib,\n pluginOptions.workspaceRoot,\n );\n }\n\n return {\n name: '@analogjs/vite-plugin-angular-fast-compile',\n enforce: 'pre' as const,\n async config(config, { command }) {\n watchMode = command === 'serve';\n const isProd = isProdMode(config.mode);\n\n tsConfigResolutionContext = {\n root: config.root || '.',\n isProd,\n isLib: !!config?.build?.lib,\n };\n\n const preliminaryTsConfigPath = resolveTsConfigPath();\n\n const depOptimizer = createDepOptimizerConfig({\n tsconfig: preliminaryTsConfigPath,\n isProd,\n jit: pluginOptions.jit,\n watchMode,\n isTest: pluginOptions.isTest,\n isAstroIntegration: pluginOptions.isAstroIntegration,\n });\n\n // No `resolve.conditions` extension here: the `style` condition is\n // scoped to `.css`-extension requests by\n // `cssExtensionStyleResolverPlugin`, registered once at the\n // `angular()` factory level (which is the only public entry point\n // that wires this plugin in).\n return {\n ...(vite.rolldownVersion ? { oxc: {} as any } : { esbuild: false }),\n ...depOptimizer,\n };\n },\n async configResolved(config) {\n resolvedConfig = config;\n const integrations = await discoverAnalogIntegrations(config);\n transformFilter = integrations.transformFilter;\n componentRegistries = integrations.componentRegistries;\n },\n configureServer(server) {\n // Watch for new .ts files and scan them into the registry. Use\n // the barrel-aware scanner so a newly added re-export entry\n // (`export * from './x'`) also expands its underlying directive\n // classes — otherwise the registry stays stale until restart.\n server.watcher.on('add', async (filePath) => {\n if (\n filePath.endsWith('.ts') &&\n !filePath.endsWith('.spec.ts') &&\n !filePath.endsWith('.d.ts')\n ) {\n await scanBarrelExports(filePath, new Set(), true);\n }\n });\n },\n async buildStart() {\n await initFastCompile();\n },\n async handleHotUpdate(ctx) {\n // Resource file changes → invalidate parent .ts module\n if (resourceToSource.has(ctx.file)) {\n const parentSource = resourceToSource.get(ctx.file)!;\n const parentModule = ctx.server.moduleGraph.getModuleById(parentSource);\n if (parentModule) {\n return [parentModule];\n }\n }\n\n if (TS_EXT_REGEX.test(ctx.file)) {\n const [fileId] = ctx.file.split('?');\n\n // Remove old entries from this file\n const oldEntries = [...registry.entries()]\n .filter(([_, v]) => v.fileName === fileId)\n .map(([k]) => k);\n for (const key of oldEntries) {\n registry.delete(key);\n }\n\n // Rescan the changed file via the barrel-aware scanner so an\n // edited barrel re-export picks up newly-referenced files.\n // Pass overwrite=true so updated metadata replaces stale\n // entries from the previous scan.\n await scanBarrelExports(fileId, new Set(), true);\n }\n\n // Let Vite handle the rest — the transform hook will recompile\n return ctx.modules;\n },\n resolveId(id, importer) {\n if (id.startsWith(VIRTUAL_RAW_PREFIX)) {\n return `\\0${id}`;\n }\n\n if (pluginOptions.jit && id.startsWith('angular:jit:')) {\n const filePath = normalizePath(\n resolve(dirname(importer as string), id.split(';')[1]),\n );\n if (id.includes(':style')) {\n markStylePathSafe(resolvedConfig, filePath);\n return filePath + '?inline';\n }\n return toVirtualRawId(filePath);\n }\n\n const rawRewrite = rewriteHtmlRawImport(id, importer);\n if (rawRewrite) return rawRewrite;\n\n // User `.scss?inline` / `.css?inline` imports: resolve and mark\n // safe so Vite's native CSS pipeline handles them.\n if (/\\.(css|scss|sass|less)\\?inline$/.test(id) && importer) {\n const filePath = id.split('?')[0];\n const resolved = isAbsolute(filePath)\n ? normalizePath(filePath)\n : normalizePath(resolve(dirname(importer), filePath));\n markStylePathSafe(resolvedConfig, resolved);\n return resolved + '?inline';\n }\n\n return undefined;\n },\n async load(id) {\n const rawModule = await loadVirtualRawModule(this, id);\n if (rawModule !== undefined) return rawModule;\n\n // Vitest fallback: module-runner can skip resolveId, so the bare\n // ?inline query reaches load. Mark safe and let Vite handle it.\n if (/\\.(css|scss|sass|less)\\?inline$/.test(id)) {\n markStylePathSafe(resolvedConfig, id.split('?')[0]);\n }\n\n return;\n },\n transform: {\n filter: {\n id: {\n include: [TS_EXT_REGEX],\n // `?raw` ids already carry Vite's native raw-loader output\n // (`export default \"<source>\"`). Recompiling them as Angular/TS\n // would strip that default export, so leave them to Vite (#2356).\n exclude: [\n /node_modules/,\n 'type=script',\n '@ng/component',\n /[?&]raw\\b/,\n ],\n },\n },\n async handler(code, id) {\n if (transformFilter && !transformFilter(code, id)) {\n return;\n }\n\n if (id.includes('.ts?')) {\n id = id.replace(/\\?(.*)/, '');\n }\n return handleFastCompileTransform(code, id);\n },\n },\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"fast-compile-plugin.js","names":[],"sources":["../../../src/lib/fast-compile-plugin.ts"],"sourcesContent":["import { promises as fsPromises } from 'node:fs';\nimport { dirname, isAbsolute, resolve } from 'node:path';\nimport { parseSync } from 'oxc-parser';\nimport * as vite from 'vite';\n\nimport * as compilerCli from '@angular/compiler-cli';\nimport { normalizePath, Plugin, preprocessCSS, ResolvedConfig } from 'vite';\n\nimport {\n compile,\n scanFile,\n scanPackageDts,\n collectImportedPackages,\n collectRelativeReExports,\n collectAllImports,\n jitTransform,\n inlineResourceUrls,\n extractInlineStyles,\n generateHmrCode,\n debugCompile,\n debugRegistry,\n ANGULAR_DECORATOR_CALL_RE,\n type ComponentRegistry,\n} from './compiler/index.js';\n\nimport {\n TS_EXT_REGEX,\n getTsConfigPath,\n createDepOptimizerConfig,\n isProdMode,\n type TsConfigResolutionContext,\n} from './utils/plugin-config.js';\nimport { releaseCssPreprocessorWorkers } from './utils/css-preprocessor-workers.js';\nimport { VIRTUAL_RAW_PREFIX, toVirtualRawId } from './utils/virtual-ids.js';\nimport {\n loadVirtualRawModule,\n rewriteHtmlRawImport,\n} from './utils/virtual-resources.js';\nimport { markStylePathSafe } from './utils/safe-module-paths.js';\nimport {\n discoverAnalogIntegrations,\n type ComponentRegistryEntries,\n type TransformFilter,\n} from './analog-plugin-interop.js';\n\nexport interface FastCompilePluginOptions {\n tsconfigGetter: () => string;\n workspaceRoot: string;\n inlineStylesExtension: string;\n jit: boolean;\n liveReload: boolean;\n supportedBrowsers: string[];\n isTest: boolean;\n isAstroIntegration: boolean;\n fastCompileMode?: 'full' | 'partial';\n}\n\n/**\n * Directory that `compilerOptions.paths` targets resolve against. Mirrors\n * TypeScript: `baseUrl` when set, otherwise the directory of the config\n * that declares `paths` (`pathsBasePath`, since `baseUrl` is optional\n * from TS 4.1).\n */\nexport function getPathsBasePath(\n options: { baseUrl?: string; pathsBasePath?: string } | undefined,\n fallback: string,\n): string {\n return options?.baseUrl ?? options?.pathsBasePath ?? fallback;\n}\n\nexport function fastCompilePlugin(\n pluginOptions: FastCompilePluginOptions,\n): Plugin {\n let resolvedConfig: ResolvedConfig;\n let transformFilter: TransformFilter | undefined;\n let componentRegistries: ComponentRegistryEntries[] = [];\n let tsConfigResolutionContext: TsConfigResolutionContext | null = null;\n let watchMode = false;\n\n // fast-compile plugin state\n const registry: ComponentRegistry = new Map();\n const resourceToSource = new Map<string, string>();\n const scannedDtsPackages = new Set<string>();\n let projectRoot = '';\n let useDefineForClassFields = true;\n\n /**\n * Scan a file into the registry, then recursively walk its relative\n * `export *` / `export { … } from './x'` chain so any underlying\n * directive classes also land in the registry. Used both at\n * `buildStart` (for tsconfig path entries) and at dev time (file\n * `add` and `handleHotUpdate`) so newly added barrels stay in sync\n * without requiring a server restart.\n *\n * The `visited` set prevents infinite recursion within a single\n * top-level call. Each fresh scan should pass an empty set (so HMR\n * re-scans aren't blocked by buildStart's earlier visits).\n *\n * `fileContents`/`scanResults` are cold-start dedup caches scoped to a\n * single `initFastCompile` call. HMR/watcher callers must omit them so\n * an edited file is always re-read from disk.\n */\n async function scanBarrelExports(\n file: string,\n visited: Set<string> = new Set(),\n overwrite = false,\n fileContents?: Map<string, string>,\n scanResults?: Map<string, ReturnType<typeof scanFile>>,\n ): Promise<void> {\n if (visited.has(file)) return;\n visited.add(file);\n let code: string;\n try {\n code =\n fileContents?.get(file) ?? (await fsPromises.readFile(file, 'utf-8'));\n fileContents?.set(file, code);\n } catch (e) {\n if (debugRegistry.enabled) {\n debugRegistry(\n 'scanBarrelExports: failed to read %s: %s',\n file,\n (e as Error)?.message,\n );\n }\n return;\n }\n // Single parse shared by scanFile and collectRelativeReExports. On a\n // parse error each consumer re-parses on its own, preserving their\n // individual failure semantics (scanFile throws past its pre-filter;\n // collectRelativeReExports swallows and returns []).\n let program: ReturnType<typeof parseSync>['program'] | undefined;\n try {\n program = parseSync(file, code).program;\n } catch {\n program = undefined;\n }\n let entries = scanResults?.get(file);\n if (!entries) {\n entries = scanFile(code, file, program);\n scanResults?.set(file, entries);\n }\n for (const entry of entries) {\n // At buildStart we want stable registry entries (don't overwrite\n // an earlier scan with a barrel re-scan); HMR explicitly asks\n // for overwrite so updated metadata replaces stale entries.\n if (overwrite || !registry.has(entry.className)) {\n registry.set(entry.className, entry);\n }\n }\n // Collect every relative re-export specifier via OXC AST so\n // recursive scans can't trip over each other (a shared `/g` regex\n // would have its `lastIndex` reset by each recursive call and\n // silently skip half of an outer barrel's re-exports, which\n // previously left directives like `HlmRadioGroup` unregistered).\n const dir = dirname(file);\n for (const rel of collectRelativeReExports(code, file, program)) {\n // NodeNext-style libraries write `export * from './foo.js'`\n // even though the source is `./foo.ts`. Strip the ESM\n // extension before probing or the candidates would be\n // `foo.js.ts` / `foo.js/index.ts`, which never exist.\n const normalizedRel = rel.replace(/\\.(?:js|mjs)$/u, '');\n const reExportCandidates = [\n resolve(dir, normalizedRel + '.ts'),\n resolve(dir, normalizedRel, 'index.ts'),\n ];\n let resolved = false;\n for (const candidate of reExportCandidates) {\n try {\n await fsPromises.access(candidate);\n await scanBarrelExports(\n candidate,\n visited,\n overwrite,\n fileContents,\n scanResults,\n );\n resolved = true;\n break;\n } catch {\n // try next candidate\n }\n }\n if (!resolved && debugRegistry.enabled) {\n debugRegistry(\n 'scanBarrelExports: %s re-export %s did not resolve to %o',\n file,\n rel,\n reExportCandidates,\n );\n }\n }\n }\n\n async function initFastCompile() {\n if (pluginOptions.jit) return; // JIT: no registry scan needed\n\n // Scan all source files to build the registry\n registry.clear();\n scannedDtsPackages.clear();\n const resolvedTsConfigPath = resolveTsConfigPath();\n projectRoot = dirname(resolvedTsConfigPath);\n const config = compilerCli.readConfiguration(resolvedTsConfigPath);\n useDefineForClassFields = config.options?.useDefineForClassFields ?? true;\n\n // Collect candidate files: tsconfig rootNames PLUS the entry points\n // named in `compilerOptions.paths`. App tsconfigs typically only\n // include the app's own sources, so workspace library entry barrels\n // (e.g. `HlmSelectImports = [HlmSelect, HlmSelectContent, ...] as\n // const`) live outside `rootNames` and would otherwise miss the\n // initial scan. The compiler then can't see that `HlmSelectImports`\n // is a tuple barrel and emits the bare identifier into the parent\n // component's `dependencies()` list, where Angular's runtime\n // silently drops it because arrays don't have a directive def.\n const candidates = new Set<string>(config.rootNames);\n const tsPaths = config.options?.paths;\n const baseUrl = getPathsBasePath(config.options, projectRoot);\n // Cold-start dedup caches shared by the three scan phases below\n // (candidates scan, walkImports, scanBarrelExports). Scoped to this\n // init call only — HMR/watcher re-scans must hit disk fresh.\n const fileContents = new Map<string, string>();\n const scanResults = new Map<string, ReturnType<typeof scanFile>>();\n if (tsPaths) {\n for (const targets of Object.values(tsPaths)) {\n for (const target of targets as string[]) {\n // Skip wildcard patterns — entry barrels are normally exact\n // file paths like \"libs/helm/select/src/index.ts\".\n if (target.includes('*')) continue;\n candidates.add(resolve(baseUrl, target));\n }\n }\n }\n const results = await Promise.all(\n Array.from(candidates).map(async (file) => {\n try {\n const code = await fsPromises.readFile(file, 'utf-8');\n fileContents.set(file, code);\n const entries = scanFile(code, file);\n scanResults.set(file, entries);\n return entries;\n } catch (e) {\n if (debugRegistry.enabled) {\n debugRegistry(\n 'initFastCompile: skipping unreadable %s: %s',\n file,\n (e as Error)?.message,\n );\n }\n return []; // Skip unreadable files\n }\n }),\n );\n\n for (const entries of results) {\n for (const entry of entries) {\n registry.set(entry.className, entry);\n }\n }\n\n // Walk the transitive import graph from the root files so the registry also\n // contains declarations that live in files not directly in tsconfig\n // `files`/`include` (transitively-imported app sources) and in workspace\n // libraries reached through wildcard `paths` (e.g. `@bitwarden/*`). Without\n // this, a non-standalone component's owning module can't classify its\n // declarations and `ɵɵsetComponentScope` is never emitted for it. Only\n // relative imports and `paths`-mapped (project/workspace) bare specifiers are\n // followed; true `node_modules` packages are left to the lazy `.d.ts` scanner.\n // Return *all* candidate base paths a bare specifier maps to. A `paths`\n // entry can list several fallback targets (e.g. a built `dist` path first\n // and the workspace `src` second); the caller probes them in order.\n const resolvePathSpecifier = (spec: string): string[] => {\n if (!tsPaths) return [];\n for (const [key, targets] of Object.entries(tsPaths)) {\n const list = targets as string[];\n if (key.endsWith('/*')) {\n const prefix = key.slice(0, -1);\n if (spec.startsWith(prefix)) {\n // `split('*').join(...)` substitutes the single tsconfig `*`\n // wildcard without `String.replace`'s first-match-only behavior or\n // `$`-pattern interpretation of the replacement.\n return list.map((t) =>\n resolve(baseUrl, t.split('*').join(spec.slice(prefix.length))),\n );\n }\n } else if (key === spec) {\n return list.map((t) => resolve(baseUrl, t));\n }\n }\n return [];\n };\n const probeToSource = async (base: string): Promise<string | null> => {\n const candidates = base.endsWith('.ts')\n ? [base]\n : [base + '.ts', resolve(base, 'index.ts')];\n for (const candidate of candidates) {\n try {\n await fsPromises.access(candidate);\n return candidate;\n } catch {\n // try next candidate\n }\n }\n return null;\n };\n // Memoize fs probes per absolute base path. The cache stores the\n // Promise (not the settled value) so concurrent walks racing on the\n // same base collapse into a single probe.\n const baseResolveCache = new Map<string, Promise<string | null>>();\n const resolveToSource = (base: string): Promise<string | null> => {\n let probe = baseResolveCache.get(base);\n if (!probe) {\n probe = probeToSource(base);\n baseResolveCache.set(base, probe);\n }\n return probe;\n };\n // Probe each `paths` target in order; first one that resolves to source wins.\n const resolveFirstSource = async (\n bases: string[],\n ): Promise<string | null> => {\n for (const base of bases) {\n const resolved = await resolveToSource(base);\n if (resolved) return resolved;\n }\n return null;\n };\n const importWalkVisited = new Set<string>();\n // Paths-mapped resolution doesn't depend on the importer, so bare\n // specifiers can be memoized by their raw text. Relative specifiers\n // must NOT be — the same './foo' resolves differently per directory.\n const bareSpecResolveCache = new Map<string, Promise<string | null>>();\n const walkImports = async (file: string): Promise<void> => {\n if (importWalkVisited.has(file)) return;\n importWalkVisited.add(file);\n let code: string;\n try {\n code =\n fileContents.get(file) ?? (await fsPromises.readFile(file, 'utf-8'));\n fileContents.set(file, code);\n } catch {\n return;\n }\n // Single parse shared by scanFile, collectImportedPackages, and\n // collectAllImports. On a parse error each consumer re-parses on\n // its own, preserving their individual failure semantics.\n let program: ReturnType<typeof parseSync>['program'] | undefined;\n try {\n program = parseSync(file, code).program;\n } catch {\n program = undefined;\n }\n let entries = scanResults.get(file);\n if (!entries) {\n entries = scanFile(code, file, program);\n scanResults.set(file, entries);\n }\n for (const entry of entries) {\n if (!registry.has(entry.className))\n registry.set(entry.className, entry);\n }\n // Pre-scan the `.d.ts` of every external package this file imports (and,\n // transitively, packages those packages' NgModules re-export — e.g.\n // BrowserModule → CommonModule → NgIf). Doing this at buildStart means the\n // registry is complete before any component transforms, so non-standalone\n // component scope resolves regardless of file transform order.\n for (const pkg of collectImportedPackages(code, file, program)) {\n if (scannedDtsPackages.has(pkg)) continue;\n scannedDtsPackages.add(pkg);\n try {\n for (const entry of scanPackageDts(\n pkg,\n projectRoot,\n scannedDtsPackages,\n )) {\n if (!registry.has(entry.className))\n registry.set(entry.className, entry);\n }\n } catch {\n // Package may not have .d.ts or not be Angular\n }\n }\n const dir = dirname(file);\n const targets = await Promise.all(\n collectAllImports(code, file, program).map((spec) => {\n if (spec.startsWith('.')) {\n return resolveToSource(\n resolve(dir, spec.replace(/\\.(?:js|mjs)$/u, '')),\n );\n }\n let resolved = bareSpecResolveCache.get(spec);\n if (!resolved) {\n resolved = resolveFirstSource(resolvePathSpecifier(spec));\n bareSpecResolveCache.set(spec, resolved);\n }\n return resolved;\n }),\n );\n await Promise.all(\n targets.filter((t): t is string => !!t).map((t) => walkImports(t)),\n );\n };\n await Promise.all(config.rootNames.map((file) => walkImports(file)));\n\n // Library barrels typically `export * from './lib/...'` rather than\n // declaring directives directly, so the entry file alone gives us\n // the tuple consts but not the directive classes they reference.\n // Walk the relative `export *` chain so the underlying classes also\n // land in the registry. Use a SHARED visited set across all\n // barrels so recursive walks don't double-scan a file that's\n // re-exported from multiple entry points.\n const buildStartVisited = new Set<string>();\n if (tsPaths) {\n const barrelCandidates: string[] = [];\n for (const targets of Object.values(tsPaths)) {\n for (const target of targets as string[]) {\n if (target.includes('*')) continue;\n barrelCandidates.push(resolve(baseUrl, target));\n }\n }\n await Promise.all(\n barrelCandidates.map((c) =>\n scanBarrelExports(\n c,\n buildStartVisited,\n false,\n fileContents,\n scanResults,\n ),\n ),\n );\n }\n debugRegistry(\n 'initFastCompile done: %d entries from %d candidate files',\n registry.size,\n candidates.size,\n );\n }\n\n function ensureDtsRegistryForSource(\n code: string,\n id: string,\n program?: ReturnType<typeof parseSync>['program'],\n ) {\n for (const pkg of collectImportedPackages(code, id, program)) {\n if (scannedDtsPackages.has(pkg)) continue;\n scannedDtsPackages.add(pkg);\n\n try {\n const dtsEntries = scanPackageDts(pkg, projectRoot, scannedDtsPackages);\n for (const entry of dtsEntries) {\n if (!registry.has(entry.className)) {\n registry.set(entry.className, entry);\n }\n }\n } catch {\n // Package may not have .d.ts files or may not be Angular\n }\n }\n }\n\n async function handleFastCompileTransform(\n code: string,\n id: string,\n ): Promise<{ code: string; map: any } | undefined> {\n if (!ANGULAR_DECORATOR_CALL_RE.test(code)) {\n // Non-Angular file — strip TS-only syntax ourselves so barrels\n // like `export { Foo, type Bar } from './x'` and other TS-only\n // forms don't leak unstripped to Rolldown. In rolldown-vite the\n // built-in `vite:oxc` strip is registered as a Rust-side native\n // plugin (`viteTransformPlugin` from `rolldown/experimental`); if\n // its hook-filter treats files our `transform.filter.id.include`\n // claimed as already-handled, no JS-side fallback runs and raw\n // TS reaches the parser → `SyntaxError: Unexpected identifier`.\n const stripped = vite.transformWithOxc\n ? await vite.transformWithOxc(code, id, {\n lang: 'ts',\n sourcemap: true,\n decorator: { legacy: false, emitDecoratorMetadata: false },\n })\n : await vite.transformWithEsbuild(code, id, {\n loader: 'ts',\n sourcemap: true,\n });\n return { code: stripped.code, map: stripped.map };\n }\n\n // JIT mode\n if (pluginOptions.jit) {\n const result = jitTransform(code, id);\n // Strip TypeScript-only syntax (e.g. `readonly`, parameter property\n // modifiers, type annotations on fields) so the output is valid JS\n // for Rolldown. `angularVitestSourcemapPlugin` normally runs this\n // strip downstream in tests, but it is intentionally skipped on\n // StackBlitz / WebContainer — and the production build pipeline\n // does not register it either — so the JIT path must self-strip\n // to stay safe across environments.\n //\n // Pass the jitTransform map as `inMap` so OXC/esbuild emit a map\n // composed with the original `.ts` source — without this, debug\n // stack traces and breakpoints land on the wrong lines once the\n // strip removes any TS-only token. `jitTransform` returns\n // `map: null` for files with no Angular class (no edits made);\n // passing that to OXC/esbuild as `inMap` throws, so coerce to\n // `undefined` in that case.\n const inMap = result.map ?? undefined;\n const stripped = vite.transformWithOxc\n ? await vite.transformWithOxc(\n result.code,\n id,\n {\n lang: 'ts',\n sourcemap: true,\n decorator: { legacy: false, emitDecoratorMetadata: false },\n },\n inMap,\n )\n : await vite.transformWithEsbuild(\n result.code,\n id,\n { loader: 'ts', sourcemap: true },\n inMap,\n );\n return { code: stripped.code, map: stripped.map };\n }\n\n // Inline external templateUrl/styleUrl(s) into the source before compilation.\n // `styleExtensions` carries the source extension of each inlined external\n // style so it can be preprocessed by its own file type (e.g. an external\n // `.scss` styleUrl) regardless of the `inlineStylesExtension` option.\n const inlined = await inlineResourceUrls(code, id);\n code = inlined.code;\n const { styleExtensions } = inlined;\n\n // Track inlined resources for HMR. `compile()` only reports resources it\n // reads through its own fallback (a templateUrl/styleUrl the inliner did\n // NOT already inline), so files inlined here must be recorded here or a\n // later edit to them never invalidates the owning module.\n for (const dep of inlined.resourceDependencies) {\n resourceToSource.set(dep, id);\n }\n\n // Single OXC parse of the post-inline source, shared by every AST\n // consumer below. `inlineResourceUrls` parsed the PRE-inline string,\n // so its program can never be reused here.\n const { program: oxcProgram } = parseSync(id, code);\n\n // Pre-resolve inline styles that need preprocessing (SCSS/Sass/Less). Run\n // whenever a style needs a non-`css` preprocessor — either the configured\n // `inlineStylesExtension` for truly-inline styles, or an external styleUrl's\n // own extension.\n let resolvedStyles: Map<string, string> | undefined;\n let resolvedInlineStyles: Map<number, string> | undefined;\n\n const inlineExt = pluginOptions.inlineStylesExtension;\n const styleNeedsPreprocess = (ext: string) => ext !== '' && ext !== 'css';\n\n if (styleNeedsPreprocess(inlineExt) || styleExtensions.size > 0) {\n const styleStrings = extractInlineStyles(code, id, oxcProgram);\n\n if (styleStrings.length > 0) {\n resolvedInlineStyles = new Map();\n for (let i = 0; i < styleStrings.length; i++) {\n // External styleUrls are preprocessed by their own extension; truly\n // inline `styles: [...]` fall back to `inlineStylesExtension`.\n const ext = styleExtensions.get(i) ?? inlineExt;\n if (!styleNeedsPreprocess(ext)) continue;\n try {\n const fakePath = id.replace(/\\.ts$/, `.inline-${i}.${ext}`);\n const processed = await preprocessCSS(\n styleStrings[i],\n fakePath,\n resolvedConfig,\n );\n resolvedInlineStyles.set(i, processed.code);\n } catch (e) {\n if (debugCompile.enabled) {\n debugCompile(\n 'inline style #%d preprocessing failed in %s: %s',\n i,\n id,\n (e as Error)?.message,\n );\n }\n // Skip styles that can't be preprocessed\n }\n }\n if (resolvedInlineStyles.size === 0) resolvedInlineStyles = undefined;\n }\n }\n\n ensureDtsRegistryForSource(code, id, oxcProgram);\n\n // Merge registries contributed through `analog.setup()` into this\n // compile's lookup view. Out-of-tree compilers register directive\n // metadata for classes fastCompile can't reach through its\n // tsconfig-driven scan (e.g. `.tsrx` files compiled by `@tsrx/analog`).\n // Without this merge, a TS `@Component({ imports: [X] })` that\n // references such a class hits `_unresolved-${className}` as its\n // selector and the tag never matches at runtime.\n let compileRegistry: ComponentRegistry = registry;\n if (componentRegistries.some((external) => external.size > 0)) {\n compileRegistry = new Map(registry);\n for (const external of componentRegistries) {\n for (const [k, v] of external) compileRegistry.set(k, v);\n }\n }\n\n const result = compile(code, id, {\n registry: compileRegistry,\n resolvedStyles,\n resolvedInlineStyles,\n useDefineForClassFields,\n compilationMode: pluginOptions.fastCompileMode,\n oxcProgram,\n });\n\n // Track resource dependencies for HMR\n for (const dep of result.resourceDependencies) {\n resourceToSource.set(dep, id);\n }\n\n // Strip TypeScript-only syntax and compose the compiler map with the\n // final generated code so downstream breakpoints map back to the source.\n const stripped = vite.transformWithOxc\n ? await vite.transformWithOxc(\n result.code,\n id,\n {\n lang: 'ts',\n sourcemap: true,\n decorator: { legacy: false, emitDecoratorMetadata: false },\n },\n result.map,\n )\n : await vite.transformWithEsbuild(\n result.code,\n id,\n { loader: 'ts', sourcemap: true },\n result.map,\n );\n let outputCode = stripped.code;\n\n // Append HMR code in dev mode\n if (watchMode && pluginOptions.liveReload) {\n const fileDeclarations = [...registry.values()].filter(\n (e) => e.fileName === id,\n );\n if (fileDeclarations.length > 0) {\n const localDepClassNames = fileDeclarations.map((e) => e.className);\n outputCode += generateHmrCode(fileDeclarations, localDepClassNames);\n }\n }\n\n return { code: outputCode, map: stripped.map };\n }\n\n function resolveTsConfigPath() {\n const { root, isProd, isLib } = tsConfigResolutionContext!;\n return getTsConfigPath(\n root,\n pluginOptions.tsconfigGetter(),\n isProd,\n pluginOptions.isTest,\n isLib,\n pluginOptions.workspaceRoot,\n );\n }\n\n return {\n name: '@analogjs/vite-plugin-angular-fast-compile',\n enforce: 'pre' as const,\n async config(config, { command }) {\n watchMode = command === 'serve';\n const isProd = isProdMode(config.mode);\n\n tsConfigResolutionContext = {\n root: config.root || '.',\n isProd,\n isLib: !!config?.build?.lib,\n };\n\n const preliminaryTsConfigPath = resolveTsConfigPath();\n\n const depOptimizer = createDepOptimizerConfig({\n tsconfig: preliminaryTsConfigPath,\n isProd,\n jit: pluginOptions.jit,\n watchMode,\n isTest: pluginOptions.isTest,\n isAstroIntegration: pluginOptions.isAstroIntegration,\n });\n\n // No `resolve.conditions` extension here: the `style` condition is\n // scoped to `.css`-extension requests by\n // `cssExtensionStyleResolverPlugin`, registered once at the\n // `angular()` factory level (which is the only public entry point\n // that wires this plugin in).\n return {\n ...(vite.rolldownVersion ? { oxc: {} as any } : { esbuild: false }),\n ...depOptimizer,\n };\n },\n async configResolved(config) {\n resolvedConfig = config;\n const integrations = await discoverAnalogIntegrations(config);\n transformFilter = integrations.transformFilter;\n componentRegistries = integrations.componentRegistries;\n },\n configureServer(server) {\n // Watch for new .ts files and scan them into the registry. Use\n // the barrel-aware scanner so a newly added re-export entry\n // (`export * from './x'`) also expands its underlying directive\n // classes — otherwise the registry stays stale until restart.\n server.watcher.on('add', async (filePath) => {\n if (\n filePath.endsWith('.ts') &&\n !filePath.endsWith('.spec.ts') &&\n !filePath.endsWith('.d.ts')\n ) {\n await scanBarrelExports(filePath, new Set(), true);\n }\n });\n },\n async buildStart() {\n await initFastCompile();\n },\n closeBundle() {\n if (!watchMode) {\n releaseCssPreprocessorWorkers();\n }\n },\n async handleHotUpdate(ctx) {\n // Resource file changes → invalidate parent .ts module\n if (resourceToSource.has(ctx.file)) {\n const parentSource = resourceToSource.get(ctx.file)!;\n const parentModule = ctx.server.moduleGraph.getModuleById(parentSource);\n if (parentModule) {\n return [parentModule];\n }\n }\n\n if (TS_EXT_REGEX.test(ctx.file)) {\n const [fileId] = ctx.file.split('?');\n\n // Remove old entries from this file\n const oldEntries = [...registry.entries()]\n .filter(([_, v]) => v.fileName === fileId)\n .map(([k]) => k);\n for (const key of oldEntries) {\n registry.delete(key);\n }\n\n // Rescan the changed file via the barrel-aware scanner so an\n // edited barrel re-export picks up newly-referenced files.\n // Pass overwrite=true so updated metadata replaces stale\n // entries from the previous scan.\n await scanBarrelExports(fileId, new Set(), true);\n }\n\n // Let Vite handle the rest — the transform hook will recompile\n return ctx.modules;\n },\n resolveId(id, importer) {\n if (id.startsWith(VIRTUAL_RAW_PREFIX)) {\n return `\\0${id}`;\n }\n\n if (pluginOptions.jit && id.startsWith('angular:jit:')) {\n const filePath = normalizePath(\n resolve(dirname(importer as string), id.split(';')[1]),\n );\n if (id.includes(':style')) {\n markStylePathSafe(resolvedConfig, filePath);\n return filePath + '?inline';\n }\n return toVirtualRawId(filePath);\n }\n\n const rawRewrite = rewriteHtmlRawImport(id, importer);\n if (rawRewrite) return rawRewrite;\n\n // User `.scss?inline` / `.css?inline` imports: resolve and mark\n // safe so Vite's native CSS pipeline handles them.\n if (/\\.(css|scss|sass|less)\\?inline$/.test(id) && importer) {\n const filePath = id.split('?')[0];\n const resolved = isAbsolute(filePath)\n ? normalizePath(filePath)\n : normalizePath(resolve(dirname(importer), filePath));\n markStylePathSafe(resolvedConfig, resolved);\n return resolved + '?inline';\n }\n\n return undefined;\n },\n async load(id) {\n const rawModule = await loadVirtualRawModule(this, id);\n if (rawModule !== undefined) return rawModule;\n\n // Vitest fallback: module-runner can skip resolveId, so the bare\n // ?inline query reaches load. Mark safe and let Vite handle it.\n if (/\\.(css|scss|sass|less)\\?inline$/.test(id)) {\n markStylePathSafe(resolvedConfig, id.split('?')[0]);\n }\n\n return;\n },\n transform: {\n filter: {\n id: {\n include: [TS_EXT_REGEX],\n // `?raw` ids already carry Vite's native raw-loader output\n // (`export default \"<source>\"`). Recompiling them as Angular/TS\n // would strip that default export, so leave them to Vite (#2356).\n exclude: [\n /node_modules/,\n 'type=script',\n '@ng/component',\n /[?&]raw\\b/,\n ],\n },\n },\n async handler(code, id) {\n if (transformFilter && !transformFilter(code, id)) {\n return;\n }\n\n if (id.includes('.ts?')) {\n id = id.replace(/\\?(.*)/, '');\n }\n return handleFastCompileTransform(code, id);\n },\n },\n };\n}\n"],"mappings":"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"}
|
package/src/lib/router-plugin.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { JavaScriptTransformer } from "./utils/devkit.js";
|
|
2
2
|
import { createPersistentTransformCache, resolveTransformCacheDir, withMemoryLayer } from "./utils/transform-cache.js";
|
|
3
3
|
//#region packages/vite-plugin-angular/src/lib/router-plugin.ts
|
|
4
4
|
function routerPlugin() {
|
|
@@ -10,7 +10,7 @@ function routerPlugin() {
|
|
|
10
10
|
}
|
|
11
11
|
};
|
|
12
12
|
const persistentDir = resolveTransformCacheDir(process.cwd());
|
|
13
|
-
const javascriptTransformer = new
|
|
13
|
+
const javascriptTransformer = new JavaScriptTransformer({ jit: true }, 1, persistentDir ? withMemoryLayer(createPersistentTransformCache(persistentDir)) : memoryOnly);
|
|
14
14
|
/**
|
|
15
15
|
* Transforms Angular packages the didn't get picked up by Vite's pre-optimization.
|
|
16
16
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"router-plugin.js","names":[],"sources":["../../../src/lib/router-plugin.ts"],"sourcesContent":["import type { Plugin } from 'vite';\nimport { JavaScriptTransformer } from './utils/devkit.js';\nimport {\n createPersistentTransformCache,\n resolveTransformCacheDir,\n withMemoryLayer,\n type TransformCacheStore,\n} from './utils/transform-cache.js';\n\nexport function routerPlugin(): Plugin {\n const memoryCache = new Map<string, Uint8Array>();\n const memoryOnly: TransformCacheStore = {\n get: (key: string) => memoryCache.get(key),\n put: (key: string, value: Uint8Array) => {\n memoryCache.set(key, value);\n },\n };\n const persistentDir = resolveTransformCacheDir(process.cwd());\n const javascriptTransformer = new JavaScriptTransformer(\n { jit: true },\n 1,\n persistentDir\n ? withMemoryLayer(createPersistentTransformCache(persistentDir))\n : memoryOnly,\n );\n\n /**\n * Transforms Angular packages the didn't get picked up by Vite's pre-optimization.\n */\n return {\n name: 'analogjs-router-optimization',\n enforce: 'pre',\n apply: 'serve',\n buildEnd() {\n return javascriptTransformer.close();\n },\n transform: {\n filter: {\n id: /fesm(.*?)\\.mjs/,\n },\n async handler(_code: string, id: string) {\n const path = id.split('?')[0];\n const contents = await javascriptTransformer.transformFile(path);\n\n return {\n code: Buffer.from(contents).toString('utf-8'),\n };\n },\n },\n };\n}\n"],"mappings":";;;AASA,SAAgB,eAAuB;CACrC,MAAM,8BAAc,IAAI,KAAyB;CACjD,MAAM,aAAkC;EACtC,MAAM,QAAgB,YAAY,IAAI,IAAI;EAC1C,MAAM,KAAa,UAAsB;AACvC,eAAY,IAAI,KAAK,MAAM;;EAE9B;CACD,MAAM,gBAAgB,yBAAyB,QAAQ,KAAK,CAAC;CAC7D,MAAM,wBAAwB,IAAI,
|
|
1
|
+
{"version":3,"file":"router-plugin.js","names":[],"sources":["../../../src/lib/router-plugin.ts"],"sourcesContent":["import type { Plugin } from 'vite';\nimport { JavaScriptTransformer } from './utils/devkit.js';\nimport {\n createPersistentTransformCache,\n resolveTransformCacheDir,\n withMemoryLayer,\n type TransformCacheStore,\n} from './utils/transform-cache.js';\n\nexport function routerPlugin(): Plugin {\n const memoryCache = new Map<string, Uint8Array>();\n const memoryOnly: TransformCacheStore = {\n get: (key: string) => memoryCache.get(key),\n put: (key: string, value: Uint8Array) => {\n memoryCache.set(key, value);\n },\n };\n const persistentDir = resolveTransformCacheDir(process.cwd());\n const javascriptTransformer = new JavaScriptTransformer(\n { jit: true },\n 1,\n persistentDir\n ? withMemoryLayer(createPersistentTransformCache(persistentDir))\n : memoryOnly,\n );\n\n /**\n * Transforms Angular packages the didn't get picked up by Vite's pre-optimization.\n */\n return {\n name: 'analogjs-router-optimization',\n enforce: 'pre',\n apply: 'serve',\n buildEnd() {\n return javascriptTransformer.close();\n },\n transform: {\n filter: {\n id: /fesm(.*?)\\.mjs/,\n },\n async handler(_code: string, id: string) {\n const path = id.split('?')[0];\n const contents = await javascriptTransformer.transformFile(path);\n\n return {\n code: Buffer.from(contents).toString('utf-8'),\n };\n },\n },\n };\n}\n"],"mappings":";;;AASA,SAAgB,eAAuB;CACrC,MAAM,8BAAc,IAAI,KAAyB;CACjD,MAAM,aAAkC;EACtC,MAAM,QAAgB,YAAY,IAAI,IAAI;EAC1C,MAAM,KAAa,UAAsB;AACvC,eAAY,IAAI,KAAK,MAAM;;EAE9B;CACD,MAAM,gBAAgB,yBAAyB,QAAQ,KAAK,CAAC;CAC7D,MAAM,wBAAwB,IAAI,sBAChC,EAAE,KAAK,MAAM,EACb,GACA,gBACI,gBAAgB,+BAA+B,cAAc,CAAC,GAC9D,WACL;;;;AAKD,QAAO;EACL,MAAM;EACN,SAAS;EACT,OAAO;EACP,WAAW;AACT,UAAO,sBAAsB,OAAO;;EAEtC,WAAW;GACT,QAAQ,EACN,IAAI,kBACL;GACD,MAAM,QAAQ,OAAe,IAAY;IACvC,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC;IAC3B,MAAM,WAAW,MAAM,sBAAsB,cAAc,KAAK;AAEhE,WAAO,EACL,MAAM,OAAO,KAAK,SAAS,CAAC,SAAS,QAAQ,EAC9C;;GAEJ;EACF"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Vite's `preprocessCSS` may spawn a fallback Sass/Less/Stylus compiler
|
|
3
|
+
* (`alwaysFakeWorkerWorkerControllerCache`) that is never closed. Unref those
|
|
4
|
+
* child processes so a one-off `vite build` can return the shell.
|
|
5
|
+
*/
|
|
6
|
+
export declare function releaseCssPreprocessorWorkers(): void;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
//#region packages/vite-plugin-angular/src/lib/utils/css-preprocessor-workers.ts
|
|
2
|
+
var PREPROCESSOR_PROCESS_RE = /sass-embedded|dart-sass|sass\.snapshot|[\\/]lessc(?:$|[\s])|[\\/]stylus(?:$|[\s])/i;
|
|
3
|
+
function getActiveHandles() {
|
|
4
|
+
const getHandles = process._getActiveHandles;
|
|
5
|
+
return typeof getHandles === "function" ? getHandles.call(process) : [];
|
|
6
|
+
}
|
|
7
|
+
function isCssPreprocessorProcess(handle) {
|
|
8
|
+
const haystack = `${handle.spawnfile ?? ""} ${(handle.spawnargs ?? []).join(" ")}`;
|
|
9
|
+
return PREPROCESSOR_PROCESS_RE.test(haystack);
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Vite's `preprocessCSS` may spawn a fallback Sass/Less/Stylus compiler
|
|
13
|
+
* (`alwaysFakeWorkerWorkerControllerCache`) that is never closed. Unref those
|
|
14
|
+
* child processes so a one-off `vite build` can return the shell.
|
|
15
|
+
*/
|
|
16
|
+
function releaseCssPreprocessorWorkers() {
|
|
17
|
+
for (const handle of getActiveHandles()) {
|
|
18
|
+
if (!isCssPreprocessorProcess(handle)) continue;
|
|
19
|
+
for (const stream of handle.stdio ?? []) stream?.unref?.();
|
|
20
|
+
handle.stdin?.unref?.();
|
|
21
|
+
handle.stdout?.unref?.();
|
|
22
|
+
handle.stderr?.unref?.();
|
|
23
|
+
handle.unref?.();
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
//#endregion
|
|
27
|
+
export { releaseCssPreprocessorWorkers };
|
|
28
|
+
|
|
29
|
+
//# sourceMappingURL=css-preprocessor-workers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"css-preprocessor-workers.js","names":[],"sources":["../../../../src/lib/utils/css-preprocessor-workers.ts"],"sourcesContent":["type ProcessHandle = {\n spawnfile?: string;\n spawnargs?: string[];\n stdin?: { unref?: () => void };\n stdout?: { unref?: () => void };\n stderr?: { unref?: () => void };\n stdio?: Array<{ unref?: () => void } | null | undefined>;\n unref?: () => void;\n};\n\nconst PREPROCESSOR_PROCESS_RE =\n /sass-embedded|dart-sass|sass\\.snapshot|[\\\\/]lessc(?:$|[\\s])|[\\\\/]stylus(?:$|[\\s])/i;\n\nfunction getActiveHandles(): ProcessHandle[] {\n const getHandles = (\n process as NodeJS.Process & { _getActiveHandles?: () => ProcessHandle[] }\n )._getActiveHandles;\n return typeof getHandles === 'function' ? getHandles.call(process) : [];\n}\n\nfunction isCssPreprocessorProcess(handle: ProcessHandle): boolean {\n const haystack = `${handle.spawnfile ?? ''} ${(handle.spawnargs ?? []).join(\n ' ',\n )}`;\n return PREPROCESSOR_PROCESS_RE.test(haystack);\n}\n\n/**\n * Vite's `preprocessCSS` may spawn a fallback Sass/Less/Stylus compiler\n * (`alwaysFakeWorkerWorkerControllerCache`) that is never closed. Unref those\n * child processes so a one-off `vite build` can return the shell.\n */\nexport function releaseCssPreprocessorWorkers(): void {\n for (const handle of getActiveHandles()) {\n if (!isCssPreprocessorProcess(handle)) {\n continue;\n }\n\n for (const stream of handle.stdio ?? []) {\n stream?.unref?.();\n }\n handle.stdin?.unref?.();\n handle.stdout?.unref?.();\n handle.stderr?.unref?.();\n handle.unref?.();\n }\n}\n"],"mappings":";AAUA,IAAM,0BACJ;AAEF,SAAS,mBAAoC;CAC3C,MAAM,aACJ,QACA;AACF,QAAO,OAAO,eAAe,aAAa,WAAW,KAAK,QAAQ,GAAG,EAAE;;AAGzE,SAAS,yBAAyB,QAAgC;CAChE,MAAM,WAAW,GAAG,OAAO,aAAa,GAAG,IAAI,OAAO,aAAa,EAAE,EAAE,KACrE,IACD;AACD,QAAO,wBAAwB,KAAK,SAAS;;;;;;;AAQ/C,SAAgB,gCAAsC;AACpD,MAAK,MAAM,UAAU,kBAAkB,EAAE;AACvC,MAAI,CAAC,yBAAyB,OAAO,CACnC;AAGF,OAAK,MAAM,UAAU,OAAO,SAAS,EAAE,CACrC,SAAQ,SAAS;AAEnB,SAAO,OAAO,SAAS;AACvB,SAAO,QAAQ,SAAS;AACxB,SAAO,QAAQ,SAAS;AACxB,SAAO,SAAS"}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
import type { JavaScriptTransformer as AngularJavaScriptTransformer } from "@angular/build/private";
|
|
1
2
|
import type { CompilerPluginOptions } from "./compiler-plugin-options.js";
|
|
3
|
+
import type { TransformCacheStore } from "./transform-cache.js";
|
|
2
4
|
declare const angularMajor: unknown;
|
|
3
5
|
declare const angularMinor: unknown;
|
|
4
6
|
declare const angularPatch: unknown;
|
|
@@ -7,4 +9,10 @@ declare let sourceFileCache: any;
|
|
|
7
9
|
declare let cjt: (...args: any[]) => any;
|
|
8
10
|
declare let jt: any;
|
|
9
11
|
declare let createAngularCompilation: (...args: any[]) => any;
|
|
10
|
-
|
|
12
|
+
declare class JavaScriptTransformer extends jt {
|
|
13
|
+
constructor(options: Partial<ConstructorParameters<typeof AngularJavaScriptTransformer>[0]>, maxThreads: number, cache?: TransformCacheStore);
|
|
14
|
+
transformFile(filename: string, skipLinker?: boolean, sideEffects?: boolean, instrumentForCoverage?: boolean): Promise<Uint8Array>;
|
|
15
|
+
transformData(filename: string, data: string, skipLinker: boolean, sideEffects?: boolean, instrumentForCoverage?: boolean): Promise<Uint8Array>;
|
|
16
|
+
close(): Promise<void>;
|
|
17
|
+
}
|
|
18
|
+
export { cjt as createJitResourceTransformer, JavaScriptTransformer, sourceFileCache as SourceFileCache, CompilerPluginOptions, angularMajor, angularMinor, angularPatch, createAngularCompilation, angularFullVersion };
|
package/src/lib/utils/devkit.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { SourceFileCache } from "./source-file-cache.js";
|
|
2
|
+
import { dirname, join } from "node:path";
|
|
2
3
|
import { createRequire } from "node:module";
|
|
3
4
|
import { VERSION } from "@angular/compiler-cli";
|
|
4
5
|
//#region packages/vite-plugin-angular/src/lib/utils/devkit.ts
|
|
@@ -12,6 +13,8 @@ var sourceFileCache;
|
|
|
12
13
|
var cjt;
|
|
13
14
|
var jt;
|
|
14
15
|
var createAngularCompilation;
|
|
16
|
+
var usesTransformOptions = angularFullVersion >= 220200;
|
|
17
|
+
var initializeHash;
|
|
15
18
|
if (angularMajor < 17) throw new Error("AnalogJS is not compatible with Angular v16 and lower");
|
|
16
19
|
else if (angularMajor >= 17 && angularMajor < 18) {
|
|
17
20
|
const cp = require("@angular-devkit/build-angular/src/tools/esbuild/angular/compiler-plugin.js");
|
|
@@ -30,8 +33,43 @@ else if (angularMajor >= 17 && angularMajor < 18) {
|
|
|
30
33
|
cjt = createJitResourceTransformer;
|
|
31
34
|
jt = JavaScriptTransformer;
|
|
32
35
|
createAngularCompilation = createAngularCompilationFn;
|
|
36
|
+
if (usesTransformOptions) ({initializeHash} = require(join(dirname(require.resolve("@angular/build/package.json")), "src/utils/hash.js")));
|
|
33
37
|
}
|
|
38
|
+
var JavaScriptTransformer = class extends jt {
|
|
39
|
+
constructor(options, maxThreads, cache) {
|
|
40
|
+
if (usesTransformOptions) super({
|
|
41
|
+
...options,
|
|
42
|
+
maxConcurrency: maxThreads
|
|
43
|
+
}, cache);
|
|
44
|
+
else super(options, maxThreads, cache);
|
|
45
|
+
}
|
|
46
|
+
async transformFile(filename, skipLinker, sideEffects, instrumentForCoverage) {
|
|
47
|
+
if (usesTransformOptions) {
|
|
48
|
+
await initializeHash();
|
|
49
|
+
return super.transformFile(filename, {
|
|
50
|
+
skipLinker,
|
|
51
|
+
sideEffects: sideEffects === void 0 ? void 0 : async () => sideEffects,
|
|
52
|
+
instrumentForCoverage
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
return super.transformFile(filename, skipLinker, sideEffects, instrumentForCoverage);
|
|
56
|
+
}
|
|
57
|
+
async transformData(filename, data, skipLinker, sideEffects, instrumentForCoverage) {
|
|
58
|
+
if (usesTransformOptions) {
|
|
59
|
+
await initializeHash();
|
|
60
|
+
return super.transformData(filename, data, {
|
|
61
|
+
skipLinker,
|
|
62
|
+
sideEffects: sideEffects === void 0 ? void 0 : async () => sideEffects,
|
|
63
|
+
instrumentForCoverage
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
return super.transformData(filename, data, skipLinker, sideEffects, instrumentForCoverage);
|
|
67
|
+
}
|
|
68
|
+
close() {
|
|
69
|
+
return super.close();
|
|
70
|
+
}
|
|
71
|
+
};
|
|
34
72
|
//#endregion
|
|
35
|
-
export { angularFullVersion, cjt, createAngularCompilation,
|
|
73
|
+
export { JavaScriptTransformer, angularFullVersion, cjt, createAngularCompilation, sourceFileCache };
|
|
36
74
|
|
|
37
75
|
//# sourceMappingURL=devkit.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"devkit.js","names":[],"sources":["../../../../src/lib/utils/devkit.ts"],"sourcesContent":["import { VERSION } from '@angular/compiler-cli';\nimport { createRequire } from 'node:module';\nimport type { CompilerPluginOptions } from './compiler-plugin-options.js';\nimport * as sfc from './source-file-cache.js';\n\nconst require = createRequire(import.meta.url);\n\nconst angularMajor = Number(VERSION.major);\nconst angularMinor = Number(VERSION.minor);\nconst angularPatch = Number(VERSION.patch);\nconst padVersion = (version: number) => String(version).padStart(2, '0');\nconst angularFullVersion = Number(\n `${angularMajor}${padVersion(angularMinor)}${padVersion(angularPatch)}`,\n);\nlet sourceFileCache: any;\nlet cjt: (...args: any[]) => any;\nlet jt: any;\nlet createAngularCompilation: (...args: any[]) => any;\n\nif (angularMajor < 17) {\n throw new Error('AnalogJS is not compatible with Angular v16 and lower');\n} else if (angularMajor >= 17 && angularMajor < 18) {\n const cp = require('@angular-devkit/build-angular/src/tools/esbuild/angular/compiler-plugin.js');\n const {\n createJitResourceTransformer,\n } = require('@angular-devkit/build-angular/src/tools/esbuild/angular/jit-resource-transformer.js');\n const {\n JavaScriptTransformer,\n } = require('@angular-devkit/build-angular/src/tools/esbuild/javascript-transformer.js');\n\n /**\n * Workaround for compatibility with Angular 17.0+\n */\n if (typeof cp['SourceFileCache'] !== 'undefined') {\n sourceFileCache = cp.SourceFileCache;\n } else {\n sourceFileCache = sfc.SourceFileCache;\n }\n\n cjt = createJitResourceTransformer;\n jt = JavaScriptTransformer;\n} else {\n const {\n createJitResourceTransformer,\n JavaScriptTransformer,\n SourceFileCache,\n createAngularCompilation: createAngularCompilationFn,\n } = require('@angular/build/private');\n\n sourceFileCache = SourceFileCache;\n cjt = createJitResourceTransformer;\n jt = JavaScriptTransformer;\n createAngularCompilation = createAngularCompilationFn;\n}\n\nexport {\n cjt as createJitResourceTransformer,\n
|
|
1
|
+
{"version":3,"file":"devkit.js","names":[],"sources":["../../../../src/lib/utils/devkit.ts"],"sourcesContent":["import { VERSION } from '@angular/compiler-cli';\nimport { createRequire } from 'node:module';\nimport { dirname, join } from 'node:path';\nimport type { JavaScriptTransformer as AngularJavaScriptTransformer } from '@angular/build/private';\nimport type { CompilerPluginOptions } from './compiler-plugin-options.js';\nimport type { TransformCacheStore } from './transform-cache.js';\nimport * as sfc from './source-file-cache.js';\n\nconst require = createRequire(import.meta.url);\n\nconst angularMajor = Number(VERSION.major);\nconst angularMinor = Number(VERSION.minor);\nconst angularPatch = Number(VERSION.patch);\nconst padVersion = (version: number) => String(version).padStart(2, '0');\nconst angularFullVersion = Number(\n `${angularMajor}${padVersion(angularMinor)}${padVersion(angularPatch)}`,\n);\nlet sourceFileCache: any;\nlet cjt: (...args: any[]) => any;\nlet jt: any;\nlet createAngularCompilation: (...args: any[]) => any;\nconst usesTransformOptions = angularFullVersion >= 220200;\nlet initializeHash: (() => Promise<void>) | undefined;\n\nif (angularMajor < 17) {\n throw new Error('AnalogJS is not compatible with Angular v16 and lower');\n} else if (angularMajor >= 17 && angularMajor < 18) {\n const cp = require('@angular-devkit/build-angular/src/tools/esbuild/angular/compiler-plugin.js');\n const {\n createJitResourceTransformer,\n } = require('@angular-devkit/build-angular/src/tools/esbuild/angular/jit-resource-transformer.js');\n const {\n JavaScriptTransformer,\n } = require('@angular-devkit/build-angular/src/tools/esbuild/javascript-transformer.js');\n\n /**\n * Workaround for compatibility with Angular 17.0+\n */\n if (typeof cp['SourceFileCache'] !== 'undefined') {\n sourceFileCache = cp.SourceFileCache;\n } else {\n sourceFileCache = sfc.SourceFileCache;\n }\n\n cjt = createJitResourceTransformer;\n jt = JavaScriptTransformer;\n} else {\n const {\n createJitResourceTransformer,\n JavaScriptTransformer,\n SourceFileCache,\n createAngularCompilation: createAngularCompilationFn,\n } = require('@angular/build/private');\n\n sourceFileCache = SourceFileCache;\n cjt = createJitResourceTransformer;\n jt = JavaScriptTransformer;\n createAngularCompilation = createAngularCompilationFn;\n\n if (usesTransformOptions) {\n ({ initializeHash } = require(\n join(\n dirname(require.resolve('@angular/build/package.json')),\n 'src/utils/hash.js',\n ),\n ));\n }\n}\n\n// Keep Angular's private transformer API differences at the compatibility boundary.\nclass JavaScriptTransformer extends jt {\n constructor(\n options: Partial<\n ConstructorParameters<typeof AngularJavaScriptTransformer>[0]\n >,\n maxThreads: number,\n cache?: TransformCacheStore,\n ) {\n if (usesTransformOptions) {\n super({ ...options, maxConcurrency: maxThreads }, cache);\n } else {\n super(options, maxThreads, cache);\n }\n }\n\n async transformFile(\n filename: string,\n skipLinker?: boolean,\n sideEffects?: boolean,\n instrumentForCoverage?: boolean,\n ): Promise<Uint8Array> {\n if (usesTransformOptions) {\n await initializeHash!();\n return super.transformFile(filename, {\n skipLinker,\n sideEffects:\n sideEffects === undefined ? undefined : async () => sideEffects,\n instrumentForCoverage,\n });\n }\n return super.transformFile(\n filename,\n skipLinker,\n sideEffects,\n instrumentForCoverage,\n );\n }\n\n async transformData(\n filename: string,\n data: string,\n skipLinker: boolean,\n sideEffects?: boolean,\n instrumentForCoverage?: boolean,\n ): Promise<Uint8Array> {\n if (usesTransformOptions) {\n await initializeHash!();\n return super.transformData(filename, data, {\n skipLinker,\n sideEffects:\n sideEffects === undefined ? undefined : async () => sideEffects,\n instrumentForCoverage,\n });\n }\n return super.transformData(\n filename,\n data,\n skipLinker,\n sideEffects,\n instrumentForCoverage,\n );\n }\n\n close(): Promise<void> {\n return super.close();\n }\n}\n\nexport {\n cjt as createJitResourceTransformer,\n JavaScriptTransformer,\n sourceFileCache as SourceFileCache,\n CompilerPluginOptions,\n angularMajor,\n angularMinor,\n angularPatch,\n createAngularCompilation,\n angularFullVersion,\n};\n"],"mappings":";;;;;AAQA,IAAM,UAAU,cAAc,OAAO,KAAK,IAAI;AAE9C,IAAM,eAAe,OAAO,QAAQ,MAAM;AAC1C,IAAM,eAAe,OAAO,QAAQ,MAAM;AAC1C,IAAM,eAAe,OAAO,QAAQ,MAAM;AAC1C,IAAM,cAAc,YAAoB,OAAO,QAAQ,CAAC,SAAS,GAAG,IAAI;AACxE,IAAM,qBAAqB,OACzB,GAAG,eAAe,WAAW,aAAa,GAAG,WAAW,aAAa,GACtE;AACD,IAAI;AACJ,IAAI;AACJ,IAAI;AACJ,IAAI;AACJ,IAAM,uBAAuB,sBAAsB;AACnD,IAAI;AAEJ,IAAI,eAAe,GACjB,OAAM,IAAI,MAAM,wDAAwD;SAC/D,gBAAgB,MAAM,eAAe,IAAI;CAClD,MAAM,KAAK,QAAQ,6EAA6E;CAChG,MAAM,EACJ,iCACE,QAAQ,sFAAsF;CAClG,MAAM,EACJ,0BACE,QAAQ,4EAA4E;;;;AAKxF,KAAI,OAAO,GAAG,uBAAuB,YACnC,mBAAkB,GAAG;KAErB,mBAAkB;AAGpB,OAAM;AACN,MAAK;OACA;CACL,MAAM,EACJ,8BACA,uBACA,iBACA,0BAA0B,+BACxB,QAAQ,yBAAyB;AAErC,mBAAkB;AAClB,OAAM;AACN,MAAK;AACL,4BAA2B;AAE3B,KAAI,qBACF,EAAC,CAAE,kBAAmB,QACpB,KACE,QAAQ,QAAQ,QAAQ,8BAA8B,CAAC,EACvD,oBACD,CACF;;AAKL,IAAM,wBAAN,cAAoC,GAAG;CACrC,YACE,SAGA,YACA,OACA;AACA,MAAI,qBACF,OAAM;GAAE,GAAG;GAAS,gBAAgB;GAAY,EAAE,MAAM;MAExD,OAAM,SAAS,YAAY,MAAM;;CAIrC,MAAM,cACJ,UACA,YACA,aACA,uBACqB;AACrB,MAAI,sBAAsB;AACxB,SAAM,gBAAiB;AACvB,UAAO,MAAM,cAAc,UAAU;IACnC;IACA,aACE,gBAAgB,KAAA,IAAY,KAAA,IAAY,YAAY;IACtD;IACD,CAAC;;AAEJ,SAAO,MAAM,cACX,UACA,YACA,aACA,sBACD;;CAGH,MAAM,cACJ,UACA,MACA,YACA,aACA,uBACqB;AACrB,MAAI,sBAAsB;AACxB,SAAM,gBAAiB;AACvB,UAAO,MAAM,cAAc,UAAU,MAAM;IACzC;IACA,aACE,gBAAgB,KAAA,IAAY,KAAA,IAAY,YAAY;IACtD;IACD,CAAC;;AAEJ,SAAO,MAAM,cACX,UACA,MACA,YACA,aACA,sBACD;;CAGH,QAAuB;AACrB,SAAO,MAAM,OAAO"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The `{ get, put }` shape `@angular/build`'s `JavaScriptTransformer`
|
|
3
|
-
* accepts
|
|
3
|
+
* accepts. Keys are content hashes the
|
|
4
4
|
* transformer derives from the file bytes plus every option that affects
|
|
5
5
|
* output, so entries are immutable and never need invalidation — but the
|
|
6
6
|
* digest does NOT cover the linker version, so stores must be namespaced
|
|
@@ -1 +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
|
|
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"}
|
|
@@ -52,13 +52,13 @@ var TsconfigResolver = class {
|
|
|
52
52
|
return this.includeCache;
|
|
53
53
|
}
|
|
54
54
|
readAngularTsconfigConfiguration(resolvedTsConfigPath, config) {
|
|
55
|
-
const
|
|
55
|
+
const emitSourceMaps = !(config.mode === "production") || !!config.build?.sourcemap;
|
|
56
56
|
return compilerCli.readConfiguration(resolvedTsConfigPath, {
|
|
57
57
|
suppressOutputPathCheck: true,
|
|
58
58
|
outDir: void 0,
|
|
59
|
-
sourceMap:
|
|
59
|
+
sourceMap: emitSourceMaps,
|
|
60
60
|
inlineSourceMap: false,
|
|
61
|
-
inlineSources:
|
|
61
|
+
inlineSources: emitSourceMaps,
|
|
62
62
|
declaration: false,
|
|
63
63
|
declarationMap: false,
|
|
64
64
|
allowEmptyCodegenFiles: false,
|
|
@@ -124,11 +124,13 @@ var TsconfigResolver = class {
|
|
|
124
124
|
return expandedRootList;
|
|
125
125
|
}
|
|
126
126
|
getTsconfigCacheKey(resolvedTsConfigPath, config) {
|
|
127
|
+
const isProd = config.mode === "production";
|
|
127
128
|
return [
|
|
128
129
|
resolvedTsConfigPath,
|
|
129
|
-
|
|
130
|
+
isProd ? "prod" : "dev",
|
|
130
131
|
this.options.isTest ? "test" : "app",
|
|
131
132
|
config.build?.lib ? "lib" : "nolib",
|
|
133
|
+
!isProd || config.build?.sourcemap ? "maps" : "nomaps",
|
|
132
134
|
this.options.liveReload ? "live-reload" : "no-live-reload"
|
|
133
135
|
].join("|");
|
|
134
136
|
}
|
|
@@ -1 +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 return compilerCli.readConfiguration(resolvedTsConfigPath, {\n suppressOutputPathCheck: true,\n outDir: undefined,\n sourceMap: !isProd,\n inlineSourceMap: false,\n inlineSources: !isProd,\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 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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"}
|
|
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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"}
|