flashts 1.0.0

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.
@@ -0,0 +1,213 @@
1
+ import { Hono } from "hono";
2
+ import { cors } from "hono/cors";
3
+ import { join } from "path";
4
+ import { mkdir, readdir, readFile } from "fs/promises";
5
+ import { serveStatic } from "hono/bun";
6
+
7
+ const app = new Hono();
8
+
9
+ // Enable CORS for the frontend
10
+ app.use("/*", cors());
11
+
12
+ // Ensure tmp directory exists
13
+ const TMP_DIR = join(process.cwd(), "tmp");
14
+ await mkdir(TMP_DIR, { recursive: true });
15
+
16
+ // Serve static files from the client/dist directory
17
+ app.use("/*", serveStatic({ root: "./client/dist" }));
18
+
19
+ app.get("/api/health", (c) => c.text("FlashTS API Active"));
20
+
21
+ app.post("/execute", async (c) => {
22
+ try {
23
+ const body = await c.req.json();
24
+ const { files, entryPoint } = body;
25
+
26
+ if (!files || !entryPoint) {
27
+ return c.json({ error: "Invalid project state" }, 400);
28
+ }
29
+
30
+ const sessionId = crypto.randomUUID();
31
+ const sessionDir = join(TMP_DIR, sessionId);
32
+ await mkdir(sessionDir, { recursive: true });
33
+
34
+ for (const [name, content] of Object.entries(files)) {
35
+ const filePath = join(sessionDir, name as string);
36
+ const dir = join(sessionDir, join(...(name as string).split('/').slice(0, -1)));
37
+ if (dir !== sessionDir) await mkdir(dir, { recursive: true });
38
+ await Bun.write(filePath, content as string);
39
+ }
40
+
41
+ const proc = Bun.spawn(["bun", "run", entryPoint], {
42
+ stdout: "pipe",
43
+ stderr: "pipe",
44
+ cwd: sessionDir,
45
+ });
46
+
47
+ const timeout = 10000;
48
+ const timeoutPromise = new Promise((_, reject) =>
49
+ setTimeout(() => {
50
+ proc.kill();
51
+ reject(new Error("Execution timed out"));
52
+ }, timeout)
53
+ );
54
+
55
+ const executionPromise = (async () => {
56
+ const stdout = await new Response(proc.stdout).text();
57
+ const stderr = await new Response(proc.stderr).text();
58
+ const exitCode = await proc.exited;
59
+ return { stdout, stderr, exitCode };
60
+ })();
61
+
62
+ const result = { ...await Promise.race([executionPromise, timeoutPromise]) as any, sessionId };
63
+
64
+ setTimeout(() => {
65
+ try {
66
+ import("fs").then(fs => fs.promises.rm(sessionDir, { recursive: true, force: true }));
67
+ } catch (e) {}
68
+ }, 5000);
69
+
70
+ return c.json(result);
71
+
72
+ } catch (error: any) {
73
+ return c.json({
74
+ stdout: "",
75
+ stderr: error.message || String(error),
76
+ exitCode: 1
77
+ }, 500);
78
+ }
79
+ });
80
+
81
+ app.post("/install", async (c) => {
82
+ const { package: pkgName } = await c.req.json();
83
+ if (!pkgName || typeof pkgName !== 'string') {
84
+ return c.json({ error: "Invalid package name" }, 400);
85
+ }
86
+
87
+ try {
88
+ const proc = Bun.spawn(["bun", "add", pkgName], {
89
+ cwd: process.cwd(),
90
+ stdout: "pipe",
91
+ stderr: "pipe",
92
+ });
93
+
94
+ const output = await new Response(proc.stdout).text();
95
+ const error = await new Response(proc.stderr).text();
96
+ const exitCode = await proc.exited;
97
+
98
+ if (exitCode !== 0) {
99
+ return c.json({ success: false, output: error || output }, 500);
100
+ }
101
+
102
+ return c.json({ success: true, output });
103
+ } catch (err: any) {
104
+ return c.json({ success: false, output: err.message }, 500);
105
+ }
106
+ });
107
+
108
+ app.get("/dependencies", async (c) => {
109
+ try {
110
+ const pkgPath = join(process.cwd(), "package.json");
111
+ const pkgData = JSON.parse(await readFile(pkgPath, "utf-8"));
112
+ return c.json(pkgData.dependencies || {});
113
+ } catch (e) {
114
+ return c.json({});
115
+ }
116
+ });
117
+
118
+ app.post("/uninstall", async (c) => {
119
+ const { package: pkgName } = await c.req.json();
120
+ if (!pkgName || typeof pkgName !== 'string') {
121
+ return c.json({ error: "Invalid package name" }, 400);
122
+ }
123
+
124
+ try {
125
+ const proc = Bun.spawn(["bun", "remove", pkgName], {
126
+ cwd: process.cwd(),
127
+ stdout: "pipe",
128
+ stderr: "pipe",
129
+ });
130
+
131
+ const output = await new Response(proc.stdout).text();
132
+ const error = await new Response(proc.stderr).text();
133
+ const exitCode = await proc.exited;
134
+
135
+ if (exitCode !== 0) {
136
+ return c.json({ success: false, output: error || output }, 500);
137
+ }
138
+
139
+ return c.json({ success: true, output });
140
+ } catch (err: any) {
141
+ return c.json({ success: false, output: err.message }, 500);
142
+ }
143
+ });
144
+
145
+ async function getPackageTypeTree(pkgName: string) {
146
+ const pkgDir = join(process.cwd(), "node_modules", pkgName);
147
+ const files: Record<string, string> = {};
148
+
149
+ async function scan(dir: string, relativePath: string = "") {
150
+ const entries = await readdir(dir, { withFileTypes: true });
151
+ for (const entry of entries) {
152
+ const res = join(dir, entry.name);
153
+ const rel = relativePath ? `${relativePath}/${entry.name}` : entry.name;
154
+
155
+ if (entry.isDirectory()) {
156
+ if (entry.name === 'node_modules') continue;
157
+ await scan(res, rel);
158
+ } else if (entry.name.endsWith(".d.ts") || entry.name === "package.json") {
159
+ try {
160
+ files[rel] = await readFile(res, "utf-8");
161
+ } catch (e) {
162
+ }
163
+ }
164
+ }
165
+ }
166
+
167
+ try {
168
+ await scan(pkgDir);
169
+ return files;
170
+ } catch (e) {
171
+ try {
172
+ const typesPkgName = pkgName.startsWith('@')
173
+ ? pkgName.slice(1).replace('/', '__')
174
+ : pkgName;
175
+ const atTypesDir = join(process.cwd(), "node_modules", "@types", typesPkgName);
176
+ await scan(atTypesDir);
177
+ return files;
178
+ } catch (e2) {
179
+ return null;
180
+ }
181
+ }
182
+ }
183
+
184
+ app.get("/package-types/:pkg{.+$}", async (c) => {
185
+ const pkgName = c.req.param("pkg");
186
+ const tree = await getPackageTypeTree(pkgName);
187
+
188
+ if (!tree) {
189
+ return c.json({ error: "Types not found" }, 404);
190
+ }
191
+
192
+ return c.json({ tree, pkgName });
193
+ });
194
+
195
+ app.get("/search", async (c) => {
196
+ const query = c.req.query("q");
197
+ if (!query) return c.json({ objects: [] });
198
+
199
+ try {
200
+ const res = await fetch(`https://registry.npmjs.org/-/v1/search?text=${encodeURIComponent(query)}&size=20`);
201
+ const data = await res.json();
202
+ return c.json(data);
203
+ } catch (err) {
204
+ return c.json({ objects: [] });
205
+ }
206
+ });
207
+
208
+ const port = parseInt(process.env.PORT || "3000");
209
+
210
+ export default {
211
+ port,
212
+ fetch: app.fetch,
213
+ };
@@ -0,0 +1,17 @@
1
+ {
2
+ "name": "server",
3
+ "module": "index.ts",
4
+ "type": "module",
5
+ "private": true,
6
+ "devDependencies": {
7
+ "@types/bun": "latest"
8
+ },
9
+ "peerDependencies": {
10
+ "typescript": "^5"
11
+ },
12
+ "dependencies": {
13
+ "@types/react": "^19.2.9",
14
+ "hono": "^4.11.5",
15
+ "react": "^19.2.3"
16
+ }
17
+ }
@@ -0,0 +1,29 @@
1
+ {
2
+ "compilerOptions": {
3
+ // Environment setup & latest features
4
+ "lib": ["ESNext"],
5
+ "target": "ESNext",
6
+ "module": "Preserve",
7
+ "moduleDetection": "force",
8
+ "jsx": "react-jsx",
9
+ "allowJs": true,
10
+
11
+ // Bundler mode
12
+ "moduleResolution": "bundler",
13
+ "allowImportingTsExtensions": true,
14
+ "verbatimModuleSyntax": true,
15
+ "noEmit": true,
16
+
17
+ // Best practices
18
+ "strict": true,
19
+ "skipLibCheck": true,
20
+ "noFallthroughCasesInSwitch": true,
21
+ "noUncheckedIndexedAccess": true,
22
+ "noImplicitOverride": true,
23
+
24
+ // Some stricter flags (disabled by default)
25
+ "noUnusedLocals": false,
26
+ "noUnusedParameters": false,
27
+ "noPropertyAccessFromIndexSignature": false
28
+ }
29
+ }
@@ -0,0 +1,2 @@
1
+ // Welcome to FlashTS!
2
+ console.log("Hello from main.tssa");