Skip to content

Commit

Permalink
setup lerna + root package
Browse files Browse the repository at this point in the history
  • Loading branch information
cameronmoreau committed Oct 2, 2021
1 parent 44bc587 commit 8d939ca
Show file tree
Hide file tree
Showing 6 changed files with 7 additions and 174 deletions.
1 change: 1 addition & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
lib/*
packages/**/lib/*
example-nextjs
4 changes: 4 additions & 0 deletions lerna.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"packages": ["packages/*"],
"version": "0.0.0"
}
3 changes: 0 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,5 @@
"lint-staged": {
"*.{js,jsx,ts,tsx}": "yarn lint",
"*.{js,jsx,ts,tsx,css,json,md}": "yarn format"
},
"dependencies": {
"pyodide": "^0.18.0"
}
}
142 changes: 0 additions & 142 deletions src/RunWasmClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,145 +13,3 @@ export class RunWasmClient {
})
}
}

export class PythonClient {
// <- [reference](https://stackoverflow.com/a/59571016/1375972)
// We redirect stdout to an IO string buffer so that it can be read later
private readonly setStdoutToOutput = `
import sys
import io
sys.stdout = io.StringIO()
`

// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
public constructor(protected pyodide: any) {
pyodide.runPython(this.setStdoutToOutput)
}

public async run({ code }: { code: string }): Promise<string> {
await this.loadPackages(code)
const output: string = this.pyodide.runPython(code) ?? ''
// Prepend the value of stdout before returning
const stdout: string = this.pyodide.runPython('sys.stdout.getvalue()')
console.log(stdout + output)
return stdout + output
}

private loadPackages(code: string): Promise<any> {
if (typeof this.pyodide.loadPackagesFromImports === 'function') {
console.log('Loading Python dependencies from code')
return this.pyodide.loadPackagesFromImports(code)
}
return this.pyodide.loadPackage([])
}
}

declare global {
interface Console {
oldLog: (message?: any, ...optionalParams: any[]) => void
}
}

export class TSClient {
// We store the logs here so that we can return them later from the run() method
public logs: any = []

private libData: any

// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
public constructor(protected ts: any) {
// Overriding the console.log method so that we can store the logs
console.oldLog = console.log
console.log = (value) => {
// For some reason, the first 'incoming' log is always an instance of TSClient. Ignoring it
if (!(value instanceof TSClient)) {
this.logs.push(value)
}
}
}

public async fetchLibs(libs: string[]): Promise<void> {
this.libData = Promise.all(
libs.map(async (lib: string) => {
const path = `typescript/lib/lib.${lib}.d.ts`
const content = await fetch(
`https://cdn.jsdelivr.net/npm/typescript@4.4.3/lib/lib.${lib}.d.ts`
)
.then((res) => res.text())
.catch(() => console.log('Failed to load lib: ' + lib))

return {
path,
content,
ast: this.ts.createSourceFile(
path,
content,
this.ts.ScriptTarget.Latest
),
}
})
).then((lib) => lib)
}

public async run({
code,
}: {
code: string
}): Promise<{ errors: string[]; output: string[] }> {
// The first time we run code, the fetch request for the lib data may still be pending.
const libData = await this.libData
const typeErrors = getTSTypeErrors(code, this.ts, libData)
if (typeErrors.length === 0) {
// If there are no errors, we can run the code
this.logs = []

// eslint-disable-next-line no-eval
eval((await this.ts.transpile(code)) as string)
}

return { errors: typeErrors, output: this.logs }
}
}

function getTSTypeErrors(code: string, ts: any, libData: any[]): string[] {
const dummyFilePath = '/file.ts'
const textAst = ts.createSourceFile(
dummyFilePath,
code,
ts.ScriptTarget.Latest
)
const options = {
lib: [...libData],
}

const host = {
fileExists: (filePath: string) =>
filePath === dummyFilePath || filePath.startsWith('typescript/lib/'),
directoryExists: (dirPath: string) => dirPath === '/',
getCurrentDirectory: () => '/',
getDirectories: () => [],
getCanonicalFileName: (fileName: any) => fileName,
getNewLine: () => '\n',
getDefaultLibFileName: () => '',
getSourceFile: (filePath: string) =>
filePath === dummyFilePath
? textAst
: libData.find((lib) => lib.path === filePath)?.ast,
readFile: (filePath: string) =>
filePath === dummyFilePath
? code
: libData.find((lib) => lib.path === filePath)?.content,
useCaseSensitiveFileNames: () => true,
// eslint-disable-next-line @typescript-eslint/no-empty-function
writeFile: () => {},
}

const rootNames = libData.map((lib) => lib.path)

const program = ts.createProgram([...rootNames, dummyFilePath], options, host)

return ts
.getPreEmitDiagnostics(program)
.filter((d: { file: any }) => d.file)
.map((d: { messageText: string }) => d.messageText)
}
13 changes: 2 additions & 11 deletions src/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import React from 'react'
import { RunWasmClient, PythonClient, TSClient } from './RunWasmClient'
import { RunWasmClient } from './RunWasmClient'

declare global {
// <- [reference](https://stackoverflow.com/a/56458070/11542903)
Expand Down Expand Up @@ -31,13 +31,4 @@ const createRunWasmClient = (language: string): RunWasmClient => {
return new RunWasmClient(language)
}

const createPythonClient = (pyodide: string): PythonClient => {
return new PythonClient(pyodide)
}

// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
const createTSClient = (ts: any): TSClient => {
return new TSClient(ts)
}

export { RunWasm, createRunWasmClient, createPythonClient, createTSClient }
export { RunWasm, createRunWasmClient }
18 changes: 0 additions & 18 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1380,11 +1380,6 @@ balanced-match@^1.0.0:
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==

base-64@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/base-64/-/base-64-1.0.0.tgz#09d0f2084e32a3fd08c2475b973788eee6ae8f4a"
integrity sha512-kwDPIFCGx0NZHog36dj+tHiwP4QMzsZ3AgMViUBKI0+V5n4U0ufTCUMhnQ04diaRI8EX/QcPfql7zlhZ7j4zgg==

brace-expansion@^1.1.7:
version "1.1.11"
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
Expand Down Expand Up @@ -3884,11 +3879,6 @@ node-fetch@^2.6.0:
dependencies:
whatwg-url "^5.0.0"

node-fetch@^2.6.1:
version "2.6.2"
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.2.tgz#986996818b73785e47b1965cc34eb093a1d464d0"
integrity sha512-aLoxToI6RfZ+0NOjmWAgn9+LEd30YCkJKFSyWacNZdEKTit/ZMcKjGkTRo8uWEsnIb/hfKecNPEbln02PdWbcA==

node-int64@^0.4.0:
version "0.4.0"
resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b"
Expand Down Expand Up @@ -4314,14 +4304,6 @@ punycode@^2.1.0, punycode@^2.1.1:
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"
integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==

pyodide@^0.18.0:
version "0.18.0"
resolved "https://registry.yarnpkg.com/pyodide/-/pyodide-0.18.0.tgz#60b9ae604ac5ef984b3fa0f407903fcdc66a948c"
integrity sha512-43ghzKcIjHHa18bhDixJJATJO1t1uFK7KFz3ATt7/ZtQspFWc20EmDZv+e2Mw88H+QV29FctqgS0Yx5OLYnh9A==
dependencies:
base-64 "^1.0.0"
node-fetch "^2.6.1"

q@^1.5.1:
version "1.5.1"
resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7"
Expand Down

0 comments on commit 8d939ca

Please sign in to comment.