ar-saas 0.1.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 (85) hide show
  1. package/README.md +62 -0
  2. package/dist/cli.js +67 -0
  3. package/dist/generator.js +242 -0
  4. package/dist/index.js +13 -0
  5. package/dist/license.js +71 -0
  6. package/package.json +46 -0
  7. package/templates/backend/.env.example +67 -0
  8. package/templates/backend/.prettierrc +4 -0
  9. package/templates/backend/README.md +168 -0
  10. package/templates/backend/eslint.config.mjs +35 -0
  11. package/templates/backend/nest-cli.json +8 -0
  12. package/templates/backend/package-lock.json +10979 -0
  13. package/templates/backend/package.json +88 -0
  14. package/templates/backend/src/app.controller.spec.ts +24 -0
  15. package/templates/backend/src/app.controller.ts +15 -0
  16. package/templates/backend/src/app.module.ts +40 -0
  17. package/templates/backend/src/app.service.ts +11 -0
  18. package/templates/backend/src/common/base/base.repository.ts +221 -0
  19. package/templates/backend/src/common/base/base.schema.ts +24 -0
  20. package/templates/backend/src/common/decorators/cookie.decorator.ts +9 -0
  21. package/templates/backend/src/common/decorators/current-user.decorator.ts +20 -0
  22. package/templates/backend/src/common/decorators/workspace-id.decorator.ts +14 -0
  23. package/templates/backend/src/common/filters/global-exception.filter.ts +61 -0
  24. package/templates/backend/src/common/guards/jwt-auth.guard.ts +5 -0
  25. package/templates/backend/src/common/interceptors/workspace-tenant.interceptor.ts +45 -0
  26. package/templates/backend/src/main.ts +51 -0
  27. package/templates/backend/src/modules/auth/auth.controller.ts +158 -0
  28. package/templates/backend/src/modules/auth/auth.module.ts +20 -0
  29. package/templates/backend/src/modules/auth/auth.service.ts +257 -0
  30. package/templates/backend/src/modules/auth/dto/forgot-password.dto.ts +9 -0
  31. package/templates/backend/src/modules/auth/dto/login.dto.ts +14 -0
  32. package/templates/backend/src/modules/auth/dto/refresh-token.dto.ts +12 -0
  33. package/templates/backend/src/modules/auth/dto/register.dto.ts +26 -0
  34. package/templates/backend/src/modules/auth/dto/reset-password.dto.ts +16 -0
  35. package/templates/backend/src/modules/auth/dto/verify-email.dto.ts +9 -0
  36. package/templates/backend/src/modules/auth/strategies/jwt.strategy.ts +43 -0
  37. package/templates/backend/src/modules/mail/mail.module.ts +9 -0
  38. package/templates/backend/src/modules/mail/mail.service.ts +141 -0
  39. package/templates/backend/src/modules/users/schemas/user.schema.ts +54 -0
  40. package/templates/backend/src/modules/users/users.module.ts +14 -0
  41. package/templates/backend/src/modules/users/users.repository.ts +51 -0
  42. package/templates/backend/src/modules/users/users.service.ts +104 -0
  43. package/templates/backend/src/modules/workspaces/schemas/workspace.schema.ts +26 -0
  44. package/templates/backend/src/modules/workspaces/workspaces.module.ts +16 -0
  45. package/templates/backend/src/modules/workspaces/workspaces.repository.ts +34 -0
  46. package/templates/backend/src/modules/workspaces/workspaces.service.ts +42 -0
  47. package/templates/backend/test/app.e2e-spec.ts +25 -0
  48. package/templates/backend/test/jest-e2e.json +9 -0
  49. package/templates/backend/tsconfig.build.json +4 -0
  50. package/templates/backend/tsconfig.json +26 -0
  51. package/templates/frontend/.env.local.example +1 -0
  52. package/templates/frontend/components.json +20 -0
  53. package/templates/frontend/eslint.config.mjs +14 -0
  54. package/templates/frontend/next.config.ts +5 -0
  55. package/templates/frontend/package-lock.json +6722 -0
  56. package/templates/frontend/package.json +40 -0
  57. package/templates/frontend/postcss.config.mjs +7 -0
  58. package/templates/frontend/src/app/(auth)/forgot-password/page.tsx +84 -0
  59. package/templates/frontend/src/app/(auth)/layout.tsx +28 -0
  60. package/templates/frontend/src/app/(auth)/login/page.tsx +111 -0
  61. package/templates/frontend/src/app/(auth)/register/page.tsx +119 -0
  62. package/templates/frontend/src/app/(auth)/reset-password/page.tsx +120 -0
  63. package/templates/frontend/src/app/(auth)/verify-email/page.tsx +78 -0
  64. package/templates/frontend/src/app/(dashboard)/dashboard/page.tsx +36 -0
  65. package/templates/frontend/src/app/(dashboard)/layout.tsx +59 -0
  66. package/templates/frontend/src/app/globals.css +81 -0
  67. package/templates/frontend/src/app/layout.tsx +26 -0
  68. package/templates/frontend/src/app/page.tsx +5 -0
  69. package/templates/frontend/src/app/setup/page.tsx +278 -0
  70. package/templates/frontend/src/components/ui/button.tsx +52 -0
  71. package/templates/frontend/src/components/ui/card.tsx +50 -0
  72. package/templates/frontend/src/components/ui/form.tsx +158 -0
  73. package/templates/frontend/src/components/ui/input.tsx +21 -0
  74. package/templates/frontend/src/components/ui/label.tsx +22 -0
  75. package/templates/frontend/src/components/ui/toast.tsx +109 -0
  76. package/templates/frontend/src/components/ui/toaster.tsx +30 -0
  77. package/templates/frontend/src/hooks/use-toast.ts +116 -0
  78. package/templates/frontend/src/lib/api/auth.ts +39 -0
  79. package/templates/frontend/src/lib/api/client.ts +66 -0
  80. package/templates/frontend/src/lib/hooks/use-auth.ts +1 -0
  81. package/templates/frontend/src/lib/utils.ts +6 -0
  82. package/templates/frontend/src/providers/auth-provider.tsx +60 -0
  83. package/templates/frontend/src/types/api.ts +12 -0
  84. package/templates/frontend/src/types/auth.ts +27 -0
  85. package/templates/frontend/tsconfig.json +23 -0
