From c0307b6fe625a47732639362f9ddaff9ce3a9152 Mon Sep 17 00:00:00 2001 From: Tylor Steinberger Date: Sat, 1 Jun 2024 15:35:44 -0400 Subject: [PATCH] WIP(compiler): raw TS API --- packages/compiler/package.json | 5 +- packages/compiler/src/Compiler.ts | 78 +++---- packages/compiler/src/typescript/Project.ts | 196 ++++++++++++++++++ packages/compiler/src/typescript/Service.ts | 25 +++ packages/compiler/src/typescript/cache.ts | 66 ++++++ .../compiler/src/typescript/diagnostics.ts | 36 ++++ packages/compiler/src/typescript/snapshot.ts | 31 +++ packages/compiler/src/typescript/util.ts | 9 + packages/compiler/test/index.ts | 11 +- packages/compiler/tsconfig.test.json | 2 +- pnpm-lock.yaml | 54 ----- 11 files changed, 402 insertions(+), 111 deletions(-) create mode 100644 packages/compiler/src/typescript/Project.ts create mode 100644 packages/compiler/src/typescript/Service.ts create mode 100644 packages/compiler/src/typescript/cache.ts create mode 100644 packages/compiler/src/typescript/diagnostics.ts create mode 100644 packages/compiler/src/typescript/snapshot.ts create mode 100644 packages/compiler/src/typescript/util.ts diff --git a/packages/compiler/package.json b/packages/compiler/package.json index e67fd30c3..701006425 100644 --- a/packages/compiler/package.json +++ b/packages/compiler/package.json @@ -40,9 +40,6 @@ "license": "MIT", "sideEffects": [], "dependencies": { - "@rnx-kit/typescript-service": "^1.5.8", - "@ts-morph/common": "^0.23.0", - "@typed/core": "workspace:*", - "ts-morph": "^22.0.0" + "@typed/core": "workspace:*" } } diff --git a/packages/compiler/src/Compiler.ts b/packages/compiler/src/Compiler.ts index 5531001af..c2033d6fd 100644 --- a/packages/compiler/src/Compiler.ts +++ b/packages/compiler/src/Compiler.ts @@ -7,10 +7,10 @@ import { parse } from "@typed/template/Parser" import type { Template } from "@typed/template/Template" -import type { SourceFile, TemplateLiteral } from "ts-morph" -import { Project } from "ts-morph" import ts from "typescript" import { findTsConfig } from "./typescript/findConfigFile.js" +import type { Project } from "./typescript/Project.js" +import { Service } from "./typescript/Service.js" /** * Compiler is an all-in-one cass for compile-time optimization and derivations @@ -20,53 +20,21 @@ import { findTsConfig } from "./typescript/findConfigFile.js" */ export class Compiler { private _cmdLine: ts.ParsedCommandLine - private _cache: ts.ModuleResolutionCache - + private _service: Service = new Service() readonly project: Project constructor(readonly directory: string, readonly tsConfig?: string) { this._cmdLine = findTsConfig(directory, tsConfig) - this._cache = ts.createModuleResolutionCache(directory, (s) => s, this._cmdLine.options) - this.project = new Project({ - compilerOptions: this._cmdLine.options, - resolutionHost: (host, getOptions) => { - return { - ...host, - resolveModuleNames: (moduleNames, containingFile, _reusedNames, redirectedReference, options) => { - return moduleNames.map((moduleName) => - ts.resolveModuleName( - moduleName, - containingFile, - options, - host, - this._cache, - redirectedReference, - ts.ModuleKind.ESNext - ).resolvedModule - ) - }, - getResolvedModuleWithFailedLookupLocationsFromCache: (moduleName, containingFile, resolutionMode) => - ts.resolveModuleName( - moduleName, - containingFile, - getOptions(), - host, - this._cache, - undefined, - resolutionMode - ) - } - } - }) + this.project = this._service.openProject(this._cmdLine, this.enhanceLanguageServiceHost) } - parseTemplates(sourceFile: SourceFile): ReadonlyArray { + parseTemplates(sourceFile: ts.SourceFile): ReadonlyArray { const templates: Array = [] - sourceFile.getDescendantsOfKind(ts.SyntaxKind.TaggedTemplateExpression).forEach((expression) => { - const tag = expression.getTag().getText() + getTaggedTemplateLiteralExpressions(sourceFile).forEach((expression) => { + const tag = expression.tag.getText() if (tag === "html") { - const literal = expression.getTemplate() + const literal = expression.template const template = parseTemplateFromNode(literal) templates.push({ literal, template }) } @@ -74,6 +42,9 @@ export class Compiler { return templates.sort(sortParsedTemplates) } + + private enhanceLanguageServiceHost = (_host: ts.LanguageServiceHost): void => { + } } // Ensure that nested templates are handled first @@ -91,28 +62,45 @@ function getSpan(template: ParsedTemplate) { } export interface ParsedTemplate { - readonly literal: TemplateLiteral + readonly literal: ts.TemplateLiteral readonly template: Template } -function parseTemplateFromNode(node: TemplateLiteral): Template { - if (node.isKind(ts.SyntaxKind.NoSubstitutionTemplateLiteral)) { +function parseTemplateFromNode(node: ts.TemplateLiteral): Template { + if (node.kind === ts.SyntaxKind.NoSubstitutionTemplateLiteral) { return parse([node.getText().slice(1, -1)]) } else { const [head, syntaxList] = node.getChildren() const children = syntaxList.getChildren() const lastChild = children[children.length - 1] const parts = children.map((child) => { - if (child.isKind(ts.SyntaxKind.TemplateSpan)) { + if (child.kind === ts.SyntaxKind.TemplateSpan) { const [, literal] = child.getChildren() const text = literal.getText() if (child === lastChild) return text.slice(1, -1) return text.slice(1) } else { - throw new Error(`Unexpected syntax kind: ${child.getKindName()}`) + throw new Error(`Unexpected syntax kind: ${ts.SyntaxKind[child.kind]}`) } }) return parse([head.getText().slice(1, -2), ...parts]) } } + +function getTaggedTemplateLiteralExpressions(node: ts.SourceFile) { + const toProcess: Array = node.getChildren() + const matches: Array = [] + + while (toProcess.length) { + const node = toProcess.shift()! + + if (node.kind === ts.SyntaxKind.TaggedTemplateExpression) { + matches.push(node as ts.TaggedTemplateExpression) + } + + toProcess.push(...node.getChildren()) + } + + return matches +} diff --git a/packages/compiler/src/typescript/Project.ts b/packages/compiler/src/typescript/Project.ts new file mode 100644 index 000000000..a1bbd9c2d --- /dev/null +++ b/packages/compiler/src/typescript/Project.ts @@ -0,0 +1,196 @@ +import ts from "typescript" +import { ExternalFileCache, ProjectFileCache } from "./cache.js" +import type { DiagnosticWriter } from "./diagnostics" + +export class Project { + private diagnosticWriter: DiagnosticWriter + private cmdLine: ts.ParsedCommandLine + + private projectFiles: ProjectFileCache + private externalFiles: ExternalFileCache + + private languageService: ts.LanguageService + private program: ts.Program + + constructor( + documentRegistry: ts.DocumentRegistry, + diagnosticWriter: DiagnosticWriter, + cmdLine: ts.ParsedCommandLine, + enhanceLanguageServiceHost?: (host: ts.LanguageServiceHost) => void + ) { + this.diagnosticWriter = diagnosticWriter + this.cmdLine = cmdLine + + this.projectFiles = new ProjectFileCache(cmdLine.fileNames) + this.externalFiles = new ExternalFileCache() + + const languageServiceHost: ts.LanguageServiceHost = { + getCompilationSettings: () => this.cmdLine.options, + // getNewLine?(): string; + // getProjectVersion?(): string; + getScriptFileNames: () => this.projectFiles.getFileNames(), + // getScriptKind?(fileName: string): ts.ScriptKind; + getScriptVersion: (fileName) => this.projectFiles.getVersion(fileName) ?? "0", + getScriptSnapshot: (fileName) => + this.projectFiles.getSnapshot(fileName) ?? + this.externalFiles.getSnapshot(fileName), + getProjectReferences: (): ReadonlyArray | undefined => cmdLine.projectReferences, + // getLocalizedDiagnosticMessages?(): any; + // getCancellationToken?(): HostCancellationToken; + getCurrentDirectory: () => process.cwd(), + getDefaultLibFileName: (o) => ts.getDefaultLibFilePath(o), + // log: (s: string): void; + // trace: (s: string): void; + // error: (s: string): void; + // useCaseSensitiveFileNames?(): boolean; + + /* + * LS host can optionally implement these methods to support completions for module specifiers. + * Without these methods, only completions for ambient modules will be provided. + */ + readDirectory: ts.sys.readDirectory, + readFile: ts.sys.readFile, + realpath: ts.sys.realpath || ((x) => x), + fileExists: ts.sys.fileExists, + + /* + * LS host can optionally implement these methods to support automatic updating when new type libraries are installed + */ + // getTypeRootsVersion?(): number; + + /* + * LS host can optionally implement this method if it wants to be completely in charge of module name resolution. + * if implementation is omitted then language service will use built-in module resolution logic and get answers to + * host specific questions using 'getScriptSnapshot'. + * + * If this is implemented, `getResolvedModuleWithFailedLookupLocationsFromCache` should be too. + */ + // resolveModuleNames?(moduleNames: string[], containingFile: string, reusedNames: string[] | undefined, redirectedReference: ResolvedProjectReference | undefined, options: CompilerOptions): (ResolvedModule | undefined)[]; + // getResolvedModuleWithFailedLookupLocationsFromCache?(modulename: string, containingFile: string): ResolvedModuleWithFailedLookupLocations | undefined; + // resolveTypeReferenceDirectives?(typeDirectiveNames: string[], containingFile: string, redirectedReference: ResolvedProjectReference | undefined, options: CompilerOptions): (ResolvedTypeReferenceDirective | undefined)[]; + + /* + * Required for full import and type reference completions. + * These should be unprefixed names. E.g. `getDirectories("/foo/bar")` should return `["a", "b"]`, not `["/foo/bar/a", "/foo/bar/b"]`. + */ + getDirectories: ts.sys.getDirectories, + + /** + * Gets a set of custom transformers to use during emit. + */ + // getCustomTransformers?(): CustomTransformers | undefined; + + // isKnownTypesPackageName?(name: string): boolean; + // installPackage?(options: InstallPackageOptions): Promise; + // writeFile?(fileName: string, content: string): void; + + // getParsedCommandLine?(fileName: string): ParsedCommandLine | undefined; + + directoryExists: ts.sys.directoryExists + } + + if (enhanceLanguageServiceHost) { + enhanceLanguageServiceHost(languageServiceHost) + } + + this.languageService = ts.createLanguageService( + languageServiceHost, + documentRegistry + ) + this.program = this.languageService.getProgram()! + } + + addFile(filePath: string) { + // Add snapshot + this.externalFiles.getSnapshot(filePath) + return this.program.getSourceFile(filePath)! + } + + getCommandLine(): ts.ParsedCommandLine { + return this.cmdLine + } + + private getFileDiagnostics(fileName: string): Array { + return [ + ...this.languageService.getSyntacticDiagnostics(fileName), + ...this.languageService.getSemanticDiagnostics(fileName), + ...this.languageService.getSuggestionDiagnostics(fileName) + ] + } + + validateFile(fileName: string): boolean { + const diagnostics = this.getFileDiagnostics(fileName).filter( + (d) => d.category !== ts.DiagnosticCategory.Suggestion + ) + if (Array.isArray(diagnostics) && diagnostics.length > 0) { + diagnostics.forEach((d) => this.diagnosticWriter.print(d)) + return false + } + return true + } + + validate(): boolean { + // filter down the list of files to be checked + const matcher = this.cmdLine.options.checkJs ? /[.][jt]sx?$/ : /[.]tsx?$/ + const files = this.projectFiles + .getFileNames() + .filter((f) => f.match(matcher)) + + // check each file + let result = true + for (const file of files) { + // always validate the file, even if others have failed + const fileResult = this.validateFile(file) + // combine this file's result with the aggregate result + result = result && fileResult + } + return result + } + + emitFile(fileName: string): boolean { + const output = this.languageService.getEmitOutput(fileName) + if (!output || output.emitSkipped) { + this.validateFile(fileName) + return false + } + output.outputFiles.forEach((o) => { + ts.sys.writeFile(o.name, o.text) + }) + return true + } + + emit(): boolean { + // emit each file + let result = true + for (const file of this.projectFiles.getFileNames()) { + // always emit the file, even if others have failed + const fileResult = this.emitFile(file) + // combine this file's result with the aggregate result + result = result && fileResult + } + return result + } + + hasFile(fileName: string): boolean { + return this.projectFiles.has(fileName) + } + + setFile(fileName: string, snapshot?: ts.IScriptSnapshot): void { + this.projectFiles.set(fileName, snapshot) + } + + removeFile(fileName: string): void { + this.projectFiles.remove(fileName) + } + + removeAllFiles(): void { + this.projectFiles.removeAll() + } + + dispose(): void { + this.languageService.dispose() + + // @ts-expect-error `languageService` cannot be used after calling dispose + this.languageService = null + } +} diff --git a/packages/compiler/src/typescript/Service.ts b/packages/compiler/src/typescript/Service.ts new file mode 100644 index 000000000..f60e12e2c --- /dev/null +++ b/packages/compiler/src/typescript/Service.ts @@ -0,0 +1,25 @@ +import ts from "typescript" +import { createDiagnosticWriter } from "./diagnostics.js" +import { Project } from "./Project.js" + +export class Service { + private documentRegistry + private diagnosticWriter + + constructor(write?: (message: string) => void) { + this.documentRegistry = ts.createDocumentRegistry() + this.diagnosticWriter = createDiagnosticWriter(write) + } + + openProject( + cmdLine: ts.ParsedCommandLine, + enhanceLanguageServiceHost?: (host: ts.LanguageServiceHost) => void + ): Project { + return new Project( + this.documentRegistry, + this.diagnosticWriter, + cmdLine, + enhanceLanguageServiceHost + ) + } +} diff --git a/packages/compiler/src/typescript/cache.ts b/packages/compiler/src/typescript/cache.ts new file mode 100644 index 000000000..0e4f4b595 --- /dev/null +++ b/packages/compiler/src/typescript/cache.ts @@ -0,0 +1,66 @@ +import { normalize } from "node:path" +import type ts from "typescript" +import { VersionedSnapshot } from "./snapshot.js" + +export class ProjectFileCache { + private files = new Map() + + constructor(fileNames: Array) { + fileNames.forEach((fileName) => this.set(fileName)) + } + + has(fileName: string): boolean { + const normalized = normalize(fileName) + return this.files.has(normalized) + } + + set(fileName: string, snapshot?: ts.IScriptSnapshot): void { + const normalized = normalize(fileName) + const file = this.files.get(normalized) + if (!file) { + this.files.set(normalized, new VersionedSnapshot(normalized, snapshot)) + } else { + file.update(snapshot) + } + } + + remove(fileName: string): void { + const normalized = normalize(fileName) + this.files.delete(normalized) + } + + removeAll(): void { + this.files.clear() + } + + getFileNames(): Array { + return Array.from(this.files.keys()) + } + + getVersion(fileName: string): string | undefined { + const normalized = normalize(fileName) + return this.files.get(normalized)?.getVersion() + } + + getSnapshot(fileName: string): ts.IScriptSnapshot | undefined { + const normalized = normalize(fileName) + return this.files.get(normalized)?.getSnapshot() + } +} + +// TODO: the files in this list need to be watched. on change/delete, remove from this list and let the file be re-cached on demand +export class ExternalFileCache { + private files = new Map() + + getSnapshot(fileName: string): ts.IScriptSnapshot { + const normalized = normalize(fileName) + + let file = this.files.get(normalized) + if (!file) { + file = new VersionedSnapshot(normalized) + this.files.set(normalized, file) + } + + return file.getSnapshot() + } +} diff --git a/packages/compiler/src/typescript/diagnostics.ts b/packages/compiler/src/typescript/diagnostics.ts new file mode 100644 index 000000000..51c790fe9 --- /dev/null +++ b/packages/compiler/src/typescript/diagnostics.ts @@ -0,0 +1,36 @@ +import ts from "typescript" +import { getCanonicalFileName, getNewLine } from "./util.js" + +export type DiagnosticWriter = { + format: (diagnostic: ts.Diagnostic) => string + print: (diagnostic: ts.Diagnostic) => void +} + +export function createDiagnosticWriter( + write?: (message: string) => void +): DiagnosticWriter { + const writeDiagnostic = write ?? ts.sys.write + + const formatDiagnosticsHost: ts.FormatDiagnosticsHost = { + getCurrentDirectory: ts.sys.getCurrentDirectory, + getCanonicalFileName, + getNewLine + } + + function format(diagnostic: ts.Diagnostic): string { + return ts.formatDiagnosticsWithColorAndContext( + Array.isArray(diagnostic) ? diagnostic : [diagnostic], + formatDiagnosticsHost + ) + } + + function print(diagnostic: ts.Diagnostic) { + const message = format(diagnostic) + writeDiagnostic(message) + } + + return { + format, + print + } +} diff --git a/packages/compiler/src/typescript/snapshot.ts b/packages/compiler/src/typescript/snapshot.ts new file mode 100644 index 000000000..e534a50bd --- /dev/null +++ b/packages/compiler/src/typescript/snapshot.ts @@ -0,0 +1,31 @@ +import fs from "node:fs" +import ts from "typescript" + +export class VersionedSnapshot { + fileName: string + private version: number + private snapshot: ts.IScriptSnapshot | undefined + + constructor(fileName: string, snapshot?: ts.IScriptSnapshot) { + this.fileName = fileName + this.version = 1 + this.snapshot = snapshot + } + + getVersion(): string { + return this.version.toString() + } + + getSnapshot(): ts.IScriptSnapshot { + if (!this.snapshot) { + const content = fs.readFileSync(this.fileName, "utf8") + this.snapshot = ts.ScriptSnapshot.fromString(content) + } + return this.snapshot + } + + update(snapshot?: ts.IScriptSnapshot): void { + this.version++ + this.snapshot = snapshot + } +} diff --git a/packages/compiler/src/typescript/util.ts b/packages/compiler/src/typescript/util.ts new file mode 100644 index 000000000..42219027c --- /dev/null +++ b/packages/compiler/src/typescript/util.ts @@ -0,0 +1,9 @@ +import ts from "typescript" + +export function getCanonicalFileName(fileName: string): string { + return ts.sys.useCaseSensitiveFileNames ? fileName : fileName.toLowerCase() +} + +export function getNewLine(): string { + return ts.sys.newLine +} diff --git a/packages/compiler/test/index.ts b/packages/compiler/test/index.ts index fe87cfe57..0c9a1d2ae 100644 --- a/packages/compiler/test/index.ts +++ b/packages/compiler/test/index.ts @@ -14,7 +14,7 @@ function makeCompiler() { const files = Object.fromEntries( fixtures.map(( fixture - ) => [path.relative(fixturesDirectory, fixture), compiler.project.addSourceFileAtPath(fixture)]) + ) => [path.relative(fixturesDirectory, fixture), compiler.project.addFile(fixture)]) ) return { @@ -25,12 +25,9 @@ function makeCompiler() { describe("Compiler", () => { const { compiler, files } = makeCompiler() - const staticDivWithText = files["static-div-with-text.ts"] - const divWithInterpolatedText = files["div-with-interpolated-text.ts"] - const nestedTemplates = files["nested-templates.ts"] it("Static
with text", () => { - const templates = compiler.parseTemplates(staticDivWithText) + const templates = compiler.parseTemplates(files["static-div-with-text.ts"]) expect(templates).toHaveLength(1) const [div] = templates const expected = new Template([new ElementNode("div", [], [new TextNode("Hello World")])], ``, []) @@ -39,7 +36,7 @@ describe("Compiler", () => { }) it("
with interpolated text", () => { - const templates = compiler.parseTemplates(divWithInterpolatedText) + const templates = compiler.parseTemplates(files["div-with-interpolated-text.ts"]) expect(templates).toHaveLength(1) const [div] = templates const nodePart = new NodePart(0) @@ -49,7 +46,7 @@ describe("Compiler", () => { }) it("nested template", () => { - const templates = compiler.parseTemplates(nestedTemplates) + const templates = compiler.parseTemplates(files["nested-templates.ts"]) expect(templates).toHaveLength(2) diff --git a/packages/compiler/tsconfig.test.json b/packages/compiler/tsconfig.test.json index 2fe740b87..bc7c913db 100644 --- a/packages/compiler/tsconfig.test.json +++ b/packages/compiler/tsconfig.test.json @@ -15,7 +15,7 @@ ], "references": [ { - "path": "../core/tsconfig.test.json" + "path": "./tsconfig.build.json" } ] } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 19b12c7f2..c372c9664 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -540,18 +540,9 @@ importers: packages/compiler: dependencies: - '@rnx-kit/typescript-service': - specifier: ^1.5.8 - version: 1.5.8(typescript@5.4.5) - '@ts-morph/common': - specifier: ^0.23.0 - version: 0.23.0 '@typed/core': specifier: workspace:* version: link:../core/dist - ts-morph: - specifier: ^22.0.0 - version: 22.0.0 publishDirectory: dist packages/context: @@ -2641,14 +2632,6 @@ packages: '@types/react': optional: true - '@rnx-kit/tools-node@2.1.1': - resolution: {integrity: sha512-jZC/pmeM3fv4LwpkVWlLyv5dOh6haUw/dBaDC0e5zkfehkIdLtRhVwz4l7iH9MW/i4I9OySoc+2DtDpX7KZyZA==} - - '@rnx-kit/typescript-service@1.5.8': - resolution: {integrity: sha512-43kvfBnu2FIejJdH9EhBlyt1tEToneu64zu8yNnvskgLpDv7reKyHb+6jYSOWb+DVAKLFYtUkUZoZJv9WJYHKg==} - peerDependencies: - typescript: '>=4.0' - '@rollup/plugin-virtual@3.0.2': resolution: {integrity: sha512-10monEYsBp3scM4/ND4LNH5Rxvh3e/cVeL3jWTgZ2SrQ+BmUoQcopVQvnaMcOnykb1VkxUFuDAN+0FnpTFRy2A==} engines: {node: '>=14.0.0'} @@ -3038,9 +3021,6 @@ packages: peerDependencies: '@testing-library/dom': '>=7.21.4' - '@ts-morph/common@0.23.0': - resolution: {integrity: sha512-m7Lllj9n/S6sOkCkRftpM7L24uvmfXQFedlW/4hENcuJH1HHm9u5EgxZb9uVjQSCGrbBWBkOGgcTxNg36r6ywA==} - '@tsconfig/node10@1.0.11': resolution: {integrity: sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==} @@ -3843,9 +3823,6 @@ packages: resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==} engines: {node: '>=0.8'} - code-block-writer@13.0.1: - resolution: {integrity: sha512-c5or4P6erEA69TxaxTNcHUNcIn+oyxSRTOWV+pSYF+z4epXqNvwvJ70XPGjPNgue83oAFAPBRQYwpAJ/Hpe/Sg==} - color-convert@1.9.3: resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} @@ -5711,11 +5688,6 @@ packages: engines: {node: '>=10'} hasBin: true - mkdirp@3.0.1: - resolution: {integrity: sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==} - engines: {node: '>=10'} - hasBin: true - mlly@1.7.0: resolution: {integrity: sha512-U9SDaXGEREBYQgfejV97coK0UL1r+qnF2SyO9A3qcI8MzKnsIFKHNVEkrDyNncQTKQQumsasmeq84eNMdBfsNQ==} @@ -6919,9 +6891,6 @@ packages: resolution: {integrity: sha512-5YhbFoHmjxa7pgQLkB07MtGnGJ/yhvjmc9uhsnDBEICME6gkPf83SBwLDQqGDoCa3XzUMWLk1AU2Wn1u1naDtA==} engines: {node: '>=14.16'} - ts-morph@22.0.0: - resolution: {integrity: sha512-M9MqFGZREyeb5fTl6gNHKZLqBQA0TjA1lea+CR48R8EBTDuWrNqW6ccC5QvjNR4s6wDumD3LTCjOFSp9iwlzaw==} - ts-node@10.9.2: resolution: {integrity: sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==} hasBin: true @@ -9234,13 +9203,6 @@ snapshots: optionalDependencies: '@types/react': 18.3.3 - '@rnx-kit/tools-node@2.1.1': {} - - '@rnx-kit/typescript-service@1.5.8(typescript@5.4.5)': - dependencies: - '@rnx-kit/tools-node': 2.1.1 - typescript: 5.4.5 - '@rollup/plugin-virtual@3.0.2(rollup@4.18.0)': optionalDependencies: rollup: 4.18.0 @@ -9985,13 +9947,6 @@ snapshots: dependencies: '@testing-library/dom': 9.3.4 - '@ts-morph/common@0.23.0': - dependencies: - fast-glob: 3.3.2 - minimatch: 9.0.4 - mkdirp: 3.0.1 - path-browserify: 1.0.1 - '@tsconfig/node10@1.0.11': {} '@tsconfig/node12@1.0.11': {} @@ -10909,8 +10864,6 @@ snapshots: clone@1.0.4: {} - code-block-writer@13.0.1: {} - color-convert@1.9.3: dependencies: color-name: 1.1.3 @@ -12998,8 +12951,6 @@ snapshots: mkdirp@1.0.4: {} - mkdirp@3.0.1: {} - mlly@1.7.0: dependencies: acorn: 8.11.3 @@ -14268,11 +14219,6 @@ snapshots: ts-graphviz@1.8.2: {} - ts-morph@22.0.0: - dependencies: - '@ts-morph/common': 0.23.0 - code-block-writer: 13.0.1 - ts-node@10.9.2(@swc/core@1.5.24)(@types/node@20.13.0)(typescript@5.4.5): dependencies: '@cspotcode/source-map-support': 0.8.1