encore-migrate

安装量: 114
排名: #7506

安装

npx skills add https://github.com/encoredev/skills --skill encore-migrate

Migrate to Encore.ts Instructions

When migrating existing Node.js applications to Encore.ts, follow these transformation patterns:

Express to Encore Basic Route // BEFORE: Express const express = require('express'); const app = express();

app.get('/users/:id', async (req, res) => { const user = await getUser(req.params.id); res.json(user); });

app.listen(3000);

// AFTER: Encore import { api } from "encore.dev/api";

interface GetUserRequest { id: string; }

interface User { id: string; email: string; name: string; }

export const getUser = api( { method: "GET", path: "/users/:id", expose: true }, async ({ id }: GetUserRequest): Promise => { return await findUser(id); } );

POST with Body // BEFORE: Express app.post('/users', async (req, res) => { const { email, name } = req.body; const user = await createUser(email, name); res.status(201).json(user); });

// AFTER: Encore interface CreateUserRequest { email: string; name: string; }

export const createUser = api( { method: "POST", path: "/users", expose: true }, async (req: CreateUserRequest): Promise => { return await insertUser(req.email, req.name); } );

Query Parameters // BEFORE: Express app.get('/users', async (req, res) => { const { limit, offset } = req.query; const users = await listUsers(Number(limit), Number(offset)); res.json(users); });

// AFTER: Encore import { Query, api } from "encore.dev/api";

interface ListUsersRequest { limit?: Query; offset?: Query; }

export const listUsers = api( { method: "GET", path: "/users", expose: true }, async ({ limit = 10, offset = 0 }: ListUsersRequest): Promise<{ users: User[] }> => { return { users: await fetchUsers(limit, offset) }; } );

Headers // BEFORE: Express app.post('/webhook', async (req, res) => { const signature = req.headers['x-signature']; // verify... });

// AFTER: Encore import { Header, api } from "encore.dev/api";

interface WebhookRequest { signature: Header<"X-Signature">; payload: any; }

export const webhook = api( { method: "POST", path: "/webhook", expose: true }, async ({ signature, payload }: WebhookRequest): Promise => { // verify signature... } );

Raw Request Access (Webhooks) // BEFORE: Express app.post('/webhooks/stripe', express.raw({ type: 'application/json' }), (req, res) => { const sig = req.headers['stripe-signature']; const event = stripe.webhooks.constructEvent(req.body, sig, secret); res.sendStatus(200); });

// AFTER: Encore export const stripeWebhook = api.raw( { expose: true, path: "/webhooks/stripe", method: "POST" }, async (req, res) => { const sig = req.headers["stripe-signature"]; const chunks: Buffer[] = []; for await (const chunk of req) { chunks.push(chunk); } const body = Buffer.concat(chunks); const event = stripe.webhooks.constructEvent(body, sig, secret); res.writeHead(200); res.end(); } );

Middleware // BEFORE: Express app.use((req, res, next) => { console.log(${req.method} ${req.path}); next(); });

// AFTER: Encore import { Service } from "encore.dev/service"; import { middleware } from "encore.dev/api";

const logMiddleware = middleware( { target: { all: true } }, async (req, next) => { console.log(${req.requestMeta?.method} ${req.requestMeta?.path}); return next(req); } );

export default new Service("my-service", { middlewares: [logMiddleware], });

Error Handling // BEFORE: Express app.get('/users/:id', async (req, res) => { const user = await getUser(req.params.id); if (!user) { return res.status(404).json({ error: 'User not found' }); } res.json(user); });

// AFTER: Encore import { APIError, api } from "encore.dev/api";

export const getUser = api( { method: "GET", path: "/users/:id", expose: true }, async ({ id }: GetUserRequest): Promise => { const user = await findUser(id); if (!user) { throw APIError.notFound("user not found"); } return user; } );

Database Migration // BEFORE: Express with pg import { Pool } from 'pg'; const pool = new Pool({ connectionString: process.env.DATABASE_URL });

const result = await pool.query('SELECT * FROM users WHERE id = $1', [id]);

// AFTER: Encore import { SQLDatabase } from "encore.dev/storage/sqldb";

const db = new SQLDatabase("users", { migrations: "./migrations", });

const user = await db.queryRowSELECT * FROM users WHERE id = ${id};

Cron Jobs // BEFORE: Node with node-cron import cron from 'node-cron';

cron.schedule('0 * * * *', () => { cleanupExpiredSessions(); });

// AFTER: Encore import { CronJob } from "encore.dev/cron"; import { api } from "encore.dev/api";

export const cleanupSessions = api( { expose: false }, async (): Promise => { // cleanup logic } );

const _ = new CronJob("cleanup-sessions", { title: "Cleanup expired sessions", schedule: "0 * * * *", endpoint: cleanupSessions, });

Migration Checklist Replace require with import Remove app.listen() - Encore handles this Convert routes to api() functions Define TypeScript interfaces for request/response Replace manual validation with Encore's type validation Convert error responses to APIError Move database connection to SQLDatabase Convert cron jobs to CronJob Move env vars to secret() for sensitive values Create encore.service.ts in each service directory

返回排行榜