Skip to content

Commit b6dc6b6

Browse files
authored
Merge pull request #427 from lenneTech/develop
Release 11.1.11
2 parents 0d10224 + 93b19e6 commit b6dc6b6

File tree

7 files changed

+415
-5
lines changed

7 files changed

+415
-5
lines changed
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# Git Commit Guidelines for Copilot & Conventional Commits
2+
3+
Follow the structure:
4+
**<type>(<TICKET>): <message>**
5+
6+
Example:
7+
`feat(DEV-123): implement user login via OAuth`
8+
9+
## Rules
10+
11+
- Extract the **ticket number** (e.g. `DEV-123`) from the current branch name.
12+
- Branch example: `DEV-123-feature-login`
13+
- Use exactly **one** Conventional Commit prefix per commit:
14+
- `feat`: for new features
15+
- `fix`: for bug fixes
16+
- `perf`: for performance improvements
17+
- `refactor`: for code changes that neither fix a bug nor add a feature
18+
- `revert`: for reverting previous commits
19+
- `docs`: for documentation-only changes
20+
- `style`: for formatting, whitespace, semicolons, etc. (no code changes)
21+
- `chore`: for tooling/config/non-runtime maintenance
22+
- `test`: for adding or updating tests
23+
- `build`: for build system or dependencies
24+
- `ci`: for CI/CD configuration
25+
- Write commit messages in **English**.
26+
- Determine the prefix (`feat`, `fix`, etc.) automatically based on the code diff.
27+
- Avoid combining multiple prefixes (e.g. `feat+fix`) – use separate commits if necessary.
28+
29+
## Format
30+
31+
`<type>(<TICKET>): <short imperative message>`
32+
33+
✅ Correct:
34+
35+
- `fix(DEV-456): prevent crash when clicking submit`
36+
- `feat(DEV-789): add search filter for product list`
37+
38+
❌ Incorrect:
39+
40+
- `fix,feat(DEV-123): ...` → use only one type
41+
- `DEV-123: fixed stuff` → missing type prefix
42+
- `feat: login feature` → missing ticket ID

.github/copilot-instructions.md

