Skip to content

Instantly share code, notes, and snippets.

@souporserious
Created April 2, 2023 07:30
Show Gist options
  • Save souporserious/7c05e2b65218c94f9f9031291e9b99e2 to your computer and use it in GitHub Desktop.
Save souporserious/7c05e2b65218c94f9f9031291e9b99e2 to your computer and use it in GitHub Desktop.
import * as React from 'react'
import * as monaco from 'monaco-editor/esm/vs/editor/editor.api'
import ts from 'typescript'
import { setupTypeAcquisition } from '@typescript/ata'
import { signal } from '@preact/signals-core'
/** Type definitions for the current project. */
export const types = signal<{ code: string; path: string }[]>([])
const ata = setupTypeAcquisition({
typescript: ts,
projectName: 'next-monaco',
delegate: {
receivedFile: (code: string, path: string) => {
monaco.languages.typescript.typescriptDefaults.addExtraLib(
code,
`file://${path}`
)
},
},
})
/** Fetches the types for a string of code based on the import declarations. */
export function useTypes(fileName: string, sourceText: string) {
React.useEffect(() => {
const moduleImportDeclarations = getImportDeclarationsFromSourceText(
fileName,
sourceText
)
moduleImportDeclarations.forEach((importdeclarationString) => {
/** Skip TSXMOD imports since they are loaded from the public folder below. */
if (importdeclarationString.includes('next-monaco')) return
ata(importdeclarationString)
})
}, [sourceText])
}
/** Gets the import declarations from a string of code. */
function getImportDeclarationsFromSourceText(
fileName: string,
sourceText: string
): string[] {
const sourceFile = ts.createSourceFile(
fileName,
sourceText,
ts.ScriptTarget.Latest
)
const importDeclarations: string[] = []
processNode(sourceFile)
function processNode(node: ts.Node): void {
if (ts.isImportDeclaration(node)) {
importDeclarations.push(node.getText(sourceFile))
}
ts.forEachChild(node, processNode)
}
return importDeclarations
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment