|
1 |
| -import ts from "typescript"; |
2 | 1 | import type { Package } from "./createPackage.js";
|
3 | 2 | import checks from "./internal/checks/index.js";
|
4 | 3 | import type { AnyCheck, CheckDependenciesContext } from "./internal/defineCheck.js";
|
5 |
| -import { CompilerHostWrapper, createCompilerHosts, type CompilerHosts } from "./multiCompilerHost.js"; |
| 4 | +import { createCompilerHosts } from "./internal/multiCompilerHost.js"; |
6 | 5 | import type {
|
7 | 6 | AnalysisTypes,
|
8 |
| - BuildTool, |
9 | 7 | CheckResult,
|
10 |
| - EntrypointInfo, |
11 | 8 | EntrypointResolutionAnalysis,
|
12 |
| - ModuleKind, |
13 | 9 | Problem,
|
14 | 10 | ProgramInfo,
|
15 |
| - Resolution, |
16 |
| - ResolutionKind, |
17 | 11 | ResolutionOption,
|
18 | 12 | } from "./types.js";
|
19 |
| -import { allBuildTools, getResolutionKinds, getResolutionOption, visitResolutions } from "./utils.js"; |
| 13 | +import { getResolutionOption, visitResolutions } from "./utils.js"; |
| 14 | +import { getEntrypointInfo, getModuleKinds, getBuildTools } from "./internal/getEntrypointInfo.js"; |
20 | 15 |
|
21 | 16 | export interface CheckPackageOptions {
|
22 | 17 | /**
|
@@ -125,204 +120,3 @@ export async function checkPackage(pkg: Package, options?: CheckPackageOptions):
|
125 | 120 | }
|
126 | 121 | }
|
127 | 122 | }
|
128 |
| - |
129 |
| -function getEntrypoints(fs: Package, exportsObject: any, options: CheckPackageOptions | undefined): string[] { |
130 |
| - if (options?.entrypoints) { |
131 |
| - return options.entrypoints.map((e) => formatEntrypointString(e, fs.packageName)); |
132 |
| - } |
133 |
| - if (exportsObject === undefined && fs) { |
134 |
| - const proxies = getProxyDirectories(`/node_modules/${fs.packageName}`, fs); |
135 |
| - if (proxies.length === 0) { |
136 |
| - return ["."]; |
137 |
| - } |
138 |
| - return proxies; |
139 |
| - } |
140 |
| - const detectedSubpaths = getSubpaths(exportsObject); |
141 |
| - if (detectedSubpaths.length === 0) { |
142 |
| - detectedSubpaths.push("."); |
143 |
| - } |
144 |
| - const included = unique([ |
145 |
| - ...detectedSubpaths, |
146 |
| - ...(options?.includeEntrypoints?.map((e) => formatEntrypointString(e, fs.packageName)) ?? []), |
147 |
| - ]); |
148 |
| - if (!options?.excludeEntrypoints) { |
149 |
| - return included; |
150 |
| - } |
151 |
| - return included.filter((entrypoint) => { |
152 |
| - return !options.excludeEntrypoints!.some((exclusion) => { |
153 |
| - if (typeof exclusion === "string") { |
154 |
| - return formatEntrypointString(exclusion, fs.packageName) === entrypoint; |
155 |
| - } |
156 |
| - return exclusion.test(entrypoint); |
157 |
| - }); |
158 |
| - }); |
159 |
| -} |
160 |
| - |
161 |
| -function formatEntrypointString(path: string, packageName: string) { |
162 |
| - return ( |
163 |
| - path === "." || path.startsWith("./") |
164 |
| - ? path |
165 |
| - : path === packageName |
166 |
| - ? "." |
167 |
| - : path.startsWith(`${packageName}/`) |
168 |
| - ? `.${path.slice(packageName.length)}` |
169 |
| - : `./${path}` |
170 |
| - ).trim(); |
171 |
| -} |
172 |
| - |
173 |
| -function getSubpaths(exportsObject: any): string[] { |
174 |
| - if (!exportsObject || typeof exportsObject !== "object" || Array.isArray(exportsObject)) { |
175 |
| - return []; |
176 |
| - } |
177 |
| - const keys = Object.keys(exportsObject); |
178 |
| - if (keys[0].startsWith(".")) { |
179 |
| - return keys; |
180 |
| - } |
181 |
| - return keys.flatMap((key) => getSubpaths(exportsObject[key])); |
182 |
| -} |
183 |
| - |
184 |
| -function getProxyDirectories(rootDir: string, fs: Package) { |
185 |
| - return fs |
186 |
| - .listFiles() |
187 |
| - .filter((f) => f.startsWith(rootDir) && f.endsWith("package.json")) |
188 |
| - .filter((f) => { |
189 |
| - try { |
190 |
| - const packageJson = JSON.parse(fs.readFile(f)); |
191 |
| - return "main" in packageJson && (!packageJson.name || packageJson.name.startsWith(fs.packageName)); |
192 |
| - } catch { |
193 |
| - return false; |
194 |
| - } |
195 |
| - }) |
196 |
| - .map((f) => "." + f.slice(rootDir.length).slice(0, -`/package.json`.length)) |
197 |
| - .filter((f) => f !== "./") |
198 |
| - .sort(); |
199 |
| -} |
200 |
| - |
201 |
| -function getEntrypointInfo( |
202 |
| - packageName: string, |
203 |
| - fs: Package, |
204 |
| - hosts: CompilerHosts, |
205 |
| - options: CheckPackageOptions | undefined, |
206 |
| -): Record<string, EntrypointInfo> { |
207 |
| - const packageJson = JSON.parse(fs.readFile(`/node_modules/${packageName}/package.json`)); |
208 |
| - let entrypoints = getEntrypoints(fs, packageJson.exports, options); |
209 |
| - if (fs.typesPackage) { |
210 |
| - const typesPackageJson = JSON.parse(fs.readFile(`/node_modules/${fs.typesPackage.packageName}/package.json`)); |
211 |
| - const typesEntrypoints = getEntrypoints(fs, typesPackageJson.exports, options); |
212 |
| - entrypoints = unique([...entrypoints, ...typesEntrypoints]); |
213 |
| - } |
214 |
| - const result: Record<string, EntrypointInfo> = {}; |
215 |
| - for (const entrypoint of entrypoints) { |
216 |
| - const resolutions: Record<ResolutionKind, EntrypointResolutionAnalysis> = { |
217 |
| - node10: getEntrypointResolution(packageName, hosts.node10, "node10", entrypoint), |
218 |
| - "node16-cjs": getEntrypointResolution(packageName, hosts.node16, "node16-cjs", entrypoint), |
219 |
| - "node16-esm": getEntrypointResolution(packageName, hosts.node16, "node16-esm", entrypoint), |
220 |
| - bundler: getEntrypointResolution(packageName, hosts.bundler, "bundler", entrypoint), |
221 |
| - }; |
222 |
| - result[entrypoint] = { |
223 |
| - subpath: entrypoint, |
224 |
| - resolutions, |
225 |
| - hasTypes: Object.values(resolutions).some((r) => r.resolution?.isTypeScript), |
226 |
| - isWildcard: !!resolutions.bundler.isWildcard, |
227 |
| - }; |
228 |
| - } |
229 |
| - return result; |
230 |
| -} |
231 |
| - |
232 |
| -function getEntrypointResolution( |
233 |
| - packageName: string, |
234 |
| - host: CompilerHostWrapper, |
235 |
| - resolutionKind: ResolutionKind, |
236 |
| - entrypoint: string, |
237 |
| -): EntrypointResolutionAnalysis { |
238 |
| - if (entrypoint.includes("*")) { |
239 |
| - return { name: entrypoint, resolutionKind, isWildcard: true }; |
240 |
| - } |
241 |
| - const moduleSpecifier = packageName + entrypoint.substring(1); // remove leading . before slash |
242 |
| - const importingFileName = resolutionKind === "node16-esm" ? "/index.mts" : "/index.ts"; |
243 |
| - const resolutionMode = |
244 |
| - resolutionKind === "node16-esm" |
245 |
| - ? ts.ModuleKind.ESNext |
246 |
| - : resolutionKind === "node16-cjs" |
247 |
| - ? ts.ModuleKind.CommonJS |
248 |
| - : undefined; |
249 |
| - const resolution = tryResolve(); |
250 |
| - const implementationResolution = tryResolve(/*noDtsResolution*/ true); |
251 |
| - const files = resolution |
252 |
| - ? host |
253 |
| - .createPrimaryProgram(resolution.fileName) |
254 |
| - .getSourceFiles() |
255 |
| - .map((f) => f.fileName) |
256 |
| - : undefined; |
257 |
| - |
258 |
| - return { |
259 |
| - name: entrypoint, |
260 |
| - resolutionKind, |
261 |
| - resolution, |
262 |
| - implementationResolution, |
263 |
| - files, |
264 |
| - }; |
265 |
| - |
266 |
| - function tryResolve(noDtsResolution?: boolean): Resolution | undefined { |
267 |
| - const { resolution, trace } = host.resolveModuleName( |
268 |
| - moduleSpecifier, |
269 |
| - importingFileName, |
270 |
| - resolutionMode, |
271 |
| - noDtsResolution, |
272 |
| - ); |
273 |
| - const fileName = resolution.resolvedModule?.resolvedFileName; |
274 |
| - if (!fileName) { |
275 |
| - return undefined; |
276 |
| - } |
277 |
| - |
278 |
| - return { |
279 |
| - fileName, |
280 |
| - isJson: resolution.resolvedModule.extension === ts.Extension.Json, |
281 |
| - isTypeScript: ts.hasTSFileExtension(resolution.resolvedModule.resolvedFileName), |
282 |
| - trace, |
283 |
| - }; |
284 |
| - } |
285 |
| -} |
286 |
| - |
287 |
| -function unique<T>(array: readonly T[]): T[] { |
288 |
| - return array.filter((value, index) => array.indexOf(value) === index); |
289 |
| -} |
290 |
| - |
291 |
| -function getBuildTools(packageJson: any): Partial<Record<BuildTool, string>> { |
292 |
| - if (!packageJson.devDependencies) { |
293 |
| - return {}; |
294 |
| - } |
295 |
| - const result: Partial<Record<BuildTool, string>> = {}; |
296 |
| - for (const buildTool of allBuildTools) { |
297 |
| - if (buildTool in packageJson.devDependencies) { |
298 |
| - result[buildTool] = packageJson.devDependencies[buildTool]; |
299 |
| - } |
300 |
| - } |
301 |
| - return result; |
302 |
| -} |
303 |
| - |
304 |
| -function getModuleKinds( |
305 |
| - entrypoints: Record<string, EntrypointInfo>, |
306 |
| - resolutionOption: ResolutionOption, |
307 |
| - hosts: CompilerHosts, |
308 |
| -): Record<string, ModuleKind> { |
309 |
| - const host = hosts[resolutionOption]; |
310 |
| - const result: Record<string, ModuleKind> = {}; |
311 |
| - for (const resolutionKind of getResolutionKinds(resolutionOption)) { |
312 |
| - for (const entrypoint of Object.values(entrypoints)) { |
313 |
| - const resolution = entrypoint.resolutions[resolutionKind]; |
314 |
| - for (const fileName of resolution.files ?? []) { |
315 |
| - if (!result[fileName]) { |
316 |
| - result[fileName] = host.getModuleKindForFile(fileName)!; |
317 |
| - } |
318 |
| - } |
319 |
| - if (resolution.implementationResolution) { |
320 |
| - const fileName = resolution.implementationResolution.fileName; |
321 |
| - if (!result[fileName]) { |
322 |
| - result[fileName] = host.getModuleKindForFile(fileName)!; |
323 |
| - } |
324 |
| - } |
325 |
| - } |
326 |
| - } |
327 |
| - return result; |
328 |
| -} |
0 commit comments