import { type AnyColumn, type AnySchema, IdColumn } from "../schema/create"; export interface ConvexConfig { type: "convex";} function mapColumnToValidator(column: AnyColumn, tableName: string): string { // Map FumaDB types to Convex validators let validator: string; if (column instanceof IdColumn) { // Convex id type: v.id("tableName") validator = `v.id("${tableName}")`; } else if ( typeof column.type === "string" && column.type.startsWith("varchar") ) { validator = "v.string()"; } else { switch (column.type) { case "uuid": case "string": validator = "v.string()"; break; case "integer": case "decimal": validator = "v.number()"; break; case "bigint": validator = "v.int64()"; break; case "bool": validator = "v.boolean()"; break; case "json": validator = "v.any()"; break; case "binary": validator = "v.bytes()"; break; case "date": case "timestamp": validator = "v.number()"; // Convex stores timestamps as numbers break; default: validator = "v.any()"; } } if (column.isNullable) { validator = `v.optional(${validator})`; } return validator;} export function generateSchema( schema: AnySchema, _config: ConvexConfig): string { // Header imports const lines: string[] = [ 'import { defineSchema, defineTable } from "convex/server";', 'import { v } from "convex/values";', "", ]; // Table definitions const tableDefs: string[] = []; const tableNames: string[] = []; for (const table of Object.values(schema.tables)) { tableNames.push(table.names.convex); const fields: string[] = []; for (const column of Object.values(table.columns)) { const validator = mapColumnToValidator(column, table.names.convex); fields.push(` ${column.names.convex}: ${validator},`); } tableDefs.push( `const ${table.names.convex}Table = defineTable({\n${fields.join("\n")}\n})` // indexes will be chained below ); } // Indexes let tableIdx = 0; for (const table of Object.values(schema.tables)) { let indexLines = ""; for (const column of Object.values(table.columns)) { if (column instanceof IdColumn) continue; indexLines += `\n .index("by_${column.names.convex}", ["${column.names.convex}"])`; } tableDefs[tableIdx] += `${indexLines};\n`; tableIdx++; } // Schema export lines.push(...tableDefs); lines.push(""); lines.push( `export default defineSchema({\n${tableNames .map((t) => ` ${t}: ${t}Table,`) .join("\n")}\n});` ); return lines.join("\n");}
import { type AnyColumn, type AnySchema, IdColumn } from "../schema/create";
export interface ConvexConfig {
type: "convex";
}
function mapColumnToValidator(column: AnyColumn, tableName: string): string {
// Map FumaDB types to Convex validators
let validator: string;
if (column instanceof IdColumn) {
// Convex id type: v.id("tableName")
validator = `v.id("${tableName}")`;
} else if (
typeof column.type === "string" &&
column.type.startsWith("varchar")
) {
validator = "v.string()";
} else {
switch (column.type) {
case "uuid":
case "string":
validator = "v.string()";
break;
case "integer":
case "decimal":
validator = "v.number()";
break;
case "bigint":
validator = "v.int64()";
break;
case "bool":
validator = "v.boolean()";
break;
case "json":
validator = "v.any()";
break;
case "binary":
validator = "v.bytes()";
break;
case "date":
case "timestamp":
validator = "v.number()"; // Convex stores timestamps as numbers
break;
default:
validator = "v.any()";
}
}
if (column.isNullable) {
validator = `v.optional(${validator})`;
}
return validator;
}
export function generateSchema(
schema: AnySchema,
_config: ConvexConfig
): string {
// Header imports
const lines: string[] = [
'import { defineSchema, defineTable } from "convex/server";',
'import { v } from "convex/values";',
"",
];
// Table definitions
const tableDefs: string[] = [];
const tableNames: string[] = [];
for (const table of Object.values(schema.tables)) {
tableNames.push(table.names.convex);
const fields: string[] = [];
for (const column of Object.values(table.columns)) {
const validator = mapColumnToValidator(column, table.names.convex);
fields.push(` ${column.names.convex}: ${validator},`);
}
tableDefs.push(
`const ${table.names.convex}Table = defineTable({\n${fields.join("\n")}\n})` // indexes will be chained below
);
}
// Indexes
let tableIdx = 0;
for (const table of Object.values(schema.tables)) {
let indexLines = "";
for (const column of Object.values(table.columns)) {
if (column instanceof IdColumn) continue;
indexLines += `\n .index("by_${column.names.convex}", ["${column.names.convex}"])`;
}
tableDefs[tableIdx] += `${indexLines};\n`;
tableIdx++;
}
// Schema export
lines.push(...tableDefs);
lines.push("");
lines.push(
`export default defineSchema({\n${tableNames
.map((t) => ` ${t}: ${t}Table,`)
.join("\n")}\n});`
);
return lines.join("\n");
}