agent-workflow-kit-cli 1.3.2 → 1.3.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/commands/add.js +3 -1
- package/dist/cli/commands/init.js +6 -0
- package/dist/core/analyzer.js +70 -0
- package/dist/core/detector.js +22 -0
- package/package.json +1 -1
- package/templates/common/AGENTS.md.hbs +4 -0
- package/templates/common/GLOBAL_RULES.md +101 -0
- package/templates/dotnet/AGENTS.md.hbs +34 -34
- package/templates/dotnet/rules/api-structure.md +15 -15
- package/templates/dotnet/rules/csharp-style.md +17 -17
- package/templates/dotnet/rules/dependency-injection.md +12 -12
- package/templates/dotnet/rules/error-handling-validation.md +15 -15
- package/templates/dotnet/skills/dotnet-controller/SKILL.md +16 -16
- package/templates/express/AGENTS.md.hbs +33 -33
- package/templates/express/rules/error-handling.md +18 -18
- package/templates/express/rules/express-style.md +19 -19
- package/templates/express/rules/router-controller.md +16 -16
- package/templates/express/skills/express-endpoint/SKILL.md +14 -14
- package/templates/golang/AGENTS.md.hbs +36 -0
- package/templates/golang/rules/concurrency.md +71 -0
- package/templates/golang/rules/error-handling.md +42 -0
- package/templates/golang/rules/golang-style.md +24 -0
- package/templates/golang/rules/project-layout.md +39 -0
- package/templates/nestjs/AGENTS.md.hbs +29 -29
- package/templates/nestjs/rules/module-architecture.md +14 -14
- package/templates/nestjs/rules/nestjs-style.md +12 -12
- package/templates/nestjs/rules/validation-errors.md +15 -15
- package/templates/nestjs/skills/nestjs-module/SKILL.md +15 -15
- package/templates/next-js/AGENTS.md.hbs +32 -32
- package/templates/next-js/rules/data-fetching-mutations.md +17 -17
- package/templates/next-js/rules/next-style.md +17 -17
- package/templates/next-js/rules/seo-metadata.md +18 -18
- package/templates/next-js/rules/server-client-components.md +17 -17
- package/templates/next-js/skills/next-feature/SKILL.md +16 -16
- package/templates/rust/AGENTS.md.hbs +34 -0
- package/templates/rust/rules/error-handling.md +36 -0
- package/templates/rust/rules/memory-concurrency.md +47 -0
- package/templates/rust/rules/project-layout.md +49 -0
- package/templates/rust/rules/rust-style.md +26 -0
|
@@ -1,24 +1,24 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: dotnet-controller
|
|
3
|
-
description:
|
|
3
|
+
description: Scaffold or extend an ASP.NET Core API Controller with corresponding DTOs, FluentValidation, and Service interfaces
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
Follow this process to generate a new API Endpoint or Controller in .NET (C#).
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
- controllerName:
|
|
10
|
-
- routePath:
|
|
11
|
-
- requestDtoName:
|
|
12
|
-
- functionality:
|
|
8
|
+
Inputs:
|
|
9
|
+
- controllerName: Name of the Controller (e.g., `CoursesController`)
|
|
10
|
+
- routePath: HTTP route mapping (e.g., `api/v1/courses`)
|
|
11
|
+
- requestDtoName: Class name of the request DTO (e.g., `CreateCourseRequestDto`)
|
|
12
|
+
- functionality: Summary of the business requirements and methods to process
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
1.
|
|
16
|
-
2.
|
|
17
|
-
3.
|
|
18
|
-
4.
|
|
19
|
-
5.
|
|
20
|
-
6.
|
|
21
|
-
7.
|
|
22
|
-
8.
|
|
14
|
+
Steps:
|
|
15
|
+
1. Declare the corresponding Request/Response DTO classes inside the Application layer (or the project's `DTOs` directory).
|
|
16
|
+
2. Create a Validator class inheriting from FluentValidation's `AbstractValidator<T>` in the Application layer to define data constraints.
|
|
17
|
+
3. Define the Service Interface (e.g., `ICourseService`) and its concrete implementation class (`CourseService`) in the Application layer to handle business logic.
|
|
18
|
+
4. Register the new Service in the Dependency Injection container (using Scoped lifetime) inside the `Program.cs` configuration file.
|
|
19
|
+
5. Create the Controller class inheriting from `ControllerBase`, decorated with `[ApiController]` and `[Route]` attributes.
|
|
20
|
+
6. Use Constructor Injection to inject the Service Interface into the Controller, delegate request processing, and map responses to appropriate `IActionResult` objects (e.g., `Ok()`, `Created()`, `BadRequest()`).
|
|
21
|
+
7. Write unit tests for the Service and Controller using xUnit and Moq.
|
|
22
|
+
8. Execute compilation and testing:
|
|
23
23
|
- `dotnet build`
|
|
24
24
|
- `dotnet test`
|
|
@@ -1,41 +1,41 @@
|
|
|
1
|
-
## 🗺️
|
|
2
|
-
|
|
3
|
-
### 🔄
|
|
4
|
-
|
|
5
|
-
1. **
|
|
6
|
-
2. **
|
|
7
|
-
3. **
|
|
8
|
-
-
|
|
9
|
-
-
|
|
10
|
-
-
|
|
11
|
-
-
|
|
12
|
-
4. **
|
|
1
|
+
## 🗺️ Express.js Development Guide (Node.js Backend)
|
|
2
|
+
|
|
3
|
+
### 🔄 Agent Development Lifecycle
|
|
4
|
+
The AI Agent must execute all Express.js tasks following this 5-step workflow:
|
|
5
|
+
1. **Design & Implementation:** Organize code according to a clean 3-tier architecture. Spaghetti code is strictly prohibited.
|
|
6
|
+
2. **Comprehensive Testing:** Write unit tests for Services using Jest, and test API integrations using Supertest.
|
|
7
|
+
3. **Code Quality & Type Safety:** Run syntax check and type check commands:
|
|
8
|
+
- Linting: `{{runCommand}} lint`
|
|
9
|
+
- Type Checking: `{{runCommand}} typecheck`
|
|
10
|
+
- Testing: `{{runCommand}} test` (or `{{runCommand}} test -- --run` for CI/CD environments)
|
|
11
|
+
- Build Validation: `{{runCommand}} build`
|
|
12
|
+
4. **Dependency Management:** Install new libraries using `{{packageManager}} add [library_name]`. Never modify the lockfile `{{lockFile}}` manually.
|
|
13
13
|
|
|
14
14
|
---
|
|
15
15
|
|
|
16
|
-
### 🏗️
|
|
17
|
-
|
|
18
|
-
-
|
|
19
|
-
-
|
|
20
|
-
-
|
|
21
|
-
-
|
|
16
|
+
### 🏗️ Template Blueprint
|
|
17
|
+
Refer to the detailed rules below:
|
|
18
|
+
- Clean coding style and type safety using TypeScript in Express: `@express-style.md`
|
|
19
|
+
- Separation of concerns: Router mappings $\rightarrow$ Controller delegation $\rightarrow$ Service execution: `@router-controller.md`
|
|
20
|
+
- Async error catching strategies and centralized global error handling middleware: `@error-handling.md`
|
|
21
|
+
- Process to scaffold new API endpoints cleanly from Routers to Validators: `@SKILL.md`
|
|
22
22
|
|
|
23
23
|
---
|
|
24
24
|
|
|
25
|
-
### 🏛️
|
|
25
|
+
### 🏛️ Strict Development Rules
|
|
26
26
|
|
|
27
|
-
#### 1.
|
|
28
|
-
|
|
27
|
+
#### 1. Strict Layer Separation
|
|
28
|
+
Strictly comply with the data flow chain:
|
|
29
29
|
$$\text{Client} \longrightarrow \text{Router} \longrightarrow \text{Middleware} \longrightarrow \text{Controller} \longrightarrow \text{Service} \longrightarrow \text{Model/Database}$$
|
|
30
|
-
- **Router:**
|
|
31
|
-
- **Controller:**
|
|
32
|
-
- **Service:**
|
|
33
|
-
|
|
34
|
-
#### 2.
|
|
35
|
-
- **
|
|
36
|
-
- **
|
|
37
|
-
- **
|
|
38
|
-
|
|
39
|
-
#### 3.
|
|
40
|
-
- **
|
|
41
|
-
- **
|
|
30
|
+
- **Router:** Must not contain processing logic. Only maps HTTP methods + paths and registers auth/validation middlewares.
|
|
31
|
+
- **Controller:** Only extracts inputs from the request object (`req.body`, `req.query`, `req.params`), invokes the target Service, and returns the response using `res.status().json()`. Never execute database queries directly here.
|
|
32
|
+
- **Service:** Houses business logic, calculations, and database model interactions. Must not reference or depend on Express `req` or `res` objects to ensure testability.
|
|
33
|
+
|
|
34
|
+
#### 2. Async Error Handling
|
|
35
|
+
- **No Manual Try/Catch in Controllers:** Avoid wrapping every controller method in manual try/catch blocks.
|
|
36
|
+
- **Use Async Handlers:** Wrap all async controller functions with an automatic error-catching wrapper (such as `express-async-handler`) to forward exceptions to the `next()` function automatically.
|
|
37
|
+
- **Centralized Global Error Middleware:** Declare a 4-parameter error-handling middleware at the end of the server bootstrap chain (after all route registrations) to format error payloads.
|
|
38
|
+
|
|
39
|
+
#### 3. Request Validation with Zod Middleware
|
|
40
|
+
- **No Manual Conditional Validation:** Do not write scattered `if` blocks to check input parameters.
|
|
41
|
+
- **Zod Schema Middleware:** Implement a shared validation middleware that accepts a Zod schema to validate request segments (`body`, `query`, `params`) before they reach the Controller.
|
|
@@ -1,36 +1,36 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Async Error Handling & Automated Validation (Zod Middleware)
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
This document defines standard practices for asynchronous error catching, centralized global error handling middleware, and automated schema validations using Zod.
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
## 🚨
|
|
8
|
-
- **
|
|
9
|
-
- **
|
|
7
|
+
## 🚨 Async Error Handling Architecture
|
|
8
|
+
- **No Manual Try/Catch in Controllers:** Wrapping every controller method in manual try/catch blocks is prohibited.
|
|
9
|
+
- **Use Async Handlers:** Wrap all async controller functions with an automatic error-catching wrapper (such as `asyncHandler`) to automatically forward exceptions to Express's `next()` function.
|
|
10
10
|
|
|
11
11
|
```typescript
|
|
12
12
|
import { Request, Response, NextFunction } from 'express';
|
|
13
13
|
|
|
14
|
-
//
|
|
15
|
-
|
|
14
|
+
// Automated async error catcher wrapper
|
|
15
|
+
const asyncHandler = (fn: Function) => (req: Request, res: Response, next: NextFunction) => {
|
|
16
16
|
Promise.resolve(fn(req, res, next)).catch(next);
|
|
17
17
|
};
|
|
18
18
|
|
|
19
|
-
//
|
|
19
|
+
// Controller usage example
|
|
20
20
|
export const getUserProfile = asyncHandler(async (req: Request, res: Response) => {
|
|
21
21
|
const userId = req.user.id;
|
|
22
|
-
const profile = await userService.getProfile(userId); //
|
|
22
|
+
const profile = await userService.getProfile(userId); // Errors thrown inside the service are automatically caught
|
|
23
23
|
return res.status(200).json({ success: true, data: profile });
|
|
24
24
|
});
|
|
25
25
|
```
|
|
26
26
|
|
|
27
27
|
---
|
|
28
28
|
|
|
29
|
-
## 🔌
|
|
30
|
-
- **
|
|
29
|
+
## 🔌 Centralized Global Error Handler Middleware
|
|
30
|
+
- **Register Error Middleware:** You must register a 4-parameter error-handling middleware at the end of the server bootstrap chain (after all route registrations) to parse and return clean error responses.
|
|
31
31
|
|
|
32
32
|
```typescript
|
|
33
|
-
//
|
|
33
|
+
// Inside app.ts or server.ts
|
|
34
34
|
app.use((err: any, req: Request, res: Response, next: NextFunction) => {
|
|
35
35
|
const statusCode = err.statusCode || 500;
|
|
36
36
|
const message = err.message || 'Internal Server Error';
|
|
@@ -46,9 +46,9 @@ Tài liệu này quy định chiến lược xử lý lỗi bất đồng bộ (
|
|
|
46
46
|
|
|
47
47
|
---
|
|
48
48
|
|
|
49
|
-
## 🛡️
|
|
50
|
-
- **
|
|
51
|
-
- **
|
|
49
|
+
## 🛡️ Automated Validation with Zod Middleware
|
|
50
|
+
- **No Manual Conditional Checks:** Do not write scattered `if (!req.body.email)` conditionals inside controllers.
|
|
51
|
+
- **Zod Schema Middleware:** Implement a shared validation middleware that accepts a Zod schema to validate request segments (`body`, `query`, `params`) before they reach the Controller.
|
|
52
52
|
|
|
53
53
|
```typescript
|
|
54
54
|
import { AnyZodObject, ZodError } from 'zod';
|
|
@@ -57,14 +57,14 @@ Tài liệu này quy định chiến lược xử lý lỗi bất đồng bộ (
|
|
|
57
57
|
export const validateSchema = (schema: AnyZodObject) => {
|
|
58
58
|
return async (req: Request, res: Response, next: NextFunction): Promise<any> => {
|
|
59
59
|
try {
|
|
60
|
-
//
|
|
60
|
+
// Validate incoming request segments concurrently
|
|
61
61
|
const parsed = await schema.parseAsync({
|
|
62
62
|
body: req.body,
|
|
63
63
|
query: req.query,
|
|
64
64
|
params: req.params,
|
|
65
65
|
});
|
|
66
66
|
|
|
67
|
-
//
|
|
67
|
+
// Re-assign parsed and sanitized payloads
|
|
68
68
|
req.body = parsed.body;
|
|
69
69
|
req.query = parsed.query;
|
|
70
70
|
req.params = parsed.params;
|
|
@@ -74,7 +74,7 @@ Tài liệu này quy định chiến lược xử lý lỗi bất đồng bộ (
|
|
|
74
74
|
if (error instanceof ZodError) {
|
|
75
75
|
return res.status(400).json({
|
|
76
76
|
success: false,
|
|
77
|
-
message: '
|
|
77
|
+
message: 'Invalid input payload parameters',
|
|
78
78
|
errors: error.errors.map((err) => ({
|
|
79
79
|
field: err.path.join('.'),
|
|
80
80
|
message: err.message,
|
|
@@ -1,28 +1,28 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Express.js Naming Conventions & Coding Style
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
This document defines coding conventions, directory layout, and TypeScript configurations for Express.js applications.
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
## 🏷️
|
|
7
|
+
## 🏷️ Naming Conventions
|
|
8
8
|
|
|
9
|
-
###
|
|
10
|
-
|
|
9
|
+
### Directory Layout (3-Tier Architecture)
|
|
10
|
+
The codebase must be structured cleanly according to a 3-tier architecture layout:
|
|
11
11
|
```bash
|
|
12
12
|
src/
|
|
13
|
-
├── config/ #
|
|
14
|
-
├── middlewares/ #
|
|
15
|
-
├── models/ #
|
|
16
|
-
├── routes/ #
|
|
17
|
-
├── controllers/ #
|
|
18
|
-
├── services/ #
|
|
19
|
-
├── utils/ #
|
|
20
|
-
└── app.ts #
|
|
13
|
+
├── config/ # Environment configurations, DB initializations
|
|
14
|
+
├── middlewares/ # Express middleware functions (Auth, Log, Validation)
|
|
15
|
+
├── models/ # Database Schemas (Mongoose, Sequelize, or Prisma client)
|
|
16
|
+
├── routes/ # HTTP Route definitions and input middleware binding
|
|
17
|
+
├── controllers/ # Request parameter extraction, response formatting
|
|
18
|
+
├── services/ # Houses 100% of business logic and computations
|
|
19
|
+
├── utils/ # Standalone utility helper functions
|
|
20
|
+
└── app.ts # Express App setup and server bootstrapping
|
|
21
21
|
```
|
|
22
22
|
|
|
23
|
-
###
|
|
24
|
-
- **
|
|
25
|
-
- **
|
|
23
|
+
### Filename Notation
|
|
24
|
+
- **Consistency:** Use `kebab-case.ts` across all filenames in the repository.
|
|
25
|
+
- **Suffix Declarations:** Filenames must end with a suffix representing their architectural role:
|
|
26
26
|
- Controller: `user-controller.ts`
|
|
27
27
|
- Service: `user-service.ts`
|
|
28
28
|
- Route: `user-route.ts`
|
|
@@ -31,9 +31,9 @@ src/
|
|
|
31
31
|
|
|
32
32
|
---
|
|
33
33
|
|
|
34
|
-
## 📦
|
|
35
|
-
- **
|
|
34
|
+
## 📦 TypeScript & Type Declarations
|
|
35
|
+
- **Explicit Type Declarations:** Avoid implicit type inference. Always define types for `req`, `res`, and `next` parameters imported from `express`:
|
|
36
36
|
```typescript
|
|
37
37
|
import { Request, Response, NextFunction } from 'express';
|
|
38
38
|
```
|
|
39
|
-
- **
|
|
39
|
+
- **Strictly Ban the `any` Keyword:** Declare interfaces or types for all request bodies and API response structures.
|
|
@@ -1,27 +1,27 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Architectural Boundaries (Router vs Controller vs Service)
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
This document establishes boundaries and responsibilities for routers, controllers, and services in Express.js projects.
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
## 🏛️
|
|
8
|
-
|
|
7
|
+
## 🏛️ Data Flow Chain
|
|
8
|
+
All features in the repository must comply with the standard 3-tier architecture data flow:
|
|
9
9
|
$$\text{Client} \longrightarrow \text{Router} \longrightarrow \text{Middleware} \longrightarrow \text{Controller} \longrightarrow \text{Service} \longrightarrow \text{Model/Database}$$
|
|
10
10
|
|
|
11
11
|
---
|
|
12
12
|
|
|
13
|
-
## 🚦
|
|
13
|
+
## 🚦 Layer Responsibilities
|
|
14
14
|
|
|
15
|
-
### 1.
|
|
16
|
-
- **
|
|
17
|
-
- **
|
|
15
|
+
### 1. Router Layer (`routes/`)
|
|
16
|
+
- **Role:** Exclusively responsible for mapping HTTP methods + paths and binding authentication or payload validation middlewares (e.g., Zod schemas).
|
|
17
|
+
- **Rule:** Under no circumstances should the Router layer house business calculations or database operations. It must only forward requests to the target Controller.
|
|
18
18
|
|
|
19
|
-
### 2.
|
|
20
|
-
- **
|
|
21
|
-
- **
|
|
22
|
-
-
|
|
23
|
-
-
|
|
19
|
+
### 2. Controller Layer (`controllers/`)
|
|
20
|
+
- **Role:** Responsible for extracting input payloads from the Express `req` object (`req.body`, `req.query`, `req.params`, `req.user`), forwarding these arguments to the Service layer, receiving outcomes, and responding to the client via `res.status().json()`.
|
|
21
|
+
- **Rules:**
|
|
22
|
+
- Never query database models or call ORM clients inside the Controller.
|
|
23
|
+
- Never write manual try/catch blocks (delegate errors to the global error handler using async wrappers).
|
|
24
24
|
|
|
25
|
-
### 3.
|
|
26
|
-
- **
|
|
27
|
-
- **
|
|
25
|
+
### 3. Service Layer (`services/`)
|
|
26
|
+
- **Role:** Houses 100% of the core business logic, coordinates data mutations, executes algorithms, and interacts with Database models.
|
|
27
|
+
- **Rule:** Never import, reference, or access Express-specific objects (`req`, `res`, or `next`) inside Services. The Service layer must remain completely decoupled from the web framework to maintain isolated testability.
|
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: express-endpoint
|
|
3
|
-
description:
|
|
3
|
+
description: Scaffold or extend a secure Express.js + TypeScript API endpoint including Router, Controller, and Validator
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
Follow this process to generate a new Express.js API Endpoint or extend an existing route.
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
- endpointName:
|
|
10
|
-
- routePath:
|
|
11
|
-
- httpMethod:
|
|
12
|
-
- targetPath:
|
|
8
|
+
Inputs:
|
|
9
|
+
- endpointName: Name of the API Endpoint to create (e.g., `user-profile`)
|
|
10
|
+
- routePath: HTTP route path of the API (e.g., `/api/v1/users/profile`)
|
|
11
|
+
- httpMethod: HTTP method (GET, POST, PUT, DELETE)
|
|
12
|
+
- targetPath: The destination path to place the code files
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
1.
|
|
16
|
-
2.
|
|
17
|
-
3.
|
|
18
|
-
4.
|
|
19
|
-
5.
|
|
20
|
-
6.
|
|
14
|
+
Steps:
|
|
15
|
+
1. Define a Zod Validation Schema under the `middlewares/` directory or alongside the controller to validate input payloads.
|
|
16
|
+
2. Implement the corresponding Service function under the `services/` directory to handle 100% of the business logic and ORM queries.
|
|
17
|
+
3. Implement the Controller dispatcher in the `controllers/` directory using the `asyncHandler` wrapper to forward errors automatically, extract inputs, and send JSON responses.
|
|
18
|
+
4. Register the Controller and mount the `validateSchema(zodSchema)` middleware on the target Route file under the `routes/` directory.
|
|
19
|
+
5. Create unit test suites for the Service and integration test suites (E2E) using Supertest.
|
|
20
|
+
6. Execute local validation:
|
|
21
21
|
- `{{runCommand}} lint`
|
|
22
22
|
- `{{runCommand}} typecheck`
|
|
23
23
|
- `{{runCommand}} test`
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
## 🗺️ Golang Development Guide (Go Backend)
|
|
2
|
+
|
|
3
|
+
### 🔄 Agent Development Lifecycle
|
|
4
|
+
The AI Agent must execute all Golang tasks following this 4-step workflow:
|
|
5
|
+
1. **Design & Implementation:** Implement business logic adhering to the Standard Go Project Layout. Keep entrypoints in `cmd/`, core business logic in `internal/`, and standalone shared libraries in `pkg/`.
|
|
6
|
+
2. **Comprehensive Testing:** Write unit tests using the table-driven testing pattern and Go's built-in `testing` library. Run tests with: `go test ./...`.
|
|
7
|
+
3. **Code Quality & Formatting:** Ensure code compiles and meets formatting/linting rules:
|
|
8
|
+
- Formatting: `gofmt -w .`
|
|
9
|
+
- Linting: `golangci-lint run`
|
|
10
|
+
- Build Validation: `go build ./...`
|
|
11
|
+
4. **Dependency Management:** Add new external libraries using `go get [library_name]`. Never manually edit the `go.sum` file.
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
### 🏗️ Template Blueprint
|
|
16
|
+
Refer to the detailed rules below:
|
|
17
|
+
- Go coding style, interface design, and naming conventions: `@golang-style.md`
|
|
18
|
+
- Directory organization and manual dependency injection: `@project-layout.md`
|
|
19
|
+
- Explicit error handling, wrapping, and custom API errors: `@error-handling.md`
|
|
20
|
+
- Concurrency, goroutine/channel lifecycle, and escape analysis: `@concurrency.md`
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
### 🏛️ Strict Development Rules
|
|
25
|
+
|
|
26
|
+
#### 1. Package Boundaries & Encapsulation
|
|
27
|
+
- **No Circular Dependencies:** Design packages around domains/components rather than tech layers (e.g., separate folders for `course`, `billing` instead of `controllers`, `models`) to avoid circular imports.
|
|
28
|
+
- **Internal Directory:** Keep 100% of core application logic inside `/internal` to enforce encapsulation and leverage Go compiler protections.
|
|
29
|
+
|
|
30
|
+
#### 2. Explicit Error Handling
|
|
31
|
+
- **Check Every Error:** Never ignore returned errors. Write `if err != nil` checks immediately after calling fallible functions.
|
|
32
|
+
- **Wrap Errors:** Use `fmt.Errorf("failed to...: %w", err)` when propagating errors to preserve runtime context.
|
|
33
|
+
|
|
34
|
+
#### 3. Safe Concurrency
|
|
35
|
+
- **Context Propagation:** Pass `ctx context.Context` as the first argument to all functions executing I/O.
|
|
36
|
+
- **Prevent Race Conditions:** Protect shared memory access across goroutines using `sync.Mutex` or `sync/atomic`.
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# Golang Concurrency & Memory Allocation
|
|
2
|
+
|
|
3
|
+
This document outlines standard guidelines for goroutines, context propagation, race conditions, and heap allocation optimizations.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 🧠 Escape Analysis & Allocations
|
|
8
|
+
The Go compiler determines if a variable should live on the Stack (fast, auto-allocated/deallocated) or Heap (garbage-collected).
|
|
9
|
+
- **Pointer Rule (*):** Return pointers only for large structs where value copying is expensive, or when you must modify the receiver's state directly.
|
|
10
|
+
- **Value Types for Small Structs:** For small configuration values or short-lived structs (under 64-128 bytes), return value types to keep allocations on the Stack.
|
|
11
|
+
```go
|
|
12
|
+
// ❌ Forces heap allocation (Bad)
|
|
13
|
+
func NewConfig() *Config {
|
|
14
|
+
return &Config{Timeout: 30}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// ✔️ Keeps allocation on the Stack (Good)
|
|
18
|
+
func NewConfig() Config {
|
|
19
|
+
return Config{Timeout: 30}
|
|
20
|
+
}
|
|
21
|
+
```
|
|
22
|
+
- **sync.Pool Usage:** For high-frequency, repetitive operations like JSON encoding/decoding or byte buffer allocation (`[]byte`), use `sync.Pool` to reuse memory, minimizing GC pressure.
|
|
23
|
+
```go
|
|
24
|
+
var bufferPool = sync.Pool{
|
|
25
|
+
New: func() any {
|
|
26
|
+
return make([]byte, 1024)
|
|
27
|
+
},
|
|
28
|
+
}
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## 🚦 Prevent Goroutine Leaks
|
|
34
|
+
- **Rule:** When writing data to a channel inside an independent goroutine, ensure the channel has a buffer or is monitored with timeouts/contexts to prevent permanent blocking.
|
|
35
|
+
```go
|
|
36
|
+
// ❌ Leaks goroutine if no reader reads from ch (Bad)
|
|
37
|
+
func FetchData() string {
|
|
38
|
+
ch := make(chan string) // Unbuffered channel
|
|
39
|
+
go func() {
|
|
40
|
+
ch <- doHeavyWork() // Blocks indefinitely if parent exits early
|
|
41
|
+
}()
|
|
42
|
+
return <-ch
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// ✔️ Safe with Buffer and Context (Good)
|
|
46
|
+
func FetchData(ctx context.Context) (string, error) {
|
|
47
|
+
ch := make(chan string, 1) // Buffered channel avoids blocking
|
|
48
|
+
go func() {
|
|
49
|
+
ch <- doHeavyWork()
|
|
50
|
+
}()
|
|
51
|
+
|
|
52
|
+
select {
|
|
53
|
+
case res := <-ch:
|
|
54
|
+
return res, nil
|
|
55
|
+
case <-ctx.Done():
|
|
56
|
+
return "", ctx.Err() // Exits safely on timeout/cancel
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
## 🧭 Context Propagation
|
|
64
|
+
- Pass `ctx context.Context` as the first argument to any functions handling network or filesystem operations.
|
|
65
|
+
- Never store Context inside a struct; pass it explicitly down the call chain.
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## ⚡ Prevent Race Conditions
|
|
70
|
+
Protect shared variables accessed concurrently across multiple goroutines using `sync.Mutex`, `sync.RWMutex`, or `sync/atomic`.
|
|
71
|
+
- Run race detection during testing: `go test -race ./...`.
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Golang Error Handling Standards
|
|
2
|
+
|
|
3
|
+
This document defines strict guidelines for error checking, error wrapping, and structuring standard API errors.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 🔄 Error Wrapping
|
|
8
|
+
- **Rule:** When passing errors up the stack (e.g., from Repository to UseCase), never return the raw error or create a new error that discards the trace.
|
|
9
|
+
- **Solution:** Use `%w` in `fmt.Errorf` to wrap the underlying error with contextual information:
|
|
10
|
+
```go
|
|
11
|
+
if err != nil {
|
|
12
|
+
return fmt.Errorf("failed to fetch user from db (id: %d): %w", id, err)
|
|
13
|
+
}
|
|
14
|
+
```
|
|
15
|
+
- **Checking Errors:** Use `errors.Is()` for comparing sentinel errors and `errors.As()` to extract custom error structures:
|
|
16
|
+
```go
|
|
17
|
+
if errors.Is(err, sql.ErrNoRows) {
|
|
18
|
+
// Handle record not found
|
|
19
|
+
}
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## 🏛️ Standard Custom Errors
|
|
25
|
+
To return uniform error responses to Frontend clients or API Gateways, define a standard struct:
|
|
26
|
+
```go
|
|
27
|
+
type AppError struct {
|
|
28
|
+
Code string `json:"code"`
|
|
29
|
+
Message string `json:"message"`
|
|
30
|
+
Details map[string]string `json:"details,omitempty"`
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
func (e *AppError) Error() string {
|
|
34
|
+
return fmt.Sprintf("[%s] %s", e.Code, e.Message)
|
|
35
|
+
}
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## 🚫 Avoid Panics
|
|
41
|
+
- **Strict Rule:** Never use `panic` and `recover` for normal business flow control or expected failures.
|
|
42
|
+
- **Exception:** Only use `panic` during application startup if a fatal dependency fails (e.g., cannot connect to the primary database, or port is already in use).
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Golang Coding Style Rules
|
|
2
|
+
|
|
3
|
+
This document defines naming conventions, interface designs, and code style rules for Golang projects.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 🏷️ Naming Conventions
|
|
8
|
+
- **Package Names:** Must be short, single-word, lowercase names (e.g., `user`, `config`, `db`, `auth`). Never use `camelCase`, `snake_case`, or hyphens.
|
|
9
|
+
- **Private Symbols (Variables & Functions):** Use `camelCase` (e.g., `userID`, `fetchData`).
|
|
10
|
+
- **Public Symbols (Exported):** Use `PascalCase` to export variables, functions, and structs (e.g., `UserID`, `FetchData`).
|
|
11
|
+
- **Acronyms:** Keep acronyms consistent in casing (e.g., `userID` instead of `userId`, `httpServer` instead of `httpServer`).
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## 🔌 Interface Design
|
|
16
|
+
- **Rule:** *"Accept interfaces, return structs"*. This optimizes escape analysis and maintains clean API boundaries.
|
|
17
|
+
- **Minimality:** Design interfaces to be small, ideally declaring only 1 or 2 methods (e.g., `io.Reader`, `io.Writer`).
|
|
18
|
+
- **Naming:** End interface names with the `-er` suffix if they declare a single method (e.g., `Reader`, `Writer`, `Validator`).
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## 🚫 Avoid Global Variables
|
|
23
|
+
- **No Global Mutable State:** Do not instantiate global variables for connections, logs, or caches.
|
|
24
|
+
- **Solution:** Pass dependencies explicitly through struct constructors (Dependency Injection) instead of accessing global instances.
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Golang Project Architecture & Layout
|
|
2
|
+
|
|
3
|
+
This document defines the Standard Go Project Layout and Clean Architecture conventions.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 🏗️ Standard Directory Structure
|
|
8
|
+
Adhere to the following layout guidelines:
|
|
9
|
+
- **/cmd:** Contains only the entrypoints of the application (e.g., `cmd/api/main.go`). Code here must only parse configs, initialize the DI container, and start the server. Do not write business logic here.
|
|
10
|
+
- **/internal:** Contains all core application code. The Go compiler enforces that external packages cannot import code from this directory. Write 100% of business logic here.
|
|
11
|
+
- **/pkg:** Contains standalone utility libraries that can be shared with other projects (e.g., `pkg/logger`, `pkg/crypto`). Code in `/pkg` must never import packages from `/internal`.
|
|
12
|
+
- **/api:** Contains API contract definitions (OpenAPI/Swagger schemas, gRPC proto files).
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## 🏛️ Clean Architecture Layers
|
|
17
|
+
Organize code inside `/internal/app` or `/internal/<domain>` into 3 distinct layers:
|
|
18
|
+
1. **Entities (Domain Models):** Pure Go structs and core business rules. They must be free of external dependencies.
|
|
19
|
+
2. **Use Cases (Services):** Coordinates business logic. Interacts only with interfaces representing external components.
|
|
20
|
+
3. **Adapters (Controllers / Repositories):** Manages external communications (e.g., database operations using GORM, API routes using Fiber/Echo, gRPC handlers).
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## 💉 Manual Dependency Injection (DI)
|
|
25
|
+
- **Constructor Injection:** Pass dependencies to structs (UseCases or Repositories) via `New[StructName]` constructors. Dependencies must be passed as interfaces.
|
|
26
|
+
- **Example:**
|
|
27
|
+
```go
|
|
28
|
+
type UserRepository interface {
|
|
29
|
+
GetByID(ctx context.Context, id int64) (*domain.User, error)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
type UserUseCase struct {
|
|
33
|
+
repo UserRepository // Access via interface
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
func NewUserUseCase(r UserRepository) *UserUseCase {
|
|
37
|
+
return &UserUseCase{repo: r}
|
|
38
|
+
}
|
|
39
|
+
```
|