Controller endpoint HTTP تعریف میکند. منطق business در Service است. body با Zod در decorator validate میشود.
نقش
Request → Controller → Service → response JSON. Controller SQL یا fetch cross-app ندارد.
نمونه CRUD
typescriptپازل API
import { Controller, get, post, put, del } from '@platform/runtime'
import { z } from 'zod'
import { OrderService } from '../services/OrderService.js'
const CreateOrderSchema = z.object({
total: z.number().int().positive(),
customerId: z.string().uuid(),
})
export class OrdersController extends Controller('/orders') {
constructor(private readonly orders: OrderService) {
super()
}
@get('/')
list() {
return this.orders.findAll()
}
@get('/:id')
detail(id: string) {
return this.orders.findById(id)
}
@post('/', { body: CreateOrderSchema })
create(body: z.infer<typeof CreateOrderSchema>) {
return this.orders.create(body)
}
@put('/:id', { body: UpdateOrderSchema })
update(id: string, body: UpdateOrderDto) {
return this.orders.update(id, body)
}
@del('/:id')
remove(id: string) {
return this.orders.delete(id)
}
}URL نهایی
/{slug}{controllerPath}{methodPath} — مثلاً slug=shop → GET /shop/orders/
Validation
{ body: Schema } در option decorator. import نسبی با پسوند .js در ESM.
DI
typescriptپازل API
import { Inject } from '@platform/runtime'
import { IAM_USER_SERVICE, type IUserService } from '@app/iam'
constructor(
private readonly orders: OrderService,
@Inject(IAM_USER_SERVICE) private readonly users: IUserService,
) { super() }بعد از weave، panel hookهایی مثل useListOrders() از همین Controller generate میشوند.