Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support tsconfig paths and package-relative imports [sc-22644] #1006

Open
wants to merge 10 commits into
base: main
Choose a base branch
from
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { PackageFilesResolver } from './resolver'
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import path from 'node:path'

import { TSConfigFile, Schema } from './tsconfig-json-file'
import { JsonSourceFile } from './json-source-file'

/**
* JSConfigFile is essentially the exact same as TSConfigFile but with
* allowJs implicitly enabled.
*
* While we could handle jsconfig.json with just TSConfigFile, it's not that
* much extra trouble to have a separate wrapper for it and doing it this way
* may enable some interesting features later.
*/
export class JSConfigFile extends TSConfigFile {
static FILENAME = 'jsconfig.json'

static #id = 0
readonly id = ++JSConfigFile.#id

static filePath (dirPath: string) {
return path.join(dirPath, JSConfigFile.FILENAME)
}

static loadFromJsonSourceFile (jsonFile: JsonSourceFile<Schema>): JSConfigFile | undefined {
return new JSConfigFile(jsonFile)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { SourceFile } from './source-file'

export class JsonSourceFile<Schema> {
static #id = 0
readonly id = ++JsonSourceFile.#id

sourceFile: SourceFile
data: Schema

private constructor (sourceFile: SourceFile, data: Schema) {
this.sourceFile = sourceFile
this.data = data
}

public get meta () {
return this.sourceFile.meta
}

static loadFromSourceFile<Schema> (sourceFile: SourceFile): JsonSourceFile<Schema> | undefined {
try {
const data: Schema = JSON.parse(sourceFile.contents)

return new JsonSourceFile(sourceFile, data)
} catch (err: any) {
}
}
}
19 changes: 19 additions & 0 deletions packages/cli/src/services/check-parser/package-files/loader.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
export type LoadFile<T> = (filePath: string) => T | undefined

export class FileLoader<T> {
loader: LoadFile<T>
cache = new Map<string, T | undefined>()

constructor (loader: LoadFile<T>) {
this.loader = loader
}

load (filePath: string): T | undefined {
if (this.cache.has(filePath)) {
return this.cache.get(filePath)
}
const file = this.loader(filePath)
this.cache.set(filePath, file)
return file
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import path from 'node:path'

import { JsonSourceFile } from './json-source-file'

type ExportCondition =
'node-addons' | 'node' | 'import' | 'require' | 'module-sync' | 'default'

type Schema = {
main?: string
exports?: string | string[] | Record<string, string> | Record<ExportCondition, Record<string, string>>
}

export class PackageJsonFile {
static FILENAME = 'package.json'

static #id = 0
readonly id = ++PackageJsonFile.#id

jsonFile: JsonSourceFile<Schema>
basePath: string
mainPaths: string[]

private constructor (jsonFile: JsonSourceFile<Schema>) {
this.jsonFile = jsonFile
this.basePath = jsonFile.meta.dirname

const fallbackMainPath = path.resolve(this.basePath, 'index.js')

this.mainPaths = jsonFile.data.main !== undefined
? [path.resolve(this.basePath, jsonFile.data.main), fallbackMainPath]
: [fallbackMainPath]
}

public get meta () {
return this.jsonFile.meta
}

static loadFromJsonSourceFile (jsonFile: JsonSourceFile<Schema>): PackageJsonFile | undefined {
return new PackageJsonFile(jsonFile)
}

static filePath (dirPath: string) {
return path.join(dirPath, PackageJsonFile.FILENAME)
}

supportsPackageRelativePaths () {
return this.jsonFile.data.exports === undefined
}
}
Loading
Loading