Add project-whiteboard app and update dependencies
This commit is contained in:
parent
b758f66c69
commit
fc9288d0cc
109
.github/instructions/bun.instructions.md
vendored
Normal file
109
.github/instructions/bun.instructions.md
vendored
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
---
|
||||
applyTo: "**/*.{js,ts,jsx,tsx}"
|
||||
---
|
||||
|
||||
Default to using Bun instead of Node.js.
|
||||
|
||||
- Use `bun <file>` instead of `node <file>` or `ts-node <file>`
|
||||
- Use `bun test` instead of `jest` or `vitest`
|
||||
- Use `bun build <file.html|file.ts|file.css>` instead of `webpack` or `esbuild`
|
||||
- Use `bun install` instead of `npm install` or `yarn install` or `pnpm install`
|
||||
- Use `bun run <script>` instead of `npm run <script>` or `yarn run <script>` or `pnpm run <script>`
|
||||
- Bun automatically loads .env, so don't use dotenv.
|
||||
|
||||
## APIs
|
||||
|
||||
- `Bun.serve()` supports WebSockets, HTTPS, and routes. Don't use `express`.
|
||||
- `bun:sqlite` for SQLite. Don't use `better-sqlite3`.
|
||||
- `Bun.redis` for Redis. Don't use `ioredis`.
|
||||
- `Bun.sql` for Postgres. Don't use `pg` or `postgres.js`.
|
||||
- `WebSocket` is built-in. Don't use `ws`.
|
||||
- Prefer `Bun.file` over `node:fs`'s readFile/writeFile
|
||||
- Bun.$`ls` instead of execa.
|
||||
|
||||
## Testing
|
||||
|
||||
Use `bun test` to run tests.
|
||||
|
||||
```ts#index.test.ts
|
||||
import { test, expect } from "bun:test";
|
||||
|
||||
test("hello world", () => {
|
||||
expect(1).toBe(1);
|
||||
});
|
||||
```
|
||||
|
||||
## Frontend
|
||||
|
||||
Use HTML imports with `Bun.serve()`. Don't use `vite`. HTML imports fully support React, CSS, Tailwind.
|
||||
|
||||
Server:
|
||||
|
||||
```ts#index.ts
|
||||
import index from "./index.html"
|
||||
|
||||
Bun.serve({
|
||||
routes: {
|
||||
"/": index,
|
||||
"/api/users/:id": {
|
||||
GET: (req) => {
|
||||
return new Response(JSON.stringify({ id: req.params.id }));
|
||||
},
|
||||
},
|
||||
},
|
||||
// optional websocket support
|
||||
websocket: {
|
||||
open: (ws) => {
|
||||
ws.send("Hello, world!");
|
||||
},
|
||||
message: (ws, message) => {
|
||||
ws.send(message);
|
||||
},
|
||||
close: (ws) => {
|
||||
// handle close
|
||||
}
|
||||
},
|
||||
development: {
|
||||
hmr: true,
|
||||
console: true,
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
HTML files can import .tsx, .jsx or .js files directly and Bun's bundler will transpile & bundle automatically. `<link>` tags can point to stylesheets and Bun's CSS bundler will bundle.
|
||||
|
||||
```html#index.html
|
||||
<html>
|
||||
<body>
|
||||
<h1>Hello, world!</h1>
|
||||
<script type="module" src="./frontend.tsx"></script>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
With the following `frontend.tsx`:
|
||||
|
||||
```tsx#frontend.tsx
|
||||
import React from "react";
|
||||
|
||||
// import .css files directly and it works
|
||||
import './index.css';
|
||||
|
||||
import { createRoot } from "react-dom/client";
|
||||
|
||||
const root = createRoot(document.body);
|
||||
|
||||
export default function Frontend() {
|
||||
return <h1>Hello, world!</h1>;
|
||||
}
|
||||
|
||||
root.render(<Frontend />);
|
||||
```
|
||||
|
||||
Then, run index.ts
|
||||
|
||||
```sh
|
||||
bun --hot ./index.ts
|
||||
```
|
||||
|
||||
For more information, read the Bun API docs in `node_modules/bun-types/docs/**.md`.
|
||||
39
bun.lock
39
bun.lock
|
|
@ -8,7 +8,7 @@
|
|||
"name": "attache",
|
||||
"dependencies": {
|
||||
"@workshop/shared": "workspace:*",
|
||||
"hono": "^4.8.0",
|
||||
"hono": "catalog:",
|
||||
"nanoid": "^5.1.5",
|
||||
},
|
||||
"devDependencies": {
|
||||
|
|
@ -59,6 +59,20 @@
|
|||
"typescript": "^5",
|
||||
},
|
||||
},
|
||||
"packages/project-whitespace": {
|
||||
"name": "@workspace/project-whitespace",
|
||||
"dependencies": {
|
||||
"@workshop/nano-remix": "workspace:*",
|
||||
"@workshop/shared": "workspace:*",
|
||||
"hono": "catalog:",
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/bun": "latest",
|
||||
},
|
||||
"peerDependencies": {
|
||||
"typescript": "^5",
|
||||
},
|
||||
},
|
||||
"packages/query": {
|
||||
"name": "@workshop/query",
|
||||
"dependencies": {
|
||||
|
|
@ -109,6 +123,7 @@
|
|||
"@lezer/generator": "^1.7.3",
|
||||
"@lezer/highlight": "^1.2.1",
|
||||
"@lezer/lr": "^1.4.2",
|
||||
"@workshop/nano-remix": "workspace:*",
|
||||
"hono": "catalog:",
|
||||
"luxon": "^3.6.1",
|
||||
"zzfx": "^1.3.0",
|
||||
|
|
@ -117,7 +132,6 @@
|
|||
"@types/bun": "latest",
|
||||
},
|
||||
"peerDependencies": {
|
||||
"hono": "^4",
|
||||
"typescript": "^5",
|
||||
},
|
||||
},
|
||||
|
|
@ -125,7 +139,8 @@
|
|||
"name": "@workshop/werewolf-ui",
|
||||
"version": "0.1.0",
|
||||
"dependencies": {
|
||||
"hono": "^4.8.3",
|
||||
"@workshop/nano-remix": "workspace:*",
|
||||
"hono": "catalog:",
|
||||
"lucide-static": "^0.525.0",
|
||||
"tailwindcss": "^4.0.6",
|
||||
},
|
||||
|
|
@ -222,6 +237,8 @@
|
|||
|
||||
"@workshop/werewolf-ui": ["@workshop/werewolf-ui@workspace:packages/werewolf-ui"],
|
||||
|
||||
"@workspace/project-whitespace": ["@workspace/project-whitespace@workspace:packages/project-whitespace"],
|
||||
|
||||
"accepts": ["accepts@1.3.8", "", { "dependencies": { "mime-types": "~2.1.34", "negotiator": "0.6.3" } }, "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw=="],
|
||||
|
||||
"ajv": ["ajv@6.10.0", "", { "dependencies": { "fast-deep-equal": "^2.0.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "sha512-nffhOpkymDECQyR0mnsUtoCE8RlX38G0rYP+wgLWFyZuUyuuojSSvi/+euOiQBIn63whYwYVIIH1TvE3tu4OEg=="],
|
||||
|
|
@ -782,6 +799,8 @@
|
|||
|
||||
"@workshop/nano-remix/hono": ["hono@4.8.4", "", {}, "sha512-KOIBp1+iUs0HrKztM4EHiB2UtzZDTBihDtOF5K6+WaJjCPeaW4Q92R8j63jOhvJI5+tZSMuKD9REVEXXY9illg=="],
|
||||
|
||||
"@workshop/shared/@types/bun": ["@types/bun@1.2.18", "", { "dependencies": { "bun-types": "1.2.18" } }, "sha512-Xf6RaWVheyemaThV0kUfaAUvCNokFr+bH8Jxp+tTZfx7dAPA8z9ePnP9S9+Vspzuxxx9JRAXhnyccRj3GyCMdQ=="],
|
||||
|
||||
"@workshop/todo/@types/bun": ["@types/bun@1.2.18", "", { "dependencies": { "bun-types": "1.2.18" } }, "sha512-Xf6RaWVheyemaThV0kUfaAUvCNokFr+bH8Jxp+tTZfx7dAPA8z9ePnP9S9+Vspzuxxx9JRAXhnyccRj3GyCMdQ=="],
|
||||
|
||||
"@workshop/todo/hono": ["hono@4.8.4", "", {}, "sha512-KOIBp1+iUs0HrKztM4EHiB2UtzZDTBihDtOF5K6+WaJjCPeaW4Q92R8j63jOhvJI5+tZSMuKD9REVEXXY9illg=="],
|
||||
|
|
@ -790,12 +809,20 @@
|
|||
|
||||
"@workshop/werewolf-ui/hono": ["hono@4.8.4", "", {}, "sha512-KOIBp1+iUs0HrKztM4EHiB2UtzZDTBihDtOF5K6+WaJjCPeaW4Q92R8j63jOhvJI5+tZSMuKD9REVEXXY9illg=="],
|
||||
|
||||
"@workspace/project-whitespace/@types/bun": ["@types/bun@1.2.18", "", { "dependencies": { "bun-types": "1.2.18" } }, "sha512-Xf6RaWVheyemaThV0kUfaAUvCNokFr+bH8Jxp+tTZfx7dAPA8z9ePnP9S9+Vspzuxxx9JRAXhnyccRj3GyCMdQ=="],
|
||||
|
||||
"@workspace/project-whitespace/hono": ["hono@4.8.4", "", {}, "sha512-KOIBp1+iUs0HrKztM4EHiB2UtzZDTBihDtOF5K6+WaJjCPeaW4Q92R8j63jOhvJI5+tZSMuKD9REVEXXY9illg=="],
|
||||
|
||||
"ajv/fast-deep-equal": ["fast-deep-equal@2.0.1", "", {}, "sha512-bCK/2Z4zLidyB4ReuIsvALH6w31YfAQDmXMqMx6FyfHqvBxtjC0eRumeSu4Bs3XtXwpyIywtSTrVT99BxY1f9w=="],
|
||||
|
||||
"amqplib/readable-stream": ["readable-stream@1.1.14", "", { "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.1", "isarray": "0.0.1", "string_decoder": "~0.10.x" } }, "sha512-+MeVjFf4L44XUkhM1eYbD8fyEsxcV81pqMSR5gblfcLCHfZvbrqy4/qYHE+/R5HoBUT11WV5O08Cr1n3YXkWVQ=="],
|
||||
|
||||
"amqplib/safe-buffer": ["safe-buffer@5.2.1", "", {}, "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="],
|
||||
|
||||
"attache/@types/bun": ["@types/bun@1.2.18", "", { "dependencies": { "bun-types": "1.2.18" } }, "sha512-Xf6RaWVheyemaThV0kUfaAUvCNokFr+bH8Jxp+tTZfx7dAPA8z9ePnP9S9+Vspzuxxx9JRAXhnyccRj3GyCMdQ=="],
|
||||
|
||||
"attache/hono": ["hono@4.8.4", "", {}, "sha512-KOIBp1+iUs0HrKztM4EHiB2UtzZDTBihDtOF5K6+WaJjCPeaW4Q92R8j63jOhvJI5+tZSMuKD9REVEXXY9illg=="],
|
||||
|
||||
"babel-runtime/regenerator-runtime": ["regenerator-runtime@0.11.1", "", {}, "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg=="],
|
||||
|
||||
"body-parser/content-type": ["content-type@1.0.5", "", {}, "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA=="],
|
||||
|
|
@ -896,14 +923,20 @@
|
|||
|
||||
"@workshop/nano-remix/@types/bun/bun-types": ["bun-types@1.2.18", "", { "dependencies": { "@types/node": "*" }, "peerDependencies": { "@types/react": "^19" } }, "sha512-04+Eha5NP7Z0A9YgDAzMk5PHR16ZuLVa83b26kH5+cp1qZW4F6FmAURngE7INf4tKOvCE69vYvDEwoNl1tGiWw=="],
|
||||
|
||||
"@workshop/shared/@types/bun/bun-types": ["bun-types@1.2.18", "", { "dependencies": { "@types/node": "*" }, "peerDependencies": { "@types/react": "^19" } }, "sha512-04+Eha5NP7Z0A9YgDAzMk5PHR16ZuLVa83b26kH5+cp1qZW4F6FmAURngE7INf4tKOvCE69vYvDEwoNl1tGiWw=="],
|
||||
|
||||
"@workshop/todo/@types/bun/bun-types": ["bun-types@1.2.18", "", { "dependencies": { "@types/node": "*" }, "peerDependencies": { "@types/react": "^19" } }, "sha512-04+Eha5NP7Z0A9YgDAzMk5PHR16ZuLVa83b26kH5+cp1qZW4F6FmAURngE7INf4tKOvCE69vYvDEwoNl1tGiWw=="],
|
||||
|
||||
"@workshop/werewolf-ui/@types/bun/bun-types": ["bun-types@1.2.18", "", { "dependencies": { "@types/node": "*" }, "peerDependencies": { "@types/react": "^19" } }, "sha512-04+Eha5NP7Z0A9YgDAzMk5PHR16ZuLVa83b26kH5+cp1qZW4F6FmAURngE7INf4tKOvCE69vYvDEwoNl1tGiWw=="],
|
||||
|
||||
"@workspace/project-whitespace/@types/bun/bun-types": ["bun-types@1.2.18", "", { "dependencies": { "@types/node": "*" }, "peerDependencies": { "@types/react": "^19" } }, "sha512-04+Eha5NP7Z0A9YgDAzMk5PHR16ZuLVa83b26kH5+cp1qZW4F6FmAURngE7INf4tKOvCE69vYvDEwoNl1tGiWw=="],
|
||||
|
||||
"amqplib/readable-stream/inherits": ["inherits@2.0.4", "", {}, "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="],
|
||||
|
||||
"amqplib/readable-stream/string_decoder": ["string_decoder@0.10.31", "", {}, "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ=="],
|
||||
|
||||
"attache/@types/bun/bun-types": ["bun-types@1.2.18", "", { "dependencies": { "@types/node": "*" }, "peerDependencies": { "@types/react": "^19" } }, "sha512-04+Eha5NP7Z0A9YgDAzMk5PHR16ZuLVa83b26kH5+cp1qZW4F6FmAURngE7INf4tKOvCE69vYvDEwoNl1tGiWw=="],
|
||||
|
||||
"body-parser/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="],
|
||||
|
||||
"compression/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="],
|
||||
|
|
|
|||
8
main.ts
8
main.ts
|
|
@ -24,7 +24,13 @@ const run = async (cmd: string[]) => {
|
|||
}
|
||||
|
||||
try {
|
||||
await Promise.all([run(["bun", "run", "--filter=@workshop/http", "start"]), run(["bun", "bot:discord"])])
|
||||
const isDev = process.env.NODE_ENV !== "production"
|
||||
const noElide = isDev ? "--elide-lines=0" : ""
|
||||
|
||||
await Promise.all([
|
||||
run(["bun", "run", noElide, "--filter=@workshop/http", "start"]),
|
||||
run(["bun", "run", noElide, "bot:discord"]),
|
||||
])
|
||||
console.log("✅ All processes completed successfully")
|
||||
} catch (error) {
|
||||
console.error("❌ One or more processes failed:", error)
|
||||
|
|
|
|||
|
|
@ -14,8 +14,8 @@
|
|||
"typescript": "^5"
|
||||
},
|
||||
"dependencies": {
|
||||
"hono": "^4.8.0",
|
||||
"hono": "catalog:",
|
||||
"nanoid": "^5.1.5",
|
||||
"@workshop/shared": "workspace:*"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3,6 +3,43 @@ import { basename, join } from "node:path"
|
|||
|
||||
export const startSubdomainServers = async () => {
|
||||
const portMap: Record<string, number> = {}
|
||||
const spawnedProcesses: { proc: any; name: string }[] = []
|
||||
|
||||
// Cleanup function to kill all spawned processes
|
||||
const cleanup = () => {
|
||||
console.log("🧹 Cleaning up spawned processes...")
|
||||
spawnedProcesses.forEach(({ proc, name }) => {
|
||||
try {
|
||||
if (!proc.killed) {
|
||||
console.log(`🔪 Killing process: ${name} (PID: ${proc.pid})`)
|
||||
proc.kill("SIGTERM") // Just send SIGTERM and let the OS handle the rest
|
||||
}
|
||||
} catch (err) {
|
||||
console.warn(`⚠️ Error killing process ${name}:`, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Register cleanup handlers
|
||||
process.on("exit", cleanup)
|
||||
process.on("SIGINT", () => {
|
||||
cleanup()
|
||||
process.exit(0)
|
||||
})
|
||||
process.on("SIGTERM", () => {
|
||||
cleanup()
|
||||
process.exit(0)
|
||||
})
|
||||
process.on("uncaughtException", (err) => {
|
||||
console.error("❌ Uncaught exception:", err)
|
||||
cleanup()
|
||||
process.exit(1)
|
||||
})
|
||||
process.on("unhandledRejection", (reason) => {
|
||||
console.error("❌ Unhandled rejection:", reason)
|
||||
cleanup()
|
||||
process.exit(1)
|
||||
})
|
||||
|
||||
try {
|
||||
const packageInfo = await subdomainPackageInfo()
|
||||
|
|
@ -12,17 +49,24 @@ export const startSubdomainServers = async () => {
|
|||
const port = currentPort++
|
||||
portMap[info.dirName] = port
|
||||
|
||||
return run(["bun", "run", `--filter=${info.packageName}`, "serve-subdomain"], {
|
||||
env: { PORT: port.toString() },
|
||||
})
|
||||
return run(
|
||||
["bun", "run", `--filter=${info.packageName}`, "serve-subdomain"],
|
||||
{
|
||||
env: { PORT: port.toString() },
|
||||
},
|
||||
spawnedProcesses,
|
||||
info.packageName
|
||||
)
|
||||
})
|
||||
|
||||
Promise.all(processes).catch((err) => {
|
||||
console.log(`❌ Error starting subdomain servers:`, err)
|
||||
cleanup()
|
||||
process.exit(1)
|
||||
})
|
||||
} catch (error) {
|
||||
console.error("❌ Error starting subdomain servers:", error)
|
||||
cleanup()
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
|
|
@ -50,7 +94,12 @@ export const subdomainPackageInfo = async () => {
|
|||
return packagePaths
|
||||
}
|
||||
|
||||
const run = async (cmd: string[], options: { env?: Record<string, string> } = {}) => {
|
||||
const run = async (
|
||||
cmd: string[],
|
||||
options: { env?: Record<string, string> } = {},
|
||||
processTracker?: { proc: any; name: string }[],
|
||||
processName?: string
|
||||
) => {
|
||||
const commandText = cmd.join(" ")
|
||||
const proc = Bun.spawn(cmd, {
|
||||
stdout: "inherit",
|
||||
|
|
@ -58,6 +107,12 @@ const run = async (cmd: string[], options: { env?: Record<string, string> } = {}
|
|||
env: { ...process.env, ...options.env },
|
||||
})
|
||||
|
||||
// Track the process if tracker is provided
|
||||
if (processTracker && processName) {
|
||||
processTracker.push({ proc, name: processName })
|
||||
console.log(`🚀 Started process: ${processName} (PID: ${proc.pid})`)
|
||||
}
|
||||
|
||||
const status = await proc.exited
|
||||
|
||||
if (status !== 0) {
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import { join } from "node:path"
|
|||
* 1. Starts multiple subdomain servers on different ports (3001+)
|
||||
* 2. Main server (port 3000) acts as a proxy that routes requests based on subdomain
|
||||
* 3. All requests are protected with Basic HTTP auth + persistent cookies
|
||||
* 4. Once authenticated, cookies work across all subdomains (*.yourdomain.com)
|
||||
* 4. Once authenticated, cookies work across all subdomains (*.thedomain.com)
|
||||
*
|
||||
* This server is designed to be run in production with NODE_ENV=production. On development,
|
||||
* it allows unauthenticated access because YOLO.
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import { join, extname } from "node:path"
|
|||
type Options = {
|
||||
routesDir?: string
|
||||
distDir?: string
|
||||
disableCache?: boolean // Disable caching for development
|
||||
disableCache?: boolean
|
||||
}
|
||||
export const nanoRemix = async (req: Request, options: Options = {}) => {
|
||||
const nanoRemixDir = join(process.cwd(), ".nano-remix")
|
||||
|
|
|
|||
34
packages/project-whiteboard/.gitignore
vendored
Normal file
34
packages/project-whiteboard/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
# dependencies (bun install)
|
||||
node_modules
|
||||
|
||||
# output
|
||||
out
|
||||
dist
|
||||
*.tgz
|
||||
|
||||
# code coverage
|
||||
coverage
|
||||
*.lcov
|
||||
|
||||
# logs
|
||||
logs
|
||||
_.log
|
||||
report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json
|
||||
|
||||
# dotenv environment variable files
|
||||
.env
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
.env.local
|
||||
|
||||
# caches
|
||||
.eslintcache
|
||||
.cache
|
||||
*.tsbuildinfo
|
||||
|
||||
# IntelliJ based IDEs
|
||||
.idea
|
||||
|
||||
# Finder (MacOS) folder config
|
||||
.DS_Store
|
||||
15
packages/project-whiteboard/README.md
Normal file
15
packages/project-whiteboard/README.md
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
# project-whitespace
|
||||
|
||||
To install dependencies:
|
||||
|
||||
```bash
|
||||
bun install
|
||||
```
|
||||
|
||||
To run:
|
||||
|
||||
```bash
|
||||
bun run index.ts
|
||||
```
|
||||
|
||||
This project was created using `bun init` in bun v1.2.18. [Bun](https://bun.sh) is a fast all-in-one JavaScript runtime.
|
||||
20
packages/project-whiteboard/package.json
Normal file
20
packages/project-whiteboard/package.json
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"name": "@workspace/project-whiteboard",
|
||||
"module": "index.ts",
|
||||
"type": "module",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@workshop/shared": "workspace:*",
|
||||
"@workshop/nano-remix": "workspace:*",
|
||||
"hono": "catalog:"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/bun": "latest"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"typescript": "^5"
|
||||
},
|
||||
"scripts": {
|
||||
"serve-subdomain": "bun run src/server.ts"
|
||||
}
|
||||
}
|
||||
BIN
packages/project-whiteboard/public/whiteboard.jpeg
Normal file
BIN
packages/project-whiteboard/public/whiteboard.jpeg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.5 MiB |
8
packages/project-whiteboard/src/routes/index.tsx
Normal file
8
packages/project-whiteboard/src/routes/index.tsx
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
export default function Index() {
|
||||
return (
|
||||
<div>
|
||||
<h1>PROJECT WHITEBOARD</h1>
|
||||
<img src="/whiteboard.jpeg" alt="Project Whiteboard" />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
15
packages/project-whiteboard/src/server.ts
Normal file
15
packages/project-whiteboard/src/server.ts
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
import { nanoRemix } from "@workshop/nano-remix"
|
||||
import { join } from "path"
|
||||
|
||||
Bun.serve({
|
||||
routes: {
|
||||
"/": {
|
||||
GET: (req) => {
|
||||
return nanoRemix(req, {
|
||||
routePath: join(import.meta.dir, "routes"),
|
||||
publicDir: join(import.meta.dir, "..", "public"),
|
||||
})
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
35
packages/project-whiteboard/tsconfig.json
Normal file
35
packages/project-whiteboard/tsconfig.json
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
// Environment setup & latest features
|
||||
"lib": ["ESNext", "DOM"],
|
||||
"target": "ESNext",
|
||||
"module": "Preserve",
|
||||
"moduleDetection": "force",
|
||||
"jsx": "react-jsx",
|
||||
"jsxImportSource": "hono/jsx",
|
||||
"allowJs": true,
|
||||
|
||||
// Bundler mode
|
||||
"moduleResolution": "bundler",
|
||||
"allowImportingTsExtensions": true,
|
||||
"verbatimModuleSyntax": true,
|
||||
"noEmit": true,
|
||||
|
||||
// Best practices
|
||||
"strict": true,
|
||||
"skipLibCheck": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"noUncheckedIndexedAccess": true,
|
||||
"noImplicitOverride": true,
|
||||
|
||||
// Some stricter flags (disabled by default)
|
||||
"noUnusedLocals": false,
|
||||
"noUnusedParameters": false,
|
||||
"noPropertyAccessFromIndexSignature": false,
|
||||
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"@/*": ["./src/*"]
|
||||
}
|
||||
}
|
||||
}
|
||||
0
packages/project-whitespace/src/server.ts
Normal file
0
packages/project-whitespace/src/server.ts
Normal file
|
|
@ -9,6 +9,7 @@
|
|||
"serve-subdomain": "bun run src/server.tsx"
|
||||
},
|
||||
"dependencies": {
|
||||
"@workshop/nano-remix": "workspace:*",
|
||||
"@codemirror/autocomplete": "^6.18.6",
|
||||
"@codemirror/commands": "^6.8.1",
|
||||
"@codemirror/language": "^6.11.1",
|
||||
|
|
@ -30,7 +31,6 @@
|
|||
"@types/bun": "latest"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"typescript": "^5",
|
||||
"hono": "^4"
|
||||
"typescript": "^5"
|
||||
}
|
||||
}
|
||||
|
|
@ -14,7 +14,8 @@
|
|||
"printWidth": 110
|
||||
},
|
||||
"dependencies": {
|
||||
"hono": "^4.8.3",
|
||||
"@workshop/nano-remix": "workspace:*",
|
||||
"hono": "catalog:",
|
||||
"lucide-static": "^0.525.0",
|
||||
"tailwindcss": "^4.0.6"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,18 +1,35 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
// Environment setup & latest features
|
||||
"lib": ["ESNext", "DOM"],
|
||||
"target": "ESNext",
|
||||
"module": "Preserve",
|
||||
"moduleResolution": "bundler",
|
||||
"moduleDetection": "force",
|
||||
"jsx": "react-jsx",
|
||||
"jsxImportSource": "hono/jsx",
|
||||
"allowJs": true,
|
||||
|
||||
// Bundler mode
|
||||
"moduleResolution": "bundler",
|
||||
"allowImportingTsExtensions": true,
|
||||
"verbatimModuleSyntax": true,
|
||||
"noEmit": true,
|
||||
|
||||
// Best practices
|
||||
"strict": true,
|
||||
"skipLibCheck": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"noUncheckedIndexedAccess": true,
|
||||
"noImplicitOverride": true,
|
||||
|
||||
// Some stricter flags (disabled by default)
|
||||
"noUnusedLocals": false,
|
||||
"noUnusedParameters": false,
|
||||
"noPropertyAccessFromIndexSignature": false,
|
||||
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"@/*": ["./src/*"]
|
||||
}
|
||||
},
|
||||
"exclude": ["dist", "node_modules"]
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user