svelte-docinfo 0.1.0

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.
Files changed (97) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +349 -0
  3. package/dist/analyze-core.d.ts +1386 -0
  4. package/dist/analyze-core.d.ts.map +1 -0
  5. package/dist/analyze-core.js +324 -0
  6. package/dist/analyze.d.ts +137 -0
  7. package/dist/analyze.d.ts.map +1 -0
  8. package/dist/analyze.js +148 -0
  9. package/dist/cli.d.ts +102 -0
  10. package/dist/cli.d.ts.map +1 -0
  11. package/dist/cli.js +206 -0
  12. package/dist/concurrency.d.ts +38 -0
  13. package/dist/concurrency.d.ts.map +1 -0
  14. package/dist/concurrency.js +57 -0
  15. package/dist/declaration-build.d.ts +164 -0
  16. package/dist/declaration-build.d.ts.map +1 -0
  17. package/dist/declaration-build.js +15 -0
  18. package/dist/declaration-helpers.d.ts +169 -0
  19. package/dist/declaration-helpers.d.ts.map +1 -0
  20. package/dist/declaration-helpers.js +239 -0
  21. package/dist/dep-resolver.d.ts +166 -0
  22. package/dist/dep-resolver.d.ts.map +1 -0
  23. package/dist/dep-resolver.js +144 -0
  24. package/dist/diagnostics.d.ts +650 -0
  25. package/dist/diagnostics.d.ts.map +1 -0
  26. package/dist/diagnostics.js +377 -0
  27. package/dist/discovery.d.ts +115 -0
  28. package/dist/discovery.d.ts.map +1 -0
  29. package/dist/discovery.js +126 -0
  30. package/dist/exports.d.ts +105 -0
  31. package/dist/exports.d.ts.map +1 -0
  32. package/dist/exports.js +274 -0
  33. package/dist/files.d.ts +77 -0
  34. package/dist/files.d.ts.map +1 -0
  35. package/dist/files.js +95 -0
  36. package/dist/index.d.ts +32 -0
  37. package/dist/index.d.ts.map +1 -0
  38. package/dist/index.js +30 -0
  39. package/dist/log.d.ts +32 -0
  40. package/dist/log.d.ts.map +1 -0
  41. package/dist/log.js +11 -0
  42. package/dist/logo.d.ts +8 -0
  43. package/dist/logo.d.ts.map +1 -0
  44. package/dist/logo.js +9 -0
  45. package/dist/main.d.ts +11 -0
  46. package/dist/main.d.ts.map +1 -0
  47. package/dist/main.js +18 -0
  48. package/dist/paths.d.ts +35 -0
  49. package/dist/paths.d.ts.map +1 -0
  50. package/dist/paths.js +34 -0
  51. package/dist/postprocess.d.ts +145 -0
  52. package/dist/postprocess.d.ts.map +1 -0
  53. package/dist/postprocess.js +305 -0
  54. package/dist/session.d.ts +248 -0
  55. package/dist/session.d.ts.map +1 -0
  56. package/dist/session.js +496 -0
  57. package/dist/source-config.d.ts +330 -0
  58. package/dist/source-config.d.ts.map +1 -0
  59. package/dist/source-config.js +356 -0
  60. package/dist/source.d.ts +126 -0
  61. package/dist/source.d.ts.map +1 -0
  62. package/dist/source.js +68 -0
  63. package/dist/svelte.d.ts +179 -0
  64. package/dist/svelte.d.ts.map +1 -0
  65. package/dist/svelte.js +898 -0
  66. package/dist/tsdoc.d.ts +145 -0
  67. package/dist/tsdoc.d.ts.map +1 -0
  68. package/dist/tsdoc.js +262 -0
  69. package/dist/types.d.ts +3381 -0
  70. package/dist/types.d.ts.map +1 -0
  71. package/dist/types.js +588 -0
  72. package/dist/typescript-exports.d.ts +91 -0
  73. package/dist/typescript-exports.d.ts.map +1 -0
  74. package/dist/typescript-exports.js +656 -0
  75. package/dist/typescript-extract-class.d.ts +29 -0
  76. package/dist/typescript-extract-class.d.ts.map +1 -0
  77. package/dist/typescript-extract-class.js +251 -0
  78. package/dist/typescript-extract-function.d.ts +47 -0
  79. package/dist/typescript-extract-function.d.ts.map +1 -0
  80. package/dist/typescript-extract-function.js +108 -0
  81. package/dist/typescript-extract-shared.d.ts +166 -0
  82. package/dist/typescript-extract-shared.d.ts.map +1 -0
  83. package/dist/typescript-extract-shared.js +528 -0
  84. package/dist/typescript-extract-type-properties.d.ts +34 -0
  85. package/dist/typescript-extract-type-properties.d.ts.map +1 -0
  86. package/dist/typescript-extract-type-properties.js +241 -0
  87. package/dist/typescript-extract-type.d.ts +48 -0
  88. package/dist/typescript-extract-type.d.ts.map +1 -0
  89. package/dist/typescript-extract-type.js +238 -0
  90. package/dist/typescript-program.d.ts +211 -0
  91. package/dist/typescript-program.d.ts.map +1 -0
  92. package/dist/typescript-program.js +290 -0
  93. package/dist/vite.d.ts +116 -0
  94. package/dist/vite.d.ts.map +1 -0
  95. package/dist/vite.js +418 -0
  96. package/package.json +131 -0
  97. package/virtual-svelte-docinfo.d.ts +49 -0
