Last active
October 19, 2021 15:18
-
-
Save okikio/e8de391154a8c85a90b39056e21ec80b to your computer and use it in GitHub Desktop.
ts-server.js
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
importScripts("https://unpkg.com/@typescript/[email protected]/dist/vfs.globals.js"); | |
importScripts( | |
"https://cdnjs.cloudflare.com/ajax/libs/typescript/4.4.3/typescript.min.js" | |
); | |
importScripts("https://unpkg.com/@okikio/[email protected]/lib/api.js"); | |
export type VFS = typeof import("https://cdn.esm.sh/@typescript/vfs"); | |
export type EVENT_EMITTER = import("https://cdn.esm.sh/@okikio/emitter").EventEmitter; | |
export type Diagnostic = import("https://cdn.esm.sh/@codemirror/lint").Diagnostic; | |
var { | |
createDefaultMapFromCDN, | |
createSystem, | |
createVirtualTypeScriptEnvironment | |
} = globalThis.tsvfs as VFS; | |
var ts = globalThis.ts; // as TS | |
var EventEmitter = globalThis.emitter.EventEmitter; | |
var _emitter: EVENT_EMITTER = new EventEmitter(); | |
globalThis.localStorage = globalThis.localStorage ?? ({} as Storage); | |
(async () => { | |
const compilerOpts = { | |
target: ts.ScriptTarget.ES2021, | |
module: ts.ScriptTarget.ES2020, | |
lib: ["es2021", "es2020", "dom", "webworker"], | |
esModuleInterop: true | |
}; | |
let initialText = "const hello = 'hi'"; | |
_emitter.once("updateText", (details) => { | |
initialText = details.text.join("\n"); | |
}); | |
const fsMap = await createDefaultMapFromCDN( | |
compilerOpts, | |
ts.version, | |
false, | |
ts | |
); | |
const ENTRY_POINT = "index.ts"; | |
fsMap.set(ENTRY_POINT, initialText); | |
const system = createSystem(fsMap); | |
const env = createVirtualTypeScriptEnvironment( | |
system, | |
[ENTRY_POINT], | |
ts, | |
compilerOpts | |
); | |
// You can then interact with the languageService to introspect the code | |
postMessage({ | |
event: "ready", | |
details: [] | |
}); | |
_emitter.on("updateText", (details) => { | |
env.updateFile(ENTRY_POINT, [].concat(details.text).join("\n")); | |
// console.log(details.text) | |
}); | |
_emitter.on("autocomplete-request", ({ pos }) => { | |
let result = env.languageService.getCompletionsAtPosition( | |
ENTRY_POINT, | |
pos, | |
{} | |
); | |
postMessage({ | |
event: "autocomplete-results", | |
details: result | |
}); | |
}); | |
_emitter.on("tooltip-request", ({ pos }) => { | |
let result = env.languageService.getQuickInfoAtPosition( | |
ENTRY_POINT, | |
pos | |
); | |
postMessage({ | |
event: "tooltip-results", | |
details: result | |
? { | |
result, | |
tootltipText: | |
ts.displayPartsToString(result.displayParts) + | |
(result.documentation?.length | |
? "\n" + | |
ts.displayPartsToString(result.documentation) | |
: "") | |
} | |
: { result, tooltipText: "" } | |
}); | |
}); | |
_emitter.on("lint-request", () => { | |
let SyntacticDiagnostics = env.languageService.getSyntacticDiagnostics( | |
ENTRY_POINT | |
); | |
let SemanticDiagnostic = env.languageService.getSemanticDiagnostics( | |
ENTRY_POINT | |
); | |
let SuggestionDiagnostics = env.languageService.getSuggestionDiagnostics( | |
ENTRY_POINT | |
); | |
type Diagnostics = typeof SyntacticDiagnostics & | |
typeof SemanticDiagnostic & | |
typeof SuggestionDiagnostics; | |
let result: Diagnostics = [].concat( | |
SyntacticDiagnostics, | |
SemanticDiagnostic, | |
SuggestionDiagnostics | |
); | |
postMessage({ | |
event: "lint-results", | |
details: result.map((v) => { | |
let from = v.start; | |
let to = v.start + v.length; | |
// let codeActions = env.languageService.getCodeFixesAtPosition(ENTRY_POINT, from, to, [v.category], {}, {}); | |
let diag: Diagnostic = { | |
from, | |
to, | |
message: v.messageText as string, | |
source: v?.source, | |
severity: ["warning", "error", "info", "info"][ | |
v.category | |
] as Diagnostic["severity"] | |
// actions: codeActions as any as Diagnostic["actions"] | |
}; | |
return diag; | |
}) | |
}); | |
}); | |
})(); | |
addEventListener( | |
"message", | |
({ data }: MessageEvent<{ event: string; details: any }>) => { | |
let { event, details } = data; | |
_emitter.emit(event, details); | |
} | |
); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment