chore: preserve database management prototype
This commit is contained in:
@@ -0,0 +1,134 @@
|
||||
import path from "path";
|
||||
import { execFileSync } from "node:child_process";
|
||||
import react from "@vitejs/plugin-react";
|
||||
import { defineConfig, type Plugin } from "vite";
|
||||
|
||||
const CATALOG_CONTAINER = process.env.THT_PROTOTYPE_CATALOG_CONTAINER
|
||||
?? "thothii-catalog-db-1";
|
||||
|
||||
const LIVE_CATALOG_SQL = String.raw`
|
||||
select json_build_object(
|
||||
'capturedAt', now(),
|
||||
'databases', coalesce((select json_agg(json_build_object(
|
||||
'id', wd.id, 'workspaceId', wd.workspace_id, 'engine', wd.engine,
|
||||
'databaseName', wd.database_name, 'schemaName', wd.schema_name,
|
||||
'version', wd.version, 'schemaSyncedVersion', wd.schema_synced_version,
|
||||
'schemaSyncedAt', wd.schema_synced_at, 'updatedAt', wd.updated_at,
|
||||
'transport', b.transport, 'host', b.host, 'port', b.port,
|
||||
'baseUrl', b.base_url, 'restPath', b.rest_path,
|
||||
'connectionStatus', b.connection_status, 'testedVersion', b.tested_version,
|
||||
'lastTestedAt', b.last_tested_at
|
||||
) order by wd.workspace_id) from workspace_databases wd left join database_bindings b on b.database_id = wd.id), '[]'::json),
|
||||
'tables', coalesce((select json_agg(json_build_object(
|
||||
'id', t.id, 'databaseId', t.database_id, 'name', t.name,
|
||||
'sourceComment', t.source_comment, 'description', t.description,
|
||||
'generatedDescription', t.generated_description, 'version', t.version,
|
||||
'lastSyncedAt', t.last_synced_at
|
||||
) order by t.name) from catalog_tables t), '[]'::json),
|
||||
'columns', coalesce((select json_agg(json_build_object(
|
||||
'id', c.id, 'tableId', c.table_id, 'name', c.name,
|
||||
'ordinalPosition', c.ordinal_position, 'dataType', c.data_type,
|
||||
'isNullable', c.is_nullable, 'defaultExpression', c.default_expression,
|
||||
'primaryKeyPosition', c.primary_key_position, 'sourceComment', c.source_comment,
|
||||
'description', c.description, 'generatedDescription', c.generated_description,
|
||||
'sensitive', c.sensitive, 'lastSyncedAt', c.last_synced_at, 'version', c.version
|
||||
) order by c.table_id, c.ordinal_position) from catalog_columns c), '[]'::json),
|
||||
'relationships', coalesce((select json_agg(json_build_object(
|
||||
'id', r.id, 'databaseId', r.database_id, 'constraintName', r.constraint_name,
|
||||
'sourceTableName', st.name, 'targetTableName', tt.name,
|
||||
'updateRule', r.update_rule, 'deleteRule', r.delete_rule
|
||||
) order by r.constraint_name) from catalog_relationships r
|
||||
join catalog_tables st on st.id = r.source_table_id
|
||||
join catalog_tables tt on tt.id = r.target_table_id), '[]'::json),
|
||||
'relationshipColumns', coalesce((select json_agg(json_build_object(
|
||||
'relationshipId', rc.relationship_id, 'ordinalPosition', rc.position,
|
||||
'sourceColumnName', sc.name, 'targetColumnName', tc.name
|
||||
) order by rc.relationship_id, rc.position) from catalog_relationship_columns rc
|
||||
join catalog_columns sc on sc.id = rc.source_column_id
|
||||
join catalog_columns tc on tc.id = rc.target_column_id), '[]'::json),
|
||||
'syncRuns', coalesce((select json_agg(json_build_object(
|
||||
'id', r.id, 'databaseId', r.database_id, 'scope', r.scope,
|
||||
'state', r.state, 'phase', r.phase, 'counts', r.counts,
|
||||
'plannedDiff', r.planned_diff, 'errorCode', r.error_code,
|
||||
'errorMessage', r.error_message, 'createdAt', r.created_at,
|
||||
'startedAt', r.started_at, 'finishedAt', r.finished_at
|
||||
) order by r.created_at desc) from (select * from catalog_sync_runs order by created_at desc limit 50) r), '[]'::json),
|
||||
'syncEvents', coalesce((select json_agg(json_build_object(
|
||||
'runId', e.run_id, 'sequence', e.sequence, 'level', e.level,
|
||||
'message', e.message, 'createdAt', e.created_at
|
||||
) order by e.created_at desc) from (select * from catalog_sync_events order by created_at desc limit 300) e), '[]'::json),
|
||||
'descriptionRuns', coalesce((select json_agg(json_build_object(
|
||||
'id', r.id, 'databaseId', r.database_id, 'scope', r.scope,
|
||||
'modelId', r.model_id, 'language', r.language, 'status', r.status,
|
||||
'total', r.total, 'processed', r.processed, 'generated', r.generated,
|
||||
'nonGeneratable', r.non_generatable, 'failed', r.failed,
|
||||
'createdAt', r.created_at, 'startedAt', r.started_at,
|
||||
'finishedAt', r.finished_at, 'errorSummary', r.error_summary
|
||||
) order by r.created_at desc) from (select * from description_generation_runs order by created_at desc limit 50) r), '[]'::json),
|
||||
'descriptionEvents', coalesce((select json_agg(json_build_object(
|
||||
'runId', e.run_id, 'sequence', e.sequence, 'level', e.level,
|
||||
'message', e.message, 'createdAt', e.created_at
|
||||
) order by e.created_at desc) from (select * from description_generation_events order by created_at desc limit 300) e), '[]'::json),
|
||||
'sensitiveRuns', coalesce((select json_agg(json_build_object(
|
||||
'id', r.id, 'databaseId', r.database_id, 'scope', r.scope,
|
||||
'modelId', r.model_id, 'status', r.status, 'total', r.total,
|
||||
'suggestedSensitive', r.suggested_sensitive,
|
||||
'suggestedNonSensitive', r.suggested_non_sensitive,
|
||||
'createdAt', r.created_at, 'startedAt', r.started_at,
|
||||
'finishedAt', r.finished_at, 'errorSummary', r.error_summary
|
||||
) order by r.created_at desc) from (select * from sensitive_data_suggestion_runs order by created_at desc limit 50) r), '[]'::json),
|
||||
'sensitiveEvents', coalesce((select json_agg(json_build_object(
|
||||
'runId', e.run_id, 'sequence', e.sequence, 'level', e.level,
|
||||
'message', e.message, 'createdAt', e.created_at
|
||||
) order by e.created_at desc) from (select * from sensitive_data_suggestion_events order by created_at desc limit 300) e), '[]'::json)
|
||||
)::text;
|
||||
`;
|
||||
|
||||
function liveCatalogPlugin(): Plugin {
|
||||
return {
|
||||
name: "database-management-prototype-live-catalog",
|
||||
configureServer(server) {
|
||||
server.middlewares.use("/__prototype/catalog-snapshot", (_request, response) => {
|
||||
try {
|
||||
const payload = execFileSync("docker", [
|
||||
"exec",
|
||||
"--env",
|
||||
`THT_PROTOTYPE_SQL=${LIVE_CATALOG_SQL}`,
|
||||
CATALOG_CONTAINER,
|
||||
"sh",
|
||||
"-lc",
|
||||
'psql -U "$POSTGRES_USER" -d "$POSTGRES_DB" -Atc "$THT_PROTOTYPE_SQL"',
|
||||
], { encoding: "utf8", maxBuffer: 32 * 1024 * 1024 }).trim();
|
||||
response.statusCode = 200;
|
||||
response.setHeader("Content-Type", "application/json; charset=utf-8");
|
||||
response.setHeader("Cache-Control", "no-store");
|
||||
response.end(payload);
|
||||
} catch (error) {
|
||||
response.statusCode = 503;
|
||||
response.setHeader("Content-Type", "application/json; charset=utf-8");
|
||||
response.end(JSON.stringify({
|
||||
error: "live_catalog_unavailable",
|
||||
detail: error instanceof Error ? error.message.split("\n")[0] : "Unknown error",
|
||||
}));
|
||||
}
|
||||
});
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export default defineConfig(({ command }) => {
|
||||
if (command !== "serve") {
|
||||
throw new Error("The database-management prototype is dev-only. Run npm run prototype:database-management.");
|
||||
}
|
||||
|
||||
return {
|
||||
root: path.resolve(__dirname, "prototypes/database-management"),
|
||||
plugins: [react(), liveCatalogPlugin()],
|
||||
appType: "spa",
|
||||
server: {
|
||||
host: "127.0.0.1",
|
||||
port: 5173,
|
||||
strictPort: true,
|
||||
},
|
||||
};
|
||||
});
|
||||
Reference in New Issue
Block a user