Skip to content

Commit

Permalink
soupify tmp outputs, support for running with core
Browse files Browse the repository at this point in the history
  • Loading branch information
seveibar committed Aug 29, 2024
1 parent 0acc098 commit dd8b9e2
Show file tree
Hide file tree
Showing 14 changed files with 240 additions and 119 deletions.
Binary file modified bun.lockb
Binary file not shown.
2 changes: 1 addition & 1 deletion cli/lib/cmd-fns/publish/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { existsSync, readFileSync } from "fs"
import { getAllPackageFiles } from "cli/lib/util/get-all-package-files"
import prompts from "prompts"
import { getGeneratedReadme } from "../init/get-generated-readme"
import { soupify } from "../../soupify"
import { soupify } from "../../soupify/soupify"
import { inferExportNameFromSource } from "../dev/infer-export-name-from-source"
import $ from "dax-sh"
import semver from "semver"
Expand Down
2 changes: 2 additions & 0 deletions cli/lib/cmd-fns/soupify.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,15 @@ export const soupifyCmd = async (ctx: AppContext, args: any) => {
file: z.string(),
export: z.string().optional(),
output: z.string().optional(),
core: z.boolean().optional(),
})
.parse(args)

const soup = await soupify(
{
filePath: params.file,
exportName: params.export,
useCore: params.core,
},
ctx,
)
Expand Down
1 change: 1 addition & 0 deletions cli/lib/get-program.ts
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,7 @@ export const getProgram = (ctx: AppContext) => {
.description("Convert an example file to tscircuit soup")
.requiredOption("--file <file>", "Input example files")
.option("--output <output.json>", "Output file")
.option("--core", "Use @tscircuit/core to build (future version)")
.option(
"--export <export_name>",
"Name of export to soupify, if not specified, soupify the default/only export",
Expand Down
115 changes: 0 additions & 115 deletions cli/lib/soupify.ts

This file was deleted.

29 changes: 29 additions & 0 deletions cli/lib/soupify/get-export-name-from-file.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { readFile } from "node:fs/promises"
import Debug from "debug"

const debug = Debug("tscircuit:soupify")

export const getExportNameFromFile = async (filePath: string) => {
debug(`reading ${filePath}`)
const targetFileContent = await readFile(filePath, "utf-8")

let exportName: string | undefined
if (targetFileContent.includes("export default")) {
exportName = "default"
} else {
// Look for "export const <name>" or "export function <name>"
const exportRegex = /export\s+(?:const|function)\s+(\w+)/g
const match = exportRegex.exec(targetFileContent)
if (match) {
exportName = match[1]
}
}

if (!exportName) {
throw new Error(
`Couldn't derive an export name and didn't find default export in "${filePath}"`,
)
}

return exportName
}
13 changes: 13 additions & 0 deletions cli/lib/soupify/get-tmp-entrpoint-filepath.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import Path from "node:path"

export const getTmpEntrypointFilePath = (filePath: string) => {
const tmpEntrypointPath = Path.join(
Path.dirname(filePath),
Path.basename(filePath).replace(/\.[^\.]+$/, "") + ".__tmp_entrypoint.tsx",
)
const tmpOutputPath = Path.join(
Path.dirname(filePath),
Path.basename(filePath).replace(/\.[^\.]+$/, "") + ".__tmp_output.json",
)
return { tmpEntrypointPath, tmpOutputPath }
}
1 change: 1 addition & 0 deletions cli/lib/soupify/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./soupify"
60 changes: 60 additions & 0 deletions cli/lib/soupify/run-entrypoint-file.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import Debug from "debug"
import { writeFileSync } from "fs"
import { readFile, unlink } from "node:fs/promises"
import $ from "dax-sh"
import kleur from "kleur"
import { AppContext } from "../util/app-context"

const debug = Debug("tscircuit:soupify")

/**
* Runs the entrypoint file to generate circuit json (soup) for a given file
*/
export const runEntrypointFile = async (
{
tmpEntrypointPath,
tmpOutputPath,
}: { tmpEntrypointPath: string; tmpOutputPath: string },
ctx: Pick<AppContext, "runtime" | "params">,
) => {
debug(`using runtime ${ctx.runtime}`)
const processCmdPart1 =
ctx.runtime === "node"
? $`npx tsx ${tmpEntrypointPath}`
: $`bun ${tmpEntrypointPath}`

debug(`starting process....`)
const processResult = await processCmdPart1
.stdout(debug.enabled ? "inheritPiped" : "piped")
.stderr(debug.enabled ? "inheritPiped" : "piped")
.noThrow()

const rawSoup = await readFile(tmpOutputPath, "utf-8")
const errText = processResult.stderr

if (ctx.params.cleanup !== false) {
debug(`deleting ${tmpEntrypointPath}`)
await unlink(tmpEntrypointPath)
debug(`deleting ${tmpOutputPath}`)
await unlink(tmpOutputPath)
}

try {
debug(`parsing result of soupify...`)
const soup = JSON.parse(rawSoup)

if (soup.COMPILE_ERROR) {
// console.log(kleur.red(`Failed to compile ${filePath}`))
console.log(kleur.red(soup.COMPILE_ERROR))
throw new Error(soup.COMPILE_ERROR)
}

return soup
} catch (e: any) {
// console.log(kleur.red(`Failed to parse result of soupify: ${e.toString()}`))
const t = Date.now()
console.log(`Dumping raw output to .tscircuit/err-${t}.log`)
writeFileSync(`.tscircuit/err-${t}.log`, rawSoup + "\n\n" + errText)
throw new Error(errText)
}
}
52 changes: 52 additions & 0 deletions cli/lib/soupify/soupify-with-core.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { AppContext } from "../util/app-context"
import { z } from "zod"
import $ from "dax-sh"
import * as Path from "path"
import { unlink } from "node:fs/promises"
import kleur from "kleur"
import { writeFileSync } from "fs"
import { readFile } from "fs/promises"
import Debug from "debug"
import { getExportNameFromFile } from "./get-export-name-from-file"
import { getTmpEntrypointFilePath } from "./get-tmp-entrpoint-filepath"
import { runEntrypointFile } from "./run-entrypoint-file"

const debug = Debug("tscircuit:soupify")

export const soupifyWithCore = async (
params: {
filePath: string
exportName?: string
},
ctx: Pick<AppContext, "runtime" | "params">,
) => {
let { filePath, exportName } = params

exportName ??= await getExportNameFromFile(filePath)

const { tmpEntrypointPath, tmpOutputPath } =
getTmpEntrypointFilePath(filePath)

debug(`writing to ${tmpEntrypointPath}`)
writeFileSync(
tmpEntrypointPath,
`
import React from "react"
import { Project } from "@tscircuit/core"
import * as EXPORTS from "./${Path.basename(filePath)}"
import { writeFileSync } from "node:fs"
const Component = EXPORTS["${exportName}"]
const project = new Project()
project.add(<Component />)
project.render()
writeFileSync("${tmpOutputPath}", JSON.stringify(project.getCircuitJson()))
`.trim(),
)

await runEntrypointFile({ tmpEntrypointPath, tmpOutputPath }, ctx)
}
66 changes: 66 additions & 0 deletions cli/lib/soupify/soupify.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { AppContext } from "../util/app-context"
import { z } from "zod"
import $ from "dax-sh"
import * as Path from "path"
import { unlink } from "node:fs/promises"
import kleur from "kleur"
import { writeFileSync } from "fs"
import { readFile } from "fs/promises"
import Debug from "debug"
import { soupifyWithCore } from "./soupify-with-core"
import { getExportNameFromFile } from "./get-export-name-from-file"
import { getTmpEntrypointFilePath } from "./get-tmp-entrpoint-filepath"
import { runEntrypointFile } from "./run-entrypoint-file"

const debug = Debug("tscircuit:soupify")

export const soupify = async (
params: {
filePath: string
exportName?: string
/**
* Use @tscircuit/core instead of @tscircuit/builder, this will be the
* default eventually
*/
useCore?: boolean
},
ctx: Pick<AppContext, "runtime" | "params">,
) => {
let { filePath, exportName, useCore } = params
if (useCore) return soupifyWithCore(params, ctx)

exportName ??= await getExportNameFromFile(filePath)

const { tmpEntrypointPath, tmpOutputPath } =
getTmpEntrypointFilePath(filePath)

debug(`writing to ${tmpEntrypointPath}`)
writeFileSync(
tmpEntrypointPath,
`
import React from "react"
import { createRoot } from "@tscircuit/react-fiber"
import { createProjectBuilder } from "@tscircuit/builder"
import { writeFileSync } from "node:fs"
import * as EXPORTS from "./${Path.basename(filePath)}"
const Component = EXPORTS["${exportName}"]
if (!Component) {
console.log(JSON.stringify({
COMPILE_ERROR: 'Failed to find "${exportName}" export in "${filePath}"'
}))
process.exit(0)
}
const projectBuilder = createProjectBuilder()
const elements = await createRoot().render(<Component />, projectBuilder)
writeFileSync("${tmpOutputPath}", JSON.stringify(elements))
`.trim(),
)

await runEntrypointFile({ tmpEntrypointPath, tmpOutputPath }, ctx)
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { test, expect, describe } from "bun:test"
import { $ } from "bun"

test("soupify", async () => {
test("soupify (builder)", async () => {
const result =
await $`bun cli/cli.ts soupify -y --file ./example-project/examples/basic-chip.tsx`.text()

Expand Down
10 changes: 10 additions & 0 deletions cli/tests/soupify-core.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { test, expect, describe } from "bun:test"
import { $ } from "bun"

test("soupify (core)", async () => {
const result =
await $`bun cli/cli.ts soupify --core -y --file ./example-project/examples/basic-chip.tsx`.text()

console.log(result)
expect(result).toContain("10kohm")

Check failure on line 9 in cli/tests/soupify-core.test.ts

View workflow job for this annotation

GitHub Actions / tests

error: expect(received).toContain(expected)

Expected to contain: "10kohm" Received: "{\n has: [ 90 ],\n keys: [\n {\n open: \"\\u001B[90m\",\n close: \"\\u001B[39m\",\n rgx: /\\x1b\\[39m/g,\n }\n ],\n reset: [Function],\n bold: [Function],\n dim: [Function],\n italic: [Function],\n underline: [Function],\n inverse: [Function],\n hidden: [Function],\n strikethrough: [Function],\n black: [Function],\n red: [Function],\n green: [Function],\n yellow: [Function],\n blue: [Function],\n magenta: [Function],\n cyan: [Function],\n white: [Function],\n gray: [Function],\n grey: [Function],\n bgBlack: [Function],\n bgRed: [Function],\n bgGreen: [Function],\n bgYellow: [Function],\n bgBlue: [Function],\n bgMagenta: [Function],\n bgCyan: [Function],\n bgWhite: [Function],\n}\nError running CLI: ENOENT: No such file or directory\n" at /home/runner/work/cli/cli/cli/tests/soupify-core.test.ts:9:18
})
Loading

0 comments on commit dd8b9e2

Please sign in to comment.