@@ -0,0 +1,168 @@
1
+ <p align="center"><samp>
2
+ ╔══════════════════════════════════╗<br/>
3
+ ║&nbsp;&nbsp;create-saas-ar-backend&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br/>
4
+ ║&nbsp;&nbsp;AFIP&nbsp;·&nbsp;Mercado&nbsp;Pago&nbsp;·&nbsp;Auth&nbsp;·&nbsp;Mail&nbsp;&nbsp;<br/>
5
+ ║&nbsp;&nbsp;todo&nbsp;integrado&nbsp;en&nbsp;un&nbsp;comando&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br/>
6
+ ╚══════════════════════════════════╝<br/>
7
+ </samp></p>
8
+
9
+ <p align="center">
10
+ <strong>El backend SaaS que ojalá hubieras tenido cuando empezaste.</strong>
11
+ <br/>
12
+ AFIP, Mercado Pago, auth, multi-tenancy, emails — ya integrado. En vez de perder
13
+ 3 semanas armando lo mismo de siempre, clonás esto y empezás a facturar.
14
+ </p>
15
+
16
+ ---
17
+
18
+ ## ¿Por qué existe esto?
19
+
20
+ Armar un SaaS en Argentina duele. Pasás semanas cableando autenticación con JWT,
21
+ aislamiento multi-tenant, envío de mails, validaciones, estructura de carpetas,
22
+ manejo de errores. Y cuando por fin terminás todo ese boilerplate, te das cuenta
23
+ de que todavía falta integrar AFIP para facturación electrónica y Mercado Pago
24
+ para cobrar. Otras 2 semanas.
25
+
26
+ `create-saas-ar` genera este repositorio completo **en un comando**. Viene con
27
+ todo lo genérico ya resuelto, más integraciones reales para operar en Argentina.
28
+ **Solo tenés que agregar tus módulos de negocio** siguiendo el patrón de
29
+ `.ai-docs/`.
30
+
31
+ ## Stack
32
+
33
+ | Capa | Tecnología | Versión |
34
+ |---|---|---|
35
+ | Runtime | Node.js | 22 LTS |
36
+ | Lenguaje | TypeScript | 5.7 |
37
+ | Framework | NestJS | 11 |
38
+ | Base de datos | MongoDB | 8 |
39
+ | ODM | Mongoose | 9 |
40
+ | Auth (tokens) | JWT + cookies HttpOnly | — |
41
+ | Auth (passwords) | bcrypt | 5.x |
42
+ | Auth (passport) | passport + passport-jwt | 0.7 / 4.x |
43
+ | Validación | class-validator | 0.14 |
44
+ | Transformación | class-transformer | 0.5 |
45
+ | Emails | Resend | 4.x |
46
+ | Documentación API | Swagger | 11.x |
47
+ | Tareas programadas | @nestjs/schedule | 6.x |
48
+ | Testing | Jest | 30 |
49
+ | Formateo | Prettier | 3.x |
50
+ | Linting | ESLint | 9.x |
51
+
52
+ ## Características principales
53
+
54
+ - **Multi-tenancy real** — Aislamiento por `workspaceId` garantizado en cada query. Un `WorkspaceTenantInterceptor` extrae el tenant del header `x-workspace-id` o del JWT. `BaseRepository` fuerza el filtro en toda operación. Imposible leakear datos entre workspaces por error humano.
55
+
56
+ - **Auth completo** — Registro, login, refresh token rotativo, email verification, password reset, change password. Access + refresh tokens en cookies `HttpOnly`, `Secure`, `SameSite=Strict`. Nunca en `localStorage` ni en el body.
57
+
58
+ - **BaseRepository genérico** — Soft delete, paginación, filtros dinámicos, agregaciones, conteo, upsert. Manejo automático de errores MongoDB (duplicate key, cast error). 12 métodos heredados por todos los repositorios.
59
+
60
+ - **DTOs con validación estricta** — `class-validator` con mensajes en español. `class-transformer` para coerción de tipos. `PartialType` de Swagger para updates. `forbidNonWhitelisted` + `whitelist` para rechazar campos no declarados.
61
+
62
+ - **Manejo de errores uniforme** — `GlobalExceptionFilter` transforma toda excepción a `{ statusCode, message, error, timestamp, path }`. Errores 5xx se loguean, 4xx no. Mensajes de validación concatenados y en español.
63
+
64
+ - **Emails con Resend** — Servicio de mail con métodos para verificación, reset de contraseña y bienvenida. Templates HTML inline. Preparado para reintentos con `@nestjs/schedule` y cola de emails fallidos.
65
+
66
+ - **Swagger automático** — `@ApiProperty` y `@ApiTags` en cada DTO y controller. Documentación interactiva en `/api/docs` sin configuración extra.
67
+
68
+ - **Soporte multi-agente IA** — El proyecto incluye `.ai-docs/` (fuente de verdad compartida entre herramientas), `.claude/CLAUDE.md` (leído automáticamente por Claude Code) y `.opencode/` (prompt + config para OpenCode/DeepSeek). Cada herramienta tiene tareas asignadas según su fortaleza: Claude Code para arquitectura y decisiones de seguridad, DeepSeek para tareas mecánicas como generar CRUD o tests.
69
+
70
+ ## Cómo empezar
71
+
72
+ ```bash
73
+ # 1. Clonar
74
+ git clone <repo-url> mi-saas-backend
75
+ cd mi-saas-backend
76
+
77
+ # 2. Instalar dependencias
78
+ npm install
79
+
80
+ # 3. Configurar variables de entorno
81
+ cp .env.example .env
82
+ # Editar .env con tus valores (MONGODB_URI, JWT secrets, RESEND_API_KEY, etc.)
83
+
84
+ # 4. Levantar en desarrollo
85
+ npm run start:dev
86
+ ```
87
+
88
+ El servidor corre en `http://localhost:3000/api`. Swagger en `http://localhost:3000/api/docs`.
89
+
90
+ ## Comandos disponibles
91
+
92
+ ```bash
93
+ npm run start:dev # Desarrollo con hot reload
94
+ npm run start:prod # Producción (build + node dist/main)
95
+ npm run build # Compilar TypeScript
96
+ npm run test # Tests unitarios
97
+ npm run test:e2e # Tests end-to-end
98
+ npm run test:cov # Tests con coverage
99
+ npm run lint # ESLint con fix automático
100
+ npm run format # Prettier en todo el proyecto
101
+ ```
102
+
103
+ ## Estructura del proyecto
104
+
105
+ ```
106
+ src/
107
+ ├── common/
108
+ │ ├── base/
109
+ │ │ ├── base.schema.ts # workspaceId, createdBy, deletedAt
110
+ │ │ └── base.repository.ts # findAll, findById, create, update, softDelete, paginate, aggregate...
111
+ │ ├── decorators/
112
+ │ │ ├── workspace-id.decorator.ts # @WorkspaceId()
113
+ │ │ └── current-user.decorator.ts # @CurrentUser()
114
+ │ ├── filters/
115
+ │ │ └── global-exception.filter.ts # 4xx/5xx → { statusCode, message, error, timestamp, path }
116
+ │ ├── guards/
117
+ │ │ └── jwt-auth.guard.ts # AuthGuard('jwt')
118
+ │ └── interceptors/
119
+ │ └── workspace-tenant.interceptor.ts # x-workspace-id header → request.workspaceId
120
+ ├── modules/
121
+ │ ├── auth/ # Registro, login, refresh, email verification, password reset
122
+ │ ├── users/ # CRUD de usuarios
123
+ │ ├── workspaces/ # CRUD de workspaces
124
+ │ └── mail/ # Envío de emails con Resend (@Global)
125
+ ├── app.module.ts
126
+ └── main.ts # bootstrap: ValidationPipe, cookieParser, CORS, Swagger
127
+ .ai-docs/ # Documentación compartida entre agentes AI y desarrolladores
128
+ ├── architecture/ # overview, module-pattern, database-pattern
129
+ ├── conventions/ # naming, error-handling, dto-validation
130
+ ├── modules/ # auth, multi-tenancy, mail
131
+ └── examples/ # full-module-example (módulo Clientes completo), repository-example
132
+ .claude/ # Prompt y reglas para Claude Code
133
+ .opencode/ # Prompt y config para OpenCode/DeepSeek
134
+ ```
135
+
136
+ ## Documentación para agentes AI
137
+
138
+ Este proyecto está diseñado para que dos agentes de IA trabajen en paralelo:
139
+
140
+ | Herramienta | Config | Ideal para |
141
+ |---|---|---|
142
+ | **Claude Code** | `.claude/CLAUDE.md` | Arquitectura, auth avanzado, decisiones de seguridad, refactors |
143
+ | **OpenCode / DeepSeek** | `.opencode/config.json` + `system-prompt.md` | CRUD de módulos nuevos, DTOs, tests, renombrar archivos |
144
+
145
+ Ambos leen `.ai-docs/` como fuente de verdad. Las **8 reglas absolutas** están en `.claude/CLAUDE.md` y `.opencode/system-prompt.md`.
146
+
147
+ ## Cómo crear un módulo nuevo
148
+
149
+ Seguí el checklist de 12 pasos en `.ai-docs/examples/full-module-example.md`. El resumen:
150
+
151
+ 1. Crear carpeta `src/modules/{nombre}/` con `schemas/` y `dto/`
152
+ 2. Schema → extiende `BaseSchema`
153
+ 3. DTO Create → `class-validator` con mensajes en español
154
+ 4. DTO Update → `extends PartialType(CreateXxxDto)`
155
+ 5. Repository → extiende `BaseRepository`, métodos con `workspaceId` primero
156
+ 6. Service → `create`, `findAll`, `findById`, `update`, `remove`
157
+ 7. Controller → `@WorkspaceId()`, `@CurrentUser()`, nunca `@Req()`
158
+ 8. Module → `MongooseModule.forFeature(...)`, exporta el service
159
+ 9. Registrar en `AppModule`
160
+ 10. `npm run build` → verificar que compila
161
+ 11. Swagger → verificar en `/api/docs`
162
+ 12. Tests → unitarios del service, e2e del controller
163
+
164
+ El archivo `.ai-docs/examples/full-module-example.md` tiene el módulo Clientes completo para copiar y adaptar.
165
+
166
+ ## Licencia
167
+
168
+ Privado (UNLICENSED). Generado con [`create-saas-ar`](https://github.com/anomalyco/create-saas-ar).
@@ -0,0 +1,35 @@
1
+ // @ts-check
2
+ import eslint from '@eslint/js';
3
+ import eslintPluginPrettierRecommended from 'eslint-plugin-prettier/recommended';
4
+ import globals from 'globals';
5
+ import tseslint from 'typescript-eslint';
6
+
7
+ export default tseslint.config(
8
+ {
9
+ ignores: ['eslint.config.mjs'],
10
+ },
11
+ eslint.configs.recommended,
12
+ ...tseslint.configs.recommendedTypeChecked,
13
+ eslintPluginPrettierRecommended,
14
+ {
15
+ languageOptions: {
16
+ globals: {
17
+ ...globals.node,
18
+ ...globals.jest,
19
+ },
20
+ sourceType: 'commonjs',
21
+ parserOptions: {
22
+ projectService: true,
23
+ tsconfigRootDir: import.meta.dirname,
24
+ },
25
+ },
26
+ },
27
+ {
28
+ rules: {
29
+ '@typescript-eslint/no-explicit-any': 'error',
30
+ '@typescript-eslint/no-floating-promises': 'warn',
31
+ '@typescript-eslint/no-unsafe-argument': 'warn',
32
+ 'prettier/prettier': ['error', { endOfLine: 'auto' }],
33
+ },
34
+ },
35
+ );
@@ -0,0 +1,8 @@
1
+ {
2
+ "$schema": "https://json.schemastore.org/nest-cli",
3
+ "collection": "@nestjs/schematics",
4
+ "sourceRoot": "src",
5
+ "compilerOptions": {
6
+ "deleteOutDir": true
7
+ }
8
+ }