@tscircuit/cli 0.0.4 → 0.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bun.lockb +0 -0
- package/dist/cli.js +201 -103
- package/lib/cmd-fns/dev/dev-server-request-handler.ts +54 -0
- package/lib/cmd-fns/dev/get-dev-server-axios.ts +25 -0
- package/lib/cmd-fns/dev/index.ts +17 -149
- package/lib/cmd-fns/dev/soupify-and-upload-example-file.ts +53 -0
- package/lib/cmd-fns/dev/start-dev-server.ts +34 -0
- package/lib/cmd-fns/dev/start-watcher.ts +48 -0
- package/lib/cmd-fns/dev/upload-examples-from-directory.ts +26 -0
- package/lib/cmd-fns/init.ts +5 -2
- package/package.json +5 -2
- package/tests/assets/example-project/src/MyCircuit.tsx +1 -1
package/bun.lockb
CHANGED
|
Binary file
|
package/dist/cli.js
CHANGED
|
@@ -210,7 +210,7 @@ import {Command} from "commander";
|
|
|
210
210
|
// package.json
|
|
211
211
|
var package_default = {
|
|
212
212
|
name: "@tscircuit/cli",
|
|
213
|
-
version: "0.0.
|
|
213
|
+
version: "0.0.5",
|
|
214
214
|
private: false,
|
|
215
215
|
type: "module",
|
|
216
216
|
description: "Command line tool for developing, publishing and installing tscircuit circuits",
|
|
@@ -221,7 +221,8 @@ var package_default = {
|
|
|
221
221
|
"start:dev-server": "bun build:dev-server && bun cli.ts dev -y --cwd ./tests/assets/example-project",
|
|
222
222
|
"build:dev-server": "cd dev-server-api && bun run build && cd ../dev-server-frontend && bun run build",
|
|
223
223
|
"build:cli": "bun build-cli.ts",
|
|
224
|
-
build: "bun build:dev-server && npm run build:cli"
|
|
224
|
+
build: "bun build:dev-server && npm run build:cli",
|
|
225
|
+
"test:init": "bun cli.ts init --dir ./tmp/test --name test"
|
|
225
226
|
},
|
|
226
227
|
bin: {
|
|
227
228
|
tscircuit: "./dist/cli.js",
|
|
@@ -238,6 +239,7 @@ var package_default = {
|
|
|
238
239
|
"@tscircuit/react-fiber": "^1.0.6",
|
|
239
240
|
axios: "^1.6.7",
|
|
240
241
|
"better-sqlite3": "^9.4.3",
|
|
242
|
+
chokidar: "^3.6.0",
|
|
241
243
|
commander: "^12.0.0",
|
|
242
244
|
configstore: "^6.0.0",
|
|
243
245
|
"dax-sh": "^0.39.2",
|
|
@@ -258,6 +260,7 @@ var package_default = {
|
|
|
258
260
|
},
|
|
259
261
|
devDependencies: {
|
|
260
262
|
"@types/bun": "^1.0.8",
|
|
263
|
+
"@types/chokidar": "^2.1.3",
|
|
261
264
|
"@types/configstore": "^6.0.2",
|
|
262
265
|
"@types/lodash": "^4.14.202",
|
|
263
266
|
"@types/mime-types": "^2.1.4",
|
|
@@ -622,8 +625,7 @@ var soupifyCmd = async (ctx, args) => {
|
|
|
622
625
|
};
|
|
623
626
|
// lib/cmd-fns/dev/index.ts
|
|
624
627
|
import {z as z16} from "zod";
|
|
625
|
-
import
|
|
626
|
-
import {join as joinPath} from "path";
|
|
628
|
+
import kleur7 from "kleur";
|
|
627
629
|
import prompts from "prompts";
|
|
628
630
|
import open from "open";
|
|
629
631
|
|
|
@@ -845,66 +847,54 @@ var bundle_default = {
|
|
|
845
847
|
"index.html": Buffer.from("PCFkb2N0eXBlIGh0bWw+CjxodG1sIGxhbmc9ImVuIj4KICA8aGVhZD4KICAgIDxtZXRhIGNoYXJzZXQ9IlVURi04IiAvPgogICAgPCEtLSA8bGluayByZWw9Imljb24iIHR5cGU9ImltYWdlL3N2Zyt4bWwiIGhyZWY9Ii92aXRlLnN2ZyIgLz4gLS0+CiAgICA8bWV0YSBuYW1lPSJ2aWV3cG9ydCIgY29udGVudD0id2lkdGg9ZGV2aWNlLXdpZHRoLCBpbml0aWFsLXNjYWxlPTEuMCIgLz4KICAgIDx0aXRsZT5bZGV2XSB0c2NpcmN1aXQ8L3RpdGxlPgogICAgPHNjcmlwdCB0eXBlPSJtb2R1bGUiIGNyb3Nzb3JpZ2luIHNyYz0iL3ByZXZpZXcvYXNzZXRzL2luZGV4LUNpRUdEejdkLmpzIj48L3NjcmlwdD4KICAgIDxsaW5rIHJlbD0ic3R5bGVzaGVldCIgY3Jvc3NvcmlnaW4gaHJlZj0iL3ByZXZpZXcvYXNzZXRzL2luZGV4LUNNNkk3TGhOLmNzcyI+CiAgPC9oZWFkPgogIDxib2R5PgogICAgPGRpdiBpZD0icm9vdCI+PC9kaXY+CiAgPC9ib2R5Pgo8L2h0bWw+Cg==", "base64")
|
|
846
848
|
};
|
|
847
849
|
|
|
848
|
-
// lib/cmd-fns/dev/
|
|
849
|
-
import defaultAxios from "axios";
|
|
850
|
-
import {readdirSync, readFileSync} from "fs";
|
|
850
|
+
// lib/cmd-fns/dev/dev-server-request-handler.ts
|
|
851
851
|
import EdgeRuntimePrimitives from "@edge-runtime/primitives";
|
|
852
852
|
import mime from "mime-types";
|
|
853
|
-
var
|
|
854
|
-
const
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
const
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
});
|
|
878
|
-
const response = await stdin_default.makeRequest(req, {});
|
|
879
|
-
return response;
|
|
880
|
-
} else if (requestType === "preview") {
|
|
881
|
-
let frontendPath = url.pathname.replace("/preview", "");
|
|
882
|
-
if (frontendPath === "/" || frontendPath === "") {
|
|
883
|
-
frontendPath = "index.html";
|
|
853
|
+
var devServerRequestHandler = async (bunReq) => {
|
|
854
|
+
const url = new URL(bunReq.url);
|
|
855
|
+
const requestType = url.pathname.startsWith("/api") ? "api" : url.pathname.startsWith("/preview") ? "preview" : "other";
|
|
856
|
+
if (requestType === "api") {
|
|
857
|
+
const req = new EdgeRuntimePrimitives.Request(bunReq.url, {
|
|
858
|
+
headers: bunReq.headers,
|
|
859
|
+
method: bunReq.method,
|
|
860
|
+
body: bunReq.body
|
|
861
|
+
});
|
|
862
|
+
const response = await stdin_default.makeRequest(req, {});
|
|
863
|
+
return response;
|
|
864
|
+
} else if (requestType === "preview") {
|
|
865
|
+
let frontendPath = url.pathname.replace("/preview", "");
|
|
866
|
+
if (frontendPath === "/" || frontendPath === "") {
|
|
867
|
+
frontendPath = "index.html";
|
|
868
|
+
}
|
|
869
|
+
frontendPath = frontendPath.replace(/^\//, "");
|
|
870
|
+
const fileContent = bundle_default[frontendPath];
|
|
871
|
+
if (!fileContent) {
|
|
872
|
+
return new Response("Not Found", { status: 404 });
|
|
873
|
+
}
|
|
874
|
+
return new Response(fileContent.toString("utf-8"), {
|
|
875
|
+
headers: {
|
|
876
|
+
"Content-Type": mime.lookup(frontendPath) || "text/plain"
|
|
884
877
|
}
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
878
|
+
});
|
|
879
|
+
} else {
|
|
880
|
+
return new Response(null, {
|
|
881
|
+
status: 302,
|
|
882
|
+
headers: {
|
|
883
|
+
Location: "/preview"
|
|
889
884
|
}
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
Location: "/preview"
|
|
900
|
-
}
|
|
901
|
-
});
|
|
902
|
-
}
|
|
903
|
-
};
|
|
885
|
+
});
|
|
886
|
+
}
|
|
887
|
+
};
|
|
888
|
+
|
|
889
|
+
// lib/cmd-fns/dev/start-dev-server.ts
|
|
890
|
+
var startDevServer = async ({
|
|
891
|
+
port,
|
|
892
|
+
devServerAxios
|
|
893
|
+
}) => {
|
|
904
894
|
let server;
|
|
905
895
|
if (typeof Bun !== "undefined") {
|
|
906
896
|
server = Bun.serve({
|
|
907
|
-
fetch:
|
|
897
|
+
fetch: devServerRequestHandler,
|
|
908
898
|
development: false,
|
|
909
899
|
port
|
|
910
900
|
});
|
|
@@ -912,49 +902,155 @@ var devCmd = async (ctx, args) => {
|
|
|
912
902
|
const { Hono } = await import("hono");
|
|
913
903
|
const { serve } = await import("@hono/node-server");
|
|
914
904
|
const honoApp = new Hono;
|
|
915
|
-
honoApp.all("/*", (c) =>
|
|
905
|
+
honoApp.all("/*", (c) => devServerRequestHandler(c.req.raw));
|
|
916
906
|
server = serve({
|
|
917
907
|
fetch: honoApp.fetch,
|
|
918
908
|
port
|
|
919
909
|
});
|
|
920
910
|
}
|
|
921
911
|
console.log("Running health check against dev server...");
|
|
922
|
-
await
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
912
|
+
await devServerAxios.get("/api/health");
|
|
913
|
+
return server;
|
|
914
|
+
};
|
|
915
|
+
|
|
916
|
+
// lib/cmd-fns/dev/get-dev-server-axios.ts
|
|
917
|
+
import kleur4 from "kleur";
|
|
918
|
+
import defaultAxios from "axios";
|
|
919
|
+
var getDevServerAxios = ({ serverUrl }) => {
|
|
920
|
+
const devServerAxios = defaultAxios.create({
|
|
921
|
+
baseURL: serverUrl
|
|
922
|
+
});
|
|
923
|
+
devServerAxios.interceptors.response.use((res) => res, (err) => {
|
|
924
|
+
console.log(kleur4.red(`[ERR] ${err.response?.status} ${err.config.method?.toUpperCase()} ${err.config.url}\n\n${JSON.stringify(err.response?.data, null, " ")}`.replace(/\\n/g, "\n").replace(/\\"/g, '"')));
|
|
925
|
+
console.log(kleur4.yellow("[Request Body]:"), err.config.data);
|
|
926
|
+
return Promise.reject(err);
|
|
927
|
+
});
|
|
928
|
+
return devServerAxios;
|
|
929
|
+
};
|
|
930
|
+
|
|
931
|
+
// lib/cmd-fns/dev/upload-examples-from-directory.ts
|
|
932
|
+
import {join as joinPath2} from "path";
|
|
933
|
+
import {readdirSync as readdirSync2} from "fs";
|
|
934
|
+
|
|
935
|
+
// lib/cmd-fns/dev/soupify-and-upload-example-file.ts
|
|
936
|
+
import kleur5 from "kleur";
|
|
937
|
+
import {join as joinPath} from "path";
|
|
938
|
+
import {readFileSync} from "fs";
|
|
939
|
+
var soupifyAndUploadExampleFile = async ({
|
|
940
|
+
examplesDir,
|
|
941
|
+
exampleFileName,
|
|
942
|
+
devServerAxios
|
|
943
|
+
}) => {
|
|
944
|
+
try {
|
|
945
|
+
const examplePath = joinPath(examplesDir, exampleFileName);
|
|
946
|
+
const exampleContent = readFileSync(examplePath).toString();
|
|
947
|
+
let exportName = "default";
|
|
948
|
+
if (!exampleContent.includes("export default")) {
|
|
949
|
+
const matches = Array.from(exampleContent.matchAll(/export\s+(const|function)\s+([A-Z]\w+)\s*=?/g)).map((m) => m[2]);
|
|
950
|
+
if (matches.length === 0) {
|
|
951
|
+
throw new Error(`No export detected in "${exampleFileName}"`);
|
|
952
|
+
}
|
|
953
|
+
if (matches.length > 1) {
|
|
954
|
+
throw new Error(`Multiple exports detected in "${exampleFileName}", only single exports currently working`);
|
|
955
|
+
}
|
|
956
|
+
exportName = matches[0];
|
|
957
|
+
}
|
|
958
|
+
console.log(kleur5.gray(`[soupifying] ${exampleFileName}...`));
|
|
959
|
+
const soup = await soupify({
|
|
960
|
+
filePath: examplePath,
|
|
961
|
+
exportName
|
|
962
|
+
});
|
|
963
|
+
console.log(kleur5.gray(`[uploading ] ${exampleFileName}...`));
|
|
964
|
+
await devServerAxios.post("/api/dev_package_examples/create", {
|
|
965
|
+
tscircuit_soup: soup,
|
|
966
|
+
file_path: examplePath,
|
|
967
|
+
export_name: exportName
|
|
968
|
+
});
|
|
969
|
+
console.log(kleur5.gray(`[ done ] ${exampleFileName}!`));
|
|
970
|
+
} catch (e) {
|
|
971
|
+
console.log(kleur5.red(e.toString()));
|
|
972
|
+
}
|
|
973
|
+
};
|
|
974
|
+
|
|
975
|
+
// lib/cmd-fns/dev/upload-examples-from-directory.ts
|
|
976
|
+
var uploadExamplesFromDirectory = async ({
|
|
977
|
+
cwd,
|
|
978
|
+
devServerAxios
|
|
979
|
+
}) => {
|
|
980
|
+
const examplesDir = joinPath2(cwd, "examples");
|
|
981
|
+
const exampleFileNames = readdirSync2(examplesDir);
|
|
926
982
|
for (const exampleFileName of exampleFileNames) {
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
983
|
+
if (exampleFileName.endsWith(".__tmp_entrypoint.tsx"))
|
|
984
|
+
continue;
|
|
985
|
+
if (!exampleFileName.endsWith(".tsx"))
|
|
986
|
+
continue;
|
|
987
|
+
await soupifyAndUploadExampleFile({
|
|
988
|
+
devServerAxios,
|
|
989
|
+
examplesDir,
|
|
990
|
+
exampleFileName
|
|
991
|
+
});
|
|
992
|
+
}
|
|
993
|
+
};
|
|
994
|
+
|
|
995
|
+
// lib/cmd-fns/dev/index.ts
|
|
996
|
+
import {unlink as unlink2} from "fs/promises";
|
|
997
|
+
import * as Path3 from "path";
|
|
998
|
+
|
|
999
|
+
// lib/cmd-fns/dev/start-watcher.ts
|
|
1000
|
+
import chokidar from "chokidar";
|
|
1001
|
+
import kleur6 from "kleur";
|
|
1002
|
+
var startWatcher = async ({
|
|
1003
|
+
cwd,
|
|
1004
|
+
devServerAxios
|
|
1005
|
+
}) => {
|
|
1006
|
+
const watcher = chokidar.watch(`${cwd}/**/*.tsx`, {
|
|
1007
|
+
ignored: /node_modules/,
|
|
1008
|
+
persistent: true
|
|
1009
|
+
});
|
|
1010
|
+
const upload_queue_state = {
|
|
1011
|
+
dirty: false,
|
|
1012
|
+
should_run: true
|
|
1013
|
+
};
|
|
1014
|
+
watcher.on("change", async (path) => {
|
|
1015
|
+
console.log(`File ${path} has been changed`);
|
|
1016
|
+
upload_queue_state.dirty = true;
|
|
1017
|
+
});
|
|
1018
|
+
async function uploadInBackground() {
|
|
1019
|
+
while (upload_queue_state.should_run) {
|
|
1020
|
+
if (upload_queue_state.dirty) {
|
|
1021
|
+
console.log(kleur6.yellow("Changes detected, re-uploading examples..."));
|
|
1022
|
+
upload_queue_state.dirty = false;
|
|
1023
|
+
await uploadExamplesFromDirectory({ cwd, devServerAxios });
|
|
940
1024
|
}
|
|
941
|
-
|
|
942
|
-
const soup = await soupify({
|
|
943
|
-
filePath: examplePath,
|
|
944
|
-
exportName
|
|
945
|
-
});
|
|
946
|
-
console.log(`Soupified ${exampleFileName}!`);
|
|
947
|
-
console.log(`Uploading ${exampleFileName}...`);
|
|
948
|
-
await axios.post("/api/dev_package_examples/create", {
|
|
949
|
-
tscircuit_soup: soup,
|
|
950
|
-
file_path: examplePath,
|
|
951
|
-
export_name: exportName
|
|
952
|
-
});
|
|
953
|
-
console.log(`Uploaded ${exampleFileName}!`);
|
|
954
|
-
} catch (e) {
|
|
955
|
-
console.log(kleur4.red(e.toString()));
|
|
1025
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
956
1026
|
}
|
|
957
1027
|
}
|
|
1028
|
+
const _backgroundUploaderPromise = uploadInBackground();
|
|
1029
|
+
return {
|
|
1030
|
+
_backgroundUploaderPromise,
|
|
1031
|
+
stop: () => {
|
|
1032
|
+
upload_queue_state.should_run = false;
|
|
1033
|
+
watcher.close();
|
|
1034
|
+
}
|
|
1035
|
+
};
|
|
1036
|
+
};
|
|
1037
|
+
|
|
1038
|
+
// lib/cmd-fns/dev/index.ts
|
|
1039
|
+
var devCmd = async (ctx, args) => {
|
|
1040
|
+
const params = z16.object({
|
|
1041
|
+
cwd: z16.string().optional().default(process.cwd()),
|
|
1042
|
+
port: z16.coerce.number().optional().default(3020)
|
|
1043
|
+
}).parse(args);
|
|
1044
|
+
const { cwd, port } = params;
|
|
1045
|
+
unlink2(Path3.join(cwd, ".tscircuit/dev-server.db")).catch(() => {
|
|
1046
|
+
});
|
|
1047
|
+
console.log(kleur7.green(`\n--------------------------------------------\n\nStarting dev server http://localhost:${port}\n\n--------------------------------------------\n\n`));
|
|
1048
|
+
const serverUrl = `http://localhost:${port}`;
|
|
1049
|
+
const devServerAxios = getDevServerAxios({ serverUrl });
|
|
1050
|
+
const server = await startDevServer({ port, devServerAxios });
|
|
1051
|
+
console.log(`Loading examples...`);
|
|
1052
|
+
await uploadExamplesFromDirectory({ devServerAxios, cwd });
|
|
1053
|
+
const watcher = await startWatcher({ cwd, devServerAxios });
|
|
958
1054
|
while (true) {
|
|
959
1055
|
const { action } = await prompts({
|
|
960
1056
|
type: "select",
|
|
@@ -978,6 +1074,7 @@ var devCmd = async (ctx, args) => {
|
|
|
978
1074
|
server.stop();
|
|
979
1075
|
if (server.close)
|
|
980
1076
|
server.close();
|
|
1077
|
+
watcher.stop();
|
|
981
1078
|
break;
|
|
982
1079
|
}
|
|
983
1080
|
}
|
|
@@ -985,13 +1082,13 @@ var devCmd = async (ctx, args) => {
|
|
|
985
1082
|
// lib/cmd-fns/init.ts
|
|
986
1083
|
import {z as z17} from "zod";
|
|
987
1084
|
import {
|
|
988
|
-
readFileSync as
|
|
1085
|
+
readFileSync as readFileSync3,
|
|
989
1086
|
writeFileSync as writeFileSync3,
|
|
990
1087
|
existsSync,
|
|
991
1088
|
mkdirSync as mkdirSync2,
|
|
992
1089
|
appendFileSync
|
|
993
1090
|
} from "fs";
|
|
994
|
-
import * as
|
|
1091
|
+
import * as Path4 from "node:path";
|
|
995
1092
|
import $2 from "dax-sh";
|
|
996
1093
|
var initCmd = async (ctx, args) => {
|
|
997
1094
|
const params = z17.object({
|
|
@@ -1015,7 +1112,7 @@ var initCmd = async (ctx, args) => {
|
|
|
1015
1112
|
}
|
|
1016
1113
|
const pkm = runtime === "bun" ? "bun" : "npm";
|
|
1017
1114
|
const runner = runtime === "bun" ? "bun" : "tsx";
|
|
1018
|
-
const packageJsonExists = existsSync(
|
|
1115
|
+
const packageJsonExists = existsSync(Path4.join(params.dir, "package.json"));
|
|
1019
1116
|
const dirExists = existsSync(params.dir);
|
|
1020
1117
|
if (!dirExists) {
|
|
1021
1118
|
console.log(`Creating directory ${params.dir}`);
|
|
@@ -1030,19 +1127,20 @@ var initCmd = async (ctx, args) => {
|
|
|
1030
1127
|
console.log(`Setting up project for typescript...`);
|
|
1031
1128
|
await $2`${pkm} add -D typescript tsx`;
|
|
1032
1129
|
}
|
|
1130
|
+
await $2`${pkm} add -D @tscircuit/react-fiber @tscircuit/builder`;
|
|
1033
1131
|
console.log("Changing package name...");
|
|
1034
|
-
const packageJson = JSON.parse(
|
|
1132
|
+
const packageJson = JSON.parse(readFileSync3("package.json", "utf-8"));
|
|
1035
1133
|
packageJson.name = params.name;
|
|
1036
1134
|
writeFileSync3("package.json", JSON.stringify(packageJson, null, 2));
|
|
1037
1135
|
console.log(`Adding ".tscircuit" to .gitignore`);
|
|
1038
|
-
appendFileSync(".gitignore", "\n.tscircuit", {
|
|
1136
|
+
appendFileSync(".gitignore", "\n.tscircuit\n*.__tmp_entrypoint.tsx", {
|
|
1039
1137
|
encoding: "utf-8",
|
|
1040
|
-
flag: "
|
|
1138
|
+
flag: "a+"
|
|
1041
1139
|
});
|
|
1042
1140
|
console.log("Creating lib and examples directories...");
|
|
1043
1141
|
mkdirSync2("examples", { recursive: true });
|
|
1044
1142
|
mkdirSync2("lib", { recursive: true });
|
|
1045
|
-
writeFileSync3(
|
|
1143
|
+
writeFileSync3(Path4.join("lib", "MyCircuit.tsx"), `
|
|
1046
1144
|
export const MyCircuit = () => (
|
|
1047
1145
|
<resistor
|
|
1048
1146
|
resistance="10kohm"
|
|
@@ -1052,7 +1150,7 @@ var initCmd = async (ctx, args) => {
|
|
|
1052
1150
|
)
|
|
1053
1151
|
`.trim());
|
|
1054
1152
|
writeFileSync3("index.ts", `export * from "./lib/MyCircuit"`);
|
|
1055
|
-
writeFileSync3(
|
|
1153
|
+
writeFileSync3(Path4.join("examples", "MyExample.tsx"), `
|
|
1056
1154
|
import { MyCircuit } from "lib/MyCircuit"
|
|
1057
1155
|
|
|
1058
1156
|
export const MyExample = () => (
|
|
@@ -1171,7 +1269,7 @@ var getProgram = (ctx) => {
|
|
|
1171
1269
|
|
|
1172
1270
|
// lib/util/create-context-and-run-program.ts
|
|
1173
1271
|
import defaultAxios2 from "axios";
|
|
1174
|
-
import
|
|
1272
|
+
import kleur8 from "kleur";
|
|
1175
1273
|
|
|
1176
1274
|
// lib/param-handlers/interact-for-local-directory.ts
|
|
1177
1275
|
import * as fs4 from "fs/promises";
|
|
@@ -1417,17 +1515,17 @@ var createContextAndRunProgram = async (process_args) => {
|
|
|
1417
1515
|
if (global_config.get("log_requests")) {
|
|
1418
1516
|
console.log(`Using registry_url: ${registry_url}`);
|
|
1419
1517
|
axios.interceptors.request.use((req) => {
|
|
1420
|
-
console.log(
|
|
1518
|
+
console.log(kleur8.grey(`[REQ] ${req.method?.toUpperCase()} ${req.url}`));
|
|
1421
1519
|
return req;
|
|
1422
1520
|
});
|
|
1423
1521
|
axios.interceptors.response.use((res) => {
|
|
1424
|
-
console.log(
|
|
1522
|
+
console.log(kleur8.grey(`[RES] ${res.status} ${res.config.method?.toUpperCase()} ${res.config.url}`));
|
|
1425
1523
|
return res;
|
|
1426
1524
|
});
|
|
1427
1525
|
}
|
|
1428
1526
|
axios.interceptors.response.use((res) => res, (err) => {
|
|
1429
|
-
console.log(
|
|
1430
|
-
console.log(
|
|
1527
|
+
console.log(kleur8.red(`[ERR] ${err.response?.status} ${err.config.method?.toUpperCase()} ${err.config.url}\n\n${JSON.stringify(err.response?.data, null, " ")}`.replace(/\\n/g, "\n").replace(/\\"/g, '"')));
|
|
1528
|
+
console.log(kleur8.yellow("[Request Body]:"), err.config.data);
|
|
1431
1529
|
return Promise.reject(err);
|
|
1432
1530
|
});
|
|
1433
1531
|
const ctx = {
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import apiServer from "../../../dev-server-api/dist/bundle"
|
|
2
|
+
import frontendVfs from "../../../dev-server-frontend/dist/bundle"
|
|
3
|
+
import EdgeRuntimePrimitives from "@edge-runtime/primitives"
|
|
4
|
+
import mime from "mime-types"
|
|
5
|
+
|
|
6
|
+
export const devServerRequestHandler = async (bunReq: Request) => {
|
|
7
|
+
const url = new URL(bunReq.url)
|
|
8
|
+
const requestType = url.pathname.startsWith("/api")
|
|
9
|
+
? "api"
|
|
10
|
+
: url.pathname.startsWith("/preview")
|
|
11
|
+
? "preview"
|
|
12
|
+
: "other"
|
|
13
|
+
|
|
14
|
+
if (requestType === "api") {
|
|
15
|
+
// We have to shim Bun's Request until they fix the issue where
|
|
16
|
+
// .clone() doesn't clone the body
|
|
17
|
+
// https://github.com/oven-sh/bun/pull/8668
|
|
18
|
+
const req = new EdgeRuntimePrimitives.Request(bunReq.url, {
|
|
19
|
+
headers: bunReq.headers,
|
|
20
|
+
method: bunReq.method,
|
|
21
|
+
body: bunReq.body,
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
const response = await apiServer.makeRequest(req, {})
|
|
25
|
+
return response
|
|
26
|
+
} else if (requestType === "preview") {
|
|
27
|
+
let frontendPath = url.pathname.replace("/preview", "")
|
|
28
|
+
if (frontendPath === "/" || frontendPath === "") {
|
|
29
|
+
frontendPath = "index.html"
|
|
30
|
+
}
|
|
31
|
+
frontendPath = frontendPath.replace(/^\//, "")
|
|
32
|
+
|
|
33
|
+
const fileContent: Buffer = (frontendVfs as any)[frontendPath]
|
|
34
|
+
if (!fileContent) {
|
|
35
|
+
return new Response("Not Found", { status: 404 })
|
|
36
|
+
}
|
|
37
|
+
return new Response(
|
|
38
|
+
// Buffer.from(fileContent.toString(), "base64").toString("utf-8"),
|
|
39
|
+
fileContent.toString("utf-8"),
|
|
40
|
+
{
|
|
41
|
+
headers: {
|
|
42
|
+
"Content-Type": mime.lookup(frontendPath) || "text/plain",
|
|
43
|
+
},
|
|
44
|
+
}
|
|
45
|
+
)
|
|
46
|
+
} else {
|
|
47
|
+
return new Response(null, {
|
|
48
|
+
status: 302,
|
|
49
|
+
headers: {
|
|
50
|
+
Location: "/preview",
|
|
51
|
+
},
|
|
52
|
+
})
|
|
53
|
+
}
|
|
54
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import kleur from "kleur"
|
|
2
|
+
import defaultAxios from "axios"
|
|
3
|
+
|
|
4
|
+
export const getDevServerAxios = ({ serverUrl }: { serverUrl: string }) => {
|
|
5
|
+
const devServerAxios = defaultAxios.create({
|
|
6
|
+
baseURL: serverUrl,
|
|
7
|
+
})
|
|
8
|
+
devServerAxios.interceptors.response.use(
|
|
9
|
+
(res) => res,
|
|
10
|
+
(err) => {
|
|
11
|
+
console.log(
|
|
12
|
+
kleur.red(
|
|
13
|
+
`[ERR] ${err.response?.status} ${err.config.method?.toUpperCase()} ${
|
|
14
|
+
err.config.url
|
|
15
|
+
}\n\n${JSON.stringify(err.response?.data, null, " ")}`
|
|
16
|
+
.replace(/\\n/g, "\n")
|
|
17
|
+
.replace(/\\"/g, '"')
|
|
18
|
+
)
|
|
19
|
+
)
|
|
20
|
+
console.log(kleur.yellow("[Request Body]:"), err.config.data)
|
|
21
|
+
return Promise.reject(err)
|
|
22
|
+
}
|
|
23
|
+
)
|
|
24
|
+
return devServerAxios
|
|
25
|
+
}
|
package/lib/cmd-fns/dev/index.ts
CHANGED
|
@@ -1,16 +1,15 @@
|
|
|
1
1
|
import { AppContext } from "../../util/app-context"
|
|
2
2
|
import { z } from "zod"
|
|
3
3
|
import kleur from "kleur"
|
|
4
|
-
import { join as joinPath } from "path"
|
|
5
4
|
import prompts from "prompts"
|
|
6
5
|
import open from "open"
|
|
7
|
-
import
|
|
8
|
-
import
|
|
9
|
-
import
|
|
10
|
-
import {
|
|
11
|
-
import
|
|
12
|
-
import
|
|
13
|
-
import
|
|
6
|
+
import { startDevServer } from "./start-dev-server"
|
|
7
|
+
import { getDevServerAxios } from "./get-dev-server-axios"
|
|
8
|
+
import { uploadExamplesFromDirectory } from "./upload-examples-from-directory"
|
|
9
|
+
import { unlink } from "fs/promises"
|
|
10
|
+
import * as Path from "path"
|
|
11
|
+
import { appendFileSync } from "fs"
|
|
12
|
+
import { startWatcher } from "./start-watcher"
|
|
14
13
|
|
|
15
14
|
export const devCmd = async (ctx: AppContext, args: any) => {
|
|
16
15
|
const params = z
|
|
@@ -24,7 +23,8 @@ export const devCmd = async (ctx: AppContext, args: any) => {
|
|
|
24
23
|
|
|
25
24
|
// Load package.json, install tscircuit if it's not installed. If any other
|
|
26
25
|
// tscircuit dependency like @tscircuit/builder is installed, then don't
|
|
27
|
-
// install anything
|
|
26
|
+
// install anything. If there is nothing in the current directory, ask to
|
|
27
|
+
// instead run "tsck init"
|
|
28
28
|
// TODO
|
|
29
29
|
|
|
30
30
|
// Check that examples directory exists, if not create it and put inside
|
|
@@ -37,13 +37,8 @@ export const devCmd = async (ctx: AppContext, args: any) => {
|
|
|
37
37
|
// Add .tscircuit to .gitignore if it's not already there
|
|
38
38
|
// TODO
|
|
39
39
|
|
|
40
|
-
// Delete
|
|
41
|
-
|
|
42
|
-
// INSIDE BACKGROUND SERVICE
|
|
43
|
-
// Soupify contents of examples directory, upload to sqlite db
|
|
44
|
-
// TODO
|
|
45
|
-
// Watch and re-soupify on file changes
|
|
46
|
-
// TODO
|
|
40
|
+
// Delete old .tscircuit/dev-server.db
|
|
41
|
+
unlink(Path.join(cwd, ".tscircuit/dev-server.db")).catch(() => {})
|
|
47
42
|
|
|
48
43
|
console.log(
|
|
49
44
|
kleur.green(
|
|
@@ -51,144 +46,16 @@ export const devCmd = async (ctx: AppContext, args: any) => {
|
|
|
51
46
|
)
|
|
52
47
|
)
|
|
53
48
|
const serverUrl = `http://localhost:${port}`
|
|
54
|
-
const
|
|
55
|
-
baseURL: serverUrl,
|
|
56
|
-
})
|
|
57
|
-
axios.interceptors.response.use(
|
|
58
|
-
(res) => res,
|
|
59
|
-
(err) => {
|
|
60
|
-
console.log(
|
|
61
|
-
kleur.red(
|
|
62
|
-
`[ERR] ${err.response?.status} ${err.config.method?.toUpperCase()} ${
|
|
63
|
-
err.config.url
|
|
64
|
-
}\n\n${JSON.stringify(err.response?.data, null, " ")}`
|
|
65
|
-
.replace(/\\n/g, "\n")
|
|
66
|
-
.replace(/\\"/g, '"')
|
|
67
|
-
)
|
|
68
|
-
)
|
|
69
|
-
console.log(kleur.yellow("[Request Body]:"), err.config.data)
|
|
70
|
-
return Promise.reject(err)
|
|
71
|
-
}
|
|
72
|
-
)
|
|
73
|
-
|
|
74
|
-
const requestHandler = async (bunReq: Request) => {
|
|
75
|
-
const url = new URL(bunReq.url)
|
|
76
|
-
const requestType = url.pathname.startsWith("/api")
|
|
77
|
-
? "api"
|
|
78
|
-
: url.pathname.startsWith("/preview")
|
|
79
|
-
? "preview"
|
|
80
|
-
: "other"
|
|
49
|
+
const devServerAxios = getDevServerAxios({ serverUrl })
|
|
81
50
|
|
|
82
|
-
|
|
83
|
-
// We have to shim Bun's Request until they fix the issue where
|
|
84
|
-
// .clone() doesn't clone the body
|
|
85
|
-
// https://github.com/oven-sh/bun/pull/8668
|
|
86
|
-
const req = new EdgeRuntimePrimitives.Request(bunReq.url, {
|
|
87
|
-
headers: bunReq.headers,
|
|
88
|
-
method: bunReq.method,
|
|
89
|
-
body: bunReq.body,
|
|
90
|
-
})
|
|
91
|
-
|
|
92
|
-
const response = await apiServer.makeRequest(req, {})
|
|
93
|
-
return response
|
|
94
|
-
} else if (requestType === "preview") {
|
|
95
|
-
let frontendPath = url.pathname.replace("/preview", "")
|
|
96
|
-
if (frontendPath === "/" || frontendPath === "") {
|
|
97
|
-
frontendPath = "index.html"
|
|
98
|
-
}
|
|
99
|
-
frontendPath = frontendPath.replace(/^\//, "")
|
|
100
|
-
|
|
101
|
-
const fileContent: Buffer = (frontendVfs as any)[frontendPath]
|
|
102
|
-
if (!fileContent) {
|
|
103
|
-
return new Response("Not Found", { status: 404 })
|
|
104
|
-
}
|
|
105
|
-
return new Response(
|
|
106
|
-
// Buffer.from(fileContent.toString(), "base64").toString("utf-8"),
|
|
107
|
-
fileContent.toString("utf-8"),
|
|
108
|
-
{
|
|
109
|
-
headers: {
|
|
110
|
-
"Content-Type": mime.lookup(frontendPath) || "text/plain",
|
|
111
|
-
},
|
|
112
|
-
}
|
|
113
|
-
)
|
|
114
|
-
} else {
|
|
115
|
-
return new Response(null, {
|
|
116
|
-
status: 302,
|
|
117
|
-
headers: {
|
|
118
|
-
Location: "/preview",
|
|
119
|
-
},
|
|
120
|
-
})
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
let server: any
|
|
125
|
-
if (typeof Bun !== "undefined") {
|
|
126
|
-
server = Bun.serve({
|
|
127
|
-
fetch: requestHandler,
|
|
128
|
-
development: false,
|
|
129
|
-
port,
|
|
130
|
-
})
|
|
131
|
-
} else {
|
|
132
|
-
// Hono messes up the globals, only import it if we don't have Bun
|
|
133
|
-
const { Hono } = await import("hono")
|
|
134
|
-
const { serve } = await import("@hono/node-server")
|
|
135
|
-
const honoApp = new Hono()
|
|
136
|
-
honoApp.all("/*", (c) => requestHandler(c.req.raw))
|
|
137
|
-
server = serve({
|
|
138
|
-
fetch: honoApp.fetch,
|
|
139
|
-
port,
|
|
140
|
-
})
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
console.log("Running health check against dev server...")
|
|
144
|
-
await axios.get("/api/health")
|
|
51
|
+
const server = await startDevServer({ port, devServerAxios })
|
|
145
52
|
|
|
146
53
|
// Soupify all examples
|
|
147
54
|
console.log(`Loading examples...`)
|
|
148
|
-
|
|
149
|
-
const exampleFileNames = readdirSync(examplesDir)
|
|
150
|
-
for (const exampleFileName of exampleFileNames) {
|
|
151
|
-
try {
|
|
152
|
-
const examplePath = joinPath(examplesDir, exampleFileName)
|
|
153
|
-
const exampleContent = readFileSync(examplePath).toString()
|
|
154
|
-
|
|
155
|
-
let exportName = "default"
|
|
156
|
-
|
|
157
|
-
if (!exampleContent.includes("export default")) {
|
|
158
|
-
// try to infer an export if possible
|
|
159
|
-
const matches = Array.from(
|
|
160
|
-
exampleContent.matchAll(
|
|
161
|
-
/export\s+(const|function)\s+([A-Z]\w+)\s*=?/g
|
|
162
|
-
)
|
|
163
|
-
).map((m) => m[2])
|
|
164
|
-
if (matches.length === 0) {
|
|
165
|
-
throw new Error(`No export detected in "${exampleFileName}"`)
|
|
166
|
-
}
|
|
167
|
-
if (matches.length > 1) {
|
|
168
|
-
throw new Error(
|
|
169
|
-
`Multiple exports detected in "${exampleFileName}", only single exports currently working`
|
|
170
|
-
)
|
|
171
|
-
}
|
|
172
|
-
exportName = matches[0]
|
|
173
|
-
}
|
|
55
|
+
await uploadExamplesFromDirectory({ devServerAxios, cwd })
|
|
174
56
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
filePath: examplePath,
|
|
178
|
-
exportName,
|
|
179
|
-
})
|
|
180
|
-
console.log(`Soupified ${exampleFileName}!`)
|
|
181
|
-
console.log(`Uploading ${exampleFileName}...`)
|
|
182
|
-
await axios.post("/api/dev_package_examples/create", {
|
|
183
|
-
tscircuit_soup: soup,
|
|
184
|
-
file_path: examplePath,
|
|
185
|
-
export_name: exportName,
|
|
186
|
-
})
|
|
187
|
-
console.log(`Uploaded ${exampleFileName}!`)
|
|
188
|
-
} catch (e: any) {
|
|
189
|
-
console.log(kleur.red(e.toString()))
|
|
190
|
-
}
|
|
191
|
-
}
|
|
57
|
+
// Start watcher
|
|
58
|
+
const watcher = await startWatcher({ cwd, devServerAxios })
|
|
192
59
|
|
|
193
60
|
while (true) {
|
|
194
61
|
const { action } = await prompts({
|
|
@@ -211,6 +78,7 @@ export const devCmd = async (ctx: AppContext, args: any) => {
|
|
|
211
78
|
} else if (!action || action === "stop") {
|
|
212
79
|
if (server.stop) server.stop()
|
|
213
80
|
if (server.close) server.close()
|
|
81
|
+
watcher.stop()
|
|
214
82
|
break
|
|
215
83
|
}
|
|
216
84
|
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import kleur from "kleur"
|
|
2
|
+
import { join as joinPath } from "path"
|
|
3
|
+
import { AxiosInstance } from "axios"
|
|
4
|
+
import { readdirSync, readFileSync } from "fs"
|
|
5
|
+
import { soupify } from "lib/soupify"
|
|
6
|
+
|
|
7
|
+
export const soupifyAndUploadExampleFile = async ({
|
|
8
|
+
examplesDir,
|
|
9
|
+
exampleFileName,
|
|
10
|
+
devServerAxios,
|
|
11
|
+
}: {
|
|
12
|
+
examplesDir: string
|
|
13
|
+
exampleFileName: string
|
|
14
|
+
devServerAxios: AxiosInstance
|
|
15
|
+
}) => {
|
|
16
|
+
try {
|
|
17
|
+
const examplePath = joinPath(examplesDir, exampleFileName)
|
|
18
|
+
const exampleContent = readFileSync(examplePath).toString()
|
|
19
|
+
|
|
20
|
+
let exportName = "default"
|
|
21
|
+
|
|
22
|
+
if (!exampleContent.includes("export default")) {
|
|
23
|
+
// try to infer an export if possible
|
|
24
|
+
const matches = Array.from(
|
|
25
|
+
exampleContent.matchAll(/export\s+(const|function)\s+([A-Z]\w+)\s*=?/g)
|
|
26
|
+
).map((m) => m[2])
|
|
27
|
+
if (matches.length === 0) {
|
|
28
|
+
throw new Error(`No export detected in "${exampleFileName}"`)
|
|
29
|
+
}
|
|
30
|
+
if (matches.length > 1) {
|
|
31
|
+
throw new Error(
|
|
32
|
+
`Multiple exports detected in "${exampleFileName}", only single exports currently working`
|
|
33
|
+
)
|
|
34
|
+
}
|
|
35
|
+
exportName = matches[0]
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
console.log(kleur.gray(`[soupifying] ${exampleFileName}...`))
|
|
39
|
+
const soup = await soupify({
|
|
40
|
+
filePath: examplePath,
|
|
41
|
+
exportName,
|
|
42
|
+
})
|
|
43
|
+
console.log(kleur.gray(`[uploading ] ${exampleFileName}...`))
|
|
44
|
+
await devServerAxios.post("/api/dev_package_examples/create", {
|
|
45
|
+
tscircuit_soup: soup,
|
|
46
|
+
file_path: examplePath,
|
|
47
|
+
export_name: exportName,
|
|
48
|
+
})
|
|
49
|
+
console.log(kleur.gray(`[ done ] ${exampleFileName}!`))
|
|
50
|
+
} catch (e: any) {
|
|
51
|
+
console.log(kleur.red(e.toString()))
|
|
52
|
+
}
|
|
53
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { AxiosInstance } from "axios"
|
|
2
|
+
import { devServerRequestHandler } from "./dev-server-request-handler"
|
|
3
|
+
|
|
4
|
+
export const startDevServer = async ({
|
|
5
|
+
port,
|
|
6
|
+
devServerAxios,
|
|
7
|
+
}: {
|
|
8
|
+
port: number
|
|
9
|
+
devServerAxios: AxiosInstance
|
|
10
|
+
}) => {
|
|
11
|
+
let server: any
|
|
12
|
+
if (typeof Bun !== "undefined") {
|
|
13
|
+
server = Bun.serve({
|
|
14
|
+
fetch: devServerRequestHandler,
|
|
15
|
+
development: false,
|
|
16
|
+
port,
|
|
17
|
+
})
|
|
18
|
+
} else {
|
|
19
|
+
// Hono messes up the globals, only import it if we don't have Bun
|
|
20
|
+
const { Hono } = await import("hono")
|
|
21
|
+
const { serve } = await import("@hono/node-server")
|
|
22
|
+
const honoApp = new Hono()
|
|
23
|
+
honoApp.all("/*", (c) => devServerRequestHandler(c.req.raw))
|
|
24
|
+
server = serve({
|
|
25
|
+
fetch: honoApp.fetch,
|
|
26
|
+
port,
|
|
27
|
+
})
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
console.log("Running health check against dev server...")
|
|
31
|
+
await devServerAxios.get("/api/health")
|
|
32
|
+
|
|
33
|
+
return server
|
|
34
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { AxiosInstance } from "axios"
|
|
2
|
+
import chokidar from "chokidar"
|
|
3
|
+
import { uploadExamplesFromDirectory } from "./upload-examples-from-directory"
|
|
4
|
+
import kleur from "kleur"
|
|
5
|
+
|
|
6
|
+
export const startWatcher = async ({
|
|
7
|
+
cwd,
|
|
8
|
+
devServerAxios,
|
|
9
|
+
}: {
|
|
10
|
+
cwd: string
|
|
11
|
+
devServerAxios: AxiosInstance
|
|
12
|
+
}) => {
|
|
13
|
+
const watcher = chokidar.watch(`${cwd}/**/*.tsx`, {
|
|
14
|
+
ignored: /node_modules/,
|
|
15
|
+
persistent: true,
|
|
16
|
+
})
|
|
17
|
+
|
|
18
|
+
const upload_queue_state = {
|
|
19
|
+
dirty: false,
|
|
20
|
+
should_run: true,
|
|
21
|
+
}
|
|
22
|
+
watcher.on("change", async (path) => {
|
|
23
|
+
console.log(`File ${path} has been changed`)
|
|
24
|
+
// TODO analyze to determine which examples were impacted
|
|
25
|
+
upload_queue_state.dirty = true
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
async function uploadInBackground() {
|
|
29
|
+
while (upload_queue_state.should_run) {
|
|
30
|
+
if (upload_queue_state.dirty) {
|
|
31
|
+
console.log(kleur.yellow("Changes detected, re-uploading examples..."))
|
|
32
|
+
upload_queue_state.dirty = false
|
|
33
|
+
await uploadExamplesFromDirectory({ cwd, devServerAxios })
|
|
34
|
+
}
|
|
35
|
+
await new Promise((resolve) => setTimeout(resolve, 100))
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const _backgroundUploaderPromise = uploadInBackground()
|
|
40
|
+
|
|
41
|
+
return {
|
|
42
|
+
_backgroundUploaderPromise,
|
|
43
|
+
stop: () => {
|
|
44
|
+
upload_queue_state.should_run = false
|
|
45
|
+
watcher.close()
|
|
46
|
+
},
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import kleur from "kleur"
|
|
2
|
+
import { join as joinPath } from "path"
|
|
3
|
+
import { AxiosInstance } from "axios"
|
|
4
|
+
import { readdirSync, readFileSync } from "fs"
|
|
5
|
+
import { soupify } from "lib/soupify"
|
|
6
|
+
import { soupifyAndUploadExampleFile } from "./soupify-and-upload-example-file"
|
|
7
|
+
|
|
8
|
+
export const uploadExamplesFromDirectory = async ({
|
|
9
|
+
cwd,
|
|
10
|
+
devServerAxios,
|
|
11
|
+
}: {
|
|
12
|
+
cwd: string
|
|
13
|
+
devServerAxios: AxiosInstance
|
|
14
|
+
}) => {
|
|
15
|
+
const examplesDir = joinPath(cwd, "examples")
|
|
16
|
+
const exampleFileNames = readdirSync(examplesDir)
|
|
17
|
+
for (const exampleFileName of exampleFileNames) {
|
|
18
|
+
if (exampleFileName.endsWith(".__tmp_entrypoint.tsx")) continue
|
|
19
|
+
if (!exampleFileName.endsWith(".tsx")) continue
|
|
20
|
+
await soupifyAndUploadExampleFile({
|
|
21
|
+
devServerAxios,
|
|
22
|
+
examplesDir,
|
|
23
|
+
exampleFileName,
|
|
24
|
+
})
|
|
25
|
+
}
|
|
26
|
+
}
|
package/lib/cmd-fns/init.ts
CHANGED
|
@@ -59,6 +59,9 @@ export const initCmd = async (ctx: AppContext, args: any) => {
|
|
|
59
59
|
await $`${pkm} add -D typescript tsx`
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
+
// TODO just allow adding "tscircuit" in the future
|
|
63
|
+
await $`${pkm} add -D @tscircuit/react-fiber @tscircuit/builder`
|
|
64
|
+
|
|
62
65
|
console.log("Changing package name...")
|
|
63
66
|
// Change package.json "name" to params.name
|
|
64
67
|
const packageJson = JSON.parse(readFileSync("package.json", "utf-8"))
|
|
@@ -66,9 +69,9 @@ export const initCmd = async (ctx: AppContext, args: any) => {
|
|
|
66
69
|
writeFileSync("package.json", JSON.stringify(packageJson, null, 2))
|
|
67
70
|
|
|
68
71
|
console.log(`Adding ".tscircuit" to .gitignore`)
|
|
69
|
-
appendFileSync(".gitignore", "\n.tscircuit", {
|
|
72
|
+
appendFileSync(".gitignore", "\n.tscircuit\n*.__tmp_entrypoint.tsx", {
|
|
70
73
|
encoding: "utf-8",
|
|
71
|
-
flag: "
|
|
74
|
+
flag: "a+",
|
|
72
75
|
})
|
|
73
76
|
|
|
74
77
|
console.log("Creating lib and examples directories...")
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tscircuit/cli",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.5",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "Command line tool for developing, publishing and installing tscircuit circuits",
|
|
@@ -11,7 +11,8 @@
|
|
|
11
11
|
"start:dev-server": "bun build:dev-server && bun cli.ts dev -y --cwd ./tests/assets/example-project",
|
|
12
12
|
"build:dev-server": "cd dev-server-api && bun run build && cd ../dev-server-frontend && bun run build",
|
|
13
13
|
"build:cli": "bun build-cli.ts",
|
|
14
|
-
"build": "bun build:dev-server && npm run build:cli"
|
|
14
|
+
"build": "bun build:dev-server && npm run build:cli",
|
|
15
|
+
"test:init": "bun cli.ts init --dir ./tmp/test --name test"
|
|
15
16
|
},
|
|
16
17
|
"bin": {
|
|
17
18
|
"tscircuit": "./dist/cli.js",
|
|
@@ -28,6 +29,7 @@
|
|
|
28
29
|
"@tscircuit/react-fiber": "^1.0.6",
|
|
29
30
|
"axios": "^1.6.7",
|
|
30
31
|
"better-sqlite3": "^9.4.3",
|
|
32
|
+
"chokidar": "^3.6.0",
|
|
31
33
|
"commander": "^12.0.0",
|
|
32
34
|
"configstore": "^6.0.0",
|
|
33
35
|
"dax-sh": "^0.39.2",
|
|
@@ -48,6 +50,7 @@
|
|
|
48
50
|
},
|
|
49
51
|
"devDependencies": {
|
|
50
52
|
"@types/bun": "^1.0.8",
|
|
53
|
+
"@types/chokidar": "^2.1.3",
|
|
51
54
|
"@types/configstore": "^6.0.2",
|
|
52
55
|
"@types/lodash": "^4.14.202",
|
|
53
56
|
"@types/mime-types": "^2.1.4",
|