Skills Plugins MCP Prompt Model 博客 我的中心
开发编程 #data #design #api #database

api-development-standards

Node.js/Express/Prisma/PostgreSQL development patterns for Design Token Manager API. Use when working with controllers, routes, middleware, DAL, or database operations. Enforces multi-tenant isolation, Prisma best practices, Express patterns, authentication, and API response standards.

DeepseekModel 官方收录技能 质量 良好 · 48 v1.0.0

获取

https://deepseekmodel.com/api/download.php?id=mbelenmontoya-design-token-manager-api-claude-skills-api-development-standards-skill-md&format=skill
下载 .skill 标准格式,含 system_prompt 与 model_config,导入任意 Agent 框架即可使用
.skill 文件中 system_prompt 字段的实际内容。
name api-development-standards description Node.js/Express/Prisma/PostgreSQL development patterns for Design Token Manager API. Use when working with controllers, routes, middleware, DAL, or database operations. Enforces multi-tenant isolation, Prisma best practices, Express patterns, authentication, and API response standards. 🔧 API Development Standards Enforces architectural patterns and best practices for the Design Token Manager API (Node.js/Express/Prisma/PostgreSQL). When to Use This Skill ALWAYS activate when: Creating or modifying API routes Building controllers or services Database operations with Prisma Adding middleware (auth, validation, tenant context) Multi-tenant data operations API authentication (JWT, API keys) Error handling and validation Writing tests for endpoints Architecture Overview Three-Layer Architecture ROUTES (Express) ↓ CONTROLLERS (Business Logic) ↓ DAL (Database Abstraction Layer) ↓ PRISMA (ORM) ↓ POSTGRESQL (Supabase) Key principles: Routes handle HTTP concerns only (validation, auth) Controllers contain business logic DAL provides database abstraction Prisma performs type-safe queries All data operations enforce tenant/project isolation Core Standards 1. Multi-Tenant Data Isolation CRITICAL : Every database query MUST include tenant/project filtering. ✅ CORRECT: // Controller with tenant/project filtering async function getTokens ( req, res, next ) { const { tenantId, projectId } = req. tenant ; // From tenantContext middleware const tokens = await databaseService. findTokensByProject (tenantId, projectId); res. json ({ tokens }); } ❌ WRONG: // Missing tenant/project isolation - SECURITY VULNERABILITY async function getTokens ( req, res, next ) { const tokens = await databaseService. findAllTokens (); // NO FILTERING! res. json ({ tokens }); } Rules: NEVER query without tenant/project filtering Use tenantContext middleware to extract tenant/project IDs DAL methods already enforce isolation - use them Test multi-tenant isolation in integration tests 2. Database Access via DAL ALWAYS use the Database Abstraction Layer, never direct Prisma calls in controllers. ✅ CORRECT: import databaseService from '../dal/DatabaseService.js' ; async function createToken ( req, res, next ) { const { tenantId, projectId } = req. tenant ; const tokenData = req. body ; const token = await databaseService. createToken ({ ...tokenData, tenantId, projectId }); res. status ( 201 ). json ({ token }); } ❌ WRONG: import prisma from '../config/prisma.js' ; async function createToken ( req, res, next ) { // Direct Prisma access bypasses DAL abstraction const token = await prisma. token . create ({ data : req. body }); res. json ({ token }); } Why: DAL provides database flexibility (could switch from Supabase) DAL methods enforce tenant isolation Consistent patterns across controllers Easier testing with DAL mocks 3. Controller Structure Controllers should follow this pattern: import databaseService from '../dal/DatabaseService.js' ; /** * Get all tokens for a project * @route GET /api/v1/tokens */ export async function listTokens ( req, res, next ) { try { const { tenantId, projectId } = req. tenant ; // From middleware const { page = 1 , limit = 20 , category } = req. query ; // Business logic const tokens = await databaseService. findTokensByProject ( tenantId, projectId, { page, limit, category } ); // Response res. json ({ tokens, pagination : { page, limit, total : tokens. length } }); } catch (error) { next (error); // Pass to error handler } } /** * Create a new token * @route POST /api/v1/tokens */ export async function createToken ( req, res, next ) { try { const { tenantId, projectId } = req. tenant ; const tokenData = req. body ; // Validation happens in route middleware // Business logic here const token = await databaseService. createToken ({ ...tokenData, tenantId, projectId }); res. status ( 201 ). json ({ token }); } catch (error) { next (error); } } Key points: Try/catch with next(error) for centralized error handling Extract tenant/project from req.tenant (middleware) JSDoc comments for route documentation Return consistent JSON responses Proper HTTP status codes (201 for created, 200 for success) 4. Route Structure Routes handle HTTP concerns, delegate to controllers: import express from 'express' ; import { body, query } from 'express-validator' ; import { verifyJWT } from '../middleware/verifyJWT.js' ; import { tenantContext } from '../middleware/tenantContext.js' ; import { requireRole } from '../middleware/requireRole.js' ; import * as tokenController from '../controllers/tokenController.js' ; const router = express. Router (); /** * @swagger * /api/v1/tokens: * get: * summary: List tokens for a project * tags: [Tokens] * security: * - BearerAuth: [] */ router. get ( '/' , verifyJWT, // Authentication tenantContext, // Multi-tenant context requireRole ([ 'admin' , 'editor' , 'viewer' ]), // Authorization query ( 'category' ). optional (). isString (), // Validation tokenController. listTokens // Controller ); /** * @swagger * /api/v1/tokens: * post: * summary: Create a new token */ router. post ( '/' , verifyJWT, tenantContext, requireRole ([ 'admin' , 'editor' ]), // Only admin/editor can create body ( 'name' ). notEmpty (). isString (), body ( 'value' ). notEmpty (). isString (), body ( 'category' ). optional (). isString (), tokenController. createToken ); export default router; Middleware order matters: Authentication ( verifyJWT or verifyApiKey ) Tenant context ( tenantContext ) Authorization ( requireRole ) Validation ( express-validator ) Controller 5. Prisma/DAL Best Practices When working in the DAL layer: ✅ Use transactions for multiple operations: async createTokenWithCategory ( tokenData ) { return await this . prisma .$transaction( async (tx) => { const category = await tx. category . findUnique ({ where : { name : tokenData. category } }); if (!category) { throw new Error ( 'Category not found' ); } return await tx. token . create ({ data : tokenData }); }); } ✅ Use proper error handling: async findTokenById ( id ) { try { const token = await this . prisma . token . findUnique ({ where : { id }, include : { tenant : true , project : true } }); if (!token) { return null ; // Let controller handle 404 } return token; } catch (error) { throw new Error ( `Failed to find token: ${error.message} ` ); } } ✅ Use select/include for performance: // Only fetch needed fields const tokens = await this . prisma . token . findMany ({ where : { tenantId, projectId }, select : { id : true , name : true , value : true , category : true // Don't fetch tenantId, projectId, createdAt if not needed } }); 6. Authentication Patterns JWT Authentication (Admin Users): import jwt from 'jsonwebtoken' ; export function verifyJWT ( req, res, next ) { const token = req. headers . authorization ?. split ( ' ' )[ 1 ]; if (!token) { return res. status ( 401 ). json ({ message : 'Authentication required' }); } try { const decoded = jwt. verify (token, process. env . JWT_SECRET ); req. user = decoded; // Attach user to request next (); } catch (error) { return res. status ( 401 ). json ({ message : 'Invalid token' }); } } API Key Authentication (Programmatic Access): export async function verifyApiKey ( req, res, next ) { const apiKey = req. headers . authorization ?. replace ( 'Bearer ' , '' ); if (!apiKey) { return res. status ( 401 ). json ({ message : 'API key required' }); } const hashedKey = hashApiKey (apiKey); const keyRecord = await databaseService. findApiKeyByHash (hashedKey); if (!keyRecord || keyRecord. revoked ) { return res. status ( 401 ). json ({ message : 'Invalid API key' }); } req. tenant = { tenantId : keyRecord. tenantId , projectId : keyRecord. projectId }; req. apiKey = keyRecord; next (); } 7. Error Handling Centralized error handler: export function errorHandler ( err, req, res, next ) { console . error (err. stack ); // Prisma errors if (err. code === 'P2002' ) { return res. status ( 409 ). json ({ message : 'Resource already exists' , field : err. meta ?. target }); } // Validation errors if (err. name === 'ValidationError' ) { return res. status ( 400 ). json ({ message : 'Validation failed' , errors : err. errors }); } // Default error res. status (err. status || 500 ). json ({ message : err. message || 'Internal server error' }); } Custom error classes: export class NotFoundError extends Error { constructor ( resource ) { super ( ` ${resource} not found` ); this . name = 'NotFoundError' ; this . status = 404 ; } } export class ForbiddenError extends Error { constructor ( message = 'Access forbidden' ) { super (message); this . name = 'ForbiddenError' ; this . status = 403 ; } } 8. Response Standards Consistent response format: ✅ Success (200/201): res. json ({ token : { id, name, value, category } }); // Or with pagination res. json ({ tokens : [...], pagination : { page : 1 , limit : 20 , total : 45 , pages : 3 } }); ✅ Created (201): res. status ( 201 ). json ({ token : newToken, message : 'Token created successfully' }); ✅ Error (4xx/5xx): res. status ( 404 ). json ({ message : 'Token not found' , code : 'RESOURCE_NOT_FOUND' }); 9. Testing Standards Integration tests for endpoints: import request from 'supertest' ; import app from '../src/index.js' ; import databaseService from '../src/dal/DatabaseService.js' ; describe ( 'POST /api/v1/tokens' , () => { let authToken; let tenantId; let projectId; beforeAll ( async () => { // Setup test data const tenant = await databaseService. createTenant ({ name : 'Test' }); tenantId = tenant. id ; const project = await databaseService. createProject ({ name : 'Test Project' , tenantId }); projectId = project. id ; // Get JWT token authToken = 'test-jwt-token' ; }); it ( 'should create a token with valid data' , async () => { const response = await request (app) . post ( '/api/v1/tokens' ) . set ( 'Authorization' , `Bearer ${authToken} ` ) . set ( 'X-Tenant-ID' , tenantId) . set ( 'X-Project-ID' , projectId) . send ({ name : 'primary-color' , value : '#007bff' , category : 'color' }); expect (response. status ). toBe ( 201 ); expect (response. body . token ). toHaveProperty ( 'id' ); expect (response. body . token . name ). toBe ( 'primary-color' ); });
Agent 识别该技能的关键词,点击任意一个即可复制。

