@agent-native/core 0.44.3 → 0.45.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/connect.d.ts +2 -1
- package/dist/cli/connect.d.ts.map +1 -1
- package/dist/cli/connect.js +185 -5
- package/dist/cli/connect.js.map +1 -1
- package/dist/cli/index.js +27 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/plan-local.d.ts +43 -0
- package/dist/cli/plan-local.d.ts.map +1 -0
- package/dist/cli/plan-local.js +477 -0
- package/dist/cli/plan-local.js.map +1 -0
- package/dist/cli/pr-visual-recap-workflow.d.ts +1 -1
- package/dist/cli/pr-visual-recap-workflow.d.ts.map +1 -1
- package/dist/cli/pr-visual-recap-workflow.js +1 -1
- package/dist/cli/pr-visual-recap-workflow.js.map +1 -1
- package/dist/cli/recap.d.ts +164 -0
- package/dist/cli/recap.d.ts.map +1 -1
- package/dist/cli/recap.js +657 -10
- package/dist/cli/recap.js.map +1 -1
- package/dist/cli/skills.d.ts +6 -2
- package/dist/cli/skills.d.ts.map +1 -1
- package/dist/cli/skills.js +440 -37
- package/dist/cli/skills.js.map +1 -1
- package/dist/client/blocks/library/AnnotatedCodeBlock.d.ts.map +1 -1
- package/dist/client/blocks/library/AnnotatedCodeBlock.js +18 -4
- package/dist/client/blocks/library/AnnotatedCodeBlock.js.map +1 -1
- package/dist/client/blocks/library/ApiEndpointBlock.d.ts.map +1 -1
- package/dist/client/blocks/library/ApiEndpointBlock.js +11 -7
- package/dist/client/blocks/library/ApiEndpointBlock.js.map +1 -1
- package/dist/client/blocks/library/DiffBlock.d.ts.map +1 -1
- package/dist/client/blocks/library/DiffBlock.js +90 -7
- package/dist/client/blocks/library/DiffBlock.js.map +1 -1
- package/dist/client/blocks/library/HighlightedCode.d.ts +2 -1
- package/dist/client/blocks/library/HighlightedCode.d.ts.map +1 -1
- package/dist/client/blocks/library/HighlightedCode.js +2 -2
- package/dist/client/blocks/library/HighlightedCode.js.map +1 -1
- package/dist/client/blocks/library/JsonExplorerBlock.d.ts.map +1 -1
- package/dist/client/blocks/library/JsonExplorerBlock.js +57 -13
- package/dist/client/blocks/library/JsonExplorerBlock.js.map +1 -1
- package/dist/client/blocks/library/annotation-rail.d.ts +15 -5
- package/dist/client/blocks/library/annotation-rail.d.ts.map +1 -1
- package/dist/client/blocks/library/annotation-rail.js +35 -24
- package/dist/client/blocks/library/annotation-rail.js.map +1 -1
- package/dist/client/blocks/library/code-filename-label.d.ts +8 -0
- package/dist/client/blocks/library/code-filename-label.d.ts.map +1 -0
- package/dist/client/blocks/library/code-filename-label.js +15 -0
- package/dist/client/blocks/library/code-filename-label.js.map +1 -0
- package/dist/client/blocks/library/code.d.ts.map +1 -1
- package/dist/client/blocks/library/code.js +28 -6
- package/dist/client/blocks/library/code.js.map +1 -1
- package/dist/client/blocks/library/columns.d.ts.map +1 -1
- package/dist/client/blocks/library/columns.js +11 -1
- package/dist/client/blocks/library/columns.js.map +1 -1
- package/dist/client/blocks/library/diff.config.d.ts +1 -1
- package/dist/client/blocks/library/diff.config.js.map +1 -1
- package/dist/client/blocks/library/narrow-container.d.ts +13 -0
- package/dist/client/blocks/library/narrow-container.d.ts.map +1 -0
- package/dist/client/blocks/library/narrow-container.js +32 -0
- package/dist/client/blocks/library/narrow-container.js.map +1 -0
- package/dist/client/blocks/library/question-form.d.ts.map +1 -1
- package/dist/client/blocks/library/question-form.js +8 -9
- package/dist/client/blocks/library/question-form.js.map +1 -1
- package/dist/client/blocks/library/tabs.d.ts.map +1 -1
- package/dist/client/blocks/library/tabs.js +11 -5
- package/dist/client/blocks/library/tabs.js.map +1 -1
- package/dist/client/blocks/types.d.ts +2 -0
- package/dist/client/blocks/types.d.ts.map +1 -1
- package/dist/client/blocks/types.js.map +1 -1
- package/dist/client/composer/TiptapComposer.d.ts.map +1 -1
- package/dist/client/composer/TiptapComposer.js +4 -1
- package/dist/client/composer/TiptapComposer.js.map +1 -1
- package/dist/client/db-admin/TableEditor.d.ts.map +1 -1
- package/dist/client/db-admin/TableEditor.js +3 -1
- package/dist/client/db-admin/TableEditor.js.map +1 -1
- package/dist/db/client.d.ts +19 -0
- package/dist/db/client.d.ts.map +1 -1
- package/dist/db/client.js +43 -2
- package/dist/db/client.js.map +1 -1
- package/dist/db/migrations.d.ts.map +1 -1
- package/dist/db/migrations.js +9 -2
- package/dist/db/migrations.js.map +1 -1
- package/dist/deploy/build.d.ts.map +1 -1
- package/dist/deploy/build.js +8 -0
- package/dist/deploy/build.js.map +1 -1
- package/dist/extensions/html-shell.js +1 -1
- package/dist/extensions/html-shell.js.map +1 -1
- package/dist/jobs/scheduler.d.ts.map +1 -1
- package/dist/jobs/scheduler.js +5 -1
- package/dist/jobs/scheduler.js.map +1 -1
- package/dist/mcp/build-server.d.ts +1 -0
- package/dist/mcp/build-server.d.ts.map +1 -1
- package/dist/mcp/build-server.js +7 -3
- package/dist/mcp/build-server.js.map +1 -1
- package/dist/mcp/oauth-route.d.ts.map +1 -1
- package/dist/mcp/oauth-route.js +56 -19
- package/dist/mcp/oauth-route.js.map +1 -1
- package/dist/mcp/oauth-store.d.ts +1 -0
- package/dist/mcp/oauth-store.d.ts.map +1 -1
- package/dist/mcp/oauth-store.js +9 -0
- package/dist/mcp/oauth-store.js.map +1 -1
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +9 -4
- package/dist/mcp/server.js.map +1 -1
- package/dist/mcp-client/errors.js +3 -3
- package/dist/mcp-client/errors.js.map +1 -1
- package/dist/server/agent-chat-plugin.d.ts.map +1 -1
- package/dist/server/agent-chat-plugin.js +3 -1
- package/dist/server/agent-chat-plugin.js.map +1 -1
- package/dist/server/agent-teams.d.ts.map +1 -1
- package/dist/server/agent-teams.js +10 -2
- package/dist/server/agent-teams.js.map +1 -1
- package/dist/server/auth.d.ts.map +1 -1
- package/dist/server/auth.js +7 -3
- package/dist/server/auth.js.map +1 -1
- package/dist/server/recap-image-route.d.ts.map +1 -1
- package/dist/server/recap-image-route.js +3 -6
- package/dist/server/recap-image-route.js.map +1 -1
- package/dist/server/sentry.d.ts.map +1 -1
- package/dist/server/sentry.js +12 -5
- package/dist/server/sentry.js.map +1 -1
- package/dist/server/social-og-image.d.ts.map +1 -1
- package/dist/server/social-og-image.js +3 -1
- package/dist/server/social-og-image.js.map +1 -1
- package/dist/styles/blocks.css +36 -10
- package/dist/templates/workspace-core/.agents/skills/external-agents/SKILL.md +22 -6
- package/docs/content/plan-plugin.md +18 -1
- package/docs/content/pr-visual-recap.md +37 -10
- package/docs/content/template-plan.md +45 -1
- package/package.json +1 -1
- package/src/templates/workspace-core/.agents/skills/external-agents/SKILL.md +22 -6
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TableEditor.d.ts","sourceRoot":"","sources":["../../../src/client/db-admin/TableEditor.tsx"],"names":[],"mappings":"AA+BA,OAAO,KAAK,EACV,cAAc,EACd,aAAa,EAId,MAAM,yBAAyB,CAAC;AAEjC,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,cAAc,CAAC;IACxB,cAAc,CAAC,EAAE,aAAa,EAAE,CAAC;IACjC,eAAe,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,EAAE,KAAK,IAAI,CAAC;CACpE;AAKD,wBAAgB,WAAW,CAAC,EAC1B,KAAK,EACL,OAAO,EACP,cAAc,EACd,eAAe,GAChB,EAAE,gBAAgB,
|
|
1
|
+
{"version":3,"file":"TableEditor.d.ts","sourceRoot":"","sources":["../../../src/client/db-admin/TableEditor.tsx"],"names":[],"mappings":"AA+BA,OAAO,KAAK,EACV,cAAc,EACd,aAAa,EAId,MAAM,yBAAyB,CAAC;AAEjC,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,cAAc,CAAC;IACxB,cAAc,CAAC,EAAE,aAAa,EAAE,CAAC;IACjC,eAAe,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,EAAE,KAAK,IAAI,CAAC;CACpE;AAKD,wBAAgB,WAAW,CAAC,EAC1B,KAAK,EACL,OAAO,EACP,cAAc,EACd,eAAe,GAChB,EAAE,gBAAgB,2CAqelB"}
|
|
@@ -173,7 +173,9 @@ export function TableEditor({ table, dialect, initialFilters, onNavigateToRow, }
|
|
|
173
173
|
commitRef.current = handleCommit;
|
|
174
174
|
useEffect(() => {
|
|
175
175
|
const onKey = (e) => {
|
|
176
|
-
if ((e.metaKey || e.ctrlKey) &&
|
|
176
|
+
if ((e.metaKey || e.ctrlKey) &&
|
|
177
|
+
typeof e.key === "string" &&
|
|
178
|
+
e.key.toLowerCase() === "s") {
|
|
177
179
|
e.preventDefault();
|
|
178
180
|
if (changeset.isDirty)
|
|
179
181
|
void commitRef.current();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TableEditor.js","sourceRoot":"","sources":["../../../src/client/db-admin/TableEditor.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport {\n IconPlus,\n IconFilter,\n IconRefresh,\n IconTrash,\n IconAlertTriangle,\n IconCode,\n IconArrowBackUp,\n IconDeviceFloppy,\n IconChevronLeft,\n IconChevronRight,\n IconChevronsLeft,\n IconChevronsRight,\n IconLoader2,\n IconCheck,\n IconKeyOff,\n} from \"@tabler/icons-react\";\nimport { cn } from \"../utils.js\";\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from \"../components/ui/popover.js\";\nimport { useTableSchema, useTableRows, mutateTable } from \"./useDbAdmin.js\";\nimport { loadGridState, saveGridState } from \"./storage.js\";\nimport { useChangeset, pkStringFor } from \"./changeset.js\";\nimport { DataGrid, type GridRow, type ActiveCell } from \"./DataGrid.js\";\nimport { FilterBar } from \"./FilterBar.js\";\nimport { RowSidePanel, type RowSidePanelMode } from \"./RowSidePanel.js\";\nimport type {\n DbAdminDialect,\n DbAdminFilter,\n DbAdminForeignKey,\n DbAdminSort,\n DbAdminMutationResult,\n} from \"../../db-admin/types.js\";\n\nexport interface TableEditorProps {\n table: string;\n dialect: DbAdminDialect;\n initialFilters?: DbAdminFilter[];\n onNavigateToRow: (table: string, filters: DbAdminFilter[]) => void;\n}\n\nconst DEFAULT_PAGE_SIZE = 100;\nconst PAGE_SIZES = [25, 50, 100, 250, 500];\n\nexport function TableEditor({\n table,\n dialect,\n initialFilters,\n onNavigateToRow,\n}: TableEditorProps) {\n // ─── Persisted view state ──────────────────────────────────────────────\n const persisted = useMemo(() => loadGridState(table), [table]);\n\n const [page, setPage] = useState(1);\n const [pageSize, setPageSize] = useState(\n persisted.pageSize ?? DEFAULT_PAGE_SIZE,\n );\n const [sort, setSort] = useState<DbAdminSort[]>(persisted.sort ?? []);\n const [filters, setFilters] = useState<DbAdminFilter[]>(\n initialFilters ?? persisted.filters ?? [],\n );\n const [columnWidths, setColumnWidths] = useState<Record<string, number>>(\n persisted.columnWidths ?? {},\n );\n const [selectedPks, setSelectedPks] = useState<Set<string>>(new Set());\n const [active, setActive] = useState<ActiveCell | null>(null);\n\n // Reset transient state when switching tables.\n useEffect(() => {\n const p = loadGridState(table);\n setPage(1);\n setPageSize(p.pageSize ?? DEFAULT_PAGE_SIZE);\n setSort(p.sort ?? []);\n setFilters(initialFilters ?? p.filters ?? []);\n setColumnWidths(p.columnWidths ?? {});\n setSelectedPks(new Set());\n setActive(null);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [table]);\n\n // Persist view state.\n useEffect(() => {\n saveGridState(table, { columnWidths, sort, filters, pageSize });\n }, [table, columnWidths, sort, filters, pageSize]);\n\n // ─── Data ────────────────────────────────────────────────────────────────\n const schemaState = useTableSchema(table);\n const rowsReq = useMemo(\n () => ({ page, pageSize, sort, filters }),\n [page, pageSize, sort, filters],\n );\n const rowsState = useTableRows(table, rowsReq);\n\n const schema = schemaState.data;\n const changeset = useChangeset(schema);\n\n // ─── Toolbar UI state ──────────────────────────────────────────────────\n const [panel, setPanel] = useState<{\n mode: RowSidePanelMode;\n pk?: string;\n } | null>(null);\n const [confirmDelete, setConfirmDelete] = useState(false);\n const [previewSql, setPreviewSql] = useState<string[] | null>(null);\n const [committing, setCommitting] = useState(false);\n const [commitError, setCommitError] = useState<string | null>(null);\n const [toast, setToast] = useState<string | null>(null);\n\n const showToast = useCallback((msg: string) => {\n setToast(msg);\n window.setTimeout(() => setToast(null), 2500);\n }, []);\n\n // ─── Original rows map (pk → fetched row) ──────────────────────────────\n const originalRows = useMemo(() => {\n const map = new Map<string, Record<string, unknown>>();\n for (const row of rowsState.data?.rows ?? []) {\n map.set(pkStringFor(schema, row), row);\n }\n return map;\n }, [rowsState.data, schema]);\n\n // ─── Build grid rows with staged edits applied ──────────────────────────\n const gridRows = useMemo<GridRow[]>(() => {\n const out: GridRow[] = [];\n // New rows first (top of grid, like Supabase).\n for (const nr of changeset.newRows) {\n out.push({\n pk: `new:${nr._localId}`,\n localId: nr._localId,\n isNew: true,\n values: { ...nr.values },\n });\n }\n for (const row of rowsState.data?.rows ?? []) {\n const pk = pkStringFor(schema, row);\n const staged = changeset.edits.get(pk);\n out.push({\n pk,\n values: staged ? { ...row, ...staged } : row,\n isDeleted: changeset.deletedKeys.has(pk),\n });\n }\n return out;\n }, [\n rowsState.data,\n schema,\n changeset.newRows,\n changeset.edits,\n changeset.deletedKeys,\n ]);\n\n // ─── Cell commit routing (existing rows vs new rows) ────────────────────\n const onCellCommit = useCallback(\n (row: GridRow, col: string, value: unknown) => {\n if (row.isNew && row.localId) {\n changeset.setNewRowCell(row.localId, col, value);\n } else {\n changeset.setCell(row.pk, col, value);\n }\n },\n [changeset],\n );\n\n const isCellDirty = useCallback(\n (row: GridRow, col: string) => {\n if (row.isNew) return true;\n return changeset.isCellDirty(row.pk, col);\n },\n [changeset],\n );\n\n const onToggleDelete = useCallback(\n (row: GridRow) => {\n if (row.isNew && row.localId) {\n changeset.removeNewRow(row.localId);\n return;\n }\n changeset.deleteRows([row.pk]);\n },\n [changeset],\n );\n\n // ─── FK navigation ───────────────────────────────────────────────────────\n const onFkNavigate = useCallback(\n (fk: DbAdminForeignKey, value: unknown) => {\n onNavigateToRow(fk.refTable, [{ column: fk.refColumn, op: \"eq\", value }]);\n },\n [onNavigateToRow],\n );\n\n // ─── Commit / preview ──────────────────────────────────────────────────\n const runCommit = useCallback(\n async (dryRun: boolean) => {\n const mutation = changeset.buildMutation(originalRows, dryRun);\n if (!mutation.inserts && !mutation.updates && !mutation.deletes) {\n return null;\n }\n return mutateTable(table, mutation);\n },\n [changeset, originalRows, table],\n );\n\n const handlePreview = useCallback(async () => {\n setCommitError(null);\n try {\n const res = await runCommit(true);\n setPreviewSql(res ? res.sql : []);\n } catch (err) {\n setCommitError(err instanceof Error ? err.message : String(err));\n }\n }, [runCommit]);\n\n const handleCommit = useCallback(async () => {\n const hasDeletes = changeset.deletedKeys.size > 0;\n if (hasDeletes && !confirmDelete) {\n setConfirmDelete(true);\n return;\n }\n setCommitting(true);\n setCommitError(null);\n try {\n const res: DbAdminMutationResult | null = await runCommit(false);\n changeset.discardAll();\n setSelectedPks(new Set());\n setConfirmDelete(false);\n rowsState.refetch();\n schemaState.refetch();\n if (res) {\n const parts: string[] = [];\n if (res.inserted) parts.push(`${res.inserted} inserted`);\n if (res.updated) parts.push(`${res.updated} updated`);\n if (res.deleted) parts.push(`${res.deleted} deleted`);\n showToast(parts.length ? parts.join(\", \") : \"No changes\");\n }\n } catch (err) {\n setCommitError(err instanceof Error ? err.message : String(err));\n } finally {\n setCommitting(false);\n }\n }, [changeset, confirmDelete, runCommit, rowsState, schemaState, showToast]);\n\n // ─── Cmd/Ctrl+S to commit ──────────────────────────────────────────────\n const commitRef = useRef(handleCommit);\n commitRef.current = handleCommit;\n useEffect(() => {\n const onKey = (e: KeyboardEvent) => {\n if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === \"s\") {\n e.preventDefault();\n if (changeset.isDirty) void commitRef.current();\n }\n };\n window.addEventListener(\"keydown\", onKey);\n return () => window.removeEventListener(\"keydown\", onKey);\n }, [changeset.isDirty]);\n\n // ─── Bulk delete from selection ────────────────────────────────────────\n const onBulkDelete = useCallback(() => {\n const pks = [...selectedPks].filter((pk) => !pk.startsWith(\"new:\"));\n changeset.deleteRows(pks);\n setSelectedPks(new Set());\n }, [selectedPks, changeset]);\n\n // ─── Render ──────────────────────────────────────────────────────────────\n const total = rowsState.data?.total ?? schema?.rowCount ?? 0;\n const totalPages = Math.max(1, Math.ceil(total / pageSize));\n\n if (schemaState.error) {\n return (\n <div className=\"flex h-full items-center justify-center p-8 text-sm text-destructive\">\n <IconAlertTriangle className=\"mr-2 h-4 w-4\" />\n {schemaState.error.message}\n </div>\n );\n }\n\n if (!schema) {\n return (\n <div className=\"flex h-full items-center justify-center p-8 text-sm text-muted-foreground\">\n <IconLoader2 className=\"mr-2 h-4 w-4 animate-spin\" />\n Loading {table}…\n </div>\n );\n }\n\n const noPk = schema.primaryKey.length === 0;\n\n return (\n <div className=\"flex h-full min-h-0 flex-col\">\n {/* Toolbar */}\n <div className=\"flex flex-col gap-2 border-b border-border px-3 py-2\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <div className=\"flex items-baseline gap-2\">\n <span className=\"text-sm font-semibold text-foreground\">\n {table}\n </span>\n <span className=\"text-xs text-muted-foreground\">\n {total.toLocaleString()} rows\n </span>\n {schema.type === \"view\" && (\n <span className=\"rounded bg-muted px-1.5 py-0.5 text-[10px] text-muted-foreground\">\n view\n </span>\n )}\n </div>\n\n <div className=\"ml-auto flex items-center gap-1.5\">\n <ToolbarButton\n icon={<IconRefresh className=\"h-3.5 w-3.5\" />}\n label=\"Refresh\"\n onClick={() => {\n rowsState.refetch();\n schemaState.refetch();\n }}\n />\n {!noPk && schema.type === \"table\" && (\n <ToolbarButton\n icon={<IconPlus className=\"h-3.5 w-3.5\" />}\n label=\"Insert\"\n onClick={() => setPanel({ mode: \"insert\" })}\n primary\n />\n )}\n </div>\n </div>\n\n {/* Filters */}\n <div className=\"flex items-center gap-2\">\n <IconFilter className=\"h-3.5 w-3.5 shrink-0 text-muted-foreground\" />\n <FilterBar\n columns={schema.columns}\n filters={filters}\n onChange={(f) => {\n setFilters(f);\n setPage(1);\n }}\n />\n </div>\n\n {/* No-PK warning */}\n {noPk && schema.type === \"table\" && (\n <div className=\"flex items-center gap-1.5 rounded-md bg-amber-500/10 px-2 py-1 text-[11px] text-amber-600 dark:text-amber-400\">\n <IconKeyOff className=\"h-3.5 w-3.5\" />\n This table has no primary key — editing and row deletion are\n disabled.\n </div>\n )}\n\n {/* Selection / changeset bar */}\n {(selectedPks.size > 0 || changeset.isDirty) && (\n <div className=\"flex flex-wrap items-center gap-2\">\n {selectedPks.size > 0 && (\n <>\n <span className=\"text-xs text-muted-foreground\">\n {selectedPks.size} selected\n </span>\n {!noPk && (\n <button\n type=\"button\"\n onClick={onBulkDelete}\n className=\"inline-flex items-center gap-1 rounded-md border border-border px-2 py-1 text-xs text-destructive hover:bg-destructive/10\"\n >\n <IconTrash className=\"h-3.5 w-3.5\" />\n Delete selected\n </button>\n )}\n <span className=\"h-4 w-px bg-border\" />\n </>\n )}\n\n {changeset.isDirty && (\n <>\n <span className=\"inline-flex items-center gap-1 rounded-md bg-amber-500/15 px-2 py-1 text-xs font-medium text-amber-600 dark:text-amber-400\">\n {changeset.pendingCount} pending change\n {changeset.pendingCount === 1 ? \"\" : \"s\"}\n </span>\n <button\n type=\"button\"\n onClick={changeset.discardAll}\n className=\"inline-flex items-center gap-1 rounded-md border border-border px-2 py-1 text-xs text-muted-foreground hover:text-foreground\"\n >\n <IconArrowBackUp className=\"h-3.5 w-3.5\" />\n Discard\n </button>\n <PreviewSqlButton\n onPreview={handlePreview}\n sql={previewSql}\n onClear={() => setPreviewSql(null)}\n error={commitError}\n />\n <button\n type=\"button\"\n onClick={() => void handleCommit()}\n disabled={committing}\n className=\"inline-flex items-center gap-1 rounded-md bg-primary px-2.5 py-1 text-xs font-medium text-primary-foreground hover:bg-primary/90 disabled:opacity-60\"\n >\n {committing ? (\n <IconLoader2 className=\"h-3.5 w-3.5 animate-spin\" />\n ) : (\n <IconDeviceFloppy className=\"h-3.5 w-3.5\" />\n )}\n Commit\n </button>\n </>\n )}\n </div>\n )}\n\n {commitError && !previewSql && (\n <div className=\"flex items-center gap-1.5 rounded-md bg-destructive/10 px-2 py-1 text-[11px] text-destructive\">\n <IconAlertTriangle className=\"h-3.5 w-3.5\" />\n {commitError}\n </div>\n )}\n </div>\n\n {/* Grid */}\n <DataGrid\n schema={schema}\n rows={gridRows}\n isLoading={rowsState.isLoading}\n pageSize={pageSize}\n sort={sort}\n onSortChange={(s) => {\n setSort(s);\n setPage(1);\n }}\n selectedPks={selectedPks}\n onSelectionChange={setSelectedPks}\n columnWidths={columnWidths}\n onColumnWidthsChange={setColumnWidths}\n active={active}\n onActiveChange={setActive}\n editable={!noPk && schema.type === \"table\"}\n onCellCommit={onCellCommit}\n isCellDirty={isCellDirty}\n onToggleDelete={onToggleDelete}\n onNavigateToRow={onFkNavigate}\n />\n\n {/* Pagination footer */}\n <div className=\"flex items-center justify-between border-t border-border px-3 py-1.5 text-xs text-muted-foreground\">\n <div className=\"flex items-center gap-2\">\n <span>Rows per page</span>\n <select\n value={pageSize}\n onChange={(e) => {\n setPageSize(Number(e.target.value));\n setPage(1);\n }}\n className=\"h-6 rounded border border-border bg-background px-1 text-xs outline-none focus:ring-1 focus:ring-ring\"\n >\n {PAGE_SIZES.map((s) => (\n <option key={s} value={s}>\n {s}\n </option>\n ))}\n </select>\n </div>\n\n <div className=\"flex items-center gap-1\">\n <span className=\"mr-2\">\n Page {page} of {totalPages}\n </span>\n <PagerButton\n disabled={page <= 1}\n onClick={() => setPage(1)}\n icon={<IconChevronsLeft className=\"h-3.5 w-3.5\" />}\n />\n <PagerButton\n disabled={page <= 1}\n onClick={() => setPage((p) => Math.max(1, p - 1))}\n icon={<IconChevronLeft className=\"h-3.5 w-3.5\" />}\n />\n <PagerButton\n disabled={page >= totalPages}\n onClick={() => setPage((p) => Math.min(totalPages, p + 1))}\n icon={<IconChevronRight className=\"h-3.5 w-3.5\" />}\n />\n <PagerButton\n disabled={page >= totalPages}\n onClick={() => setPage(totalPages)}\n icon={<IconChevronsRight className=\"h-3.5 w-3.5\" />}\n />\n </div>\n </div>\n\n {/* Row side panel */}\n {panel && (\n <RowSidePanel\n schema={schema}\n mode={panel.mode}\n row={panel.pk ? originalRows.get(panel.pk) : undefined}\n staged={panel.pk ? changeset.edits.get(panel.pk) : undefined}\n onClose={() => setPanel(null)}\n onSave={(values) => {\n if (panel.mode === \"insert\") {\n changeset.addRow(values);\n } else if (panel.pk) {\n changeset.setCells(panel.pk, values);\n }\n }}\n />\n )}\n\n {/* Destructive commit confirmation */}\n {confirmDelete && (\n <ConfirmModal\n title=\"Commit deletions?\"\n body={`${changeset.deletedKeys.size} row${\n changeset.deletedKeys.size === 1 ? \"\" : \"s\"\n } will be permanently deleted along with any other pending changes. This cannot be undone.`}\n confirmLabel=\"Delete and commit\"\n destructive\n onCancel={() => setConfirmDelete(false)}\n onConfirm={() => void handleCommit()}\n />\n )}\n\n {/* Toast */}\n {toast &&\n typeof document !== \"undefined\" &&\n createPortal(\n <div className=\"fixed bottom-4 right-4 z-[500] flex items-center gap-2 rounded-md border border-border bg-card px-3 py-2 text-xs text-foreground shadow-lg\">\n <IconCheck className=\"h-4 w-4 text-emerald-500\" />\n {toast}\n </div>,\n document.body,\n )}\n </div>\n );\n}\n\n// ─── Small UI atoms ────────────────────────────────────────────────────────\n\nfunction ToolbarButton({\n icon,\n label,\n onClick,\n primary,\n}: {\n icon: React.ReactNode;\n label: string;\n onClick: () => void;\n primary?: boolean;\n}) {\n return (\n <button\n type=\"button\"\n onClick={onClick}\n className={cn(\n \"inline-flex items-center gap-1 rounded-md px-2 py-1 text-xs\",\n primary\n ? \"bg-primary text-primary-foreground hover:bg-primary/90\"\n : \"border border-border text-muted-foreground hover:text-foreground\",\n )}\n >\n {icon}\n {label}\n </button>\n );\n}\n\nfunction PagerButton({\n disabled,\n onClick,\n icon,\n}: {\n disabled: boolean;\n onClick: () => void;\n icon: React.ReactNode;\n}) {\n return (\n <button\n type=\"button\"\n disabled={disabled}\n onClick={onClick}\n className=\"rounded border border-border p-1 text-muted-foreground hover:text-foreground disabled:opacity-40\"\n >\n {icon}\n </button>\n );\n}\n\nfunction PreviewSqlButton({\n onPreview,\n sql,\n onClear,\n error,\n}: {\n onPreview: () => void;\n sql: string[] | null;\n onClear: () => void;\n error: string | null;\n}) {\n return (\n <Popover\n open={sql !== null}\n onOpenChange={(o) => {\n if (!o) onClear();\n }}\n >\n <PopoverTrigger asChild>\n <button\n type=\"button\"\n onClick={onPreview}\n className=\"inline-flex items-center gap-1 rounded-md border border-border px-2 py-1 text-xs text-muted-foreground hover:text-foreground\"\n >\n <IconCode className=\"h-3.5 w-3.5\" />\n Preview SQL\n </button>\n </PopoverTrigger>\n <PopoverContent align=\"end\" className=\"w-[34rem] p-0\">\n <div className=\"border-b border-border px-3 py-2 text-xs font-medium text-foreground\">\n Preview SQL\n </div>\n <div className=\"max-h-80 overflow-auto p-3\">\n {error ? (\n <div className=\"text-xs text-destructive\">{error}</div>\n ) : sql && sql.length > 0 ? (\n <pre className=\"whitespace-pre-wrap break-all font-mono text-[11px] leading-relaxed text-foreground\">\n {sql.join(\";\\n\")}\n </pre>\n ) : (\n <div className=\"text-xs text-muted-foreground\">\n No statements to run.\n </div>\n )}\n </div>\n </PopoverContent>\n </Popover>\n );\n}\n\nfunction ConfirmModal({\n title,\n body,\n confirmLabel,\n destructive,\n onCancel,\n onConfirm,\n}: {\n title: string;\n body: string;\n confirmLabel: string;\n destructive?: boolean;\n onCancel: () => void;\n onConfirm: () => void;\n}) {\n useEffect(() => {\n const onKey = (e: KeyboardEvent) => {\n if (e.key === \"Escape\") onCancel();\n };\n window.addEventListener(\"keydown\", onKey);\n return () => window.removeEventListener(\"keydown\", onKey);\n }, [onCancel]);\n\n if (typeof document === \"undefined\") return null;\n return createPortal(\n <div className=\"fixed inset-0 z-[450] flex items-center justify-center\">\n <div className=\"absolute inset-0 bg-black/40\" onClick={onCancel} />\n <div className=\"relative w-full max-w-sm rounded-lg border border-border bg-card p-4 shadow-xl\">\n <div className=\"mb-1 flex items-center gap-2\">\n {destructive && (\n <IconAlertTriangle className=\"h-4 w-4 text-destructive\" />\n )}\n <h2 className=\"text-sm font-semibold text-foreground\">{title}</h2>\n </div>\n <p className=\"mb-4 text-xs text-muted-foreground\">{body}</p>\n <div className=\"flex justify-end gap-2\">\n <button\n type=\"button\"\n onClick={onCancel}\n className=\"rounded-md px-3 py-1.5 text-xs text-muted-foreground hover:bg-muted hover:text-foreground\"\n >\n Cancel\n </button>\n <button\n type=\"button\"\n onClick={onConfirm}\n className={cn(\n \"rounded-md px-3 py-1.5 text-xs font-medium text-primary-foreground\",\n destructive\n ? \"bg-destructive hover:bg-destructive/90\"\n : \"bg-primary hover:bg-primary/90\",\n )}\n >\n {confirmLabel}\n </button>\n </div>\n </div>\n </div>,\n document.body,\n );\n}\n"]}
|
|
1
|
+
{"version":3,"file":"TableEditor.js","sourceRoot":"","sources":["../../../src/client/db-admin/TableEditor.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport {\n IconPlus,\n IconFilter,\n IconRefresh,\n IconTrash,\n IconAlertTriangle,\n IconCode,\n IconArrowBackUp,\n IconDeviceFloppy,\n IconChevronLeft,\n IconChevronRight,\n IconChevronsLeft,\n IconChevronsRight,\n IconLoader2,\n IconCheck,\n IconKeyOff,\n} from \"@tabler/icons-react\";\nimport { cn } from \"../utils.js\";\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from \"../components/ui/popover.js\";\nimport { useTableSchema, useTableRows, mutateTable } from \"./useDbAdmin.js\";\nimport { loadGridState, saveGridState } from \"./storage.js\";\nimport { useChangeset, pkStringFor } from \"./changeset.js\";\nimport { DataGrid, type GridRow, type ActiveCell } from \"./DataGrid.js\";\nimport { FilterBar } from \"./FilterBar.js\";\nimport { RowSidePanel, type RowSidePanelMode } from \"./RowSidePanel.js\";\nimport type {\n DbAdminDialect,\n DbAdminFilter,\n DbAdminForeignKey,\n DbAdminSort,\n DbAdminMutationResult,\n} from \"../../db-admin/types.js\";\n\nexport interface TableEditorProps {\n table: string;\n dialect: DbAdminDialect;\n initialFilters?: DbAdminFilter[];\n onNavigateToRow: (table: string, filters: DbAdminFilter[]) => void;\n}\n\nconst DEFAULT_PAGE_SIZE = 100;\nconst PAGE_SIZES = [25, 50, 100, 250, 500];\n\nexport function TableEditor({\n table,\n dialect,\n initialFilters,\n onNavigateToRow,\n}: TableEditorProps) {\n // ─── Persisted view state ──────────────────────────────────────────────\n const persisted = useMemo(() => loadGridState(table), [table]);\n\n const [page, setPage] = useState(1);\n const [pageSize, setPageSize] = useState(\n persisted.pageSize ?? DEFAULT_PAGE_SIZE,\n );\n const [sort, setSort] = useState<DbAdminSort[]>(persisted.sort ?? []);\n const [filters, setFilters] = useState<DbAdminFilter[]>(\n initialFilters ?? persisted.filters ?? [],\n );\n const [columnWidths, setColumnWidths] = useState<Record<string, number>>(\n persisted.columnWidths ?? {},\n );\n const [selectedPks, setSelectedPks] = useState<Set<string>>(new Set());\n const [active, setActive] = useState<ActiveCell | null>(null);\n\n // Reset transient state when switching tables.\n useEffect(() => {\n const p = loadGridState(table);\n setPage(1);\n setPageSize(p.pageSize ?? DEFAULT_PAGE_SIZE);\n setSort(p.sort ?? []);\n setFilters(initialFilters ?? p.filters ?? []);\n setColumnWidths(p.columnWidths ?? {});\n setSelectedPks(new Set());\n setActive(null);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [table]);\n\n // Persist view state.\n useEffect(() => {\n saveGridState(table, { columnWidths, sort, filters, pageSize });\n }, [table, columnWidths, sort, filters, pageSize]);\n\n // ─── Data ────────────────────────────────────────────────────────────────\n const schemaState = useTableSchema(table);\n const rowsReq = useMemo(\n () => ({ page, pageSize, sort, filters }),\n [page, pageSize, sort, filters],\n );\n const rowsState = useTableRows(table, rowsReq);\n\n const schema = schemaState.data;\n const changeset = useChangeset(schema);\n\n // ─── Toolbar UI state ──────────────────────────────────────────────────\n const [panel, setPanel] = useState<{\n mode: RowSidePanelMode;\n pk?: string;\n } | null>(null);\n const [confirmDelete, setConfirmDelete] = useState(false);\n const [previewSql, setPreviewSql] = useState<string[] | null>(null);\n const [committing, setCommitting] = useState(false);\n const [commitError, setCommitError] = useState<string | null>(null);\n const [toast, setToast] = useState<string | null>(null);\n\n const showToast = useCallback((msg: string) => {\n setToast(msg);\n window.setTimeout(() => setToast(null), 2500);\n }, []);\n\n // ─── Original rows map (pk → fetched row) ──────────────────────────────\n const originalRows = useMemo(() => {\n const map = new Map<string, Record<string, unknown>>();\n for (const row of rowsState.data?.rows ?? []) {\n map.set(pkStringFor(schema, row), row);\n }\n return map;\n }, [rowsState.data, schema]);\n\n // ─── Build grid rows with staged edits applied ──────────────────────────\n const gridRows = useMemo<GridRow[]>(() => {\n const out: GridRow[] = [];\n // New rows first (top of grid, like Supabase).\n for (const nr of changeset.newRows) {\n out.push({\n pk: `new:${nr._localId}`,\n localId: nr._localId,\n isNew: true,\n values: { ...nr.values },\n });\n }\n for (const row of rowsState.data?.rows ?? []) {\n const pk = pkStringFor(schema, row);\n const staged = changeset.edits.get(pk);\n out.push({\n pk,\n values: staged ? { ...row, ...staged } : row,\n isDeleted: changeset.deletedKeys.has(pk),\n });\n }\n return out;\n }, [\n rowsState.data,\n schema,\n changeset.newRows,\n changeset.edits,\n changeset.deletedKeys,\n ]);\n\n // ─── Cell commit routing (existing rows vs new rows) ────────────────────\n const onCellCommit = useCallback(\n (row: GridRow, col: string, value: unknown) => {\n if (row.isNew && row.localId) {\n changeset.setNewRowCell(row.localId, col, value);\n } else {\n changeset.setCell(row.pk, col, value);\n }\n },\n [changeset],\n );\n\n const isCellDirty = useCallback(\n (row: GridRow, col: string) => {\n if (row.isNew) return true;\n return changeset.isCellDirty(row.pk, col);\n },\n [changeset],\n );\n\n const onToggleDelete = useCallback(\n (row: GridRow) => {\n if (row.isNew && row.localId) {\n changeset.removeNewRow(row.localId);\n return;\n }\n changeset.deleteRows([row.pk]);\n },\n [changeset],\n );\n\n // ─── FK navigation ───────────────────────────────────────────────────────\n const onFkNavigate = useCallback(\n (fk: DbAdminForeignKey, value: unknown) => {\n onNavigateToRow(fk.refTable, [{ column: fk.refColumn, op: \"eq\", value }]);\n },\n [onNavigateToRow],\n );\n\n // ─── Commit / preview ──────────────────────────────────────────────────\n const runCommit = useCallback(\n async (dryRun: boolean) => {\n const mutation = changeset.buildMutation(originalRows, dryRun);\n if (!mutation.inserts && !mutation.updates && !mutation.deletes) {\n return null;\n }\n return mutateTable(table, mutation);\n },\n [changeset, originalRows, table],\n );\n\n const handlePreview = useCallback(async () => {\n setCommitError(null);\n try {\n const res = await runCommit(true);\n setPreviewSql(res ? res.sql : []);\n } catch (err) {\n setCommitError(err instanceof Error ? err.message : String(err));\n }\n }, [runCommit]);\n\n const handleCommit = useCallback(async () => {\n const hasDeletes = changeset.deletedKeys.size > 0;\n if (hasDeletes && !confirmDelete) {\n setConfirmDelete(true);\n return;\n }\n setCommitting(true);\n setCommitError(null);\n try {\n const res: DbAdminMutationResult | null = await runCommit(false);\n changeset.discardAll();\n setSelectedPks(new Set());\n setConfirmDelete(false);\n rowsState.refetch();\n schemaState.refetch();\n if (res) {\n const parts: string[] = [];\n if (res.inserted) parts.push(`${res.inserted} inserted`);\n if (res.updated) parts.push(`${res.updated} updated`);\n if (res.deleted) parts.push(`${res.deleted} deleted`);\n showToast(parts.length ? parts.join(\", \") : \"No changes\");\n }\n } catch (err) {\n setCommitError(err instanceof Error ? err.message : String(err));\n } finally {\n setCommitting(false);\n }\n }, [changeset, confirmDelete, runCommit, rowsState, schemaState, showToast]);\n\n // ─── Cmd/Ctrl+S to commit ──────────────────────────────────────────────\n const commitRef = useRef(handleCommit);\n commitRef.current = handleCommit;\n useEffect(() => {\n const onKey = (e: KeyboardEvent) => {\n if (\n (e.metaKey || e.ctrlKey) &&\n typeof e.key === \"string\" &&\n e.key.toLowerCase() === \"s\"\n ) {\n e.preventDefault();\n if (changeset.isDirty) void commitRef.current();\n }\n };\n window.addEventListener(\"keydown\", onKey);\n return () => window.removeEventListener(\"keydown\", onKey);\n }, [changeset.isDirty]);\n\n // ─── Bulk delete from selection ────────────────────────────────────────\n const onBulkDelete = useCallback(() => {\n const pks = [...selectedPks].filter((pk) => !pk.startsWith(\"new:\"));\n changeset.deleteRows(pks);\n setSelectedPks(new Set());\n }, [selectedPks, changeset]);\n\n // ─── Render ──────────────────────────────────────────────────────────────\n const total = rowsState.data?.total ?? schema?.rowCount ?? 0;\n const totalPages = Math.max(1, Math.ceil(total / pageSize));\n\n if (schemaState.error) {\n return (\n <div className=\"flex h-full items-center justify-center p-8 text-sm text-destructive\">\n <IconAlertTriangle className=\"mr-2 h-4 w-4\" />\n {schemaState.error.message}\n </div>\n );\n }\n\n if (!schema) {\n return (\n <div className=\"flex h-full items-center justify-center p-8 text-sm text-muted-foreground\">\n <IconLoader2 className=\"mr-2 h-4 w-4 animate-spin\" />\n Loading {table}…\n </div>\n );\n }\n\n const noPk = schema.primaryKey.length === 0;\n\n return (\n <div className=\"flex h-full min-h-0 flex-col\">\n {/* Toolbar */}\n <div className=\"flex flex-col gap-2 border-b border-border px-3 py-2\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <div className=\"flex items-baseline gap-2\">\n <span className=\"text-sm font-semibold text-foreground\">\n {table}\n </span>\n <span className=\"text-xs text-muted-foreground\">\n {total.toLocaleString()} rows\n </span>\n {schema.type === \"view\" && (\n <span className=\"rounded bg-muted px-1.5 py-0.5 text-[10px] text-muted-foreground\">\n view\n </span>\n )}\n </div>\n\n <div className=\"ml-auto flex items-center gap-1.5\">\n <ToolbarButton\n icon={<IconRefresh className=\"h-3.5 w-3.5\" />}\n label=\"Refresh\"\n onClick={() => {\n rowsState.refetch();\n schemaState.refetch();\n }}\n />\n {!noPk && schema.type === \"table\" && (\n <ToolbarButton\n icon={<IconPlus className=\"h-3.5 w-3.5\" />}\n label=\"Insert\"\n onClick={() => setPanel({ mode: \"insert\" })}\n primary\n />\n )}\n </div>\n </div>\n\n {/* Filters */}\n <div className=\"flex items-center gap-2\">\n <IconFilter className=\"h-3.5 w-3.5 shrink-0 text-muted-foreground\" />\n <FilterBar\n columns={schema.columns}\n filters={filters}\n onChange={(f) => {\n setFilters(f);\n setPage(1);\n }}\n />\n </div>\n\n {/* No-PK warning */}\n {noPk && schema.type === \"table\" && (\n <div className=\"flex items-center gap-1.5 rounded-md bg-amber-500/10 px-2 py-1 text-[11px] text-amber-600 dark:text-amber-400\">\n <IconKeyOff className=\"h-3.5 w-3.5\" />\n This table has no primary key — editing and row deletion are\n disabled.\n </div>\n )}\n\n {/* Selection / changeset bar */}\n {(selectedPks.size > 0 || changeset.isDirty) && (\n <div className=\"flex flex-wrap items-center gap-2\">\n {selectedPks.size > 0 && (\n <>\n <span className=\"text-xs text-muted-foreground\">\n {selectedPks.size} selected\n </span>\n {!noPk && (\n <button\n type=\"button\"\n onClick={onBulkDelete}\n className=\"inline-flex items-center gap-1 rounded-md border border-border px-2 py-1 text-xs text-destructive hover:bg-destructive/10\"\n >\n <IconTrash className=\"h-3.5 w-3.5\" />\n Delete selected\n </button>\n )}\n <span className=\"h-4 w-px bg-border\" />\n </>\n )}\n\n {changeset.isDirty && (\n <>\n <span className=\"inline-flex items-center gap-1 rounded-md bg-amber-500/15 px-2 py-1 text-xs font-medium text-amber-600 dark:text-amber-400\">\n {changeset.pendingCount} pending change\n {changeset.pendingCount === 1 ? \"\" : \"s\"}\n </span>\n <button\n type=\"button\"\n onClick={changeset.discardAll}\n className=\"inline-flex items-center gap-1 rounded-md border border-border px-2 py-1 text-xs text-muted-foreground hover:text-foreground\"\n >\n <IconArrowBackUp className=\"h-3.5 w-3.5\" />\n Discard\n </button>\n <PreviewSqlButton\n onPreview={handlePreview}\n sql={previewSql}\n onClear={() => setPreviewSql(null)}\n error={commitError}\n />\n <button\n type=\"button\"\n onClick={() => void handleCommit()}\n disabled={committing}\n className=\"inline-flex items-center gap-1 rounded-md bg-primary px-2.5 py-1 text-xs font-medium text-primary-foreground hover:bg-primary/90 disabled:opacity-60\"\n >\n {committing ? (\n <IconLoader2 className=\"h-3.5 w-3.5 animate-spin\" />\n ) : (\n <IconDeviceFloppy className=\"h-3.5 w-3.5\" />\n )}\n Commit\n </button>\n </>\n )}\n </div>\n )}\n\n {commitError && !previewSql && (\n <div className=\"flex items-center gap-1.5 rounded-md bg-destructive/10 px-2 py-1 text-[11px] text-destructive\">\n <IconAlertTriangle className=\"h-3.5 w-3.5\" />\n {commitError}\n </div>\n )}\n </div>\n\n {/* Grid */}\n <DataGrid\n schema={schema}\n rows={gridRows}\n isLoading={rowsState.isLoading}\n pageSize={pageSize}\n sort={sort}\n onSortChange={(s) => {\n setSort(s);\n setPage(1);\n }}\n selectedPks={selectedPks}\n onSelectionChange={setSelectedPks}\n columnWidths={columnWidths}\n onColumnWidthsChange={setColumnWidths}\n active={active}\n onActiveChange={setActive}\n editable={!noPk && schema.type === \"table\"}\n onCellCommit={onCellCommit}\n isCellDirty={isCellDirty}\n onToggleDelete={onToggleDelete}\n onNavigateToRow={onFkNavigate}\n />\n\n {/* Pagination footer */}\n <div className=\"flex items-center justify-between border-t border-border px-3 py-1.5 text-xs text-muted-foreground\">\n <div className=\"flex items-center gap-2\">\n <span>Rows per page</span>\n <select\n value={pageSize}\n onChange={(e) => {\n setPageSize(Number(e.target.value));\n setPage(1);\n }}\n className=\"h-6 rounded border border-border bg-background px-1 text-xs outline-none focus:ring-1 focus:ring-ring\"\n >\n {PAGE_SIZES.map((s) => (\n <option key={s} value={s}>\n {s}\n </option>\n ))}\n </select>\n </div>\n\n <div className=\"flex items-center gap-1\">\n <span className=\"mr-2\">\n Page {page} of {totalPages}\n </span>\n <PagerButton\n disabled={page <= 1}\n onClick={() => setPage(1)}\n icon={<IconChevronsLeft className=\"h-3.5 w-3.5\" />}\n />\n <PagerButton\n disabled={page <= 1}\n onClick={() => setPage((p) => Math.max(1, p - 1))}\n icon={<IconChevronLeft className=\"h-3.5 w-3.5\" />}\n />\n <PagerButton\n disabled={page >= totalPages}\n onClick={() => setPage((p) => Math.min(totalPages, p + 1))}\n icon={<IconChevronRight className=\"h-3.5 w-3.5\" />}\n />\n <PagerButton\n disabled={page >= totalPages}\n onClick={() => setPage(totalPages)}\n icon={<IconChevronsRight className=\"h-3.5 w-3.5\" />}\n />\n </div>\n </div>\n\n {/* Row side panel */}\n {panel && (\n <RowSidePanel\n schema={schema}\n mode={panel.mode}\n row={panel.pk ? originalRows.get(panel.pk) : undefined}\n staged={panel.pk ? changeset.edits.get(panel.pk) : undefined}\n onClose={() => setPanel(null)}\n onSave={(values) => {\n if (panel.mode === \"insert\") {\n changeset.addRow(values);\n } else if (panel.pk) {\n changeset.setCells(panel.pk, values);\n }\n }}\n />\n )}\n\n {/* Destructive commit confirmation */}\n {confirmDelete && (\n <ConfirmModal\n title=\"Commit deletions?\"\n body={`${changeset.deletedKeys.size} row${\n changeset.deletedKeys.size === 1 ? \"\" : \"s\"\n } will be permanently deleted along with any other pending changes. This cannot be undone.`}\n confirmLabel=\"Delete and commit\"\n destructive\n onCancel={() => setConfirmDelete(false)}\n onConfirm={() => void handleCommit()}\n />\n )}\n\n {/* Toast */}\n {toast &&\n typeof document !== \"undefined\" &&\n createPortal(\n <div className=\"fixed bottom-4 right-4 z-[500] flex items-center gap-2 rounded-md border border-border bg-card px-3 py-2 text-xs text-foreground shadow-lg\">\n <IconCheck className=\"h-4 w-4 text-emerald-500\" />\n {toast}\n </div>,\n document.body,\n )}\n </div>\n );\n}\n\n// ─── Small UI atoms ────────────────────────────────────────────────────────\n\nfunction ToolbarButton({\n icon,\n label,\n onClick,\n primary,\n}: {\n icon: React.ReactNode;\n label: string;\n onClick: () => void;\n primary?: boolean;\n}) {\n return (\n <button\n type=\"button\"\n onClick={onClick}\n className={cn(\n \"inline-flex items-center gap-1 rounded-md px-2 py-1 text-xs\",\n primary\n ? \"bg-primary text-primary-foreground hover:bg-primary/90\"\n : \"border border-border text-muted-foreground hover:text-foreground\",\n )}\n >\n {icon}\n {label}\n </button>\n );\n}\n\nfunction PagerButton({\n disabled,\n onClick,\n icon,\n}: {\n disabled: boolean;\n onClick: () => void;\n icon: React.ReactNode;\n}) {\n return (\n <button\n type=\"button\"\n disabled={disabled}\n onClick={onClick}\n className=\"rounded border border-border p-1 text-muted-foreground hover:text-foreground disabled:opacity-40\"\n >\n {icon}\n </button>\n );\n}\n\nfunction PreviewSqlButton({\n onPreview,\n sql,\n onClear,\n error,\n}: {\n onPreview: () => void;\n sql: string[] | null;\n onClear: () => void;\n error: string | null;\n}) {\n return (\n <Popover\n open={sql !== null}\n onOpenChange={(o) => {\n if (!o) onClear();\n }}\n >\n <PopoverTrigger asChild>\n <button\n type=\"button\"\n onClick={onPreview}\n className=\"inline-flex items-center gap-1 rounded-md border border-border px-2 py-1 text-xs text-muted-foreground hover:text-foreground\"\n >\n <IconCode className=\"h-3.5 w-3.5\" />\n Preview SQL\n </button>\n </PopoverTrigger>\n <PopoverContent align=\"end\" className=\"w-[34rem] p-0\">\n <div className=\"border-b border-border px-3 py-2 text-xs font-medium text-foreground\">\n Preview SQL\n </div>\n <div className=\"max-h-80 overflow-auto p-3\">\n {error ? (\n <div className=\"text-xs text-destructive\">{error}</div>\n ) : sql && sql.length > 0 ? (\n <pre className=\"whitespace-pre-wrap break-all font-mono text-[11px] leading-relaxed text-foreground\">\n {sql.join(\";\\n\")}\n </pre>\n ) : (\n <div className=\"text-xs text-muted-foreground\">\n No statements to run.\n </div>\n )}\n </div>\n </PopoverContent>\n </Popover>\n );\n}\n\nfunction ConfirmModal({\n title,\n body,\n confirmLabel,\n destructive,\n onCancel,\n onConfirm,\n}: {\n title: string;\n body: string;\n confirmLabel: string;\n destructive?: boolean;\n onCancel: () => void;\n onConfirm: () => void;\n}) {\n useEffect(() => {\n const onKey = (e: KeyboardEvent) => {\n if (e.key === \"Escape\") onCancel();\n };\n window.addEventListener(\"keydown\", onKey);\n return () => window.removeEventListener(\"keydown\", onKey);\n }, [onCancel]);\n\n if (typeof document === \"undefined\") return null;\n return createPortal(\n <div className=\"fixed inset-0 z-[450] flex items-center justify-center\">\n <div className=\"absolute inset-0 bg-black/40\" onClick={onCancel} />\n <div className=\"relative w-full max-w-sm rounded-lg border border-border bg-card p-4 shadow-xl\">\n <div className=\"mb-1 flex items-center gap-2\">\n {destructive && (\n <IconAlertTriangle className=\"h-4 w-4 text-destructive\" />\n )}\n <h2 className=\"text-sm font-semibold text-foreground\">{title}</h2>\n </div>\n <p className=\"mb-4 text-xs text-muted-foreground\">{body}</p>\n <div className=\"flex justify-end gap-2\">\n <button\n type=\"button\"\n onClick={onCancel}\n className=\"rounded-md px-3 py-1.5 text-xs text-muted-foreground hover:bg-muted hover:text-foreground\"\n >\n Cancel\n </button>\n <button\n type=\"button\"\n onClick={onConfirm}\n className={cn(\n \"rounded-md px-3 py-1.5 text-xs font-medium text-primary-foreground\",\n destructive\n ? \"bg-destructive hover:bg-destructive/90\"\n : \"bg-primary hover:bg-primary/90\",\n )}\n >\n {confirmLabel}\n </button>\n </div>\n </div>\n </div>,\n document.body,\n );\n}\n"]}
|
package/dist/db/client.d.ts
CHANGED
|
@@ -26,6 +26,17 @@ export interface DbExecConfig {
|
|
|
26
26
|
export declare function getDatabaseUrl(fallback?: string): string;
|
|
27
27
|
/** Same per-app resolution for DATABASE_AUTH_TOKEN (used by Turso/libsql). */
|
|
28
28
|
export declare function getDatabaseAuthToken(): string | undefined;
|
|
29
|
+
/**
|
|
30
|
+
* Database URL to use for migrations — identical to DATABASE_URL but with the
|
|
31
|
+
* Neon connection-pooler suffix stripped. Neon's PgBouncer runs in transaction
|
|
32
|
+
* mode, which resets session-level ownership after each statement and causes
|
|
33
|
+
* `ALTER TABLE … ADD COLUMN` to fail with "must be owner of table <x>" even
|
|
34
|
+
* when the connecting role owns it. The direct endpoint bypasses PgBouncer so
|
|
35
|
+
* DDL honours the role's actual ownership.
|
|
36
|
+
*
|
|
37
|
+
* Non-Neon URLs and already-direct Neon URLs are returned unchanged.
|
|
38
|
+
*/
|
|
39
|
+
export declare function getMigrationDatabaseUrl(): string;
|
|
29
40
|
export declare function isLocalSqliteUrl(url: string): boolean;
|
|
30
41
|
export declare function prepareLocalSqliteUrl(url: string): Promise<string>;
|
|
31
42
|
export declare function sqliteFilenameFromUrl(url: string): string;
|
|
@@ -127,6 +138,14 @@ export declare function pgPoolOptions(url: string): Record<string, unknown>;
|
|
|
127
138
|
* proceed when one connection is busy.
|
|
128
139
|
*/
|
|
129
140
|
export declare function neonPoolMax(): number;
|
|
141
|
+
/**
|
|
142
|
+
* Render any rejection reason as a readable message. The Neon serverless
|
|
143
|
+
* driver surfaces WebSocket failures as raw DOM-style ErrorEvent objects (not
|
|
144
|
+
* Error instances), which stringify uselessly as "[object ErrorEvent]" — pull
|
|
145
|
+
* the message off the event (or its nested `.error`) instead so logs carry
|
|
146
|
+
* actual context.
|
|
147
|
+
*/
|
|
148
|
+
export declare function describeDbError(err: unknown): string;
|
|
130
149
|
export declare function attachNeonPoolErrorLogger(pool: unknown, label?: string): void;
|
|
131
150
|
export declare function createDbExec(config?: DbExecConfig): Promise<DbExec>;
|
|
132
151
|
/**
|
package/dist/db/client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/db/client.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/db/client.ts"],"names":[],"mappings":"AAmBA,MAAM,MAAM,OAAO,GAAG,QAAQ,GAAG,UAAU,GAAG,IAAI,CAAC;AAEnD,MAAM,WAAW,MAAM;IACrB,OAAO,CACL,GAAG,EAAE,MAAM,GAAG;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,GAAG,EAAE,CAAA;KAAE,GACzC,OAAO,CAAC;QAAE,IAAI,EAAE,GAAG,EAAE,CAAC;QAAC,YAAY,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACnD;AAED,MAAM,WAAW,YAAY;IAC3B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,GAAG,CAAC;CACjB;AAMD;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAAC,QAAQ,SAAK,GAAG,MAAM,CAOpD;AAED,8EAA8E;AAC9E,wBAAgB,oBAAoB,IAAI,MAAM,GAAG,SAAS,CAOzD;AAED;;;;;;;;;GASG;AACH,wBAAgB,uBAAuB,IAAI,MAAM,CAShD;AAED,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAErD;AAED,wBAAsB,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAmBxE;AAED,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAQzD;AAMD;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,GAAG,CAAC,CAO/D;AAMD;;;;GAIG;AACH,wBAAsB,eAAe,CAAC,CAAC,EACrC,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACpB,IAAI,GAAE;IAAE,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAO,GAC3E,OAAO,CAAC,CAAC,CAAC,CAkBZ;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,cAAc,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAOxE;AAiBD;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,GAAG,GAAG,OAAO,CAejD;AAQD,wBAAgB,UAAU,IAAI,OAAO,CAyBpC;AAED,wBAAgB,UAAU,IAAI,OAAO,CAEpC;AAgBD;;;;;;;;GAQG;AACH,wBAAgB,eAAe,IAAI,OAAO,CAIzC;AAED,iFAAiF;AACjF,wBAAgB,OAAO,IAAI,MAAM,CAEhC;AA2BD,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,GAAG,GAAG,OAAO,CAoBnD;AAED,wBAAsB,sBAAsB,CAAC,CAAC,EAC5C,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACpB,WAAW,SAAI,GACd,OAAO,CAAC,CAAC,CAAC,CAYZ;AAMD;;;;;;;;;;;GAWG;AACH,wBAAgB,aAAa,IAAI,MAAM,CAItC;AAgBD;;;;GAIG;AACH,wBAAsB,aAAa,CAAC,CAAC,EACnC,EAAE,EAAE,MAAM,EACV,GAAG,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACrB,EAAE,SAAkB,EACpB,SAAS,CAAC,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,GACrC,OAAO,CAAC,CAAC,CAAC,CAmDZ;AAMD;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,IAAI,OAAO,CAQ7C;AAED;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAYlE;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,IAAI,MAAM,CAEpC;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAepD;AAED,wBAAgB,yBAAyB,CACvC,IAAI,EAAE,OAAO,EACb,KAAK,SAAY,GAChB,IAAI,CA2CN;AAoSD,wBAAsB,YAAY,CAAC,MAAM,GAAE,YAAiB,GAAG,OAAO,CAAC,MAAM,CAAC,CAE7E;AAiBD;;;GAGG;AACH,wBAAgB,SAAS,IAAI,MAAM,CAoClC;AAED,qEAAqE;AACrE,wBAAsB,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CAejD"}
|
package/dist/db/client.js
CHANGED
|
@@ -43,6 +43,26 @@ export function getDatabaseAuthToken() {
|
|
|
43
43
|
}
|
|
44
44
|
return process.env.DATABASE_AUTH_TOKEN;
|
|
45
45
|
}
|
|
46
|
+
/**
|
|
47
|
+
* Database URL to use for migrations — identical to DATABASE_URL but with the
|
|
48
|
+
* Neon connection-pooler suffix stripped. Neon's PgBouncer runs in transaction
|
|
49
|
+
* mode, which resets session-level ownership after each statement and causes
|
|
50
|
+
* `ALTER TABLE … ADD COLUMN` to fail with "must be owner of table <x>" even
|
|
51
|
+
* when the connecting role owns it. The direct endpoint bypasses PgBouncer so
|
|
52
|
+
* DDL honours the role's actual ownership.
|
|
53
|
+
*
|
|
54
|
+
* Non-Neon URLs and already-direct Neon URLs are returned unchanged.
|
|
55
|
+
*/
|
|
56
|
+
export function getMigrationDatabaseUrl() {
|
|
57
|
+
const url = getDatabaseUrl();
|
|
58
|
+
// Neon pooler hostname: ep-<id>-pooler.<region>.<cloud>.neon.tech
|
|
59
|
+
// Direct hostname: ep-<id>.<region>.<cloud>.neon.tech
|
|
60
|
+
// The region between `-pooler.` and `.neon.tech` can contain multiple
|
|
61
|
+
// dot-separated labels (e.g. `c-7.us-east-1.aws`), so the matched segment
|
|
62
|
+
// must allow dots — `[a-z0-9.-]+` — not just a single label. Anchoring on the
|
|
63
|
+
// stable `.neon.tech` suffix keeps this from touching non-Neon hosts.
|
|
64
|
+
return url.replace(/-pooler(\.[a-z0-9.-]+\.neon\.tech)/, "$1");
|
|
65
|
+
}
|
|
46
66
|
export function isLocalSqliteUrl(url) {
|
|
47
67
|
return url === "" || url.startsWith("file:") || !url.includes("://");
|
|
48
68
|
}
|
|
@@ -435,6 +455,27 @@ export function pgPoolOptions(url) {
|
|
|
435
455
|
export function neonPoolMax() {
|
|
436
456
|
return isServerlessRuntime() ? 2 : 10;
|
|
437
457
|
}
|
|
458
|
+
/**
|
|
459
|
+
* Render any rejection reason as a readable message. The Neon serverless
|
|
460
|
+
* driver surfaces WebSocket failures as raw DOM-style ErrorEvent objects (not
|
|
461
|
+
* Error instances), which stringify uselessly as "[object ErrorEvent]" — pull
|
|
462
|
+
* the message off the event (or its nested `.error`) instead so logs carry
|
|
463
|
+
* actual context.
|
|
464
|
+
*/
|
|
465
|
+
export function describeDbError(err) {
|
|
466
|
+
if (err instanceof Error)
|
|
467
|
+
return err.message;
|
|
468
|
+
if (err && typeof err === "object") {
|
|
469
|
+
const evt = err;
|
|
470
|
+
const msg = evt.message ?? evt.error?.message;
|
|
471
|
+
if (typeof msg === "string" && msg)
|
|
472
|
+
return msg;
|
|
473
|
+
if (evt.type === "error") {
|
|
474
|
+
return "WebSocket ErrorEvent (connection failed; no message attached)";
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
return String(err);
|
|
478
|
+
}
|
|
438
479
|
export function attachNeonPoolErrorLogger(pool, label = "db/neon") {
|
|
439
480
|
if (!pool || typeof pool !== "object")
|
|
440
481
|
return;
|
|
@@ -445,7 +486,7 @@ export function attachNeonPoolErrorLogger(pool, label = "db/neon") {
|
|
|
445
486
|
return;
|
|
446
487
|
loggedNeonPools.add(pool);
|
|
447
488
|
withEvents.on("error", (err) => {
|
|
448
|
-
console.warn(`[${label}] pool error (will reconnect on next query):`, err
|
|
489
|
+
console.warn(`[${label}] pool error (will reconnect on next query):`, describeDbError(err));
|
|
449
490
|
});
|
|
450
491
|
// Attach a persistent 'error' listener to EVERY client for its whole lifetime.
|
|
451
492
|
//
|
|
@@ -468,7 +509,7 @@ export function attachNeonPoolErrorLogger(pool, label = "db/neon") {
|
|
|
468
509
|
if (typeof clientEvents.on !== "function")
|
|
469
510
|
return;
|
|
470
511
|
clientEvents.on("error", (err) => {
|
|
471
|
-
console.warn(`[${label}] client connection error (connection discarded, next query reconnects):`, err
|
|
512
|
+
console.warn(`[${label}] client connection error (connection discarded, next query reconnects):`, describeDbError(err));
|
|
472
513
|
});
|
|
473
514
|
});
|
|
474
515
|
}
|