feat: complete catalog-driven preprocessing
Publish documentation / publish (push) Successful in 2m12s
Publish documentation / publish (push) Successful in 2m12s
This commit is contained in:
@@ -1,5 +1,3 @@
|
||||
import { buildInstallationContract } from "../workspaces/contracts.js";
|
||||
import { resolveBinding } from "../workspaces/bindings.js";
|
||||
import type { WorkspaceRegistry } from "../workspaces/registry.js";
|
||||
import type { WorkspaceDescriptor } from "../workspaces/schema.js";
|
||||
import { discoverWorkspaceSecretRequirements } from "../workspaces/secret-requirements.js";
|
||||
@@ -45,60 +43,33 @@ export interface CatalogListItem extends Omit<WorkspaceDatabase, "id"> {
|
||||
secrets: Record<CatalogSecretName, boolean>;
|
||||
}
|
||||
|
||||
function bindingValue(workspace: WorkspaceDescriptor, values: Record<string, string>, suffix: string) {
|
||||
const variable = buildInstallationContract(workspace).variables.find((entry) => (
|
||||
entry.role === "DWH" && entry.suffix === suffix
|
||||
));
|
||||
return variable ? values[variable.name] : undefined;
|
||||
}
|
||||
|
||||
function numeric(value: string | undefined): number | undefined {
|
||||
if (!value) return undefined;
|
||||
const parsed = Number(value);
|
||||
return Number.isInteger(parsed) && parsed >= 1 && parsed <= 65_535 ? parsed : undefined;
|
||||
}
|
||||
|
||||
function yamlBinding(workspace: WorkspaceDescriptor, secretRoots: readonly string[]): DatabaseBinding {
|
||||
const effective = resolveBinding(workspace, "DWH", process.env, secretRoots);
|
||||
const value = (suffix: string) => bindingValue(workspace, effective.values, suffix);
|
||||
return {
|
||||
transport: effective.transport,
|
||||
host: value("HOST"),
|
||||
port: numeric(value("PORT")) ?? workspace.dwh.port,
|
||||
username: value("USER"),
|
||||
baseUrl: value("BASE_URL"),
|
||||
restPath: workspace.diagnostics?.dwh_rest?.path ?? "/health",
|
||||
restAuth: workspace.diagnostics?.dwh_rest?.auth ?? "bearer",
|
||||
tlsServername: value("TLS_SERVERNAME"),
|
||||
sshHost: value("SSH_HOST"),
|
||||
sshPort: numeric(value("SSH_PORT")),
|
||||
sshUsername: value("SSH_USER"),
|
||||
sshTargetHost: value("SSH_TARGET_HOST"),
|
||||
sshTargetPort: numeric(value("SSH_TARGET_PORT")),
|
||||
};
|
||||
}
|
||||
|
||||
function secretState(store: WorkspaceSecretStore, workspaceId: string): Record<CatalogSecretName, boolean> {
|
||||
return Object.fromEntries(Object.entries(CATALOG_SECRET_IDS).map(([name, id]) => (
|
||||
[name, store.has(workspaceId, id)]
|
||||
))) as Record<CatalogSecretName, boolean>;
|
||||
}
|
||||
|
||||
function workspaceRuntimeState(
|
||||
function databaseRuntimeState(
|
||||
store: WorkspaceSecretStore,
|
||||
workspace: WorkspaceDescriptor,
|
||||
secretRoots: readonly string[],
|
||||
database: WorkspaceDatabase,
|
||||
): NonNullable<CatalogListItem["runtimeBinding"]> {
|
||||
const requirements = discoverWorkspaceSecretRequirements(workspace, process.env);
|
||||
const secretVariables = new Set(requirements.map(({ variable }) => variable));
|
||||
const effective = resolveBinding(workspace, "DWH", process.env, secretRoots);
|
||||
const configurationRequired = requirements.some(({ id, required }) => (
|
||||
required && !store.has(workspace.workspace.id, id)
|
||||
)) || effective.missing.some((variable) => !secretVariables.has(variable));
|
||||
const { binding, workspaceId } = database;
|
||||
const configured = (id: string) => store.has(workspaceId, id);
|
||||
const connectionComplete = binding.transport === "postgres_direct"
|
||||
? Boolean(binding.host && binding.port && binding.username && configured(CATALOG_SECRET_IDS.password))
|
||||
: binding.transport === "rest_api"
|
||||
? Boolean(binding.baseUrl && (binding.restAuth === "none" || configured(CATALOG_SECRET_IDS.apiKey)))
|
||||
: Boolean(
|
||||
binding.username && binding.sshHost && binding.sshPort && binding.sshUsername
|
||||
&& binding.sshTargetHost && binding.sshTargetPort
|
||||
&& configured(CATALOG_SECRET_IDS.password)
|
||||
&& configured(CATALOG_SECRET_IDS.sshPrivateKey)
|
||||
&& configured(CATALOG_SECRET_IDS.sshKnownHosts),
|
||||
);
|
||||
return {
|
||||
transport: effective.transport,
|
||||
configurationState: configurationRequired ? "configuration_required" : "ready",
|
||||
sessionTransportSupported: effective.transport !== "ssh_tunnel",
|
||||
transport: binding.transport,
|
||||
configurationState: connectionComplete ? "ready" : "configuration_required",
|
||||
sessionTransportSupported: binding.transport !== "ssh_tunnel",
|
||||
};
|
||||
}
|
||||
|
||||
@@ -145,17 +116,18 @@ export class CatalogService {
|
||||
const active = await Promise.all(workspaces.map(async (entry) => {
|
||||
const database = byWorkspace.get(entry.id);
|
||||
const { workspace } = await this.registry.readPinned(entry.id, entry.revision.commit);
|
||||
const runtimeDatabaseBinding = yamlBinding(workspace, this.secretRoots);
|
||||
const base = database ?? {
|
||||
workspaceId: entry.id,
|
||||
engine: "postgres" as const,
|
||||
databaseName: workspace.dwh.database,
|
||||
schema: workspace.dwh.schema,
|
||||
databaseName: "",
|
||||
schema: "",
|
||||
version: 0,
|
||||
createdAt: "",
|
||||
updatedAt: "",
|
||||
binding: runtimeDatabaseBinding,
|
||||
binding: { transport: "postgres_direct" as const },
|
||||
connectionStatus: "untested" as const,
|
||||
metadataContentRevision: 0,
|
||||
preprocessingStatus: "failed" as const,
|
||||
};
|
||||
return {
|
||||
...base,
|
||||
@@ -167,7 +139,7 @@ export class CatalogService {
|
||||
blob: entry.revision.blob,
|
||||
},
|
||||
workspaceEvidence: workspaceEvidenceState(this.secretStore, workspace),
|
||||
runtimeBinding: workspaceRuntimeState(this.secretStore, workspace, this.secretRoots),
|
||||
runtimeBinding: database ? databaseRuntimeState(this.secretStore, database) : null,
|
||||
configured: database !== undefined,
|
||||
secrets: secretState(this.secretStore, entry.id),
|
||||
};
|
||||
@@ -195,13 +167,13 @@ export class CatalogService {
|
||||
}
|
||||
|
||||
async normalizeInput(input: DatabaseConfigurationInput): Promise<DatabaseConfigurationInput> {
|
||||
const workspace = await this.ensureWorkspace(input.workspaceId);
|
||||
await this.ensureWorkspace(input.workspaceId);
|
||||
if (input.binding.transport !== "rest_api") return input;
|
||||
return {
|
||||
...input,
|
||||
binding: {
|
||||
...input.binding,
|
||||
restPath: workspace.diagnostics?.dwh_rest?.path ?? "/health",
|
||||
restPath: input.binding.restPath ?? "/health",
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user