@@ -0,0 +1,211 @@
1
+ /**
2
+ * TypeScript program and language-service creation.
3
+ *
4
+ * Two entry points sharing host configuration (tsconfig parsing, virtual file
5
+ * plumbing, `.svelte` module resolution):
6
+ *
7
+ * - `createAnalysisProgram` — one-shot `ts.Program` from a `ts.CompilerHost`.
8
+ * Lower-level escape hatch for power users + dependency resolution. Does not
9
+ * support incremental updates.
10
+ * - `createAnalysisLanguageService` — persistent `ts.LanguageService` with
11
+ * versioned `IScriptSnapshot`s. Incremental: subsequent `getProgram()` calls
12
+ * reuse parsed ASTs and checker state for unchanged files. Used by
13
+ * `createAnalysisSession` (in `session.ts`).
14
+ *
15
+ * @see `typescript-exports.ts` for `analyzeExports`, `analyzeDeclaration`
16
+ * @see `typescript-extract-*.ts` for the per-declaration extractors
17
+ * @see `session.ts` for `createAnalysisSession`, the high-level incremental API
18
+ *
19
+ * @module
20
+ */
21
+ import ts from 'typescript';
22
+ import type { AnalysisLog } from './log.js';
23
+ import { type ModuleSourceOptions } from './source-config.js';
24
+ /**
25
+ * Base configuration shared by every entry point in this module.
26
+ *
27
+ * `projectRoot` + `tsconfig` + `compilerOptions` together drive `loadTsconfig`,
28
+ * which is also exposed publicly. `AnalysisProgramOptions` and
29
+ * `AnalysisLanguageServiceOptions` extend this with their own fields.
30
+ */
31
+ export interface LoadTsconfigOptions {
32
+ /**
33
+ * Absolute path to project root directory.
34
+ * @default process.cwd()
35
+ */
36
+ projectRoot?: string;
37
+ /**
38
+ * Path to tsconfig.json (relative to `projectRoot`).
39
+ * @default 'tsconfig.json'
40
+ */
41
+ tsconfig?: string;
42
+ /**
43
+ * Compiler options merged on top of those parsed from `tsconfig.json`
44
+ * (per-key override; user-supplied keys win). Does not bypass the
45
+ * `tsconfig.json` file requirement — `loadTsconfig` still throws when no
46
+ * config file is found.
47
+ */
48
+ compilerOptions?: ts.CompilerOptions;
49
+ }
50
+ /**
51
+ * Options for `createAnalysisProgram`.
52
+ */
53
+ export interface AnalysisProgramOptions extends LoadTsconfigOptions {
54
+ /**
55
+ * Virtual files to seed the program (maps virtual path to content).
56
+ *
57
+ * Used to include svelte2tsx transformed outputs alongside real source files,
58
+ * enabling full type resolution for Svelte components via the checker.
59
+ *
60
+ * On a `LanguageService`, virtuals can also be added/replaced/removed after
61
+ * construction via `setFile` / `deleteFile`.
62
+ */
63
+ virtualFiles?: Map<string, string>;
64
+ }
65
+ /**
66
+ * Options for `createAnalysisLanguageService`.
67
+ */
68
+ export interface AnalysisLanguageServiceOptions extends AnalysisProgramOptions {
69
+ /**
70
+ * Optional document registry for AST sharing across services.
71
+ *
72
+ * Pass an explicit registry to share parsed source files when running
73
+ * multiple language services (e.g., LSP integration). Defaults to a fresh
74
+ * registry per service when omitted.
75
+ */
76
+ documentRegistry?: ts.DocumentRegistry;
77
+ }
78
+ /**
79
+ * Persistent language-service handle that drives a `ts.Program` incrementally.
80
+ *
81
+ * Owns the LS, document registry, and a `Map<path, {content, version}>` of
82
+ * "owned" files (real source files + virtuals pushed via `setFile`). Files
83
+ * not in the owned map are read from disk on demand by the LS host.
84
+ *
85
+ * Each `setFile(path, content)` bumps the version when content differs from
86
+ * cache, so the next `getProgram()` reparses only the changed file. Calling
87
+ * `getProgram()` with no version bumps returns the same `ts.Program` as the
88
+ * previous call (reference-stable when nothing changed).
89
+ *
90
+ * @see `createAnalysisSession` in `session.ts` for the high-level API that
91
+ * wraps this with content cache + svelte virtual cache + analysis pipeline.
92
+ */
93
+ export interface AnalysisLanguageService {
94
+ /**
95
+ * Get the current `ts.Program`.
96
+ *
97
+ * Returns the same reference as the previous call when no `setFile` /
98
+ * `deleteFile` invalidated state in between. Returns a fresh `ts.Program`
99
+ * (sharing parsed ASTs for unchanged files via the document registry) when
100
+ * versions changed.
101
+ *
102
+ * @throws Error if the underlying LS returned undefined (should not happen
103
+ * in practice — TS only returns undefined during initialization)
104
+ */
105
+ getProgram(): ts.Program;
106
+ /**
107
+ * Set or replace a file's content (real path or virtual path).
108
+ *
109
+ * - New file: added to the owned map with version 1.
110
+ * - Existing file with identical content: no-op (version unchanged).
111
+ * - Existing file with new content: version bumped.
112
+ *
113
+ * @returns `true` when the file was added or its version bumped, `false` on no-op.
114
+ */
115
+ setFile(path: string, content: string): boolean;
116
+ /**
117
+ * Remove a file from the owned set.
118
+ *
119
+ * @returns `true` when the file was tracked, `false` when it was unknown.
120
+ */
121
+ deleteFile(path: string): boolean;
122
+ /** Whether the given path is currently tracked. */
123
+ hasFile(path: string): boolean;
124
+ /**
125
+ * Release LS resources.
126
+ *
127
+ * Calls `ts.LanguageService.dispose()` and clears the owned map. The
128
+ * service must not be used after disposal.
129
+ */
130
+ dispose(): void;
131
+ }
132
+ /**
133
+ * Load and parse tsconfig.json into compiler options + initial file list.
134
+ *
135
+ * Shared by `createAnalysisProgram` and `createAnalysisLanguageService` so
136
+ * tsconfig-resolution behavior stays identical across the two paths. Also
137
+ * useful directly when a caller needs only `CompilerOptions` (e.g., import
138
+ * resolution via `ts.resolveModuleName`) without the cost of building a full
139
+ * `ts.Program`.
140
+ *
141
+ * @throws Error if tsconfig.json (or the requested `tsconfigName`) is not found.
142
+ */
143
+ export declare const loadTsconfig: (options?: LoadTsconfigOptions, log?: AnalysisLog) => {
144
+ compilerOptions: ts.CompilerOptions;
145
+ rootFileNames: Array<string>;
146
+ };
147
+ /**
148
+ * Create TypeScript program for one-shot analysis.
149
+ *
150
+ * Use `createAnalysisLanguageService` instead when you need to analyze the
151
+ * same source set multiple times — the LS path reuses parsed ASTs and checker
152
+ * state across calls.
153
+ *
154
+ * @param options - configuration options for program creation
155
+ * @param log - optional logger for info messages
156
+ * @returns the TypeScript program
157
+ * @throws Error if tsconfig.json is not found
158
+ *
159
+ * @example
160
+ * ```ts
161
+ * const program = createAnalysisProgram({projectRoot: process.cwd()});
162
+ * ```
163
+ */
164
+ export declare const createAnalysisProgram: (options?: AnalysisProgramOptions, log?: AnalysisLog) => ts.Program;
165
+ /**
166
+ * Create a persistent language service for incremental analysis.
167
+ *
168
+ * The LS owns parsed source ASTs and checker state across calls. Use the
169
+ * returned handle to push file-content updates (`setFile` / `deleteFile`)
170
+ * between analysis passes; subsequent `getProgram()` calls return either the
171
+ * same `ts.Program` (no changes since last call) or a fresh one that reuses
172
+ * unchanged files via the document registry.
173
+ *
174
+ * @param options - configuration options
175
+ * @param log - optional logger for info messages
176
+ * @returns the language service handle
177
+ * @throws Error if tsconfig.json is not found
178
+ *
179
+ * @example
180
+ * ```ts
181
+ * const ls = createAnalysisLanguageService({projectRoot});
182
+ * ls.setFile('/abs/path/to/foo.ts', 'export const x = 1;');
183
+ * const program = ls.getProgram();
184
+ * // ... use program ...
185
+ * ls.setFile('/abs/path/to/foo.ts', 'export const x = 2;'); // bumps version
186
+ * const program2 = ls.getProgram(); // fresh program, foo.ts reparsed
187
+ * ls.dispose();
188
+ * ```
189
+ */
190
+ export declare const createAnalysisLanguageService: (options?: AnalysisLanguageServiceOptions, log?: AnalysisLog) => AnalysisLanguageService;
191
+ /**
192
+ * Predicate for determining whether a TypeScript source file is external to the project.
193
+ * Used by intersection type filtering to separate user-authored properties from
194
+ * library/framework properties.
195
+ *
196
+ * Constructed from `ModuleSourceOptions` at analysis entry points — files under the
197
+ * source root (e.g., `src/lib/`) are internal, everything else is external.
198
+ */
199
+ export type IsExternalFile = (sourceFile: ts.SourceFile) => boolean;
200
+ /**
201
+ * Create an `IsExternalFile` predicate from `ModuleSourceOptions`.
202
+ *
203
+ * A file is external if it is:
204
+ * - Outside the project root
205
+ * - Inside `node_modules/`
206
+ * - A `.d.ts` declaration file outside the source root (catches framework-generated
207
+ * declarations like `.svelte-kit/non-ambient.d.ts` while keeping user `.d.ts` files
208
+ * in the source tree)
209
+ */
210
+ export declare const createIsExternalFile: (options: ModuleSourceOptions) => IsExternalFile;
211
+ //# sourceMappingURL=typescript-program.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"typescript-program.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/typescript-program.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAGH,OAAO,EAAE,MAAM,YAAY,CAAC;AAE5B,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,UAAU,CAAC;AAE1C,OAAO,EAAC,KAAK,mBAAmB,EAAgB,MAAM,oBAAoB,CAAC;AAG3E;;;;;;GAMG;AACH,MAAM,WAAW,mBAAmB;IACnC;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;;OAKG;IACH,eAAe,CAAC,EAAE,EAAE,CAAC,eAAe,CAAC;CACrC;AAED;;GAEG;AACH,MAAM,WAAW,sBAAuB,SAAQ,mBAAmB;IAClE;;;;;;;;OAQG;IACH,YAAY,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACnC;AAED;;GAEG;AACH,MAAM,WAAW,8BAA+B,SAAQ,sBAAsB;IAC7E;;;;;;OAMG;IACH,gBAAgB,CAAC,EAAE,EAAE,CAAC,gBAAgB,CAAC;CACvC;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,WAAW,uBAAuB;IACvC;;;;;;;;;;OAUG;IACH,UAAU,IAAI,EAAE,CAAC,OAAO,CAAC;IACzB;;;;;;;;OAQG;IACH,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC;IAChD;;;;OAIG;IACH,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;IAClC,mDAAmD;IACnD,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;IAC/B;;;;;OAKG;IACH,OAAO,IAAI,IAAI,CAAC;CAChB;AAED;;;;;;;;;;GAUG;AACH,eAAO,MAAM,YAAY,GACxB,UAAU,mBAAmB,EAC7B,MAAM,WAAW,KACf;IAAC,eAAe,EAAE,EAAE,CAAC,eAAe,CAAC;IAAC,aAAa,EAAE,KAAK,CAAC,MAAM,CAAC,CAAA;CAmBpE,CAAC;AA2BF;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,qBAAqB,GACjC,UAAU,sBAAsB,EAChC,MAAM,WAAW,KACf,EAAE,CAAC,OA8CL,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,eAAO,MAAM,6BAA6B,GACzC,UAAU,8BAA8B,EACxC,MAAM,WAAW,KACf,uBAmIF,CAAC;AAEF;;;;;;;GAOG;AACH,MAAM,MAAM,cAAc,GAAG,CAAC,UAAU,EAAE,EAAE,CAAC,UAAU,KAAK,OAAO,CAAC;AAEpE;;;;;;;;;GASG;AACH,eAAO,MAAM,oBAAoB,GAAI,SAAS,mBAAmB,KAAG,cAQnE,CAAC"}
@@ -0,0 +1,290 @@
1
+ /**
2
+ * TypeScript program and language-service creation.
3
+ *
4
+ * Two entry points sharing host configuration (tsconfig parsing, virtual file
5
+ * plumbing, `.svelte` module resolution):
6
+ *
7
+ * - `createAnalysisProgram` — one-shot `ts.Program` from a `ts.CompilerHost`.
8
+ * Lower-level escape hatch for power users + dependency resolution. Does not
9
+ * support incremental updates.
10
+ * - `createAnalysisLanguageService` — persistent `ts.LanguageService` with
11
+ * versioned `IScriptSnapshot`s. Incremental: subsequent `getProgram()` calls
12
+ * reuse parsed ASTs and checker state for unchanged files. Used by
13
+ * `createAnalysisSession` (in `session.ts`).
14
+ *
15
+ * @see `typescript-exports.ts` for `analyzeExports`, `analyzeDeclaration`
16
+ * @see `typescript-extract-*.ts` for the per-declaration extractors
17
+ * @see `session.ts` for `createAnalysisSession`, the high-level incremental API
18
+ *
19
+ * @module
20
+ */
21
+ import { join, dirname } from 'node:path';
22
+ import ts from 'typescript';
23
+ import { SVELTE_VIRTUAL_SUFFIX } from './source.js';
24
+ import { getSourceRoot } from './source-config.js';
25
+ import { toPosixPath } from './paths.js';
26
+ /**
27
+ * Load and parse tsconfig.json into compiler options + initial file list.
28
+ *
29
+ * Shared by `createAnalysisProgram` and `createAnalysisLanguageService` so
30
+ * tsconfig-resolution behavior stays identical across the two paths. Also
31
+ * useful directly when a caller needs only `CompilerOptions` (e.g., import
32
+ * resolution via `ts.resolveModuleName`) without the cost of building a full
33
+ * `ts.Program`.
34
+ *
35
+ * @throws Error if tsconfig.json (or the requested `tsconfigName`) is not found.
36
+ */
37
+ export const loadTsconfig = (options, log) => {
38
+ const projectRoot = options?.projectRoot ?? process.cwd();
39
+ const tsconfigName = options?.tsconfig ?? 'tsconfig.json';
40
+ const configPath = ts.findConfigFile(projectRoot, ts.sys.fileExists, tsconfigName);
41
+ if (!configPath) {
42
+ throw new Error(`No ${tsconfigName} found in ${projectRoot}`);
43
+ }
44
+ log?.info(`using ${configPath}`);
45
+ const configFile = ts.readConfigFile(configPath, ts.sys.readFile);
46
+ const parsedConfig = ts.parseJsonConfigFileContent(configFile.config, ts.sys, projectRoot);
47
+ const compilerOptions = options?.compilerOptions
48
+ ? { ...parsedConfig.options, ...options.compilerOptions }
49
+ : parsedConfig.options;
50
+ return { compilerOptions, rootFileNames: parsedConfig.fileNames };
51
+ };
52
+ /**
53
+ * Resolve `.svelte` import specifiers to their virtual `.__svelte2tsx__.ts` paths.
54
+ *
55
+ * Shared between the `CompilerHost` and `LanguageServiceHost` paths so cross-Svelte
56
+ * re-exports (`export {X} from './Other.svelte'`) work uniformly. Returns `undefined`
57
+ * for non-Svelte specifiers; the caller falls back to default module resolution.
58
+ */
59
+ const resolveSvelteVirtualSpecifier = (specifier, containingFile, hasVirtual) => {
60
+ if (!specifier.startsWith('.') || !specifier.endsWith('.svelte'))
61
+ return undefined;
62
+ // `join`/`dirname` return native separators on Windows. Posixify so the
63
+ // `hasVirtual` lookup hits the POSIX-keyed virtual map populated by
64
+ // session ingest.
65
+ const resolved = toPosixPath(join(dirname(containingFile), specifier)) + SVELTE_VIRTUAL_SUFFIX;
66
+ if (!hasVirtual(resolved))
67
+ return undefined;
68
+ return {
69
+ resolvedFileName: resolved,
70
+ isExternalLibraryImport: false,
71
+ extension: ts.Extension.Ts,
72
+ };
73
+ };
74
+ /**
75
+ * Create TypeScript program for one-shot analysis.
76
+ *
77
+ * Use `createAnalysisLanguageService` instead when you need to analyze the
78
+ * same source set multiple times — the LS path reuses parsed ASTs and checker
79
+ * state across calls.
80
+ *
81
+ * @param options - configuration options for program creation
82
+ * @param log - optional logger for info messages
83
+ * @returns the TypeScript program
84
+ * @throws Error if tsconfig.json is not found
85
+ *
86
+ * @example
87
+ * ```ts
88
+ * const program = createAnalysisProgram({projectRoot: process.cwd()});
89
+ * ```
90
+ */
91
+ export const createAnalysisProgram = (options, log) => {
92
+ const { compilerOptions, rootFileNames } = loadTsconfig(options, log);
93
+ const virtualFiles = options?.virtualFiles;
94
+ if (!virtualFiles || virtualFiles.size === 0) {
95
+ return ts.createProgram(rootFileNames, compilerOptions);
96
+ }
97
+ // Include virtual file paths alongside real files
98
+ const allRootFiles = [...rootFileNames, ...virtualFiles.keys()];
99
+ const host = ts.createCompilerHost(compilerOptions);
100
+ const originalGetSourceFile = host.getSourceFile;
101
+ const originalFileExists = host.fileExists;
102
+ const originalReadFile = host.readFile;
103
+ host.getSourceFile = (fileName, languageVersion, onError, shouldCreate) => {
104
+ const virtualContent = virtualFiles.get(fileName);
105
+ if (virtualContent !== undefined) {
106
+ return ts.createSourceFile(fileName, virtualContent, languageVersion, true);
107
+ }
108
+ return originalGetSourceFile.call(host, fileName, languageVersion, onError, shouldCreate);
109
+ };
110
+ host.fileExists = (fileName) => {
111
+ if (virtualFiles.has(fileName))
112
+ return true;
113
+ return originalFileExists.call(host, fileName);
114
+ };
115
+ host.readFile = (fileName) => {
116
+ const virtualContent = virtualFiles.get(fileName);
117
+ if (virtualContent !== undefined)
118
+ return virtualContent;
119
+ return originalReadFile.call(host, fileName);
120
+ };
121
+ host.resolveModuleNameLiterals = (literals, containingFile, _redirected, optionsInner) => {
122
+ return literals.map((literal) => {
123
+ const resolved = resolveSvelteVirtualSpecifier(literal.text, containingFile, (p) => virtualFiles.has(p));
124
+ if (resolved)
125
+ return { resolvedModule: resolved };
126
+ return ts.resolveModuleName(literal.text, containingFile, optionsInner, host);
127
+ });
128
+ };
129
+ return ts.createProgram(allRootFiles, compilerOptions, host);
130
+ };
131
+ /**
132
+ * Create a persistent language service for incremental analysis.
133
+ *
134
+ * The LS owns parsed source ASTs and checker state across calls. Use the
135
+ * returned handle to push file-content updates (`setFile` / `deleteFile`)
136
+ * between analysis passes; subsequent `getProgram()` calls return either the
137
+ * same `ts.Program` (no changes since last call) or a fresh one that reuses
138
+ * unchanged files via the document registry.
139
+ *
140
+ * @param options - configuration options
141
+ * @param log - optional logger for info messages
142
+ * @returns the language service handle
143
+ * @throws Error if tsconfig.json is not found
144
+ *
145
+ * @example
146
+ * ```ts
147
+ * const ls = createAnalysisLanguageService({projectRoot});
148
+ * ls.setFile('/abs/path/to/foo.ts', 'export const x = 1;');
149
+ * const program = ls.getProgram();
150
+ * // ... use program ...
151
+ * ls.setFile('/abs/path/to/foo.ts', 'export const x = 2;'); // bumps version
152
+ * const program2 = ls.getProgram(); // fresh program, foo.ts reparsed
153
+ * ls.dispose();
154
+ * ```
155
+ */
156
+ export const createAnalysisLanguageService = (options, log) => {
157
+ const projectRoot = options?.projectRoot ?? process.cwd();
158
+ const { compilerOptions, rootFileNames } = loadTsconfig(options, log);
159
+ const documentRegistry = options?.documentRegistry ?? ts.createDocumentRegistry();
160
+ const owned = new Map();
161
+ // Root file names from tsconfig — kept as a Set for fast membership checks
162
+ // during deleteFile (so a deleted owned file that was *also* in tsconfig
163
+ // stays in the program's root set, falling through to disk).
164
+ const tsconfigRoots = new Set(rootFileNames);
165
+ // Virtual roots (e.g., `.__svelte2tsx__.ts` paths) added via `setFile`.
166
+ // Tracked separately so `deleteFile` can drop them from the LS's root list.
167
+ const ownedRoots = new Set();
168
+ const setFileInternal = (path, content) => {
169
+ const existing = owned.get(path);
170
+ if (existing && existing.content === content)
171
+ return false;
172
+ owned.set(path, {
173
+ content,
174
+ version: existing ? existing.version + 1 : 1,
175
+ snapshot: ts.ScriptSnapshot.fromString(content),
176
+ });
177
+ if (!tsconfigRoots.has(path))
178
+ ownedRoots.add(path);
179
+ return true;
180
+ };
181
+ // Seed initial virtuals from options. Common path for one-shot callers.
182
+ if (options?.virtualFiles) {
183
+ for (const [path, content] of options.virtualFiles) {
184
+ setFileInternal(path, content);
185
+ }
186
+ }
187
+ // Combined module-resolution host — used both as the LS host's resolution
188
+ // surface and (cast) as the fallback host for `ts.resolveModuleName`. Owned
189
+ // content takes precedence over `ts.sys` so virtuals resolve correctly.
190
+ const moduleResolutionHost = {
191
+ fileExists: (path) => owned.has(path) || ts.sys.fileExists(path),
192
+ readFile: (path) => {
193
+ const entry = owned.get(path);
194
+ if (entry)
195
+ return entry.content;
196
+ return ts.sys.readFile(path);
197
+ },
198
+ directoryExists: ts.sys.directoryExists,
199
+ getCurrentDirectory: () => projectRoot,
200
+ getDirectories: ts.sys.getDirectories,
201
+ realpath: ts.sys.realpath,
202
+ useCaseSensitiveFileNames: ts.sys.useCaseSensitiveFileNames,
203
+ };
204
+ const host = {
205
+ getCompilationSettings: () => compilerOptions,
206
+ getScriptFileNames: () => {
207
+ // Combine tsconfig roots with owned virtual roots. Set semantics
208
+ // dedupe when an owned file was also a tsconfig root.
209
+ if (ownedRoots.size === 0)
210
+ return [...tsconfigRoots];
211
+ const combined = new Set(tsconfigRoots);
212
+ for (const path of ownedRoots)
213
+ combined.add(path);
214
+ return [...combined];
215
+ },
216
+ getScriptVersion: (fileName) => {
217
+ const entry = owned.get(fileName);
218
+ // External / disk-only files: stable version. We don't watch them;
219
+ // the LS reads them once into the document registry.
220
+ return entry ? String(entry.version) : '1';
221
+ },
222
+ getScriptSnapshot: (fileName) => {
223
+ const entry = owned.get(fileName);
224
+ if (entry)
225
+ return entry.snapshot;
226
+ if (!ts.sys.fileExists(fileName))
227
+ return undefined;
228
+ const content = ts.sys.readFile(fileName);
229
+ if (content === undefined)
230
+ return undefined;
231
+ return ts.ScriptSnapshot.fromString(content);
232
+ },
233
+ getCurrentDirectory: () => projectRoot,
234
+ getDefaultLibFileName: ts.getDefaultLibFilePath,
235
+ fileExists: moduleResolutionHost.fileExists,
236
+ readFile: moduleResolutionHost.readFile,
237
+ directoryExists: moduleResolutionHost.directoryExists,
238
+ getDirectories: moduleResolutionHost.getDirectories,
239
+ readDirectory: ts.sys.readDirectory,
240
+ realpath: moduleResolutionHost.realpath,
241
+ useCaseSensitiveFileNames: () => ts.sys.useCaseSensitiveFileNames,
242
+ resolveModuleNameLiterals: (literals, containingFile, _redirected, optionsInner) => {
243
+ return literals.map((literal) => {
244
+ const resolved = resolveSvelteVirtualSpecifier(literal.text, containingFile, (p) => owned.has(p));
245
+ if (resolved)
246
+ return { resolvedModule: resolved };
247
+ return ts.resolveModuleName(literal.text, containingFile, optionsInner, moduleResolutionHost);
248
+ });
249
+ },
250
+ };
251
+ const ls = ts.createLanguageService(host, documentRegistry);
252
+ const getProgram = () => {
253
+ const program = ls.getProgram();
254
+ if (!program) {
255
+ throw new Error('LanguageService.getProgram() returned undefined');
256
+ }
257
+ return program;
258
+ };
259
+ const setFile = (path, content) => setFileInternal(path, content);
260
+ const deleteFile = (path) => {
261
+ const removed = owned.delete(path);
262
+ ownedRoots.delete(path);
263
+ return removed;
264
+ };
265
+ const hasFile = (path) => owned.has(path);
266
+ const dispose = () => {
267
+ ls.dispose();
268
+ owned.clear();
269
+ ownedRoots.clear();
270
+ };
271
+ return { getProgram, setFile, deleteFile, hasFile, dispose };
272
+ };
273
+ /**
274
+ * Create an `IsExternalFile` predicate from `ModuleSourceOptions`.
275
+ *
276
+ * A file is external if it is:
277
+ * - Outside the project root
278
+ * - Inside `node_modules/`
279
+ * - A `.d.ts` declaration file outside the source root (catches framework-generated
280
+ * declarations like `.svelte-kit/non-ambient.d.ts` while keeping user `.d.ts` files
281
+ * in the source tree)
282
+ */
283
+ export const createIsExternalFile = (options) => {
284
+ const projectPrefix = options.projectRoot + '/';
285
+ const effectiveRoot = getSourceRoot(options);
286
+ const sourcePrefix = effectiveRoot ? projectPrefix + effectiveRoot + '/' : projectPrefix;
287
+ return (sf) => !sf.fileName.startsWith(projectPrefix) ||
288
+ sf.fileName.includes('/node_modules/') ||
289
+ (sf.isDeclarationFile && !sf.fileName.startsWith(sourcePrefix));
290
+ };
package/dist/vite.d.ts ADDED
@@ -0,0 +1,116 @@
1
+ /**
2
+ * Vite plugin for svelte-docinfo.
3
+ *
4
+ * Drives a long-lived `AnalysisSession` against a debounce-batched watcher.
5
+ * Every file change funnels into a `pendingChanges` Map and flushes via one
6
+ * `setFiles` + one `query` per debounce window — multi-file editor saves
7
+ * collapse to a single re-analysis instead of N serialized round-trips.
8
+ *
9
+ * The plugin no longer maintains a `fileCache.content` mirror — `setFile`
10
+ * returns `{changed: boolean}` so HMR invalidation reacts to that flag
11
+ * directly. `session.list()` / `session.has()` cover owned-set introspection.
12
+ *
13
+ * Consumers import the analysis result:
14
+ *
15
+ * ```ts
16
+ * import {modules, diagnostics} from 'virtual:svelte-docinfo';
17
+ * ```
18
+ *
19
+ * For TypeScript support, add to your `app.d.ts`:
20
+ *
21
+ * ```ts
22
+ * /// <reference types="svelte-docinfo/virtual-svelte-docinfo.js" />
23
+ * ```
24
+ *
25
+ * @example
26
+ * ```ts
27
+ * // vite.config.ts
28
+ * import svelteDocinfo from './vite.js';
29
+ *
30
+ * export default defineConfig({
31
+ * plugins: [
32
+ * sveltekit(),
33
+ * svelteDocinfo(),
34
+ * ],
35
+ * });
36
+ * ```
37
+ *
38
+ * @module
39
+ */
40
+ import type { Plugin } from 'vite';
41
+ import type { OnDuplicates } from './analyze-core.js';
42
+ import { type Discovery } from './discovery.js';
43
+ import { type SourceOptionsDefaults } from './source-config.js';
44
+ /** Options for the `svelteDocinfo` Vite plugin. */
45
+ export interface VitePluginSvelteDocinfoOptions {
46
+ /**
47
+ * Absolute path to project root directory.
48
+ * Defaults to Vite's resolved `config.root`.
49
+ */
50
+ projectRoot?: string;
51
+ /**
52
+ * Glob patterns to include (relative to `projectRoot`).
53
+ *
54
+ * When provided under the default `discovery: 'auto'`, collapses the chain
55
+ * to glob (exports discovery is skipped). Combining `include` with
56
+ * `discovery: 'exports'` throws at config-resolve time — `exports` mode
57
+ * has no concept of include patterns.
58
+ *
59
+ * When omitted, the glob fallback derives an include from
60
+ * `sourceOptions.sourcePaths` via `deriveIncludePatterns`, so custom
61
+ * `sourcePaths` survive the fallback instead of silently defaulting to
62
+ * `src/lib`.
63
+ */
64
+ include?: Array<string>;
65
+ /**
66
+ * Glob patterns to exclude, applied at both discovery and analysis time.
67
+ *
68
+ * When provided, **fully replaces** `sourceOptions.exclude` (no array
69
+ * merge) — the default test and spec filters are dropped unless
70
+ * re-included explicitly.
71
+ */
72
+ exclude?: Array<string>;
73
+ /**
74
+ * Whether to resolve import dependencies.
75
+ *
76
+ * When `false`, the session's resolver returns null for every specifier,
77
+ * so module dependencies/dependents stay empty.
78
+ *
79
+ * @default true
80
+ */
81
+ resolveDependencies?: boolean;
82
+ /**
83
+ * Discovery strategy for source files.
84
+ *
85
+ * @default 'auto'
86
+ * @see {@link Discovery}
87
+ */
88
+ discovery?: Discovery;
89
+ /**
90
+ * Dist directory name relative to project root, used for exports-based discovery.
91
+ * @default 'dist'
92
+ */
93
+ distDir?: string;
94
+ /**
95
+ * Partial overrides for default source options (SvelteKit `src/lib` layout).
96
+ */
97
+ sourceOptions?: Partial<SourceOptionsDefaults>;
98
+ /** Behavior when duplicate declaration names are found across modules. */
99
+ onDuplicates?: OnDuplicates;
100
+ /**
101
+ * HMR debounce delay in milliseconds. Coalesces rapid file changes during dev.
102
+ * @default 100
103
+ */
104
+ hmrDebounceMs?: number;
105
+ }
106
+ /**
107
+ * Vite plugin: analyzes TypeScript and Svelte source files via a persistent
108
+ * `AnalysisSession` and serves the result as `virtual:svelte-docinfo`.
109
+ *
110
+ * In dev mode, watches source files and triggers debounced HMR updates on
111
+ * changes via `setFiles` batches drained from a pending-changes Map.
112
+ * In build mode, runs analysis once during `buildStart`.
113
+ */
114
+ declare const svelteDocinfo: (options?: VitePluginSvelteDocinfoOptions) => Plugin;
115
+ export default svelteDocinfo;
116
+ //# sourceMappingURL=vite.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vite.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/vite.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AAGH,OAAO,KAAK,EAAuB,MAAM,EAAgB,MAAM,MAAM,CAAC;AAGtE,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAsB,KAAK,SAAS,EAAC,MAAM,gBAAgB,CAAC;AAKnE,OAAO,EAIN,KAAK,qBAAqB,EAC1B,MAAM,oBAAoB,CAAC;AAY5B,mDAAmD;AACnD,MAAM,WAAW,8BAA8B;IAC9C;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;;;;;;;;;OAYG;IACH,OAAO,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IACxB;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IACxB;;;;;;;OAOG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B;;;;;OAKG;IACH,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;OAEG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC,qBAAqB,CAAC,CAAC;IAC/C,0EAA0E;IAC1E,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;;GAOG;AACH,QAAA,MAAM,aAAa,GAAI,UAAS,8BAAmC,KAAG,MAsXrE,CAAC;AAEF,eAAe,aAAa,CAAC"}