Files
Chris Tate c1b1aaaddb custom schema system (#56)
* add rate limits

* fix lint

* better

generate prompt

update examples

* fixes

* fixes

* new api

* update docs

* fixes

* fixes

* generated prompt

* Add tests for catalog validation and prompt generation

- Test generateSystemPrompt with components, actions, custom rules
- Test new defineCatalog API from schema system
- Test catalog.prompt() method with custom rules
- Test catalog.validate() for valid and invalid specs
- Test catalog.zodSchema() for custom validation
- Test catalog.jsonSchema() for structured outputs
- Add tests for nested specs with children
- Add tests for rejecting invalid component types

* Fix lint: pass children as nested elements in renderer

Change from children={...} prop to nested children pattern
to satisfy react/no-children-prop rule.

* Fix lint errors in dashboard and web apps

- Disable react/prop-types in both eslint configs (TypeScript handles this)
- Allow styled-jsx 'jsx' property in dashboard
- Add DATABASE_URL to turbo env allowlist
- Remove unused drizzle-orm imports (and, sql)
- Suppress unused variable warnings where intentional

* Add server entry point for @json-render/remotion

The main package entry includes React components that require
client-side context (React.createContext). This causes build
failures when importing in server-side API routes.

Added `@json-render/remotion/server` entry point that exports
only schema and catalog definitions without React dependencies:
- schema, RemotionSchema, RemotionSpec
- standardComponentDefinitions, standardTransitionDefinitions
- standardEffectDefinitions
- Type exports for catalogs

Updated remotion example to import from /server in catalog.ts

* Make dashboard database connection lazy-initialized

The database connection threw an error at module load time if
DATABASE_URL was not set, causing builds to fail in CI where
the database is not available.

Changed to lazy initialization using a Proxy so the error only
occurs when the database is actually used at runtime, not at
build time.

* Fix previousSpec property name and lazy rate limiting

- Fix property name mismatch: playground now passes previousSpec
  instead of previousTree to match what useUIStream hook expects
- Make rate limiting lazy-initialized to avoid runtime errors when
  Redis env vars (KV_REST_API_URL, KV_REST_API_TOKEN) are not set
- Rate limiting gracefully becomes a no-op when Redis is unavailable
2026-02-05 03:59:56 -06:00

174 lines
4.3 KiB
TypeScript

"use client";
import { useEffect, useState } from "react";
import { codeToHtml } from "shiki";
const vercelDarkTheme = {
name: "vercel-dark",
type: "dark" as const,
colors: {
"editor.background": "transparent",
"editor.foreground": "#EDEDED",
},
settings: [
{
scope: ["comment", "punctuation.definition.comment"],
settings: { foreground: "#666666" },
},
{
scope: ["string", "string.quoted", "string.template"],
settings: { foreground: "#50E3C2" },
},
{
scope: [
"constant.numeric",
"constant.language.boolean",
"constant.language.null",
],
settings: { foreground: "#50E3C2" },
},
{
scope: ["keyword", "storage.type", "storage.modifier"],
settings: { foreground: "#FF0080" },
},
{
scope: ["keyword.operator", "keyword.control"],
settings: { foreground: "#FF0080" },
},
{
scope: ["entity.name.function", "support.function", "meta.function-call"],
settings: { foreground: "#7928CA" },
},
{
scope: ["variable", "variable.other", "variable.parameter"],
settings: { foreground: "#EDEDED" },
},
{
scope: ["entity.name.tag", "support.class.component", "entity.name.type"],
settings: { foreground: "#FF0080" },
},
{
scope: ["punctuation", "meta.brace", "meta.bracket"],
settings: { foreground: "#888888" },
},
{
scope: [
"support.type.property-name",
"entity.name.tag.json",
"meta.object-literal.key",
],
settings: { foreground: "#EDEDED" },
},
{
scope: ["entity.other.attribute-name"],
settings: { foreground: "#50E3C2" },
},
{
scope: ["support.type.primitive", "entity.name.type.primitive"],
settings: { foreground: "#50E3C2" },
},
],
};
const vercelLightTheme = {
name: "vercel-light",
type: "light" as const,
colors: {
"editor.background": "transparent",
"editor.foreground": "#171717",
},
settings: [
{
scope: ["comment", "punctuation.definition.comment"],
settings: { foreground: "#6b7280" },
},
{
scope: ["string", "string.quoted", "string.template"],
settings: { foreground: "#067a6e" },
},
{
scope: [
"constant.numeric",
"constant.language.boolean",
"constant.language.null",
],
settings: { foreground: "#067a6e" },
},
{
scope: ["keyword", "storage.type", "storage.modifier"],
settings: { foreground: "#d6409f" },
},
{
scope: ["keyword.operator", "keyword.control"],
settings: { foreground: "#d6409f" },
},
{
scope: ["entity.name.function", "support.function", "meta.function-call"],
settings: { foreground: "#6e56cf" },
},
{
scope: ["variable", "variable.other", "variable.parameter"],
settings: { foreground: "#171717" },
},
{
scope: ["entity.name.tag", "support.class.component", "entity.name.type"],
settings: { foreground: "#d6409f" },
},
{
scope: ["punctuation", "meta.brace", "meta.bracket"],
settings: { foreground: "#6b7280" },
},
{
scope: [
"support.type.property-name",
"entity.name.tag.json",
"meta.object-literal.key",
],
settings: { foreground: "#171717" },
},
{
scope: ["entity.other.attribute-name"],
settings: { foreground: "#067a6e" },
},
{
scope: ["support.type.primitive", "entity.name.type.primitive"],
settings: { foreground: "#067a6e" },
},
],
};
interface CodeHighlightProps {
code: string;
language?: string;
}
export function CodeHighlight({ code, language = "json" }: CodeHighlightProps) {
const [html, setHtml] = useState<string>("");
useEffect(() => {
codeToHtml(code, {
lang: language,
themes: {
light: vercelLightTheme,
dark: vercelDarkTheme,
},
defaultColor: false,
}).then(setHtml);
}, [code, language]);
if (!html) {
return (
<pre className="text-xs font-mono whitespace-pre-wrap break-all">
{code}
</pre>
);
}
return (
<div
className="text-xs [&_pre]:!bg-transparent [&_pre]:!p-0 [&_code]:!bg-transparent [&_.shiki]:!bg-transparent"
dangerouslySetInnerHTML={{ __html: html }}
/>
);
}