Rhys Sullivanfmtc92c57d6 months agoHistory
82 lines · 4.7 KB · Markdown
RawDownload

Storage Migration Notes (PR #262 — sdk-refactor-inplace)

What was done

1. DBSchema alignment with better-auth

  • Vendored better-auth's BetterAuthPluginDBSchema pattern into storage-core/src/schema.ts
  • Made modelName optional (falls back to the key), renamed disableMigrations → disableMigration, dropped order
  • Removed explicit modelName from all plugin schemas (core-schema, openapi, mcp, graphql, google-discovery, workos-vault) — keys already match table names

2. @executor-js/cli package (packages/core/cli/)

  • Mirrors better-auth's CLI approach: load config → collect plugin schemas → generate drizzle TS
  • executor generate --config ./executor.config.ts --output ./src/services/executor-schema.ts
  • Generator ported from better-auth's drizzle generator, adapted for our DBSchema
  • Handles pg/sqlite/mysql dialects, indexes, references, relations, default values
  • Uses jiti for config loading (supports TS configs)

3. apps/cloud wired up

  • executor.config.ts defines plugins with stub credentials (only used for schema shape)
  • drizzle.config.ts points at both schema.ts (cloud tables) and executor-schema.ts (executor tables)
  • Fresh drizzle/0000_initial.sql with all tables (cloud + core + plugin + blob), indexes, FKs

4. apps/local wired up

  • executor.config.ts defines plugins + dialect sqlite
  • drizzle.config.ts for drizzle-kit generate/push
  • Generated executor-schema.ts with all sqlite tables + blob table
  • drizzle/0000_*.sql initial migration
  • At startup: migrate(db, { migrationsFolder }) from drizzle-orm/bun-sqlite/migrator applies pending migrations before constructing the adapter

5. Adapter DDL removed

  • makeSqliteAdapter and makePostgresAdapter no longer run DDL — they return DBAdapter directly (not Effect.Effect<DBAdapter>)
  • makeSqliteBlobStore and makePostgresBlobStore no longer run DDL — they return BlobStore directly
  • buildCreateTableStatements deleted from storage-file/compile.ts
  • Blob table included in both local and cloud generated schemas — managed by drizzle-kit alongside all other tables

Migration path — what's next

The plan: re-derive sources from executor.jsonc

The @executor-js/config package already maintains executor.jsonc as a source of truth for source configurations. The config-store.ts decorator intercepts putSource/removeSource on each plugin and mirrors to this file. So for existing users, executor.jsonc already has everything.

Local app migration

  1. On first run, migrate() creates all tables from the initial migration
  2. Add a sync-from-config step after executor creation:
    • loadConfig(configPath) reads executor.jsonc
    • For each source, call the plugin's add method (executor.openapi.addSpec(), executor.mcp.addSource(), etc.)
    • This re-fetches specs, re-parses tools, populates typed tables
  3. Secrets survive untouched — they live in keychain/1password/file-secrets, not in the DB. The secret routing table gets re-populated when sources are added.

What won't survive (acceptable losses)

  • Tool invocation history / blobs (old KV format)
  • OAuth sessions (ephemeral, users re-auth)
  • Stale source state (re-fetching is actually a benefit)

Cloud migration

  • Only ~2 users, just drop old tables and re-add manually
  • Or write a one-off SQL migration

Key files

File Role
packages/core/cli/src/commands/generate.ts CLI generate command
packages/core/cli/src/generators/drizzle.ts Drizzle schema generator
packages/core/sdk/src/config.ts defineExecutorConfig helper
packages/core/config/src/schema.ts executor.jsonc schema
packages/core/config/src/config-store.ts Plugin store → config file decorator
packages/core/config/src/load.ts Config loading
apps/cloud/executor.config.ts Cloud config for CLI
apps/cloud/src/services/executor-schema.ts Generated drizzle schema
apps/cloud/drizzle/0000_*.sql Fresh migration
apps/local/executor.config.ts Local config for CLI
apps/local/src/server/executor-schema.ts Generated drizzle schema
apps/local/drizzle/0000_*.sql Fresh migration
apps/local/src/server/executor.ts Local executor bootstrap with migrate()