Skip to content

Commit fed1b27

Browse files
eluce2claude
andcommitted
feat(typegen): enhance logging and update form handling in TableOptionsForm
- Added $schema to proofkit-typegen.config.jsonc for schema validation. - Improved logging in createApiApp to track received data, parsed config, and transformed data. - Updated handleSaveAll in App component to use form.getValues() for current form state, ensuring accurate data submission. - Refactored TableOptionsForm to utilize watch() for dynamic field updates, improving form state management. - Adjusted MetadataTablesEditor for better column sizing and pinning options. Co-Authored-By: Claude Opus 4.5 <[email protected]>
1 parent c2fba31 commit fed1b27

File tree

6 files changed

+194
-162
lines changed

6 files changed

+194
-162
lines changed

packages/typegen/proofkit-typegen.config.jsonc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
{
2+
"$schema": "https://proofkit.dev/typegen-config-schema.json",
23
"config": [
34
{
45
"type": "fmodata",

packages/typegen/src/server/app.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ export function createApiApp(context: ApiContext) {
113113
async (c) => {
114114
try {
115115
const data = c.req.valid("json");
116+
console.log("[Server POST /config] Received data:", JSON.stringify(data, null, 2));
116117

117118
// Transform validated data using runtime schema (applies transforms)
118119
const transformedData = {
@@ -124,9 +125,12 @@ export function createApiApp(context: ApiContext) {
124125
? config
125126
: { ...(config as Record<string, unknown>), type: "fmdapi" as const };
126127
// Parse with runtime schema to apply transforms
127-
return typegenConfigSingle.parse(configWithType);
128+
const parsed = typegenConfigSingle.parse(configWithType);
129+
console.log("[Server POST /config] After parse, config:", JSON.stringify(parsed, null, 2));
130+
return parsed;
128131
}),
129132
};
133+
console.log("[Server POST /config] Transformed data:", JSON.stringify(transformedData, null, 2));
130134

131135
// Validate with Zod (data is already { config: [...], postGenerateCommand?: string })
132136
const validation = typegenConfig.safeParse(transformedData);
@@ -162,12 +166,14 @@ export function createApiApp(context: ApiContext) {
162166
const fullPath = path.resolve(context.cwd, context.configPath);
163167
// Add $schema at the top of the config
164168
const configData = validation.data as Record<string, unknown>;
169+
console.log("[Server POST /config] Validation data to write:", JSON.stringify(configData, null, 2));
165170
const { $schema: _, ...rest } = configData;
166171
const configWithSchema = {
167172
$schema: "https://proofkit.dev/typegen-config-schema.json",
168173
...rest,
169174
};
170175
const jsonContent = `${JSON.stringify(configWithSchema, null, 2)}\n`;
176+
console.log("[Server POST /config] Final JSON content:\n", jsonContent);
171177

172178
await fs.ensureDir(path.dirname(fullPath));
173179
await fs.writeFile(fullPath, jsonContent, "utf8");

packages/typegen/web/src/App.tsx

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -153,14 +153,29 @@ function App() {
153153
},
154154
});
155155

156-
const handleSaveAll = form.handleSubmit(async (data) => {
156+
const handleSaveAll = form.handleSubmit(async (_data) => {
157+
// IMPORTANT: Use form.getValues() instead of the `data` parameter passed to handleSubmit.
158+
// react-hook-form's handleSubmit callback receives stale data for dynamically added nested
159+
// fields (like table-level options set via setValue in child components).
160+
// form.getValues() returns the current live form state with all updates.
161+
const currentConfigs = form.getValues("config");
162+
const currentPostGenerateCommand = form.getValues("postGenerateCommand");
163+
console.log(
164+
"[App.handleSaveAll] Form data being submitted:",
165+
JSON.stringify({ config: currentConfigs, postGenerateCommand: currentPostGenerateCommand }, null, 2),
166+
);
167+
console.log("[App.handleSaveAll] Form dirty fields:", form.formState.dirtyFields);
157168
try {
158-
await saveMutation.mutateAsync({ configsToSave: data.config, postGenerateCommand: data.postGenerateCommand });
169+
await saveMutation.mutateAsync({
170+
configsToSave: currentConfigs,
171+
postGenerateCommand: currentPostGenerateCommand,
172+
});
159173
// Reset the form with the current form state to clear dirty state
160-
// Use getValues() to get the current state, preserving any changes made during the save request
161174
// The accordion state is preserved because it's controlled and the component doesn't unmount
162-
const currentConfigs = form.getValues("config");
163-
const currentPostGenerateCommand = form.getValues("postGenerateCommand");
175+
console.log(
176+
"[App.handleSaveAll] After save, form values:",
177+
JSON.stringify({ config: currentConfigs, postGenerateCommand: currentPostGenerateCommand }, null, 2),
178+
);
164179
form.reset({ config: currentConfigs, postGenerateCommand: currentPostGenerateCommand });
165180
} catch (err) {
166181
// Error is handled by the mutation

packages/typegen/web/src/components/MetadataTablesEditor.tsx

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -472,7 +472,7 @@ export function MetadataTablesEditor({ configIndex }: MetadataTablesEditorProps)
472472
id: "actions",
473473
header: () => null,
474474
enableSorting: false,
475-
size: 150,
475+
size: 1,
476476
cell: (info) => {
477477
const row = info.row.original;
478478
return (
@@ -494,7 +494,9 @@ export function MetadataTablesEditor({ configIndex }: MetadataTablesEditorProps)
494494
);
495495
},
496496
meta: {
497-
skeleton: <Skeleton className="h-9 w-32" />,
497+
skeleton: <Skeleton className="h-8 w-[72px]" />,
498+
cellClassName: "!w-px",
499+
headerClassName: "!w-px",
498500
},
499501
},
500502
],
@@ -511,6 +513,9 @@ export function MetadataTablesEditor({ configIndex }: MetadataTablesEditorProps)
511513
globalFilterFn: "includesString",
512514
state: {
513515
globalFilter: searchFilter,
516+
columnPinning: {
517+
right: ["actions"],
518+
},
514519
},
515520
onGlobalFilterChange: setSearchFilter,
516521
});
@@ -647,6 +652,7 @@ export function MetadataTablesEditor({ configIndex }: MetadataTablesEditorProps)
647652
width: "auto",
648653
headerSticky: true,
649654
dense: true,
655+
columnsPinnable: true,
650656
}}
651657
>
652658
<DataGridContainer>

packages/typegen/web/src/components/metadata-fields-dialog/MetadataFieldsDialog.tsx

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
import { useReactTable } from "@tanstack/react-table";
2-
import { Search } from "lucide-react";
2+
import { Search, X } from "lucide-react";
33
import { useEffect, useMemo, useState } from "react";
44
import { useFormContext } from "react-hook-form";
55
import { useTableMetadata } from "../../hooks/useTableMetadata";
66
import type { SingleConfig } from "../../lib/config-utils";
7-
import { Dialog, DialogBody, DialogContent, DialogHeader, DialogTitle } from "../ui/dialog";
7+
import { Dialog, DialogBody, DialogClose, DialogContent, DialogHeader, DialogTitle } from "../ui/dialog";
88
import { Input, InputWrapper } from "../ui/input";
9+
import { Tooltip, TooltipContent, TooltipTrigger } from "../ui/tooltip";
910
import { FieldsDataGrid } from "./FieldsDataGrid";
1011
import { createFieldsColumns } from "./fieldsColumns";
1112
import { TableOptionsForm } from "./TableOptionsForm";
@@ -138,16 +139,26 @@ export function MetadataFieldsDialog({ open, onOpenChange, tableName, configInde
138139
return (
139140
<Dialog onOpenChange={onOpenChange} open={open}>
140141
<DialogContent
141-
className="!top-[5vh] !translate-y-0 flex max-h-[90vh] w-full max-w-6xl flex-col"
142+
className="top-[5vh]! flex max-h-[90vh] w-full max-w-6xl translate-y-0! flex-col"
143+
showCloseButton={false}
142144
variant="default"
143145
>
144-
<DialogHeader className="flex-shrink-0">
146+
<Tooltip>
147+
<TooltipTrigger asChild>
148+
<DialogClose className="absolute end-5 top-5 flex cursor-pointer items-center gap-1.5 rounded-sm opacity-60 outline-0 ring-offset-background transition-opacity hover:opacity-100 focus:outline-hidden disabled:pointer-events-none">
149+
<span className="text-muted-foreground text-xs">Close</span>
150+
<X className="size-4" />
151+
</DialogClose>
152+
</TooltipTrigger>
153+
<TooltipContent>Selections will persist when you close the dialog</TooltipContent>
154+
</Tooltip>
155+
<DialogHeader className="shrink-0">
145156
<DialogTitle>
146157
Including {selectedFieldsCount} of {fieldsData.length} fields for {tableName || "Table"}
147158
</DialogTitle>
148159
</DialogHeader>
149160
<DialogBody className="flex min-h-0 flex-1 flex-col overflow-x-auto overflow-y-auto">
150-
<div className="mb-2 flex-shrink-0 space-y-2">
161+
<div className="mb-2 shrink-0 space-y-2">
151162
<InputWrapper>
152163
<Search className="size-4" />
153164
<Input

0 commit comments

Comments
 (0)