@agent-native/core 0.86.0 → 0.86.1
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/corpus/README.md +2 -2
- package/corpus/core/CHANGELOG.md +9 -0
- package/corpus/core/package.json +2 -1
- package/corpus/core/src/client/AgentPanel.tsx +10 -0
- package/corpus/core/src/client/AssistantChat.tsx +91 -27
- package/corpus/core/src/client/ErrorBoundary.tsx +67 -12
- package/corpus/core/src/client/ErrorReportActions.tsx +69 -0
- package/corpus/core/src/client/FeedbackButton.tsx +8 -4
- package/corpus/core/src/client/db-admin/DbAdminPage.tsx +41 -13
- package/corpus/core/src/client/db-admin/SqlEditor.tsx +10 -3
- package/corpus/core/src/client/db-admin/TableEditor.tsx +12 -5
- package/corpus/core/src/client/db-admin/useAgentSync.ts +10 -3
- package/corpus/core/src/client/db-admin/useDbAdmin.ts +65 -16
- package/corpus/core/src/client/error-reporting.ts +100 -0
- package/corpus/core/src/client/index.ts +11 -0
- package/corpus/core/src/client/org/RequireActiveOrg.tsx +12 -0
- package/corpus/core/src/client/visual-style-controls.tsx +615 -2
- package/corpus/core/src/db-admin/index.ts +26 -0
- package/corpus/core/src/db-admin/operations.ts +87 -49
- package/corpus/core/src/localization/default-messages.ts +4 -0
- package/corpus/core/src/server/builder-design-systems.ts +328 -9
- package/corpus/core/src/server/index.ts +15 -0
- package/corpus/core/src/templates/default/app/root.tsx +47 -0
- package/corpus/templates/analytics/AGENTS.md +6 -4
- package/corpus/templates/analytics/actions/delete-db-admin-connection.ts +19 -0
- package/corpus/templates/analytics/actions/list-db-admin-connections.ts +18 -0
- package/corpus/templates/analytics/actions/navigate.ts +17 -3
- package/corpus/templates/analytics/actions/save-db-admin-connection.ts +33 -0
- package/corpus/templates/analytics/actions/view-screen.ts +11 -3
- package/corpus/templates/analytics/app/hooks/use-navigation-state.ts +11 -2
- package/corpus/templates/analytics/app/i18n/zh-TW.ts +23 -2
- package/corpus/templates/analytics/app/i18n-data.ts +230 -20
- package/corpus/templates/analytics/app/pages/Agents.tsx +398 -4
- package/corpus/templates/analytics/changelog/2026-07-03-connect-other-app-databases-from-analytics.md +6 -0
- package/corpus/templates/analytics/server/db/schema.ts +27 -0
- package/corpus/templates/analytics/server/lib/db-admin-connections.ts +458 -0
- package/corpus/templates/analytics/server/plugins/db.ts +35 -0
- package/corpus/templates/analytics/server/routes/[base]/_agent-native/analytics-db-admin/[...path].ts +1 -0
- package/corpus/templates/analytics/server/routes/_agent-native/analytics-db-admin/[...path].ts +160 -0
- package/corpus/templates/content/app/root.tsx +9 -0
- package/corpus/templates/content/changelog/2026-07-03-error-screens-now-include-a-feedback-button-with-debug-info.md +6 -0
- package/corpus/templates/design/AGENTS.md +13 -7
- package/corpus/templates/design/actions/get-design-system.ts +21 -0
- package/corpus/templates/design/actions/index-design-system-with-builder.ts +14 -37
- package/corpus/templates/design/app/components/design/code-workbench/CodeWorkbench.tsx +3 -3
- package/corpus/templates/design/app/components/design/code-workbench/SideBar.tsx +70 -9
- package/corpus/templates/design/app/components/design/code-workbench/editor/EditorTabs.tsx +11 -2
- package/corpus/templates/design/app/components/design/code-workbench/editor/MonacoHost.tsx +1 -1
- package/corpus/templates/design/app/components/design/code-workbench/editor/StatusBar.tsx +1 -1
- package/corpus/templates/design/app/components/design/code-workbench/explorer/ExplorerView.tsx +8 -2
- package/corpus/templates/design/app/components/design/code-workbench/explorer/FileTree.tsx +7 -3
- package/corpus/templates/design/app/components/design/code-workbench/store.tsx +48 -0
- package/corpus/templates/design/app/hooks/useDesignHotkeys.ts +6 -0
- package/corpus/templates/design/app/i18n/zh-TW.ts +15 -14
- package/corpus/templates/design/app/i18n-data.ts +154 -142
- package/corpus/templates/design/app/pages/DesignSystemSetup.tsx +32 -14
- package/corpus/templates/design/changelog/2026-07-03-design-system-setup-now-indexes-figma-code-and-design-md-sou.md +6 -0
- package/corpus/templates/design/changelog/2026-07-03-the-code-editor-is-easier-to-use-with-top-sidebar-tabs-clear.md +6 -0
- package/corpus/templates/design/server/lib/builder-design-system-proxy.ts +16 -106
- package/corpus/templates/mail/app/root.tsx +60 -1
- package/corpus/templates/mail/changelog/2026-07-03-error-screens-now-include-a-feedback-button-with-debug-info.md +6 -0
- package/corpus/templates/plan/app/i18n/ar-SA.ts +3 -0
- package/corpus/templates/plan/app/i18n/de-DE.ts +4 -0
- package/corpus/templates/plan/app/i18n/en-US.ts +4 -0
- package/corpus/templates/plan/app/i18n/es-ES.ts +4 -0
- package/corpus/templates/plan/app/i18n/fr-FR.ts +4 -0
- package/corpus/templates/plan/app/i18n/hi-IN.ts +3 -0
- package/corpus/templates/plan/app/i18n/ja-JP.ts +4 -0
- package/corpus/templates/plan/app/i18n/ko-KR.ts +4 -0
- package/corpus/templates/plan/app/i18n/pt-BR.ts +4 -0
- package/corpus/templates/plan/app/i18n/zh-CN.ts +3 -0
- package/corpus/templates/plan/app/i18n/zh-TW.ts +3 -0
- package/corpus/templates/plan/app/pages/PlansPage.tsx +74 -3
- package/corpus/templates/plan/changelog/2026-07-03-error-screens-now-include-a-feedback-button-with-debug-info.md +6 -0
- package/corpus/templates/slides/AGENTS.md +7 -3
- package/corpus/templates/slides/actions/get-design-system.ts +21 -0
- package/corpus/templates/slides/actions/import-file.ts +15 -7
- package/corpus/templates/slides/actions/index-design-system-with-builder.ts +14 -37
- package/corpus/templates/slides/app/components/design-system/DesignSystemSetup.tsx +32 -8
- package/corpus/templates/slides/app/components/editor/EditorSidebar.tsx +2 -2
- package/corpus/templates/slides/app/components/editor/EditorToolbar.tsx +2 -4
- package/corpus/templates/slides/app/components/editor/SlideEditor.tsx +163 -154
- package/corpus/templates/slides/app/components/editor/SlideStyleInspector.tsx +19 -15
- package/corpus/templates/slides/app/components/editor/SpeakerNotesPanel.tsx +56 -6
- package/corpus/templates/slides/app/components/layout/Layout.tsx +6 -1
- package/corpus/templates/slides/app/i18n/ar-SA.ts +8 -7
- package/corpus/templates/slides/app/i18n/de-DE.ts +7 -8
- package/corpus/templates/slides/app/i18n/en-US.ts +8 -7
- package/corpus/templates/slides/app/i18n/es-ES.ts +7 -8
- package/corpus/templates/slides/app/i18n/fr-FR.ts +7 -8
- package/corpus/templates/slides/app/i18n/hi-IN.ts +8 -7
- package/corpus/templates/slides/app/i18n/ja-JP.ts +7 -8
- package/corpus/templates/slides/app/i18n/ko-KR.ts +7 -7
- package/corpus/templates/slides/app/i18n/pt-BR.ts +7 -8
- package/corpus/templates/slides/app/i18n/zh-CN.ts +8 -7
- package/corpus/templates/slides/app/i18n/zh-TW.ts +8 -7
- package/corpus/templates/slides/app/lib/canvas-zoom.ts +16 -1
- package/corpus/templates/slides/app/pages/DeckEditor.tsx +3 -3
- package/corpus/templates/slides/changelog/2026-07-03-design-system-setup-now-indexes-figma-code-and-design-md-sou.md +6 -0
- package/corpus/templates/slides/changelog/2026-07-03-slide-editing-now-keeps-thumbnails-speaker-notes-styling-and.md +6 -0
- package/corpus/templates/slides/server/lib/builder-design-system-proxy.ts +16 -104
- package/dist/client/AgentPanel.d.ts.map +1 -1
- package/dist/client/AgentPanel.js +2 -1
- package/dist/client/AgentPanel.js.map +1 -1
- package/dist/client/AssistantChat.d.ts.map +1 -1
- package/dist/client/AssistantChat.js +77 -25
- package/dist/client/AssistantChat.js.map +1 -1
- package/dist/client/ErrorBoundary.d.ts.map +1 -1
- package/dist/client/ErrorBoundary.js +37 -2
- package/dist/client/ErrorBoundary.js.map +1 -1
- package/dist/client/ErrorReportActions.d.ts +13 -0
- package/dist/client/ErrorReportActions.d.ts.map +1 -0
- package/dist/client/ErrorReportActions.js +14 -0
- package/dist/client/ErrorReportActions.js.map +1 -0
- package/dist/client/FeedbackButton.d.ts +3 -1
- package/dist/client/FeedbackButton.d.ts.map +1 -1
- package/dist/client/FeedbackButton.js +6 -5
- package/dist/client/FeedbackButton.js.map +1 -1
- package/dist/client/db-admin/DbAdminPage.d.ts +9 -1
- package/dist/client/db-admin/DbAdminPage.d.ts.map +1 -1
- package/dist/client/db-admin/DbAdminPage.js +17 -13
- package/dist/client/db-admin/DbAdminPage.js.map +1 -1
- package/dist/client/db-admin/SqlEditor.d.ts +3 -1
- package/dist/client/db-admin/SqlEditor.d.ts.map +1 -1
- package/dist/client/db-admin/SqlEditor.js +3 -3
- package/dist/client/db-admin/SqlEditor.js.map +1 -1
- package/dist/client/db-admin/TableEditor.d.ts +3 -1
- package/dist/client/db-admin/TableEditor.d.ts.map +1 -1
- package/dist/client/db-admin/TableEditor.js +6 -6
- package/dist/client/db-admin/TableEditor.js.map +1 -1
- package/dist/client/db-admin/useAgentSync.d.ts +3 -2
- package/dist/client/db-admin/useAgentSync.d.ts.map +1 -1
- package/dist/client/db-admin/useAgentSync.js +8 -4
- package/dist/client/db-admin/useAgentSync.js.map +1 -1
- package/dist/client/db-admin/useDbAdmin.d.ts +11 -7
- package/dist/client/db-admin/useDbAdmin.d.ts.map +1 -1
- package/dist/client/db-admin/useDbAdmin.js +45 -20
- package/dist/client/db-admin/useDbAdmin.js.map +1 -1
- package/dist/client/error-reporting.d.ts +19 -0
- package/dist/client/error-reporting.d.ts.map +1 -0
- package/dist/client/error-reporting.js +71 -0
- package/dist/client/error-reporting.js.map +1 -0
- package/dist/client/index.d.ts +3 -1
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +3 -1
- package/dist/client/index.js.map +1 -1
- package/dist/client/org/RequireActiveOrg.d.ts.map +1 -1
- package/dist/client/org/RequireActiveOrg.js +2 -1
- package/dist/client/org/RequireActiveOrg.js.map +1 -1
- package/dist/client/visual-style-controls.d.ts +11 -0
- package/dist/client/visual-style-controls.d.ts.map +1 -1
- package/dist/client/visual-style-controls.js +350 -1
- package/dist/client/visual-style-controls.js.map +1 -1
- package/dist/collab/routes.d.ts +1 -1
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/db-admin/index.d.ts +3 -0
- package/dist/db-admin/index.d.ts.map +1 -0
- package/dist/db-admin/index.js +2 -0
- package/dist/db-admin/index.js.map +1 -0
- package/dist/db-admin/operations.d.ts +26 -5
- package/dist/db-admin/operations.d.ts.map +1 -1
- package/dist/db-admin/operations.js +66 -55
- package/dist/db-admin/operations.js.map +1 -1
- package/dist/localization/default-messages.d.ts +3 -0
- package/dist/localization/default-messages.d.ts.map +1 -1
- package/dist/localization/default-messages.js +3 -0
- package/dist/localization/default-messages.js.map +1 -1
- package/dist/notifications/routes.d.ts +1 -1
- package/dist/provider-api/corpus-jobs.d.ts +2 -2
- package/dist/resources/handlers.d.ts +1 -1
- package/dist/secrets/routes.d.ts +9 -9
- package/dist/server/builder-design-systems.d.ts +61 -0
- package/dist/server/builder-design-systems.d.ts.map +1 -1
- package/dist/server/builder-design-systems.js +219 -14
- package/dist/server/builder-design-systems.js.map +1 -1
- package/dist/server/index.d.ts +1 -1
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +1 -1
- package/dist/server/index.js.map +1 -1
- package/dist/server/transcribe-voice.d.ts +1 -1
- package/dist/templates/default/app/root.tsx +47 -0
- package/package.json +2 -1
- package/src/templates/default/app/root.tsx +47 -0
|
@@ -1,18 +1,24 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Database admin operations.
|
|
3
3
|
*
|
|
4
4
|
* Pure, dialect-agnostic, RAW/UNSCOPED helpers backing the Supabase-Studio-like
|
|
5
5
|
* DB admin. These run the FULL database with no per-user `accessFilter`
|
|
6
|
-
* scoping
|
|
7
|
-
*
|
|
8
|
-
*
|
|
6
|
+
* scoping. Callers MUST gate access before invoking them. The built-in core
|
|
7
|
+
* route gates this to dev + localhost; production-reachable surfaces must pass
|
|
8
|
+
* an explicit runtime for the target database and enforce their own admin-only
|
|
9
|
+
* checks before reading or mutating.
|
|
9
10
|
*
|
|
10
11
|
* All access goes through the unified `getDbExec()` client, which uses `?`
|
|
11
12
|
* placeholders (auto-converted to `$1,$2,…` for Postgres) and returns rows
|
|
12
13
|
* keyed by column name. Identifiers are validated against a strict pattern and
|
|
13
14
|
* always double-quoted; values are ALWAYS parameterized — never interpolated.
|
|
14
15
|
*/
|
|
15
|
-
import {
|
|
16
|
+
import {
|
|
17
|
+
getDbExec,
|
|
18
|
+
getDialect,
|
|
19
|
+
type DbExec,
|
|
20
|
+
type Dialect,
|
|
21
|
+
} from "../db/client.js";
|
|
16
22
|
import { notifyActionChange } from "../server/action-change.js";
|
|
17
23
|
import type {
|
|
18
24
|
DbAdminColumn,
|
|
@@ -35,6 +41,12 @@ import type {
|
|
|
35
41
|
|
|
36
42
|
const IDENT_RE = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
37
43
|
|
|
44
|
+
export interface DbAdminRuntime {
|
|
45
|
+
db?: DbExec;
|
|
46
|
+
dialect?: Dialect;
|
|
47
|
+
notifyChange?: () => Promise<void>;
|
|
48
|
+
}
|
|
49
|
+
|
|
38
50
|
/** Throw on any identifier that isn't a plain `[A-Za-z_][A-Za-z0-9_]*`. */
|
|
39
51
|
function assertIdent(name: string, kind = "identifier"): string {
|
|
40
52
|
if (typeof name !== "string" || !IDENT_RE.test(name)) {
|
|
@@ -48,15 +60,27 @@ function quoteIdent(name: string): string {
|
|
|
48
60
|
return `"${assertIdent(name)}"`;
|
|
49
61
|
}
|
|
50
62
|
|
|
51
|
-
function
|
|
52
|
-
return
|
|
63
|
+
function db(runtime?: DbAdminRuntime): DbExec {
|
|
64
|
+
return runtime?.db ?? getDbExec();
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function dialect(runtime?: DbAdminRuntime): DbAdminDialect {
|
|
68
|
+
return (runtime?.dialect ?? getDialect()) as DbAdminDialect;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function isPostgresRuntime(runtime?: DbAdminRuntime): boolean {
|
|
72
|
+
return dialect(runtime) === "postgres";
|
|
53
73
|
}
|
|
54
74
|
|
|
55
75
|
// ---------------------------------------------------------------------------
|
|
56
76
|
// Notify the UI after a real mutation so polling refetches.
|
|
57
77
|
// ---------------------------------------------------------------------------
|
|
58
78
|
|
|
59
|
-
async function notifyDbAdminChange(): Promise<void> {
|
|
79
|
+
async function notifyDbAdminChange(runtime?: DbAdminRuntime): Promise<void> {
|
|
80
|
+
if (runtime?.notifyChange) {
|
|
81
|
+
await runtime.notifyChange();
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
60
84
|
// The UI keys on useChangeVersions(["db-admin","action"]). notifyActionChange
|
|
61
85
|
// records a "db-admin" change AND a marker; the action route layer's generic
|
|
62
86
|
// "action" source is covered by passing the db-admin action name through the
|
|
@@ -68,15 +92,15 @@ async function notifyDbAdminChange(): Promise<void> {
|
|
|
68
92
|
// listTables
|
|
69
93
|
// ---------------------------------------------------------------------------
|
|
70
94
|
|
|
71
|
-
export async function listTables(): Promise<{
|
|
95
|
+
export async function listTables(runtime?: DbAdminRuntime): Promise<{
|
|
72
96
|
dialect: DbAdminDialect;
|
|
73
97
|
tables: DbAdminTableSummary[];
|
|
74
98
|
}> {
|
|
75
|
-
const
|
|
99
|
+
const client = db(runtime);
|
|
76
100
|
const summaries: DbAdminTableSummary[] = [];
|
|
77
101
|
|
|
78
|
-
if (
|
|
79
|
-
const res = await
|
|
102
|
+
if (isPostgresRuntime(runtime)) {
|
|
103
|
+
const res = await client.execute(
|
|
80
104
|
`SELECT table_name AS name, table_type AS type
|
|
81
105
|
FROM information_schema.tables
|
|
82
106
|
WHERE table_schema = 'public'
|
|
@@ -89,11 +113,11 @@ export async function listTables(): Promise<{
|
|
|
89
113
|
summaries.push({
|
|
90
114
|
name,
|
|
91
115
|
type,
|
|
92
|
-
rowCount: type === "view" ? null : await safeRowCount(name),
|
|
116
|
+
rowCount: type === "view" ? null : await safeRowCount(name, runtime),
|
|
93
117
|
});
|
|
94
118
|
}
|
|
95
119
|
} else {
|
|
96
|
-
const res = await
|
|
120
|
+
const res = await client.execute(
|
|
97
121
|
`SELECT name, type FROM sqlite_master
|
|
98
122
|
WHERE type IN ('table', 'view')
|
|
99
123
|
AND name NOT LIKE 'sqlite_%'
|
|
@@ -105,18 +129,21 @@ export async function listTables(): Promise<{
|
|
|
105
129
|
summaries.push({
|
|
106
130
|
name,
|
|
107
131
|
type,
|
|
108
|
-
rowCount: type === "view" ? null : await safeRowCount(name),
|
|
132
|
+
rowCount: type === "view" ? null : await safeRowCount(name, runtime),
|
|
109
133
|
});
|
|
110
134
|
}
|
|
111
135
|
}
|
|
112
136
|
|
|
113
|
-
return { dialect: dialect(), tables: summaries };
|
|
137
|
+
return { dialect: dialect(runtime), tables: summaries };
|
|
114
138
|
}
|
|
115
139
|
|
|
116
|
-
async function safeRowCount(
|
|
140
|
+
async function safeRowCount(
|
|
141
|
+
table: string,
|
|
142
|
+
runtime?: DbAdminRuntime,
|
|
143
|
+
): Promise<number | null> {
|
|
117
144
|
try {
|
|
118
|
-
const
|
|
119
|
-
const res = await
|
|
145
|
+
const client = db(runtime);
|
|
146
|
+
const res = await client.execute(
|
|
120
147
|
`SELECT COUNT(*) AS c FROM ${quoteIdent(table)}`,
|
|
121
148
|
);
|
|
122
149
|
const c = (res.rows[0] as any)?.c;
|
|
@@ -133,26 +160,28 @@ async function safeRowCount(table: string): Promise<number | null> {
|
|
|
133
160
|
|
|
134
161
|
export async function getTableSchema(
|
|
135
162
|
table: string,
|
|
163
|
+
runtime?: DbAdminRuntime,
|
|
136
164
|
): Promise<DbAdminTableSchema> {
|
|
137
165
|
assertIdent(table, "table name");
|
|
138
|
-
return
|
|
139
|
-
? getTableSchemaPostgres(table)
|
|
140
|
-
: getTableSchemaSqlite(table);
|
|
166
|
+
return isPostgresRuntime(runtime)
|
|
167
|
+
? getTableSchemaPostgres(table, runtime)
|
|
168
|
+
: getTableSchemaSqlite(table, runtime);
|
|
141
169
|
}
|
|
142
170
|
|
|
143
171
|
async function getTableSchemaPostgres(
|
|
144
172
|
table: string,
|
|
173
|
+
runtime?: DbAdminRuntime,
|
|
145
174
|
): Promise<DbAdminTableSchema> {
|
|
146
|
-
const
|
|
175
|
+
const client = db(runtime);
|
|
147
176
|
|
|
148
|
-
const typeRes = await
|
|
177
|
+
const typeRes = await client.execute({
|
|
149
178
|
sql: `SELECT table_type AS type FROM information_schema.tables
|
|
150
179
|
WHERE table_schema = 'public' AND table_name = ?`,
|
|
151
180
|
args: [table],
|
|
152
181
|
});
|
|
153
182
|
const type = (typeRes.rows[0] as any)?.type === "VIEW" ? "view" : "table";
|
|
154
183
|
|
|
155
|
-
const colRes = await
|
|
184
|
+
const colRes = await client.execute({
|
|
156
185
|
sql: `SELECT
|
|
157
186
|
column_name AS name,
|
|
158
187
|
data_type AS type,
|
|
@@ -164,7 +193,7 @@ async function getTableSchemaPostgres(
|
|
|
164
193
|
args: [table],
|
|
165
194
|
});
|
|
166
195
|
|
|
167
|
-
const pkRes = await
|
|
196
|
+
const pkRes = await client.execute({
|
|
168
197
|
sql: `SELECT kcu.column_name AS col
|
|
169
198
|
FROM information_schema.table_constraints tc
|
|
170
199
|
JOIN information_schema.key_column_usage kcu
|
|
@@ -179,7 +208,7 @@ async function getTableSchemaPostgres(
|
|
|
179
208
|
const primaryKey = pkRes.rows.map((r) => String((r as any).col));
|
|
180
209
|
const pkSet = new Set(primaryKey);
|
|
181
210
|
|
|
182
|
-
const fkRes = await
|
|
211
|
+
const fkRes = await client.execute({
|
|
183
212
|
sql: `SELECT
|
|
184
213
|
kcu.column_name AS col,
|
|
185
214
|
ccu.table_name AS ref_table,
|
|
@@ -202,7 +231,7 @@ async function getTableSchemaPostgres(
|
|
|
202
231
|
refColumn: String((r as any).ref_col),
|
|
203
232
|
}));
|
|
204
233
|
|
|
205
|
-
const idxRes = await
|
|
234
|
+
const idxRes = await client.execute({
|
|
206
235
|
sql: `SELECT indexname AS name, indexdef AS def
|
|
207
236
|
FROM pg_indexes
|
|
208
237
|
WHERE schemaname = 'public' AND tablename = ?`,
|
|
@@ -248,22 +277,25 @@ async function getTableSchemaPostgres(
|
|
|
248
277
|
primaryKey,
|
|
249
278
|
foreignKeys,
|
|
250
279
|
indexes,
|
|
251
|
-
rowCount: type === "view" ? null : await safeRowCount(table),
|
|
280
|
+
rowCount: type === "view" ? null : await safeRowCount(table, runtime),
|
|
252
281
|
};
|
|
253
282
|
}
|
|
254
283
|
|
|
255
284
|
async function getTableSchemaSqlite(
|
|
256
285
|
table: string,
|
|
286
|
+
runtime?: DbAdminRuntime,
|
|
257
287
|
): Promise<DbAdminTableSchema> {
|
|
258
|
-
const
|
|
288
|
+
const client = db(runtime);
|
|
259
289
|
|
|
260
|
-
const typeRes = await
|
|
290
|
+
const typeRes = await client.execute({
|
|
261
291
|
sql: `SELECT type FROM sqlite_master WHERE name = ? AND type IN ('table','view')`,
|
|
262
292
|
args: [table],
|
|
263
293
|
});
|
|
264
294
|
const type = (typeRes.rows[0] as any)?.type === "view" ? "view" : "table";
|
|
265
295
|
|
|
266
|
-
const colRes = await
|
|
296
|
+
const colRes = await client.execute(
|
|
297
|
+
`PRAGMA table_info(${quoteIdent(table)})`,
|
|
298
|
+
);
|
|
267
299
|
const columns: DbAdminColumn[] = colRes.rows.map((r) => {
|
|
268
300
|
const name = String((r as any).name);
|
|
269
301
|
const dflt = (r as any).dflt_value;
|
|
@@ -290,7 +322,7 @@ async function getTableSchemaSqlite(
|
|
|
290
322
|
}
|
|
291
323
|
}
|
|
292
324
|
|
|
293
|
-
const fkRes = await
|
|
325
|
+
const fkRes = await client.execute(
|
|
294
326
|
`PRAGMA foreign_key_list(${quoteIdent(table)})`,
|
|
295
327
|
);
|
|
296
328
|
const foreignKeys: DbAdminForeignKey[] = fkRes.rows.map((r) => ({
|
|
@@ -299,14 +331,14 @@ async function getTableSchemaSqlite(
|
|
|
299
331
|
refColumn: String((r as any).to),
|
|
300
332
|
}));
|
|
301
333
|
|
|
302
|
-
const idxListRes = await
|
|
334
|
+
const idxListRes = await client.execute(
|
|
303
335
|
`PRAGMA index_list(${quoteIdent(table)})`,
|
|
304
336
|
);
|
|
305
337
|
const indexes: DbAdminIndex[] = [];
|
|
306
338
|
for (const idx of idxListRes.rows) {
|
|
307
339
|
const idxName = String((idx as any).name);
|
|
308
340
|
if (idxName.startsWith("sqlite_")) continue;
|
|
309
|
-
const infoRes = await
|
|
341
|
+
const infoRes = await client.execute(
|
|
310
342
|
`PRAGMA index_info(${quoteIdent(idxName)})`,
|
|
311
343
|
);
|
|
312
344
|
indexes.push({
|
|
@@ -325,7 +357,7 @@ async function getTableSchemaSqlite(
|
|
|
325
357
|
primaryKey,
|
|
326
358
|
foreignKeys,
|
|
327
359
|
indexes,
|
|
328
|
-
rowCount: type === "view" ? null : await safeRowCount(table),
|
|
360
|
+
rowCount: type === "view" ? null : await safeRowCount(table, runtime),
|
|
329
361
|
};
|
|
330
362
|
}
|
|
331
363
|
|
|
@@ -358,7 +390,10 @@ const OP_SQL: Record<string, string> = {
|
|
|
358
390
|
};
|
|
359
391
|
|
|
360
392
|
/** Build a parameterized WHERE clause + args from filters. */
|
|
361
|
-
function buildWhere(
|
|
393
|
+
function buildWhere(
|
|
394
|
+
filters: DbAdminFilter[] | undefined,
|
|
395
|
+
runtime?: DbAdminRuntime,
|
|
396
|
+
): {
|
|
362
397
|
clause: string;
|
|
363
398
|
args: unknown[];
|
|
364
399
|
} {
|
|
@@ -391,7 +426,7 @@ function buildWhere(filters: DbAdminFilter[] | undefined): {
|
|
|
391
426
|
case "ilike": {
|
|
392
427
|
// SQLite LIKE is case-insensitive for ASCII by default; Postgres has
|
|
393
428
|
// a dedicated ILIKE operator.
|
|
394
|
-
if (
|
|
429
|
+
if (isPostgresRuntime(runtime)) {
|
|
395
430
|
parts.push(`${col} ILIKE ?`);
|
|
396
431
|
} else {
|
|
397
432
|
parts.push(`${col} LIKE ?`);
|
|
@@ -421,26 +456,27 @@ function buildOrderBy(sort: DbAdminRowsRequest["sort"]): string {
|
|
|
421
456
|
export async function getRows(
|
|
422
457
|
table: string,
|
|
423
458
|
req: DbAdminRowsRequest,
|
|
459
|
+
runtime?: DbAdminRuntime,
|
|
424
460
|
): Promise<DbAdminRowsResult> {
|
|
425
461
|
assertIdent(table, "table name");
|
|
426
|
-
const
|
|
427
|
-
const schema = await getTableSchema(table);
|
|
462
|
+
const client = db(runtime);
|
|
463
|
+
const schema = await getTableSchema(table, runtime);
|
|
428
464
|
|
|
429
465
|
const page = Math.max(1, Math.floor(req.page) || 1);
|
|
430
466
|
const pageSize = Math.min(1000, Math.max(1, Math.floor(req.pageSize) || 50));
|
|
431
467
|
const offset = (page - 1) * pageSize;
|
|
432
468
|
|
|
433
|
-
const where = buildWhere(req.filters);
|
|
469
|
+
const where = buildWhere(req.filters, runtime);
|
|
434
470
|
const orderBy = buildOrderBy(req.sort);
|
|
435
471
|
const quoted = quoteIdent(table);
|
|
436
472
|
|
|
437
|
-
const countRes = await
|
|
473
|
+
const countRes = await client.execute({
|
|
438
474
|
sql: `SELECT COUNT(*) AS c FROM ${quoted}${where.clause}`,
|
|
439
475
|
args: where.args,
|
|
440
476
|
});
|
|
441
477
|
const total = Number((countRes.rows[0] as any)?.c ?? 0) || 0;
|
|
442
478
|
|
|
443
|
-
const rowsRes = await
|
|
479
|
+
const rowsRes = await client.execute({
|
|
444
480
|
sql: `SELECT * FROM ${quoted}${where.clause}${orderBy} LIMIT ? OFFSET ?`,
|
|
445
481
|
args: [...where.args, pageSize, offset],
|
|
446
482
|
});
|
|
@@ -512,6 +548,7 @@ function buildDelete(
|
|
|
512
548
|
export async function applyMutations(
|
|
513
549
|
table: string,
|
|
514
550
|
m: DbAdminMutation,
|
|
551
|
+
runtime?: DbAdminRuntime,
|
|
515
552
|
): Promise<DbAdminMutationResult> {
|
|
516
553
|
assertIdent(table, "table name");
|
|
517
554
|
|
|
@@ -540,13 +577,13 @@ export async function applyMutations(
|
|
|
540
577
|
// sequentially. A failure mid-batch surfaces as a thrown error with the
|
|
541
578
|
// counts accumulated so far; callers should treat a partial batch as a
|
|
542
579
|
// failure and re-run with a corrected payload.
|
|
543
|
-
const
|
|
580
|
+
const client = db(runtime);
|
|
544
581
|
const insertCount = m.inserts?.length ?? 0;
|
|
545
582
|
const updateCount = m.updates?.length ?? 0;
|
|
546
583
|
|
|
547
584
|
let executed = 0;
|
|
548
585
|
for (const stmt of statements) {
|
|
549
|
-
const res = await
|
|
586
|
+
const res = await client.execute({ sql: stmt.sql, args: stmt.args });
|
|
550
587
|
if (executed < insertCount) {
|
|
551
588
|
result.inserted += 1;
|
|
552
589
|
} else if (executed < insertCount + updateCount) {
|
|
@@ -557,7 +594,7 @@ export async function applyMutations(
|
|
|
557
594
|
executed += 1;
|
|
558
595
|
}
|
|
559
596
|
|
|
560
|
-
if (statements.length > 0) await notifyDbAdminChange();
|
|
597
|
+
if (statements.length > 0) await notifyDbAdminChange(runtime);
|
|
561
598
|
return result;
|
|
562
599
|
}
|
|
563
600
|
|
|
@@ -611,6 +648,7 @@ export async function runSql(
|
|
|
611
648
|
sql: string,
|
|
612
649
|
params: unknown[] | undefined,
|
|
613
650
|
opts: { confirmDestructive?: boolean } = {},
|
|
651
|
+
runtime?: DbAdminRuntime,
|
|
614
652
|
): Promise<DbAdminQueryResult> {
|
|
615
653
|
if (typeof sql !== "string" || !sql.trim()) {
|
|
616
654
|
throw new Error("SQL is required");
|
|
@@ -629,9 +667,9 @@ export async function runSql(
|
|
|
629
667
|
finalSql = `${finalSql} LIMIT 100`;
|
|
630
668
|
}
|
|
631
669
|
|
|
632
|
-
const
|
|
670
|
+
const client = db(runtime);
|
|
633
671
|
const started = Date.now();
|
|
634
|
-
const res = await
|
|
672
|
+
const res = await client.execute(
|
|
635
673
|
params && params.length > 0 ? { sql: finalSql, args: params } : finalSql,
|
|
636
674
|
);
|
|
637
675
|
const durationMs = Date.now() - started;
|
|
@@ -642,7 +680,7 @@ export async function runSql(
|
|
|
642
680
|
? Object.keys(rows[0])
|
|
643
681
|
: [];
|
|
644
682
|
|
|
645
|
-
if (isMutatingSql(finalSql)) await notifyDbAdminChange();
|
|
683
|
+
if (isMutatingSql(finalSql)) await notifyDbAdminChange(runtime);
|
|
646
684
|
|
|
647
685
|
return {
|
|
648
686
|
columns,
|
|
@@ -362,6 +362,10 @@ const messages = {
|
|
|
362
362
|
loadErrorTitle: "Couldn't load organization",
|
|
363
363
|
loadErrorFallback: "Couldn't load organization.",
|
|
364
364
|
tryAgain: "Try again",
|
|
365
|
+
sendFeedback: "Send feedback",
|
|
366
|
+
feedbackPlaceholder:
|
|
367
|
+
"Describe what happened before this organization error appeared.",
|
|
368
|
+
openGitHubIssue: "Open GitHub issue",
|
|
365
369
|
yourOrganization: "Your organization",
|
|
366
370
|
joinYourTeam: "Join your team",
|
|
367
371
|
openToDomainEmails: "Open to @{{domain}} emails",
|