nestjs-ddd-cli 2.2.1 → 3.2.1

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 (254) hide show
  1. package/README.md +247 -408
  2. package/ddd.schema.json +111 -0
  3. package/dist/commands/aggregate-validator.d.ts +9 -0
  4. package/dist/commands/aggregate-validator.js +953 -0
  5. package/dist/commands/aggregate-validator.js.map +1 -0
  6. package/dist/commands/ai-assist.d.ts +8 -0
  7. package/dist/commands/ai-assist.js +337 -0
  8. package/dist/commands/ai-assist.js.map +1 -0
  9. package/dist/commands/api-contracts.d.ts +9 -0
  10. package/dist/commands/api-contracts.js +1368 -0
  11. package/dist/commands/api-contracts.js.map +1 -0
  12. package/dist/commands/api-docs.d.ts +8 -0
  13. package/dist/commands/api-docs.js +408 -0
  14. package/dist/commands/api-docs.js.map +1 -0
  15. package/dist/commands/api-versioning.d.ts +11 -0
  16. package/dist/commands/api-versioning.js +643 -0
  17. package/dist/commands/api-versioning.js.map +1 -0
  18. package/dist/commands/audit-logging.d.ts +9 -0
  19. package/dist/commands/audit-logging.js +1129 -0
  20. package/dist/commands/audit-logging.js.map +1 -0
  21. package/dist/commands/batch-generate.d.ts +10 -0
  22. package/dist/commands/batch-generate.js +405 -0
  23. package/dist/commands/batch-generate.js.map +1 -0
  24. package/dist/commands/caching-strategies.d.ts +9 -0
  25. package/dist/commands/caching-strategies.js +874 -0
  26. package/dist/commands/caching-strategies.js.map +1 -0
  27. package/dist/commands/code-analyzer.d.ts +42 -0
  28. package/dist/commands/code-analyzer.js +474 -0
  29. package/dist/commands/code-analyzer.js.map +1 -0
  30. package/dist/commands/database-seeding.d.ts +6 -0
  31. package/dist/commands/database-seeding.js +621 -0
  32. package/dist/commands/database-seeding.js.map +1 -0
  33. package/dist/commands/db-optimization.d.ts +7 -0
  34. package/dist/commands/db-optimization.js +687 -0
  35. package/dist/commands/db-optimization.js.map +1 -0
  36. package/dist/commands/dependency-graph.d.ts +6 -0
  37. package/dist/commands/dependency-graph.js +329 -0
  38. package/dist/commands/dependency-graph.js.map +1 -0
  39. package/dist/commands/doctor-enhanced.d.ts +22 -0
  40. package/dist/commands/doctor-enhanced.js +543 -0
  41. package/dist/commands/doctor-enhanced.js.map +1 -0
  42. package/dist/commands/doctor.d.ts +4 -0
  43. package/dist/commands/doctor.js +151 -0
  44. package/dist/commands/doctor.js.map +1 -0
  45. package/dist/commands/env-manager.d.ts +6 -0
  46. package/dist/commands/env-manager.js +419 -0
  47. package/dist/commands/env-manager.js.map +1 -0
  48. package/dist/commands/event-sourcing-full.d.ts +10 -0
  49. package/dist/commands/event-sourcing-full.js +1107 -0
  50. package/dist/commands/event-sourcing-full.js.map +1 -0
  51. package/dist/commands/feature-flags.d.ts +9 -0
  52. package/dist/commands/feature-flags.js +824 -0
  53. package/dist/commands/feature-flags.js.map +1 -0
  54. package/dist/commands/filter-dsl.d.ts +10 -0
  55. package/dist/commands/filter-dsl.js +1407 -0
  56. package/dist/commands/filter-dsl.js.map +1 -0
  57. package/dist/commands/generate-all.js +485 -32
  58. package/dist/commands/generate-all.js.map +1 -1
  59. package/dist/commands/generate-deployment.d.ts +8 -0
  60. package/dist/commands/generate-deployment.js +746 -0
  61. package/dist/commands/generate-deployment.js.map +1 -0
  62. package/dist/commands/generate-domain-service.d.ts +14 -0
  63. package/dist/commands/generate-domain-service.js +796 -0
  64. package/dist/commands/generate-domain-service.js.map +1 -0
  65. package/dist/commands/generate-entity.js +82 -24
  66. package/dist/commands/generate-entity.js.map +1 -1
  67. package/dist/commands/generate-from-schema.d.ts +56 -0
  68. package/dist/commands/generate-from-schema.js +222 -0
  69. package/dist/commands/generate-from-schema.js.map +1 -0
  70. package/dist/commands/generate-orchestrator.d.ts +14 -0
  71. package/dist/commands/generate-orchestrator.js +887 -0
  72. package/dist/commands/generate-orchestrator.js.map +1 -0
  73. package/dist/commands/generate-repository.d.ts +14 -0
  74. package/dist/commands/generate-repository.js +1019 -0
  75. package/dist/commands/generate-repository.js.map +1 -0
  76. package/dist/commands/generate-shared.d.ts +4 -0
  77. package/dist/commands/generate-shared.js +388 -0
  78. package/dist/commands/generate-shared.js.map +1 -0
  79. package/dist/commands/generate-value-object.d.ts +32 -0
  80. package/dist/commands/generate-value-object.js +700 -0
  81. package/dist/commands/generate-value-object.js.map +1 -0
  82. package/dist/commands/graphql-subscriptions.d.ts +6 -0
  83. package/dist/commands/graphql-subscriptions.js +607 -0
  84. package/dist/commands/graphql-subscriptions.js.map +1 -0
  85. package/dist/commands/graphql-types.d.ts +5 -0
  86. package/dist/commands/graphql-types.js +423 -0
  87. package/dist/commands/graphql-types.js.map +1 -0
  88. package/dist/commands/health-probes-advanced.d.ts +6 -0
  89. package/dist/commands/health-probes-advanced.js +655 -0
  90. package/dist/commands/health-probes-advanced.js.map +1 -0
  91. package/dist/commands/i18n-setup.d.ts +10 -0
  92. package/dist/commands/i18n-setup.js +677 -0
  93. package/dist/commands/i18n-setup.js.map +1 -0
  94. package/dist/commands/init-config.d.ts +6 -0
  95. package/dist/commands/init-config.js +370 -0
  96. package/dist/commands/init-config.js.map +1 -0
  97. package/dist/commands/init-project.js +56 -6
  98. package/dist/commands/init-project.js.map +1 -1
  99. package/dist/commands/interactive-scaffold.d.ts +5 -0
  100. package/dist/commands/interactive-scaffold.js +271 -0
  101. package/dist/commands/interactive-scaffold.js.map +1 -0
  102. package/dist/commands/metrics-prometheus.d.ts +6 -0
  103. package/dist/commands/metrics-prometheus.js +681 -0
  104. package/dist/commands/metrics-prometheus.js.map +1 -0
  105. package/dist/commands/migration-engine.d.ts +6 -0
  106. package/dist/commands/migration-engine.js +446 -0
  107. package/dist/commands/migration-engine.js.map +1 -0
  108. package/dist/commands/migration.d.ts +12 -0
  109. package/dist/commands/migration.js +484 -0
  110. package/dist/commands/migration.js.map +1 -0
  111. package/dist/commands/monorepo.d.ts +8 -0
  112. package/dist/commands/monorepo.js +483 -0
  113. package/dist/commands/monorepo.js.map +1 -0
  114. package/dist/commands/multi-database.d.ts +5 -0
  115. package/dist/commands/multi-database.js +439 -0
  116. package/dist/commands/multi-database.js.map +1 -0
  117. package/dist/commands/observability-tracing.d.ts +10 -0
  118. package/dist/commands/observability-tracing.js +740 -0
  119. package/dist/commands/observability-tracing.js.map +1 -0
  120. package/dist/commands/openapi-export.d.ts +8 -0
  121. package/dist/commands/openapi-export.js +359 -0
  122. package/dist/commands/openapi-export.js.map +1 -0
  123. package/dist/commands/perf-analyzer.d.ts +8 -0
  124. package/dist/commands/perf-analyzer.js +423 -0
  125. package/dist/commands/perf-analyzer.js.map +1 -0
  126. package/dist/commands/rate-limiting.d.ts +10 -0
  127. package/dist/commands/rate-limiting.js +953 -0
  128. package/dist/commands/rate-limiting.js.map +1 -0
  129. package/dist/commands/recipe-plugin.d.ts +56 -0
  130. package/dist/commands/recipe-plugin.js +315 -0
  131. package/dist/commands/recipe-plugin.js.map +1 -0
  132. package/dist/commands/recipe.d.ts +6 -0
  133. package/dist/commands/recipe.js +3941 -0
  134. package/dist/commands/recipe.js.map +1 -0
  135. package/dist/commands/recipes/elasticsearch.recipe.d.ts +1 -0
  136. package/dist/commands/recipes/elasticsearch.recipe.js +761 -0
  137. package/dist/commands/recipes/elasticsearch.recipe.js.map +1 -0
  138. package/dist/commands/recipes/event-sourcing.recipe.d.ts +1 -0
  139. package/dist/commands/recipes/event-sourcing.recipe.js +889 -0
  140. package/dist/commands/recipes/event-sourcing.recipe.js.map +1 -0
  141. package/dist/commands/recipes/index.d.ts +7 -0
  142. package/dist/commands/recipes/index.js +24 -0
  143. package/dist/commands/recipes/index.js.map +1 -0
  144. package/dist/commands/recipes/message-queue.recipe.d.ts +1 -0
  145. package/dist/commands/recipes/message-queue.recipe.js +706 -0
  146. package/dist/commands/recipes/message-queue.recipe.js.map +1 -0
  147. package/dist/commands/recipes/middleware.recipe.d.ts +1 -0
  148. package/dist/commands/recipes/middleware.recipe.js +383 -0
  149. package/dist/commands/recipes/middleware.recipe.js.map +1 -0
  150. package/dist/commands/recipes/multi-tenancy.recipe.d.ts +1 -0
  151. package/dist/commands/recipes/multi-tenancy.recipe.js +520 -0
  152. package/dist/commands/recipes/multi-tenancy.recipe.js.map +1 -0
  153. package/dist/commands/recipes/oauth2.recipe.d.ts +1 -0
  154. package/dist/commands/recipes/oauth2.recipe.js +472 -0
  155. package/dist/commands/recipes/oauth2.recipe.js.map +1 -0
  156. package/dist/commands/recipes/websocket.recipe.d.ts +1 -0
  157. package/dist/commands/recipes/websocket.recipe.js +453 -0
  158. package/dist/commands/recipes/websocket.recipe.js.map +1 -0
  159. package/dist/commands/resilience-patterns.d.ts +13 -0
  160. package/dist/commands/resilience-patterns.js +1029 -0
  161. package/dist/commands/resilience-patterns.js.map +1 -0
  162. package/dist/commands/security-patterns.d.ts +11 -0
  163. package/dist/commands/security-patterns.js +2233 -0
  164. package/dist/commands/security-patterns.js.map +1 -0
  165. package/dist/commands/template-debug.d.ts +27 -0
  166. package/dist/commands/template-debug.js +388 -0
  167. package/dist/commands/template-debug.js.map +1 -0
  168. package/dist/commands/test-factory-full.d.ts +9 -0
  169. package/dist/commands/test-factory-full.js +1570 -0
  170. package/dist/commands/test-factory-full.js.map +1 -0
  171. package/dist/commands/test-scaffold.d.ts +7 -0
  172. package/dist/commands/test-scaffold.js +621 -0
  173. package/dist/commands/test-scaffold.js.map +1 -0
  174. package/dist/index.js +1088 -0
  175. package/dist/index.js.map +1 -1
  176. package/dist/templates/ai-context/CLAUDE.md.hbs +158 -0
  177. package/dist/templates/ai-context/conventions.md.hbs +154 -0
  178. package/dist/templates/command/create-command.hbs +6 -14
  179. package/dist/templates/command/delete-command.hbs +19 -0
  180. package/dist/templates/command/update-command.hbs +24 -0
  181. package/dist/templates/controller/controller.hbs +64 -17
  182. package/dist/templates/dto/create-dto.hbs +29 -5
  183. package/dist/templates/dto/filter-dto.hbs +52 -0
  184. package/dist/templates/dto/filter-query.dto.hbs +148 -0
  185. package/dist/templates/dto/paginated-response.dto.hbs +29 -0
  186. package/dist/templates/dto/pagination-query.dto.hbs +30 -0
  187. package/dist/templates/dto/response-dto.hbs +38 -0
  188. package/dist/templates/dto/update-dto.hbs +11 -0
  189. package/dist/templates/entity/entity.hbs +32 -1
  190. package/dist/templates/event/domain-event.hbs +33 -7
  191. package/dist/templates/event/event-handler.hbs +40 -0
  192. package/dist/templates/exception/base-exceptions.hbs +69 -0
  193. package/dist/templates/exception/entity-not-found.exception.hbs +7 -0
  194. package/dist/templates/mapper/mapper.hbs +49 -24
  195. package/dist/templates/module/module.hbs +34 -10
  196. package/dist/templates/orm-entity/orm-entity.hbs +63 -12
  197. package/dist/templates/prisma/prisma-mapper.hbs +71 -0
  198. package/dist/templates/prisma/prisma-repository.hbs +114 -0
  199. package/dist/templates/prisma/prisma-schema.hbs +20 -0
  200. package/dist/templates/prisma/prisma-service.hbs +51 -0
  201. package/dist/templates/query/get-all.query.hbs +50 -0
  202. package/dist/templates/query/get-by-id.query.hbs +31 -0
  203. package/dist/templates/repository/repository.hbs +55 -13
  204. package/dist/templates/resolver/graphql-input.hbs +54 -0
  205. package/dist/templates/resolver/graphql-type.hbs +58 -0
  206. package/dist/templates/resolver/pagination-args.hbs +33 -0
  207. package/dist/templates/resolver/resolver.hbs +62 -0
  208. package/dist/templates/shared/prisma-query-builder.util.hbs +189 -0
  209. package/dist/templates/shared/query-builder.util.hbs +218 -0
  210. package/dist/templates/test/controller.spec.hbs +124 -0
  211. package/dist/templates/test/repository.spec.hbs +158 -0
  212. package/dist/templates/test/usecase.spec.hbs +116 -0
  213. package/dist/templates/usecase/create-usecase.hbs +19 -7
  214. package/dist/templates/usecase/delete-usecase.hbs +17 -0
  215. package/dist/templates/usecase/update-usecase.hbs +31 -0
  216. package/dist/utils/config.utils.d.ts +45 -0
  217. package/dist/utils/config.utils.js +211 -0
  218. package/dist/utils/config.utils.js.map +1 -0
  219. package/dist/utils/error.utils.d.ts +145 -0
  220. package/dist/utils/error.utils.js +422 -0
  221. package/dist/utils/error.utils.js.map +1 -0
  222. package/dist/utils/field.utils.d.ts +54 -0
  223. package/dist/utils/field.utils.js +389 -0
  224. package/dist/utils/field.utils.js.map +1 -0
  225. package/dist/utils/file.utils.d.ts +19 -8
  226. package/dist/utils/file.utils.js +135 -4
  227. package/dist/utils/file.utils.js.map +1 -1
  228. package/dist/utils/idempotency.utils.d.ts +123 -0
  229. package/dist/utils/idempotency.utils.js +444 -0
  230. package/dist/utils/idempotency.utils.js.map +1 -0
  231. package/dist/utils/naming.utils.js +24 -5
  232. package/dist/utils/naming.utils.js.map +1 -1
  233. package/dist/utils/performance.utils.d.ts +37 -0
  234. package/dist/utils/performance.utils.js +158 -0
  235. package/dist/utils/performance.utils.js.map +1 -0
  236. package/dist/utils/relation.utils.d.ts +92 -0
  237. package/dist/utils/relation.utils.js +388 -0
  238. package/dist/utils/relation.utils.js.map +1 -0
  239. package/dist/utils/rollback.utils.d.ts +49 -0
  240. package/dist/utils/rollback.utils.js +306 -0
  241. package/dist/utils/rollback.utils.js.map +1 -0
  242. package/dist/utils/schema.utils.d.ts +123 -0
  243. package/dist/utils/schema.utils.js +419 -0
  244. package/dist/utils/schema.utils.js.map +1 -0
  245. package/dist/utils/security.utils.d.ts +57 -0
  246. package/dist/utils/security.utils.js +315 -0
  247. package/dist/utils/security.utils.js.map +1 -0
  248. package/dist/utils/template-engine.utils.d.ts +80 -0
  249. package/dist/utils/template-engine.utils.js +463 -0
  250. package/dist/utils/template-engine.utils.js.map +1 -0
  251. package/dist/utils/validation-registry.utils.d.ts +160 -0
  252. package/dist/utils/validation-registry.utils.js +526 -0
  253. package/dist/utils/validation-registry.utils.js.map +1 -0
  254. package/package.json +3 -1
