Revert "Unify workspace dropdowns; Update layouts (#458)"
This reverts commit 4bc8448a1d.
This commit is contained in:
@@ -17,21 +17,19 @@ Create validation schema in `_lib/schemas/`:
|
||||
|
||||
```typescript
|
||||
// _lib/schemas/feature.schema.ts
|
||||
import * as z from 'zod';
|
||||
import { z } from 'zod';
|
||||
|
||||
export const CreateFeatureSchema = z.object({
|
||||
name: z.string().min(1, 'Name is required'),
|
||||
accountId: z.string().uuid('Invalid account ID'),
|
||||
});
|
||||
|
||||
export type CreateFeatureInput = z.output<typeof CreateFeatureSchema>;
|
||||
export type CreateFeatureInput = z.infer<typeof CreateFeatureSchema>;
|
||||
```
|
||||
|
||||
### Step 2: Create Service Layer
|
||||
|
||||
**North star: services are decoupled from their interface.** The service is pure logic — it receives a database client
|
||||
as a dependency, never imports one. This means the same service works whether called from a server action, an MCP tool,
|
||||
a CLI command, or a plain unit test.
|
||||
**North star: services are decoupled from their interface.** The service is pure logic — it receives a database client as a dependency, never imports one. This means the same service works whether called from a server action, an MCP tool, a CLI command, or a plain unit test.
|
||||
|
||||
Create service in `_lib/server/`:
|
||||
|
||||
@@ -64,13 +62,11 @@ class FeatureService {
|
||||
}
|
||||
```
|
||||
|
||||
The service never calls `getSupabaseServerClient()` — the caller provides the client. This keeps the service testable (
|
||||
pass a mock client) and reusable (any interface can supply its own client).
|
||||
The service never calls `getSupabaseServerClient()` — the caller provides the client. This keeps the service testable (pass a mock client) and reusable (any interface can supply its own client).
|
||||
|
||||
### Step 3: Create Server Action (Thin Adapter)
|
||||
|
||||
The action is a **thin adapter** — it resolves dependencies (client, logger) and delegates to the service. No business
|
||||
logic lives here.
|
||||
The action is a **thin adapter** — it resolves dependencies (client, logger) and delegates to the service. No business logic lives here.
|
||||
|
||||
Create action in `_lib/server/server-actions.ts`:
|
||||
|
||||
@@ -111,18 +107,13 @@ export const createFeatureAction = enhanceAction(
|
||||
|
||||
## Key Patterns
|
||||
|
||||
1. **Services are pure, interfaces are thin adapters.** The service contains all business logic. The server action (or
|
||||
MCP tool, or CLI command) is glue code that resolves dependencies and calls the service. If an MCP tool and a server
|
||||
action do the same thing, they call the same service function.
|
||||
2. **Inject dependencies, don't import them in services.** Services receive their database client, logger, or any I/O
|
||||
capability as constructor arguments — never by importing framework-specific modules. This keeps them testable with
|
||||
stubs and reusable across interfaces.
|
||||
1. **Services are pure, interfaces are thin adapters.** The service contains all business logic. The server action (or MCP tool, or CLI command) is glue code that resolves dependencies and calls the service. If an MCP tool and a server action do the same thing, they call the same service function.
|
||||
2. **Inject dependencies, don't import them in services.** Services receive their database client, logger, or any I/O capability as constructor arguments — never by importing framework-specific modules. This keeps them testable with stubs and reusable across interfaces.
|
||||
3. **Schema in separate file** - Reusable between client and server
|
||||
4. **Logging** - Always log before and after operations
|
||||
5. **Revalidation** - Use `revalidatePath` after mutations
|
||||
6. **Trust RLS** - Don't add manual auth checks (RLS handles it)
|
||||
7. **Testable in isolation** - Because services accept their dependencies, you can test them with a mock client and no
|
||||
running infrastructure
|
||||
7. **Testable in isolation** - Because services accept their dependencies, you can test them with a mock client and no running infrastructure
|
||||
|
||||
## File Structure
|
||||
|
||||
|
||||
Reference in New Issue
Block a user