Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
147baa7
chore(api): add cursor rules for api module
EdouardDem Aug 4, 2025
6a333ae
chore(api): implement cursor pagination rules for improved data handling
EdouardDem Aug 8, 2025
639801c
docs: add reference link for installation and context in config.mdc
EdouardDem Aug 8, 2025
22b07a8
docs: add CLI commands architecture and change guidelines
EdouardDem Aug 8, 2025
aeab045
fix: correct formatting in development workflow rules for API extension
EdouardDem Aug 8, 2025
7684a73
docs: update CLI commands and config service guidelines with descript…
EdouardDem Aug 8, 2025
ffb6106
docs: add collections services architecture and extension guidelines
EdouardDem Aug 8, 2025
ba7a136
docs: add seed services architecture and operational guidelines
EdouardDem Aug 8, 2025
c80fe74
docs: update reference links in configuration and services collection…
EdouardDem Aug 8, 2025
6e17e91
docs: add snapshot and specifications services architecture and chang…
EdouardDem Aug 8, 2025
5b9e188
docs: add services clients architecture and change guidelines
EdouardDem Aug 8, 2025
87d8ceb
docs: add end-to-end testing guidelines and architecture overview
EdouardDem Aug 8, 2025
f89f537
docs: enhance end-to-end testing guidelines with practical examples a…
EdouardDem Aug 9, 2025
4369f1a
docs: update end-to-end testing instructions with build and execution…
EdouardDem Aug 9, 2025
45a1134
docs(e2e): log level debugging instructions and correct import file r…
EdouardDem Aug 9, 2025
fc504c9
feat(e2e): implement dynamic ID handling in data mapping and update d…
EdouardDem Aug 9, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 49 additions & 0 deletions .cursor/rules/project-overview.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
---
description: Repository overview and package responsibilities
globs: packages/**/*, website/**/*, docker/**/*, *.md, lerna.json
---

# Repository Overview

Monorepo providing a Directus endpoint extension, a CLI for syncing schema/data, an e2e test harness, and documentation.

High-level flow
- The CLI connects to a Directus instance and orchestrates pull/diff/push/seed/specs operations.
- The API extension exposes endpoints used by the CLI for SyncID↔LocalID mapping and helpers.
- E2E tests spin up a Directus server locally and validate the full flow (CLI + extension) end-to-end.

Packages
- `packages/api` (Directus endpoint extension)
- Exposes `/directus-extension-sync` routes for SyncID mapping and helpers (e.g., permissions deduplication).
- Uses Express-style router via Directus SDK, Zod validation, and Knex for a small mapping table.
- Key files: `src/index.ts` (routes), `src/api/*` (middleware/helpers), `src/database/*` (IdMapper, Permissions).

- `packages/cli` (Directus Sync CLI)
- Orchestrates schema and system collections synchronization; supports seed data and API specifications dump.
- Structure:
- `services/config`: options resolution (defaults → config file → CLI flags), Zod validation.
- `services/collections`: per-collection pull/diff/push with id mapping.
- `services/snapshot`: schema snapshot pull/diff/push.
- `services/seed`: seed files loader/differ/pusher with dynamic id mapping.
- `services/specifications`: GraphQL/OpenAPI dump.
- `services/*-client.ts`: Directus SDK client, extension HTTP client, health checks.
- `commands` + `program.ts`: command wiring and execution.
- Technologies: TypeScript, typedi (DI), pino (logging), Zod, @directus/sdk.

- `packages/e2e` (End-to-end tests)
- Jasmine-based tests against a locally started Directus server.
- Helpers start the server, create a Directus client, and run CLI commands programmatically, asserting logs and state.
- See `spec/helpers/sdk/*`, `spec/pull-diff-push/*`.

- `website` (Documentation)
- Docusaurus site documenting installation, features, and how the sync works.

Other top-level
- `docker/`: build/publish scripts and Dockerfile for distributing Directus with the extension.
- `lerna.json`: monorepo management.
- `DOCUMENTATION.md`, `CHANGELOG.md`, etc.: project docs and changelog.

Conventions (brief)
- TypeScript across packages; DI via `typedi`; logging via `pino`; validation via `zod`.
- Keep business logic in services; commands/endpoints orchestrate only.
- Follow per-package rules under `.cursor/rules/` for detailed guidance.
69 changes: 69 additions & 0 deletions packages/api/.cursor/rules/api-middleware.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
---
description: API middleware patterns and helper functions for request handling
globs: packages/api/src/api/**/*.ts
---

# API Middleware & Helpers Rules

## Authentication Middleware
- Use `ensureIsAdminHandler` for all endpoints requiring admin access
- Check `req.accountability.user` for user authentication
- Check `req.accountability.admin` for admin permissions
- Return 401 for unauthenticated users, 403 for insufficient permissions
- Apply middleware at router level for all routes