@@ -0,0 +1,472 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.applyOAuth2Recipe = applyOAuth2Recipe;
40
+ const path = __importStar(require("path"));
41
+ const chalk_1 = __importDefault(require("chalk"));
42
+ const file_utils_1 = require("../../utils/file.utils");
43
+ async function applyOAuth2Recipe(basePath) {
44
+ const sharedPath = path.join(basePath, 'src/shared');
45
+ const oauthPath = path.join(sharedPath, 'oauth');
46
+ await (0, file_utils_1.ensureDir)(oauthPath);
47
+ await (0, file_utils_1.ensureDir)(path.join(oauthPath, 'strategies'));
48
+ await (0, file_utils_1.ensureDir)(path.join(oauthPath, 'guards'));
49
+ // OAuth types
50
+ const oauthTypesContent = `export interface OAuthProfile {
51
+ provider: string;
52
+ providerId: string;
53
+ email: string;
54
+ emailVerified: boolean;
55
+ firstName?: string;
56
+ lastName?: string;
57
+ displayName?: string;
58
+ avatarUrl?: string;
59
+ accessToken: string;
60
+ refreshToken?: string;
61
+ raw: any;
62
+ }
63
+
64
+ export interface OAuthUser {
65
+ id: string;
66
+ email: string;
67
+ providers: OAuthProvider[];
68
+ }
69
+
70
+ export interface OAuthProvider {
71
+ provider: string;
72
+ providerId: string;
73
+ accessToken?: string;
74
+ refreshToken?: string;
75
+ linkedAt: Date;
76
+ }
77
+
78
+ export type OAuthProviderType = "google" | "github" | "microsoft" | "facebook";
79
+ `;
80
+ await (0, file_utils_1.writeFile)(path.join(oauthPath, 'oauth.types.ts'), oauthTypesContent);
81
+ // Google Strategy
82
+ const googleStrategyContent = `import { Injectable } from "@nestjs/common";
83
+ import { PassportStrategy } from "@nestjs/passport";
84
+ import { Strategy, VerifyCallback, Profile } from "passport-google-oauth20";
85
+ import { OAuthProfile } from "../oauth.types";
86
+
87
+ @Injectable()
88
+ export class GoogleStrategy extends PassportStrategy(Strategy, "google") {
89
+ constructor() {
90
+ super({
91
+ clientID: process.env.GOOGLE_CLIENT_ID,
92
+ clientSecret: process.env.GOOGLE_CLIENT_SECRET,
93
+ callbackURL: process.env.GOOGLE_CALLBACK_URL || "/auth/google/callback",
94
+ scope: ["email", "profile"],
95
+ });
96
+ }
97
+
98
+ async validate(
99
+ accessToken: string,
100
+ refreshToken: string,
101
+ profile: Profile,
102
+ done: VerifyCallback
103
+ ): Promise<void> {
104
+ const { id, emails, name, photos, displayName } = profile;
105
+
106
+ const oauthProfile: OAuthProfile = {
107
+ provider: "google",
108
+ providerId: id,
109
+ email: emails?.[0]?.value || "",
110
+ emailVerified: emails?.[0]?.verified || false,
111
+ firstName: name?.givenName,
112
+ lastName: name?.familyName,
113
+ displayName: displayName,
114
+ avatarUrl: photos?.[0]?.value,
115
+ accessToken,
116
+ refreshToken,
117
+ raw: profile._json,
118
+ };
119
+
120
+ done(null, oauthProfile);
121
+ }
122
+ }
123
+ `;
124
+ await (0, file_utils_1.writeFile)(path.join(oauthPath, 'strategies/google.strategy.ts'), googleStrategyContent);
125
+ // GitHub Strategy
126
+ const githubStrategyContent = `import { Injectable } from "@nestjs/common";
127
+ import { PassportStrategy } from "@nestjs/passport";
128
+ import { Strategy, Profile } from "passport-github2";
129
+ import { OAuthProfile } from "../oauth.types";
130
+
131
+ @Injectable()
132
+ export class GitHubStrategy extends PassportStrategy(Strategy, "github") {
133
+ constructor() {
134
+ super({
135
+ clientID: process.env.GITHUB_CLIENT_ID,
136
+ clientSecret: process.env.GITHUB_CLIENT_SECRET,
137
+ callbackURL: process.env.GITHUB_CALLBACK_URL || "/auth/github/callback",
138
+ scope: ["user:email"],
139
+ });
140
+ }
141
+
142
+ async validate(
143
+ accessToken: string,
144
+ refreshToken: string,
145
+ profile: Profile,
146
+ done: (err: any, user: any) => void
147
+ ): Promise<void> {
148
+ const { id, emails, displayName, photos, username } = profile;
149
+
150
+ const oauthProfile: OAuthProfile = {
151
+ provider: "github",
152
+ providerId: id,
153
+ email: emails?.[0]?.value || "",
154
+ emailVerified: true, // GitHub verifies emails
155
+ displayName: displayName || username,
156
+ avatarUrl: photos?.[0]?.value,
157
+ accessToken,
158
+ refreshToken,
159
+ raw: profile._json,
160
+ };
161
+
162
+ done(null, oauthProfile);
163
+ }
164
+ }
165
+ `;
166
+ await (0, file_utils_1.writeFile)(path.join(oauthPath, 'strategies/github.strategy.ts'), githubStrategyContent);
167
+ // OAuth Guards
168
+ const oauthGuardsContent = `import { Injectable, ExecutionContext } from "@nestjs/common";
169
+ import { AuthGuard } from "@nestjs/passport";
170
+
171
+ @Injectable()
172
+ export class GoogleAuthGuard extends AuthGuard("google") {
173
+ async canActivate(context: ExecutionContext): Promise<boolean> {
174
+ const result = (await super.canActivate(context)) as boolean;
175
+ const request = context.switchToHttp().getRequest();
176
+ await super.logIn(request);
177
+ return result;
178
+ }
179
+ }
180
+
181
+ @Injectable()
182
+ export class GitHubAuthGuard extends AuthGuard("github") {
183
+ async canActivate(context: ExecutionContext): Promise<boolean> {
184
+ const result = (await super.canActivate(context)) as boolean;
185
+ const request = context.switchToHttp().getRequest();
186
+ await super.logIn(request);
187
+ return result;
188
+ }
189
+ }
190
+
191
+ @Injectable()
192
+ export class OAuthCallbackGuard extends AuthGuard(["google", "github"]) {
193
+ handleRequest(err: any, user: any, info: any) {
194
+ if (err || !user) {
195
+ throw err || new Error("OAuth authentication failed");
196
+ }
197
+ return user;
198
+ }
199
+ }
200
+ `;
201
+ await (0, file_utils_1.writeFile)(path.join(oauthPath, 'guards/oauth.guard.ts'), oauthGuardsContent);
202
+ // OAuth Service
203
+ const oauthServiceContent = `import { Injectable, Logger, UnauthorizedException } from "@nestjs/common";
204
+ import { JwtService } from "@nestjs/jwt";
205
+ import { OAuthProfile, OAuthUser, OAuthProvider } from "./oauth.types";
206
+
207
+ @Injectable()
208
+ export class OAuthService {
209
+ private readonly logger = new Logger(OAuthService.name);
210
+
211
+ constructor(private jwtService: JwtService) {}
212
+
213
+ /**
214
+ * Handle OAuth callback - find or create user
215
+ */
216
+ async handleOAuthLogin(profile: OAuthProfile): Promise<{
217
+ user: OAuthUser;
218
+ accessToken: string;
219
+ isNewUser: boolean;
220
+ }> {
221
+ // TODO: Implement actual user lookup/creation
222
+ // This is a placeholder implementation
223
+
224
+ const existingUser = await this.findUserByProvider(
225
+ profile.provider,
226
+ profile.providerId
227
+ );
228
+
229
+ if (existingUser) {
230
+ // Update tokens
231
+ await this.updateProviderTokens(
232
+ existingUser.id,
233
+ profile.provider,
234
+ profile.accessToken,
235
+ profile.refreshToken
236
+ );
237
+
238
+ const accessToken = await this.generateJwtToken(existingUser);
239
+ return { user: existingUser, accessToken, isNewUser: false };
240
+ }
241
+
242
+ // Check if user exists with same email
243
+ const userByEmail = await this.findUserByEmail(profile.email);
244
+
245
+ if (userByEmail) {
246
+ // Link new provider to existing account
247
+ await this.linkProvider(userByEmail.id, profile);
248
+ const accessToken = await this.generateJwtToken(userByEmail);
249
+ return { user: userByEmail, accessToken, isNewUser: false };
250
+ }
251
+
252
+ // Create new user
253
+ const newUser = await this.createUserFromOAuth(profile);
254
+ const accessToken = await this.generateJwtToken(newUser);
255
+ return { user: newUser, accessToken, isNewUser: true };
256
+ }
257
+
258
+ /**
259
+ * Link OAuth provider to existing account
260
+ */
261
+ async linkProvider(userId: string, profile: OAuthProfile): Promise<void> {
262
+ const provider: OAuthProvider = {
263
+ provider: profile.provider,
264
+ providerId: profile.providerId,
265
+ accessToken: profile.accessToken,
266
+ refreshToken: profile.refreshToken,
267
+ linkedAt: new Date(),
268
+ };
269
+
270
+ // TODO: Save provider to database
271
+ this.logger.log(\`Linked \${profile.provider} to user \${userId}\`);
272
+ }
273
+
274
+ /**
275
+ * Unlink OAuth provider from account
276
+ */
277
+ async unlinkProvider(userId: string, provider: string): Promise<void> {
278
+ // TODO: Remove provider from database
279
+ // Ensure user has at least one auth method remaining
280
+ this.logger.log(\`Unlinked \${provider} from user \${userId}\`);
281
+ }
282
+
283
+ /**
284
+ * Generate JWT token for user
285
+ */
286
+ async generateJwtToken(user: OAuthUser): Promise<string> {
287
+ const payload = {
288
+ sub: user.id,
289
+ email: user.email,
290
+ };
291
+
292
+ return this.jwtService.signAsync(payload);
293
+ }
294
+
295
+ /**
296
+ * Refresh OAuth access token
297
+ */
298
+ async refreshProviderToken(
299
+ userId: string,
300
+ provider: string
301
+ ): Promise<string | null> {
302
+ // TODO: Implement token refresh using provider's refresh token
303
+ return null;
304
+ }
305
+
306
+ // Placeholder methods - implement with your actual data layer
307
+ private async findUserByProvider(
308
+ provider: string,
309
+ providerId: string
310
+ ): Promise<OAuthUser | null> {
311
+ return null;
312
+ }
313
+
314
+ private async findUserByEmail(email: string): Promise<OAuthUser | null> {
315
+ return null;
316
+ }
317
+
318
+ private async createUserFromOAuth(profile: OAuthProfile): Promise<OAuthUser> {
319
+ return {
320
+ id: "new-user-id",
321
+ email: profile.email,
322
+ providers: [
323
+ {
324
+ provider: profile.provider,
325
+ providerId: profile.providerId,
326
+ accessToken: profile.accessToken,
327
+ refreshToken: profile.refreshToken,
328
+ linkedAt: new Date(),
329
+ },
330
+ ],
331
+ };
332
+ }
333
+
334
+ private async updateProviderTokens(
335
+ userId: string,
336
+ provider: string,
337
+ accessToken: string,
338
+ refreshToken?: string
339
+ ): Promise<void> {
340
+ // TODO: Update tokens in database
341
+ }
342
+ }
343
+ `;
344
+ await (0, file_utils_1.writeFile)(path.join(oauthPath, 'oauth.service.ts'), oauthServiceContent);
345
+ // OAuth Controller
346
+ const oauthControllerContent = `import {
347
+ Controller,
348
+ Get,
349
+ UseGuards,
350
+ Req,
351
+ Res,
352
+ Query,
353
+ HttpStatus,
354
+ } from "@nestjs/common";
355
+ import { ApiTags, ApiOperation, ApiExcludeEndpoint } from "@nestjs/swagger";
356
+ import { Response } from "express";
357
+ import { GoogleAuthGuard, GitHubAuthGuard } from "./guards/oauth.guard";
358
+ import { OAuthService } from "./oauth.service";
359
+ import { OAuthProfile } from "./oauth.types";
360
+
361
+ @ApiTags("OAuth")
362
+ @Controller("auth")
363
+ export class OAuthController {
364
+ constructor(private oauthService: OAuthService) {}
365
+
366
+ // Google OAuth
367
+ @Get("google")
368
+ @UseGuards(GoogleAuthGuard)
369
+ @ApiOperation({ summary: "Initiate Google OAuth login" })
370
+ googleLogin() {
371
+ // Guard redirects to Google
372
+ }
373
+
374
+ @Get("google/callback")
375
+ @UseGuards(GoogleAuthGuard)
376
+ @ApiExcludeEndpoint()
377
+ async googleCallback(@Req() req: any, @Res() res: Response) {
378
+ return this.handleCallback(req.user, res);
379
+ }
380
+
381
+ // GitHub OAuth
382
+ @Get("github")
383
+ @UseGuards(GitHubAuthGuard)
384
+ @ApiOperation({ summary: "Initiate GitHub OAuth login" })
385
+ githubLogin() {
386
+ // Guard redirects to GitHub
387
+ }
388
+
389
+ @Get("github/callback")
390
+ @UseGuards(GitHubAuthGuard)
391
+ @ApiExcludeEndpoint()
392
+ async githubCallback(@Req() req: any, @Res() res: Response) {
393
+ return this.handleCallback(req.user, res);
394
+ }
395
+
396
+ /**
397
+ * Common callback handler
398
+ */
399
+ private async handleCallback(profile: OAuthProfile, res: Response) {
400
+ try {
401
+ const { user, accessToken, isNewUser } =
402
+ await this.oauthService.handleOAuthLogin(profile);
403
+
404
+ // Redirect to frontend with token
405
+ const frontendUrl = process.env.FRONTEND_URL || "http://localhost:3000";
406
+ const redirectUrl = new URL("/auth/callback", frontendUrl);
407
+ redirectUrl.searchParams.set("token", accessToken);
408
+ redirectUrl.searchParams.set("isNewUser", String(isNewUser));
409
+
410
+ return res.redirect(redirectUrl.toString());
411
+ } catch (error) {
412
+ const frontendUrl = process.env.FRONTEND_URL || "http://localhost:3000";
413
+ const errorUrl = new URL("/auth/error", frontendUrl);
414
+ errorUrl.searchParams.set("error", "oauth_failed");
415
+
416
+ return res.redirect(errorUrl.toString());
417
+ }
418
+ }
419
+ }
420
+ `;
421
+ await (0, file_utils_1.writeFile)(path.join(oauthPath, 'oauth.controller.ts'), oauthControllerContent);
422
+ // OAuth Module
423
+ const oauthModuleContent = `import { Module } from "@nestjs/common";
424
+ import { PassportModule } from "@nestjs/passport";
425
+ import { JwtModule } from "@nestjs/jwt";
426
+ import { GoogleStrategy } from "./strategies/google.strategy";
427
+ import { GitHubStrategy } from "./strategies/github.strategy";
428
+ import { OAuthService } from "./oauth.service";
429
+ import { OAuthController } from "./oauth.controller";
430
+
431
+ @Module({
432
+ imports: [
433
+ PassportModule.register({ session: false }),
434
+ JwtModule.register({
435
+ secret: process.env.JWT_SECRET,
436
+ signOptions: { expiresIn: "7d" },
437
+ }),
438
+ ],
439
+ controllers: [OAuthController],
440
+ providers: [
441
+ OAuthService,
442
+ GoogleStrategy,
443
+ GitHubStrategy,
444
+ ],
445
+ exports: [OAuthService],
446
+ })
447
+ export class OAuthModule {}
448
+ `;
449
+ await (0, file_utils_1.writeFile)(path.join(oauthPath, 'oauth.module.ts'), oauthModuleContent);
450
+ // Index exports
451
+ await (0, file_utils_1.writeFile)(path.join(oauthPath, 'index.ts'), `export * from "./oauth.types";
452
+ export * from "./oauth.service";
453
+ export * from "./oauth.controller";
454
+ export * from "./oauth.module";
455
+ export * from "./strategies/google.strategy";
456
+ export * from "./strategies/github.strategy";
457
+ export * from "./guards/oauth.guard";
458
+ `);
459
+ await (0, file_utils_1.writeFile)(path.join(oauthPath, 'strategies/index.ts'), `export * from "./google.strategy";
460
+ export * from "./github.strategy";
461
+ `);
462
+ await (0, file_utils_1.writeFile)(path.join(oauthPath, 'guards/index.ts'), `export * from "./oauth.guard";
463
+ `);
464
+ console.log(chalk_1.default.green(' ✓ OAuth types and interfaces'));
465
+ console.log(chalk_1.default.green(' ✓ Google OAuth strategy'));
466
+ console.log(chalk_1.default.green(' ✓ GitHub OAuth strategy'));
467
+ console.log(chalk_1.default.green(' ✓ OAuth guards'));
468
+ console.log(chalk_1.default.green(' ✓ OAuth service (login, link/unlink providers)'));
469
+ console.log(chalk_1.default.green(' ✓ OAuth controller with callbacks'));
470
+ console.log(chalk_1.default.green(' ✓ OAuth module'));
471
+ }
472
+ //# sourceMappingURL=oauth2.recipe.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oauth2.recipe.js","sourceRoot":"","sources":["../../../src/commands/recipes/oauth2.recipe.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export declare function applyWebSocketRecipe(basePath: string): Promise<void>;