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

134 lines
3.9 KiB
TypeScript

import {
pgTable,
varchar,
text,
integer,
decimal,
timestamp,
pgEnum,
jsonb,
} from "drizzle-orm/pg-core";
// Enums
export const customerStatusEnum = pgEnum("customer_status", [
"active",
"inactive",
]);
export const invoiceStatusEnum = pgEnum("invoice_status", [
"draft",
"sent",
"paid",
"overdue",
]);
export const expenseStatusEnum = pgEnum("expense_status", [
"pending",
"approved",
"rejected",
]);
export const accountTypeEnum = pgEnum("account_type", [
"bank",
"credit_card",
"cash",
]);
export const transactionTypeEnum = pgEnum("transaction_type", [
"income",
"expense",
"transfer",
]);
// Tables
export const customers = pgTable("customers", {
id: varchar("id", { length: 50 }).primaryKey(),
name: varchar("name", { length: 255 }).notNull(),
email: varchar("email", { length: 255 }).notNull(),
phone: varchar("phone", { length: 50 }),
balance: decimal("balance", { precision: 12, scale: 2 })
.notNull()
.default("0"),
status: customerStatusEnum("status").notNull().default("active"),
createdAt: timestamp("created_at").notNull().defaultNow(),
});
export const invoices = pgTable("invoices", {
id: varchar("id", { length: 50 }).primaryKey(),
customerId: varchar("customer_id", { length: 50 })
.notNull()
.references(() => customers.id),
customerName: varchar("customer_name", { length: 255 }).notNull(),
amount: decimal("amount", { precision: 12, scale: 2 }).notNull(),
status: invoiceStatusEnum("status").notNull().default("draft"),
dueDate: timestamp("due_date").notNull(),
createdAt: timestamp("created_at").notNull().defaultNow(),
items: jsonb("items").$type<InvoiceItem[]>().notNull().default([]),
});
export const expenses = pgTable("expenses", {
id: varchar("id", { length: 50 }).primaryKey(),
vendor: varchar("vendor", { length: 255 }).notNull(),
category: varchar("category", { length: 100 }).notNull(),
amount: decimal("amount", { precision: 12, scale: 2 }).notNull(),
date: timestamp("date").notNull(),
status: expenseStatusEnum("status").notNull().default("pending"),
description: text("description"),
});
export const accounts = pgTable("accounts", {
id: varchar("id", { length: 50 }).primaryKey(),
name: varchar("name", { length: 255 }).notNull(),
type: accountTypeEnum("type").notNull(),
balance: decimal("balance", { precision: 12, scale: 2 }).notNull(),
lastSync: timestamp("last_sync").notNull().defaultNow(),
});
export const transactions = pgTable("transactions", {
id: varchar("id", { length: 50 }).primaryKey(),
accountId: varchar("account_id", { length: 50 })
.notNull()
.references(() => accounts.id),
type: transactionTypeEnum("type").notNull(),
amount: decimal("amount", { precision: 12, scale: 2 }).notNull(),
description: text("description").notNull(),
category: varchar("category", { length: 100 }).notNull(),
date: timestamp("date").notNull(),
});
export const widgets = pgTable("widgets", {
id: varchar("id", { length: 50 }).primaryKey(),
prompt: text("prompt").notNull(),
spec: jsonb("spec").$type<WidgetSpec>().notNull(),
order: integer("order").notNull().default(0),
createdAt: timestamp("created_at").notNull().defaultNow(),
updatedAt: timestamp("updated_at").notNull().defaultNow(),
});
// Types
export interface WidgetSpec {
root: string;
elements: Record<string, unknown>;
}
export interface InvoiceItem {
description: string;
quantity: number;
rate: number;
amount: number;
}
export type Customer = typeof customers.$inferSelect;
export type NewCustomer = typeof customers.$inferInsert;
export type Invoice = typeof invoices.$inferSelect;
export type NewInvoice = typeof invoices.$inferInsert;
export type Expense = typeof expenses.$inferSelect;
export type NewExpense = typeof expenses.$inferInsert;
export type Account = typeof accounts.$inferSelect;
export type Transaction = typeof transactions.$inferSelect;
export type Widget = typeof widgets.$inferSelect;
export type NewWidget = typeof widgets.$inferInsert;