## Input Validation Helper
- Use `validateInput` function with Zod schemas for all parameter validation
- Combine multiple input sources: `{...req.params, ...req.body}` for POST requests
- Handle Zod validation errors by extracting issue details
- Transform ZodError into readable error messages with field paths
- Throw standard Error objects for consistent error handling

## Error Handling Middleware
- Use `errorHandler` as final middleware in chain
- Check `res.headersSent` before sending error responses
- Distinguish between HTTP errors and generic errors
- Use proper HTTP status codes (isHttpError check)
- Return JSON error responses with message field

## Logging Middleware
- Use `logError` middleware for centralized error logging
- Log only 5xx errors to avoid noise from client errors
- Extract status code and message from HTTP errors
- Use Pino logger instance from Directus context
- Call `next(err)` to continue error chain

## TypeScript Interfaces
- Extend Express Request interface to include Directus accountability
- Define accountability object with user and admin properties
- Re-export Express Response and NextFunction types
- Keep interfaces minimal and focused on extension needs

## HTTP Error Creation
- Use `createError` from `http-errors` library for standardized error responses
- Pass error to `next()` function for middleware chain handling
- Use appropriate HTTP status codes
- Include descriptive error messages for debugging

## Error Creation Patterns
```typescript
// Not found
next(createError(404, 'No id map found'));

// Conflict
next(createError(409, 'Local id already exists'));

// Authentication required
next(createError(401, 'You must be logged in to access this.'));

// Insufficient permissions
next(createError(403, 'You do not have permission to access this.'));
```

## Middleware Chain Order
```typescript
router.use(ensureIsAdminHandler); // Authentication first
// Route definitions here
router.use(logError(logger)); // Log errors
router.use(errorHandler); // Handle errors last
```
58 changes: 58 additions & 0 deletions packages/api/.cursor/rules/database-layer.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
---
description: Database layer patterns and Knex.js usage for business logic classes
globs: packages/api/src/database/**/*.ts
---

# Database Layer Rules

## Class Structure
- Business logic classes should accept `Knex` database connection in constructor
- Store database connection as `protected readonly database: Knex`
- Include logger parameter for classes that need logging (e.g., `protected readonly logger: pino.Logger`)
- Implement `init()` method for table creation/schema setup when needed

## Table Management
- Use descriptive table names with clear prefixes (e.g., `directus_sync_id_map`)
- Check table existence with `database.schema.hasTable()` before creation
- Return boolean from `init()` indicating if table was created
- Use proper column types and constraints in schema definitions
- Add appropriate indexes for query performance

## Query Patterns
- Use parameterized queries to prevent SQL injection
- Handle null results explicitly (return `null` when no records found)
- Use transactions for multi-step operations
- Implement proper error handling for database operations
- Use `first()` for single record queries, return typed results

## Interface Definitions
- Define TypeScript interfaces for database entities (e.g., `IdMap`)
- Include all table columns in interface definitions
- Use proper types (string, number, Date) for each column
- Export interfaces from the database layer for reuse

## Testing Approach
- Use in-memory SQLite database for unit tests
- Create fresh database instance for each test case
- Clean up database connections in `afterEach` hooks
- Test both success and error scenarios
- Verify table creation and data persistence

## Example Patterns
```typescript
export class BusinessLogicClass {
protected readonly tableName = 'directus_prefix_table_name';

constructor(protected readonly database: Knex) {}

async init(): Promise<boolean> {
if (!(await this.database.schema.hasTable(this.tableName))) {
await this.database.schema.createTable(this.tableName, (table) => {
// Define schema
});
return true;
}
return false;
}
}
```
44 changes: 44 additions & 0 deletions packages/api/.cursor/rules/development-workflow.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
---
description: Development workflow and debugging patterns for the API extension
globs: packages/api/src/**/*.ts,packages/api/package.json
---

# Development Workflow Rules

## Extension Development Setup
- Use `npm run dev` for development with watch mode and no minification
- Use `npm run link /path/to/directus/extensions` to link to Directus instance
- Build extension with `npm run build` for production deployment
- Run tests with `npm test` using Jest configuration

## Directus Extension Configuration
- Extension type is `endpoint` as defined in package.json
- Entry point is `src/index.ts`, build output is `dist/index.js`
- Target Directus host version `^11.0.0` or compatible
- Use ES modules (`"type": "module"` in package.json)

## Development Dependencies
- Use `@directus/extensions-sdk` for build tooling and type definitions
- Include proper type definitions for all external libraries
- Use Jest with TypeScript support for testing
- Include Pino for logging (matches Directus logger interface)

