From 480067d36f6d248c79da49abbd04db2a900fb74e Mon Sep 17 00:00:00 2001 From: seveibar Date: Tue, 9 Apr 2024 22:14:09 -0700 Subject: [PATCH] add export gerbers command --- bun.lockb | Bin 176772 -> 192963 bytes lib/cmd-fns/export-gerbers.ts | 60 ++++++++ lib/cmd-fns/index.ts | 1 + lib/get-program.ts | 15 ++ lib/soupify.ts | 22 +++ package-lock.json | 281 ++++++++++++++++++++++++++++++++-- package.json | 5 +- 7 files changed, 367 insertions(+), 17 deletions(-) create mode 100644 lib/cmd-fns/export-gerbers.ts diff --git a/bun.lockb b/bun.lockb index ae04e9c11aa1bfcd424f4ec038c4f3d84d8a5593..45ee83482625704c4816d807996781753cbc612f 100755 GIT binary patch delta 43301 zcmeEvcU%?nVR@+Sty;pSKonjL_sy>Pwv*^~M z>`P_NR;}N!$mu47`YlfTyf>kAe3uE;T8*pSwdPAvMVGNSv7LiHMI~zzr7}~ga{8vm zN=kP@r78|RF~hxEQfgO~Eewl7mlRmsfL;uGa$-tiT69K6?IJ3b2KsjJBws)`hYT`O zsY*buQ~2x9Euf!t;p(7sDQ+jgt+v?%#2##sbC}IN_HP` zBhSR7$GF$@QmIx$AwDTJHaY_}afY!{fRz8A^L>N((y&j=&_}1IM`x=ZfS?R*A*o

0&6^q;{pGZimhz%r- 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 z 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 XUT>zUvJ>?2n`eC~Ki%-(SQh>tZz5P* diff --git a/lib/cmd-fns/export-gerbers.ts b/lib/cmd-fns/export-gerbers.ts new file mode 100644 index 0000000..4907f39 --- /dev/null +++ b/lib/cmd-fns/export-gerbers.ts @@ -0,0 +1,60 @@ +import { AppContext } from "../util/app-context" +import { z } from "zod" +import * as Path from "path" +import { unlink } from "node:fs/promises" +import { soupify } from "lib/soupify" +import * as fs from "fs" +import { + stringifyGerberCommandLayers, + convertSoupToGerberCommands, +} from "@tscircuit/builder" +import { zip } from "zip-a-folder" +import kleur from "kleur" +import archiver from "archiver" + +export const exportGerbersCmd = async (ctx: AppContext, args: any) => { + const params = z + .object({ + file: z.string(), + export: z.string().optional(), + outputfile: z.string().optional().default("gerbers.zip"), + }) + .parse(args) + + console.log(kleur.gray("[soupifying]...")) + const soup = await soupify( + { + filePath: params.file, + exportName: params.export, + }, + ctx + ) + + console.log(kleur.gray("[soup to gerber json]...")) + const gerber_layer_cmds = convertSoupToGerberCommands(soup) + + console.log(kleur.gray("[stringify gerber json]...")) + const gerber_file_contents = stringifyGerberCommandLayers(gerber_layer_cmds) + + console.log(kleur.gray("[writing gerbers to tmp dir]...")) + const tempDir = Path.join(".tscircuit", "tmp-gerber-export") + await fs.mkdirSync(tempDir, { recursive: true }) + for (const [fileName, fileContents] of Object.entries(gerber_file_contents)) { + const filePath = Path.join(tempDir, fileName) + await fs.writeFileSync(filePath, fileContents) + } + + console.log(kleur.gray("[zipping tmp dir]...")) + const output = fs.createWriteStream(params.outputfile) + const archive = archiver("zip", { + zlib: { level: 9 }, + }) + + archive.pipe(output) + archive.directory(tempDir, false) + + await new Promise((resolve, reject) => { + output.on("close", resolve) + output.on("error", reject) + }) +} diff --git a/lib/cmd-fns/index.ts b/lib/cmd-fns/index.ts index c36f48c..a4e02bc 100644 --- a/lib/cmd-fns/index.ts +++ b/lib/cmd-fns/index.ts @@ -36,3 +36,4 @@ export { devServerUpload } from "./dev-server-upload" export { configClear } from "./config-clear" export { openCmd as open } from "./open" export { versionCmd as version } from "./version" +export { exportGerbersCmd as exportGerbers } from "./export-gerbers" diff --git a/lib/get-program.ts b/lib/get-program.ts index f0e2da3..56448c8 100644 --- a/lib/get-program.ts +++ b/lib/get-program.ts @@ -251,6 +251,21 @@ export const getProgram = (ctx: AppContext) => { .description("Clear your local authentication") .action((args) => CMDFN.authLogout(ctx, args)) + const exportCmd = cmd + .command("export") + .description("Export Gerbers, Drill Files, Netlists and more") + + exportCmd + .command("gerbers") + .description("Export Gerber files from an example file") + .requiredOption("--file ", "Input example files") + .option( + "--export ", + "Name of export to soupify, if not specified, soupify the default/only export" + ) + .option("--outputfile ", "Output file name", "gerbers.zip") + .action((args) => CMDFN.exportGerbers(ctx, args)) + cmd .command("soupify") .description("Convert an example file to tscircuit soup") diff --git a/lib/soupify.ts b/lib/soupify.ts index 85496b4..070a511 100644 --- a/lib/soupify.ts +++ b/lib/soupify.ts @@ -5,6 +5,7 @@ import * as Path from "path" import { unlink } from "node:fs/promises" import kleur from "kleur" import { writeFileSync } from "fs" +import { readFile } from "fs/promises" export const soupify = async ( { @@ -16,6 +17,27 @@ export const soupify = async ( }, ctx: { runtime: "node" | "bun" } ) => { + const targetFileContent = await readFile(filePath, "utf-8") + + if (!exportName) { + if (targetFileContent.includes("export default")) { + exportName = "default" + } else { + // Look for "export const " or "export function " + 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}"` + ) + } + const tmpFilePath = Path.join( Path.dirname(filePath), Path.basename(filePath).replace(/\.[^\.]+$/, "") + ".__tmp_entrypoint.tsx" diff --git a/package-lock.json b/package-lock.json index 73645aa..fc22abc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,18 +1,18 @@ { "name": "@tscircuit/cli", - "version": "0.0.52", + "version": "0.0.57", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@tscircuit/cli", - "version": "0.0.52", + "version": "0.0.57", "license": "ISC", "dependencies": { "@edge-runtime/primitives": "^4.1.0", "@hono/node-server": "^1.8.2", - "@tscircuit/builder": "^1.5.32", - "@tscircuit/react-fiber": "^1.0.22", + "@tscircuit/builder": "1.5.53", + "@tscircuit/react-fiber": "latest", "axios": "^1.6.7", "better-sqlite3": "^9.4.3", "chokidar": "^3.6.0", @@ -37,6 +37,7 @@ "prompts": "^2.4.2", "react": "^18.2.0", "semver": "^7.6.0", + "zip-a-folder": "^3.1.6", "zod": "latest" }, "bin": { @@ -674,16 +675,16 @@ } }, "node_modules/@tscircuit/builder": { - "version": "1.5.32", - "resolved": "https://registry.npmjs.org/@tscircuit/builder/-/builder-1.5.32.tgz", - "integrity": "sha512-wTZl7zbr9AC7Pr/n106z2CcJX3dWyxM+A4cBN9LNMmvi7MdgB4ZTgUa5v0m9T0vMG1rCcujSJfnRTPm89Pst7A==", + "version": "1.5.53", + "resolved": "https://registry.npmjs.org/@tscircuit/builder/-/builder-1.5.53.tgz", + "integrity": "sha512-DJWEJAacSN+5p4Sc1RSbYAUEMqbKarS8HusrLpyDHnP+K3NzDG4/kxMGrD9rzTZSq2hfed97Zne/BZlVqfigVQ==", "dependencies": { "@lume/kiwi": "^0.1.0", "@tscircuit/footprints": "^0.0.14", "@tscircuit/routing": "^1.3.1", "@tscircuit/sparkfun-packages": "^1.2.0", "convert-units": "^2.3.4", - "parsel-js": "^1.0.2", + "fast-json-stable-stringify": "^2.1.0", "rectilinear-router": "^1.0.1", "svg-path-bounds": "^1.0.2", "transformation-matrix": "^2.12.0" @@ -1019,6 +1020,78 @@ "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==", "dev": true }, + "node_modules/archiver": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/archiver/-/archiver-6.0.2.tgz", + "integrity": "sha512-UQ/2nW7NMl1G+1UnrLypQw1VdT9XZg/ECcKPq7l+STzStrSivFIXIp34D8M5zeNGW5NoOupdYCHv6VySCPNNlw==", + "dependencies": { + "archiver-utils": "^4.0.1", + "async": "^3.2.4", + "buffer-crc32": "^0.2.1", + "readable-stream": "^3.6.0", + "readdir-glob": "^1.1.2", + "tar-stream": "^3.0.0", + "zip-stream": "^5.0.1" + }, + "engines": { + "node": ">= 12.0.0" + } + }, + "node_modules/archiver-utils": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-4.0.1.tgz", + "integrity": "sha512-Q4Q99idbvzmgCTEAAhi32BkOyq8iVI5EwdO0PmBDSGIzzjYNdcFn7Q7k3OzbLy4kLUPXfJtG6fO2RjftXbobBg==", + "dependencies": { + "glob": "^8.0.0", + "graceful-fs": "^4.2.0", + "lazystream": "^1.0.0", + "lodash": "^4.17.15", + "normalize-path": "^3.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">= 12.0.0" + } + }, + "node_modules/archiver-utils/node_modules/glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/archiver-utils/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/archiver/node_modules/tar-stream": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.1.7.tgz", + "integrity": "sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==", + "dependencies": { + "b4a": "^1.6.4", + "fast-fifo": "^1.2.0", + "streamx": "^2.15.0" + } + }, "node_modules/are-we-there-yet": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", @@ -1071,6 +1144,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/async": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz", + "integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==" + }, "node_modules/async-listen": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/async-listen/-/async-listen-3.0.1.tgz", @@ -1195,11 +1273,22 @@ "proxy-from-env": "^1.1.0" } }, + "node_modules/b4a": { + "version": "1.6.6", + "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.6.tgz", + "integrity": "sha512-5Tk1HLk6b6ctmjIkAcU/Ujv/1WqiDl0F0JdRCR80VsOcUlHcu7pWeWRlOqQLHfDEsVx9YH/aif5AG4ehoCtTmg==" + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, + "node_modules/bare-events": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.2.2.tgz", + "integrity": "sha512-h7z00dWdG0PYOQEvChhOSWvOfkIKsdZGkWr083FgN/HyoQuebSew/cgirYqh9SCuy/hRvxc5Vy6Fw8xAmYHLkQ==", + "optional": true + }, "node_modules/base64-js": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", @@ -1314,6 +1403,14 @@ "ieee754": "^1.1.13" } }, + "node_modules/buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", + "engines": { + "node": "*" + } + }, "node_modules/bun-types": { "version": "1.0.29", "resolved": "https://registry.npmjs.org/bun-types/-/bun-types-1.0.29.tgz", @@ -1638,6 +1735,20 @@ "integrity": "sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w==", "dev": true }, + "node_modules/compress-commons": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-5.0.3.tgz", + "integrity": "sha512-/UIcLWvwAQyVibgpQDPtfNM3SvqN7G9elAPAV7GM0L53EbNWwWiCsWtK8Fwed/APEbptPHXs5PuW+y8Bq8lFTA==", + "dependencies": { + "crc-32": "^1.2.0", + "crc32-stream": "^5.0.0", + "normalize-path": "^3.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">= 12.0.0" + } + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -1783,6 +1894,34 @@ "lodash.keys": "2.3.x" } }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" + }, + "node_modules/crc-32": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz", + "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==", + "bin": { + "crc32": "bin/crc32.njs" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/crc32-stream": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-5.0.1.tgz", + "integrity": "sha512-lO1dFui+CEUh/ztYIpgpKItKW9Bb4NWakCRJrnqAbFIYD+OZAwb2VfD5T5eXMw2FNcsDHkQcNl/Wh3iVXYwU6g==", + "dependencies": { + "crc-32": "^1.2.0", + "readable-stream": "^3.4.0" + }, + "engines": { + "node": ">= 12.0.0" + } + }, "node_modules/cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -2646,6 +2785,11 @@ "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", "dev": true }, + "node_modules/fast-fifo": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz", + "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==" + }, "node_modules/fast-glob": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", @@ -2661,6 +2805,11 @@ "node": ">=8.6.0" } }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + }, "node_modules/fastq": { "version": "1.17.1", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", @@ -2802,8 +2951,7 @@ "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" }, "node_modules/fsevents": { "version": "2.3.3", @@ -3094,7 +3242,6 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "dev": true, "dependencies": { "once": "^1.3.0", "wrappy": "1" @@ -3269,6 +3416,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + }, "node_modules/isexe": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", @@ -3352,6 +3504,44 @@ "kysely": "^0.27.2" } }, + "node_modules/lazystream": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.1.tgz", + "integrity": "sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==", + "dependencies": { + "readable-stream": "^2.0.5" + }, + "engines": { + "node": ">= 0.6.3" + } + }, + "node_modules/lazystream/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/lazystream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/lazystream/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, "node_modules/load-json-file": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-7.0.1.tgz", @@ -4058,11 +4248,6 @@ "resolved": "https://registry.npmjs.org/parse-svg-path/-/parse-svg-path-0.1.2.tgz", "integrity": "sha512-JyPSBnkTJ0AI8GGJLfMXvKq42cj5c006fnLz6fXy6zfoVjJizi8BNTpu8on8ziI1cKy9d9DGNuY17Ce7wuejpQ==" }, - "node_modules/parsel-js": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/parsel-js/-/parsel-js-1.1.2.tgz", - "integrity": "sha512-D66DG2nKx4Yoq66TMEyCUHlR2STGqO7vsBrX7tgyS9cfQyO6XD5JyzOiflwmWN6a4wbUAqpmHqmrxlTQVGZcbA==" - }, "node_modules/path-browserify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", @@ -4209,6 +4394,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, "node_modules/promise-make-naked": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/promise-make-naked/-/promise-make-naked-2.1.1.tgz", @@ -4267,6 +4457,11 @@ } ] }, + "node_modules/queue-tick": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/queue-tick/-/queue-tick-1.0.1.tgz", + "integrity": "sha512-kJt5qhMxoszgU/62PLP1CJytzd2NKetjSRnyuj31fDd3Rlcz3fzlFdFLD1SItunPwyqEOkca6GbV612BWfaBag==" + }, "node_modules/rc": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", @@ -4331,6 +4526,25 @@ "node": ">= 6" } }, + "node_modules/readdir-glob": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/readdir-glob/-/readdir-glob-1.1.3.tgz", + "integrity": "sha512-v05I2k7xN8zXvPD9N+z/uhXPaj0sUFCe2rcWZIpBsqxfP7xXFQ0tipAd/wjj1YxWyWtUS5IDJpOG82JKt2EAVA==", + "dependencies": { + "minimatch": "^5.1.0" + } + }, + "node_modules/readdir-glob/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", @@ -4787,6 +5001,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/streamx": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.16.1.tgz", + "integrity": "sha512-m9QYj6WygWyWa3H1YY69amr4nVgy61xfjys7xO7kviL5rfIEc2naf+ewFiOA+aEJD7y0JO3h2GoiUv4TDwEGzQ==", + "dependencies": { + "fast-fifo": "^1.1.0", + "queue-tick": "^1.0.1" + }, + "optionalDependencies": { + "bare-events": "^2.2.0" + } + }, "node_modules/string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", @@ -5971,6 +6197,29 @@ "node": ">=8" } }, + "node_modules/zip-a-folder": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/zip-a-folder/-/zip-a-folder-3.1.6.tgz", + "integrity": "sha512-u+qRL0sSsq2T2mDFcDzdgCSVO8sChsJ4swd2aZlzyoIoNwyVL7HBHPKDQVq1t0utd8nPXzCq44gAKzXAhbvpXA==", + "dependencies": { + "archiver": "^6.0.1", + "glob": "^10.3.10", + "is-glob": "^4.0.3" + } + }, + "node_modules/zip-stream": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-5.0.2.tgz", + "integrity": "sha512-LfOdrUvPB8ZoXtvOBz6DlNClfvi//b5d56mSWyJi7XbH/HfhOHfUhOqxhT/rUiR7yiktlunqRo+jY6y/cWC/5g==", + "dependencies": { + "archiver-utils": "^4.0.1", + "compress-commons": "^5.0.1", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">= 12.0.0" + } + }, "node_modules/zod": { "version": "3.22.4", "resolved": "https://registry.npmjs.org/zod/-/zod-3.22.4.tgz", diff --git a/package.json b/package.json index cf3e495..e5ec8f5 100644 --- a/package.json +++ b/package.json @@ -35,8 +35,9 @@ "dependencies": { "@edge-runtime/primitives": "^4.1.0", "@hono/node-server": "^1.8.2", - "@tscircuit/builder": "latest", + "@tscircuit/builder": "1.5.53", "@tscircuit/react-fiber": "latest", + "archiver": "^7.0.1", "axios": "^1.6.7", "better-sqlite3": "^9.4.3", "chokidar": "^3.6.0", @@ -61,9 +62,11 @@ "prompts": "^2.4.2", "react": "^18.2.0", "semver": "^7.6.0", + "zip-a-folder": "^3.1.6", "zod": "latest" }, "devDependencies": { + "@types/archiver": "^6.0.2", "@types/bun": "^1.0.8", "@types/chokidar": "^2.1.3", "@types/configstore": "^6.0.2",