Skip to content

feat: PostgreSQL database migration with Drizzle ORM - #165

Merged
PaulJPhilp merged 8 commits into
mainfrom
feature/postgres-drizzle-migration
Dec 22, 2025
Merged

feat: PostgreSQL database migration with Drizzle ORM#165
PaulJPhilp merged 8 commits into
mainfrom
feature/postgres-drizzle-migration

Conversation

@PaulJPhilp

@PaulJPhilp PaulJPhilp commented Dec 22, 2025

Copy link
Copy Markdown
Owner

This PR adds PostgreSQL database support with Drizzle ORM for patterns, use cases, and application patterns. Includes comprehensive database testing utilities and migration guides.


Note

Database integration

  • Introduces PostgreSQL with Drizzle ORM (schemas, repos, services) and adds db scripts/workflow references across docs
  • Adds migration, verification, and studio guidance (ARCHITECTURE.md, DATA_MODEL.md, DATABASE_TESTING.md, MIGRATION_TESTING.md)

Coding standards

  • New rules: always use Effect.Service; forbid as any; avoid Live/Default/Impl suffixes

Docs and content

  • Updates README.md navigation (removes Schema section, reorganizes Sinks links)
  • Expands architecture and data model to make PostgreSQL the primary source of truth

Dependencies

  • Adds drizzle-orm, postgres, drizzle-kit, @types/pg; bumps ai, turbo; large lockfile updates

Written by Cursor Bugbot for commit 4ae95e5. This will update automatically on new commits. Configure here.

…s, and application patterns

- Add Drizzle ORM and postgres dependencies
- Create database schema for application_patterns, effect_patterns, jobs, and relations
- Implement repository layer with CRUD and search operations
- Add migration script to parse existing JSON/MDX/MD files
- Update toolkit to support both file-based and database-based storage
- Add integration tests for all repositories
- Configure drizzle.config.ts for migrations

Database tables:
- application_patterns: High-level pattern categories
- effect_patterns: Concrete code examples
- jobs: Jobs-to-be-Done entries
- pattern_jobs: Many-to-many pattern-job relationships
- pattern_relations: Related patterns linking

New scripts:
- bun run db:generate - Generate migrations
- bun run db:push - Push schema to database
- bun run db:migrate - Run data migration from files
- bun run db:verify - Verify migration results
- bun run db:studio - Open Drizzle Studio
- Create DatabaseService with Effect.Service wrapper for repositories
- Add high-level database operations (searchEffectPatterns, findEffectPatternBySlug)
- Update MCP server PatternsService to use database instead of file loading
- Convert database EffectPattern types to legacy Pattern types for compatibility
- Add migration testing guide

Database service provides:
- DatabaseLayer for dependency injection
- Effect-based repository access
- Type conversion from DB schema to legacy Pattern schema
- Error handling and logging integration
- Replace file-based loading with database queries
- Load application patterns and effect patterns from PostgreSQL
- Find actual file paths by searching filesystem
- Maintain backward compatibility with existing file structure
- Improve path resolution accuracy
CLI Updates:
- Update search, list, and show commands to use database
- Replace JSON file loading with database queries
- Add proper error handling and database connection management
- Support related patterns query from database

Documentation Updates:
- Update DATA_MODEL.md to reflect PostgreSQL as primary source
- Add database schema documentation
- Update ARCHITECTURE.md with database technologies
- Add database configuration section
- Update package descriptions to mention database
- Add migration guide references
Testing Infrastructure:
- Add test-db.ts - Comprehensive database test runner
- Add test-db-quick.ts - Quick database connectivity test
- Add db-helpers.ts - Test utilities (setup, cleanup, seeding)
- Update repositories.test.ts to use test helpers

Documentation:
- Add DATABASE_TESTING.md - Complete testing guide
- Update MIGRATION_TESTING.md with testing steps

