Skip to main content
EVOKORE// BROWSE
>

./browse/prompts

2 NODES
šŸ¤–system prompt•7 months ago

bazel-build-optimization

Optimize Bazel builds for large-scale monorepos. Use when

coding
⭐1
# Bazel Build Optimization Production patterns for Bazel in large-scale monorepos. ## When to Use This Skill - Setting up Bazel for monorepos - Configuring remote caching/execution - Optimizing build times - Writing custom Bazel rules - Debugging build issues - Migrating to Bazel ## Core Concepts ### 1. Bazel Architecture ``` workspace/ ā”œā”€ā”€ WORKSPACE.bazel # External dependencies ā”œā”€ā”€ .bazelrc # Build configurations ā”œā”€ā”€ .bazelversion # Bazel version ā”œā”€ā”€ BUILD.bazel # Root build file ā”œā”€ā”€ apps/ │ └── web/ │ └── BUILD.bazel ā”œā”€ā”€ libs/ │ └── utils/ │ └── BUILD.bazel └── tools/ └── bazel/ └── rules/ ``` ### 2. Key Concepts | Concept | Description | | ----------- | -------------------------------------- | | **Target** | Buildable unit (library, binary, test) | | **Package** | Directory with BUILD file | | **Label** | Target identifier `//path/to:target` | | **Rule** | Defines how to build a target | | **Aspect** | Cross-cutting build behavior | ## Templates ### Template 1: WORKSPACE Configuration ```python # WORKSPACE.bazel workspace(name = "myproject") load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") # Rules for JavaScript/TypeScript http_archive( name = "aspect_rules_js", sha256 = "...", strip_prefix = "rules_js-1.34.0", url = "https://github.com/aspect-build/rules_js/releases/download/v1.34.0/rules_js-v1.34.0.tar.gz", ) load("@aspect_rules_js//js:repositories.bzl", "rules_js_dependencies") rules_js_dependencies() load("@rules_nodejs//nodejs:repositories.bzl", "nodejs_register_toolchains") nodejs_register_toolchains( name = "nodejs", node_version = "20.9.0", ) load("@aspect_rules_js//npm:repositories.bzl", "npm_translate_lock") npm_translate_lock( name = "npm", pnpm_lock = "//:pnpm-lock.yaml", verify_node_modules_ignored = "//:.bazelignore", ) load("@npm//:repositories.bzl", "npm_repositories") npm_repositories() # Rules for Python http_archive( name = "rules_python", sha256 = "...", strip_prefix = "rules_python-0.27.0", url = "https://github.com/bazelbuild/rules_python/releases/download/0.27.0/rules_python-0.27.0.tar.gz", ) load("@rules_python//python:repositories.bzl", "py_repositories") py_repositories() ``` ### Template 2: .bazelrc Configuration ```bash # .bazelrc # Build settings build --enable_platform_specific_config build --incompatible_enable_cc_toolchain_resolution build --experimental_strict_conflict_checks # Performance build --jobs=auto build --local_cpu_resources=HOST_CPUS*.75 build --local_ram_resources=HOST_RAM*.75 # Caching build --disk_cache=~/.cache/bazel-disk build --repository_cache=~/.cache/bazel-repo # Remote caching (optional) build:remote-cache --remote_cache=grpcs://cache.example.com build:remote-cache --remote_upload_local_results=true build:remote-cache --remote_timeout=3600 # Remote execution (optional) build:remote-exec --remote_executor=grpcs://remote.example.com build:remote-exec --remote_instance_name=projects/myproject/instances/default build:remote-exec --jobs=500 # Platform configurations build:linux --platforms=//platforms:linux_x86_64 build:macos --platforms=//platforms:macos_arm64 # CI configuration build:ci --config=remote-cache build:ci --build_metadata=ROLE=CI build:ci --bes_results_url=https://results.example.com/invocation/ build:ci --bes_backend=grpcs://bes.example.com # Test settings test --test_output=errors test --test_summary=detailed # Coverage coverage --combined_report=lcov coverage --instrumentation_filter="//..." # Convenience aliases build:opt --compilation_mode=opt build:dbg --compilation_mode=dbg # Import user settings try-import %workspace%/user.bazelrc ``` ### Template 3: TypeScript Library BUILD ```python # libs/utils/BUILD.bazel load("@aspect_rules_ts//ts:defs.bzl", "ts_project") load("@aspect_rules_js//js:defs.bzl", "js_library") load("@npm//:defs.bzl", "npm_link_all_packages") npm_link_all_packages(name = "node_modules") ts_project( name = "utils_ts", srcs = glob(["src/**/*.ts"]), declaration = True, source_map = True, tsconfig = "//:tsconfig.json", deps = [ ":node_modules/@types/node", ], ) js_library( name = "utils", srcs = [":utils_ts"], visibility = ["//visibility:public"], ) # Tests load("@aspect_rules_jest//jest:defs.bzl", "jest_test") jest_test( name = "utils_test", config = "//:jest.config.js", data = [ ":utils", "//:node_modules/jest", ], node_modules = "//:node_modules", ) ``` ### Template 4: Python Library BUILD ```python # libs/ml/BUILD.bazel load("@rules_python//python:defs.bzl", "py_library", "py_test", "py_binary") load("@pip//:requirements.bzl", "requirement") py_library( name = "ml", srcs = glob(["src/**/*.py"]), deps = [ requirement("numpy"), requirement("pandas"), requirement("scikit-learn"), "//libs/utils:utils_py", ], visibility = ["//visibility:public"], ) py_test( name = "ml_test", srcs = glob(["tests/**/*.py"]), deps = [ ":ml", requirement("pytest"), ], size = "medium", timeout = "moderate", ) py_binary( name = "train", srcs = ["train.py"], deps = [":ml"], data = ["//data:training_data"], ) ``` ### Template 5: Custom Rule for Docker ```python # tools/bazel/rules/docker.bzl def _docker_image_impl(ctx): dockerfile = ctx.file.dockerfile base_image = ctx.attr.base_image layers = ctx.files.layers # Build the image output = ctx.actions.declare_file(ctx.attr.name + ".tar") args = ctx.actions.args() args.add("--dockerfile", dockerfile) args.add("--output", output) args.add("--base", base_image) args.add_all("--layer", layers) ctx.actions.run( inputs = [dockerfile] + layers, outputs = [output], executable = ctx.executable._builder, arguments = [args], mnemonic = "DockerBuild", progress_message = "Building Docker image %s" % ctx.label, ) return [DefaultInfo(files = depset([output]))] docker_image = rule( implementation = _docker_image_impl, attrs = { "dockerfile": attr.label( allow_single_file = [".dockerfile", "Dockerfile"], mandatory = True, ), "base_image": attr.string(mandatory = True), "layers": attr.label_list(allow_files = True), "_builder": attr.label( default = "//tools/docker:builder", executable = True, cfg = "exec", ), }, ) ``` ### Template 6: Query and Dependency Analysis ```bash # Find all dependencies of a target bazel query "deps(//apps/web:web)" # Find reverse dependencies (what depends on this) bazel query "rdeps(//..., //libs/utils:utils)" # Find all targets in a package bazel query "//libs/..." # Find changed targets since commit bazel query "rdeps(//..., set($(git diff --name-only HEAD~1 | sed 's/.*/"&"/' | tr '\n' ' ')))" # Generate dependency graph bazel query "deps(//apps/web:web)" --output=graph | dot -Tpng > deps.png # Find all test targets bazel query "kind('.*_test', //...)" # Find targets with specific tag bazel query "attr(tags, 'integration', //...)" # Compute build graph size bazel query "deps(//...)" --output=package | wc -l ``` ### Template 7: Remote Execution Setup ```python # platforms/BUILD.bazel platform( name = "linux_x86_64", constraint_values = [ "@platforms//os:linux", "@platforms//cpu:x86_64", ], exec_properties = { "container-image": "docker://gcr.io/myproject/bazel-worker:latest", "OSFamily": "Linux", }, ) platform( name = "remote_linux", parents = [":linux_x86_64"], exec_properties = { "Pool": "default", "dockerNetwork": "standard", }, ) # toolchains/BUILD.bazel toolchain( name = "cc_toolchain_linux", exec_compatible_with = [ "@platforms//os:linux", "@platforms//cpu:x86_64", ], target_compatible_with = [ "@platforms//os:linux", "@platforms//cpu:x86_64", ], toolchain = "@remotejdk11_linux//:jdk", toolchain_type = "@bazel_tools//tools/jdk:runtime_toolchain_type", ) ``` ## Performance Optimization ```bash # Profile build bazel build //... --profile=profile.json bazel analyze-profile profile.json # Identify slow actions bazel build //... --execution_log_json_file=exec_log.json # Memory profiling bazel build //... --memory_profile=memory.json # Skip analysis cache bazel build //... --notrack_incremental_state ``` ## Best Practices ### Do's - **Use fine-grained targets** - Better caching - **Pin dependencies** - Reproducible builds - **Enable remote caching** - Share build artifacts - **Use visibility wisely** - Enforce architecture - **Write BUILD files per directory** - Standard convention ### Don'ts - **Don't use glob for deps** - Explicit is better - **Don't commit bazel-\* dirs** - Add to .gitignore - **Don't skip WORKSPACE setup** - Foundation of build - **Don't ignore build warnings** - Technical debt ## Resources - [Bazel Documentation](https://bazel.build/docs) - [Bazel Remote Execution](https://bazel.build/docs/remote-execution) - [rules_js](https://github.com/aspect-build/rules_js)
šŸ‘0
šŸ‘ļø0
šŸ¤– Auto-discovered
šŸ¤–system prompt•7 months ago

