743 lines · 24.4 KB · TypeScript
RawDownload
import { createHash, randomUUID } from "node:crypto";import { mkdirSync } from "node:fs";import { dirname, resolve as resolvePath } from "node:path"; import { Database } from "bun:sqlite";import { and, eq } from "drizzle-orm";import { drizzle } from "drizzle-orm/bun-sqlite";import {  integer,  sqliteTable,  text,} from "drizzle-orm/sqlite-core"; import {  createExecutorBackend,  type ExecutorBackend,  type ExecutorBackendRepositories,  type ExecutorWorkspaceConfigRepository,  type ExecutorWorkspaceStateRepository,  type ExecutorWorkspaceSourceArtifactRepository,} from "@executor/platform-sdk";import type {  Execution,  ExecutionInteraction,  ExecutionStep,  LocalExecutorConfig,  LocalInstallation,  SecretMaterial,  SecretRef,  SecretStore,} from "@executor/platform-sdk/schema";import {  ScopeIdSchema,  SecretMaterialIdSchema,  SourceCatalogIdSchema,  SourceCatalogRevisionIdSchema,} from "@executor/platform-sdk/schema";import {  contentHash,  snapshotFromSourceCatalogSyncResult,} from "@executor/source-core"; export type CreateSqliteExecutorBackendOptions = {  databasePath?: string;  scopeName?: string;  scopeRoot?: string | null;  scopeId?: string;  actorScopeId?: string;}; type ScopeConfig = Awaited<ReturnType<ExecutorWorkspaceConfigRepository["load"]>>;type ScopeState = Awaited<ReturnType<ExecutorWorkspaceStateRepository["load"]>>;type SourceArtifact =  ReturnType<ExecutorWorkspaceSourceArtifactRepository["build"]>;type SourceArtifactBuildInput = Parameters<  ExecutorWorkspaceSourceArtifactRepository["build"]>[0]; type SecretMaterialSummary = {  id: string;  storeId: string;  name: string | null;  purpose: string;  createdAt: number;  updatedAt: number;}; type SqliteSecretStoredData = {  value: string;}; const SQLITE_SECRET_STORE_KIND = "sqlite";const SQLITE_SECRET_STORE_ID = "sts_sqlite"; const installations = sqliteTable("installations", {  key: text("key").primaryKey(),  scopeId: text("scope_id").notNull(),  actorScopeId: text("actor_scope_id").notNull(),  resolutionScopeIdsJson: text("resolution_scope_ids_json").notNull(),}); const scopeConfigs = sqliteTable("scope_configs", {  key: text("key").primaryKey(),  projectConfigJson: text("project_config_json").notNull(),}); const scopeStates = sqliteTable("scope_states", {  key: text("key").primaryKey(),  stateJson: text("state_json").notNull(),}); const sourceArtifacts = sqliteTable("source_artifacts", {  sourceId: text("source_id").primaryKey(),  artifactJson: text("artifact_json").notNull(),}); const secretMaterials = sqliteTable("secret_materials", {  id: text("id").primaryKey(),  storeId: text("store_id").notNull(),  name: text("name"),  purpose: text("purpose").notNull(),  createdAt: integer("created_at").notNull(),  updatedAt: integer("updated_at").notNull(),  json: text("json").notNull(),}); const secretMaterialStoredData = sqliteTable("secret_material_stored_data", {  secretId: text("secret_id").primaryKey(),  json: text("json").notNull(),}); const executions = sqliteTable("executions", {  id: text("id").primaryKey(),  scopeId: text("scope_id").notNull(),  json: text("json").notNull(),}); const executionInteractions = sqliteTable("execution_interactions", {  id: text("id").primaryKey(),  executionId: text("execution_id").notNull(),  status: text("status").notNull(),  json: text("json").notNull(),}); const executionSteps = sqliteTable("execution_steps", {  id: text("id").primaryKey(),  executionId: text("execution_id").notNull(),  sequence: integer("sequence").notNull(),  json: text("json").notNull(),}); const makeHash = (value: string): string =>  createHash("sha256").update(value).digest("hex").slice(0, 24); const parseJson = <T>(value: string): T => JSON.parse(value) as T; const createSourceArtifact = (input: SourceArtifactBuildInput): SourceArtifact => {  const snapshot = snapshotFromSourceCatalogSyncResult(input.syncResult);  const sourceConfigJson = JSON.stringify({    kind: input.source.kind,    namespace: input.source.namespace,    name: input.source.name,    enabled: input.source.enabled,  });  const importMetadataJson = JSON.stringify(snapshot.import);  const catalogId = SourceCatalogIdSchema.make(`src_catalog_${makeHash(sourceConfigJson)}`);  const revisionId = SourceCatalogRevisionIdSchema.make(    `src_catalog_rev_${makeHash(sourceConfigJson)}`,  );   return {    version: 4,    sourceId: input.source.id,    catalogId,    generatedAt: Date.now(),    revision: {      id: revisionId,      catalogId,      revisionNumber: 1,      sourceConfigJson,      importMetadataJson,      importMetadataHash: contentHash(importMetadataJson),      snapshotHash: contentHash(JSON.stringify(snapshot)),      createdAt: input.source.createdAt,      updatedAt: input.source.updatedAt,    },    snapshot,  };}; const defaultScopeState = (): ScopeState => ({  version: 1,  sources: {},  policies: {},}); const createInstallation = (  options: CreateSqliteExecutorBackendOptions,): LocalInstallation => {  const scopeId = ScopeIdSchema.make(options.scopeId ?? "scope_sqlite_example");  const actorScopeId = ScopeIdSchema.make(    options.actorScopeId ?? "account_sqlite_example",  );   return {    scopeId,    actorScopeId,    resolutionScopeIds: [scopeId, actorScopeId],  };}; const openSqliteStore = (databasePath: string) => {  if (databasePath !== ":memory:") {    mkdirSync(dirname(databasePath), { recursive: true });  }   const sqlite = new Database(databasePath, { create: true, strict: true });  const db = drizzle(sqlite);   sqlite.exec(`      CREATE TABLE IF NOT EXISTS installations (        key TEXT PRIMARY KEY NOT NULL,        scope_id TEXT NOT NULL,        actor_scope_id TEXT NOT NULL,        resolution_scope_ids_json TEXT NOT NULL      );       CREATE TABLE IF NOT EXISTS scope_configs (        key TEXT PRIMARY KEY NOT NULL,        project_config_json TEXT NOT NULL      );       CREATE TABLE IF NOT EXISTS scope_states (        key TEXT PRIMARY KEY NOT NULL,        state_json TEXT NOT NULL      );       CREATE TABLE IF NOT EXISTS source_artifacts (        source_id TEXT PRIMARY KEY NOT NULL,        artifact_json TEXT NOT NULL      );       CREATE TABLE IF NOT EXISTS secret_materials (        id TEXT PRIMARY KEY NOT NULL,        store_id TEXT NOT NULL,        name TEXT,        purpose TEXT NOT NULL,        created_at INTEGER NOT NULL,        updated_at INTEGER NOT NULL,        json TEXT NOT NULL      );       CREATE TABLE IF NOT EXISTS secret_material_stored_data (        secret_id TEXT PRIMARY KEY NOT NULL,        json TEXT NOT NULL      );       CREATE TABLE IF NOT EXISTS executions (        id TEXT PRIMARY KEY NOT NULL,        scope_id TEXT NOT NULL,        json TEXT NOT NULL      );       CREATE TABLE IF NOT EXISTS execution_interactions (        id TEXT PRIMARY KEY NOT NULL,        execution_id TEXT NOT NULL,        status TEXT NOT NULL,        json TEXT NOT NULL      );       CREATE TABLE IF NOT EXISTS execution_steps (        id TEXT PRIMARY KEY NOT NULL,        execution_id TEXT NOT NULL,        sequence INTEGER NOT NULL,        json TEXT NOT NULL      );    `);   return {    sqlite,    db,    close: () => {      sqlite.close();    },  };}; type SqliteStore = ReturnType<typeof openSqliteStore>; const createStorageDomains = (  store: SqliteStore,  installation: LocalInstallation,) => ({  secrets: {    secretStores: {      getById: (id: SecretStore["id"]) =>        id === SQLITE_SECRET_STORE_ID          ? {              id: SQLITE_SECRET_STORE_ID as SecretStore["id"],              scopeId: installation.scopeId,              kind: SQLITE_SECRET_STORE_KIND,              name: "SQLite Store",              status: "connected" as const,              enabled: true,              createdAt: 0,              updatedAt: 0,            }          : null,      listAll: () => [{        id: SQLITE_SECRET_STORE_ID,        scopeId: installation.scopeId,        kind: SQLITE_SECRET_STORE_KIND,        name: "SQLite Store",        status: "connected",        enabled: true,        createdAt: 0,        updatedAt: 0,      }],      upsert: (_secretStore: SecretStore) => {},      updateById: (_id: SecretStore["id"], _update: Partial<Pick<SecretStore, "name" | "status" | "enabled">>) => null,      removeById: (_id: SecretStore["id"]) => false,    },    getById: (id: SecretMaterial["id"]) => {      const row = store.db.select().from(secretMaterials).where(eq(secretMaterials.id, id)).get();      return row ? parseJson<SecretMaterial>(row.json) : null;    },    listAll: (): readonly SecretMaterialSummary[] =>      store.db.select().from(secretMaterials).all().map((row) => ({        id: row.id,        storeId: row.storeId,        name: row.name,        purpose: row.purpose,        createdAt: row.createdAt,        updatedAt: row.updatedAt,      })),    upsert: (material: SecretMaterial) =>      store.db.insert(secretMaterials).values({        id: material.id,        storeId: material.storeId,        name: material.name,        purpose: material.purpose,        createdAt: material.createdAt,        updatedAt: material.updatedAt,        json: JSON.stringify(material),      }).onConflictDoUpdate({        target: secretMaterials.id,        set: {          storeId: material.storeId,          name: material.name,          purpose: material.purpose,          createdAt: material.createdAt,          updatedAt: material.updatedAt,          json: JSON.stringify(material),        },      }).run(),    updateById: (      id: SecretMaterial["id"],      update: { name?: string | null },    ) => {      const row = store.db.select().from(secretMaterials).where(eq(secretMaterials.id, id)).get();      if (!row) return null;      const current = parseJson<SecretMaterial>(row.json);      const next = {        ...current,        name: update.name === undefined ? current.name : update.name,        updatedAt: Date.now(),      };      store.db.update(secretMaterials).set({        storeId: next.storeId,        name: next.name,        purpose: next.purpose,        createdAt: next.createdAt,        updatedAt: next.updatedAt,        json: JSON.stringify(next),      }).where(eq(secretMaterials.id, id)).run();      return {        id: next.id,        storeId: next.storeId,        name: next.name,        purpose: next.purpose,        createdAt: next.createdAt,        updatedAt: next.updatedAt,      } satisfies SecretMaterialSummary;    },    removeById: (id: SecretMaterial["id"]) => {      const row = store.db.select({ id: secretMaterials.id }).from(secretMaterials).where(        eq(secretMaterials.id, id),      ).get();      if (!row) return false;      store.db.delete(secretMaterials).where(eq(secretMaterials.id, id)).run();      return true;    },    secretMaterialStoredData: {      getBySecretId: (secretId: SecretMaterial["id"]) => {        const row = store.db.select().from(secretMaterialStoredData).where(          eq(secretMaterialStoredData.secretId, secretId),        ).get();        return row          ? {              secretId,              data: parseJson<SqliteSecretStoredData>(row.json),            }          : null;      },      upsert: (record: { secretId: SecretMaterial["id"]; data: unknown }) => {        store.db.insert(secretMaterialStoredData).values({          secretId: record.secretId,          json: JSON.stringify(record.data),        }).onConflictDoUpdate({          target: secretMaterialStoredData.secretId,          set: {            json: JSON.stringify(record.data),          },        }).run();      },      removeBySecretId: (secretId: SecretMaterial["id"]) => {        const row = store.db.select({ secretId: secretMaterialStoredData.secretId }).from(          secretMaterialStoredData,        ).where(eq(secretMaterialStoredData.secretId, secretId)).get();        if (!row) return false;        store.db.delete(secretMaterialStoredData).where(          eq(secretMaterialStoredData.secretId, secretId),        ).run();        return true;      },    },  },  executions: {    runs: {    listByScope: (scopeId: Execution["scopeId"]) =>      store.db.select().from(executions).where(        eq(executions.scopeId, scopeId),      ).all()        .map((row) => parseJson<Execution>(row.json))        .sort((left, right) => right.createdAt - left.createdAt),    getById: (executionId: Execution["id"]) => {      const row = store.db.select().from(executions).where(eq(executions.id, executionId)).get();      return row ? parseJson<Execution>(row.json) : null;    },    getByScopeAndId: (      scopeId: Execution["scopeId"],      executionId: Execution["id"],    ) => {      const row = store.db.select().from(executions).where(        and(eq(executions.scopeId, scopeId), eq(executions.id, executionId)),      ).get();      return row ? parseJson<Execution>(row.json) : null;    },    insert: (execution: Execution) =>      store.db.insert(executions).values({        id: execution.id,        scopeId: execution.scopeId,        json: JSON.stringify(execution),      }).run(),    update: (      executionId: Execution["id"],      patch: Partial<Omit<Execution, "id" | "scopeId" | "createdByScopeId" | "createdAt">>,    ) => {      const row = store.db.select().from(executions).where(eq(executions.id, executionId)).get();      if (!row) return null;      const next = { ...parseJson<Execution>(row.json), ...patch };      store.db.update(executions).set({        scopeId: next.scopeId,        json: JSON.stringify(next),      }).where(eq(executions.id, executionId)).run();      return next;    },  },    interactions: {    getById: (interactionId: ExecutionInteraction["id"]) => {      const row = store.db.select().from(executionInteractions).where(        eq(executionInteractions.id, interactionId),      ).get();      return row ? parseJson<ExecutionInteraction>(row.json) : null;    },    listByExecutionId: (executionId: ExecutionInteraction["executionId"]) =>      store.db.select().from(executionInteractions).where(        eq(executionInteractions.executionId, executionId),      ).all().map((row) => parseJson<ExecutionInteraction>(row.json)),    getPendingByExecutionId: (executionId: ExecutionInteraction["executionId"]) => {      const row = store.db.select().from(executionInteractions).where(        and(          eq(executionInteractions.executionId, executionId),          eq(executionInteractions.status, "pending"),        ),      ).get();      return row ? parseJson<ExecutionInteraction>(row.json) : null;    },    insert: (interaction: ExecutionInteraction) =>      store.db.insert(executionInteractions).values({        id: interaction.id,        executionId: interaction.executionId,        status: interaction.status,        json: JSON.stringify(interaction),      }).run(),    update: (      interactionId: ExecutionInteraction["id"],      patch: Partial<Omit<ExecutionInteraction, "id" | "executionId" | "createdAt">>,    ) => {      const row = store.db.select().from(executionInteractions).where(        eq(executionInteractions.id, interactionId),      ).get();      if (!row) return null;      const next = { ...parseJson<ExecutionInteraction>(row.json), ...patch };      store.db.update(executionInteractions).set({        executionId: next.executionId,        status: next.status,        json: JSON.stringify(next),      }).where(eq(executionInteractions.id, interactionId)).run();      return next;    },  },    steps: {    getByExecutionAndSequence: (      executionId: ExecutionStep["executionId"],      sequence: ExecutionStep["sequence"],    ) => {      const row = store.db.select().from(executionSteps).where(        and(          eq(executionSteps.executionId, executionId),

Lines 1–500 of 743.