@devstroupe/devkit-cli 1.0.0

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.
Files changed (170) hide show
  1. package/README.md +40 -0
  2. package/dist/boilerplates/angular-template/.dockerignore +4 -0
  3. package/dist/boilerplates/angular-template/.postcssrc.json +5 -0
  4. package/dist/boilerplates/angular-template/Dockerfile +14 -0
  5. package/dist/boilerplates/angular-template/angular.json +85 -0
  6. package/dist/boilerplates/angular-template/components.json +5 -0
  7. package/dist/boilerplates/angular-template/framework.code-workspace +7 -0
  8. package/dist/boilerplates/angular-template/nginx.conf +23 -0
  9. package/dist/boilerplates/angular-template/node_modules/.bin/browserslist +21 -0
  10. package/dist/boilerplates/angular-template/node_modules/.bin/jiti +21 -0
  11. package/dist/boilerplates/angular-template/node_modules/.bin/lessc +21 -0
  12. package/dist/boilerplates/angular-template/node_modules/.bin/ng +21 -0
  13. package/dist/boilerplates/angular-template/node_modules/.bin/ng-xi18n +21 -0
  14. package/dist/boilerplates/angular-template/node_modules/.bin/ngc +21 -0
  15. package/dist/boilerplates/angular-template/node_modules/.bin/sass +21 -0
  16. package/dist/boilerplates/angular-template/node_modules/.bin/terser +21 -0
  17. package/dist/boilerplates/angular-template/node_modules/.bin/tsc +21 -0
  18. package/dist/boilerplates/angular-template/node_modules/.bin/tsserver +21 -0
  19. package/dist/boilerplates/angular-template/node_modules/.bin/vite +21 -0
  20. package/dist/boilerplates/angular-template/node_modules/.bin/vitest +21 -0
  21. package/dist/boilerplates/angular-template/node_modules/.bin/yaml +21 -0
  22. package/dist/boilerplates/angular-template/package.json +47 -0
  23. package/dist/boilerplates/angular-template/postcss.config.js +5 -0
  24. package/dist/boilerplates/angular-template/proxy.conf.json +7 -0
  25. package/dist/boilerplates/angular-template/src/app/app.component.html +3 -0
  26. package/dist/boilerplates/angular-template/src/app/app.component.ts +12 -0
  27. package/dist/boilerplates/angular-template/src/app/app.config.ts +59 -0
  28. package/dist/boilerplates/angular-template/src/app/app.entity-routes.ts +4 -0
  29. package/dist/boilerplates/angular-template/src/app/app.routes.ts +25 -0
  30. package/dist/boilerplates/angular-template/src/app/core/guards/auth.guard.ts +16 -0
  31. package/dist/boilerplates/angular-template/src/app/core/services/auth.service.ts +98 -0
  32. package/dist/boilerplates/angular-template/src/app/modules/auth/login/login.component.html +51 -0
  33. package/dist/boilerplates/angular-template/src/app/modules/auth/login/login.component.ts +47 -0
  34. package/dist/boilerplates/angular-template/src/app/modules/auth/register/register.component.html +59 -0
  35. package/dist/boilerplates/angular-template/src/app/modules/auth/register/register.component.ts +47 -0
  36. package/dist/boilerplates/angular-template/src/app/modules/dashboard/dashboard.component.html +14 -0
  37. package/dist/boilerplates/angular-template/src/app/modules/dashboard/dashboard.component.ts +23 -0
  38. package/dist/boilerplates/angular-template/src/app/shared/interceptors/tenant.interceptor.ts +25 -0
  39. package/dist/boilerplates/angular-template/src/index.html +64 -0
  40. package/dist/boilerplates/angular-template/src/main.ts +6 -0
  41. package/dist/boilerplates/angular-template/src/styles.css +9 -0
  42. package/dist/boilerplates/angular-template/tsconfig.json +36 -0
  43. package/dist/boilerplates/nest-template/Dockerfile +16 -0
  44. package/dist/boilerplates/nest-template/node_modules/.bin/acorn +21 -0
  45. package/dist/boilerplates/nest-template/node_modules/.bin/nest +21 -0
  46. package/dist/boilerplates/nest-template/node_modules/.bin/prettier +21 -0
  47. package/dist/boilerplates/nest-template/node_modules/.bin/tsc +21 -0
  48. package/dist/boilerplates/nest-template/node_modules/.bin/tsserver +21 -0
  49. package/dist/boilerplates/nest-template/node_modules/.bin/typeorm +21 -0
  50. package/dist/boilerplates/nest-template/node_modules/.bin/typeorm-ts-node-commonjs +21 -0
  51. package/dist/boilerplates/nest-template/node_modules/.bin/typeorm-ts-node-esm +21 -0
  52. package/dist/boilerplates/nest-template/node_modules/.bin/webpack +21 -0
  53. package/dist/boilerplates/nest-template/package.json +43 -0
  54. package/dist/boilerplates/nest-template/src/app.module.ts +24 -0
  55. package/dist/boilerplates/nest-template/src/database/data-source.ts +16 -0
  56. package/dist/boilerplates/nest-template/src/database/migrations/1700000000000-create-users.ts +26 -0
  57. package/dist/boilerplates/nest-template/src/main.ts +46 -0
  58. package/dist/boilerplates/nest-template/src/modules/auth/auth.controller.ts +34 -0
  59. package/dist/boilerplates/nest-template/src/modules/auth/auth.module.ts +22 -0
  60. package/dist/boilerplates/nest-template/src/modules/auth/auth.service.ts +57 -0
  61. package/dist/boilerplates/nest-template/src/modules/auth/current-user.decorator.ts +8 -0
  62. package/dist/boilerplates/nest-template/src/modules/auth/jwt-auth.guard.ts +31 -0
  63. package/dist/boilerplates/nest-template/src/modules/auth/roles.decorator.ts +4 -0
  64. package/dist/boilerplates/nest-template/src/modules/auth/roles.guard.ts +24 -0
  65. package/dist/boilerplates/nest-template/src/modules/user/database-seed.service.ts +47 -0
  66. package/dist/boilerplates/nest-template/src/modules/user/domain/user.repository.ts +9 -0
  67. package/dist/boilerplates/nest-template/src/modules/user/domain/user.ts +9 -0
  68. package/dist/boilerplates/nest-template/src/modules/user/infra/database/user.orm-entity.ts +31 -0
  69. package/dist/boilerplates/nest-template/src/modules/user/infra/database/user.repository.adapter.ts +53 -0
  70. package/dist/boilerplates/nest-template/src/modules/user/service/user.service.ts +44 -0
  71. package/dist/boilerplates/nest-template/src/modules/user/user.module.ts +20 -0
  72. package/dist/boilerplates/nest-template/tsconfig.build.json +4 -0
  73. package/dist/boilerplates/nest-template/tsconfig.json +21 -0
  74. package/dist/index.d.ts +2 -0
  75. package/dist/index.js +1967 -0
  76. package/dist/migrations/sort-entities.d.ts +2 -0
  77. package/dist/migrations/sort-entities.js +30 -0
  78. package/dist/rules/linter-rules.d.ts +12 -0
  79. package/dist/rules/linter-rules.js +338 -0
  80. package/dist/rules/linter-rules.test.d.ts +1 -0
  81. package/dist/rules/linter-rules.test.js +214 -0
  82. package/dist/templates/angular/dialog-handler.template.d.ts +2 -0
  83. package/dist/templates/angular/dialog-handler.template.js +49 -0
  84. package/dist/templates/angular/form.template.d.ts +3 -0
  85. package/dist/templates/angular/form.template.js +453 -0
  86. package/dist/templates/angular/index.d.ts +4 -0
  87. package/dist/templates/angular/index.js +20 -0
  88. package/dist/templates/angular/list.template.d.ts +3 -0
  89. package/dist/templates/angular/list.template.js +213 -0
  90. package/dist/templates/angular/service.template.d.ts +1 -0
  91. package/dist/templates/angular/service.template.js +20 -0
  92. package/dist/templates/cli-templates.d.ts +2 -0
  93. package/dist/templates/cli-templates.js +18 -0
  94. package/dist/templates/nest/crud.templates.d.ts +9 -0
  95. package/dist/templates/nest/crud.templates.js +362 -0
  96. package/dist/templates/nest/index.d.ts +3 -0
  97. package/dist/templates/nest/index.js +19 -0
  98. package/dist/templates/nest/microservice.templates.d.ts +4 -0
  99. package/dist/templates/nest/microservice.templates.js +157 -0
  100. package/dist/templates/nest/migration.template.d.ts +3 -0
  101. package/dist/templates/nest/migration.template.js +127 -0
  102. package/dist/templates/relationship-templates.test.d.ts +1 -0
  103. package/dist/templates/relationship-templates.test.js +181 -0
  104. package/dist/templates/shared/names.d.ts +3 -0
  105. package/dist/templates/shared/names.js +14 -0
  106. package/dist/templates/shared/relationships.d.ts +27 -0
  107. package/dist/templates/shared/relationships.js +96 -0
  108. package/dist/templates/ui/components/avatar.template.d.ts +3 -0
  109. package/dist/templates/ui/components/avatar.template.js +66 -0
  110. package/dist/templates/ui/components/badge.template.d.ts +3 -0
  111. package/dist/templates/ui/components/badge.template.js +27 -0
  112. package/dist/templates/ui/components/button.template.d.ts +5 -0
  113. package/dist/templates/ui/components/button.template.js +64 -0
  114. package/dist/templates/ui/components/card-list.template.d.ts +5 -0
  115. package/dist/templates/ui/components/card-list.template.js +79 -0
  116. package/dist/templates/ui/components/dialog.template.d.ts +5 -0
  117. package/dist/templates/ui/components/dialog.template.js +51 -0
  118. package/dist/templates/ui/components/filter.template.d.ts +4 -0
  119. package/dist/templates/ui/components/filter.template.js +218 -0
  120. package/dist/templates/ui/components/index.d.ts +10 -0
  121. package/dist/templates/ui/components/index.js +26 -0
  122. package/dist/templates/ui/components/input.template.d.ts +4 -0
  123. package/dist/templates/ui/components/input.template.js +76 -0
  124. package/dist/templates/ui/components/select.template.d.ts +4 -0
  125. package/dist/templates/ui/components/select.template.js +176 -0
  126. package/dist/templates/ui/components/simple-list.template.d.ts +5 -0
  127. package/dist/templates/ui/components/simple-list.template.js +89 -0
  128. package/dist/templates/ui/components/table.template.d.ts +5 -0
  129. package/dist/templates/ui/components/table.template.js +112 -0
  130. package/dist/templates/ui/index.d.ts +9 -0
  131. package/dist/templates/ui/index.js +25 -0
  132. package/dist/templates/ui/layout/header.template.d.ts +5 -0
  133. package/dist/templates/ui/layout/header.template.js +236 -0
  134. package/dist/templates/ui/layout/index.d.ts +4 -0
  135. package/dist/templates/ui/layout/index.js +20 -0
  136. package/dist/templates/ui/layout/main-layout.template.d.ts +5 -0
  137. package/dist/templates/ui/layout/main-layout.template.js +126 -0
  138. package/dist/templates/ui/layout/shell.template.d.ts +5 -0
  139. package/dist/templates/ui/layout/shell.template.js +76 -0
  140. package/dist/templates/ui/layout/sidebar.template.d.ts +5 -0
  141. package/dist/templates/ui/layout/sidebar.template.js +412 -0
  142. package/dist/templates/ui/playground.template.d.ts +5 -0
  143. package/dist/templates/ui/playground.template.js +570 -0
  144. package/dist/templates/ui/readme.template.d.ts +1 -0
  145. package/dist/templates/ui/readme.template.js +23 -0
  146. package/dist/templates/ui/shared/colors.d.ts +1 -0
  147. package/dist/templates/ui/shared/colors.js +31 -0
  148. package/dist/templates/ui/shared/profile-component.template.d.ts +5 -0
  149. package/dist/templates/ui/shared/profile-component.template.js +403 -0
  150. package/dist/templates/ui/shared/profile-service.template.d.ts +1 -0
  151. package/dist/templates/ui/shared/profile-service.template.js +44 -0
  152. package/dist/templates/ui/shared/theme-service.template.d.ts +1 -0
  153. package/dist/templates/ui/shared/theme-service.template.js +47 -0
  154. package/dist/templates/ui/spartan/badge-directive.template.d.ts +3 -0
  155. package/dist/templates/ui/spartan/badge-directive.template.js +50 -0
  156. package/dist/templates/ui/spartan/button-directive.template.d.ts +3 -0
  157. package/dist/templates/ui/spartan/button-directive.template.js +82 -0
  158. package/dist/templates/ui/spartan/button-token.template.d.ts +3 -0
  159. package/dist/templates/ui/spartan/button-token.template.js +31 -0
  160. package/dist/templates/ui/spartan/hlm-core.template.d.ts +3 -0
  161. package/dist/templates/ui/spartan/hlm-core.template.js +322 -0
  162. package/dist/templates/ui/spartan/index.d.ts +5 -0
  163. package/dist/templates/ui/spartan/index.js +21 -0
  164. package/dist/templates/ui/spartan/input-directive.template.d.ts +3 -0
  165. package/dist/templates/ui/spartan/input-directive.template.js +31 -0
  166. package/dist/templates/ui/theme-css.template.d.ts +7 -0
  167. package/dist/templates/ui/theme-css.template.js +210 -0
  168. package/dist/templates/ui-templates.d.ts +1 -0
  169. package/dist/templates/ui-templates.js +17 -0
  170. package/package.json +50 -0