nodejs-backend-patterns

Build production-ready Node.js backend services with

coding
⭐1
# Node.js Backend Patterns Comprehensive guidance for building scalable, maintainable, and production-ready Node.js backend applications with modern frameworks, architectural patterns, and best practices. ## When to Use This Skill - Building REST APIs or GraphQL servers - Creating microservices with Node.js - Implementing authentication and authorization - Designing scalable backend architectures - Setting up middleware and error handling - Integrating databases (SQL and NoSQL) - Building real-time applications with WebSockets - Implementing background job processing ## Core Frameworks ### Express.js - Minimalist Framework **Basic Setup:** ```typescript import express, { Request, Response, NextFunction } from "express"; import helmet from "helmet"; import cors from "cors"; import compression from "compression"; const app = express(); // Security middleware app.use(helmet()); app.use(cors({ origin: process.env.ALLOWED_ORIGINS?.split(",") })); app.use(compression()); // Body parsing app.use(express.json({ limit: "10mb" })); app.use(express.urlencoded({ extended: true, limit: "10mb" })); // Request logging app.use((req: Request, res: Response, next: NextFunction) => { console.log(`${req.method} ${req.path}`); next(); }); const PORT = process.env.PORT || 3000; app.listen(PORT, () => { console.log(`Server running on port ${PORT}`); }); ``` ### Fastify - High Performance Framework **Basic Setup:** ```typescript import Fastify from "fastify"; import helmet from "@fastify/helmet"; import cors from "@fastify/cors"; import compress from "@fastify/compress"; const fastify = Fastify({ logger: { level: process.env.LOG_LEVEL || "info", transport: { target: "pino-pretty", options: { colorize: true }, }, }, }); // Plugins await fastify.register(helmet); await fastify.register(cors, { origin: true }); await fastify.register(compress); // Type-safe routes with schema validation fastify.post<{ Body: { name: string; email: string }; Reply: { id: string; name: string }; }>( "/users", { schema: { body: { type: "object", required: ["name", "email"], properties: { name: { type: "string", minLength: 1 }, email: { type: "string", format: "email" }, }, }, }, }, async (request, reply) => { const { name, email } = request.body; return { id: "123", name }; }, ); await fastify.listen({ port: 3000, host: "0.0.0.0" }); ``` ## Architectural Patterns ### Pattern 1: Layered Architecture **Structure:** ``` src/ ā”œā”€ā”€ controllers/ # Handle HTTP requests/responses ā”œā”€ā”€ services/ # Business logic ā”œā”€ā”€ repositories/ # Data access layer ā”œā”€ā”€ models/ # Data models ā”œā”€ā”€ middleware/ # Express/Fastify middleware ā”œā”€ā”€ routes/ # Route definitions ā”œā”€ā”€ utils/ # Helper functions ā”œā”€ā”€ config/ # Configuration └── types/ # TypeScript types ``` **Controller Layer:** ```typescript // controllers/user.controller.ts import { Request, Response, NextFunction } from "express"; import { UserService } from "../services/user.service"; import { CreateUserDTO, UpdateUserDTO } from "../types/user.types"; export class UserController { constructor(private userService: UserService) {} async createUser(req: Request, res: Response, next: NextFunction) { try { const userData: CreateUserDTO = req.body; const user = await this.userService.createUser(userData); res.status(201).json(user); } catch (error) { next(error); } } async getUser(req: Request, res: Response, next: NextFunction) { try { const { id } = req.params; const user = await this.userService.getUserById(id); res.json(user); } catch (error) { next(error); } } async updateUser(req: Request, res: Response, next: NextFunction) { try { const { id } = req.params; const updates: UpdateUserDTO = req.body; const user = await this.userService.updateUser(id, updates); res.json(user); } catch (error) { next(error); } } async deleteUser(req: Request, res: Response, next: NextFunction) { try { const { id } = req.params; await this.userService.deleteUser(id); res.status(204).send(); } catch (error) { next(error); } } } ``` **Service Layer:** ```typescript // services/user.service.ts import { UserRepository } from "../repositories/user.repository"; import { CreateUserDTO, UpdateUserDTO, User } from "../types/user.types"; import { NotFoundError, ValidationError } from "../utils/errors"; import bcrypt from "bcrypt"; export class UserService { constructor(private userRepository: UserRepository) {} async createUser(userData: CreateUserDTO): Promise<User> { // Validation const existingUser = await this.userRepository.findByEmail(userData.email); if (existingUser) { throw new ValidationError("Email already exists"); } // Hash password const hashedPassword = await bcrypt.hash(userData.password, 10); // Create user const user = await this.userRepository.create({ ...userData, password: hashedPassword, }); // Remove password from response const { password, ...userWithoutPassword } = user; return userWithoutPassword as User; } async getUserById(id: string): Promise<User> { const user = await this.userRepository.findById(id); if (!user) { throw new NotFoundError("User not found"); } const { password, ...userWithoutPassword } = user; return userWithoutPassword as User; } async updateUser(id: string, updates: UpdateUserDTO): Promise<User> { const user = await this.userRepository.update(id, updates); if (!user) { throw new NotFoundError("User not found"); } const { password, ...userWithoutPassword } = user; return userWithoutPassword as User; } async deleteUser(id: string): Promise<void> { const deleted = await this.userRepository.delete(id); if (!deleted) { throw new NotFoundError("User not found"); } } } ``` **Repository Layer:** ```typescript // repositories/user.repository.ts import { Pool } from "pg"; import { CreateUserDTO, UpdateUserDTO, UserEntity } from "../types/user.types"; export class UserRepository { constructor(private db: Pool) {} async create( userData: CreateUserDTO & { password: string }, ): Promise<UserEntity> { const query = ` INSERT INTO users (name, email, password) VALUES ($1, $2, $3) RETURNING id, name, email, password, created_at, updated_at `; const { rows } = await this.db.query(query, [ userData.name, userData.email, userData.password, ]); return rows[0]; } async findById(id: string): Promise<UserEntity | null> { const query = "SELECT * FROM users WHERE id = $1"; const { rows } = await this.db.query(query, [id]); return rows[0] || null; } async findByEmail(email: string): Promise<UserEntity | null> { const query = "SELECT * FROM users WHERE email = $1"; const { rows } = await this.db.query(query, [email]); return rows[0] || null; } async update(id: string, updates: UpdateUserDTO): Promise<UserEntity | null> { const fields = Object.keys(updates); const values = Object.values(updates); const setClause = fields .map((field, idx) => `${field} = $${idx + 2}`) .join(", "); const query = ` UPDATE users SET ${setClause}, updated_at = CURRENT_TIMESTAMP WHERE id = $1 RETURNING * `; const { rows } = await this.db.query(query, [id, ...values]); return rows[0] || null; } async delete(id: string): Promise<boolean> { const query = "DELETE FROM users WHERE id = $1"; const { rowCount } = await this.db.query(query, [id]); return rowCount > 0; } } ``` ### Pattern 2: Dependency Injection **DI Container:** ```typescript // di-container.ts import { Pool } from "pg"; import { UserRepository } from "./repositories/user.repository"; import { UserService } from "./services/user.service"; import { UserController } from "./controllers/user.controller"; import { AuthService } from "./services/auth.service"; class Container { private instances = new Map<string, any>(); register<T>(key: string, factory: () => T): void { this.instances.set(key, factory); } resolve<T>(key: string): T { const factory = this.instances.get(key); if (!factory) { throw new Error(`No factory registered for ${key}`); } return factory(); } singleton<T>(key: string, factory: () => T): void { let instance: T; this.instances.set(key, () => { if (!instance) { instance = factory(); } return instance; }); } } export const container = new Container(); // Register dependencies container.singleton( "db", () => new Pool({ host: process.env.DB_HOST, port: parseInt(process.env.DB_PORT || "5432"), database: process.env.DB_NAME, user: process.env.DB_USER, password: process.env.DB_PASSWORD, max: 20, idleTimeoutMillis: 30000, connectionTimeoutMillis: 2000, }), ); container.singleton( "userRepository", () => new UserRepository(container.resolve("db")), ); container.singleton( "userService", () => new UserService(container.resolve("userRepository")), ); container.register( "userController", () => new UserController(container.resolve("userService")), ); container.singleton( "authService", () => new AuthService(container.resolve("userRepository")), ); ``` ## Middleware Patterns ### Authentication Middleware ```typescript // middleware/auth.middleware.ts import { Request, Response, NextFunction } from "express"; import jwt from "jsonwebtoken"; import { UnauthorizedError } from "../utils/errors"; interface JWTPayload { userId: string; email: string; } declare global { namespace Express { interface Request { user?: JWTPayload; } } } export const authenticate = async ( req: Request, res: Response, next: NextFunction, ) => { try { const token = req.headers.authorization?.replace("Bearer ", ""); if (!token) { throw new UnauthorizedError("No token provided"); } const payload = jwt.verify(token, process.env.JWT_SECRET!) as JWTPayload; req.user = payload; next(); } catch (error) { next(new UnauthorizedError("Invalid token")); } }; export const authorize = (...roles: string[]) => { return async (req: Request, res: Response, next: NextFunction) => { if (!req.user) { return next(new UnauthorizedError("Not authenticated")); } // Check if user has required role const hasRole = roles.some((role) => req.user?.roles?.includes(role)); if (!hasRole) { return next(new UnauthorizedError("Insufficient permissions")); } next(); }; }; ``` ### Validation Middleware ```typescript // middleware/validation.middleware.ts import { Request, Response, NextFunction } from "express"; import { AnyZodObject, ZodError } from "zod"; import { ValidationError } from "../utils/errors"; export const validate = (schema: AnyZodObject) => { return async (req: Request, res: Response, next: NextFunction) => { try { await schema.parseAsync({ body: req.body, query: req.query, params: req.params, }); next(); } catch (error) { if (error instanceof ZodError) { const errors = error.errors.map((err) => ({ field: err.path.join("."), message: err.message, })); next(new ValidationError("Validation failed", errors)); } else { next(error); } } }; }; // Usage with Zod import { z } from "zod"; const createUserSchema = z.object({ body: z.object({ name: z.string().min(1), email: z.string().email(), password: z.string().min(8), }), }); router.post("/users", validate(createUserSchema), userController.createUser); ``` ### Rate Limiting Middleware ```typescript // middleware/rate-limit.middleware.ts import rateLimit from "express-rate-limit"; import RedisStore from "rate-limit-redis"; import Redis from "ioredis"; const redis = new Redis({ host: process.env.REDIS_HOST, port: parseInt(process.env.REDIS_PORT || "6379"), }); export const apiLimiter = rateLimit({ store: new RedisStore({ client: redis, prefix: "rl:", }), windowMs: 15 * 60 * 1000, // 15 minutes max: 100, // Limit each IP to 100 requests per windowMs message: "Too many requests from this IP, please try again later", standardHeaders: true, legacyHeaders: false, }); export const authLimiter = rateLimit({ store: new RedisStore({ client: redis, prefix: "rl:auth:", }), windowMs: 15 * 60 * 1000, max: 5, // Stricter limit for auth endpoints skipSuccessfulRequests: true, }); ``` ### Request Logging Middleware ```typescript // middleware/logger.middleware.ts import { Request, Response, NextFunction } from "express"; import pino from "pino"; const logger = pino({ level: process.env.LOG_LEVEL || "info", transport: { target: "pino-pretty", options: { colorize: true }, }, }); export const requestLogger = ( req: Request, res: Response, next: NextFunction, ) => { const start = Date.now(); // Log response when finished res.on("finish", () => { const duration = Date.now() - start; logger.info({ method: req.method, url: req.url, status: res.statusCode, duration: `${duration}ms`, userAgent: req.headers["user-agent"], ip: req.ip, }); }); next(); }; export { logger }; ``` ## Error Handling ### Custom Error Classes ```typescript // utils/errors.ts export class AppError extends Error { constructor( public message: string, public statusCode: number = 500, public isOperational: boolean = true, ) { super(message); Object.setPrototypeOf(this, AppError.prototype); Error.captureStackTrace(this, this.constructor); } } export class ValidationError extends AppError { constructor( message: string, public errors?: any[], ) { super(message, 400); } } export class NotFoundError extends AppError { constructor(message: string = "Resource not found") { super(message, 404); } } export class UnauthorizedError extends AppError { constructor(message: string = "Unauthorized") { super(message, 401); } } export class ForbiddenError extends AppError { constructor(message: string = "Forbidden") { super(message, 403); } } export class ConflictError extends AppError { constructor(message: string) { super(message, 409); } } ``` ### Global Error Handler ```typescript // middleware/error-handler.ts import { Request, Response, NextFunction } from "express"; import { AppError } from "../utils/errors"; import { logger } from "./logger.middleware"; export const errorHandler = ( err: Error, req: Request, res: Response, next: NextFunction, ) => { if (err instanceof AppError) { return res.status(err.statusCode).json({ status: "error", message: err.message, ...(err instanceof ValidationError && { errors: err.errors }), }); } // Log unexpected errors logger.error({ error: err.message, stack: err.stack, url: req.url, method: req.method, }); // Don't leak error details in production const message = process.env.NODE_ENV === "production" ? "Internal server error" : err.message; res.status(500).json({ status: "error", message, }); }; // Async error wrapper export const asyncHandler = ( fn: (req: Request, res: Response, next: NextFunction) => Promise<any>, ) => { return (req: Request, res: Response, next: NextFunction) => { Promise.resolve(fn(req, res, next)).catch(next); }; }; ``` ## Database Patterns ### PostgreSQL with Connection Pool ```typescript // config/database.ts import { Pool, PoolConfig } from "pg"; const poolConfig: PoolConfig = { host: process.env.DB_HOST, port: parseInt(process.env.DB_PORT || "5432"), database: process.env.DB_NAME, user: process.env.DB_USER, password: process.env.DB_PASSWORD, max: 20, idleTimeoutMillis: 30000, connectionTimeoutMillis: 2000, }; export const pool = new Pool(poolConfig); // Test connection pool.on("connect", () => { console.log("Database connected"); }); pool.on("error", (err) => { console.error("Unexpected database error", err); process.exit(-1); }); // Graceful shutdown export const closeDatabase = async () => { await pool.end(); console.log("Database connection closed"); }; ``` ### MongoDB with Mongoose ```typescript // config/mongoose.ts import mongoose from "mongoose"; const connectDB = async () => { try { await mongoose.connect(process.env.MONGODB_URI!, { maxPoolSize: 10, serverSelectionTimeoutMS: 5000, socketTimeoutMS: 45000, }); console.log("MongoDB connected"); } catch (error) { console.error("MongoDB connection error:", error); process.exit(1); } }; mongoose.connection.on("disconnected", () => { console.log("MongoDB disconnected"); }); mongoose.connection.on("error", (err) => { console.error("MongoDB error:", err); }); export { connectDB }; // Model example import { Schema, model, Document } from "mongoose"; interface IUser extends Document { name: string; email: string; password: string; createdAt: Date; updatedAt: Date; } const userSchema = new Schema<IUser>( { name: { type: String, required: true }, email: { type: String, required: true, unique: true }, password: { type: String, required: true }, }, { timestamps: true, }, ); // Indexes userSchema.index({ email: 1 }); export const User = model<IUser>("User", userSchema); ``` ### Transaction Pattern ```typescript // services/order.service.ts import { Pool } from "pg"; export class OrderService { constructor(private db: Pool) {} async createOrder(userId: string, items: any[]) { const client = await this.db.connect(); try { await client.query("BEGIN"); // Create order const orderResult = await client.query( "INSERT INTO orders (user_id, total) VALUES ($1, $2) RETURNING id", [userId, calculateTotal(items)], ); const orderId = orderResult.rows[0].id; // Create order items for (const item of items) { await client.query( "INSERT INTO order_items (order_id, product_id, quantity, price) VALUES ($1, $2, $3, $4)", [orderId, item.productId, item.quantity, item.price], ); // Update inventory await client.query( "UPDATE products SET stock = stock - $1 WHERE id = $2", [item.quantity, item.productId], ); } await client.query("COMMIT"); return orderId; } catch (error) { await client.query("ROLLBACK"); throw error; } finally { client.release(); } } } ``` ## Authentication & Authorization ### JWT Authentication ```typescript // services/auth.service.ts import jwt from
šŸ‘0
šŸ‘ļø0
šŸ¤– Auto-discovered