Initial zod usage

This commit is contained in:
Adria Navarro 2025-04-01 11:16:42 +02:00
parent 595ddbaea5
commit ad0b9f8b7a
2 changed files with 110 additions and 122 deletions

@ -1 +1 @@
Subproject commit 703247c76a6d008ce425318b9c038a1509c71df4 Subproject commit 0e940ad427ef13ff48bc0911b18743734c34ccce

View File

@ -3,13 +3,11 @@ import {
FieldType, FieldType,
GenerateTablesRequest, GenerateTablesRequest,
GenerateTablesResponse, GenerateTablesResponse,
RelationshipFieldMetadata,
SourceName, SourceName,
Table, TableSourceType,
UserCtx, UserCtx,
} from "@budibase/types" } from "@budibase/types"
import { getLLM } from "packages/pro/src/ai" import { getLLM } from "packages/pro/src/ai"
import * as tableController from "./public/tables"
import { context, utils } from "@budibase/backend-core" import { context, utils } from "@budibase/backend-core"
import sdk from "../../sdk" import sdk from "../../sdk"
import fs from "fs" import fs from "fs"
@ -44,51 +42,41 @@ export async function generateTables(
config: {}, config: {},
}) })
console.warn(response?.message)
if (!useCached) { if (!useCached) {
const dir = path.join(process.env.PWD!, `../../llm-output/${cacheKey}`) const dir = path.join(process.env.PWD!, `../../llm-output/${cacheKey}`)
if (!fs.existsSync(dir)) { if (!fs.existsSync(dir)) {
fs.mkdirSync(dir) fs.mkdirSync(dir)
} }
fs.writeFileSync(path.join(dir, "prompt.txt"), prompt) fs.writeFileSync(path.join(dir, "prompt.txt"), prompt)
fs.writeFileSync(path.join(dir, "latest.json"), response?.message || "") fs.writeFileSync(path.join(dir, "latest.json"), JSON.stringify(response))
fs.writeFileSync( fs.writeFileSync(
path.join(dir, `${Date.now()}.json`), path.join(dir, `${Date.now()}.json`),
response?.message || "" JSON.stringify(response)
) )
} }
const json = JSON.parse(response!.message || "") as {
tables: Table[]
data: Record<string, any[]>
}
const createdTables: GenerateTablesResponse["createdTables"] = [] const createdTables: GenerateTablesResponse["createdTables"] = []
for (const table of Object.values(json.tables)) { for (const table of response!.tables) {
const createTableCtx = { const { _id, ...structure } = table.structure
request: { const createdTable = await sdk.tables.create({
body: { ...structure,
...table, sourceId: dsId,
sourceId: dsId, schema: {},
schema: {}, primaryDisplay: undefined,
primaryDisplay: undefined, sourceType: TableSourceType.INTERNAL,
}, type: "table",
}, })
user: ctx.user,
throw: ctx.throw, createdTables.push({ id: createdTable._id!, name: createdTable.name })
} as any table.structure._id = createdTable._id!
await tableController.create(createTableCtx, async () => {})
const createdTable = createTableCtx.body
createdTables.push({ id: createdTable._id, name: createdTable.name })
table._id = createdTable._id
} }
for (const table of Object.values(json.tables)) { for (const table of Object.values(response!.tables)) {
for (const fieldKey of Object.keys(table.schema).filter( for (const field of table.structure.schema.filter(
f => table.schema[f].type === FieldType.LINK f => f.type === FieldType.LINK
)) { )) {
const field = table.schema[fieldKey] as RelationshipFieldMetadata // const field = table.schema[fieldKey] as RelationshipFieldMetadata
const linkedTable = createdTables.find(t => t.name === field.tableId) const linkedTable = createdTables.find(t => t.name === field.tableId)
if (!linkedTable) { if (!linkedTable) {
throw `Table ${field.tableId} not found in the json response.` throw `Table ${field.tableId} not found in the json response.`
@ -97,106 +85,106 @@ export async function generateTables(
} }
} }
for (const table of Object.values(json.tables)) { // for (const table of Object.values(json.tables)) {
const readTableCtx = { // const readTableCtx = {
params: { tableId: table._id }, // params: { tableId: table._id },
user: ctx.user, // user: ctx.user,
throw: ctx.throw, // throw: ctx.throw,
} as any // } as any
await tableController.read(readTableCtx, async () => {}) // await tableController.read(readTableCtx, async () => {})
const updateTableCtx = { // const updateTableCtx = {
request: { // request: {
body: { // body: {
...readTableCtx.body, // ...readTableCtx.body,
schema: { // schema: {
...readTableCtx.body.schema, // ...readTableCtx.body.schema,
...table.schema, // ...table.schema,
}, // },
primaryDisplay: table.primaryDisplay, // primaryDisplay: table.primaryDisplay,
}, // },
}, // },
params: { tableId: table._id }, // params: { tableId: table._id },
user: ctx.user, // user: ctx.user,
throw: ctx.throw, // throw: ctx.throw,
} as any // } as any
await tableController.update(updateTableCtx, async () => {}) // await tableController.update(updateTableCtx, async () => {})
} // }
if (addData) { // if (addData) {
const createdData: Record<string, Record<string, string>> = {} // const createdData: Record<string, Record<string, string>> = {}
const toUpdateLinks: { // const toUpdateLinks: {
tableId: string // tableId: string
rowId: string // rowId: string
data: Record<string, { rowId: string; tableId: string }> // data: Record<string, { rowId: string; tableId: string }>
}[] = [] // }[] = []
for (const table of Object.values(json.tables)) { // for (const table of Object.values(json.tables)) {
const dataToAdd = json.data?.[table.name] // const dataToAdd = json.data?.[table.name]
const linksOverride: Record<string, null> = {} // const linksOverride: Record<string, null> = {}
for (const fieldKey of Object.keys(table.schema).filter( // for (const fieldKey of Object.keys(table.schema).filter(
f => table.schema[f].type === FieldType.LINK // f => table.schema[f].type === FieldType.LINK
)) { // )) {
linksOverride[fieldKey] = null // linksOverride[fieldKey] = null
} // }
for (const entry of dataToAdd || []) { // for (const entry of dataToAdd || []) {
const createdRow = await sdk.rows.save( // const createdRow = await sdk.rows.save(
table._id!, // table._id!,
{ // {
...entry, // ...entry,
...linksOverride, // ...linksOverride,
_id: undefined, // _id: undefined,
}, // },
ctx.user._id // ctx.user._id
) // )
createdData[table._id!] ??= {} // createdData[table._id!] ??= {}
createdData[table._id!][entry._id] = createdRow.row._id! // createdData[table._id!][entry._id] = createdRow.row._id!
const overridenLinks = Object.keys(linksOverride).reduce< // const overridenLinks = Object.keys(linksOverride).reduce<
Record<string, { rowId: string; tableId: string }> // Record<string, { rowId: string; tableId: string }>
>((acc, l) => { // >((acc, l) => {
if (entry[l]) { // if (entry[l]) {
acc[l] = { // acc[l] = {
tableId: (table.schema[l] as RelationshipFieldMetadata).tableId, // tableId: (table.schema[l] as RelationshipFieldMetadata).tableId,
rowId: entry[l], // rowId: entry[l],
} // }
} // }
return acc // return acc
}, {}) // }, {})
if (Object.keys(overridenLinks)) { // if (Object.keys(overridenLinks)) {
toUpdateLinks.push({ // toUpdateLinks.push({
tableId: createdRow.table._id!, // tableId: createdRow.table._id!,
rowId: createdRow.row._id!, // rowId: createdRow.row._id!,
data: overridenLinks, // data: overridenLinks,
}) // })
} // }
} // }
} // }
for (const data of toUpdateLinks.filter(d => Object.keys(d.data).length)) { // for (const data of toUpdateLinks.filter(d => Object.keys(d.data).length)) {
const persistedRow = await sdk.rows.find(data.tableId, data.rowId) // const persistedRow = await sdk.rows.find(data.tableId, data.rowId)
const updatedLinks = Object.keys(data.data).reduce< // const updatedLinks = Object.keys(data.data).reduce<
Record<string, string> // Record<string, string>
>((acc, d) => { // >((acc, d) => {
acc[d] = createdData[data.data[d].tableId][data.data[d].rowId] // acc[d] = createdData[data.data[d].tableId][data.data[d].rowId]
return acc // return acc
}, {}) // }, {})
await sdk.rows.save( // await sdk.rows.save(
data.tableId, // data.tableId,
{ // {
...persistedRow, // ...persistedRow,
...updatedLinks, // ...updatedLinks,
}, // },
ctx.user._id // ctx.user._id
) // )
} // }
} // }
ctx.body = { ctx.body = {
createdTables, createdTables,