Scripts:
- bun run test:db - Run full database test suite
- bun run test:db:quick - Quick connectivity test
- bun run test:db:repositories - Run repository integration tests
- Add validated and validatedAt fields to application_patterns, effect_patterns, and jobs tables
- Implement lock/unlock methods in all repositories
- Add locked error types (EffectPatternLockedError, ApplicationPatternLockedError, JobLockedError)
- Enforce read-only behavior for locked entities in update/delete/upsert operations
- Add lock and unlock commands to ep-admin CLI
- Fix postgres import in database client (use default import instead of namespace)
- Fix generate.ts to group patterns by applicationPatternId from database
- Generate database migration for locking fields
- Export locked error types from toolkit package
@vercel

vercel Bot commented Dec 22, 2025

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Review Updated (UTC)
effect-patterns Ready Ready Preview, Comment Dec 22, 2025 11:33pm
effect-patterns-mcp-server Error Error Dec 22, 2025 11:33pm

createEffectPatternRepository,
createJobRepository,
} from "../repositories/index.js"
import { eq } from "drizzle-orm"

Check notice

Code scanning / CodeQL

Unused variable, import, function or class Note test

Unused import eq.

Copilot Autofix

AI 9 months ago

To fix the problem, remove the unused import from the file so that every imported symbol is referenced somewhere in the code. This eliminates confusion, keeps the test file minimal, and silences the static analysis warning.

Concretely, in packages/toolkit/src/__tests__/repositories.test.ts, delete the line that imports eq from "drizzle-orm" (line 22). No other changes are needed: there are no reported usages to update, and we are not altering any behavior because the symbol is never used. No new methods, imports, or definitions are required.

Suggested changeset 1
packages/toolkit/src/__tests__/repositories.test.ts

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/packages/toolkit/src/__tests__/repositories.test.ts b/packages/toolkit/src/__tests__/repositories.test.ts
--- a/packages/toolkit/src/__tests__/repositories.test.ts
+++ b/packages/toolkit/src/__tests__/repositories.test.ts
@@ -19,7 +19,6 @@
   createEffectPatternRepository,
   createJobRepository,
 } from "../repositories/index.js"
-import { eq } from "drizzle-orm"
 import {
   setupTestDatabase,
   cleanDatabase,
EOF
@@ -19,7 +19,6 @@
createEffectPatternRepository,
createJobRepository,
} from "../repositories/index.js"
import { eq } from "drizzle-orm"
import {
setupTestDatabase,
cleanDatabase,
Copilot is powered by AI and may make mistakes. Always verify output.
} from "../db/schema/index.js"
import type { Pattern } from "../schemas/pattern.js"
import { ToolkitLogger, ToolkitLoggerLive } from "./logger.js"
import { ToolkitConfig, ToolkitConfigLive } from "./config.js"

Check notice

Code scanning / CodeQL

Unused variable, import, function or class Note

Unused import ToolkitConfig.

Copilot Autofix

AI 9 months ago

To fix the problem, remove the unused ToolkitConfig symbol from the import statement while keeping the used ToolkitConfigLive. This eliminates the unused value import without affecting runtime behavior or typings.

Concretely, in packages/toolkit/src/services/database.ts, locate the line:

import { ToolkitLogger, ToolkitLoggerLive } from "./logger.js"
import { ToolkitConfig, ToolkitConfigLive } from "./config.js"

and change it so that only ToolkitConfigLive is imported from ./config.js. No other code changes are required because no code references ToolkitConfig.

Suggested changeset 1
packages/toolkit/src/services/database.ts

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/packages/toolkit/src/services/database.ts b/packages/toolkit/src/services/database.ts
--- a/packages/toolkit/src/services/database.ts
+++ b/packages/toolkit/src/services/database.ts
@@ -29,7 +29,7 @@
 } from "../db/schema/index.js"
 import type { Pattern } from "../schemas/pattern.js"
 import { ToolkitLogger, ToolkitLoggerLive } from "./logger.js"
