From f3600aed416e1cb1105538c1bf86b54ffd63e046 Mon Sep 17 00:00:00 2001 From: Corey Johnson Date: Mon, 16 Jun 2025 11:26:21 -0700 Subject: [PATCH] Readme stuff --- README.md | 32 +++++- bun.lock | 39 ++++++- packages/mything/.gitignore | 34 ++++++ packages/mything/README.md | 21 ++++ packages/mything/build.ts | 169 +++++++++++++++++++++++++++++ packages/mything/bun-env.d.ts | 17 +++ packages/mything/bunfig.toml | 4 + packages/mything/package.json | 24 ++++ packages/mything/src/APITester.tsx | 63 +++++++++++ packages/mything/src/App.tsx | 32 ++++++ packages/mything/src/frontend.tsx | 20 ++++ packages/mything/src/index.css | 50 +++++++++ packages/mything/src/index.html | 13 +++ packages/mything/src/index.tsx | 39 +++++++ packages/mything/src/logo.svg | 1 + packages/mything/src/react.svg | 8 ++ packages/mything/tsconfig.json | 17 +++ 17 files changed, 578 insertions(+), 5 deletions(-) create mode 100644 packages/mything/.gitignore create mode 100644 packages/mything/README.md create mode 100644 packages/mything/build.ts create mode 100644 packages/mything/bun-env.d.ts create mode 100644 packages/mything/bunfig.toml create mode 100644 packages/mything/package.json create mode 100644 packages/mything/src/APITester.tsx create mode 100644 packages/mything/src/App.tsx create mode 100644 packages/mything/src/frontend.tsx create mode 100644 packages/mything/src/index.css create mode 100644 packages/mything/src/index.html create mode 100644 packages/mything/src/index.tsx create mode 100644 packages/mything/src/logo.svg create mode 100644 packages/mything/src/react.svg create mode 100644 packages/mything/tsconfig.json diff --git a/README.md b/README.md index 18f026f..d936b51 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,33 @@ # The Rabbit Hole -We'll figure out what this is later. +We are making a bunch of smaller projects that occasionally rely on each other. So a monorepo makes a lot of sense! It lets us share code, and share dependencies with minimal fuss. + +## Ok, I want to add a new project. + +- `bun init packages/WHATEVER_YOU_WANT` +- Edit the `package.json` and change the name to `@the-rabbit-hole/WHATEVER_YOU_WANT` + +To add one of the existing packages as a dependency, edit the `package.json` and add it to the `dependencies` or `devDependencies` section. For example, if you want to add `@the-rabbit-hole/WHATEVER_YOU_WANT`, you would do: + +```json +{ + "dependencies": { + "@the-rabbit-hole/WHATEVER_YOU_WANT": "workspace:*" + } +} +``` + +Then run `bun install` and import it in your code like so: + +```javascript +import { something } from "@the-rabbit-hole/WHATEVER_YOU_WANT" +``` + +## What does corey not love about this? + +- I'd prefer the namespace to be shorter, `@the-rabbit-hole` is a bit long. +- There are lots things I don't love about nano-remix, but it works well enough for now. + +## How do I run the tests? + +šŸ˜‚ diff --git a/bun.lock b/bun.lock index bbaf1db..94842db 100644 --- a/bun.lock +++ b/bun.lock @@ -3,10 +3,6 @@ "workspaces": { "": { "name": "the-rabbit-hole", - "devDependencies": { - "@the-rabbit-hole/http": "workspace:*", - "@the-rabbit-hole/spike": "workspace:*", - }, }, "packages/http": { "name": "@the-rabbit-hole/http", @@ -22,6 +18,21 @@ "typescript": "^5", }, }, + "packages/mything": { + "name": "bun-react-template", + "version": "0.1.0", + "dependencies": { + "bun-plugin-tailwind": "^0.0.14", + "react": "^19", + "react-dom": "^19", + "tailwindcss": "^4.0.6", + }, + "devDependencies": { + "@types/bun": "latest", + "@types/react": "^19", + "@types/react-dom": "^19", + }, + }, "packages/nano-remix": { "name": "@the-rabbit-hole/nano-remix", "dependencies": { @@ -93,12 +104,22 @@ "@types/node": ["@types/node@24.0.1", "", { "dependencies": { "undici-types": "~7.8.0" } }, "sha512-MX4Zioh39chHlDJbKmEgydJDS3tspMP/lnQC67G3SWsTnb9NeYVWOjkxpOSy4oMfPs4StcWHwBrvUb4ybfnuaw=="], + "@types/react": ["@types/react@19.1.8", "", { "dependencies": { "csstype": "^3.0.2" } }, "sha512-AwAfQ2Wa5bCx9WP8nZL2uMZWod7J7/JSplxbTmBQ5ms6QpqNYm672H0Vu9ZVKVngQ+ii4R/byguVEUZQyeg44g=="], + + "@types/react-dom": ["@types/react-dom@19.1.6", "", { "peerDependencies": { "@types/react": "^19.0.0" } }, "sha512-4hOiT/dwO8Ko0gV1m/TJZYk3y0KBnY9vzDh7W+DH17b2HFSOGgdj33dhihPeuy3l0q23+4e+hoXHV6hCC4dCXw=="], + "@types/ws": ["@types/ws@8.18.1", "", { "dependencies": { "@types/node": "*" } }, "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg=="], "@vladfrangu/async_event_emitter": ["@vladfrangu/async_event_emitter@2.4.6", "", {}, "sha512-RaI5qZo6D2CVS6sTHFKg1v5Ohq/+Bo2LZ5gzUEwZ/WkHhwtGTCB/sVLw8ijOkAUxasZ+WshN/Rzj4ywsABJ5ZA=="], + "bun-plugin-tailwind": ["bun-plugin-tailwind@0.0.14", "", { "dependencies": { "tailwindcss": "4.0.0-beta.9" }, "peerDependencies": { "typescript": "^5.0.0" } }, "sha512-Ge8M8DQsRDErCzH/uI8pYjx5vZWXxQvnwM/xMQMElxQqHieGbAopfYo/q/kllkPkRbFHiwhnHwTpRMAMJZCjug=="], + + "bun-react-template": ["bun-react-template@workspace:packages/mything"], + "bun-types": ["bun-types@1.2.16", "", { "dependencies": { "@types/node": "*" } }, "sha512-ciXLrHV4PXax9vHvUrkvun9VPVGOVwbbbBF/Ev1cXz12lyEZMoJpIJABOfPcN9gDJRaiKF9MVbSygLg4NXu3/A=="], + "csstype": ["csstype@3.1.3", "", {}, "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="], + "discord-api-types": ["discord-api-types@0.38.11", "", {}, "sha512-XN0qhcQpetkyb/49hcDHuoeUPsQqOkb17wbV/t48gUkoEDi4ajhsxqugGcxvcN17BBtI9FPPWEgzv6IhQmCwyw=="], "discord.js": ["discord.js@14.19.3", "", { "dependencies": { "@discordjs/builders": "^1.11.2", "@discordjs/collection": "1.5.3", "@discordjs/formatters": "^0.6.1", "@discordjs/rest": "^2.5.0", "@discordjs/util": "^1.1.1", "@discordjs/ws": "^1.2.2", "@sapphire/snowflake": "3.5.3", "discord-api-types": "^0.38.1", "fast-deep-equal": "3.1.3", "lodash.snakecase": "4.1.1", "magic-bytes.js": "^1.10.0", "tslib": "^2.6.3", "undici": "6.21.1" } }, "sha512-lncTRk0k+8Q5D3nThnODBR8fR8x2fM798o8Vsr40Krx0DjPwpZCuxxTcFMrXMQVOqM1QB9wqWgaXPg3TbmlHqA=="], @@ -117,6 +138,14 @@ "openai": ["openai@5.3.0", "", { "peerDependencies": { "ws": "^8.18.0", "zod": "^3.23.8" }, "optionalPeers": ["ws", "zod"], "bin": { "openai": "bin/cli" } }, "sha512-VIKmoF7y4oJCDOwP/oHXGzM69+x0dpGFmN9QmYO+uPbLFOmmnwO+x1GbsgUtI+6oraxomGZ566Y421oYVu191w=="], + "react": ["react@19.1.0", "", {}, "sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg=="], + + "react-dom": ["react-dom@19.1.0", "", { "dependencies": { "scheduler": "^0.26.0" }, "peerDependencies": { "react": "^19.1.0" } }, "sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g=="], + + "scheduler": ["scheduler@0.26.0", "", {}, "sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA=="], + + "tailwindcss": ["tailwindcss@4.1.10", "", {}, "sha512-P3nr6WkvKV/ONsTzj6Gb57sWPMX29EPNPopo7+FcpkQaNsrNpZ1pv8QmrYI2RqEKD7mlGqLnGovlcYnBK0IqUA=="], + "ts-mixer": ["ts-mixer@6.0.4", "", {}, "sha512-ufKpbmrugz5Aou4wcr5Wc1UUFWOLhq+Fm6qa6P0w0K5Qw2yhaUoiWszhCVuNQyNwrlGiscHOmqYoAox1PtvgjA=="], "tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], @@ -134,5 +163,7 @@ "@discordjs/rest/@discordjs/collection": ["@discordjs/collection@2.1.1", "", {}, "sha512-LiSusze9Tc7qF03sLCujF5iZp7K+vRNEDBZ86FT9aQAv3vxMLihUvKvpsCWiQ2DJq1tVckopKm1rxomgNUc9hg=="], "@discordjs/ws/@discordjs/collection": ["@discordjs/collection@2.1.1", "", {}, "sha512-LiSusze9Tc7qF03sLCujF5iZp7K+vRNEDBZ86FT9aQAv3vxMLihUvKvpsCWiQ2DJq1tVckopKm1rxomgNUc9hg=="], + + "bun-plugin-tailwind/tailwindcss": ["tailwindcss@4.0.0-beta.9", "", {}, "sha512-96KpsfQi+/sFIOfyFnGzyy5pobuzf1iMBD9NVtelerPM/lPI2XUS4Kikw9yuKRniXXw77ov1sl7gCSKLsn6CJA=="], } } diff --git a/packages/mything/.gitignore b/packages/mything/.gitignore new file mode 100644 index 0000000..a14702c --- /dev/null +++ b/packages/mything/.gitignore @@ -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 diff --git a/packages/mything/README.md b/packages/mything/README.md new file mode 100644 index 0000000..2521717 --- /dev/null +++ b/packages/mything/README.md @@ -0,0 +1,21 @@ +# bun-react-tailwind-template + +To install dependencies: + +```bash +bun install +``` + +To start a development server: + +```bash +bun dev +``` + +To run for production: + +```bash +bun start +``` + +This project was created using `bun init` in bun v1.2.16. [Bun](https://bun.sh) is a fast all-in-one JavaScript runtime. diff --git a/packages/mything/build.ts b/packages/mything/build.ts new file mode 100644 index 0000000..50ad7cf --- /dev/null +++ b/packages/mything/build.ts @@ -0,0 +1,169 @@ +#!/usr/bin/env bun +import { build, type BuildConfig } from "bun"; +import plugin from "bun-plugin-tailwind"; +import { existsSync } from "fs"; +import { rm } from "fs/promises"; +import path from "path"; + +// Print help text if requested +if (process.argv.includes("--help") || process.argv.includes("-h")) { + console.log(` +šŸ—ļø Bun Build Script + +Usage: bun run build.ts [options] + +Common Options: + --outdir Output directory (default: "dist") + --minify Enable minification (or --minify.whitespace, --minify.syntax, etc) + --source-map Sourcemap type: none|linked|inline|external + --target Build target: browser|bun|node + --format Output format: esm|cjs|iife + --splitting Enable code splitting + --packages Package handling: bundle|external + --public-path Public path for assets + --env Environment handling: inline|disable|prefix* + --conditions Package.json export conditions (comma separated) + --external External packages (comma separated) + --banner Add banner text to output + --footer Add footer text to output + --define Define global constants (e.g. --define.VERSION=1.0.0) + --help, -h Show this help message + +Example: + bun run build.ts --outdir=dist --minify --source-map=linked --external=react,react-dom +`); + process.exit(0); +} + +// Helper function to convert kebab-case to camelCase +const toCamelCase = (str: string): string => { + return str.replace(/-([a-z])/g, g => g[1].toUpperCase()); +}; + +// Helper function to parse a value into appropriate type +const parseValue = (value: string): any => { + // Handle true/false strings + if (value === "true") return true; + if (value === "false") return false; + + // Handle numbers + if (/^\d+$/.test(value)) return parseInt(value, 10); + if (/^\d*\.\d+$/.test(value)) return parseFloat(value); + + // Handle arrays (comma-separated) + if (value.includes(",")) return value.split(",").map(v => v.trim()); + + // Default to string + return value; +}; + +// Magical argument parser that converts CLI args to BuildConfig +function parseArgs(): Partial { + const config: Record = {}; + const args = process.argv.slice(2); + + for (let i = 0; i < args.length; i++) { + const arg = args[i]; + if (!arg.startsWith("--")) continue; + + // Handle --no-* flags + if (arg.startsWith("--no-")) { + const key = toCamelCase(arg.slice(5)); + config[key] = false; + continue; + } + + // Handle --flag (boolean true) + if (!arg.includes("=") && (i === args.length - 1 || args[i + 1].startsWith("--"))) { + const key = toCamelCase(arg.slice(2)); + config[key] = true; + continue; + } + + // Handle --key=value or --key value + let key: string; + let value: string; + + if (arg.includes("=")) { + [key, value] = arg.slice(2).split("=", 2); + } else { + key = arg.slice(2); + value = args[++i]; + } + + // Convert kebab-case key to camelCase + key = toCamelCase(key); + + // Handle nested properties (e.g. --minify.whitespace) + if (key.includes(".")) { + const [parentKey, childKey] = key.split("."); + config[parentKey] = config[parentKey] || {}; + config[parentKey][childKey] = parseValue(value); + } else { + config[key] = parseValue(value); + } + } + + return config as Partial; +} + +// Helper function to format file sizes +const formatFileSize = (bytes: number): string => { + const units = ["B", "KB", "MB", "GB"]; + let size = bytes; + let unitIndex = 0; + + while (size >= 1024 && unitIndex < units.length - 1) { + size /= 1024; + unitIndex++; + } + + return `${size.toFixed(2)} ${units[unitIndex]}`; +}; + +console.log("\nšŸš€ Starting build process...\n"); + +// Parse CLI arguments with our magical parser +const cliConfig = parseArgs(); +const outdir = cliConfig.outdir || path.join(process.cwd(), "dist"); + +if (existsSync(outdir)) { + console.log(`šŸ—‘ļø Cleaning previous build at ${outdir}`); + await rm(outdir, { recursive: true, force: true }); +} + +const start = performance.now(); + +// Scan for all HTML files in the project +const entrypoints = [...new Bun.Glob("**.html").scanSync("src")] + .map(a => path.resolve("src", a)) + .filter(dir => !dir.includes("node_modules")); +console.log(`šŸ“„ Found ${entrypoints.length} HTML ${entrypoints.length === 1 ? "file" : "files"} to process\n`); + +// Build all the HTML files +const result = await build({ + entrypoints, + outdir, + plugins: [plugin], + minify: true, + target: "browser", + sourcemap: "linked", + define: { + "process.env.NODE_ENV": JSON.stringify("production"), + }, + ...cliConfig, // Merge in any CLI-provided options +}); + +// Print the results +const end = performance.now(); + +const outputTable = result.outputs.map(output => ({ + "File": path.relative(process.cwd(), output.path), + "Type": output.kind, + "Size": formatFileSize(output.size), +})); + +console.table(outputTable); +const buildTime = (end - start).toFixed(2); + +console.log(`\nāœ… Build completed in ${buildTime}ms\n`); diff --git a/packages/mything/bun-env.d.ts b/packages/mything/bun-env.d.ts new file mode 100644 index 0000000..72f1c26 --- /dev/null +++ b/packages/mything/bun-env.d.ts @@ -0,0 +1,17 @@ +// Generated by `bun init` + +declare module "*.svg" { + /** + * A path to the SVG file + */ + const path: `${string}.svg`; + export = path; +} + +declare module "*.module.css" { + /** + * A record of class names to their corresponding CSS module classes + */ + const classes: { readonly [key: string]: string }; + export = classes; +} diff --git a/packages/mything/bunfig.toml b/packages/mything/bunfig.toml new file mode 100644 index 0000000..8877354 --- /dev/null +++ b/packages/mything/bunfig.toml @@ -0,0 +1,4 @@ + +[serve.static] +plugins = ["bun-plugin-tailwind"] +env = "BUN_PUBLIC_*" \ No newline at end of file diff --git a/packages/mything/package.json b/packages/mything/package.json new file mode 100644 index 0000000..de3c8d9 --- /dev/null +++ b/packages/mything/package.json @@ -0,0 +1,24 @@ +{ + "name": "bun-react-template", + "version": "0.1.0", + "private": true, + "type": "module", + "main": "src/index.tsx", + "module": "src/index.tsx", + "scripts": { + "dev": "bun --hot src/index.tsx", + "start": "NODE_ENV=production bun src/index.tsx", + "build": "bun run build.ts" + }, + "dependencies": { + "bun-plugin-tailwind": "^0.0.14", + "react": "^19", + "react-dom": "^19", + "tailwindcss": "^4.0.6" + }, + "devDependencies": { + "@types/react": "^19", + "@types/react-dom": "^19", + "@types/bun": "latest" + } +} diff --git a/packages/mything/src/APITester.tsx b/packages/mything/src/APITester.tsx new file mode 100644 index 0000000..0f378ae --- /dev/null +++ b/packages/mything/src/APITester.tsx @@ -0,0 +1,63 @@ +import { useRef, type FormEvent } from "react"; + +export function APITester() { + const responseInputRef = useRef(null); + + const testEndpoint = async (e: FormEvent) => { + e.preventDefault(); + + try { + const form = e.currentTarget; + const formData = new FormData(form); + const endpoint = formData.get("endpoint") as string; + const url = new URL(endpoint, location.href); + const method = formData.get("method") as string; + const res = await fetch(url, { method }); + + const data = await res.json(); + responseInputRef.current!.value = JSON.stringify(data, null, 2); + } catch (error) { + responseInputRef.current!.value = String(error); + } + }; + + return ( +
+
+ + + +
+