startup-mvp
Complete toolkit for building a startup MVP - React/Next.js frontend, Node.js/Express backend, PostgreSQL database, authentication, deployment, and testing
prpm install startup-mvp packages
📦 Packages (10)
#1
@sanjeed5/react
RequiredVersion: latest
📄 Prompt Content
# React Best Practices: A Comprehensive Guide
This document outlines the best practices for developing React applications, covering various aspects from code organization to security and testing. Following these guidelines leads to more maintainable, scalable, and performant applications.
## 1. Code Organization and Structure
### 1.1 Directory Structure
A well-defined directory structure is crucial for maintainability. Here's a recommended structure:
src/
├── components/
│ ├── Button/
│ │ ├── Button.jsx
│ │ ├── Button.module.css
│ │ └── Button.test.jsx
│ ├── Input/
│ │ ├── Input.jsx
│ │ ├── Input.module.css
│ │ └── Input.test.jsx
│ └── ...
├── contexts/
│ ├── AuthContext.jsx
│ └── ThemeContext.jsx
├── hooks/
│ ├── useAuth.js
│ └── useTheme.js
├── pages/
│ ├── Home.jsx
│ ├── About.jsx
│ └── ...
├── services/
│ ├── api.js
│ └── auth.js
├── utils/
│ ├── helpers.js
│ └── validators.js
├── App.jsx
├── index.jsx
└── ...
- **`components/`**: Reusable UI components.
- Each component has its own directory containing the component file, associated styles (using CSS modules), and tests.
- **`contexts/`**: React context providers.
- **`hooks/`**: Custom React hooks.
- **`pages/`**: Top-level components representing different routes or views.
- **`services/`**: API interaction logic.
- **`utils/`**: Utility functions.
### 1.2 File Naming Conventions
- **Components**: Use PascalCase (e.g., `MyComponent.jsx`).
- **Hooks**: Use camelCase prefixed with `use` (e.g., `useMyHook.js`).
- **Contexts**: Use PascalCase suffixed with `Context` (e.g., `MyContext.jsx`).
- **Services/Utils**: Use camelCase (e.g., `apiService.js`, `stringUtils.js`).
- **CSS Modules**: Use `.module.css` or `.module.scss` (e.g., `Button.module.css`).
### 1.3 Module Organization
- **Co-location**: Keep related files (component, styles, tests) together in the same directory.
- **Single Responsibility**: Each module should have a clear and specific purpose.
- **Avoid Circular Dependencies**: Ensure modules don't depend on each other in a circular manner.
### 1.4 Component Architecture
- **Atomic Design**: Consider using Atomic Design principles (Atoms, Molecules, Organisms, Templates, Pages) to structure components.
- **Composition over Inheritance**: Favor component composition to reuse code and functionality.
- **Presentational and Container Components**: Separate UI rendering (presentational) from state management and logic (container).
### 1.5 Code Splitting Strategies
- **Route-Based Splitting**: Use `React.lazy` and `Suspense` to load components only when a specific route is accessed. This is very common and improves initial load time.
- **Component-Based Splitting**: Split large components into smaller chunks that can be loaded on demand.
- **Bundle Analyzer**: Use a tool like `webpack-bundle-analyzer` to identify large dependencies and optimize bundle size.
## 2. Common Patterns and Anti-patterns
### 2.1 Design Patterns
- **Higher-Order Components (HOCs)**: Reusable logic that wraps components (use with caution; prefer hooks).
- **Render Props**: Sharing code using a prop whose value is a function.
- **Compound Components**: Components that work together implicitly (e.g., `Tabs`, `Tab`).
- **Hooks**: Reusable stateful logic that can be shared across functional components.
### 2.2 Recommended Approaches
- **Form Handling**: Use controlled components with local state or a form library like Formik or React Hook Form.
- **API Calls**: Use `useEffect` hook to make API calls and manage loading states.
- **Conditional Rendering**: Use short-circuit evaluation (`&&`) or ternary operators for simple conditions; use separate components for complex scenarios.
- **List Rendering**: Always provide a unique and stable `key` prop when rendering lists.
### 2.3 Anti-patterns and Code Smells
- **Direct DOM Manipulation**: Avoid directly manipulating the DOM; let React handle updates.
- **Mutating State Directly**: Always use `setState` or the state updater function to modify state.
- **Inline Styles**: Use CSS modules or styled-components for maintainable styles.
- **Over-Engineering**: Avoid using complex solutions for simple problems.
- **Prop Drilling**: Passing props through multiple levels of components without them being used.
### 2.4 State Management Best Practices
- **Local State**: Use `useState` for component-specific state.
- **Context API**: Use `useContext` for global state accessible to many components, but avoid for very frequently updated data.
- **Redux/Mobx**: Use these libraries for complex state management in large applications.
- **Recoil/Zustand**: Lightweight alternatives to Redux, often easier to set up and use.
- **Immutable Data**: Treat state as immutable to prevent unexpected side effects.
### 2.5 Error Handling Patterns
- **Error Boundaries**: Wrap components with error boundaries to catch errors during rendering and prevent crashes.
- **Try-Catch Blocks**: Use try-catch blocks for handling errors in asynchronous operations and event handlers.
- **Centralized Error Logging**: Implement a centralized error logging service to track errors and improve application stability.
## 3. Performance Considerations
### 3.1 Optimization Techniques
- **Memoization**: Use `React.memo`, `useMemo`, and `useCallback` to prevent unnecessary re-renders and recalculations.
- **Virtualization**: Use libraries like `react-window` or `react-virtualized` to efficiently render large lists or tables.
- **Debouncing/Throttling**: Limit the rate at which functions are executed (e.g., in input fields).
- **Code Splitting**: Load code on demand using `React.lazy` and `Suspense`.
### 3.2 Memory Management
- **Avoid Memory Leaks**: Clean up event listeners, timers, and subscriptions in `useEffect`'s cleanup function.
- **Release Unused Objects**: Avoid holding onto large objects in memory when they are no longer needed.
- **Garbage Collection**: Understand how JavaScript's garbage collection works and avoid creating unnecessary objects.
### 3.3 Rendering Optimization
- **Minimize State Updates**: Avoid unnecessary state updates that trigger re-renders.
- **Batch Updates**: Batch multiple state updates into a single update using `ReactDOM.unstable_batchedUpdates`.
- **Keys**: Ensure that keys are unique and consistent across renders.
### 3.4 Bundle Size Optimization
- **Tree Shaking**: Remove unused code during the build process.
- **Minification**: Reduce the size of JavaScript and CSS files.
- **Image Optimization**: Compress and optimize images to reduce file size.
- **Dependency Analysis**: Use tools like `webpack-bundle-analyzer` to identify large dependencies.
### 3.5 Lazy Loading Strategies
- **Route-Based Lazy Loading**: Load components when a user navigates to a specific route.
- **Component-Based Lazy Loading**: Load components when they are about to be rendered.
- **Intersection Observer**: Load components when they become visible in the viewport.
## 4. Security Best Practices
### 4.1 Common Vulnerabilities and Prevention
- **Cross-Site Scripting (XSS)**: Sanitize user input to prevent malicious code injection.
- **Cross-Site Request Forgery (CSRF)**: Use anti-CSRF tokens to protect against unauthorized requests.
- **Denial of Service (DoS)**: Implement rate limiting and request validation to prevent abuse.
- **Injection Attacks**: Avoid directly embedding user input into database queries or system commands.
### 4.2 Input Validation
- **Client-Side Validation**: Validate user input in the browser to provide immediate feedback.
- **Server-Side Validation**: Always validate user input on the server to prevent malicious data.
- **Sanitize Input**: Sanitize user input to remove potentially harmful characters or code.
### 4.3 Authentication and Authorization
- **Secure Authentication**: Use secure authentication mechanisms like OAuth 2.0 or JWT.
- **Role-Based Access Control (RBAC)**: Implement RBAC to control access to resources based on user roles.
- **Multi-Factor Authentication (MFA)**: Enable MFA to add an extra layer of security.
### 4.4 Data Protection Strategies
- **Encryption**: Encrypt sensitive data at rest and in transit.
- **Data Masking**: Mask sensitive data in logs and UI displays.
- **Regular Backups**: Create regular backups of application data.
### 4.5 Secure API Communication
- **HTTPS**: Use HTTPS to encrypt communication between the client and the server.
- **API Keys**: Protect API keys and secrets.
- **CORS**: Configure Cross-Origin Resource Sharing (CORS) to prevent unauthorized access to APIs.
## 5. Testing Approaches
### 5.1 Unit Testing
- **Test Components**: Test individual components in isolation.
- **Testing Library**: Use React Testing Library for UI testing, focusing on user behavior.
- **Jest**: Use Jest as the test runner.
### 5.2 Integration Testing
- **Test Component Interactions**: Test how components interact with each other.
- **Mock API Calls**: Mock API calls to test component behavior in different scenarios.
- **React Testing Library**: Effective for testing integration points in components.
### 5.3 End-to-End (E2E) Testing
- **Test Full Application Flows**: Test complete user flows, such as login, registration, and checkout.
- **Cypress/Playwright**: Use tools like Cypress or Playwright for E2E testing.
- **Automated Browser Tests**: Automate browser tests to ensure application stability.
### 5.4 Test Organization
- **Co-locate Tests**: Keep test files close to the components they test (e.g., `Button.test.jsx` in the `Button` directory).
- **Descriptive Names**: Use descriptive names for test files and test cases.
- **Test Suites**: Organize tests into logical suites.
### 5.5 Mocking and Stubbing
- **Mock Modules**: Mock external modules or API calls to isolate components during testing.
- **Stub Functions**: Stub function implementations to control component behavior.
- **Jest Mocks**: Utilize Jest's mocking capabilities for effective unit testing.
## 6. Common Pitfalls and Gotchas
### 6.1 Frequent Mistakes
- **Ignoring Keys in Lists**: Forgetting to provide unique and stable `key` props when rendering lists.
- **Incorrect State Updates**: Mutating state directly instead of using `setState` or the state updater function.
- **Missing Dependencies in `useEffect`**: Not including all dependencies in the dependency array of the `useEffect` hook.
- **Over-Using State**: Storing derived data in state instead of calculating it on demand.
### 6.2 Edge Cases
- **Asynchronous State Updates**: Handling state updates in asynchronous operations.
- **Race Conditions**: Preventing race conditions when making multiple API calls.
- **Handling Errors in Event Handlers**: Properly handling errors in event handlers to prevent crashes.
### 6.3 Version-Specific Issues
- **React 16 vs. React 17/18**: Understanding differences in lifecycle methods, error handling, and concurrent mode.
- **Deprecated Features**: Being aware of deprecated features and using recommended alternatives.
### 6.4 Compatibility Concerns
- **Browser Compatibility**: Ensuring compatibility with different browsers and devices.
- **Library Compatibility**: Ensuring compatibility between React and other libraries.
### 6.5 Debugging Strategies
- **React DevTools**: Use React DevTools to inspect component hierarchies, props, and state.
- **Console Logging**: Use console logging to debug code and track variables.
- **Breakpoints**: Set breakpoints in the code to step through execution and inspect variables.
## 7. Tooling and Environment
### 7.1 Recommended Development Tools
- **VS Code**: A popular code editor with excellent React support.
- **Create React App**: A tool for quickly setting up a new React project.
- **React DevTools**: A browser extension for inspecting React components.
- **ESLint**: A linter for enforcing code style and preventing errors.
- **Prettier**: A code formatter for automatically formatting code.
### 7.2 Build Configuration
- **Webpack/Vite**: Configure Webpack or Vite to bundle and optimize code.
- **Babel**: Configure Babel to transpile JavaScript code to older versions.
- **Environment Variables**: Use environment variables to configure different environments.
### 7.3 Linting and Formatting
- **ESLint**: Configure ESLint with recommended React rules.
- **Prettier**: Configure Prettier to automatically format code.
- **Husky/lint-staged**: Use Husky and lint-staged to run linters and formatters before committing code.
### 7.4 Deployment Best Practices
- **Static Hosting**: Host static assets on a CDN.
- **Server-Side Rendering (SSR)**: Use SSR to improve SEO and initial load time.
- **Continuous Deployment**: Automate the deployment process using CI/CD.
### 7.5 CI/CD Integration
- **GitHub Actions/GitLab CI**: Use GitHub Actions or GitLab CI to automate testing, linting, and deployment.
- **Automated Testing**: Run automated tests on every commit or pull request.
- **Automated Deployment**: Automatically deploy code to production after successful tests.
By following these best practices, React developers can build high-quality, maintainable, and scalable applications that meet the demands of modern web development. Continual education and adaptation to emerging trends in the React ecosystem are crucial for sustained success.#2
@sanjeed5/typescript
RequiredVersion: latest
📄 Prompt Content
# TypeScript Best Practices and Coding Standards
This document outlines best practices and coding standards for developing TypeScript applications. Following these guidelines will help ensure code quality, maintainability, and scalability.
## 1. Code Organization and Structure
- **Directory Structure:**
- **Feature-based:** Group files related to a specific feature within a dedicated directory.
src/
├── feature1/
│ ├── components/
│ │ ├── ComponentA.tsx
│ │ └── ComponentB.tsx
│ ├── services/
│ │ └── feature1.service.ts
│ ├── types.ts
│ └── feature1.module.ts
├── feature2/
│ └── ...
└── shared/
├── components/
│ └── ReusableComponent.tsx
├── services/
│ └── api.service.ts
└── types/
└── global.d.ts
- **Type-based:** Separate files based on their role (components, services, types, etc.).
src/
├── components/
│ ├── Feature1Component.tsx
│ └── Feature2Component.tsx
├── services/
│ ├── feature1.service.ts
│ └── feature2.service.ts
├── types/
│ ├── feature1.types.ts
│ └── feature2.types.ts
└── modules/
├── feature1.module.ts
└── feature2.module.ts
- Choose the structure that best fits your project's complexity and team's preferences. Consistency is key.
- **File Naming Conventions:**
- Use descriptive and consistent file names.
- Components: `ComponentName.tsx`
- Services: `serviceName.service.ts`
- Types: `typeName.types.ts` or `types.ts` (if grouping related types)
- Modules: `moduleName.module.ts`
- Interfaces: `IInterfaceName.ts` (or `interfaceName.interface.ts` if preferred and consistent throughout the codebase)
- **Module Organization:**
- Use ES Modules (`import`/`export`) for modularity and reusability.
- Favor named exports over default exports for better discoverability and refactoring.
- Group related functionality into modules.
- Avoid circular dependencies.
- **Component Architecture:**
- Consider using component-based architectures like React, Angular, or Vue.js.
- Follow component design principles: Single Responsibility Principle, separation of concerns.
- Use composition over inheritance.
- Keep components small and focused.
- **Code Splitting Strategies:**
- Split your application into smaller chunks to improve initial load time.
- Implement lazy loading for modules and components that are not immediately needed.
- Use dynamic imports (`import()`).
- Webpack, Parcel, and other bundlers offer built-in support for code splitting.
## 2. Common Patterns and Anti-patterns
- **Design Patterns:**
- **Factory Pattern:** Use factories to create objects with complex initialization logic.
- **Singleton Pattern:** Use sparingly, and only when a single instance is truly required.
- **Observer Pattern:** Implement reactive patterns for handling events and data changes.
- **Strategy Pattern:** Define a family of algorithms and encapsulate each one into a separate class.
- **Dependency Injection:** Reduce coupling by injecting dependencies into components and services.
- **Recommended Approaches:**
- **Data Fetching:** Use libraries like `axios` or `fetch` for making API requests.
- **State Management:** Choose a state management solution appropriate for your application's complexity (e.g., React Context, Redux, Zustand, MobX).
- **Form Handling:** Use libraries like `react-hook-form` or `formik` for managing form state and validation.
- **Anti-patterns and Code Smells:**
- **`any` type overuse:** Avoid using `any` as much as possible. Use more specific types or generics.
- **Long methods/functions:** Break down large functions into smaller, more manageable units.
- **Deeply nested code:** Refactor deeply nested code to improve readability.
- **Magic numbers/strings:** Use constants for values that have a specific meaning.
- **Duplicated code:** Extract common logic into reusable functions or components.
- **Ignoring errors:** Always handle errors gracefully. Don't just catch and ignore them.
- **Over-commenting:** Write self-documenting code and use comments only when necessary to explain complex logic.
- **State Management Best Practices:**
- Choose a state management library based on project needs: React Context API, Redux, Zustand, MobX.
- Keep state minimal and derive values where possible.
- Follow immutable update patterns (especially with Redux).
- Use selectors to access state.
- Centralize state logic.
- **Error Handling Patterns:**
- Use `try...catch` blocks to handle potential errors.
- Implement a global error handler to catch unhandled exceptions.
- Use error logging to track errors in production.
- Use discriminated unions for representing different error states.
- Implement retry mechanisms for transient errors.
## 3. Performance Considerations
- **Optimization Techniques:**
- **Memoization:** Use memoization techniques (e.g., `React.memo`, `useMemo`) to avoid unnecessary re-renders.
- **Debouncing and Throttling:** Limit the rate at which functions are executed in response to user input.
- **Virtualization:** Use virtualization for rendering large lists or tables.
- **Code Splitting:** Split your code into smaller chunks to reduce initial load time.
- **Memory Management:**
- Avoid memory leaks by properly cleaning up resources (e.g., event listeners, timers).
- Use weak references to avoid circular dependencies that can prevent garbage collection.
- Profile your application to identify memory leaks.
- **Rendering Optimization:**
- Minimize DOM manipulations.
- Use CSS transforms and animations instead of JavaScript animations.
- Optimize images and other assets.
- Use the `shouldComponentUpdate` lifecycle method or `React.memo` to prevent unnecessary re-renders.
- **Bundle Size Optimization:**
- Use tree shaking to remove unused code from your bundle.
- Minify your code to reduce bundle size.
- Compress your code using gzip or Brotli.
- Use code splitting to load only the code that is needed for a particular page or component.
- **Lazy Loading Strategies:**
- Lazy load modules and components that are not immediately needed.
- Use dynamic imports (`import()`) to load modules on demand.
- Implement a loading indicator to provide feedback to the user while the module is loading.
## 4. Security Best Practices
- **Common Vulnerabilities and Prevention:**
- **Cross-Site Scripting (XSS):** Sanitize user input and escape output to prevent XSS attacks.
- **Cross-Site Request Forgery (CSRF):** Use anti-CSRF tokens to protect against CSRF attacks.
- **SQL Injection:** Use parameterized queries or ORMs to prevent SQL injection attacks (relevant for backend TypeScript).
- **Denial of Service (DoS):** Implement rate limiting and other measures to prevent DoS attacks.
- **Man-in-the-Middle (MitM):** Use HTTPS to encrypt communication between the client and server.
- **Input Validation:**
- Validate all user input on both the client and server sides.
- Use strong validation rules to prevent malicious input.
- Sanitize user input to remove potentially harmful characters.
- **Authentication and Authorization Patterns:**
- Use a secure authentication mechanism to verify user identities.
- Implement authorization checks to control access to resources.
- Use role-based access control (RBAC) to manage user permissions.
- Use JSON Web Tokens (JWT) for stateless authentication.
- **Data Protection Strategies:**
- Encrypt sensitive data at rest and in transit.
- Use strong encryption algorithms.
- Store passwords securely using a hashing algorithm and salt.
- Protect API keys and other secrets.
- **Secure API Communication:**
- Use HTTPS for all API communication.
- Implement proper authentication and authorization for API endpoints.
- Use rate limiting to prevent abuse.
- Validate API requests and responses.
## 5. Testing Approaches
- **Unit Testing Strategies:**
- Write unit tests for individual functions and components.
- Use mocking and stubbing to isolate units of code.
- Test edge cases and error conditions.
- Aim for high code coverage.
- **Integration Testing:**
- Test the interaction between different modules and components.
- Verify that different parts of the application work together correctly.
- **End-to-End Testing:**
- Test the entire application from the user's perspective.
- Use tools like Cypress or Playwright to automate end-to-end tests.
- **Test Organization:**
- Organize tests in a way that makes it easy to find and run them.
- Group tests by feature or module.
- Use descriptive test names.
- **Mocking and Stubbing:**
- Use mocking and stubbing to isolate units of code and simulate dependencies.
- Use mocking libraries like Jest or Sinon.js.
## 6. Common Pitfalls and Gotchas
- **Frequent Mistakes:**
- Incorrectly handling asynchronous operations (Promises, async/await).
- Not handling errors properly.
- Overusing the `any` type.
- Ignoring compiler warnings.
- Not keeping dependencies up to date.
- **Edge Cases:**
- Handling different browser versions and devices.
- Dealing with network latency and failures.
- Handling different time zones and locales.
- Handling large datasets and complex calculations.
- **Version-Specific Issues:**
- Be aware of breaking changes in new versions of TypeScript and related libraries.
- Consult the release notes for each new version to identify potential issues.
- Use TypeScript's compiler options to target specific ECMAScript versions and maintain backwards compatibility if needed.
- **Compatibility Concerns:**
- Ensure that your code is compatible with the target browsers and devices.
- Use polyfills to provide support for older browsers.
- Test your code on different platforms to identify compatibility issues.
- **Debugging Strategies:**
- Use a debugger to step through your code and inspect variables.
- Use console logging to track the flow of execution and identify errors.
- Use TypeScript's type checking to catch errors early.
- Use source maps to debug code that has been transpiled or minified.
- Learn to read and understand stack traces.
## 7. Tooling and Environment
- **Recommended Development Tools:**
- **IDE:** Visual Studio Code with the TypeScript extension.
- **Package Manager:** npm or Yarn.
- **Bundler:** Webpack, Parcel, or Rollup.
- **Linter:** ESLint with TypeScript-specific rules.
- **Formatter:** Prettier.
- **Testing Framework:** Jest, Mocha, or Jasmine.
- **Build Configuration:**
- Use a `tsconfig.json` file to configure the TypeScript compiler.
- Configure compiler options like `target`, `module`, `jsx`, and `strict`.
- Use TypeScript's project references to organize large projects.
- **Linting and Formatting:**
- Use ESLint with TypeScript-specific rules to enforce coding standards.
- Use Prettier to automatically format your code.
- Integrate linting and formatting into your development workflow using Git hooks or CI/CD pipelines.
- **Deployment Best Practices:**
- Use a build process to transpile and bundle your code.
- Minify and compress your code to reduce bundle size.
- Use a CDN to serve static assets.
- Implement caching strategies to improve performance.
- **CI/CD Integration:**
- Integrate your tests and linters into your CI/CD pipeline.
- Automate the build and deployment process.
- Use environment variables to configure your application for different environments.#3
@sanjeed5/express
RequiredVersion: latest
📄 Prompt Content
- # Express.js Best Practices
This document outlines best practices for developing Express.js applications to ensure code quality, maintainability, performance, and security.
## 1. Code Organization and Structure
- ### Directory Structure Best Practices
- **Modular Structure:** Organize your application into logical modules based on functionality (e.g., `controllers`, `models`, `routes`, `middleware`, `services`).
- **Configuration:** Separate configuration files for different environments (development, production, testing).
- **Public Assets:** Keep static assets (CSS, JavaScript, images) in a dedicated `public` directory.
- **Views:** Store template files in a `views` directory. Use a template engine like EJS or Pug.
- **Example Structure:**
my-express-app/
├── controllers/
│ ├── userController.js
│ └── productController.js
├── models/
│ ├── user.js
│ └── product.js
├── routes/
│ ├── userRoutes.js
│ └── productRoutes.js
├── middleware/
│ ├── authMiddleware.js
│ └── errorMiddleware.js
├── services/
│ ├── userService.js
│ └── productService.js
├── config/
│ ├── config.js
│ └── db.js
├── views/
│ ├── index.ejs
│ └── user.ejs
├── public/
│ ├── css/
│ │ └── style.css
│ ├── js/
│ │ └── script.js
│ └── images/
├── app.js # Main application file
├── package.json
└── .env # Environment variables
- ### File Naming Conventions
- **Descriptive Names:** Use clear and descriptive names for files and directories.
- **Case Convention:** Use camelCase for JavaScript files and directories. For components consider PascalCase.
- **Route Files:** Name route files according to the resource they handle (e.g., `userRoutes.js`, `productRoutes.js`).
- **Controller Files:** Name controller files according to the resource they handle (e.g., `userController.js`, `productController.js`).
- **Model Files:** Name model files after the data model they represent (e.g., `user.js`, `product.js`).
- ### Module Organization
- **ES Modules:** Use ES modules (`import`/`export`) for modularity.
- **Single Responsibility Principle:** Each module should have a single, well-defined responsibility.
- **Loose Coupling:** Minimize dependencies between modules to improve reusability and testability.
- ### Component Architecture
- **Reusable Components:** Break down the application into reusable components (e.g., UI components, service components).
- **Separation of Concerns:** Separate presentation logic (views) from business logic (controllers/services).
- **Component Composition:** Compose complex components from simpler ones.
- ### Code Splitting Strategies
- **Route-Based Splitting:** Split code based on application routes to reduce initial load time. Use dynamic imports (`import()`) to load modules on demand.
- **Component-Based Splitting:** Split code based on components, loading components only when they are needed.
## 2. Common Patterns and Anti-patterns
- ### Design Patterns Specific to Express
- **Middleware Pattern:** Use middleware functions to handle request processing, authentication, logging, etc.
- **MVC Pattern:** Implement the Model-View-Controller (MVC) pattern to separate concerns and improve code organization.
- **Observer Pattern:** Implement the observer pattern when you need to notify multiple objects about state changes.
- ### Recommended Approaches for Common Tasks
- **Route Handling:** Use Express Router to define routes in separate modules.
- **Error Handling:** Use custom error handling middleware to catch and handle errors gracefully. See section 6 for more details.
- **Data Validation:** Use middleware for validating request data before processing it.
- **Asynchronous Operations:** Use `async/await` or Promises to handle asynchronous operations.
- ### Anti-patterns and Code Smells to Avoid
- **God Object:** Avoid creating a single, massive object that handles too many responsibilities.
- **Callback Hell:** Avoid deeply nested callbacks; use Promises or `async/await` instead.
- **Ignoring Errors:** Always handle errors properly instead of ignoring them.
- **Global Variables:** Minimize the use of global variables to avoid naming conflicts and unexpected behavior.
- **Hardcoding Secrets:** Never hardcode sensitive information (API keys, passwords) in your code. Use environment variables instead.
- ### State Management Best Practices
- **Stateless Controllers:** Keep controllers stateless to improve scalability and testability.
- **Session Management:** Use session management middleware (e.g., `express-session`) to manage user sessions.
- **Caching:** Implement caching strategies (e.g., Redis, Memcached) to improve performance.
- ### Error Handling Patterns
- **Centralized Error Handling:** Create a custom error handling middleware to catch and handle errors from different parts of the application.
- **Error Logging:** Log errors to a file or a monitoring service for debugging and analysis.
- **Custom Error Objects:** Create custom error objects with specific error codes and messages.
- **Graceful Error Messages:** Return user-friendly error messages instead of exposing internal errors.
- **Example Error Handler Middleware:**
javascript
// middleware/errorMiddleware.js
const errorHandler = (err, req, res, next) => {
console.error(err.stack);
const statusCode = res.statusCode === 200 ? 500 : res.statusCode;
res.status(statusCode);
res.json({
message: err.message,
stack: process.env.NODE_ENV === 'production' ? null : err.stack,
});
};
module.exports = errorHandler;
## 3. Performance Considerations
- ### Optimization Techniques
- **Gzip Compression:** Use Gzip compression to reduce the size of responses.
- **Caching:** Implement caching at different levels (e.g., browser caching, server-side caching) to reduce server load.
- **Connection Pooling:** Use connection pooling for database connections to improve performance.
- **Load Balancing:** Distribute traffic across multiple servers using a load balancer.
- ### Memory Management
- **Avoid Memory Leaks:** Be mindful of memory leaks, especially when working with large datasets or long-running processes. Use tools like `memwatch` to profile.
- **Garbage Collection:** Understand how garbage collection works in Node.js and optimize your code accordingly.
- **Streams:** Use streams for handling large files or data streams to avoid loading the entire data into memory.
- ### Rendering Optimization
- **Template Caching:** Enable template caching in your template engine to improve rendering performance.
- **Minify Assets:** Minify CSS and JavaScript files to reduce their size.
- **Lazy Loading Images:** Lazy load images to improve initial page load time.
- ### Bundle Size Optimization
- **Tree Shaking:** Use tree shaking to remove unused code from your bundles.
- **Code Splitting:** Split your code into smaller chunks to reduce the size of initial bundles.
- **Dependency Analysis:** Analyze your dependencies to identify and remove unnecessary packages.
- ### Lazy Loading Strategies
- **Lazy Load Modules:** Load modules only when they are needed using dynamic imports (`import()`).
- **Lazy Load Images and Other Assets:** Use lazy loading for images and other assets that are not immediately visible on the page.
## 4. Security Best Practices
- ### Common Vulnerabilities and How to Prevent Them
- **Cross-Site Scripting (XSS):** Prevent XSS attacks by sanitizing user input and encoding output.
- **Cross-Site Request Forgery (CSRF):** Protect against CSRF attacks by using CSRF tokens.
- **SQL Injection:** Use parameterized queries or an ORM to prevent SQL injection attacks.
- **NoSQL Injection:** Sanitize user input and avoid constructing queries from strings to prevent NoSQL injection attacks.
- **Command Injection:** Avoid executing shell commands based on user input. If necessary, sanitize the input and use appropriate escaping.
- **Denial of Service (DoS):** Implement rate limiting and other measures to prevent DoS attacks.
- **Man-in-the-Middle (MitM):** Use HTTPS to encrypt communication between the client and server and protect against MitM attacks.
- **HTTP Parameter Pollution (HPP):** Avoid using the same parameter multiple times in a request to prevent HPP attacks.
- ### Input Validation
- **Server-Side Validation:** Always validate user input on the server-side, even if you have client-side validation.
- **Data Sanitization:** Sanitize user input to remove potentially harmful characters or code.
- **Schema Validation:** Use schema validation libraries (e.g., Joi, express-validator) to validate request data against a predefined schema.
- ### Authentication and Authorization Patterns
- **Authentication:** Use a secure authentication mechanism (e.g., JWT, OAuth) to verify user identities.
- **Authorization:** Implement role-based access control (RBAC) or attribute-based access control (ABAC) to control access to resources.
- **Secure Password Storage:** Use a strong hashing algorithm (e.g., bcrypt) to store user passwords securely.
- **Multi-Factor Authentication (MFA):** Implement MFA to add an extra layer of security.
- ### Data Protection Strategies
- **Encryption:** Encrypt sensitive data at rest and in transit.
- **Data Masking:** Mask sensitive data in logs and other outputs.
- **Access Control:** Restrict access to sensitive data to authorized users and processes.
- ### Secure API Communication
- **HTTPS:** Use HTTPS for all API communication.
- **API Keys:** Use API keys to authenticate clients.
- **Rate Limiting:** Implement rate limiting to prevent abuse and DoS attacks.
- **Input Validation:** Validate all input data to prevent injection attacks.
- **Output Encoding:** Encode all output data to prevent XSS attacks.
## 5. Testing Approaches
- ### Unit Testing Strategies
- **Test-Driven Development (TDD):** Write unit tests before writing the actual code.
- **Test Individual Modules:** Test individual modules in isolation to ensure they work correctly.
- **Mock Dependencies:** Mock external dependencies (e.g., databases, APIs) to isolate the module being tested.
- ### Integration Testing
- **Test Interactions Between Modules:** Test the interactions between different modules to ensure they work together correctly.
- **Test API Endpoints:** Test API endpoints to ensure they return the expected results.
- ### End-to-End Testing
- **Test the Entire Application Flow:** Test the entire application flow from start to finish.
- **Simulate User Interactions:** Simulate user interactions to ensure the application behaves as expected.
- ### Test Organization
- **Separate Test Files:** Create separate test files for each module or component.
- **Descriptive Test Names:** Use clear and descriptive names for test cases.
- **Arrange-Act-Assert Pattern:** Follow the Arrange-Act-Assert pattern in your tests.
- ### Mocking and Stubbing
- **Use Mocking Libraries:** Use mocking libraries (e.g., Jest, Sinon) to create mocks and stubs.
- **Mock External Dependencies:** Mock external dependencies to isolate the module being tested.
- **Stub Function Calls:** Stub function calls to control the behavior of dependencies.
## 6. Common Pitfalls and Gotchas
- ### Frequent Mistakes Developers Make
- **Not Handling Errors Properly:** Always handle errors properly to prevent unexpected behavior.
- **Ignoring Security Vulnerabilities:** Be aware of common security vulnerabilities and take steps to prevent them.
- **Not Using Middleware Wisely:** Use middleware wisely to handle common tasks such as authentication, logging, and error handling.
- **Over-Engineering:** Avoid over-engineering your code by keeping it simple and focused.
- ### Edge Cases to Be Aware Of
- **Handling Large File Uploads:** Use streams or middleware libraries for handling large file uploads to prevent memory issues.
- **Dealing with Timezones:** Be aware of timezone issues when working with dates and times.
- **Handling Unicode Characters:** Properly handle Unicode characters to prevent encoding issues.
- **Dealing with Concurrent Requests:** Implement concurrency control mechanisms to handle concurrent requests safely.
- ### Version-Specific Issues
- **Deprecated Features:** Be aware of deprecated features and use the recommended alternatives.
- **Breaking Changes:** Be aware of breaking changes when upgrading to a new version of Express.js.
- ### Compatibility Concerns
- **Browser Compatibility:** Test your application in different browsers to ensure it works correctly.
- **Operating System Compatibility:** Test your application on different operating systems to ensure it works correctly.
- **Node.js Version Compatibility:** Ensure your application is compatible with the supported versions of Node.js.
- ### Debugging Strategies
- **Use Debugging Tools:** Use debugging tools (e.g., Node.js Inspector, Chrome DevTools) to debug your code.
- **Log Statements:** Use log statements to track the flow of execution and identify issues.
- **Error Messages:** Read error messages carefully to understand the cause of the error.
## 7. Tooling and Environment
- ### Recommended Development Tools
- **IDE:** Use a good IDE such as VS Code, WebStorm, or Sublime Text.
- **Debugger:** Use a debugger to step through your code and identify issues.
- **Linter:** Use a linter (e.g., ESLint) to enforce coding standards.
- **Formatter:** Use a formatter (e.g., Prettier) to format your code automatically.
- ### Build Configuration
- **Use a Build Tool:** Use a build tool (e.g., Webpack, Parcel) to bundle and optimize your code.
- **Configure Build Scripts:** Configure build scripts in your `package.json` file to automate the build process.
- **Use Environment Variables:** Use environment variables to configure your application for different environments.
- ### Linting and Formatting
- **Use ESLint:** Use ESLint to enforce coding standards and identify potential issues.
- **Use Prettier:** Use Prettier to format your code automatically.
- **Configure Editor Integration:** Configure your editor to automatically run ESLint and Prettier on save.
- ### Deployment Best Practices
- **Use a Process Manager:** Use a process manager (e.g., PM2, Forever) to keep your application running in production.
- **Use a Reverse Proxy:** Use a reverse proxy (e.g., Nginx, Apache) to handle incoming requests and forward them to your application.
- **Use a Load Balancer:** Use a load balancer to distribute traffic across multiple servers.
- **Use HTTPS:** Use HTTPS to encrypt communication between the client and server.
- **Monitor Your Application:** Monitor your application to identify and resolve issues.
- ### CI/CD Integration
- **Use a CI/CD Pipeline:** Use a CI/CD pipeline (e.g., Jenkins, Travis CI, CircleCI, GitHub Actions) to automate the build, test, and deployment process.
- **Run Tests Automatically:** Configure your CI/CD pipeline to run tests automatically on every commit.
- **Automate Deployment:** Automate the deployment process to reduce the risk of errors.#4
@sanjeed5/postgresql
RequiredVersion: latest
📄 Prompt Content
- **Code Formatting and Comments:**
- Maintain consistent code formatting using a tool like `pgformatter` or similar.
- Use clear and concise comments to explain complex logic and intentions. Update comments regularly to avoid confusion.
- Use inline comments sparingly; prefer block comments for detailed explanations.
- Write comments in plain, easy-to-follow English.
- Add a space after line comments (`-- a comment`); do not add a space for commented-out code (`--raise notice`).
- Keep comments up-to-date; incorrect comments are worse than no comments.
- **Naming Conventions:**
- Use `snake_case` for identifiers (e.g., `user_id`, `customer_name`).
- Use plural nouns for table names (e.g., `customers`, `products`).
- Use consistent naming conventions for functions, procedures, and triggers.
- Choose descriptive and meaningful names for all database objects.
- **Data Integrity and Data Types:**
- Use appropriate data types for columns to ensure data integrity (e.g., `INTEGER`, `VARCHAR`, `TIMESTAMP`).
- Use constraints (e.g., `NOT NULL`, `UNIQUE`, `CHECK`, `FOREIGN KEY`) to enforce data integrity.
- Define primary keys for all tables.
- Use foreign keys to establish relationships between tables.
- Utilize domains to enforce data type constraints reusable across multiple columns.
- **SQL Injection Prevention:**
- Always use parameterized queries or prepared statements to prevent SQL injection attacks.
- Sanitize user inputs before using them in SQL queries.
- Avoid constructing SQL queries by concatenating strings directly.
- Use the `quote_literal()` and `quote_ident()` functions to properly escape strings and identifiers.
- **Transaction Management:**
- Use explicit transactions to ensure data consistency and atomicity.
- Start transactions with `BEGIN;` and end them with `COMMIT;` or `ROLLBACK;`.
- Handle transaction errors properly to prevent data corruption.
- Use savepoints to allow partial rollbacks within a transaction.
- **Indexing:**
- Create indexes on columns frequently used in `WHERE` clauses and `JOIN` conditions.
- Avoid over-indexing, as it can slow down write operations.
- Consider using partial indexes for specific query patterns.
- Use appropriate index types (e.g., `B-tree`, `Hash`, `GIN`, `GiST`) based on the data and query requirements.
- Regularly analyze and maintain indexes using `ANALYZE` and `VACUUM`.
- **Query Optimization:**
- Use `EXPLAIN ANALYZE` to analyze query execution plans and identify performance bottlenecks.
- Avoid using `SELECT *` and specify only the necessary columns.
- Use `JOIN` operations instead of subqueries where possible.
- Optimize `WHERE` clauses to reduce the number of rows processed.
- Consider using materialized views for frequently executed, complex queries.
- Rewrite slow performing queries with more efficient alternatives.
- **PL/pgSQL Best Practices:**
- Keep PL/pgSQL functions and procedures short and focused.
- Use exception handling to gracefully handle errors.
- Use `RAISE NOTICE`, `RAISE WARNING`, and `RAISE EXCEPTION` for logging and error reporting.
- Avoid using cursors unless absolutely necessary; prefer set-based operations.
- Use the `STRICT` attribute to ensure that a function returns a value.
- **Security Best Practices:**
- Grant the least privileges necessary to database users.
- Use roles to manage permissions.
- Regularly audit database activity.
- Encrypt sensitive data at rest and in transit.
- Use the `SECURITY DEFINER` attribute for functions that require elevated privileges.
- Configure appropriate authentication mechanisms (e.g., `SCRAM-SHA-256`).
- **Connection Management:**
- Use connection pooling to reduce the overhead of establishing new connections.
- Close connections when they are no longer needed.
- Configure connection timeouts to prevent idle connections from consuming resources.
- **Backup and Recovery:**
- Implement a robust backup and recovery strategy.
- Regularly back up the database.
- Test the recovery process to ensure it works as expected.
- Consider using replication for high availability.
- **Code Organization and Structure:**
- Organize database objects into schemas based on functionality or application modules.
- Use version control for database scripts and migrations.
- Follow a consistent directory structure for database-related files.
- **Common Pitfalls and Gotchas:**
- Avoid using reserved keywords as identifiers.
- Be aware of the limitations of data types (e.g., maximum length of `VARCHAR` columns).
- Handle null values carefully.
- Test database changes thoroughly before deploying them to production.
- **Tooling and Environment:**
- Use a code editor with SQL syntax highlighting and autocompletion.
- Use a database client tool for querying and managing the database (e.g., `pgAdmin`, `DBeaver`, `psql`).
- Use a version control system (e.g., Git) to manage database scripts and migrations.
- Use a CI/CD pipeline to automate database deployments.
- **C Coding Standards (When Extending PostgreSQL):**
- Adhere to the C99 standard. Only use language features available in the C99 standard.
- Follow PostgreSQL's source code conventions ([PostgreSQL Documentation](https://www.postgresql.org/docs/current/source-conventions.html)).
- Manage memory carefully; avoid memory leaks.
- Properly handle errors and exceptions.
- Document code thoroughly.
- **Use Case specific optimizations:**
- Time series data: Consider timescaledb extension
- Geospatial data: Consider postgis extension
@file ./rules/postgresql_security_rules.mdc#5
@sanjeed5/prisma
RequiredVersion: latest
📄 Prompt Content
- **General Principles:**
- **Never expose the raw Prisma client directly in APIs.** Instead, create abstraction layers (e.g., repositories or services) to handle data access logic. This protects you from accidentally exposing sensitive database details and allows you to easily change your data access implementation in the future.
- **Always use input validation** before performing any database operations. Use a validation library like Zod or Yup to ensure that user input conforms to your expected schema and data types. This helps prevent injection attacks and data corruption.
- **Implement row-level security (RLS) where applicable.** If your application handles sensitive data, use Prisma policies or database-level RLS to restrict data access based on user roles or permissions. Carefully design your policies to prevent unauthorized data access.
- **Sanitize and validate all user inputs** to prevent injection attacks, such as SQL injection. Use Prisma's built-in features to escape user input and prevent it from being interpreted as code.
- **Code Organization and Structure:**
- **Directory Structure:**
- `prisma/`: Contains the `schema.prisma` file and any seed scripts or migrations.
- `src/`: Contains the main application code.
- `src/lib/prisma.ts`: A single module that exports an instance of the Prisma client. This promotes reuse and simplifies dependency injection.
- `src/models/`: Database model definitions as classes, abstracting Prisma calls.
- `src/repositories/`: Contains data access logic, abstracting Prisma queries.
- `src/services/`: Contains business logic, orchestrating data access through repositories.
- **File Naming Conventions:**
- Use descriptive names for files and directories that reflect their purpose.
- Use consistent naming conventions (e.g., camelCase for variables, PascalCase for components).
- **Module Organization:**
- Organize code into logical modules with clear responsibilities.
- Use dependency injection to decouple modules and improve testability.
- **Component Architecture:**
- Design components that are reusable, testable, and maintainable.
- Follow the single responsibility principle for each component.
- **Code Splitting Strategies:**
- Use dynamic imports to load code on demand and reduce initial bundle size.
- Split code based on routes, features, or user roles.
- **Common Patterns and Anti-patterns:**
- **Design Patterns:**
- **Repository Pattern:** Abstract data access logic behind repositories.
- **Service Layer Pattern:** Encapsulate business logic in service classes.
- **Unit of Work Pattern:** Manage transactions across multiple repositories.
- **Recommended Approaches:**
- Use Prisma's relation features to model complex relationships between entities.
- Use Prisma's transaction features to ensure data consistency.
- Use Prisma's filtering and sorting options to optimize queries.
- **Anti-patterns:**
- **Exposing the Prisma client directly to the client-side.** This is a major security risk.
- **Writing complex queries directly in components.** Move query logic to repositories or services.
- **Ignoring error handling.** Always handle potential errors when interacting with the database.
- **State Management:**
- Consider using a state management library like Redux, Zustand, or Jotai for complex applications.
- Use server-side data fetching for initial data loading and hydration.
- **Error Handling:**
- Use try-catch blocks to handle potential errors when interacting with the database.
- Log errors to a centralized logging system for monitoring and debugging.
- Return meaningful error messages to the client-side.
- **Performance Considerations:**
- **Optimization Techniques:**
- Use Prisma's connection pooling to reduce database connection overhead.
- Use Prisma's batching features to reduce the number of database roundtrips.
- Optimize database queries by using indexes and filtering data on the server-side.
- **Memory Management:**
- Avoid loading large amounts of data into memory at once. Use pagination or streaming to process data in smaller chunks.
- Clean up resources after use, such as database connections and file handles.
- **Rendering Optimization:**
- Use virtualization for large lists or tables.
- Optimize images and other assets.
- **Bundle Size Optimization:**
- Use code splitting to reduce the initial bundle size.
- Remove unused code and dependencies.
- **Lazy Loading Strategies:**
- Load data on demand when it is needed.
- Use placeholders or skeletons to improve the user experience during loading.
- **Security Best Practices:**
- **Common Vulnerabilities:**
- SQL injection: Prevented by using Prisma's prepared statements and escaping user input.
- Cross-site scripting (XSS): Prevented by sanitizing user input and output.
- Cross-site request forgery (CSRF): Prevented by using CSRF tokens.
- **Input Validation:**
- Use a validation library to validate all user input.
- Validate data types, lengths, and formats.
- **Authentication and Authorization:**
- Use a secure authentication library like NextAuth.js or Clerk.
- Implement role-based access control (RBAC) to restrict access to sensitive data and functionality.
- **Data Protection:**
- Encrypt sensitive data at rest and in transit.
- Use HTTPS to secure communication between the client and server.
- **Secure API Communication:**
- Use API keys or tokens to authenticate API requests.
- Rate limit API requests to prevent abuse.
- **Testing Approaches:**
- **Unit Testing:**
- Test individual components and functions in isolation.
- Use mocking and stubbing to isolate components from external dependencies.
- **Integration Testing:**
- Test the interaction between different components and modules.
- Test database interactions using a test database.
- **End-to-End Testing:**
- Test the entire application from end to end.
- Use a testing framework like Cypress or Playwright.
- **Test Organization:**
- Organize tests into logical suites based on functionality.
- Use descriptive names for tests.
- **Mocking and Stubbing:**
- Use mocking to replace external dependencies with test doubles.
- Use stubbing to control the behavior of dependencies.
- **Common Pitfalls and Gotchas:**
- **Frequent Mistakes:**
- Forgetting to handle errors when interacting with the database.
- Exposing the Prisma client directly to the client-side.
- Writing complex queries directly in components.
- **Edge Cases:**
- Handling large datasets.
- Dealing with concurrency issues.
- Managing database migrations.
- **Version-Specific Issues:**
- Be aware of breaking changes between Prisma versions.
- Use version control to manage dependencies.
- **Compatibility Concerns:**
- Ensure that your code is compatible with different browsers and devices.
- Test your application on different environments.
- **Debugging Strategies:**
- Use logging to track down errors.
- Use a debugger to step through code.
- Use Prisma's query logging feature to inspect database queries.
- **Tooling and Environment:**
- **Recommended Development Tools:**
- VS Code with the Prisma extension.
- Prisma Studio for visualizing and managing data.
- Docker for containerizing the application.
- **Build Configuration:**
- Use a build tool like Webpack, Parcel, or esbuild to bundle and optimize code.
- Configure the build tool to generate production-ready code.
- **Linting and Formatting:**
- Use ESLint and Prettier to enforce code style and prevent errors.
- Configure the linter and formatter to use consistent settings across the project.
- **Deployment Best Practices:**
- Use a CI/CD pipeline to automate deployments.
- Deploy to a cloud platform like Vercel, Netlify, or AWS.
- **CI/CD Integration:**
- Integrate with CI/CD tools like GitHub Actions, GitLab CI, or CircleCI.
- Run tests and linters as part of the CI/CD pipeline.
- **Specific Prisma Configuration:**
- **Schema Design:**
- Use clear and concise names for models and fields.
- Define relationships between models using Prisma's relation features.
- Use indexes to optimize query performance.
- Consider using enums for fields with a limited set of values.
- Properly use `@id`, `@unique`, and `@relation` directives for optimal schema design.
- **Data Types:**
- Use the appropriate data types for each field.
- Use `DateTime` for storing timestamps.
- Use `Json` for storing complex data structures.
- **Prisma Client Generation:**
- Ensure your `.env` file is correctly configured for database connection.
- Regularly update the Prisma client to the latest version.
- Use `prisma generate` to generate the client after schema changes.
- **Query Optimization:**
- **Select only the necessary fields** to reduce the amount of data transferred from the database.
- **Use `include` and `select` carefully** to optimize the query shape.
- **Avoid N+1 queries** by using Prisma's `include` or `join` features.
- **Use pagination** to limit the number of results returned by a query.
- **Use `take` and `skip`** for efficient pagination.
- **Transaction Management:**
- **Use Prisma's `prisma.$transaction` method** to ensure atomicity of database operations.
- **Handle potential errors** within the transaction to prevent data inconsistency.
- **Keep transactions short** to minimize the impact on database performance.
- **Seed Data Management:**
- **Create a seed script** to populate the database with initial data.
- **Use Prisma's `prisma.create` method** to create seed data.
- **Use environment variables** to configure seed data for different environments.
- **Migration Management:**
- **Use Prisma Migrate** to manage database schema changes.
- **Create migrations** for each schema change.
- **Apply migrations** to the database using `prisma migrate deploy`.
- **Use shadow database** to test migrations before deploying them to production.
- **Monitoring and Logging:**
- **Use Prisma's query logging feature** to monitor database queries.
- **Log errors and warnings** to a centralized logging system.
- **Monitor database performance** using tools like Prometheus or Grafana.
- **Further Study:**
- Always refer to the [official Prisma documentation](https://www.prisma.io/docs/) for the most up-to-date information.
- Consider taking an [official Prisma course](https://www.prisma.io/learn/).#6
@sanjeed5/jest
RequiredVersion: latest
📄 Prompt Content
- **Organize tests by feature or module:**
- Group tests into files or directories that correspond to the features or modules they are testing. This makes it easier to locate and maintain tests.
- Create a `__tests__` directory alongside your source code files. This is a common convention that Jest recognizes.
- **Use descriptive test names:**
- Write test names that clearly describe what the test is verifying. This makes it easier to understand the purpose of each test and to diagnose failures.
- Use the `describe` and `it` blocks to structure your tests and provide context.
- Example: `describe('User authentication', () => { it('should log in a user with valid credentials', () => { /* ... */ }); });`
- **Keep tests isolated and independent:**
- Each test should be independent of other tests. Avoid sharing state or dependencies between tests.
- Use `beforeEach` and `afterEach` hooks to set up and tear down the environment for each test.
- **Avoid testing implementation details:**
- Focus on testing the public API of your code, rather than the internal implementation details.
- This makes your tests more resilient to changes in the implementation.
- Test the "what", not the "how".
- **Use setup and teardown methods:**
- Use `beforeAll`, `afterAll`, `beforeEach`, and `afterEach` hooks to set up and tear down the environment for your tests.
- `beforeAll` and `afterAll` run once before and after all tests in a `describe` block.
- `beforeEach` and `afterEach` run before and after each test in a `describe` block.
- **Mock external dependencies:**
- Use mocking to isolate your code from external dependencies, such as network requests or database connections.
- Jest provides built-in mocking capabilities with `jest.mock` and `jest.spyOn`.
- Consider using a library like `axios-mock-adapter` for mocking HTTP requests.
- **Write tests that are easy to read and maintain:**
- Keep your tests concise and focused.
- Use clear and consistent formatting.
- Add comments to explain complex logic.
- Refactor your tests regularly to keep them up to date.
- **Aim for high test coverage, but prioritize meaningful tests over quantity:**
- Aim for high test coverage to ensure that your code is well-tested.
- However, prioritize writing meaningful tests that verify the core functionality of your code.
- Don't just aim for 100% coverage without considering the value of each test.
- **Use Jest's built-in matchers effectively:**
- Jest provides a rich set of matchers for asserting different conditions.
- Use matchers like `toBe`, `toEqual`, `toBeGreaterThan`, `toContain`, `toHaveBeenCalled`, etc.
- Explore the Jest documentation for the full list of matchers.
- **Handle asynchronous code correctly:**
- Use `async/await` or Promises to handle asynchronous code in your tests.
- Use the `resolves` and `rejects` matchers to assert that a Promise resolves or rejects.
- Example: `expect(myAsyncFunction()).resolves.toBe(expectedValue);`
- **Test error handling:**
- Write tests to verify that your code handles errors correctly.
- Use the `toThrow` matcher to assert that a function throws an error.
- Example: `expect(() => myDangerousFunction()).toThrow(Error);`
- **Use snapshots sparingly:**
- Snapshots can be useful for verifying the output of a component or function.
- However, they can also be brittle and difficult to maintain if used excessively.
- Use snapshots strategically and review them carefully when they change.
- **Configure Jest correctly:**
- Configure Jest using the `jest.config.js` or `jest.config.ts` file.
- Configure settings such as test environment, module file extensions, and coverage thresholds.
- Consider using presets like `ts-jest` or `babel-jest` for TypeScript or Babel support.
- **Leverage code coverage reports:**
- Use Jest's code coverage reports to identify areas of your code that are not well-tested.
- Aim to increase coverage in critical areas of your codebase.
- Use the `--coverage` flag to generate coverage reports.
- **Keep test data separate from test logic:**
- Externalize test data to improve readability and maintainability.
- Use fixtures or factories to generate test data.
- Avoid hardcoding data directly in your tests.
- **Consider using test-driven development (TDD):**
- Write tests before you write code to drive the development process.
- This can help you write more testable and well-designed code.
- **Run tests frequently:**
- Run your tests frequently to catch errors early.
- Use Jest's watch mode to automatically run tests when files change.
- Integrate tests into your CI/CD pipeline.
- **Document your tests:**
- Add comments to explain the purpose of each test and the expected behavior.
- This will make it easier for others to understand and maintain your tests.
- **Code Organization and Structure:**
- **Directory structure best practices:** Organize test files alongside the component/module they test (e.g., `src/components/MyComponent/MyComponent.test.js`)
- **File naming conventions:** Use `.test.js` or `.spec.js` suffixes for test files (e.g., `MyComponent.test.js`, `MyModule.spec.ts`).
- **Module organization:** Keep test files close to the modules they are testing. Use a consistent naming convention for test files.
- **Component architecture:** Test components in isolation, mocking dependencies where necessary.
- **Code splitting strategies:** Ensure tests cover all code paths in dynamically imported modules.
- **Common Patterns and Anti-patterns:**
- **Design patterns specific to Jest:** Use Page Object Model (POM) for UI tests, Factory pattern for test data generation.
- **Recommended approaches for common tasks:** Use `jest.mock` for mocking modules, `jest.spyOn` for spying on methods, and `fakeTimers` for controlling time-dependent behavior.
- **Anti-patterns and code smells to avoid:** Avoid testing implementation details, relying on global state, and creating brittle snapshots.
- **State management best practices:** Mock external state dependencies and verify state changes using `expect` assertions.
- **Error handling patterns:** Test for specific error messages and ensure error boundaries are properly tested.
- **Performance Considerations:**
- **Optimization techniques:** Use `jest.clearAllMocks` and `jest.resetAllMocks` in `beforeEach` blocks to prevent state leakage and improve test performance.
- **Memory management:** Avoid creating large data structures in tests that are not necessary. Manually trigger garbage collection in tests where large objects are created and released.
- **Rendering optimization:** Mock expensive rendering logic to speed up tests that involve React components.
- **Bundle size optimization:** Not applicable, as Jest primarily tests individual modules or components.
- **Lazy loading strategies:** Ensure tests cover all code paths in dynamically imported modules.
- **Security Best Practices:**
- **Common vulnerabilities and how to prevent them:** Avoid using sensitive data in test snapshots. Sanitize test data to prevent potential injection attacks.
- **Input validation:** Test input validation logic and ensure that invalid inputs are handled correctly.
- **Authentication and authorization patterns:** Mock authentication and authorization logic to test different user roles and permissions.
- **Data protection strategies:** Not directly applicable, as Jest primarily focuses on functional testing.
- **Secure API communication:** Mock API calls and verify that data is transmitted securely.
- **Testing Approaches:**
- **Unit testing strategies:** Test individual functions, classes, or components in isolation.
- **Integration testing:** Test interactions between different modules or components.
- **End-to-end testing:** Use tools like Cypress or Playwright for end-to-end tests.
- **Test organization:** Group tests into logical suites based on functionality or module.
- **Mocking and stubbing:** Use `jest.mock` and `jest.spyOn` to create mocks and stubs for dependencies.
- **Common Pitfalls and Gotchas:**
- **Frequent mistakes developers make:** Forgetting to mock dependencies, testing implementation details, and creating brittle snapshots.
- **Edge cases to be aware of:** Testing asynchronous code correctly, handling errors, and testing different input types.
- **Version-specific issues:** Be aware of breaking changes in Jest updates and update your tests accordingly.
- **Compatibility concerns:** Ensure tests are compatible with different browsers or environments.
- **Debugging strategies:** Use `console.log` statements, debuggers, or Jest's interactive mode to debug tests.
- **Tooling and Environment:**
- **Recommended development tools:** VS Code, WebStorm, Jest Runner extension.
- **Build configuration:** Configure Jest using `jest.config.js` or `package.json`.
- **Linting and formatting:** Use ESLint and Prettier to enforce code style and prevent errors.
- **Deployment best practices:** Integrate tests into your CI/CD pipeline to ensure code quality.
- **CI/CD integration:** Use tools like GitHub Actions, Jenkins, or CircleCI to automate testing and deployment.#7
@sanjeed5/playwright
RequiredVersion: latest
📄 Prompt Content
- **General Principles**
- **Test User-Visible Behavior:** Focus tests on how users interact with your application, not on internal implementation details.
- **Isolate Tests:** Ensure tests are independent of each other to prevent cascading failures and ensure predictable results.
- **Avoid Testing Third-Party Dependencies:** Mock or stub external services and APIs to isolate your application's behavior.
- **Code Organization and Structure**
- **Directory Structure:**
- `tests/`: Contains all test files.
- `tests/e2e/`: End-to-end tests.
- `tests/unit/`: Unit tests (if applicable, though Playwright is primarily for E2E).
- `tests/utils/`: Helper functions and page object models.
- **File Naming Conventions:**
- Use `.spec.ts` or `.spec.js` for test files (e.g., `login.spec.ts`).
- Group related tests in the same file.
- **Module Organization:**
- Employ Page Object Model (POM) to encapsulate UI elements and interactions.
- **Component Architecture:**
- Structure tests around components or features of your application.
- **Code Splitting Strategies:**
- Not directly applicable to tests, but keep test files concise and focused.
- **Common Patterns and Anti-patterns**
- **Design Patterns:**
- **Page Object Model (POM):** A common pattern where each page is represented as a class, with methods for interacting with the page's elements. This improves reusability and maintainability. Example:
typescript
class LoginPage {
constructor(private readonly page: Page) {}
async goto() {
await this.page.goto('/login');
}
async login(username: string, password: string) {
await this.page.fill('#username', username);
await this.page.fill('#password', password);
await this.page.click('#login-button');
}
async getErrorMessage() {
return await this.page.textContent('#error-message');
}
}
- **Fixture pattern:** Use Playwright's built-in fixtures to manage test setup and teardown. This ensures each test starts in a clean state.
- **Recommended Approaches:**
- Use `baseURL` in `playwright.config.ts` to avoid hardcoding URLs in tests.
- Utilize `expect` matchers for assertions (e.g., `expect(page.locator('#success')).toBeVisible()`).
- Use auto-waiting features for improved stability.
- **Anti-patterns:**
- Hardcoding URLs.
- Using brittle selectors (e.g., XPath based on DOM structure).
- Writing tests that depend on each other.
- **State Management:**
- Keep tests stateless. Reset the application state before each test.
- Use database transactions or API calls to seed data for tests.
- **Error Handling:**
- Use `try...catch` blocks to handle expected errors.
- Log errors and failures with descriptive messages.
- Use `expect.soft()` for non-critical assertions that shouldn't fail the test immediately.
- **Performance Considerations**
- **Optimization Techniques:**
- Run tests in parallel to reduce overall test execution time.
- Use `reuseExistingServer: true` in `playwright.config.ts` during development to speed up debugging.
- Use `codegen` to generate selectors automatically.
- **Memory Management:**
- Close pages and browsers after each test or group of tests to release resources.
- **Rendering Optimization:**
- Not directly applicable but optimize your application's rendering for faster testing.
- **Bundle Size Optimization:**
- Not directly applicable, but optimize your application's bundle size for faster loading.
- **Lazy Loading Strategies:**
- Not directly applicable to tests.
- **Security Best Practices**
- **Common Vulnerabilities:**
- Avoid exposing sensitive data (e.g., passwords, API keys) in test code or logs.
- **Input Validation:**
- Test input validation to ensure your application handles invalid data correctly.
- **Authentication and Authorization:**
- Test different user roles and permissions.
- **Data Protection:**
- Ensure sensitive data is encrypted in the database.
- **Secure API Communication:**
- Test that API calls are made over HTTPS.
- **Testing Approaches**
- **Unit Testing:**
- While Playwright primarily focuses on E2E testing, unit tests can be written for utility functions or components.
- **Integration Testing:**
- Test the interaction between different parts of your application.
- **End-to-End Testing:**
- Simulate user flows to test the entire application.
- **Test Organization:**
- Group tests by feature or functionality.
- Use `describe` blocks to organize tests.
- **Mocking and Stubbing:**
- Use Playwright's `route` API to mock API responses.
- Use `locator.evaluate` to stub JavaScript functions.
- **Common Pitfalls and Gotchas**
- **Frequent Mistakes:**
- Using XPath instead of CSS selectors.
- Not using auto-waiting features.
- Writing flaky tests.
- **Edge Cases:**
- Handling different screen sizes and devices.
- Testing error conditions and edge cases.
- **Version-Specific Issues:**
- Stay up-to-date with Playwright's release notes and upgrade guides.
- **Compatibility Concerns:**
- Test on different browsers and operating systems.
- **Debugging Strategies:**
- Use Playwright Inspector to debug tests visually.
- Use `console.log` statements to log information during test execution.
- Use `pause()` to halt test execution and inspect the page.
- **Tooling and Environment**
- **Recommended Development Tools:**
- VS Code with the Playwright extension.
- **Build Configuration:**
- Use TypeScript for type safety and autocompletion.
- **Linting and Formatting:**
- Use ESLint and Prettier to enforce code style.
- **Deployment Best Practices:**
- Run tests in CI/CD pipeline before deploying to production.
- **CI/CD Integration:**
- Integrate Playwright with CI/CD tools like GitHub Actions, Jenkins, or GitLab CI.
- **Specific Best Practices & Details**
- **Stable Selectors:** Prefer CSS selectors based on attributes like `data-testid` or `data-test-id` over XPath or fragile CSS classnames.
- **Leverage Auto-waiting:** Playwright automatically waits for elements to be actionable before performing actions. Avoid explicit waits where possible. However, use explicit waits (e.g. `waitForSelector`) when necessary.
- **Web-First Assertions:** Use `expect` assertions, which retry and wait for conditions to be met. They help to avoid flakiness.
- **Configure Debugging Highlights:** Configure `playwright.config.ts` to highlight actions performed by playwright in the browser during debugging to see what's happening step by step. Example:
typescript
use: {
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
trace: 'on-first-retry',
video: 'on',
screenshot: 'only-on-failure',
}
- **Additional Notes**
- Regularly review and update your test suite to reflect changes in your application.
- Document your tests to make them easier to understand and maintain.
- Use a consistent naming convention for your tests.#8
@sanjeed5/github-actions
RequiredVersion: latest
📄 Prompt Content
# GitHub Actions Best Practices and Coding Standards
This guide provides comprehensive guidelines for developing efficient, reliable, secure, and maintainable GitHub Actions workflows. It covers various aspects of GitHub Actions development, including code organization, common patterns, performance considerations, security best practices, testing approaches, and tooling.
## 1. Code Organization and Structure
### 1.1 Directory Structure Best Practices
- **Workflows Directory:** Store all workflow files in the `.github/workflows` directory. This is the standard location recognized by GitHub.
- **Reusable Actions Directory (Optional):** If you create custom reusable actions, consider storing them in a dedicated directory like `actions/` within your repository.
- **Scripts Directory (Optional):** For complex workflows, you might have supporting scripts (e.g., shell scripts, Python scripts). Store these in a `scripts/` directory.
- **Example Directory Structure:**
.github/
└── workflows/
├── main.yml
├── deploy.yml
└── release.yml
actions/
├── my-custom-action/
│ ├── action.yml
│ └── index.js
scripts/
├── cleanup.sh
└── build.py
### 1.2 File Naming Conventions
- **Workflow Files:** Use descriptive and consistent names for workflow files (e.g., `deploy-staging.yml`, `code-analysis.yml`). Avoid generic names like `main.yml` if possible, especially in repositories with multiple workflows.
- **Action Files:** Name action files `action.yml` or `action.yaml` to clearly indicate their purpose.
- **Script Files:** Use appropriate extensions for scripts (e.g., `.sh` for shell scripts, `.py` for Python scripts).
### 1.3 Module Organization
- **Reusable Workflows:** Break down complex workflows into smaller, reusable workflows using the `uses:` syntax. This promotes modularity, reduces duplication, and improves maintainability.
- **Composite Actions:** For reusable steps within a workflow, consider creating composite actions. These group multiple steps into a single action.
- **Modular Scripts:** If you're using scripts, organize them into modules or functions for better readability and reusability.
### 1.4 Component Architecture
- **Workflow as a Component:** Treat each workflow as a self-contained component responsible for a specific task (e.g., building, testing, deploying).
- **Separation of Concerns:** Separate concerns within a workflow. For example, use different jobs for building, testing, and deploying.
- **Inputs and Outputs:** Define clear inputs and outputs for reusable workflows and composite actions to improve their composability.
### 1.5 Code Splitting Strategies
- **Job Splitting:** Divide a workflow into multiple jobs that run in parallel to reduce overall execution time.
- **Step Splitting:** Break down long-running steps into smaller, more manageable steps.
- **Conditional Execution:** Use `if:` conditions to conditionally execute jobs or steps based on specific criteria (e.g., branch name, file changes).
## 2. Common Patterns and Anti-patterns
### 2.1 Design Patterns Specific to GitHub Actions
- **Fan-out/Fan-in:** Use matrix builds to parallelize testing across different environments, then aggregate the results in a subsequent job.
- **Workflow Orchestration:** Use reusable workflows to orchestrate complex processes involving multiple steps and dependencies.
- **Event-Driven Workflows:** Trigger workflows based on specific GitHub events (e.g., push, pull request, issue creation) to automate tasks.
- **Policy Enforcement:** Implement workflows that enforce coding standards, security policies, or other organizational guidelines.
### 2.2 Recommended Approaches for Common Tasks
- **Dependency Caching:** Use the `actions/cache` action to cache dependencies (e.g., npm packages, Maven artifacts) to speed up subsequent workflow runs.
- **Secret Management:** Store sensitive information (e.g., API keys, passwords) as GitHub Secrets and access them in your workflows using the `${{ secrets.SECRET_NAME }}` syntax. Never hardcode secrets in your workflow files.
- **Artifact Storage:** Use the `actions/upload-artifact` and `actions/download-artifact` actions to store and retrieve build artifacts (e.g., compiled binaries, test reports).
- **Environment Variables:** Use environment variables to configure workflows and steps. Set environment variables at the workflow, job, or step level.
- **Workflow Status Badges:** Add workflow status badges to your repository's README file to provide a visual indication of the workflow's health.
### 2.3 Anti-patterns and Code Smells to Avoid
- **Hardcoding Secrets:** Never hardcode secrets directly in your workflow files. Use GitHub Secrets instead.
- **Ignoring Errors:** Don't ignore errors or warnings in your workflows. Implement proper error handling to ensure workflows fail gracefully.
- **Overly Complex Workflows:** Avoid creating overly complex workflows that are difficult to understand and maintain. Break them down into smaller, reusable workflows.
- **Lack of Testing:** Don't skip testing your workflows. Implement unit tests, integration tests, and end-to-end tests to ensure they function correctly.
- **Unnecessary Dependencies:** Avoid including unnecessary dependencies in your workflows. This can increase build times and introduce security vulnerabilities.
- **Directly Modifying `GITHUB_PATH` or `GITHUB_ENV`:** While these environment variables exist, using the recommended step outputs is preferred for cleaner, more robust interaction with other steps.
### 2.4 State Management Best Practices
- **Artifacts:** Use artifacts for persisting files between jobs. Upload at the end of one job, download at the start of another.
- **Environment Variables:** Define environment variables at the workflow or job level to pass configuration settings between steps.
- **Outputs:** Use step outputs to pass data between steps within a job.
- **GitHub API:** Use the GitHub API to store and retrieve data related to your workflows (e.g., workflow run status, deployment information).
- **External Databases:** For more complex state management requirements, consider using an external database.
### 2.5 Error Handling Patterns
- **`if: always()`:** Ensures a step runs even if a previous step failed, useful for cleanup or notification tasks. `if: always()` should be used with caution, as it can mask underlying issues.
- **`continue-on-error: true`:** Allows a job to continue even if a step fails. This is useful for non-critical steps or when you want to collect information about multiple failures before failing the workflow.
- **`try...catch...finally` (within Scripts):** Use `try...catch...finally` blocks in your scripts to handle exceptions and ensure proper cleanup.
- **Notifications:** Send notifications (e.g., email, Slack) when workflows fail or succeed to keep stakeholders informed.
- **Workflow Retries:** Consider using the `retry:` keyword to automatically retry failed jobs.
## 3. Performance Considerations
### 3.1 Optimization Techniques
- **Caching:** Use the `actions/cache` action aggressively to cache dependencies and intermediate build artifacts.
- **Concurrency:** Use concurrency to prevent multiple workflows from running at the same time.
- **Parallel Execution:** Run jobs in parallel to reduce overall execution time.
- **Optimized Images:** Optimize images before uploading them to your repository to reduce their size.
- **Minify Code:** Minify JavaScript and CSS files to reduce their size.
### 3.2 Memory Management
- **Resource Limits:** Be aware of the resource limits imposed by GitHub Actions runners. Monitor memory and CPU usage to prevent workflows from exceeding these limits.
- **Garbage Collection:** Ensure that your scripts and actions properly manage memory and avoid memory leaks.
- **Large Datasets:** If you're processing large datasets, consider using streaming techniques or splitting the data into smaller chunks.
### 3.3 Rendering Optimization
- N/A - Not typically relevant for GitHub Actions workflows themselves, but may be applicable to applications built and deployed by workflows.
### 3.4 Bundle Size Optimization
- N/A - Not typically relevant for GitHub Actions workflows themselves, but may be applicable to applications built and deployed by workflows.
### 3.5 Lazy Loading Strategies
- N/A - Not typically relevant for GitHub Actions workflows themselves, but may be applicable to applications built and deployed by workflows.
## 4. Security Best Practices
### 4.1 Common Vulnerabilities and How to Prevent Them
- **Code Injection:** Prevent code injection by validating all inputs and sanitizing data before using it in scripts or commands.
- **Secret Exposure:** Avoid exposing secrets in logs or error messages. Mask secrets using the `::add-mask::` command.
- **Third-Party Actions:** Carefully vet third-party actions before using them in your workflows. Pin actions to specific versions or commits to prevent unexpected changes.
- **Privilege Escalation:** Run workflows with the least privileges necessary to perform their tasks.
- **Workflow Command Injection:** Be cautious when dynamically constructing commands. If possible, use parameters or environment variables instead of concatenating strings.
### 4.2 Input Validation
- **Validate Inputs:** Validate all inputs to your workflows and actions to prevent malicious data from being processed.
- **Data Sanitization:** Sanitize data before using it in scripts or commands to prevent code injection vulnerabilities.
- **Regular Expressions:** Use regular expressions to validate the format of inputs.
### 4.3 Authentication and Authorization Patterns
- **GitHub Tokens:** Use GitHub tokens to authenticate with the GitHub API. Grant tokens the minimum necessary permissions.
- **Service Accounts:** Use service accounts to authenticate with external services. Store service account credentials as GitHub Secrets.
- **Role-Based Access Control (RBAC):** Implement RBAC to control access to your workflows and actions.
### 4.4 Data Protection Strategies
- **Encryption:** Encrypt sensitive data at rest and in transit.
- **Data Masking:** Mask sensitive data in logs and error messages.
- **Data Retention:** Establish a data retention policy to ensure that sensitive data is not stored indefinitely.
### 4.5 Secure API Communication
- **HTTPS:** Use HTTPS for all API communication.
- **TLS:** Use TLS encryption to protect data in transit.
- **API Keys:** Protect API keys and other credentials. Store them as GitHub Secrets and use them securely in your workflows.
- **Rate Limiting:** Implement rate limiting to prevent abuse of your APIs.
## 5. Testing Approaches
### 5.1 Unit Testing Strategies
- **Test Reusable Actions:** Unit test your custom reusable actions to ensure they function correctly.
- **Test Scripts:** Unit test your scripts to ensure they handle different inputs and edge cases correctly.
- **Mock Dependencies:** Use mocking to isolate units of code and test them in isolation.
### 5.2 Integration Testing
- **Test Workflow Integration:** Integrate test your workflows to ensure that all components work together correctly.
- **Test API Integrations:** Test your integrations with external APIs to ensure they function correctly.
- **Test Database Integrations:** Test your integrations with databases to ensure data is read and written correctly.
### 5.3 End-to-end Testing
- **Full Workflow Tests:** Run end-to-end tests to verify that your workflows function correctly from start to finish.
- **Simulate Real-World Scenarios:** Simulate real-world scenarios to ensure that your workflows can handle different situations.
### 5.4 Test Organization
- **Dedicated Test Directory:** Create a dedicated `tests/` directory for your tests.
- **Test Naming Conventions:** Follow consistent naming conventions for your test files and functions.
- **Test Suites:** Organize your tests into test suites based on functionality or component.
### 5.5 Mocking and Stubbing
- **Mock External Services:** Mock external services to isolate your tests from external dependencies.
- **Stub Functions:** Stub functions to control the behavior of dependencies during testing.
- **Mock GitHub API:** Mock the GitHub API to test your workflows without making real API calls.
## 6. Common Pitfalls and Gotchas
### 6.1 Frequent Mistakes Developers Make
- **Incorrect Syntax:** YAML syntax can be tricky. Use a linter or validator to catch syntax errors.
- **Incorrect Indentation:** Indentation is crucial in YAML. Use consistent indentation throughout your workflow files.
- **Missing Permissions:** Grant workflows the necessary permissions to access resources (e.g., repository contents, secrets).
- **Typos in Secrets:** Double-check the names of your secrets to avoid typos.
- **Not Pinning Action Versions:** Always pin actions to specific versions or commits to prevent unexpected changes.
### 6.2 Edge Cases to Be Aware Of
- **Rate Limits:** Be aware of GitHub API rate limits. Implement retry logic to handle rate limit errors.
- **Concurrent Workflow Runs:** Handle concurrent workflow runs gracefully to avoid conflicts.
- **Network Issues:** Implement error handling to handle network issues and transient errors.
- **Large File Sizes:** Be aware of the maximum file sizes supported by GitHub Actions.
### 6.3 Version-Specific Issues
- **Action Compatibility:** Ensure that your actions are compatible with the version of GitHub Actions you are using.
- **Runner Images:** Be aware of the changes in runner images and update your workflows accordingly.
### 6.4 Compatibility Concerns
- **Cross-Platform Compatibility:** Ensure that your workflows are compatible with different operating systems (e.g., Linux, Windows, macOS).
- **Browser Compatibility:** If your workflows involve web applications, test them in different browsers.
### 6.5 Debugging Strategies
- **Workflow Logs:** Examine workflow logs to identify errors and warnings.
- **Debugging Actions:** Use debugging actions to inspect the state of your workflows.
- **Step-by-Step Debugging:** Insert `echo` statements or debugging actions to trace the execution of your workflows step by step.
- **Local Testing:** Use tools like `act` to test your workflows locally before pushing them to GitHub.
## 7. Tooling and Environment
### 7.1 Recommended Development Tools
- **VS Code with GitHub Actions Extension:** Use VS Code with the GitHub Actions extension for syntax highlighting, code completion, and validation.
- **GitHub CLI:** Use the GitHub CLI to interact with the GitHub API from your workflows.
- **`act`:** Use `act` to test your workflows locally.
- **YAML Linter:** Use a YAML linter to catch syntax errors in your workflow files.
### 7.2 Build Configuration
- **`.github/workflows/`:** Place all workflow files in this directory.
- **`action.yml`:** For reusable actions, define their metadata in this file.
### 7.3 Linting and Formatting
- **YAML Lint:** Use a YAML linting tool to enforce consistent formatting and catch syntax errors.
- **Shellcheck:** Use Shellcheck to lint your shell scripts.
- **Prettier:** Use Prettier to format your JavaScript and CSS files.
### 7.4 Deployment Best Practices
- **Environment Variables:** Use environment variables to configure your deployments.
- **Deployment Strategies:** Use appropriate deployment strategies (e.g., blue/green deployment, canary deployment) to minimize downtime.
- **Rollback Strategies:** Implement rollback strategies to revert to a previous version if a deployment fails.
### 7.5 CI/CD Integration
- **Continuous Integration (CI):** Run automated tests on every commit to ensure code quality.
- **Continuous Delivery (CD):** Automate the deployment process to deliver new features and bug fixes to users quickly.
- **Automated Releases:** Automate the release process to create and publish releases automatically.
## Conclusion
By following these best practices and coding standards, you can create efficient, reliable, secure, and maintainable GitHub Actions workflows. Remember to adapt these guidelines to your specific needs and context. Continuously review and improve your workflows to ensure they meet your evolving requirements.#9
@sanjeed5/graphql
RequiredVersion: latest
📄 Prompt Content
- **Naming Conventions**:
- Use `camelCase` for field names, argument names, and directive names. This is a widely accepted convention that enhances readability and consistency.
- Use the suffix `Input` when naming input types (e.g., `UserInput`). This clearly distinguishes input types from other types in your schema.
- Avoid verb prefixes like `get` in field names (e.g., use `users` instead of `getUsers`). This maintains clarity and consistency in your schema.
- **Schema Design and Query Optimization**:
- Design your schema to prevent over-fetching or under-fetching of data. Use fragments to request only the necessary data.
- Use variables for parameters instead of hard-coded values. This enhances flexibility and maintainability, and allows for query caching.
- Implement pagination for large datasets to avoid overwhelming the client and improve performance.
- Use field aliases to rename fields in the response, which can be useful for backward compatibility or to simplify the client-side code.
- **Code Organization and Structure**:
- **Directory Structure**: Organize your GraphQL schema files into a logical directory structure. Consider grouping related types and resolvers together (e.g., `schemas/user/`, `resolvers/user/`).
- **File Naming Conventions**: Use descriptive names for schema files (e.g., `user.graphql`, `product.graphql`).
- **Module Organization**: Break down your schema into smaller, reusable modules. Use schema stitching or federation to combine these modules into a single API.
- **Component Architecture**: If using a GraphQL client library like Apollo Client or Relay, structure your components to efficiently manage GraphQL queries and data fetching.
- **Common Patterns and Anti-patterns**:
- **Design Patterns**: Consider using patterns like the Facade pattern to simplify complex resolvers or the DataLoader pattern to batch and cache data fetching.
- **Anti-patterns**: Avoid creating overly complex queries that fetch too much data in a single request. Also avoid using deeply nested resolvers, as this can lead to performance issues.
- **State Management**: Choose a state management solution that integrates well with your GraphQL client library. Consider using Apollo Client's cache or Relay's store for client-side data management.
- **Error Handling**: Implement robust error handling in your resolvers. Return user-friendly error messages and log detailed error information on the server.
- **Performance Considerations**:
- **Optimization Techniques**: Use techniques like query batching, caching, and persisted queries to optimize performance.
- **Memory Management**: Be mindful of memory usage in your resolvers, especially when dealing with large datasets.
- **Lazy Loading**: Implement lazy loading for non-critical data to improve initial page load times.
- **Security Best Practices**:
- **Input Validation**: Validate all user inputs to prevent injection attacks and other security vulnerabilities. Use appropriate data types and constraints in your schema.
- **Authentication and Authorization**: Implement strong authentication and authorization mechanisms to protect your API. Use role-based access control (RBAC) to restrict access to sensitive data.
- **Data Protection**: Protect sensitive data by encrypting it at rest and in transit. Use HTTPS to secure API communication.
- **Rate Limiting**: Implement rate limiting to prevent denial-of-service (DoS) attacks.
- **Query Complexity Analysis**: Limit the complexity of GraphQL queries to prevent malicious users from overloading the server. Tools like `graphql-cost-analysis` can help.
- **Testing Approaches**:
- **Unit Testing**: Write unit tests for your resolvers to ensure they are functioning correctly.
- **Integration Testing**: Write integration tests to verify that your GraphQL API integrates correctly with your data sources and other services.
- **End-to-end Testing**: Write end-to-end tests to simulate user interactions with your API and verify that the entire system is working as expected.
- **Test Organization**: Organize your tests into a logical directory structure. Use clear and descriptive names for your test files.
- **Mocking and Stubbing**: Use mocking and stubbing to isolate your resolvers from external dependencies during testing.
- **Common Pitfalls and Gotchas**:
- **N+1 Problem**: Be aware of the N+1 problem, where fetching a list of items requires N additional queries to fetch related data. Use DataLoader to batch and cache these queries.
- **Circular Dependencies**: Avoid circular dependencies between your schema types, as this can lead to errors.
- **Tooling and Environment**:
- **Recommended Development Tools**: Use tools like GraphQL Playground or GraphiQL for exploring and testing your API. Consider using a GraphQL IDE like Apollo Studio or Altair GraphQL Client for advanced features.
- **Linting and Formatting**: Use a GraphQL linter and formatter to enforce code style and prevent errors. Consider using ESLint with the `eslint-plugin-graphql` plugin.
- **Deployment Best Practices**: Deploy your GraphQL API behind a CDN to improve performance and availability. Use a GraphQL gateway to manage authentication, authorization, and rate limiting.
- **CI/CD Integration**: Integrate your GraphQL API into your CI/CD pipeline to automate testing and deployment.#10
@sanjeed5/redis
RequiredVersion: latest
📄 Prompt Content
- **General Best Practices**
- Follow official Redis documentation and community best practices.
- Use the most recent stable version of the Redis client library for your language.
- Regularly update the Redis server and client libraries to benefit from bug fixes, performance improvements, and security patches.
- **Connection Management**
- **Connection Pooling:** Use connection pooling to reduce the overhead of creating new connections for each operation. This significantly improves performance, especially in high-traffic scenarios.
- **Connection Timeout:** Configure appropriate connection timeouts to prevent indefinite blocking in case of network issues.
- **Retry Logic:** Implement retry logic with exponential backoff for transient connection errors.
- **Secure Connections:** When connecting to a remote Redis instance, always use TLS/SSL encryption (redis+ssl://) to protect data in transit, especially when dealing with sensitive information. Ensure proper certificate validation.
- **Data Modeling and Serialization**
- **Key Naming:** Use consistent and meaningful key naming conventions. Consider using namespaces or prefixes to organize keys and avoid collisions.
- **Data Serialization:** Choose an efficient serialization format (e.g., JSON, Protocol Buffers, MessagePack) and use it consistently. Consider the trade-offs between human readability, storage space, and serialization/deserialization performance.
- **Smaller Values:** Redis works best with smaller values. Break larger data structures into smaller chunks and distribute them across multiple keys. This improves memory utilization and performance.
- **Data Types:** Leverage Redis's rich data types (strings, lists, sets, sorted sets, hashes, streams) effectively to optimize data storage and operations. Choose the data type that best suits the use case.
- **Command Usage**
- **Transactions:** Use transactions (`MULTI`, `EXEC`, `DISCARD`, `WATCH`) to ensure atomicity when performing multiple operations. Be aware of the limitations of Redis transactions (no rollback on individual command failure).
- **Pipelines:** Use pipelines to batch multiple commands together and reduce network round-trip time. This dramatically improves performance for bulk operations.
- **Lua Scripting:** Use Lua scripting for complex operations that require atomicity and server-side processing. This reduces network traffic and improves performance compared to executing multiple individual commands.
- **Avoid Blocking Commands:** Avoid using blocking commands like `KEYS`, `FLUSHALL`, `FLUSHDB`, `SORT` without `LIMIT` in production environments. These commands can block the Redis server and degrade performance.
- **Use SCAN:** Instead of `KEYS`, use the `SCAN` command for iterating over keys in a non-blocking manner. This allows the Redis server to continue serving other requests while iterating.
- **Efficient Deletion:** Instead of `FLUSHALL` or `FLUSHDB`, use `SCAN` with `DEL` to delete keys in batches, minimizing disruption to the server.
- **TTL Management:** Set appropriate Time-To-Live (TTL) values for keys to automatically expire data that is no longer needed. This helps manage memory usage and prevent data from becoming stale.
- **Memory Management**
- **Maxmemory:** Configure the `maxmemory` directive to limit the amount of memory Redis can use. When the limit is reached, Redis will evict keys based on the configured eviction policy.
- **Eviction Policies:** Choose an appropriate eviction policy (e.g., `LRU`, `LFU`, `volatile-ttl`) based on your application's needs. Understand the trade-offs between different eviction policies.
- **Memory Fragmentation:** Monitor memory fragmentation and consider restarting Redis periodically to defragment memory. The `INFO memory` command provides information about memory usage and fragmentation.
- **Performance Monitoring and Tuning**
- **Redis Monitor:** Use the `MONITOR` command (with caution in production) to observe real-time commands being executed on the server. This can help identify performance bottlenecks.
- **Redis Slow Log:** Configure the Redis slow log to record commands that take longer than a specified amount of time to execute. Analyze the slow log to identify performance issues.
- **INFO Command:** Use the `INFO` command to gather information about the Redis server, including memory usage, CPU usage, and client connections. This information can be used to monitor performance and identify potential problems.
- **Latency Monitoring:** Monitor Redis latency using tools like `redis-cli --latency` or dedicated monitoring solutions. High latency can indicate performance issues.
- **Security Considerations**
- **Authentication:** Enable authentication using the `requirepass` directive to protect the Redis server from unauthorized access. Use a strong password.
- **Access Control Lists (ACLs):** Use ACLs to restrict access to specific commands and keys for different users. This provides fine-grained control over access to Redis data.
- **Network Security:** Restrict network access to the Redis server using firewalls or other network security measures. Only allow connections from trusted sources.
- **Disable Unsafe Commands:** Disable or rename potentially dangerous commands like `FLUSHALL`, `FLUSHDB`, `KEYS`, `EVAL` using the `rename-command` directive. This reduces the risk of accidental or malicious misuse.
- **Regular Audits:** Conduct regular security audits of the Redis configuration and usage patterns to identify and address potential vulnerabilities.
- **Input Validation:** Always validate and sanitize any data being stored in Redis to prevent injection attacks.
- **Testing Strategies**
- **Unit Tests:** Write unit tests to verify the functionality of your code that interacts with Redis. Use mocking or stubbing to isolate the Redis interactions from the rest of the code.
- **Integration Tests:** Write integration tests to verify the interaction between your code and the Redis server. Use a dedicated test Redis instance for integration tests.
- **End-to-End Tests:** Write end-to-end tests to verify the entire application flow, including the interaction with Redis. This ensures that the application works correctly in a realistic environment.
- **Data Population:** When testing, consider populating your redis database with a representative set of data.
- **Test Organization:** Organize tests logically, separating unit, integration, and end-to-end tests into different directories or modules.
- **Mocking and Stubbing:** Use mocking and stubbing frameworks to simulate Redis behavior during unit tests.
- **Code Organization and Structure**
- **Dedicated Module:** Create a dedicated module or class to encapsulate all Redis-related operations. This promotes code reuse and maintainability.
- **Configuration Management:** Store Redis connection parameters (host, port, password) in a configuration file or environment variables. This makes it easy to change the Redis configuration without modifying code.
- **Abstraction Layer:** Consider creating an abstraction layer on top of the Redis client library to provide a higher-level API for your application. This can improve code readability and make it easier to switch to a different Redis client library in the future.
- **Common Pitfalls and Gotchas**
- **N+1 Problem:** Avoid the N+1 problem when retrieving data from Redis. Instead of making multiple individual requests, use pipelining or Lua scripting to retrieve the data in a single request.
- **Race Conditions:** Be aware of potential race conditions when updating data in Redis. Use transactions or Lua scripting to ensure atomicity.
- **Large Values:** Avoid storing extremely large values in Redis. This can lead to performance issues and memory exhaustion.
- **Key Expiration:** Be careful when using key expiration (TTL). If keys expire unexpectedly, it can lead to data loss or inconsistent application behavior.
- **Blocking Operations in Event Loops:** Do not perform blocking Redis operations directly in event loops or GUI threads. Use asynchronous operations instead to avoid blocking the main thread.
- **Tooling and Environment**
- **Redis CLI:** Use the Redis CLI (`redis-cli`) for interacting with the Redis server, executing commands, and monitoring performance.
- **Redis Desktop Manager:** Use a Redis desktop manager (e.g., RedisInsight, Medis) for visualizing data, managing keys, and monitoring the Redis server.
- **Linting and Formatting:** Configure linters and formatters to enforce consistent code style and best practices in your Redis-related code.
- **CI/CD Integration:** Integrate Redis testing and deployment into your CI/CD pipeline to automate the testing and deployment process.
- **Monitoring Tools:** Utilize monitoring tools like Prometheus, Grafana, or Datadog to monitor Redis performance and health in production environments.