-import { ToolkitConfig, ToolkitConfigLive } from "./config.js"
+import { ToolkitConfigLive } from "./config.js"
 
 /**
  * Convert database EffectPattern to legacy Pattern format
EOF
@@ -29,7 +29,7 @@
} from "../db/schema/index.js"
import type { Pattern } from "../schemas/pattern.js"
import { ToolkitLogger, ToolkitLoggerLive } from "./logger.js"
import { ToolkitConfig, ToolkitConfigLive } from "./config.js"
import { ToolkitConfigLive } from "./config.js"

/**
* Convert database EffectPattern to legacy Pattern format
Copilot is powered by AI and may make mistakes. Always verify output.
@PaulJPhilp
PaulJPhilp merged commit 2849026 into main Dec 22, 2025
10 of 21 checks passed
@PaulJPhilp
PaulJPhilp deleted the feature/postgres-drizzle-migration branch December 22, 2025 23:33
Comment thread scripts/migrate-state.ts
* Create initial step state
*/
function _createInitialStepState(
function createInitialStepState(

Check notice

Code scanning / CodeQL

Unused variable, import, function or class Note

Unused function createInitialStepState.

Copilot Autofix

AI 9 months ago

In general, to fix an "unused function" finding, either delete the function or start using it where appropriate. To avoid changing runtime behavior, we should not alter the logic of existing, used code; instead, we remove only code that truly has no effect: the unused createInitialStepState helper and its associated comment.

Concretely, in scripts/migrate-state.ts, remove the entire createInitialStepState function definition (lines 93–105 in the snippet) and its JSDoc comment, leaving the rest of the file unchanged. No additional imports, methods, or definitions are required because nothing else depends on this function.

Suggested changeset 1
scripts/migrate-state.ts

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/scripts/migrate-state.ts b/scripts/migrate-state.ts
--- a/scripts/migrate-state.ts
+++ b/scripts/migrate-state.ts
@@ -91,20 +91,6 @@
 // --- HELPER FUNCTIONS ---
 
 /**
- * Create initial step state
- */
-function createInitialStepState(
-  status: StepState['status'] = 'pending',
-): StepState {
-  return {
-    status,
-    attempts: 0,
-    checkpoints: [],
-    errors: [],
-  };
-}
-
-/**
  * Create pattern state with all steps completed
  */
 function createCompletedPatternState(
EOF
@@ -91,20 +91,6 @@
// --- HELPER FUNCTIONS ---

/**
* Create initial step state
*/
function createInitialStepState(
status: StepState['status'] = 'pending',
): StepState {
return {
status,
attempts: 0,
checkpoints: [],
errors: [],
};
}

/**
* Create pattern state with all steps completed
*/
function createCompletedPatternState(
Copilot is powered by AI and may make mistakes. Always verify output.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the final PR Bugbot will review for you during this billing cycle

Your free Bugbot reviews will reset on January 17

Details

You are on the Bugbot Free tier. On this plan, Bugbot will review limited PRs each billing cycle.

To receive Bugbot reviews on all of your PRs, visit the Cursor dashboard to activate Pro and start your 14-day free trial.

Comment thread README.md
| :--- | :--- | :--- |
| [Stream Pattern 1: Transform Streams with Map and Filter](./content/published/patterns/streams/stream-pattern-map-filter-transformations.mdx) | 🟢 **Beginner** | Use Stream.map and Stream.filter to transform and select stream elements, enabling data pipelines that reshape and filter data in flight. |
| [Sink Pattern 1: Batch Insert Stream Records into Database](./content/published/patterns/streams/sink-pattern-batch-insert-stream-records-into-database.mdx) | 🟡 **Intermediate** | Use Sink to batch stream records and insert them efficiently into a database in groups, rather than one-by-one, for better performance and resource usage. |
| [Sink Pattern 2: Write Stream Events to Event Log](./content/published/patterns/streams/sink-pattern-write-stream-events-to-event-log.mdx) | 🟡 **Intermediate** | Use Sink to append stream events to an event log with metadata and causal ordering, enabling event sourcing and audit trail patterns. |

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

README links to non-existent Sink Pattern files

The README adds links to Sink Pattern 1 and 2 that point to incorrect file paths. The links reference ./content/published/patterns/streams/sink-pattern-batch-insert-stream-records-into-database.mdx and ./content/published/patterns/streams/sink-pattern-write-stream-events-to-event-log.mdx, but the actual files exist at ./content/published/patterns/streams/sinks/batch-insert-stream-records-into-database.mdx and ./content/published/patterns/streams/sinks/write-stream-events-to-event-log.mdx. The links use the wrong directory (streams/ instead of streams/sinks/) and incorrect filenames (added sink-pattern- prefix). Users clicking these links will get 404 errors.

Fix in Cursor Fix in Web

PaulJPhilp added a commit that referenced this pull request Jan 18, 2026
* feat: add PostgreSQL database with Drizzle ORM for patterns, use cases, and application patterns

- Add Drizzle ORM and postgres dependencies
- Create database schema for application_patterns, effect_patterns, jobs, and relations
- Implement repository layer with CRUD and search operations
- Add migration script to parse existing JSON/MDX/MD files
- Update toolkit to support both file-based and database-based storage
- Add integration tests for all repositories
- Configure drizzle.config.ts for migrations

Database tables:
- application_patterns: High-level pattern categories
- effect_patterns: Concrete code examples
- jobs: Jobs-to-be-Done entries
- pattern_jobs: Many-to-many pattern-job relationships
- pattern_relations: Related patterns linking

New scripts:
- bun run db:generate - Generate migrations
- bun run db:push - Push schema to database
- bun run db:migrate - Run data migration from files
- bun run db:verify - Verify migration results
- bun run db:studio - Open Drizzle Studio

* feat: add database service layer and update MCP server to use database

- Create DatabaseService with Effect.Service wrapper for repositories
- Add high-level database operations (searchEffectPatterns, findEffectPatternBySlug)
- Update MCP server PatternsService to use database instead of file loading
- Convert database EffectPattern types to legacy Pattern types for compatibility
- Add migration testing guide

Database service provides:
- DatabaseLayer for dependency injection
- Effect-based repository access
- Type conversion from DB schema to legacy Pattern schema
- Error handling and logging integration

* feat: update publishing pipeline to use database

- Replace file-based loading with database queries
- Load application patterns and effect patterns from PostgreSQL
- Find actual file paths by searching filesystem
- Maintain backward compatibility with existing file structure
- Improve path resolution accuracy

* feat: update CLI tools and documentation for database migration

CLI Updates:
- Update search, list, and show commands to use database
- Replace JSON file loading with database queries
- Add proper error handling and database connection management
- Support related patterns query from database

Documentation Updates:
- Update DATA_MODEL.md to reflect PostgreSQL as primary source
- Add database schema documentation
- Update ARCHITECTURE.md with database technologies
- Add database configuration section
- Update package descriptions to mention database
- Add migration guide references

* feat: add comprehensive database testing utilities and guides

Testing Infrastructure:
- Add test-db.ts - Comprehensive database test runner
- Add test-db-quick.ts - Quick database connectivity test
- Add db-helpers.ts - Test utilities (setup, cleanup, seeding)
- Update repositories.test.ts to use test helpers

Documentation:
- Add DATABASE_TESTING.md - Complete testing guide
- Update MIGRATION_TESTING.md with testing steps

Scripts:
- bun run test:db - Run full database test suite
- bun run test:db:quick - Quick connectivity test
- bun run test:db:repositories - Run repository integration tests

* feat: add entity locking mechanism for validated patterns

- Add validated and validatedAt fields to application_patterns, effect_patterns, and jobs tables
- Implement lock/unlock methods in all repositories
- Add locked error types (EffectPatternLockedError, ApplicationPatternLockedError, JobLockedError)
- Enforce read-only behavior for locked entities in update/delete/upsert operations
- Add lock and unlock commands to ep-admin CLI
- Fix postgres import in database client (use default import instead of namespace)
- Fix generate.ts to group patterns by applicationPatternId from database
- Generate database migration for locking fields
- Export locked error types from toolkit package

* feat: update pipeline state and database services with latest changes
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants