Skip to content

Instantly share code, notes, and snippets.

@lg
Created July 3, 2022 20:47
Show Gist options
  • Save lg/663e33abc3cd5c6b10c78d21c679f3f9 to your computer and use it in GitHub Desktop.
Save lg/663e33abc3cd5c6b10c78d21c679f3f9 to your computer and use it in GitHub Desktop.

Revisions

  1. lg created this gist Jul 3, 2022.
    52 changes: 52 additions & 0 deletions esbuild.ts
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,52 @@
    import * as esbuild from "esbuild-wasm"
    import esbuildWasmUrl from "esbuild-wasm/esbuild.wasm?url"
    import Path from "path"

    let isEsbuildWasmInitialized = false

    export const tsToJs = async (tree: Record<string, string>) => {
    if (!isEsbuildWasmInitialized) {
    await esbuild.initialize({ wasmURL: esbuildWasmUrl })
    isEsbuildWasmInitialized = true
    }

    const out = await esbuild.build({
    entryPoints: ["index.ts"],
    plugins: [ESBuildFakeFS(tree)],
    logOverride: { "commonjs-variable-in-esm": "silent" },
    bundle: true,
    write: false,
    })
    return out.outputFiles[0].text
    }

    // mostly from: https://github.com/evanw/esbuild/issues/1952
    const ESBuildFakeFS = (tree: Record<string, string>) => {
    const map = new Map(Object.entries(tree))

    return {
    name: "ESBuildFakeFS",
    setup: (build: esbuild.PluginBuild) => {
    build.onResolve({ filter: /.*/, }, (args: esbuild.OnResolveArgs) => {
    if (args.kind === "entry-point")
    return { path: `/${args.path}` }
    if (args.kind === "import-statement") {
    const dirname = Path.dirname(args.importer)
    const path = Path.join(dirname, args.path)
    return { path }
    }
    throw Error("not resolvable")
    })
    build.onLoad({ filter: /.*/ }, (args: esbuild.OnLoadArgs) => {
    const path = map.has(args.path) ? args.path : `${args.path}.ts`
    if (!map.has(path))
    throw Error("not loadable")
    const ext = Path.extname(path)
    const contents = map.get(path)!
    const loader = ({ ".ts": "ts", ".tsx": "tsx", ".js": "js", ".jsx": "jsx" }[ext]) as esbuild.Loader || "default"
    return { contents, loader }
    })

    }
    }
    }
    19 changes: 19 additions & 0 deletions example.ts
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,19 @@
    const scraperCode = import.meta.glob("../scrapers/*.ts", { as: "raw" })

    const fetchAwardAvailability = async ({ signal, meta, queryKey }: ReactQuery.QueryFunctionContext) => {
    const scraperQuery = meta as ScraperForRoute
    const scraperPath = (name: string) => {
    const localPath = Object.keys(scraperCode).find((scraperKey) => scraperKey.indexOf(`${name}.ts`) > -1)
    if (!localPath) throw new Error(`Could not find scraper ${name}`)
    return localPath
    }

    const jsCode = await tsToJs({
    "/index.ts": scraperCode[scraperPath(scraperQuery.scraper)] as unknown as string,
    "/common.ts": scraperCode[scraperPath("common")] as unknown as string
    })

    const postData: { code: string, context: ScraperQuery } = { code: jsCode, context: scraperQuery }
    // axios post...
    return scraperResults.flightsWithFares
    }