@@ -0,0 +1,25 @@
1
+ import { Routes } from '@angular/router';
2
+ import { authGuard } from './core/guards/auth.guard';
3
+ import { LoginComponent } from './modules/auth/login/login.component';
4
+ import { RegisterComponent } from './modules/auth/register/register.component';
5
+ import { DashboardComponent } from './modules/dashboard/dashboard.component';
6
+ import { MainLayoutComponent } from './shared/layouts/main-layout/main-layout.component';
7
+ import { ENTITY_ROUTES } from './app.entity-routes';
8
+
9
+ export const routes: Routes = [
10
+ { path: 'login', component: LoginComponent },
11
+ { path: 'register', component: RegisterComponent },
12
+ {
13
+ path: '',
14
+ component: MainLayoutComponent,
15
+ canActivate: [authGuard],
16
+ children: [
17
+ { path: '', component: DashboardComponent },
18
+ { path: 'dashboard', component: DashboardComponent },
19
+ { path: 'profile', loadComponent: () => import('./modules/profile/profile.component').then(m => m.ProfileComponent) },
20
+ { path: 'playground', loadComponent: () => import('./modules/playground/playground.component').then(m => m.PlaygroundComponent) },
21
+ ...ENTITY_ROUTES
22
+ ]
23
+ },
24
+ { path: '**', redirectTo: '' }
25
+ ];
@@ -0,0 +1,16 @@
1
+ import { inject } from '@angular/core';
2
+ import { CanActivateFn, Router } from '@angular/router';
3
+ import { AuthService } from '../services/auth.service';
4
+
5
+ export const authGuard: CanActivateFn = (route, state) => {
6
+ const authService = inject(AuthService);
7
+ const router = inject(Router);
8
+
9
+ if (authService.isAuthenticated) {
10
+ return true;
11
+ }
12
+
13
+ // Redireciona para o login se não estiver autenticado
14
+ router.navigate(['/login']);
15
+ return false;
16
+ };
@@ -0,0 +1,98 @@
1
+ import { Injectable, inject } from '@angular/core';
2
+ import { HttpClient } from '@angular/common/http';
3
+ import { BehaviorSubject, Observable, tap } from 'rxjs';
4
+
5
+ export interface User {
6
+ id: number;
7
+ name: string;
8
+ email: string;
9
+ role: 'ADMIN' | 'USER';
10
+ avatar?: string;
11
+ tenantId?: string;
12
+ isActive: boolean;
13
+ }
14
+
15
+ export interface AuthResponse {
16
+ accessToken: string;
17
+ user: User;
18
+ }
19
+
20
+ @Injectable({
21
+ providedIn: 'root',
22
+ })
23
+ export class AuthService {
24
+ private http = inject(HttpClient);
25
+ private apiUrl = '/api/auth';
26
+
27
+ private currentUserSubject = new BehaviorSubject<User | null>(null);
28
+ public currentUser$ = this.currentUserSubject.asObservable();
29
+
30
+ constructor() {
31
+ this.loadSession();
32
+ }
33
+
34
+ get currentUser(): User | null {
35
+ return this.currentUserSubject.getValue();
36
+ }
37
+
38
+ setCurrentUser(user: User): void {
39
+ this.currentUserSubject.next(user);
40
+ }
41
+
42
+ private loadSession(): void {
43
+ const userJson = localStorage.getItem('user');
44
+ const token = localStorage.getItem('token');
45
+ if (userJson && token) {
46
+ try {
47
+ const user = JSON.parse(userJson);
48
+ this.currentUserSubject.next(user);
49
+ // Atualiza o tenantId no localStorage para o tenantInterceptor ler
50
+ if (user.tenantId) {
51
+ localStorage.setItem('tenantId', user.tenantId);
52
+ }
53
+ } catch {
54
+ this.clearSession();
55
+ }
56
+ }
57
+ }
58
+
59
+ login(credentials: { email: string; password: string }): Observable<AuthResponse> {
60
+ return this.http.post<AuthResponse>(`${this.apiUrl}/login`, credentials).pipe(
61
+ tap((res) => this.setSession(res))
62
+ );
63
+ }
64
+
65
+ register(userData: any): Observable<any> {
66
+ return this.http.post<any>(`${this.apiUrl}/register`, userData);
67
+ }
68
+
69
+ logout(): void {
70
+ this.clearSession();
71
+ }
72
+
73
+ private setSession(authResult: AuthResponse): void {
74
+ localStorage.setItem('token', authResult.accessToken);
75
+ localStorage.setItem('user', JSON.stringify(authResult.user));
76
+ if (authResult.user.tenantId) {
77
+ localStorage.setItem('tenantId', authResult.user.tenantId);
78
+ } else {
79
+ localStorage.removeItem('tenantId');
80
+ }
81
+ this.currentUserSubject.next(authResult.user);
82
+ }
83
+
84
+ private clearSession(): void {
85
+ localStorage.removeItem('token');
86
+ localStorage.removeItem('user');
87
+ localStorage.removeItem('tenantId');
88
+ this.currentUserSubject.next(null);
89
+ }
90
+
91
+ get token(): string | null {
92
+ return localStorage.getItem('token');
93
+ }
94
+
95
+ get isAuthenticated(): boolean {
96
+ return !!this.token;
97
+ }
98
+ }
@@ -0,0 +1,51 @@
1
+ <div class="min-h-screen bg-background text-foreground px-4 py-12 sm:px-6 lg:px-8">
2
+ <div class="mx-auto flex min-h-[calc(100vh-6rem)] w-full max-w-md items-center">
3
+ <div class="w-full rounded-xl border border-border bg-card p-8 text-card-foreground">
4
+ <div class="space-y-2 text-center">
5
+ <h1 class="text-3xl font-bold tracking-tight text-foreground">
6
+ DT-DevKit
7
+ </h1>
8
+ <p class="text-sm text-muted-foreground">
9
+ Entre na sua conta para continuar
10
+ </p>
11
+ </div>
12
+
13
+ <form class="mt-8 space-y-6" [formGroup]="form" (ngSubmit)="onSubmit()">
14
+ <div class="space-y-4">
15
+ <devkit-input
16
+ formControlName="email"
17
+ label="Endereço de E-mail"
18
+ placeholder="exemplo@email.com"
19
+ type="email"
20
+ [required]="true">
21
+ </devkit-input>
22
+
23
+ <devkit-input
24
+ formControlName="password"
25
+ label="Senha"
26
+ placeholder="Digite sua senha"
27
+ type="password"
28
+ [required]="true">
29
+ </devkit-input>
30
+ </div>
31
+
32
+ <div *ngIf="errorMessage" class="rounded-lg border border-destructive/30 bg-destructive/10 p-3 text-center text-sm font-medium text-destructive">
33
+ {{ errorMessage }}
34
+ </div>
35
+
36
+ <devkit-button type="submit" [disabled]="form.invalid || loading" [loading]="loading" [fullWidth]="true">
37
+ Entrar
38
+ </devkit-button>
39
+ </form>
40
+
41
+ <div class="mt-6 text-center">
42
+ <p class="text-sm text-muted-foreground">
43
+ Não tem uma conta?
44
+ <a routerLink="/register" class="font-medium text-primary underline-offset-4 hover:underline">
45
+ Cadastre-se grátis
46
+ </a>
47
+ </p>
48
+ </div>
49
+ </div>
50
+ </div>
51
+ </div>
@@ -0,0 +1,47 @@
1
+ import { ChangeDetectorRef, Component, inject } from '@angular/core';
2
+ import { CommonModule } from '@angular/common';
3
+ import { FormBuilder, FormGroup, Validators, ReactiveFormsModule } from '@angular/forms';
4
+ import { Router, RouterModule } from '@angular/router';
5
+ import { AuthService } from '../../../core/services/auth.service';
6
+ import { DevkitInputComponent } from '@devstroupe/ui/input/input.component';
7
+ import { DevkitButtonComponent } from '@devstroupe/ui/button/button.component';
8
+
9
+ @Component({
10
+ selector: 'app-login',
11
+ standalone: true,
12
+ imports: [CommonModule, ReactiveFormsModule, DevkitInputComponent, DevkitButtonComponent, RouterModule],
13
+ templateUrl: './login.component.html',
14
+ })
15
+ export class LoginComponent {
16
+ private fb = inject(FormBuilder);
17
+ private authService = inject(AuthService);
18
+ private router = inject(Router);
19
+ private changeDetector = inject(ChangeDetectorRef);
20
+
21
+ form: FormGroup = this.fb.group({
22
+ email: ['', [Validators.required, Validators.email]],
23
+ password: ['', [Validators.required, Validators.minLength(6)]],
24
+ });
25
+
26
+ errorMessage = '';
27
+ loading = false;
28
+
29
+ onSubmit(): void {
30
+ if (this.form.invalid) return;
31
+
32
+ this.loading = true;
33
+ this.errorMessage = '';
34
+
35
+ this.authService.login(this.form.value).subscribe({
36
+ next: () => {
37
+ this.loading = false;
38
+ this.changeDetector.markForCheck();
39
+ this.router.navigate(['/']);
40
+ },
41
+ error: (err) => {
42
+ this.loading = false;
43
+ this.errorMessage = err.error?.message || 'Erro ao tentar fazer login. Tente novamente.';
44
+ },
45
+ });
46
+ }
47
+ }
@@ -0,0 +1,59 @@
1
+ <div class="min-h-screen bg-background text-foreground px-4 py-12 sm:px-6 lg:px-8">
2
+ <div class="mx-auto flex min-h-[calc(100vh-6rem)] w-full max-w-md items-center">
3
+ <div class="w-full rounded-xl border border-border bg-card p-8 text-card-foreground">
4
+ <div class="space-y-2 text-center">
5
+ <h1 class="text-3xl font-bold tracking-tight text-foreground">
6
+ Crie sua conta
7
+ </h1>
8
+ <p class="text-sm text-muted-foreground">
9
+ Cadastre-se para começar a usar o DT-DevKit
10
+ </p>
11
+ </div>
12
+
13
+ <form class="mt-8 space-y-6" [formGroup]="form" (ngSubmit)="onSubmit()">
14
+ <div class="space-y-4">
15
+ <devkit-input
16
+ formControlName="name"
17
+ label="Nome Completo"
18
+ placeholder="Digite seu nome"
19
+ type="text"
20
+ [required]="true">
21
+ </devkit-input>
22
+
23
+ <devkit-input
24
+ formControlName="email"
25
+ label="Endereço de E-mail"
26
+ placeholder="exemplo@email.com"
27
+ type="email"
28
+ [required]="true">
29
+ </devkit-input>
30
+
31
+ <devkit-input
32
+ formControlName="password"
33
+ label="Senha (mínimo 6 caracteres)"
34
+ placeholder="Crie uma senha forte"
35
+ type="password"
36
+ [required]="true">
37
+ </devkit-input>
38
+ </div>
39
+
40
+ <div *ngIf="errorMessage" class="rounded-lg border border-destructive/30 bg-destructive/10 p-3 text-center text-sm font-medium text-destructive">
41
+ {{ errorMessage }}
42
+ </div>
43
+
44
+ <devkit-button type="submit" [disabled]="form.invalid || loading" [loading]="loading" [fullWidth]="true">
45
+ Cadastrar
46
+ </devkit-button>
47
+ </form>
48
+
49
+ <div class="mt-6 text-center">
50
+ <p class="text-sm text-muted-foreground">
51
+ Já tem uma conta?
52
+ <a routerLink="/login" class="font-medium text-primary underline-offset-4 hover:underline">
53
+ Faça login
54
+ </a>
55
+ </p>
56
+ </div>
57
+ </div>
58
+ </div>
59
+ </div>
@@ -0,0 +1,47 @@
1
+ import { Component, inject } from '@angular/core';
2
+ import { CommonModule } from '@angular/common';
3
+ import { FormBuilder, FormGroup, Validators, ReactiveFormsModule } from '@angular/forms';
4
+ import { Router, RouterModule } from '@angular/router';
5
+ import { AuthService } from '../../../core/services/auth.service';
6
+ import { DevkitInputComponent } from '@devstroupe/ui/input/input.component';
7
+ import { DevkitButtonComponent } from '@devstroupe/ui/button/button.component';
8
+
9
+ @Component({
10
+ selector: 'app-register',
11
+ standalone: true,
12
+ imports: [CommonModule, ReactiveFormsModule, DevkitInputComponent, DevkitButtonComponent, RouterModule],
13
+ templateUrl: './register.component.html',
14
+ })
15
+ export class RegisterComponent {
16
+ private fb = inject(FormBuilder);
17
+ private authService = inject(AuthService);
18
+ private router = inject(Router);
19
+
20
+ form: FormGroup = this.fb.group({
21
+ name: ['', [Validators.required, Validators.minLength(2)]],
22
+ email: ['', [Validators.required, Validators.email]],
23
+ password: ['', [Validators.required, Validators.minLength(6)]],
24
+ });
25
+
26
+ errorMessage = '';
27
+ loading = false;
28
+
29
+ onSubmit(): void {
30
+ if (this.form.invalid) return;
31
+
32
+ this.loading = true;
33
+ this.errorMessage = '';
34
+
35
+ this.authService.register(this.form.value).subscribe({
36
+ next: () => {
37
+ // Redireciona para o login após cadastro com sucesso
38
+ alert('Cadastro realizado com sucesso! Faça login para continuar.');
39
+ this.router.navigate(['/login']);
40
+ },
41
+ error: (err) => {
42
+ this.loading = false;
43
+ this.errorMessage = err.error?.message || 'Erro ao realizar cadastro. Tente novamente.';
44
+ },
45
+ });
46
+ }
47
+ }
@@ -0,0 +1,14 @@
1
+ <div class="space-y-8 text-foreground" *ngIf="currentUser$ | async as user">
2
+ <section class="rounded-xl border border-border bg-card p-8 text-card-foreground">
3
+ <div class="flex flex-col gap-6 md:flex-row md:items-center md:justify-between">
4
+ <div class="space-y-2">
5
+ <p class="text-sm font-medium text-muted-foreground">Dashboard</p>
6
+ <h1 class="text-3xl font-bold tracking-tight text-foreground">Bem-vindo de volta, {{ user.name }}!</h1>
7
+ <p class="max-w-2xl text-sm text-muted-foreground">
8
+ Você está autenticado com sucesso e conectado ao ecossistema do seu projeto.
9
+ </p>
10
+ </div>
11
+ <devkit-button variant="outline" (btnClick)="logout()">Sair</devkit-button>
12
+ </div>
13
+ </section>
14
+ </div>
@@ -0,0 +1,23 @@
1
+ import { Component, inject } from '@angular/core';
2
+ import { CommonModule } from '@angular/common';
3
+ import { Router } from '@angular/router';
4
+ import { AuthService } from '../../core/services/auth.service';
5
+ import { DevkitButtonComponent } from '@devstroupe/ui/button/button.component';
6
+
7
+ @Component({
8
+ selector: 'app-dashboard',
9
+ standalone: true,
10
+ imports: [CommonModule, DevkitButtonComponent],
11
+ templateUrl: './dashboard.component.html'
12
+ })
13
+ export class DashboardComponent {
14
+ authService = inject(AuthService);
15
+ private router = inject(Router);
16
+
17
+ currentUser$ = this.authService.currentUser$;
18
+
19
+ logout(): void {
20
+ this.authService.logout();
21
+ this.router.navigate(['/login']);
22
+ }
23
+ }
@@ -0,0 +1,25 @@
1
+ import { HttpInterceptorFn } from '@angular/common/http';
2
+
3
+ export const tenantInterceptor: HttpInterceptorFn = (req, next) => {
4
+ const tenantId = localStorage.getItem('tenantId');
5
+ const token = localStorage.getItem('token');
6
+
7
+ let headers: Record<string, string> = {};
8
+
9
+ if (tenantId) {
10
+ headers['x-tenant-id'] = tenantId;
11
+ }
12
+
13
+ if (token) {
14
+ headers['Authorization'] = `Bearer ${token}`;
15
+ }
16
+
17
+ if (Object.keys(headers).length > 0) {
18
+ const cloned = req.clone({
19
+ setHeaders: headers
20
+ });
21
+ return next(cloned);
22
+ }
23
+
24
+ return next(req);
25
+ };
@@ -0,0 +1,64 @@
1
+ <!doctype html>
2
+ <html lang="pt-BR">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <title>DevsTroupe App</title>
6
+ <base href="/">
7
+ <meta name="viewport" content="width=device-width, initial-scale=1">
8
+ <link rel="icon" type="image/x-icon" href="favicon.ico">
9
+ </head>
10
+ <body>
11
+ <app-root>
12
+ <div style="
13
+ position: fixed;
14
+ top: 0;
15
+ left: 0;
16
+ width: 100vw;
17
+ height: 100vh;
18
+ display: flex;
19
+ flex-direction: column;
20
+ align-items: center;
21
+ justify-content: center;
22
+ background-color: #09090b;
23
+ color: #fafafa;
24
+ font-family: system-ui, -apple-system, sans-serif;
25
+ z-index: 9999;
26
+ ">
27
+ <div style="margin-bottom: 24px; position: relative;">
28
+ <!-- Pulsing logo outer ring -->
29
+ <div style="
30
+ width: 64px;
31
+ height: 64px;
32
+ border-radius: 50%;
33
+ border: 2px solid #7136ff;
34
+ border-top-color: transparent;
35
+ animation: spin 1s linear infinite;
36
+ "></div>
37
+ <!-- Inner pulsing dot -->
38
+ <div style="
39
+ position: absolute;
40
+ top: 50%;
41
+ left: 50%;
42
+ transform: translate(-50%, -50%);
43
+ width: 16px;
44
+ height: 16px;
45
+ border-radius: 50%;
46
+ background-color: #ff6633;
47
+ animation: pulse 1.5s ease-in-out infinite;
48
+ "></div>
49
+ </div>
50
+ <h1 style="font-size: 20px; font-weight: 700; letter-spacing: -0.025em; margin: 0; color: #ffffff;">DevsTroupe</h1>
51
+ <p style="font-size: 13px; color: #a1a1aa; margin-top: 8px; font-weight: 400;">Inicializando ambiente...</p>
52
+ </div>
53
+ <style>
54
+ @keyframes spin {
55
+ to { transform: rotate(360deg); }
56
+ }
57
+ @keyframes pulse {
58
+ 0%, 100% { transform: translate(-50%, -50%) scale(0.85); opacity: 0.5; }
59
+ 50% { transform: translate(-50%, -50%) scale(1.15); opacity: 1; }
60
+ }
61
+ </style>
62
+ </app-root>
63
+ </body>
64
+ </html>
@@ -0,0 +1,6 @@
1
+ import { bootstrapApplication } from '@angular/platform-browser';
2
+ import { appConfig } from './app/app.config';
3
+ import { AppComponent } from './app/app.component';
4
+
5
+ bootstrapApplication(AppComponent, appConfig)
6
+ .catch((err) => console.error(err));
@@ -0,0 +1,9 @@
1
+ @import 'tailwindcss';
2
+ @import '@spartan-ng/brain/hlm-tailwind-preset.css';
3
+ @import '@angular/cdk/overlay-prebuilt.css';
4
+
5
+ @source './app';
6
+ @source '../libs/ui';
7
+
8
+ /* O tema do DevKit é importado automaticamente após rodar: devstroupe init-ui */
9
+ /* @import "./app/shared/components/devkit/devkit.css"; */
@@ -0,0 +1,36 @@
1
+ {
2
+ "compileOnSave": false,
3
+ "compilerOptions": {
4
+ "outDir": "./dist/out-tsc",
5
+ "forceConsistentCasingInFileNames": true,
6
+ "strict": true,
7
+ "skipLibCheck": true,
8
+ "noImplicitOverride": true,
9
+ "noPropertyAccessFromIndexSignature": true,
10
+ "noImplicitReturns": true,
11
+ "noFallthroughCasesInSwitch": true,
12
+ "sourceMap": true,
13
+ "declaration": false,
14
+ "experimentalDecorators": true,
15
+ "moduleResolution": "bundler",
16
+ "importHelpers": true,
17
+ "target": "ES2022",
18
+ "module": "ES2022",
19
+ "useDefineForClassFields": false,
20
+ "lib": [
21
+ "ES2022",
22
+ "dom"
23
+ ],
24
+ "baseUrl": "./",
25
+ "paths": {
26
+ "@devstroupe/ui/*": [
27
+ "src/app/shared/components/devkit/*"
28
+ ]
29
+ }
30
+ },
31
+ "angularCompilerOptions": {
32
+ "enableI18nLegacyMessageIdFormat": false,
33
+ "strictTemplates": true,
34
+ "strictInjectionParameters": true
35
+ }
36
+ }
@@ -0,0 +1,16 @@
1
+ # Stage 1: Build
2
+ FROM node:20-alpine AS builder
3
+ WORKDIR /app
4
+ COPY package*.json ./
5
+ RUN npm install
6
+ COPY . .
7
+ RUN npm run build
8
+
9
+ # Stage 2: Run
10
+ FROM node:20-alpine AS runner
11
+ WORKDIR /app
12
+ COPY package*.json ./
13
+ RUN npm install --only=production
14
+ COPY --from=builder /app/dist ./dist
15
+ EXPOSE 13000
16
+ CMD ["node", "dist/main.js"]
@@ -0,0 +1,21 @@
1
+ #!/bin/sh
2
+ basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
3
+
4
+ case `uname` in
5
+ *CYGWIN*|*MINGW*|*MSYS*)
6
+ if command -v cygpath > /dev/null 2>&1; then
7
+ basedir=`cygpath -w "$basedir"`
8
+ fi
9
+ ;;
10
+ esac
11
+
12
+ if [ -z "$NODE_PATH" ]; then
13
+ export NODE_PATH="/home/vitor/trabalho/devstroupe/framework/node_modules/.pnpm/acorn@8.17.0/node_modules/acorn/node_modules:/home/vitor/trabalho/devstroupe/framework/node_modules/.pnpm/acorn@8.17.0/node_modules:/home/vitor/trabalho/devstroupe/framework/node_modules/.pnpm/node_modules"
14
+ else
15
+ export NODE_PATH="/home/vitor/trabalho/devstroupe/framework/node_modules/.pnpm/acorn@8.17.0/node_modules/acorn/node_modules:/home/vitor/trabalho/devstroupe/framework/node_modules/.pnpm/acorn@8.17.0/node_modules:/home/vitor/trabalho/devstroupe/framework/node_modules/.pnpm/node_modules:$NODE_PATH"
16
+ fi
17
+ if [ -x "$basedir/node" ]; then
18
+ exec "$basedir/node" "$basedir/../../../../node_modules/.pnpm/acorn@8.17.0/node_modules/acorn/bin/acorn" "$@"
19
+ else
20
+ exec node "$basedir/../../../../node_modules/.pnpm/acorn@8.17.0/node_modules/acorn/bin/acorn" "$@"
21
+ fi
@@ -0,0 +1,21 @@
1
+ #!/bin/sh
2
+ basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
3
+
4
+ case `uname` in
5
+ *CYGWIN*|*MINGW*|*MSYS*)
6
+ if command -v cygpath > /dev/null 2>&1; then
7
+ basedir=`cygpath -w "$basedir"`
8
+ fi
9
+ ;;
10
+ esac
11
+
12
+ if [ -z "$NODE_PATH" ]; then
13
+ export NODE_PATH="/home/vitor/trabalho/devstroupe/framework/node_modules/.pnpm/@nestjs+cli@11.0.23_@types+node@20.19.43_prettier@3.9.4/node_modules/@nestjs/cli/node_modules:/home/vitor/trabalho/devstroupe/framework/node_modules/.pnpm/@nestjs+cli@11.0.23_@types+node@20.19.43_prettier@3.9.4/node_modules:/home/vitor/trabalho/devstroupe/framework/node_modules/.pnpm/node_modules"
14
+ else
15
+ export NODE_PATH="/home/vitor/trabalho/devstroupe/framework/node_modules/.pnpm/@nestjs+cli@11.0.23_@types+node@20.19.43_prettier@3.9.4/node_modules/@nestjs/cli/node_modules:/home/vitor/trabalho/devstroupe/framework/node_modules/.pnpm/@nestjs+cli@11.0.23_@types+node@20.19.43_prettier@3.9.4/node_modules:/home/vitor/trabalho/devstroupe/framework/node_modules/.pnpm/node_modules:$NODE_PATH"
16
+ fi
17
+ if [ -x "$basedir/node" ]; then
18
+ exec "$basedir/node" "$basedir/../@nestjs/cli/bin/nest.js" "$@"
19
+ else
20
+ exec node "$basedir/../@nestjs/cli/bin/nest.js" "$@"
21
+ fi
@@ -0,0 +1,21 @@
1
+ #!/bin/sh
2
+ basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
3
+
4
+ case `uname` in
5
+ *CYGWIN*|*MINGW*|*MSYS*)
6
+ if command -v cygpath > /dev/null 2>&1; then
7
+ basedir=`cygpath -w "$basedir"`
8
+ fi
9
+ ;;
10
+ esac
11
+
12
+ if [ -z "$NODE_PATH" ]; then
13
+ export NODE_PATH="/home/vitor/trabalho/devstroupe/framework/node_modules/.pnpm/prettier@3.9.4/node_modules/prettier/node_modules:/home/vitor/trabalho/devstroupe/framework/node_modules/.pnpm/prettier@3.9.4/node_modules:/home/vitor/trabalho/devstroupe/framework/node_modules/.pnpm/node_modules"
14
+ else
15
+ export NODE_PATH="/home/vitor/trabalho/devstroupe/framework/node_modules/.pnpm/prettier@3.9.4/node_modules/prettier/node_modules:/home/vitor/trabalho/devstroupe/framework/node_modules/.pnpm/prettier@3.9.4/node_modules:/home/vitor/trabalho/devstroupe/framework/node_modules/.pnpm/node_modules:$NODE_PATH"
16
+ fi
17
+ if [ -x "$basedir/node" ]; then
18
+ exec "$basedir/node" "$basedir/../../../../node_modules/.pnpm/prettier@3.9.4/node_modules/prettier/bin/prettier.cjs" "$@"
19
+ else
20
+ exec node "$basedir/../../../../node_modules/.pnpm/prettier@3.9.4/node_modules/prettier/bin/prettier.cjs" "$@"
21
+ fi
@@ -0,0 +1,21 @@
1
+ #!/bin/sh
2
+ basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
3
+
4
+ case `uname` in
5
+ *CYGWIN*|*MINGW*|*MSYS*)
6
+ if command -v cygpath > /dev/null 2>&1; then
7
+ basedir=`cygpath -w "$basedir"`
8
+ fi
9
+ ;;
10
+ esac
11
+
12
+ if [ -z "$NODE_PATH" ]; then
13
+ export NODE_PATH="/home/vitor/trabalho/devstroupe/framework/node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/node_modules:/home/vitor/trabalho/devstroupe/framework/node_modules/.pnpm/typescript@5.9.3/node_modules:/home/vitor/trabalho/devstroupe/framework/node_modules/.pnpm/node_modules"
14
+ else
15
+ export NODE_PATH="/home/vitor/trabalho/devstroupe/framework/node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/node_modules:/home/vitor/trabalho/devstroupe/framework/node_modules/.pnpm/typescript@5.9.3/node_modules:/home/vitor/trabalho/devstroupe/framework/node_modules/.pnpm/node_modules:$NODE_PATH"
16
+ fi
17
+ if [ -x "$basedir/node" ]; then
18
+ exec "$basedir/node" "$basedir/../typescript/bin/tsc" "$@"
19
+ else
20
+ exec node "$basedir/../typescript/bin/tsc" "$@"
21
+ fi
@@ -0,0 +1,21 @@
1
+ #!/bin/sh
2
+ basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
3
+
4
+ case `uname` in
5
+ *CYGWIN*|*MINGW*|*MSYS*)
6
+ if command -v cygpath > /dev/null 2>&1; then
7
+ basedir=`cygpath -w "$basedir"`
8
+ fi
9
+ ;;
10
+ esac
11
+
12
+ if [ -z "$NODE_PATH" ]; then
13
+ export NODE_PATH="/home/vitor/trabalho/devstroupe/framework/node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/node_modules:/home/vitor/trabalho/devstroupe/framework/node_modules/.pnpm/typescript@5.9.3/node_modules:/home/vitor/trabalho/devstroupe/framework/node_modules/.pnpm/node_modules"
14
+ else
15
+ export NODE_PATH="/home/vitor/trabalho/devstroupe/framework/node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/node_modules:/home/vitor/trabalho/devstroupe/framework/node_modules/.pnpm/typescript@5.9.3/node_modules:/home/vitor/trabalho/devstroupe/framework/node_modules/.pnpm/node_modules:$NODE_PATH"
16
+ fi
17
+ if [ -x "$basedir/node" ]; then
18
+ exec "$basedir/node" "$basedir/../typescript/bin/tsserver" "$@"
19
+ else
20
+ exec node "$basedir/../typescript/bin/tsserver" "$@"
21
+ fi