Add Angular 21 and NestJS tech preset to installation wizard#569
Add Angular 21 and NestJS tech preset to installation wizard#569Silvino-Miranda wants to merge 2 commits intoSynkraAI:mainfrom
Conversation
|
@Silvino-Miranda is attempting to deploy a commit to the Pedro Valério Lopez's projects Team on Vercel. A member of the Team first needs to authorize it. |
WalkthroughA new "angular-nestjs" technology preset has been added to the system. This includes updated entity registry metadata, a comprehensive preset documentation file containing architecture patterns and best practices for Angular 21 and NestJS fullstack development, an updated installation manifest, and a UI option in the installer wizard. Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes 🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Tip Try Coding Plans. Let us write the prompt for your AI agent so you can ship faster (with fewer bugs). Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Welcome to aiox-core! Thanks for your first pull request.
What happens next?
- Automated checks will run on your PR
- A maintainer will review your changes
- Once approved, we'll merge your contribution!
PR Checklist:
- Tests pass (
npm test) - Linting passes (
npm run lint) - Commit messages follow Conventional Commits
Thanks for contributing!
There was a problem hiding this comment.
Actionable comments posted: 7
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
.aiox-core/install-manifest.yaml (1)
1-3:⚠️ Potential issue | 🟡 MinorManifest metadata mismatch—regenerate with
npm run generate:manifest.The manifest entry for
angular-nestjs.mdlists a file size of 22,621 bytes, but the actual file is 21,910 bytes. The hash matches correctly, but the stale size metadata indicates the manifest was not properly regenerated. Runnpm run generate:manifestto update both hash and size entries.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.aiox-core/install-manifest.yaml around lines 1 - 3, The manifest metadata for angular-nestjs.md has a stale file size; regenerate the install manifest by running the generate script so size and hash entries are recalculated: run the project script (npm run generate:manifest) to update the entry for angular-nestjs.md and commit the updated .aiox-core/install-manifest.yaml so the size (and hash if changed) match the actual file.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In @.aiox-core/data/entity-registry.yaml:
- Around line 14088-14110: The "angular-nestjs" registry entry is using hard
`dependencies` for scaffold modules (auth, user, jwt) which creates incorrect
graph edges; update the "angular-nestjs" entry to move those items from
`dependencies` into a `plannedDeps` list, remove them from `dependencies`, and
add the missing structural fields `externalDeps` and `lifecycle` consistent with
the `nextjs-react` preset pattern so the IDS loader treats them as planned
scaffold targets rather than concrete registry links.
In @.aiox-core/data/tech-presets/angular-nestjs.md:
- Around line 185-203: The code currently stores JWTs in localStorage within the
login/logout flows (see methods login, logout and the key 'access_token'), which
encourages an XSS-sensitive default; update the implementation to use a safer
default or clearly mark it as an example: either switch to setting an HttpOnly
cookie from the server (remove client-side localStorage.setItem/removeItem usage
and rely on cookie-based auth) or, if keeping a client-side token example,
replace direct localStorage usage with a clearly documented, opt-in alternative
(e.g., a TokenStorageService abstraction used by login/logout instead of
localStorage) and add a comment in login/logout explaining the security
trade-offs. Ensure references to 'access_token', login(), and logout() are
updated accordingly.
- Line 355: Several fenced code blocks in angular-nestjs.md (the tree and prompt
example blocks that are currently just ``` ) are missing language identifiers;
update each triple-backtick fence for the tree and prompt examples to use a
plain-text language tag (e.g., ```text or ```plaintext) so markdownlint MD040 is
satisfied—search for the untagged fences labeled as the "tree" output and the
"prompt" example blocks and replace the opening ``` with ```text (or
```plaintext) for each occurrence noted in the comment.
- Around line 271-279: In canActivate, guard against missing request.user before
accessing user.role: after retrieving requiredRoles and the request via
context.switchToHttp().getRequest(), check that request.user exists and return
false if it's absent; then perform the roles check with
requiredRoles.includes(user.role). This change in canActivate (the reflector
usage and the request = context.switchToHttp().getRequest() block) prevents a
thrown error when JwtAuthGuard wasn't applied.
- Around line 90-113: The AuthModule example uses ConfigService in
JwtModule.registerAsync but does not import or register ConfigModule; update the
AuthModule to import ConfigModule and reference ConfigService for DI: add
ConfigModule (e.g., ConfigModule.forRoot() or ConfigModule) to the Module
imports array and include ConfigService in the inject array already used by
JwtModule.registerAsync so JwtModule.registerAsync can resolve the ConfigService
dependency; ensure imports include ConfigModule and that AuthModule
providers/exports remain unchanged (AuthModule, JwtModule.registerAsync,
ConfigService, ConfigModule).
- Around line 236-239: The onSubmit example uses an unsafe cast "as any";
replace it with a concrete type (e.g., define an interface LoginDto or
LoginCredentials with the expected fields) and pass that type to auth.login (for
example: const payload = this.form.getRawValue() as LoginDto; await
this.auth.login(payload)); also update the exception filter snippet to avoid "as
any" by accepting unknown, narrowing it with a type guard or instanceof checks
and mapping to a known Error/HttpException type before accessing properties;
reference the onSubmit method and the exception filter code when making these
changes so copied snippets demonstrate proper typing instead of using any.
- Around line 42-73: The shared TypeScript interfaces LoginRequestDto,
LoginResponseDto and UserDto are erased at runtime and won't work with NestJS
ValidationPipe for `@Body`() parameters; update the doc to either (a) add backend
DTO classes (e.g., LoginRequestDtoClass) that implement/extend the shared
interfaces and include class-validator decorators like `@IsString/`@IsEmail so
controllers using ValidationPipe can validate requests, or (b) explicitly state
that the shown interfaces are type-only and must be paired with separate
decorated NestJS DTO classes used in controllers; reference LoginRequestDto,
LoginResponseDto, UserDto, ValidationPipe and `@Body`() so readers know where to
apply the fix.
---
Outside diff comments:
In @.aiox-core/install-manifest.yaml:
- Around line 1-3: The manifest metadata for angular-nestjs.md has a stale file
size; regenerate the install manifest by running the generate script so size and
hash entries are recalculated: run the project script (npm run
generate:manifest) to update the entry for angular-nestjs.md and commit the
updated .aiox-core/install-manifest.yaml so the size (and hash if changed) match
the actual file.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: c4801c36-0d98-4a8d-86b0-d1e8dd70fc6b
📒 Files selected for processing (4)
.aiox-core/data/entity-registry.yaml.aiox-core/data/tech-presets/angular-nestjs.md.aiox-core/install-manifest.yamlpackages/installer/src/wizard/questions.js
| angular-nestjs: | ||
| path: .aiox-core/data/tech-presets/angular-nestjs.md | ||
| layer: L3 | ||
| type: data | ||
| purpose: >- | ||
| 'Arquitetura otimizada para aplicações fullstack com Angular 21 (Signals, Standalone Components) no frontend e | ||
| NestJS (Modular, DI, Guards) no backend' | ||
| keywords: | ||
| - angular | ||
| - nestjs | ||
| - tech | ||
| - preset | ||
| usedBy: [] | ||
| dependencies: | ||
| - auth | ||
| - user | ||
| - jwt | ||
| adaptability: | ||
| score: 0.5 | ||
| constraints: [] | ||
| extensionPoints: [] | ||
| checksum: sha256:225db28dd5970a708e26dd02a88890f406d1780a013f986a0670b7c7731a1ebf | ||
| lastVerified: '2026-03-08T03:53:26.108Z' |
There was a problem hiding this comment.
Use plannedDeps here instead of hard registry dependencies.
auth, user, and jwt read like scaffolded app modules, not concrete registry entities. Unlike the sibling nextjs-react preset, this entry puts them in dependencies, and the IDS loader returns those values verbatim, so this will create misleading graph edges. It also leaves the preset structurally incomplete by omitting externalDeps and lifecycle.
Suggested fix
angular-nestjs:
path: .aiox-core/data/tech-presets/angular-nestjs.md
layer: L3
type: data
purpose: >-
'Arquitetura otimizada para aplicações fullstack com Angular 21 (Signals, Standalone Components) no frontend e
NestJS (Modular, DI, Guards) no backend'
keywords:
- angular
- nestjs
- tech
- preset
usedBy: []
- dependencies:
+ dependencies: []
+ externalDeps: []
+ plannedDeps:
- auth
- user
- jwt
+ lifecycle: experimental
adaptability:
score: 0.5
constraints: []
extensionPoints: []🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.aiox-core/data/entity-registry.yaml around lines 14088 - 14110, The
"angular-nestjs" registry entry is using hard `dependencies` for scaffold
modules (auth, user, jwt) which creates incorrect graph edges; update the
"angular-nestjs" entry to move those items from `dependencies` into a
`plannedDeps` list, remove them from `dependencies`, and add the missing
structural fields `externalDeps` and `lifecycle` consistent with the
`nextjs-react` preset pattern so the IDS loader treats them as planned scaffold
targets rather than concrete registry links.
| ```typescript | ||
| // backend/src/features/auth/auth.module.ts | ||
| import { Module } from '@nestjs/common'; | ||
| import { JwtModule } from '@nestjs/jwt'; | ||
| import { AuthController } from './auth.controller'; | ||
| import { AuthService } from './auth.service'; | ||
| import { UserRepository } from './repositories/user.repository'; | ||
| import { JwtStrategy } from './strategies/jwt.strategy'; | ||
|
|
||
| @Module({ | ||
| imports: [ | ||
| JwtModule.registerAsync({ | ||
| useFactory: (config: ConfigService) => ({ | ||
| secret: config.get('JWT_SECRET'), | ||
| signOptions: { expiresIn: '1h' }, | ||
| }), | ||
| inject: [ConfigService], | ||
| }), | ||
| ], | ||
| controllers: [AuthController], | ||
| providers: [AuthService, UserRepository, JwtStrategy], | ||
| exports: [AuthService], // Exporta apenas o que outros módulos precisam | ||
| }) | ||
| export class AuthModule {} |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
cat -n .aiox-core/data/tech-presets/angular-nestjs.md | head -120 | tail -35Repository: SynkraAI/aiox-core
Length of output: 1483
Add missing ConfigModule and ConfigService imports to the AuthModule example.
The example uses ConfigService on lines 102–106 without importing it or registering ConfigModule in the imports array. As written, dependency injection will fail at runtime.
Suggested fix
import { Module } from '@nestjs/common';
+import { ConfigModule, ConfigService } from '@nestjs/config';
import { JwtModule } from '@nestjs/jwt';
import { AuthController } from './auth.controller';
import { AuthService } from './auth.service';
import { UserRepository } from './repositories/user.repository';
import { JwtStrategy } from './strategies/jwt.strategy';
`@Module`({
imports: [
+ ConfigModule,
JwtModule.registerAsync({
useFactory: (config: ConfigService) => ({
secret: config.get('JWT_SECRET'),
signOptions: { expiresIn: '1h' },
}),
inject: [ConfigService],
}),
],🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.aiox-core/data/tech-presets/angular-nestjs.md around lines 90 - 113, The
AuthModule example uses ConfigService in JwtModule.registerAsync but does not
import or register ConfigModule; update the AuthModule to import ConfigModule
and reference ConfigService for DI: add ConfigModule (e.g.,
ConfigModule.forRoot() or ConfigModule) to the Module imports array and include
ConfigService in the inject array already used by JwtModule.registerAsync so
JwtModule.registerAsync can resolve the ConfigService dependency; ensure imports
include ConfigModule and that AuthModule providers/exports remain unchanged
(AuthModule, JwtModule.registerAsync, ConfigService, ConfigModule).
| async onSubmit(): Promise<void> { | ||
| if (this.form.invalid) return; | ||
| await this.auth.login(this.form.getRawValue() as any); | ||
| } |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
find . -name "angular-nestjs.md" -type f 2>/dev/null | head -20Repository: SynkraAI/aiox-core
Length of output: 110
🏁 Script executed:
wc -l ./.aiox-core/data/tech-presets/angular-nestjs.mdRepository: SynkraAI/aiox-core
Length of output: 114
🏁 Script executed:
sed -n '230,245p' ./.aiox-core/data/tech-presets/angular-nestjs.mdRepository: SynkraAI/aiox-core
Length of output: 447
🏁 Script executed:
sed -n '475,482p' ./.aiox-core/data/tech-presets/angular-nestjs.mdRepository: SynkraAI/aiox-core
Length of output: 546
🏁 Script executed:
sed -n '510,520p' ./.aiox-core/data/tech-presets/angular-nestjs.mdRepository: SynkraAI/aiox-core
Length of output: 438
Update code examples to comply with the preset's own No any rule.
Line 478 explicitly bans any in favor of unknown with type guards or explicit types, but the Angular submit flow (lines 236–239) and exception filter (lines 514–518) both use as any. Since these snippets are likely to be copied directly, they should demonstrate proper typing instead of the escape hatch they're meant to avoid.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.aiox-core/data/tech-presets/angular-nestjs.md around lines 236 - 239, The
onSubmit example uses an unsafe cast "as any"; replace it with a concrete type
(e.g., define an interface LoginDto or LoginCredentials with the expected
fields) and pass that type to auth.login (for example: const payload =
this.form.getRawValue() as LoginDto; await this.auth.login(payload)); also
update the exception filter snippet to avoid "as any" by accepting unknown,
narrowing it with a type guard or instanceof checks and mapping to a known
Error/HttpException type before accessing properties; reference the onSubmit
method and the exception filter code when making these changes so copied
snippets demonstrate proper typing instead of using any.
| canActivate(context: ExecutionContext): boolean { | ||
| const requiredRoles = this.reflector.getAllAndOverride<string[]>('roles', [ | ||
| context.getHandler(), | ||
| context.getClass(), | ||
| ]); | ||
| if (!requiredRoles) return true; | ||
|
|
||
| const { user } = context.switchToHttp().getRequest(); | ||
| return requiredRoles.includes(user.role); |
There was a problem hiding this comment.
Guard against a missing request.user before reading role.
If someone uses @Roles() without JwtAuthGuard on a route, user.role throws and turns an auth failure into a 500. Returning false when user is absent keeps the guard safe to reuse.
Suggested doc fix
canActivate(context: ExecutionContext): boolean {
const requiredRoles = this.reflector.getAllAndOverride<string[]>('roles', [
context.getHandler(),
context.getClass(),
]);
if (!requiredRoles) return true;
const { user } = context.switchToHttp().getRequest();
- return requiredRoles.includes(user.role);
+ return !!user && requiredRoles.includes(user.role);
}
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| canActivate(context: ExecutionContext): boolean { | |
| const requiredRoles = this.reflector.getAllAndOverride<string[]>('roles', [ | |
| context.getHandler(), | |
| context.getClass(), | |
| ]); | |
| if (!requiredRoles) return true; | |
| const { user } = context.switchToHttp().getRequest(); | |
| return requiredRoles.includes(user.role); | |
| canActivate(context: ExecutionContext): boolean { | |
| const requiredRoles = this.reflector.getAllAndOverride<string[]>('roles', [ | |
| context.getHandler(), | |
| context.getClass(), | |
| ]); | |
| if (!requiredRoles) return true; | |
| const { user } = context.switchToHttp().getRequest(); | |
| return !!user && requiredRoles.includes(user.role); | |
| } | |
| } |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.aiox-core/data/tech-presets/angular-nestjs.md around lines 271 - 279, In
canActivate, guard against missing request.user before accessing user.role:
after retrieving requiredRoles and the request via
context.switchToHttp().getRequest(), check that request.user exists and return
false if it's absent; then perform the roles check with
requiredRoles.includes(user.role). This change in canActivate (the reflector
usage and the request = context.switchToHttp().getRequest() block) prevents a
thrown error when JwtAuthGuard wasn't applied.
|
|
||
| ## Project Structure | ||
|
|
||
| ``` |
There was a problem hiding this comment.
Add language identifiers to the remaining fenced blocks.
markdownlint is already flagging these fences with MD040. Using text/plaintext for the tree and prompt examples will keep the preset lint-clean.
Also applies to: 544-544, 635-635, 655-655
🧰 Tools
🪛 markdownlint-cli2 (0.21.0)
[warning] 355-355: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In @.aiox-core/data/tech-presets/angular-nestjs.md at line 355, Several fenced
code blocks in angular-nestjs.md (the tree and prompt example blocks that are
currently just ``` ) are missing language identifiers; update each
triple-backtick fence for the tree and prompt examples to use a plain-text
language tag (e.g., ```text or ```plaintext) so markdownlint MD040 is
satisfied—search for the untagged fences labeled as the "tree" output and the
"prompt" example blocks and replace the opening ``` with ```text (or
```plaintext) for each occurrence noted in the comment.
|
Solid contribution, @Silvino-Miranda! Angular 21 + NestJS is a popular enterprise stack and this preset fills a real gap in the wizard options. Implementation quality: The preset file is thorough — 711 lines covering 5 design patterns, project structure, coding standards, and testing strategy. I like that you followed the existing Specific observations:
One suggestion: The preset metadata lists Another minor thing: The Clean PR overall — good to merge once the Zod/class-validator clarification is addressed. Well done! |
Pull Request
📋 Description
Add Angular 21 + NestJS as a new tech preset option in the AIOX installation wizard. This enables developers using Angular (Signals, Standalone Components) on the frontend and NestJS on the backend to get architecture patterns, project structure, coding standards, and testing strategies tailored to their stack.
🎯 AIOX Story Reference
Story ID: N/A (community contribution)
Story File: N/A
Sprint: N/A
Acceptance Criteria Addressed
New angular-nestjs option appears in the Tech Preset wizard question
Preset file follows the existing _template.md structure
Includes 5 design patterns, project structure, tech stack, coding standards, testing strategy
🔗 Related Issue
N/A
📦 Type of Change
🐛 Bug fix (non-breaking change which fixes an issue)
✨ New feature (non-breaking change which adds functionality)
💥 Breaking change (fix or feature that would cause existing functionality to not work as expected)
📚 Documentation update
🔧 Refactoring (no functional changes)
⚡ Performance improvement
🧪 Test update
🎯 Scope
Core framework (aiox-core/)
Squad (squads)
Tools (tools/)
Documentation (docs)
CI/CD (.github)
Other: ________________
📝 Changes Made
Added angular-nestjs choice to getTechPresetQuestion() in questions.js
Created angular-nestjs.md (22KB) with:
5 Design Patterns: Contract (Shared DTOs), NestJS Module, Angular Signals + Service, NestJS Guard + Decorator, Builder (Tests)
Project Structure: Monorepo layout with frontend/, backend/, shared/contracts/
Tech Stack: Angular 21, NestJS 11+, Prisma, class-validator, Angular Material, Jest, Playwright
Coding Standards: Standalone Components, Signals over BehaviorSubject, inject() over constructor DI, Guards for auth
Testing Strategy: NestJS TestingModule + Angular HttpClientTestingModule templates
Patterns to Avoid: NgModules, BehaviorSubject, logic in controllers, any types
🧪 Testing
All existing tests pass
Manual testing completed
Added tests for new functionality
Tested on multiple platforms (if applicable)
Test Results
📸 Screenshots (if applicable)
N/A — CLI wizard change (new list option added).
✅ Checklist⚠️ Skipped (missing @eslint/js dep in local env)
My code follows the project's style guidelines
I have performed a self-review of my code
I have commented my code, particularly in hard-to-understand areas
I have updated the documentation accordingly
My changes generate no new warnings
I have added tests that prove my fix is effective or that my feature works
New and existing unit tests pass locally with my changes
Any dependent changes have been merged and published
🔒 Security
I have reviewed my code for security vulnerabilities
I have not introduced any new security issues
I have checked for sensitive data exposure
🐰 CodeRabbit Review
No CRITICAL issues found
No HIGH severity issues blocking merge
All CodeRabbit suggestions addressed or documented
📊 Quality Gates
Check Status
Lint
TypeCheck ✅ Passed
Tests ✅ 24/27 passed (3 pre-existing failures)
Coverage ⏳ Pending
CodeRabbit ⏳ Pending
📖 Documentation
Updated README.md (if needed)
Updated CHANGELOG.md
Updated API documentation (if applicable)
Added code comments (if applicable)
👥 Reviewers
@SynkraAI
🚀 Deployment Notes
No migration needed. Non-breaking addition — new preset option is additive only.
Summary by CodeRabbit