该技能未提供触发词。

下载的 .skill 包内含以下字段。
字段 说明
format格式标识(skill/v1)
skill_id技能唯一 ID
name技能名称
version版本号
description技能描述
category所属分类(数组)
trigger_words触发词列表
tags标签列表
source来源标识
source_url来源链接(本页地址)
exported_at导出时间(每次下载生成)
system_prompt系统提示词正文
model_config模型参数:provider / model / temperature / max_tokens / top_p
examples示例
install_guide各平台导入说明(Coze / Dify / Claude / 自定义框架)
同一份技能可按不同平台格式导出。
.skill 标准格式,含 system_prompt 与 model_config,导入任意 Agent 框架即可使用 下载
.skillpro 增强格式,额外含脚本 / 工具 / 依赖 / 钩子占位 下载
.json 纯 JSON 导出,只含 system_prompt 与模型参数 下载
Coze 带 frontmatter 的 Markdown,Coze 平台导入用 下载
Dify Dify DSL,创建应用后直接导入 下载

每日精选 Skill 推荐,免费送到你邮箱

输入邮箱,每天接收一个精选 AI Agent 技能推荐。完全免费,持续更新。

验证码 --

提交后我们会发送一封确认邮件,点击邮件里的链接才会开始收信。

完全免费,取消任意时间。我们不会发送垃圾邮件。