From 21ba4996abe4b4ee9a3b76f82881f9cc97c13e33 Mon Sep 17 00:00:00 2001 From: Tyler <26290074+tylersayshi@users.noreply.github.com> Date: Sat, 18 Oct 2025 21:35:29 -0700 Subject: [PATCH 01/23] rename prototypey to prototypekit across entire project --- .github/workflows/ci.yml | 4 ++-- README.md | 4 ++-- package.json | 4 ++-- packages/cli/README.md | 20 +++++++++---------- packages/cli/package.json | 8 ++++---- packages/cli/src/index.ts | 2 +- packages/cli/src/templates/inferred.ts | 4 ++-- packages/cli/tests/commands/gen-emit.test.ts | 20 +++++++++---------- .../cli/tests/commands/gen-inferred.test.ts | 10 +++++----- packages/cli/tests/fixtures/simple-lexicon.ts | 2 +- .../{prototypey => prototypekit}/package.json | 6 +++--- .../setup-vitest.ts | 0 .../{prototypey => prototypekit}/src/index.ts | 0 .../{prototypey => prototypekit}/src/infer.ts | 0 .../{prototypey => prototypekit}/src/lib.ts | 0 .../src/type-utils.ts | 0 .../tests/base-case.test.ts | 0 .../tests/bsky-actor.test.ts | 0 .../tests/bsky-feed.test.ts | 0 .../tests/infer.bench.ts | 0 .../tests/infer.test.ts | 0 .../tests/primitives.test.ts | 0 .../tsconfig.json | 0 .../tsdown.config.ts | 0 .../vitest.config.ts | 0 pnpm-lock.yaml | 6 +++--- 26 files changed, 45 insertions(+), 45 deletions(-) rename packages/{prototypey => prototypekit}/package.json (85%) rename packages/{prototypey => prototypekit}/setup-vitest.ts (100%) rename packages/{prototypey => prototypekit}/src/index.ts (100%) rename packages/{prototypey => prototypekit}/src/infer.ts (100%) rename packages/{prototypey => prototypekit}/src/lib.ts (100%) rename packages/{prototypey => prototypekit}/src/type-utils.ts (100%) rename packages/{prototypey => prototypekit}/tests/base-case.test.ts (100%) rename packages/{prototypey => prototypekit}/tests/bsky-actor.test.ts (100%) rename packages/{prototypey => prototypekit}/tests/bsky-feed.test.ts (100%) rename packages/{prototypey => prototypekit}/tests/infer.bench.ts (100%) rename packages/{prototypey => prototypekit}/tests/infer.test.ts (100%) rename packages/{prototypey => prototypekit}/tests/primitives.test.ts (100%) rename packages/{prototypey => prototypekit}/tsconfig.json (100%) rename packages/{prototypey => prototypekit}/tsdown.config.ts (100%) rename packages/{prototypey => prototypekit}/vitest.config.ts (100%) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8ce63e1..26fed7d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -6,7 +6,7 @@ jobs: - uses: actions/checkout@v4 - uses: ./.github/actions/prepare - run: pnpm build - - run: node packages/prototypey/lib/index.js + - run: node packages/prototypekit/lib/index.js lint: name: Lint runs-on: ubuntu-latest @@ -44,7 +44,7 @@ jobs: steps: - uses: actions/checkout@v4 - uses: ./.github/actions/prepare - - run: pnpm -F prototypey test:bench + - run: pnpm -F prototypekit test:bench name: CI diff --git a/README.md b/README.md index ae82064..f946db3 100644 --- a/README.md +++ b/README.md @@ -73,8 +73,8 @@ const profileNamespace = lx.namespace("app.bsky.actor.profile", { ---

- 🤝 Code of Conduct: Kept - 📝 License: MIT + 🤝 Code of Conduct: Kept + 📝 License: MIT 💪 TypeScript: Strict

diff --git a/package.json b/package.json index 260a876..e7f6341 100644 --- a/package.json +++ b/package.json @@ -1,11 +1,11 @@ { - "name": "prototypey-monorepo", + "name": "prototypekit-monorepo", "version": "0.0.0", "private": true, "description": "Type-safe lexicon inference for ATProto schemas", "repository": { "type": "git", - "url": "git+https://github.com/tylersayshi/prototypey.git" + "url": "git+https://github.com/tylersayshi/prototypekit.git" }, "license": "MIT", "author": { diff --git a/packages/cli/README.md b/packages/cli/README.md index 4b4c31c..7fa65e1 100644 --- a/packages/cli/README.md +++ b/packages/cli/README.md @@ -1,17 +1,17 @@ -# @prototypey/cli +# @prototypekit/cli CLI tool for generating types from ATProto lexicon schemas. ## Installation ```bash -npm install -g @prototypey/cli +npm install -g @prototypekit/cli ``` Or use directly with npx: ```bash -npx @prototypey/cli +npx @prototypekit/cli ``` ## Commands @@ -23,7 +23,7 @@ Generate type-inferred TypeScript code from JSON lexicon schemas. **Usage:** ```bash -prototypey gen-inferred +prototypekit gen-inferred ``` **Arguments:** @@ -34,7 +34,7 @@ prototypey gen-inferred **Example:** ```bash -prototypey gen-inferred ./generated/inferred ./lexicons/**/*.json +prototypekit gen-inferred ./generated/inferred ./lexicons/**/*.json ``` **What it does:** @@ -51,7 +51,7 @@ Emit JSON lexicon schemas from authored TypeScript files. **Usage:** ```bash -prototypey gen-emit +prototypekit gen-emit ``` **Arguments:** @@ -62,7 +62,7 @@ prototypey gen-emit **Example:** ```bash -prototypey gen-emit ./lexicons ./src/lexicons/**/*.ts +prototypekit gen-emit ./lexicons ./src/lexicons/**/*.ts ``` **What it does:** @@ -76,7 +76,7 @@ prototypey gen-emit ./lexicons ./src/lexicons/**/*.ts The typical workflow combines both commands for bidirectional type safety: -1. **Author lexicons in TypeScript** using the `prototypey` library +1. **Author lexicons in TypeScript** using the `prototypekit` library 2. **Emit to JSON** with `gen-emit` for runtime validation and API contracts 3. **Generate inferred types** with `gen-inferred` for consuming code @@ -85,10 +85,10 @@ The typical workflow combines both commands for bidirectional type safety: # src/lexicons/app.bsky.actor.profile.ts # Emit JSON schemas -prototypey gen-emit ./schemas ./src/lexicons/**/*.ts +prototypekit gen-emit ./schemas ./src/lexicons/**/*.ts # Generate TypeScript types from schemas -prototypey gen-inferred ./generated ./schemas/**/*.json +prototypekit gen-inferred ./generated ./schemas/**/*.json ``` ## Requirements diff --git a/packages/cli/package.json b/packages/cli/package.json index 62b107a..de53923 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,10 +1,10 @@ { - "name": "@prototypey/cli", + "name": "@prototypekit/cli", "version": "0.0.0", "description": "CLI tool for generating types from ATProto lexicon schemas", "repository": { "type": "git", - "url": "git+https://github.com/tylersayshi/prototypey.git", + "url": "git+https://github.com/tylersayshi/prototypekit.git", "directory": "packages/cli" }, "license": "MIT", @@ -14,7 +14,7 @@ }, "type": "module", "bin": { - "prototypey": "./lib/index.js" + "prototypekit": "./lib/index.js" }, "files": [ "lib/", @@ -26,7 +26,7 @@ "tsc": "tsc" }, "dependencies": { - "prototypey": "workspace:*", + "prototypekit": "workspace:*", "sade": "^1.8.1", "tinyglobby": "^0.2.15" }, diff --git a/packages/cli/src/index.ts b/packages/cli/src/index.ts index 4cf303b..950b091 100644 --- a/packages/cli/src/index.ts +++ b/packages/cli/src/index.ts @@ -7,7 +7,7 @@ const pkg = JSON.parse( await readFile(new URL("../package.json", import.meta.url), "utf-8"), ) as { version: string }; -const prog = sade("prototypey"); +const prog = sade("prototypekit"); prog .version(pkg.version) diff --git a/packages/cli/src/templates/inferred.ts b/packages/cli/src/templates/inferred.ts index 23a4970..fa80d17 100644 --- a/packages/cli/src/templates/inferred.ts +++ b/packages/cli/src/templates/inferred.ts @@ -22,9 +22,9 @@ export function generateInferredCode( // Generate a clean type name from the NSID const typeName = generateTypeName(id); - return `// Generated by prototypey - DO NOT EDIT + return `// Generated by prototypekit - DO NOT EDIT // Source: ${id} -import type { Infer } from "prototypey"; +import type { Infer } from "prototypekit"; import schema from "${relativeSchemaPath}" with { type: "json" }; /** diff --git a/packages/cli/tests/commands/gen-emit.test.ts b/packages/cli/tests/commands/gen-emit.test.ts index 135628a..d4169a4 100644 --- a/packages/cli/tests/commands/gen-emit.test.ts +++ b/packages/cli/tests/commands/gen-emit.test.ts @@ -10,7 +10,7 @@ describe("genEmit", () => { beforeEach(async () => { // Create a temporary directory for test files - testDir = join(tmpdir(), `prototypey-test-${Date.now()}`); + testDir = join(tmpdir(), `prototypekit-test-${Date.now()}`); outDir = join(testDir, "output"); await mkdir(testDir, { recursive: true }); await mkdir(outDir, { recursive: true }); @@ -27,7 +27,7 @@ describe("genEmit", () => { await writeFile( lexiconFile, ` -import { lx } from "prototypey"; +import { lx } from "prototypekit"; export const profileNamespace = lx.namespace("app.bsky.actor.profile", { main: lx.record({ @@ -83,7 +83,7 @@ export const profileNamespace = lx.namespace("app.bsky.actor.profile", { await writeFile( lexiconFile, ` -import { lx } from "prototypey"; +import { lx } from "prototypekit"; export const profile = lx.namespace("app.bsky.actor.profile", { main: lx.record({ @@ -128,7 +128,7 @@ export const post = lx.namespace("app.bsky.feed.post", { await writeFile( join(lexicons, "profile.ts"), ` -import { lx } from "prototypey"; +import { lx } from "prototypekit"; export const schema = lx.namespace("app.bsky.actor.profile", { main: lx.record({ key: "self", record: lx.object({}) }), }); @@ -138,7 +138,7 @@ export const schema = lx.namespace("app.bsky.actor.profile", { await writeFile( join(lexicons, "post.ts"), ` -import { lx } from "prototypey"; +import { lx } from "prototypekit"; export const schema = lx.namespace("app.bsky.feed.post", { main: lx.record({ key: "tid", record: lx.object({}) }), }); @@ -167,7 +167,7 @@ export const schema = lx.namespace("app.bsky.feed.post", { await writeFile( lexiconFile, ` -import { lx } from "prototypey"; +import { lx } from "prototypekit"; export const searchPosts = lx.namespace("app.bsky.feed.searchPosts", { main: lx.query({ @@ -236,7 +236,7 @@ export const searchPosts = lx.namespace("app.bsky.feed.searchPosts", { await writeFile( lexiconFile, ` -import { lx } from "prototypey"; +import { lx } from "prototypekit"; export const createPost = lx.namespace("com.atproto.repo.createRecord", { main: lx.procedure({ @@ -307,7 +307,7 @@ export const createPost = lx.namespace("com.atproto.repo.createRecord", { await writeFile( lexiconFile, ` -import { lx } from "prototypey"; +import { lx } from "prototypekit"; export const subscribeRepos = lx.namespace("com.atproto.sync.subscribeRepos", { main: lx.subscription({ @@ -394,7 +394,7 @@ export const subscribeRepos = lx.namespace("com.atproto.sync.subscribeRepos", { await writeFile( lexiconFile, ` -import { lx } from "prototypey"; +import { lx } from "prototypekit"; export const feedDefs = lx.namespace("app.bsky.feed.defs", { postView: lx.object({ @@ -458,7 +458,7 @@ export const feedDefs = lx.namespace("app.bsky.feed.defs", { await writeFile( lexiconFile, ` -import { lx } from "prototypey"; +import { lx } from "prototypekit"; export const imagePost = lx.namespace("app.example.imagePost", { main: lx.record({ diff --git a/packages/cli/tests/commands/gen-inferred.test.ts b/packages/cli/tests/commands/gen-inferred.test.ts index 3af2790..5fc9649 100644 --- a/packages/cli/tests/commands/gen-inferred.test.ts +++ b/packages/cli/tests/commands/gen-inferred.test.ts @@ -11,7 +11,7 @@ describe("genInferred", () => { beforeEach(async () => { // Create a temporary directory for test files - testDir = join(tmpdir(), `prototypey-inferred-test-${Date.now()}`); + testDir = join(tmpdir(), `prototypekit-inferred-test-${Date.now()}`); outDir = join(testDir, "output"); schemasDir = join(testDir, "schemas"); await mkdir(testDir, { recursive: true }); @@ -68,9 +68,9 @@ describe("genInferred", () => { const content = await readFile(outputFile, "utf-8"); // Verify the generated code structure - expect(content).toContain("// Generated by prototypey - DO NOT EDIT"); + expect(content).toContain("// Generated by prototypekit - DO NOT EDIT"); expect(content).toContain("// Source: app.bsky.actor.profile"); - expect(content).toContain('import type { Infer } from "prototypey"'); + expect(content).toContain('import type { Infer } from "prototypekit"'); expect(content).toContain('with { type: "json" }'); expect(content).toContain("export type Profile = Infer"); expect(content).toContain("export const ProfileSchema = schema"); @@ -321,7 +321,7 @@ describe("genInferred", () => { const content = await readFile(outputFile, "utf-8"); // Check all required exports - expect(content).toContain('import type { Infer } from "prototypey"'); + expect(content).toContain('import type { Infer } from "prototypekit"'); expect(content).toContain("export type Complete = Infer"); expect(content).toContain("export const CompleteSchema = schema"); expect(content).toContain( @@ -335,7 +335,7 @@ describe("genInferred", () => { expect(content).toContain('v.$type === "app.test.complete"'); // Check comments - expect(content).toContain("// Generated by prototypey - DO NOT EDIT"); + expect(content).toContain("// Generated by prototypekit - DO NOT EDIT"); expect(content).toContain("// Source: app.test.complete"); expect(content).toContain( "* Type-inferred from lexicon schema: app.test.complete", diff --git a/packages/cli/tests/fixtures/simple-lexicon.ts b/packages/cli/tests/fixtures/simple-lexicon.ts index 0842706..6e1259e 100644 --- a/packages/cli/tests/fixtures/simple-lexicon.ts +++ b/packages/cli/tests/fixtures/simple-lexicon.ts @@ -1,4 +1,4 @@ -import { lx } from "prototypey"; +import { lx } from "prototypekit"; export const profileNamespace = lx.namespace("app.bsky.actor.profile", { main: lx.record({ diff --git a/packages/prototypey/package.json b/packages/prototypekit/package.json similarity index 85% rename from packages/prototypey/package.json rename to packages/prototypekit/package.json index 55d1a36..8ba0b5a 100644 --- a/packages/prototypey/package.json +++ b/packages/prototypekit/package.json @@ -1,11 +1,11 @@ { - "name": "prototypey", + "name": "prototypekit", "version": "0.0.0", "description": "Type-safe lexicon inference for ATProto schemas", "repository": { "type": "git", - "url": "git+https://github.com/tylersayshi/prototypey.git", - "directory": "packages/prototypey" + "url": "git+https://github.com/tylersayshi/prototypekit.git", + "directory": "packages/prototypekit" }, "license": "MIT", "author": { diff --git a/packages/prototypey/setup-vitest.ts b/packages/prototypekit/setup-vitest.ts similarity index 100% rename from packages/prototypey/setup-vitest.ts rename to packages/prototypekit/setup-vitest.ts diff --git a/packages/prototypey/src/index.ts b/packages/prototypekit/src/index.ts similarity index 100% rename from packages/prototypey/src/index.ts rename to packages/prototypekit/src/index.ts diff --git a/packages/prototypey/src/infer.ts b/packages/prototypekit/src/infer.ts similarity index 100% rename from packages/prototypey/src/infer.ts rename to packages/prototypekit/src/infer.ts diff --git a/packages/prototypey/src/lib.ts b/packages/prototypekit/src/lib.ts similarity index 100% rename from packages/prototypey/src/lib.ts rename to packages/prototypekit/src/lib.ts diff --git a/packages/prototypey/src/type-utils.ts b/packages/prototypekit/src/type-utils.ts similarity index 100% rename from packages/prototypey/src/type-utils.ts rename to packages/prototypekit/src/type-utils.ts diff --git a/packages/prototypey/tests/base-case.test.ts b/packages/prototypekit/tests/base-case.test.ts similarity index 100% rename from packages/prototypey/tests/base-case.test.ts rename to packages/prototypekit/tests/base-case.test.ts diff --git a/packages/prototypey/tests/bsky-actor.test.ts b/packages/prototypekit/tests/bsky-actor.test.ts similarity index 100% rename from packages/prototypey/tests/bsky-actor.test.ts rename to packages/prototypekit/tests/bsky-actor.test.ts diff --git a/packages/prototypey/tests/bsky-feed.test.ts b/packages/prototypekit/tests/bsky-feed.test.ts similarity index 100% rename from packages/prototypey/tests/bsky-feed.test.ts rename to packages/prototypekit/tests/bsky-feed.test.ts diff --git a/packages/prototypey/tests/infer.bench.ts b/packages/prototypekit/tests/infer.bench.ts similarity index 100% rename from packages/prototypey/tests/infer.bench.ts rename to packages/prototypekit/tests/infer.bench.ts diff --git a/packages/prototypey/tests/infer.test.ts b/packages/prototypekit/tests/infer.test.ts similarity index 100% rename from packages/prototypey/tests/infer.test.ts rename to packages/prototypekit/tests/infer.test.ts diff --git a/packages/prototypey/tests/primitives.test.ts b/packages/prototypekit/tests/primitives.test.ts similarity index 100% rename from packages/prototypey/tests/primitives.test.ts rename to packages/prototypekit/tests/primitives.test.ts diff --git a/packages/prototypey/tsconfig.json b/packages/prototypekit/tsconfig.json similarity index 100% rename from packages/prototypey/tsconfig.json rename to packages/prototypekit/tsconfig.json diff --git a/packages/prototypey/tsdown.config.ts b/packages/prototypekit/tsdown.config.ts similarity index 100% rename from packages/prototypey/tsdown.config.ts rename to packages/prototypekit/tsdown.config.ts diff --git a/packages/prototypey/vitest.config.ts b/packages/prototypekit/vitest.config.ts similarity index 100% rename from packages/prototypey/vitest.config.ts rename to packages/prototypekit/vitest.config.ts diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d89136b..589ffb0 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -23,9 +23,9 @@ importers: packages/cli: dependencies: - prototypey: + prototypekit: specifier: workspace:* - version: link:../prototypey + version: link:../prototypekit sade: specifier: ^1.8.1 version: 1.8.1 @@ -46,7 +46,7 @@ importers: specifier: ^3.2.4 version: 3.2.4(@types/node@24.0.4)(jiti@2.6.1) - packages/prototypey: + packages/prototypekit: devDependencies: '@ark/attest': specifier: ^0.49.0 From 814d692af2756e0f965f776aa584805fef9b135a Mon Sep 17 00:00:00 2001 From: Tyler <26290074+tylersayshi@users.noreply.github.com> Date: Sat, 18 Oct 2025 21:37:59 -0700 Subject: [PATCH 02/23] add interactive playground site with Monaco editor and real-time compilation --- package.json | 3 + packages/site/index.html | 12 + packages/site/package.json | 25 + packages/site/src/App.tsx | 11 + packages/site/src/components/Editor.tsx | 44 ++ packages/site/src/components/Header.tsx | 31 ++ packages/site/src/components/OutputPanel.tsx | 95 ++++ packages/site/src/components/Playground.tsx | 96 ++++ packages/site/src/index.css | 32 ++ packages/site/src/main.tsx | 10 + packages/site/tsconfig.json | 21 + packages/site/vite.config.ts | 6 + pnpm-lock.yaml | 491 ++++++++++++++++++- 13 files changed, 876 insertions(+), 1 deletion(-) create mode 100644 packages/site/index.html create mode 100644 packages/site/package.json create mode 100644 packages/site/src/App.tsx create mode 100644 packages/site/src/components/Editor.tsx create mode 100644 packages/site/src/components/Header.tsx create mode 100644 packages/site/src/components/OutputPanel.tsx create mode 100644 packages/site/src/components/Playground.tsx create mode 100644 packages/site/src/index.css create mode 100644 packages/site/src/main.tsx create mode 100644 packages/site/tsconfig.json create mode 100644 packages/site/vite.config.ts diff --git a/package.json b/package.json index e7f6341..41745b8 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,9 @@ "scripts": { "build": "pnpm -r build", "codegen:samples": "node packages/cli/src/index.ts gen-inferred ./generated/inferred './samples/*.json'", + "dev:site": "pnpm -F @prototypekit/site dev", + "build:site": "pnpm -F @prototypekit/site build", + "preview:site": "pnpm -F @prototypekit/site preview", "format": "prettier . --list-different", "format:fix": "prettier . --write", "lint": "pnpm -r lint", diff --git a/packages/site/index.html b/packages/site/index.html new file mode 100644 index 0000000..0049fa7 --- /dev/null +++ b/packages/site/index.html @@ -0,0 +1,12 @@ + + + + + + prototypekit - Type-safe lexicon inference for ATProto + + +
+ + + diff --git a/packages/site/package.json b/packages/site/package.json new file mode 100644 index 0000000..f435495 --- /dev/null +++ b/packages/site/package.json @@ -0,0 +1,25 @@ +{ + "name": "@prototypekit/site", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "tsc && vite build", + "preview": "vite preview" + }, + "dependencies": { + "@monaco-editor/react": "^4.6.0", + "monaco-editor": "^0.52.2", + "prototypekit": "workspace:*", + "react": "^18.3.1", + "react-dom": "^18.3.1" + }, + "devDependencies": { + "@types/react": "^18.3.18", + "@types/react-dom": "^18.3.5", + "@vitejs/plugin-react": "^4.3.4", + "typescript": "5.8.3", + "vite": "^6.0.5" + } +} diff --git a/packages/site/src/App.tsx b/packages/site/src/App.tsx new file mode 100644 index 0000000..e21258a --- /dev/null +++ b/packages/site/src/App.tsx @@ -0,0 +1,11 @@ +import { Header } from "./components/Header"; +import { Playground } from "./components/Playground"; + +export function App() { + return ( + <> +
+ + + ); +} diff --git a/packages/site/src/components/Editor.tsx b/packages/site/src/components/Editor.tsx new file mode 100644 index 0000000..21d7d9e --- /dev/null +++ b/packages/site/src/components/Editor.tsx @@ -0,0 +1,44 @@ +import MonacoEditor from "@monaco-editor/react"; + +interface EditorProps { + value: string; + onChange: (value: string) => void; +} + +export function Editor({ value, onChange }: EditorProps) { + return ( +
+
+ Input +
+
+ onChange(value || "")} + theme="vs-light" + options={{ + minimap: { enabled: false }, + fontSize: 14, + lineNumbers: "on", + renderLineHighlight: "all", + scrollBeyondLastLine: false, + automaticLayout: true, + tabSize: 2, + padding: { top: 16, bottom: 16 }, + }} + /> +
+
+ ); +} diff --git a/packages/site/src/components/Header.tsx b/packages/site/src/components/Header.tsx new file mode 100644 index 0000000..643584b --- /dev/null +++ b/packages/site/src/components/Header.tsx @@ -0,0 +1,31 @@ +export function Header() { + return ( +
+
+

+ at://prototypekit +

+

+ Type-safe lexicon inference for ATProto schemas +

+
+
+ ); +} diff --git a/packages/site/src/components/OutputPanel.tsx b/packages/site/src/components/OutputPanel.tsx new file mode 100644 index 0000000..b944d40 --- /dev/null +++ b/packages/site/src/components/OutputPanel.tsx @@ -0,0 +1,95 @@ +import { useState } from "react"; +import MonacoEditor from "@monaco-editor/react"; + +interface OutputPanelProps { + output: { + json: string; + typeInfo: string; + error: string; + }; +} + +export function OutputPanel({ output }: OutputPanelProps) { + const [activeTab, setActiveTab] = useState<"json" | "types">("json"); + + return ( +
+
+ + +
+
+ {output.error ? ( +
+ Error: {output.error} +
+ ) : ( + + )} +
+
+ ); +} diff --git a/packages/site/src/components/Playground.tsx b/packages/site/src/components/Playground.tsx new file mode 100644 index 0000000..18c20d6 --- /dev/null +++ b/packages/site/src/components/Playground.tsx @@ -0,0 +1,96 @@ +import { useState, useEffect } from "react"; +import { Editor } from "./Editor"; +import { OutputPanel } from "./OutputPanel"; +import { lx } from "prototypekit"; + +export function Playground() { + const [code, setCode] = useState(DEFAULT_CODE); + const [output, setOutput] = useState({ json: "", typeInfo: "", error: "" }); + + const handleCodeChange = (newCode: string) => { + setCode(newCode); + }; + + useEffect(() => { + const timeoutId = setTimeout(() => { + try { + const AsyncFunction = async function () {}.constructor as new ( + ...args: string[] + ) => (...args: unknown[]) => Promise; + + const wrappedCode = ` + const { lx } = arguments[0]; + ${code} + const exports = {}; + for (const key in this) { + if (this.hasOwnProperty(key) && key !== 'lx') { + exports[key] = this[key]; + } + } + return Object.values(exports)[0]; + `; + + const fn = new AsyncFunction(wrappedCode); + const result = fn.call({}, { lx }); + + if (result && typeof result === "object" && "json" in result) { + const jsonOutput = (result as { json: unknown }).json; + setOutput({ + json: JSON.stringify(jsonOutput, null, 2), + typeInfo: "// Type inference not yet implemented in playground", + error: "", + }); + } else { + setOutput({ + json: JSON.stringify(result, null, 2), + typeInfo: "// Type inference not yet implemented in playground", + error: "", + }); + } + } catch (error) { + setOutput({ + json: "", + typeInfo: "", + error: error instanceof Error ? error.message : "Unknown error", + }); + } + }, 500); + + return () => clearTimeout(timeoutId); + }, [code]); + + return ( +
+
+ +
+
+ +
+
+ ); +} + +const DEFAULT_CODE = `import { lx } from "prototypekit"; + +const profileNamespace = lx.namespace("app.bsky.actor.profile", { + main: lx.record({ + key: "self", + record: lx.object({ + displayName: lx.string({ maxLength: 64, maxGraphemes: 64 }), + description: lx.string({ maxLength: 256, maxGraphemes: 256 }), + }), + }), +});`; diff --git a/packages/site/src/index.css b/packages/site/src/index.css new file mode 100644 index 0000000..cef07a7 --- /dev/null +++ b/packages/site/src/index.css @@ -0,0 +1,32 @@ +* { + box-sizing: border-box; + margin: 0; + padding: 0; +} + +:root { + font-family: + -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", + "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif; + line-height: 1.5; + font-weight: 400; + color: #213547; + background-color: #ffffff; + font-synthesis: none; + text-rendering: optimizeLegibility; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +body { + margin: 0; + display: flex; + min-width: 320px; + min-height: 100vh; +} + +#root { + width: 100%; + display: flex; + flex-direction: column; +} diff --git a/packages/site/src/main.tsx b/packages/site/src/main.tsx new file mode 100644 index 0000000..9192dbe --- /dev/null +++ b/packages/site/src/main.tsx @@ -0,0 +1,10 @@ +import { StrictMode } from "react"; +import { createRoot } from "react-dom/client"; +import "./index.css"; +import { App } from "./App.tsx"; + +createRoot(document.getElementById("root")!).render( + + + , +); diff --git a/packages/site/tsconfig.json b/packages/site/tsconfig.json new file mode 100644 index 0000000..7d578fa --- /dev/null +++ b/packages/site/tsconfig.json @@ -0,0 +1,21 @@ +{ + "compilerOptions": { + "target": "ES2020", + "useDefineForClassFields": true, + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "module": "ESNext", + "skipLibCheck": true, + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "isolatedModules": true, + "moduleDetection": "force", + "noEmit": true, + "jsx": "react-jsx", + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true, + "noUncheckedSideEffectImports": true + }, + "include": ["src"] +} diff --git a/packages/site/vite.config.ts b/packages/site/vite.config.ts new file mode 100644 index 0000000..f9f0d5e --- /dev/null +++ b/packages/site/vite.config.ts @@ -0,0 +1,6 @@ +import { defineConfig } from "vite"; +import react from "@vitejs/plugin-react"; + +export default defineConfig({ + plugins: [react()], +}); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 589ffb0..c88d4b1 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -64,6 +64,40 @@ importers: specifier: ^3.2.4 version: 3.2.4(@types/node@24.0.4)(jiti@2.6.1) + packages/site: + dependencies: + '@monaco-editor/react': + specifier: ^4.6.0 + version: 4.7.0(monaco-editor@0.52.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + monaco-editor: + specifier: ^0.52.2 + version: 0.52.2 + prototypekit: + specifier: workspace:* + version: link:../prototypekit + react: + specifier: ^18.3.1 + version: 18.3.1 + react-dom: + specifier: ^18.3.1 + version: 18.3.1(react@18.3.1) + devDependencies: + '@types/react': + specifier: ^18.3.18 + version: 18.3.26 + '@types/react-dom': + specifier: ^18.3.5 + version: 18.3.7(@types/react@18.3.26) + '@vitejs/plugin-react': + specifier: ^4.3.4 + version: 4.7.0(vite@6.4.0(@types/node@24.0.4)(jiti@2.6.1)) + typescript: + specifier: 5.8.3 + version: 5.8.3 + vite: + specifier: ^6.0.5 + version: 6.4.0(@types/node@24.0.4)(jiti@2.6.1) + packages: '@ark/attest@0.49.0': @@ -81,10 +115,44 @@ packages: '@ark/util@0.49.0': resolution: {integrity: sha512-/BtnX7oCjNkxi2vi6y1399b+9xd1jnCrDYhZ61f0a+3X8x8DxlK52VgEEzyuC2UQMPACIfYrmHkhD3lGt2GaMA==} + '@babel/code-frame@7.27.1': + resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==} + engines: {node: '>=6.9.0'} + + '@babel/compat-data@7.28.4': + resolution: {integrity: sha512-YsmSKC29MJwf0gF8Rjjrg5LQCmyh+j/nD8/eP7f+BeoQTKYqs9RoWbjGOdy0+1Ekr68RJZMUOPVQaQisnIo4Rw==} + engines: {node: '>=6.9.0'} + + '@babel/core@7.28.4': + resolution: {integrity: sha512-2BCOP7TN8M+gVDj7/ht3hsaO/B/n5oDbiAyyvnRlNOs+u1o+JWNYTQrmpuNp1/Wq2gcFrI01JAW+paEKDMx/CA==} + engines: {node: '>=6.9.0'} + '@babel/generator@7.28.3': resolution: {integrity: sha512-3lSpxGgvnmZznmBkCRnVREPUFJv2wrv9iAoFDvADJc0ypmdOxdUtcLeBgBJ6zE0PMeTKnxeQzyk0xTBq4Ep7zw==} engines: {node: '>=6.9.0'} + '@babel/helper-compilation-targets@7.27.2': + resolution: {integrity: sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==} + engines: {node: '>=6.9.0'} + + '@babel/helper-globals@7.28.0': + resolution: {integrity: sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-imports@7.27.1': + resolution: {integrity: sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-transforms@7.28.3': + resolution: {integrity: sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-plugin-utils@7.27.1': + resolution: {integrity: sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==} + engines: {node: '>=6.9.0'} + '@babel/helper-string-parser@7.27.1': resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==} engines: {node: '>=6.9.0'} @@ -93,11 +161,39 @@ packages: resolution: {integrity: sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==} engines: {node: '>=6.9.0'} + '@babel/helper-validator-option@7.27.1': + resolution: {integrity: sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==} + engines: {node: '>=6.9.0'} + + '@babel/helpers@7.28.4': + resolution: {integrity: sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w==} + engines: {node: '>=6.9.0'} + '@babel/parser@7.28.4': resolution: {integrity: sha512-yZbBqeM6TkpP9du/I2pUZnJsRMGGvOuIrhjzC1AwHwW+6he4mni6Bp/m8ijn0iOuZuPI2BfkCoSRunpyjnrQKg==} engines: {node: '>=6.0.0'} hasBin: true + '@babel/plugin-transform-react-jsx-self@7.27.1': + resolution: {integrity: sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-react-jsx-source@7.27.1': + resolution: {integrity: sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/template@7.27.2': + resolution: {integrity: sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==} + engines: {node: '>=6.9.0'} + + '@babel/traverse@7.28.4': + resolution: {integrity: sha512-YEzuboP2qvQavAcjgQNVgsvHIDv6ZpwXvcvjmyySP2DIMuByS/6ioU5G9pYrWHM6T2YDfc7xga9iNzYOs12CFQ==} + engines: {node: '>=6.9.0'} + '@babel/types@7.28.4': resolution: {integrity: sha512-bkFqkLhh3pMBUQQkpVgWDWq/lqzc2678eUyDlTBhRqhCHFguYYGM0Efga7tYk4TogG/3x0EEl66/OQ+WGbWB/Q==} engines: {node: '>=6.9.0'} @@ -328,6 +424,9 @@ packages: '@jridgewell/gen-mapping@0.3.13': resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} + '@jridgewell/remapping@2.3.5': + resolution: {integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==} + '@jridgewell/resolve-uri@3.1.2': resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} engines: {node: '>=6.0.0'} @@ -338,6 +437,16 @@ packages: '@jridgewell/trace-mapping@0.3.31': resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} + '@monaco-editor/loader@1.6.1': + resolution: {integrity: sha512-w3tEnj9HYEC73wtjdpR089AqkUPskFRcdkxsiSFt3SoUc3OHpmu+leP94CXBm4mHfefmhsdfI0ZQu6qJ0wgtPg==} + + '@monaco-editor/react@4.7.0': + resolution: {integrity: sha512-cyzXQCtO47ydzxpQtCGSQGOC8Gk3ZUeBXFAxD+CWXYFo5OqZyZUonFl0DwUlTyAfRHntBfw2p3w4s9R6oe1eCA==} + peerDependencies: + monaco-editor: '>= 0.25.0 < 1' + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + '@napi-rs/wasm-runtime@0.2.12': resolution: {integrity: sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==} @@ -431,6 +540,9 @@ packages: '@rolldown/pluginutils@1.0.0-beta.11-commit.f051675': resolution: {integrity: sha512-TAqMYehvpauLKz7v4TZOTUQNjxa5bUQWw2+51/+Zk3ItclBxgoSWhnZ31sXjdoX6le6OXdK2vZfV3KoyW/O/GA==} + '@rolldown/pluginutils@1.0.0-beta.27': + resolution: {integrity: sha512-+d0F4MKMCbeVUJwG96uQ4SgAznZNSq93I3V+9NHA4OpvqG8mRCpGdKmK8l/dl02h2CCDHwW2FqilnTyDcAnqjA==} + '@rollup/rollup-android-arm-eabi@4.52.4': resolution: {integrity: sha512-BTm2qKNnWIQ5auf4deoetINJm2JzvihvGb9R6K/ETwKLql/Bb3Eg2H1FBp1gUb4YGbydMA3jcmQTR73q7J+GAA==} cpu: [arm] @@ -544,6 +656,18 @@ packages: '@tybys/wasm-util@0.10.1': resolution: {integrity: sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==} + '@types/babel__core@7.20.5': + resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} + + '@types/babel__generator@7.27.0': + resolution: {integrity: sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==} + + '@types/babel__template@7.4.4': + resolution: {integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==} + + '@types/babel__traverse@7.28.0': + resolution: {integrity: sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==} + '@types/chai@5.2.2': resolution: {integrity: sha512-8kB30R7Hwqf40JPiKhVzodJs2Qc1ZJ5zuT3uzw5Hq/dhNCl3G3l83jfpdI1e20BP348+fV7VIL/+FxaXkqBmWg==} @@ -559,6 +683,17 @@ packages: '@types/node@24.0.4': resolution: {integrity: sha512-ulyqAkrhnuNq9pB76DRBTkcS6YsmDALy6Ua63V8OhrOBgbcYt6IOdzpw5P1+dyRIyMerzLkeYWBeOXPpA9GMAA==} + '@types/prop-types@15.7.15': + resolution: {integrity: sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==} + + '@types/react-dom@18.3.7': + resolution: {integrity: sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==} + peerDependencies: + '@types/react': ^18.0.0 + + '@types/react@18.3.26': + resolution: {integrity: sha512-RFA/bURkcKzx/X9oumPG9Vp3D3JUgus/d0b67KB0t5S/raciymilkOa66olh78MUI92QLbEJevO7rvqU/kjwKA==} + '@typescript-eslint/eslint-plugin@8.35.0': resolution: {integrity: sha512-ijItUYaiWuce0N1SoSMrEd0b6b6lYkYt99pqCPfybd+HKVXtEvYhICfLdwp42MhiI5mp0oq7PKEL+g1cNiz/Eg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -627,6 +762,12 @@ packages: peerDependencies: typescript: '*' + '@vitejs/plugin-react@4.7.0': + resolution: {integrity: sha512-gUu9hwfWvvEDBBmgtAowQCojwZmJ5mcLn3aufeCsitijs3+f2NsrPtlAWIR6OPiqljl96GVCUbLe0HyqIpVaoA==} + engines: {node: ^14.18.0 || >=16.0.0} + peerDependencies: + vite: ^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 + '@vitest/expect@3.2.4': resolution: {integrity: sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig==} @@ -698,6 +839,10 @@ packages: balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + baseline-browser-mapping@2.8.18: + resolution: {integrity: sha512-UYmTpOBwgPScZpS4A+YbapwWuBwasxvO/2IOHArSsAhL/+ZdmATBXTex3t+l2hXwLVYK382ibr/nKoY9GKe86w==} + hasBin: true + birpc@2.6.1: resolution: {integrity: sha512-LPnFhlDpdSH6FJhJyn4M0kFO7vtQ5iPw24FnG0y21q09xC7e8+1LeR31S1MAIrDAHp4m7aas4bEkTDTvMAtebQ==} @@ -711,6 +856,11 @@ packages: resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} engines: {node: '>=8'} + browserslist@4.26.3: + resolution: {integrity: sha512-lAUU+02RFBuCKQPj/P6NgjlbCnLBMp4UtgTx7vNHd3XSIJF87s9a5rA3aH2yw3GS9DqZAUbOtZdCCiZeVRqt0w==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + cac@6.7.14: resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} engines: {node: '>=8'} @@ -719,6 +869,9 @@ packages: resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} engines: {node: '>=6'} + caniuse-lite@1.0.30001751: + resolution: {integrity: sha512-A0QJhug0Ly64Ii3eIqHu5X51ebln3k4yTUkY1j8drqpWHVreg/VLijN48cZ1bYPiqOQuqpkIKnzr/Ul8V+p6Cw==} + chai@5.3.3: resolution: {integrity: sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==} engines: {node: '>=18'} @@ -748,10 +901,16 @@ packages: concat-map@0.0.1: resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + convert-source-map@2.0.0: + resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + cross-spawn@7.0.6: resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} engines: {node: '>= 8'} + csstype@3.1.3: + resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} + debug@4.4.3: resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} engines: {node: '>=6.0'} @@ -784,6 +943,9 @@ packages: oxc-resolver: optional: true + electron-to-chromium@1.5.237: + resolution: {integrity: sha512-icUt1NvfhGLar5lSWH3tHNzablaA5js3HVHacQimfP8ViEBOQv+L7DKEuHdbTZ0SKCO1ogTJTIL1Gwk9S6Qvcg==} + emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} @@ -909,6 +1071,10 @@ packages: engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} os: [darwin] + gensync@1.0.0-beta.2: + resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} + engines: {node: '>=6.9.0'} + get-caller-file@2.0.5: resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} engines: {node: 6.* || 8.* || >= 10.*} @@ -980,6 +1146,9 @@ packages: resolution: {integrity: sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==} hasBin: true + js-tokens@4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + js-tokens@9.0.1: resolution: {integrity: sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==} @@ -1001,6 +1170,11 @@ packages: json-stable-stringify-without-jsonify@1.0.1: resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} + json5@2.2.3: + resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} + engines: {node: '>=6'} + hasBin: true + jsonparse@1.3.1: resolution: {integrity: sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==} engines: {'0': node >= 0.2.0} @@ -1024,9 +1198,16 @@ packages: lodash.merge@4.6.2: resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + loose-envify@1.4.0: + resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} + hasBin: true + loupe@3.2.1: resolution: {integrity: sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==} + lru-cache@5.1.1: + resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} + magic-string@0.30.19: resolution: {integrity: sha512-2N21sPY9Ws53PZvsEpVtNuSW+ScYbQdp4b9qUaL+9QkHUrGFKo56Lg9Emg5s9V/qrtNBmiR01sYhUOwu3H+VOw==} @@ -1048,6 +1229,9 @@ packages: resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} engines: {node: '>=16 || 14 >=14.17'} + monaco-editor@0.52.2: + resolution: {integrity: sha512-GEQWEZmfkOGLdd3XK8ryrfWz3AIP8YymVXiPHEdewrUq7mh0qrKrfHLNCXcbB6sTnMLnOZ3ztSiKcciFUkIJwQ==} + mri@1.2.0: resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==} engines: {node: '>=4'} @@ -1063,6 +1247,9 @@ packages: natural-compare@1.4.0: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + node-releases@2.0.25: + resolution: {integrity: sha512-4auku8B/vw5psvTiiN9j1dAOsXvMoGqJuKJcR+dTdqiXEK20mMTk1UEo3HS16LeGQsVG6+qKTPM9u/qQ2LqATA==} + optionator@0.9.4: resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} engines: {node: '>= 0.8.0'} @@ -1133,6 +1320,19 @@ packages: queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + react-dom@18.3.1: + resolution: {integrity: sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==} + peerDependencies: + react: ^18.3.1 + + react-refresh@0.17.0: + resolution: {integrity: sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==} + engines: {node: '>=0.10.0'} + + react@18.3.1: + resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==} + engines: {node: '>=0.10.0'} + readable-stream@3.6.2: resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} engines: {node: '>= 6'} @@ -1191,6 +1391,13 @@ packages: safe-buffer@5.2.1: resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + scheduler@0.23.2: + resolution: {integrity: sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==} + + semver@6.3.1: + resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} + hasBin: true + semver@7.7.3: resolution: {integrity: sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==} engines: {node: '>=10'} @@ -1217,6 +1424,9 @@ packages: stackback@0.0.2: resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} + state-local@1.0.7: + resolution: {integrity: sha512-HTEHMNieakEnoe33shBYcZ7NX83ACUjCu8c40iOGEZsngj9zRnkqS9j1pqQPXwobB0ZcVTk27REb7COQ0UR59w==} + std-env@3.9.0: resolution: {integrity: sha512-UGvjygr6F6tpH7o2qyqR6QYpwraIjKSdtzyBdyytFOHmPZY917kwdwLG0RbOjWOnKmnm3PeHjaoLLMie7kPLQw==} @@ -1331,6 +1541,12 @@ packages: undici-types@7.8.0: resolution: {integrity: sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw==} + update-browserslist-db@1.1.3: + resolution: {integrity: sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==} + hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' + uri-js@4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} @@ -1342,6 +1558,46 @@ packages: engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} hasBin: true + vite@6.4.0: + resolution: {integrity: sha512-oLnWs9Hak/LOlKjeSpOwD6JMks8BeICEdYMJBf6P4Lac/pO9tKiv/XhXnAM7nNfSkZahjlCZu9sS50zL8fSnsw==} + engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} + hasBin: true + peerDependencies: + '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0 + jiti: '>=1.21.0' + less: '*' + lightningcss: ^1.21.0 + sass: '*' + sass-embedded: '*' + stylus: '*' + sugarss: '*' + terser: ^5.16.0 + tsx: ^4.8.1 + yaml: ^2.4.2 + peerDependenciesMeta: + '@types/node': + optional: true + jiti: + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + tsx: + optional: true + yaml: + optional: true + vite@7.1.9: resolution: {integrity: sha512-4nVGliEpxmhCL8DslSAUdxlB6+SMrhB0a1v5ijlh1xB1nEPuy1mxaHxysVucLHuWryAxLWg6a5ei+U4TLn/rFg==} engines: {node: ^20.19.0 || >=22.12.0} @@ -1432,6 +1688,9 @@ packages: resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} engines: {node: '>=10'} + yallist@3.1.1: + resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} + yargs-parser@20.2.9: resolution: {integrity: sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==} engines: {node: '>=10'} @@ -1467,6 +1726,34 @@ snapshots: '@ark/util@0.49.0': {} + '@babel/code-frame@7.27.1': + dependencies: + '@babel/helper-validator-identifier': 7.27.1 + js-tokens: 4.0.0 + picocolors: 1.1.1 + + '@babel/compat-data@7.28.4': {} + + '@babel/core@7.28.4': + dependencies: + '@babel/code-frame': 7.27.1 + '@babel/generator': 7.28.3 + '@babel/helper-compilation-targets': 7.27.2 + '@babel/helper-module-transforms': 7.28.3(@babel/core@7.28.4) + '@babel/helpers': 7.28.4 + '@babel/parser': 7.28.4 + '@babel/template': 7.27.2 + '@babel/traverse': 7.28.4 + '@babel/types': 7.28.4 + '@jridgewell/remapping': 2.3.5 + convert-source-map: 2.0.0 + debug: 4.4.3 + gensync: 1.0.0-beta.2 + json5: 2.2.3 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + '@babel/generator@7.28.3': dependencies: '@babel/parser': 7.28.4 @@ -1475,14 +1762,77 @@ snapshots: '@jridgewell/trace-mapping': 0.3.31 jsesc: 3.1.0 + '@babel/helper-compilation-targets@7.27.2': + dependencies: + '@babel/compat-data': 7.28.4 + '@babel/helper-validator-option': 7.27.1 + browserslist: 4.26.3 + lru-cache: 5.1.1 + semver: 6.3.1 + + '@babel/helper-globals@7.28.0': {} + + '@babel/helper-module-imports@7.27.1': + dependencies: + '@babel/traverse': 7.28.4 + '@babel/types': 7.28.4 + transitivePeerDependencies: + - supports-color + + '@babel/helper-module-transforms@7.28.3(@babel/core@7.28.4)': + dependencies: + '@babel/core': 7.28.4 + '@babel/helper-module-imports': 7.27.1 + '@babel/helper-validator-identifier': 7.27.1 + '@babel/traverse': 7.28.4 + transitivePeerDependencies: + - supports-color + + '@babel/helper-plugin-utils@7.27.1': {} + '@babel/helper-string-parser@7.27.1': {} '@babel/helper-validator-identifier@7.27.1': {} + '@babel/helper-validator-option@7.27.1': {} + + '@babel/helpers@7.28.4': + dependencies: + '@babel/template': 7.27.2 + '@babel/types': 7.28.4 + '@babel/parser@7.28.4': dependencies: '@babel/types': 7.28.4 + '@babel/plugin-transform-react-jsx-self@7.27.1(@babel/core@7.28.4)': + dependencies: + '@babel/core': 7.28.4 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-react-jsx-source@7.27.1(@babel/core@7.28.4)': + dependencies: + '@babel/core': 7.28.4 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/template@7.27.2': + dependencies: + '@babel/code-frame': 7.27.1 + '@babel/parser': 7.28.4 + '@babel/types': 7.28.4 + + '@babel/traverse@7.28.4': + dependencies: + '@babel/code-frame': 7.27.1 + '@babel/generator': 7.28.3 + '@babel/helper-globals': 7.28.0 + '@babel/parser': 7.28.4 + '@babel/template': 7.27.2 + '@babel/types': 7.28.4 + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + '@babel/types@7.28.4': dependencies: '@babel/helper-string-parser': 7.27.1 @@ -1646,6 +1996,11 @@ snapshots: '@jridgewell/sourcemap-codec': 1.5.5 '@jridgewell/trace-mapping': 0.3.31 + '@jridgewell/remapping@2.3.5': + dependencies: + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 + '@jridgewell/resolve-uri@3.1.2': {} '@jridgewell/sourcemap-codec@1.5.5': {} @@ -1655,6 +2010,17 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.5 + '@monaco-editor/loader@1.6.1': + dependencies: + state-local: 1.0.7 + + '@monaco-editor/react@4.7.0(monaco-editor@0.52.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@monaco-editor/loader': 1.6.1 + monaco-editor: 0.52.2 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + '@napi-rs/wasm-runtime@0.2.12': dependencies: '@emnapi/core': 1.5.0 @@ -1727,6 +2093,8 @@ snapshots: '@rolldown/pluginutils@1.0.0-beta.11-commit.f051675': {} + '@rolldown/pluginutils@1.0.0-beta.27': {} + '@rollup/rollup-android-arm-eabi@4.52.4': optional: true @@ -1798,6 +2166,27 @@ snapshots: tslib: 2.8.1 optional: true + '@types/babel__core@7.20.5': + dependencies: + '@babel/parser': 7.28.4 + '@babel/types': 7.28.4 + '@types/babel__generator': 7.27.0 + '@types/babel__template': 7.4.4 + '@types/babel__traverse': 7.28.0 + + '@types/babel__generator@7.27.0': + dependencies: + '@babel/types': 7.28.4 + + '@types/babel__template@7.4.4': + dependencies: + '@babel/parser': 7.28.4 + '@babel/types': 7.28.4 + + '@types/babel__traverse@7.28.0': + dependencies: + '@babel/types': 7.28.4 + '@types/chai@5.2.2': dependencies: '@types/deep-eql': 4.0.2 @@ -1812,6 +2201,17 @@ snapshots: dependencies: undici-types: 7.8.0 + '@types/prop-types@15.7.15': {} + + '@types/react-dom@18.3.7(@types/react@18.3.26)': + dependencies: + '@types/react': 18.3.26 + + '@types/react@18.3.26': + dependencies: + '@types/prop-types': 15.7.15 + csstype: 3.1.3 + '@typescript-eslint/eslint-plugin@8.35.0(@typescript-eslint/parser@8.35.0(eslint@9.29.0(jiti@2.6.1))(typescript@5.8.3))(eslint@9.29.0(jiti@2.6.1))(typescript@5.8.3)': dependencies: '@eslint-community/regexpp': 4.12.1 @@ -1922,6 +2322,18 @@ snapshots: transitivePeerDependencies: - supports-color + '@vitejs/plugin-react@4.7.0(vite@6.4.0(@types/node@24.0.4)(jiti@2.6.1))': + dependencies: + '@babel/core': 7.28.4 + '@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.28.4) + '@babel/plugin-transform-react-jsx-source': 7.27.1(@babel/core@7.28.4) + '@rolldown/pluginutils': 1.0.0-beta.27 + '@types/babel__core': 7.20.5 + react-refresh: 0.17.0 + vite: 6.4.0(@types/node@24.0.4)(jiti@2.6.1) + transitivePeerDependencies: + - supports-color + '@vitest/expect@3.2.4': dependencies: '@types/chai': 5.2.2 @@ -2001,6 +2413,8 @@ snapshots: balanced-match@1.0.2: {} + baseline-browser-mapping@2.8.18: {} + birpc@2.6.1: {} brace-expansion@1.1.12: @@ -2016,10 +2430,20 @@ snapshots: dependencies: fill-range: 7.1.1 + browserslist@4.26.3: + dependencies: + baseline-browser-mapping: 2.8.18 + caniuse-lite: 1.0.30001751 + electron-to-chromium: 1.5.237 + node-releases: 2.0.25 + update-browserslist-db: 1.1.3(browserslist@4.26.3) + cac@6.7.14: {} callsites@3.1.0: {} + caniuse-lite@1.0.30001751: {} + chai@5.3.3: dependencies: assertion-error: 2.0.1 @@ -2053,12 +2477,16 @@ snapshots: concat-map@0.0.1: {} + convert-source-map@2.0.0: {} + cross-spawn@7.0.6: dependencies: path-key: 3.1.1 shebang-command: 2.0.0 which: 2.0.2 + csstype@3.1.3: {} + debug@4.4.3: dependencies: ms: 2.1.3 @@ -2073,6 +2501,8 @@ snapshots: dts-resolver@2.1.2: {} + electron-to-chromium@1.5.237: {} + emoji-regex@8.0.0: {} empathic@1.1.0: {} @@ -2234,6 +2664,8 @@ snapshots: fsevents@2.3.3: optional: true + gensync@1.0.0-beta.2: {} + get-caller-file@2.0.5: {} get-tsconfig@4.12.0: @@ -2283,6 +2715,8 @@ snapshots: jiti@2.6.1: {} + js-tokens@4.0.0: {} + js-tokens@9.0.1: {} js-yaml@4.1.0: @@ -2297,6 +2731,8 @@ snapshots: json-stable-stringify-without-jsonify@1.0.1: {} + json5@2.2.3: {} + jsonparse@1.3.1: {} jsonstream-next@3.0.0: @@ -2319,8 +2755,16 @@ snapshots: lodash.merge@4.6.2: {} + loose-envify@1.4.0: + dependencies: + js-tokens: 4.0.0 + loupe@3.2.1: {} + lru-cache@5.1.1: + dependencies: + yallist: 3.1.1 + magic-string@0.30.19: dependencies: '@jridgewell/sourcemap-codec': 1.5.5 @@ -2342,6 +2786,8 @@ snapshots: dependencies: brace-expansion: 2.0.2 + monaco-editor@0.52.2: {} + mri@1.2.0: {} ms@2.1.3: {} @@ -2350,6 +2796,8 @@ snapshots: natural-compare@1.4.0: {} + node-releases@2.0.25: {} + optionator@0.9.4: dependencies: deep-is: 0.1.4 @@ -2403,6 +2851,18 @@ snapshots: queue-microtask@1.2.3: {} + react-dom@18.3.1(react@18.3.1): + dependencies: + loose-envify: 1.4.0 + react: 18.3.1 + scheduler: 0.23.2 + + react-refresh@0.17.0: {} + + react@18.3.1: + dependencies: + loose-envify: 1.4.0 + readable-stream@3.6.2: dependencies: inherits: 2.0.4 @@ -2494,6 +2954,12 @@ snapshots: safe-buffer@5.2.1: {} + scheduler@0.23.2: + dependencies: + loose-envify: 1.4.0 + + semver@6.3.1: {} + semver@7.7.3: {} shebang-command@2.0.0: @@ -2512,6 +2978,8 @@ snapshots: stackback@0.0.2: {} + state-local@1.0.7: {} + std-env@3.9.0: {} string-width@4.2.3: @@ -2620,6 +3088,12 @@ snapshots: undici-types@7.8.0: {} + update-browserslist-db@1.1.3(browserslist@4.26.3): + dependencies: + browserslist: 4.26.3 + escalade: 3.2.0 + picocolors: 1.1.1 + uri-js@4.4.1: dependencies: punycode: 2.3.1 @@ -2632,7 +3106,7 @@ snapshots: debug: 4.4.3 es-module-lexer: 1.7.0 pathe: 2.0.3 - vite: 7.1.9(@types/node@24.0.4)(jiti@2.6.1) + vite: 6.4.0(@types/node@24.0.4)(jiti@2.6.1) transitivePeerDependencies: - '@types/node' - jiti @@ -2647,6 +3121,19 @@ snapshots: - tsx - yaml + vite@6.4.0(@types/node@24.0.4)(jiti@2.6.1): + dependencies: + esbuild: 0.25.10 + fdir: 6.5.0(picomatch@4.0.3) + picomatch: 4.0.3 + postcss: 8.5.6 + rollup: 4.52.4 + tinyglobby: 0.2.15 + optionalDependencies: + '@types/node': 24.0.4 + fsevents: 2.3.3 + jiti: 2.6.1 + vite@7.1.9(@types/node@24.0.4)(jiti@2.6.1): dependencies: esbuild: 0.25.10 @@ -2720,6 +3207,8 @@ snapshots: y18n@5.0.8: {} + yallist@3.1.1: {} + yargs-parser@20.2.9: {} yargs@16.2.0: From a0ae289c78ae0d2d1c0b9049895c736962a6b921 Mon Sep 17 00:00:00 2001 From: Tyler <26290074+tylersayshi@users.noreply.github.com> Date: Sat, 18 Oct 2025 21:47:57 -0700 Subject: [PATCH 03/23] add vitest testing setup to site package with component tests --- packages/site/package.json | 9 ++- .../site/tests/components/Editor.test.tsx | 40 ++++++++++++ .../site/tests/components/Header.test.tsx | 18 ++++++ .../tests/components/OutputPanel.test.tsx | 61 +++++++++++++++++++ .../site/tests/components/Playground.test.tsx | 49 +++++++++++++++ packages/site/vitest.config.ts | 11 ++++ 6 files changed, 186 insertions(+), 2 deletions(-) create mode 100644 packages/site/tests/components/Editor.test.tsx create mode 100644 packages/site/tests/components/Header.test.tsx create mode 100644 packages/site/tests/components/OutputPanel.test.tsx create mode 100644 packages/site/tests/components/Playground.test.tsx create mode 100644 packages/site/vitest.config.ts diff --git a/packages/site/package.json b/packages/site/package.json index f435495..a0a0984 100644 --- a/packages/site/package.json +++ b/packages/site/package.json @@ -6,7 +6,8 @@ "scripts": { "dev": "vite", "build": "tsc && vite build", - "preview": "vite preview" + "preview": "vite preview", + "test": "vitest" }, "dependencies": { "@monaco-editor/react": "^4.6.0", @@ -16,10 +17,14 @@ "react-dom": "^18.3.1" }, "devDependencies": { + "@testing-library/react": "^16.1.0", + "@testing-library/user-event": "^14.5.2", "@types/react": "^18.3.18", "@types/react-dom": "^18.3.5", "@vitejs/plugin-react": "^4.3.4", + "jsdom": "^25.0.1", "typescript": "5.8.3", - "vite": "^6.0.5" + "vite": "^6.0.5", + "vitest": "^3.2.4" } } diff --git a/packages/site/tests/components/Editor.test.tsx b/packages/site/tests/components/Editor.test.tsx new file mode 100644 index 0000000..e4744a3 --- /dev/null +++ b/packages/site/tests/components/Editor.test.tsx @@ -0,0 +1,40 @@ +import { describe, it, expect, vi } from "vitest"; +import { render, screen } from "@testing-library/react"; +import { userEvent } from "@testing-library/user-event"; +import { Editor } from "../../src/components/Editor"; + +vi.mock("@monaco-editor/react", () => ({ + default: ({ value, onChange }: any) => ( +