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.
- package/LICENSE +21 -0
- package/README.md +349 -0
- package/dist/analyze-core.d.ts +1386 -0
- package/dist/analyze-core.d.ts.map +1 -0
- package/dist/analyze-core.js +324 -0
- package/dist/analyze.d.ts +137 -0
- package/dist/analyze.d.ts.map +1 -0
- package/dist/analyze.js +148 -0
- package/dist/cli.d.ts +102 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +206 -0
- package/dist/concurrency.d.ts +38 -0
- package/dist/concurrency.d.ts.map +1 -0
- package/dist/concurrency.js +57 -0
- package/dist/declaration-build.d.ts +164 -0
- package/dist/declaration-build.d.ts.map +1 -0
- package/dist/declaration-build.js +15 -0
- package/dist/declaration-helpers.d.ts +169 -0
- package/dist/declaration-helpers.d.ts.map +1 -0
- package/dist/declaration-helpers.js +239 -0
- package/dist/dep-resolver.d.ts +166 -0
- package/dist/dep-resolver.d.ts.map +1 -0
- package/dist/dep-resolver.js +144 -0
- package/dist/diagnostics.d.ts +650 -0
- package/dist/diagnostics.d.ts.map +1 -0
- package/dist/diagnostics.js +377 -0
- package/dist/discovery.d.ts +115 -0
- package/dist/discovery.d.ts.map +1 -0
- package/dist/discovery.js +126 -0
- package/dist/exports.d.ts +105 -0
- package/dist/exports.d.ts.map +1 -0
- package/dist/exports.js +274 -0
- package/dist/files.d.ts +77 -0
- package/dist/files.d.ts.map +1 -0
- package/dist/files.js +95 -0
- package/dist/index.d.ts +32 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +30 -0
- package/dist/log.d.ts +32 -0
- package/dist/log.d.ts.map +1 -0
- package/dist/log.js +11 -0
- package/dist/logo.d.ts +8 -0
- package/dist/logo.d.ts.map +1 -0
- package/dist/logo.js +9 -0
- package/dist/main.d.ts +11 -0
- package/dist/main.d.ts.map +1 -0
- package/dist/main.js +18 -0
- package/dist/paths.d.ts +35 -0
- package/dist/paths.d.ts.map +1 -0
- package/dist/paths.js +34 -0
- package/dist/postprocess.d.ts +145 -0
- package/dist/postprocess.d.ts.map +1 -0
- package/dist/postprocess.js +305 -0
- package/dist/session.d.ts +248 -0
- package/dist/session.d.ts.map +1 -0
- package/dist/session.js +496 -0
- package/dist/source-config.d.ts +330 -0
- package/dist/source-config.d.ts.map +1 -0
- package/dist/source-config.js +356 -0
- package/dist/source.d.ts +126 -0
- package/dist/source.d.ts.map +1 -0
- package/dist/source.js +68 -0
- package/dist/svelte.d.ts +179 -0
- package/dist/svelte.d.ts.map +1 -0
- package/dist/svelte.js +898 -0
- package/dist/tsdoc.d.ts +145 -0
- package/dist/tsdoc.d.ts.map +1 -0
- package/dist/tsdoc.js +262 -0
- package/dist/types.d.ts +3381 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +588 -0
- package/dist/typescript-exports.d.ts +91 -0
- package/dist/typescript-exports.d.ts.map +1 -0
- package/dist/typescript-exports.js +656 -0
- package/dist/typescript-extract-class.d.ts +29 -0
- package/dist/typescript-extract-class.d.ts.map +1 -0
- package/dist/typescript-extract-class.js +251 -0
- package/dist/typescript-extract-function.d.ts +47 -0
- package/dist/typescript-extract-function.d.ts.map +1 -0
- package/dist/typescript-extract-function.js +108 -0
- package/dist/typescript-extract-shared.d.ts +166 -0
- package/dist/typescript-extract-shared.d.ts.map +1 -0
- package/dist/typescript-extract-shared.js +528 -0
- package/dist/typescript-extract-type-properties.d.ts +34 -0
- package/dist/typescript-extract-type-properties.d.ts.map +1 -0
- package/dist/typescript-extract-type-properties.js +241 -0
- package/dist/typescript-extract-type.d.ts +48 -0
- package/dist/typescript-extract-type.d.ts.map +1 -0
- package/dist/typescript-extract-type.js +238 -0
- package/dist/typescript-program.d.ts +211 -0
- package/dist/typescript-program.d.ts.map +1 -0
- package/dist/typescript-program.js +290 -0
- package/dist/vite.d.ts +116 -0
- package/dist/vite.d.ts.map +1 -0
- package/dist/vite.js +418 -0
- package/package.json +131 -0
- 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"}
|