## Logging Standards
- Use logger provided by Directus extension context
- Log initialization events (table creation, startup)
- Log errors with appropriate levels (error for 5xx, info for operations)
- Avoid logging sensitive data (IDs, user information)
- Use structured logging with descriptive messages

## Database Connection Handling
- Database connection is provided by Directus extension context
- Use the same connection for all database operations
- No need to manage connection lifecycle (handled by Directus)
- Use transactions for multi-step operations when needed

## Error Debugging
- Use descriptive error messages that help identify the issue
- Include relevant context in error messages (table name, ID, operation)
- Log errors before throwing or passing to error handler
- Use HTTP status codes that match the error type
- Provide consistent error response format
49 changes: 49 additions & 0 deletions packages/api/.cursor/rules/directus-extension-architecture.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
---
description: Directus endpoint extension architecture and patterns for the API module
globs: packages/api/src/**/*.ts
---

# Directus Extension Architecture Rules

## Extension Type & Structure
- This is a Directus **endpoint extension** that provides custom API routes
- Follow Directus extension patterns using `defineEndpoint` from `@directus/extensions-sdk`
- Main entry point is `src/index.ts` which exports the router configuration
- Organize code in layers: `/api` (middleware/helpers), `/database` (business logic)

## Router & Endpoint Patterns
- Use Express router provided by Directus extension context
- All endpoints MUST be admin-only (use `ensureIsAdminHandler` middleware)
- Follow RESTful conventions:
- GET endpoints for retrieval
- POST endpoints for creation
- DELETE endpoints for removal
- Path structure: `/table/:table/sync_id/:sync_id` or `/table/:table/local_id/:local_id`

## Request Handling Standards
- ALWAYS validate inputs using Zod schemas with `validateInput` helper
- Handle errors with proper HTTP status codes (404, 409, 500)
- Use `next(error)` for error propagation to error handler middleware
- Return JSON responses with appropriate status codes
- Use async/await for all database operations

## Business Logic Organization
- Keep business logic in separate classes in `/database` directory
- Classes should accept database connection and logger in constructor
- Implement proper initialization methods (e.g., `init()` for table creation)
- Use Knex.js for all database operations
- Export classes from `/database/index.ts`

## Error Handling Requirements
- Use `http-errors` library for creating HTTP errors
- Implement centralized error handling with `errorHandler` middleware
- Log errors using Pino logger with `logError` middleware
- Check for existing headers before sending responses
- Use early returns for error conditions to avoid nested logic

## Input Validation
- Use Zod for runtime type validation
- Create specific schemas for each endpoint's expected inputs
- Combine `req.params` and `req.body` when validating POST requests
- Handle validation errors gracefully with descriptive messages
- Use TypeScript interfaces that match Zod schemas
61 changes: 61 additions & 0 deletions packages/api/.cursor/rules/testing-patterns.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
---
description: Testing patterns and Jest configuration for the API extension
globs: packages/api/src/**/*.spec.ts, packages/api/jest.config.cjs
---

# Testing Patterns Rules

## Test Structure
- Use describe blocks for organizing test suites by class/functionality
- Use descriptive test names that explain the expected behavior
- Group related tests within nested describe blocks when appropriate
- Follow AAA pattern: Arrange, Act, Assert

## Database Testing Setup
- Use in-memory SQLite database for isolated testing
- Create fresh database instance in `beforeEach` hook
- Clean up database connections in `afterEach` hook
- Initialize business logic classes with test database instance
- Use `useNullAsDefault: true` for SQLite compatibility

## Test Database Configuration
```typescript
beforeEach(() => {
database = Knex.knex({
client: 'sqlite3',
connection: { filename: ':memory:' },
useNullAsDefault: true,
});
businessLogic = new BusinessLogicClass(database);
});

afterEach(async () => {
await database.destroy();
});
```

## Testing Business Logic
- Test initialization methods (table creation, return values)
- Test CRUD operations (create, read, update, delete)
- Test error scenarios (duplicate keys, missing records)
- Test edge cases (null values, empty results)
- Verify database state after operations

## Assertion Patterns
- Use `expect().toBe()` for primitive values and booleans
- Use `expect().toBeNull()` for null checks
- Use `expect().toEqual()` for object comparisons
- Test both positive and negative cases
- Verify error handling with appropriate assertions

## Mock Data
- Use consistent test data across related tests
- Use descriptive variable names for test data
- Create reusable test fixtures when appropriate
- Generate unique identifiers for isolation (UUIDs, timestamps)

## Test Coverage Goals
- Cover all public methods of business logic classes
- Test error paths and exception handling
- Verify initialization and cleanup procedures
- Test boundary conditions and edge cases
Loading