refactor(core): simplify integration credentials (#31968)
This commit is contained in:
parent
a9c810cbbc
commit
30aec297d8
112 changed files with 2467 additions and 47728 deletions
1
packages/core/src/database/migration.gen.ts
generated
1
packages/core/src/database/migration.gen.ts
generated
|
|
@ -35,5 +35,6 @@ export const migrations = (
|
|||
import("./migration/20260605003541_add_session_context_snapshot"),
|
||||
import("./migration/20260605042240_add_context_epoch_agent"),
|
||||
import("./migration/20260611035744_credential"),
|
||||
import("./migration/20260611192811_lush_chimera"),
|
||||
])
|
||||
).map((module) => module.default) satisfies DatabaseMigration.Migration[]
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import { sql } from "drizzle-orm"
|
|||
import { Effect, Semaphore } from "effect"
|
||||
import type { EffectDrizzleSqlite } from "@opencode-ai/effect-drizzle-sqlite"
|
||||
import { migrations } from "./migration.gen"
|
||||
import schema from "./schema.gen"
|
||||
|
||||
type Database = EffectDrizzleSqlite.EffectSQLiteDatabase
|
||||
type Transaction = Parameters<Parameters<Database["transaction"]>[0]>[0]
|
||||
|
|
@ -15,7 +16,28 @@ export type Migration = {
|
|||
}
|
||||
|
||||
export function apply(db: Database) {
|
||||
return lock.withPermit(applyOnly(db, migrations))
|
||||
return lock.withPermit(
|
||||
Effect.gen(function* () {
|
||||
const tables = yield* db.all<{ name: string }>(
|
||||
sql`SELECT name FROM sqlite_master WHERE type = 'table' AND name NOT LIKE 'sqlite_%'`,
|
||||
)
|
||||
if (tables.some((table) => table.name === "session")) return yield* applyOnly(db, migrations)
|
||||
if (tables.length > 0) return yield* Effect.die("Database is not empty and has no session table")
|
||||
yield* db.transaction((tx) =>
|
||||
Effect.gen(function* () {
|
||||
yield* schema.up(tx)
|
||||
yield* tx.run(
|
||||
sql`CREATE TABLE ${sql.identifier("migration")} (id TEXT PRIMARY KEY, time_completed INTEGER NOT NULL)`,
|
||||
)
|
||||
yield* Effect.forEach(migrations, (migration) =>
|
||||
tx.run(
|
||||
sql`INSERT INTO ${sql.identifier("migration")} (id, time_completed) VALUES (${migration.id}, ${Date.now()})`,
|
||||
),
|
||||
)
|
||||
}),
|
||||
)
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
export function applyOnly(db: Database, input: Migration[]) {
|
||||
|
|
@ -48,7 +70,7 @@ export function applyOnly(db: Database, input: Migration[]) {
|
|||
if (completed.has(migration.id)) continue
|
||||
yield* db.transaction((tx) =>
|
||||
Effect.gen(function* () {
|
||||
if (!process.env.OPENCODE_SKIP_MIGRATIONS) yield* migration.up(tx)
|
||||
yield* migration.up(tx)
|
||||
yield* tx.run(
|
||||
sql`INSERT INTO ${sql.identifier("migration")} (id, time_completed) VALUES (${migration.id}, ${Date.now()})`,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,15 @@
|
|||
import { Effect } from "effect"
|
||||
import type { DatabaseMigration } from "../migration"
|
||||
|
||||
export default {
|
||||
id: "20260611192811_lush_chimera",
|
||||
up(tx) {
|
||||
return Effect.gen(function* () {
|
||||
yield* tx.run(`ALTER TABLE \`credential\` ADD \`integration_id\` text NOT NULL;`)
|
||||
yield* tx.run(`DROP INDEX IF EXISTS \`credential_connector_active_idx\`;`)
|
||||
yield* tx.run(`ALTER TABLE \`credential\` DROP COLUMN \`connector_id\`;`)
|
||||
yield* tx.run(`ALTER TABLE \`credential\` DROP COLUMN \`method_id\`;`)
|
||||
yield* tx.run(`ALTER TABLE \`credential\` DROP COLUMN \`active\`;`)
|
||||
})
|
||||
},
|
||||
} satisfies DatabaseMigration.Migration
|
||||
257
packages/core/src/database/schema.gen.ts
Normal file
257
packages/core/src/database/schema.gen.ts
Normal file
|
|
@ -0,0 +1,257 @@
|
|||
import { Effect } from "effect"
|
||||
import type { DatabaseMigration } from "./migration"
|
||||
|
||||
export default {
|
||||
up(tx) {
|
||||
return Effect.gen(function* () {
|
||||
yield* tx.run(`
|
||||
CREATE TABLE \`workspace\` (
|
||||
\`id\` text PRIMARY KEY,
|
||||
\`type\` text NOT NULL,
|
||||
\`name\` text DEFAULT '' NOT NULL,
|
||||
\`branch\` text,
|
||||
\`directory\` text,
|
||||
\`extra\` text,
|
||||
\`project_id\` text NOT NULL,
|
||||
\`time_used\` integer NOT NULL,
|
||||
CONSTRAINT \`fk_workspace_project_id_project_id_fk\` FOREIGN KEY (\`project_id\`) REFERENCES \`project\`(\`id\`) ON DELETE CASCADE
|
||||
);
|
||||
`)
|
||||
yield* tx.run(`
|
||||
CREATE TABLE \`data_migration\` (
|
||||
\`name\` text PRIMARY KEY,
|
||||
\`time_completed\` integer NOT NULL
|
||||
);
|
||||
`)
|
||||
yield* tx.run(`
|
||||
CREATE TABLE \`account_state\` (
|
||||
\`id\` integer PRIMARY KEY,
|
||||
\`active_account_id\` text,
|
||||
\`active_org_id\` text,
|
||||
CONSTRAINT \`fk_account_state_active_account_id_account_id_fk\` FOREIGN KEY (\`active_account_id\`) REFERENCES \`account\`(\`id\`) ON DELETE SET NULL
|
||||
);
|
||||
`)
|
||||
yield* tx.run(`
|
||||
CREATE TABLE \`account\` (
|
||||
\`id\` text PRIMARY KEY,
|
||||
\`email\` text NOT NULL,
|
||||
\`url\` text NOT NULL,
|
||||
\`access_token\` text NOT NULL,
|
||||
\`refresh_token\` text NOT NULL,
|
||||
\`token_expiry\` integer,
|
||||
\`time_created\` integer NOT NULL,
|
||||
\`time_updated\` integer NOT NULL
|
||||
);
|
||||
`)
|
||||
yield* tx.run(`
|
||||
CREATE TABLE \`control_account\` (
|
||||
\`email\` text NOT NULL,
|
||||
\`url\` text NOT NULL,
|
||||
\`access_token\` text NOT NULL,
|
||||
\`refresh_token\` text NOT NULL,
|
||||
\`token_expiry\` integer,
|
||||
\`active\` integer NOT NULL,
|
||||
\`time_created\` integer NOT NULL,
|
||||
\`time_updated\` integer NOT NULL,
|
||||
CONSTRAINT \`control_account_pk\` PRIMARY KEY(\`email\`, \`url\`)
|
||||
);
|
||||
`)
|
||||
yield* tx.run(`
|
||||
CREATE TABLE \`credential\` (
|
||||
\`id\` text PRIMARY KEY,
|
||||
\`integration_id\` text NOT NULL,
|
||||
\`label\` text NOT NULL,
|
||||
\`value\` text NOT NULL,
|
||||
\`time_created\` integer NOT NULL,
|
||||
\`time_updated\` integer NOT NULL
|
||||
);
|
||||
`)
|
||||
yield* tx.run(`
|
||||
CREATE TABLE \`event_sequence\` (
|
||||
\`aggregate_id\` text PRIMARY KEY,
|
||||
\`seq\` integer NOT NULL,
|
||||
\`owner_id\` text
|
||||
);
|
||||
`)
|
||||
yield* tx.run(`
|
||||
CREATE TABLE \`event\` (
|
||||
\`id\` text PRIMARY KEY,
|
||||
\`aggregate_id\` text NOT NULL,
|
||||
\`seq\` integer NOT NULL,
|
||||
\`type\` text NOT NULL,
|
||||
\`data\` text NOT NULL,
|
||||
CONSTRAINT \`fk_event_aggregate_id_event_sequence_aggregate_id_fk\` FOREIGN KEY (\`aggregate_id\`) REFERENCES \`event_sequence\`(\`aggregate_id\`) ON DELETE CASCADE
|
||||
);
|
||||
`)
|
||||
yield* tx.run(`
|
||||
CREATE TABLE \`permission\` (
|
||||
\`id\` text PRIMARY KEY,
|
||||
\`project_id\` text NOT NULL,
|
||||
\`action\` text NOT NULL,
|
||||
\`resource\` text NOT NULL,
|
||||
\`time_created\` integer NOT NULL,
|
||||
\`time_updated\` integer NOT NULL,
|
||||
CONSTRAINT \`fk_permission_project_id_project_id_fk\` FOREIGN KEY (\`project_id\`) REFERENCES \`project\`(\`id\`) ON DELETE CASCADE
|
||||
);
|
||||
`)
|
||||
yield* tx.run(`
|
||||
CREATE TABLE \`project_directory\` (
|
||||
\`project_id\` text NOT NULL,
|
||||
\`directory\` text NOT NULL,
|
||||
\`type\` text NOT NULL,
|
||||
\`time_created\` integer NOT NULL,
|
||||
CONSTRAINT \`project_directory_pk\` PRIMARY KEY(\`project_id\`, \`directory\`),
|
||||
CONSTRAINT \`fk_project_directory_project_id_project_id_fk\` FOREIGN KEY (\`project_id\`) REFERENCES \`project\`(\`id\`) ON DELETE CASCADE
|
||||
);
|
||||
`)
|
||||
yield* tx.run(`
|
||||
CREATE TABLE \`project\` (
|
||||
\`id\` text PRIMARY KEY,
|
||||
\`worktree\` text NOT NULL,
|
||||
\`vcs\` text,
|
||||
\`name\` text,
|
||||
\`icon_url\` text,
|
||||
\`icon_url_override\` text,
|
||||
\`icon_color\` text,
|
||||
\`time_created\` integer NOT NULL,
|
||||
\`time_updated\` integer NOT NULL,
|
||||
\`time_initialized\` integer,
|
||||
\`sandboxes\` text NOT NULL,
|
||||
\`commands\` text
|
||||
);
|
||||
`)
|
||||
yield* tx.run(`
|
||||
CREATE TABLE \`message\` (
|
||||
\`id\` text PRIMARY KEY,
|
||||
\`session_id\` text NOT NULL,
|
||||
\`time_created\` integer NOT NULL,
|
||||
\`time_updated\` integer NOT NULL,
|
||||
\`data\` text NOT NULL,
|
||||
CONSTRAINT \`fk_message_session_id_session_id_fk\` FOREIGN KEY (\`session_id\`) REFERENCES \`session\`(\`id\`) ON DELETE CASCADE
|
||||
);
|
||||
`)
|
||||
yield* tx.run(`
|
||||
CREATE TABLE \`part\` (
|
||||
\`id\` text PRIMARY KEY,
|
||||
\`message_id\` text NOT NULL,
|
||||
\`session_id\` text NOT NULL,
|
||||
\`time_created\` integer NOT NULL,
|
||||
\`time_updated\` integer NOT NULL,
|
||||
\`data\` text NOT NULL,
|
||||
CONSTRAINT \`fk_part_message_id_message_id_fk\` FOREIGN KEY (\`message_id\`) REFERENCES \`message\`(\`id\`) ON DELETE CASCADE
|
||||
);
|
||||
`)
|
||||
yield* tx.run(`
|
||||
CREATE TABLE \`session_context_epoch\` (
|
||||
\`session_id\` text PRIMARY KEY,
|
||||
\`baseline\` text NOT NULL,
|
||||
\`agent\` text DEFAULT 'build' NOT NULL,
|
||||
\`snapshot\` text NOT NULL,
|
||||
\`baseline_seq\` integer NOT NULL,
|
||||
\`replacement_seq\` integer,
|
||||
\`revision\` integer DEFAULT 0 NOT NULL,
|
||||
CONSTRAINT \`fk_session_context_epoch_session_id_session_id_fk\` FOREIGN KEY (\`session_id\`) REFERENCES \`session\`(\`id\`) ON DELETE CASCADE
|
||||
);
|
||||
`)
|
||||
yield* tx.run(`
|
||||
CREATE TABLE \`session_input\` (
|
||||
\`id\` text PRIMARY KEY,
|
||||
\`session_id\` text NOT NULL,
|
||||
\`prompt\` text NOT NULL,
|
||||
\`delivery\` text NOT NULL,
|
||||
\`admitted_seq\` integer NOT NULL,
|
||||
\`promoted_seq\` integer,
|
||||
\`time_created\` integer NOT NULL,
|
||||
CONSTRAINT \`fk_session_input_session_id_session_id_fk\` FOREIGN KEY (\`session_id\`) REFERENCES \`session\`(\`id\`) ON DELETE CASCADE
|
||||
);
|
||||
`)
|
||||
yield* tx.run(`
|
||||
CREATE TABLE \`session_message\` (
|
||||
\`id\` text PRIMARY KEY,
|
||||
\`session_id\` text NOT NULL,
|
||||
\`type\` text NOT NULL,
|
||||
\`seq\` integer NOT NULL,
|
||||
\`time_created\` integer NOT NULL,
|
||||
\`time_updated\` integer NOT NULL,
|
||||
\`data\` text NOT NULL,
|
||||
CONSTRAINT \`fk_session_message_session_id_session_id_fk\` FOREIGN KEY (\`session_id\`) REFERENCES \`session\`(\`id\`) ON DELETE CASCADE
|
||||
);
|
||||
`)
|
||||
yield* tx.run(`
|
||||
CREATE TABLE \`session\` (
|
||||
\`id\` text PRIMARY KEY,
|
||||
\`project_id\` text NOT NULL,
|
||||
\`workspace_id\` text,
|
||||
\`parent_id\` text,
|
||||
\`slug\` text NOT NULL,
|
||||
\`directory\` text NOT NULL,
|
||||
\`path\` text,
|
||||
\`title\` text NOT NULL,
|
||||
\`version\` text NOT NULL,
|
||||
\`share_url\` text,
|
||||
\`summary_additions\` integer,
|
||||
\`summary_deletions\` integer,
|
||||
\`summary_files\` integer,
|
||||
\`summary_diffs\` text,
|
||||
\`metadata\` text,
|
||||
\`cost\` real DEFAULT 0 NOT NULL,
|
||||
\`tokens_input\` integer DEFAULT 0 NOT NULL,
|
||||
\`tokens_output\` integer DEFAULT 0 NOT NULL,
|
||||
\`tokens_reasoning\` integer DEFAULT 0 NOT NULL,
|
||||
\`tokens_cache_read\` integer DEFAULT 0 NOT NULL,
|
||||
\`tokens_cache_write\` integer DEFAULT 0 NOT NULL,
|
||||
\`revert\` text,
|
||||
\`permission\` text,
|
||||
\`agent\` text,
|
||||
\`model\` text,
|
||||
\`time_created\` integer NOT NULL,
|
||||
\`time_updated\` integer NOT NULL,
|
||||
\`time_compacting\` integer,
|
||||
\`time_archived\` integer,
|
||||
CONSTRAINT \`fk_session_project_id_project_id_fk\` FOREIGN KEY (\`project_id\`) REFERENCES \`project\`(\`id\`) ON DELETE CASCADE
|
||||
);
|
||||
`)
|
||||
yield* tx.run(`
|
||||
CREATE TABLE \`todo\` (
|
||||
\`session_id\` text NOT NULL,
|
||||
\`content\` text NOT NULL,
|
||||
\`status\` text NOT NULL,
|
||||
\`priority\` text NOT NULL,
|
||||
\`position\` integer NOT NULL,
|
||||
\`time_created\` integer NOT NULL,
|
||||
\`time_updated\` integer NOT NULL,
|
||||
CONSTRAINT \`todo_pk\` PRIMARY KEY(\`session_id\`, \`position\`),
|
||||
CONSTRAINT \`fk_todo_session_id_session_id_fk\` FOREIGN KEY (\`session_id\`) REFERENCES \`session\`(\`id\`) ON DELETE CASCADE
|
||||
);
|
||||
`)
|
||||
yield* tx.run(`
|
||||
CREATE TABLE \`session_share\` (
|
||||
\`session_id\` text PRIMARY KEY,
|
||||
\`id\` text NOT NULL,
|
||||
\`secret\` text NOT NULL,
|
||||
\`url\` text NOT NULL,
|
||||
\`time_created\` integer NOT NULL,
|
||||
\`time_updated\` integer NOT NULL,
|
||||
CONSTRAINT \`fk_session_share_session_id_session_id_fk\` FOREIGN KEY (\`session_id\`) REFERENCES \`session\`(\`id\`) ON DELETE CASCADE
|
||||
);
|
||||
`)
|
||||
yield* tx.run(`CREATE UNIQUE INDEX \`event_aggregate_seq_idx\` ON \`event\` (\`aggregate_id\`,\`seq\`);`)
|
||||
yield* tx.run(`CREATE INDEX \`event_aggregate_type_seq_idx\` ON \`event\` (\`aggregate_id\`,\`type\`,\`seq\`);`)
|
||||
yield* tx.run(`CREATE UNIQUE INDEX \`permission_project_action_resource_idx\` ON \`permission\` (\`project_id\`,\`action\`,\`resource\`);`)
|
||||
yield* tx.run(`CREATE INDEX \`message_session_time_created_id_idx\` ON \`message\` (\`session_id\`,\`time_created\`,\`id\`);`)
|
||||
yield* tx.run(`CREATE INDEX \`part_message_id_id_idx\` ON \`part\` (\`message_id\`,\`id\`);`)
|
||||
yield* tx.run(`CREATE INDEX \`part_session_idx\` ON \`part\` (\`session_id\`);`)
|
||||
yield* tx.run(`CREATE INDEX \`session_input_session_pending_delivery_seq_idx\` ON \`session_input\` (\`session_id\`,\`promoted_seq\`,\`delivery\`,\`admitted_seq\`);`)
|
||||
yield* tx.run(`CREATE UNIQUE INDEX \`session_input_session_admitted_seq_idx\` ON \`session_input\` (\`session_id\`,\`admitted_seq\`);`)
|
||||
yield* tx.run(`CREATE UNIQUE INDEX \`session_input_session_promoted_seq_idx\` ON \`session_input\` (\`session_id\`,\`promoted_seq\`);`)
|
||||
yield* tx.run(`CREATE UNIQUE INDEX \`session_message_session_seq_idx\` ON \`session_message\` (\`session_id\`,\`seq\`);`)
|
||||
yield* tx.run(`CREATE INDEX \`session_message_session_type_seq_idx\` ON \`session_message\` (\`session_id\`,\`type\`,\`seq\`);`)
|
||||
yield* tx.run(`CREATE INDEX \`session_message_session_time_created_id_idx\` ON \`session_message\` (\`session_id\`,\`time_created\`,\`id\`);`)
|
||||
yield* tx.run(`CREATE INDEX \`session_message_time_created_idx\` ON \`session_message\` (\`time_created\`);`)
|
||||
yield* tx.run(`CREATE INDEX \`session_project_idx\` ON \`session\` (\`project_id\`);`)
|
||||
yield* tx.run(`CREATE INDEX \`session_workspace_idx\` ON \`session\` (\`workspace_id\`);`)
|
||||
yield* tx.run(`CREATE INDEX \`session_parent_idx\` ON \`session\` (\`parent_id\`);`)
|
||||
yield* tx.run(`CREATE INDEX \`todo_session_idx\` ON \`todo\` (\`session_id\`);`)
|
||||
})
|
||||
},
|
||||
} satisfies Omit<DatabaseMigration.Migration, "id">
|
||||
Loading…
Add table
Add a link
Reference in a new issue