Lines changed: 218 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,218 @@
1+
# GitHub Copilot Instructions for lenne.Tech Nest Server
2+
3+
This file provides specific guidance for GitHub Copilot when working with this NestJS-based server project.
4+
5+
## Project Overview
6+
7+
This is a **NestJS server framework** with:
8+
- **GraphQL API** using Apollo Server
9+
- **MongoDB** integration with Mongoose
10+
- **JWT authentication** with refresh tokens
11+
- **Role-based access control**
12+
- **Modular architecture** with Core/Server separation
13+
14+
## Code Architecture & Patterns
15+
16+
### Module Structure
17+
- **Core modules** (`src/core/`): Reusable framework components
18+
- **Server modules** (`src/server/`): Project-specific implementations
19+
- Use `CoreModule.forRoot()` for dynamic module configuration
20+
- Extend core classes rather than creating from scratch
21+
22+
### Model Patterns
23+
```typescript
24+
// Always extend CorePersistenceModel for database entities
25+
@MongooseSchema({ timestamps: true })
26+
@ObjectType({ description: 'Your Model' })
27+
@Restricted(RoleEnum.S_EVERYONE)
28+
export class YourModel extends CorePersistenceModel {
29+
@UnifiedField({
30+
description: 'Field description',
31+
roles: RoleEnum.S_EVERYONE,
32+
validator: () => [IsString()],
33+
})
34+
fieldName: string = undefined;
35+
}
36+
```
37+
38+
### Input Classes
39+
```typescript
40+
// Use CoreInput as base and UnifiedField decorator
41+
@InputType({ description: 'Your input' })
42+
@Restricted(RoleEnum.S_EVERYONE)
43+
export class YourInput extends CoreInput {
44+
@UnifiedField({
45+
description: 'Field description',
46+
isOptional: false,
47+
roles: RoleEnum.S_EVERYONE,
48+
validator: () => [IsString(), IsNotEmpty()],
49+
})
50+
fieldName: string = undefined;
51+
}
52+
```
53+
54+
### Service Patterns
55+
```typescript
56+
// Extend CrudService for standard CRUD operations
57+
@Injectable()
58+
export class YourService extends CrudService<YourModel, YourCreateInput, YourUpdateInput> {
59+
constructor(
60+
@InjectModel('YourModel') protected readonly model: Model<YourModelDocument>,
61+
protected readonly configService: ConfigService,
62+
) {
63+
super({ model });
64+
}
65+
}
66+
```
67+
68+
## Security & Authorization
69+
70+
### Access Control
71+
- Use `@Restricted(RoleEnum.ROLE_NAME)` on classes and fields
72+
- Use `@Roles(RoleEnum.ROLE_NAME)` on methods
73+
- Never expose sensitive fields without proper restrictions
74+
- Password fields should use `@Restricted(RoleEnum.S_NO_ONE)`
75+
76+
### Authentication
77+
- JWT tokens contain: `id`, `deviceId`, `tokenId`, `deviceDescription`
78+
- Refresh tokens are stored in `user.refreshTokens[deviceId]`
79+
- Use `@CurrentUser()` decorator to access authenticated user
80+
- Device tracking is automatic via `deviceId`
81+
82+
## Database Patterns
83+
84+
### Mongoose Configuration
85+
- Use `@Prop()` for simple fields
86+
- Use `@Prop(raw({}))` for dynamic objects
87+
- Index important fields with `@Prop({ index: true })`
88+
- Always use timestamps: `@MongooseSchema({ timestamps: true })`
89+
90+
### Filtering & Pagination
91+
```typescript
92+
// Use built-in filtering and pagination
93+
async findMany(
94+
filter?: FilterArgs,
95+
pagination?: PaginationArgs,
96+
serviceOptions?: ServiceOptions,
97+
): Promise<YourModel[]> {
98+
return super.find(filter, serviceOptions, pagination);
99+
}
100+
```
101+
102+
## GraphQL Patterns
103+
104+
### Resolvers
105+
```typescript
106+
@Resolver(() => YourModel)
107+
export class YourResolver {
108+
@Query(() => YourModel)
109+
@Roles(RoleEnum.USER)
110+
async getYour(@Args() args: GetArgs): Promise<YourModel> {
111+
return this.yourService.get(args.id);
112+
}
113+
114+
@Mutation(() => YourModel)
115+
@Roles(RoleEnum.USER)
116+
async createYour(@Args('input') input: YourCreateInput): Promise<YourModel> {
117+
return this.yourService.create(input);
118+
}
119+
}
120+
```
121+
122+
### Field Resolvers
123+
```typescript
124+
@ResolverField(() => [RelatedModel])
125+
async relatedItems(@Parent() parent: YourModel): Promise<RelatedModel[]> {
126+
return this.relatedService.find({ yourId: parent.id });
127+
}
128+
```
129+
130+
## Development Practices
131+
132+
### Error Handling
133+
- Use NestJS exceptions: `BadRequestException`, `UnauthorizedException`
134+
- Provide meaningful error messages
135+
- Handle validation errors automatically via `MapAndValidatePipe`
136+
137+
### Testing
138+
- Write E2E tests in `tests/` directory
139+
- Use `test.helper.ts` utilities
140+
- Test with `NODE_ENV=local`
141+
- Mock external services appropriately
142+
143+
### Configuration
144+
- Environment configs in `src/config.env.ts`
145+
- Support multiple config sources:
146+
- Direct environment variables
147+
- `NEST_SERVER_CONFIG` JSON
148+
- `NSC__*` prefixed variables
149+
150+
## File Organization
151+
152+
### New Features
153+
1. Create module in appropriate location (`src/core/` or `src/server/`)
154+
2. Include: model, service, resolver, controller (if needed)
155+
3. Add input/output classes in dedicated folders
156+
4. Export everything in module's `index.ts`
157+
158+
### Naming Conventions
159+
- Models: `YourModel` (singular)
160+
- Services: `YourService`
161+
- Resolvers: `YourResolver`
162+
- Controllers: `YourController`
163+
- Inputs: `YourCreateInput`, `YourUpdateInput`
164+
- Files: kebab-case (e.g., `your-model.model.ts`)
165+
166+
## Common Commands
167+
168+
### Development
169+
```bash
170+
npm start # Start local development
171+
npm run start:dev # Start with file watching
172+
npm run build # Build application
173+
npm run lint # Run ESLint
174+
npm run test:e2e # Run E2E tests
175+
npm run docs # Generate documentation
176+
```
177+
178+
### Package Development
179+
```bash
180+
npm run build:dev # Build and push to yalc
181+
npm run build:pack # Create tarball for testing
182+
```
183+
184+
## Anti-Patterns to Avoid
185+
186+
**Don't do:**
187+
- Create models without extending `CorePersistenceModel`
188+
- Use plain `@Field()` instead of `@UnifiedField()`
189+
- Expose sensitive data without `@Restricted()`
190+
- Create services without proper CRUD patterns
191+
- Skip input validation
192+
- Hardcode configuration values
193+
- Create duplicate authentication logic
194+
195+
**Do instead:**
196+
- Follow established inheritance patterns
197+
- Use framework decorators and helpers
198+
- Implement proper security restrictions
199+
- Leverage existing CRUD functionality
200+
- Use configuration system
201+
- Follow modular architecture
202+
203+
## TypeScript Guidelines
204+
205+
- Use strict typing, avoid `any`
206+
- Use interfaces for complex data structures
207+
- Prefer composition over inheritance where appropriate
208+
- Use proper generics for reusable components
209+
- Export types alongside implementation files
210+
211+
## Email & Templates
212+
213+
- Use `EmailService` for sending emails
214+
- Templates are in `src/templates/` using EJS
215+
- Support both SMTP and Mailjet providers
216+
- Use `TemplateService` for rendering
217+
218+
Remember: This is a **framework package** that can be extended. Focus on creating reusable, well-documented components that follow the established patterns.

0 commit comments

Comments
 (0)