@chrishdx/llm-dev-server 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 (184) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +164 -0
  3. package/backend/bin/llm-dev-server.js +3 -0
  4. package/backend/dist/cli.d.ts +15 -0
  5. package/backend/dist/cli.d.ts.map +1 -0
  6. package/backend/dist/cli.js +326 -0
  7. package/backend/dist/cli.js.map +1 -0
  8. package/backend/dist/config/database.d.ts +10 -0
  9. package/backend/dist/config/database.d.ts.map +1 -0
  10. package/backend/dist/config/database.js +61 -0
  11. package/backend/dist/config/database.js.map +1 -0
  12. package/backend/dist/config/environment.d.ts +20 -0
  13. package/backend/dist/config/environment.d.ts.map +1 -0
  14. package/backend/dist/config/environment.js +77 -0
  15. package/backend/dist/config/environment.js.map +1 -0
  16. package/backend/dist/controllers/AuthController.d.ts +18 -0
  17. package/backend/dist/controllers/AuthController.d.ts.map +1 -0
  18. package/backend/dist/controllers/AuthController.js +282 -0
  19. package/backend/dist/controllers/AuthController.js.map +1 -0
  20. package/backend/dist/controllers/ConversationController.d.ts +44 -0
  21. package/backend/dist/controllers/ConversationController.d.ts.map +1 -0
  22. package/backend/dist/controllers/ConversationController.js +193 -0
  23. package/backend/dist/controllers/ConversationController.js.map +1 -0
  24. package/backend/dist/controllers/JobController.d.ts +49 -0
  25. package/backend/dist/controllers/JobController.d.ts.map +1 -0
  26. package/backend/dist/controllers/JobController.js +227 -0
  27. package/backend/dist/controllers/JobController.js.map +1 -0
  28. package/backend/dist/index.d.ts +2 -0
  29. package/backend/dist/index.d.ts.map +1 -0
  30. package/backend/dist/index.js +160 -0
  31. package/backend/dist/index.js.map +1 -0
  32. package/backend/dist/middleware/auth.middleware.d.ts +25 -0
  33. package/backend/dist/middleware/auth.middleware.d.ts.map +1 -0
  34. package/backend/dist/middleware/auth.middleware.js +116 -0
  35. package/backend/dist/middleware/auth.middleware.js.map +1 -0
  36. package/backend/dist/middleware/authelia.middleware.d.ts +26 -0
  37. package/backend/dist/middleware/authelia.middleware.d.ts.map +1 -0
  38. package/backend/dist/middleware/authelia.middleware.js +165 -0
  39. package/backend/dist/middleware/authelia.middleware.js.map +1 -0
  40. package/backend/dist/middleware/error.middleware.d.ts +23 -0
  41. package/backend/dist/middleware/error.middleware.d.ts.map +1 -0
  42. package/backend/dist/middleware/error.middleware.js +59 -0
  43. package/backend/dist/middleware/error.middleware.js.map +1 -0
  44. package/backend/dist/models/AuthToken.d.ts +42 -0
  45. package/backend/dist/models/AuthToken.d.ts.map +1 -0
  46. package/backend/dist/models/AuthToken.js +97 -0
  47. package/backend/dist/models/AuthToken.js.map +1 -0
  48. package/backend/dist/models/Conversation.d.ts +36 -0
  49. package/backend/dist/models/Conversation.d.ts.map +1 -0
  50. package/backend/dist/models/Conversation.js +100 -0
  51. package/backend/dist/models/Conversation.js.map +1 -0
  52. package/backend/dist/models/FileOperation.d.ts +36 -0
  53. package/backend/dist/models/FileOperation.d.ts.map +1 -0
  54. package/backend/dist/models/FileOperation.js +117 -0
  55. package/backend/dist/models/FileOperation.js.map +1 -0
  56. package/backend/dist/models/Job.d.ts +48 -0
  57. package/backend/dist/models/Job.d.ts.map +1 -0
  58. package/backend/dist/models/Job.js +87 -0
  59. package/backend/dist/models/Job.js.map +1 -0
  60. package/backend/dist/models/Message.d.ts +38 -0
  61. package/backend/dist/models/Message.d.ts.map +1 -0
  62. package/backend/dist/models/Message.js +87 -0
  63. package/backend/dist/models/Message.js.map +1 -0
  64. package/backend/dist/models/User.d.ts +26 -0
  65. package/backend/dist/models/User.d.ts.map +1 -0
  66. package/backend/dist/models/User.js +67 -0
  67. package/backend/dist/models/User.js.map +1 -0
  68. package/backend/dist/models/index.d.ts +13 -0
  69. package/backend/dist/models/index.d.ts.map +1 -0
  70. package/backend/dist/models/index.js +24 -0
  71. package/backend/dist/models/index.js.map +1 -0
  72. package/backend/dist/routes/auth.routes.d.ts +3 -0
  73. package/backend/dist/routes/auth.routes.d.ts.map +1 -0
  74. package/backend/dist/routes/auth.routes.js +27 -0
  75. package/backend/dist/routes/auth.routes.js.map +1 -0
  76. package/backend/dist/routes/conversation.routes.d.ts +3 -0
  77. package/backend/dist/routes/conversation.routes.d.ts.map +1 -0
  78. package/backend/dist/routes/conversation.routes.js +17 -0
  79. package/backend/dist/routes/conversation.routes.js.map +1 -0
  80. package/backend/dist/routes/filesystem.routes.d.ts +3 -0
  81. package/backend/dist/routes/filesystem.routes.d.ts.map +1 -0
  82. package/backend/dist/routes/filesystem.routes.js +64 -0
  83. package/backend/dist/routes/filesystem.routes.js.map +1 -0
  84. package/backend/dist/routes/index.d.ts +3 -0
  85. package/backend/dist/routes/index.d.ts.map +1 -0
  86. package/backend/dist/routes/index.js +27 -0
  87. package/backend/dist/routes/index.js.map +1 -0
  88. package/backend/dist/routes/job.routes.d.ts +3 -0
  89. package/backend/dist/routes/job.routes.d.ts.map +1 -0
  90. package/backend/dist/routes/job.routes.js +18 -0
  91. package/backend/dist/routes/job.routes.js.map +1 -0
  92. package/backend/dist/services/auth/BaseAuthService.d.ts +49 -0
  93. package/backend/dist/services/auth/BaseAuthService.d.ts.map +1 -0
  94. package/backend/dist/services/auth/BaseAuthService.js +97 -0
  95. package/backend/dist/services/auth/BaseAuthService.js.map +1 -0
  96. package/backend/dist/services/auth/ClaudeAuthService.d.ts +69 -0
  97. package/backend/dist/services/auth/ClaudeAuthService.d.ts.map +1 -0
  98. package/backend/dist/services/auth/ClaudeAuthService.js +401 -0
  99. package/backend/dist/services/auth/ClaudeAuthService.js.map +1 -0
  100. package/backend/dist/services/auth/CodexAuthService.d.ts +37 -0
  101. package/backend/dist/services/auth/CodexAuthService.d.ts.map +1 -0
  102. package/backend/dist/services/auth/CodexAuthService.js +186 -0
  103. package/backend/dist/services/auth/CodexAuthService.js.map +1 -0
  104. package/backend/dist/services/auth/GeminiAuthService.d.ts +50 -0
  105. package/backend/dist/services/auth/GeminiAuthService.d.ts.map +1 -0
  106. package/backend/dist/services/auth/GeminiAuthService.js +284 -0
  107. package/backend/dist/services/auth/GeminiAuthService.js.map +1 -0
  108. package/backend/dist/services/auth/JwtService.d.ts +27 -0
  109. package/backend/dist/services/auth/JwtService.d.ts.map +1 -0
  110. package/backend/dist/services/auth/JwtService.js +65 -0
  111. package/backend/dist/services/auth/JwtService.js.map +1 -0
  112. package/backend/dist/services/auth/TokenRefreshService.d.ts +36 -0
  113. package/backend/dist/services/auth/TokenRefreshService.d.ts.map +1 -0
  114. package/backend/dist/services/auth/TokenRefreshService.js +178 -0
  115. package/backend/dist/services/auth/TokenRefreshService.js.map +1 -0
  116. package/backend/dist/services/conversation/ConversationService.d.ts +89 -0
  117. package/backend/dist/services/conversation/ConversationService.d.ts.map +1 -0
  118. package/backend/dist/services/conversation/ConversationService.js +255 -0
  119. package/backend/dist/services/conversation/ConversationService.js.map +1 -0
  120. package/backend/dist/services/job/JobService.d.ts +83 -0
  121. package/backend/dist/services/job/JobService.d.ts.map +1 -0
  122. package/backend/dist/services/job/JobService.js +213 -0
  123. package/backend/dist/services/job/JobService.js.map +1 -0
  124. package/backend/dist/services/job/WorkingDirectoryService.d.ts +73 -0
  125. package/backend/dist/services/job/WorkingDirectoryService.d.ts.map +1 -0
  126. package/backend/dist/services/job/WorkingDirectoryService.js +289 -0
  127. package/backend/dist/services/job/WorkingDirectoryService.js.map +1 -0
  128. package/backend/dist/services/llm/ClaudeProvider.d.ts +16 -0
  129. package/backend/dist/services/llm/ClaudeProvider.d.ts.map +1 -0
  130. package/backend/dist/services/llm/ClaudeProvider.js +229 -0
  131. package/backend/dist/services/llm/ClaudeProvider.js.map +1 -0
  132. package/backend/dist/services/llm/CodexProvider.d.ts +15 -0
  133. package/backend/dist/services/llm/CodexProvider.d.ts.map +1 -0
  134. package/backend/dist/services/llm/CodexProvider.js +301 -0
  135. package/backend/dist/services/llm/CodexProvider.js.map +1 -0
  136. package/backend/dist/services/llm/GeminiProvider.d.ts +17 -0
  137. package/backend/dist/services/llm/GeminiProvider.d.ts.map +1 -0
  138. package/backend/dist/services/llm/GeminiProvider.js +190 -0
  139. package/backend/dist/services/llm/GeminiProvider.js.map +1 -0
  140. package/backend/dist/services/llm/LLMProviderBase.d.ts +76 -0
  141. package/backend/dist/services/llm/LLMProviderBase.d.ts.map +1 -0
  142. package/backend/dist/services/llm/LLMProviderBase.js +34 -0
  143. package/backend/dist/services/llm/LLMProviderBase.js.map +1 -0
  144. package/backend/dist/services/llm/ProviderFactory.d.ts +17 -0
  145. package/backend/dist/services/llm/ProviderFactory.d.ts.map +1 -0
  146. package/backend/dist/services/llm/ProviderFactory.js +58 -0
  147. package/backend/dist/services/llm/ProviderFactory.js.map +1 -0
  148. package/backend/dist/utils/crypto.d.ts +33 -0
  149. package/backend/dist/utils/crypto.d.ts.map +1 -0
  150. package/backend/dist/utils/crypto.js +165 -0
  151. package/backend/dist/utils/crypto.js.map +1 -0
  152. package/backend/dist/utils/logger.d.ts +4 -0
  153. package/backend/dist/utils/logger.d.ts.map +1 -0
  154. package/backend/dist/utils/logger.js +44 -0
  155. package/backend/dist/utils/logger.js.map +1 -0
  156. package/backend/dist/utils/validators.d.ts +22 -0
  157. package/backend/dist/utils/validators.d.ts.map +1 -0
  158. package/backend/dist/utils/validators.js +127 -0
  159. package/backend/dist/utils/validators.js.map +1 -0
  160. package/backend/package.json +45 -0
  161. package/backend/public/assets/index-C207-KqP.js +188 -0
  162. package/backend/public/index.html +12 -0
  163. package/package.json +96 -0
  164. package/shared/dist/index.d.ts +5 -0
  165. package/shared/dist/index.d.ts.map +1 -0
  166. package/shared/dist/index.js +25 -0
  167. package/shared/dist/index.js.map +1 -0
  168. package/shared/dist/types/api.d.ts +27 -0
  169. package/shared/dist/types/api.d.ts.map +1 -0
  170. package/shared/dist/types/api.js +3 -0
  171. package/shared/dist/types/api.js.map +1 -0
  172. package/shared/dist/types/auth.d.ts +62 -0
  173. package/shared/dist/types/auth.d.ts.map +1 -0
  174. package/shared/dist/types/auth.js +3 -0
  175. package/shared/dist/types/auth.js.map +1 -0
  176. package/shared/dist/types/conversation.d.ts +98 -0
  177. package/shared/dist/types/conversation.d.ts.map +1 -0
  178. package/shared/dist/types/conversation.js +3 -0
  179. package/shared/dist/types/conversation.js.map +1 -0
  180. package/shared/dist/types/job.d.ts +93 -0
  181. package/shared/dist/types/job.d.ts.map +1 -0
  182. package/shared/dist/types/job.js +3 -0
  183. package/shared/dist/types/job.js.map +1 -0
  184. package/shared/package.json +15 -0
@@ -0,0 +1,50 @@
1
+ import { BaseAuthService } from './BaseAuthService';
2
+ import { AuthToken } from '../../models';
3
+ export declare class GeminiAuthService extends BaseAuthService {
4
+ private geminiHome;
5
+ constructor();
6
+ /**
7
+ * Start Gemini OAuth login flow
8
+ */
9
+ startLogin(): Promise<{
10
+ loginUrl: string;
11
+ sessionId: string;
12
+ state: string;
13
+ }>;
14
+ /**
15
+ * Complete Gemini OAuth login flow
16
+ */
17
+ completeLogin(params: {
18
+ sessionId: string;
19
+ code: string;
20
+ state: string;
21
+ }): Promise<AuthToken>;
22
+ /**
23
+ * Load credentials from file on server startup
24
+ */
25
+ loadFromFile(): Promise<AuthToken | null>;
26
+ /**
27
+ * Get current authentication status
28
+ */
29
+ getStatus(): Promise<{
30
+ loggedIn: boolean;
31
+ tokenId?: string;
32
+ email?: string;
33
+ expiresAt?: Date;
34
+ }>;
35
+ /**
36
+ * Start Gemini OAuth login flow with manual code redirect (for remote clients)
37
+ * Uses Google's special redirect URI that displays the code to the user
38
+ */
39
+ startLoginWithRedirect(_redirectUri: string): Promise<{
40
+ loginUrl: string;
41
+ state: string;
42
+ }>;
43
+ /**
44
+ * Complete Gemini OAuth login from manual code (for remote clients)
45
+ * User provides the authorization code shown by Google
46
+ */
47
+ completeLoginFromCallback(code: string, state: string): Promise<AuthToken>;
48
+ }
49
+ export default GeminiAuthService;
50
+ //# sourceMappingURL=GeminiAuthService.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GeminiAuthService.d.ts","sourceRoot":"","sources":["../../../src/services/auth/GeminiAuthService.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAazC,qBAAa,iBAAkB,SAAQ,eAAe;IACpD,OAAO,CAAC,UAAU,CAAS;;IAO3B;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC;QAC1B,QAAQ,EAAE,MAAM,CAAC;QACjB,SAAS,EAAE,MAAM,CAAC;QAClB,KAAK,EAAE,MAAM,CAAC;KACf,CAAC;IAwCF;;OAEG;IACG,aAAa,CAAC,MAAM,EAAE;QAC1B,SAAS,EAAE,MAAM,CAAC;QAClB,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,EAAE,MAAM,CAAC;KACf,GAAG,OAAO,CAAC,SAAS,CAAC;IAoFtB;;OAEG;IACG,YAAY,IAAI,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC;IA0C/C;;OAEG;IACG,SAAS,IAAI,OAAO,CAAC;QACzB,QAAQ,EAAE,OAAO,CAAC;QAClB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,SAAS,CAAC,EAAE,IAAI,CAAC;KAClB,CAAC;IAeF;;;OAGG;IACG,sBAAsB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC;QAC1D,QAAQ,EAAE,MAAM,CAAC;QACjB,KAAK,EAAE,MAAM,CAAC;KACf,CAAC;IAwCF;;;OAGG;IACG,yBAAyB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC;CAmFjF;AAED,eAAe,iBAAiB,CAAC"}
@@ -0,0 +1,284 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.GeminiAuthService = void 0;
7
+ const path_1 = __importDefault(require("path"));
8
+ const promises_1 = __importDefault(require("fs/promises"));
9
+ const crypto_1 = __importDefault(require("crypto"));
10
+ const google_auth_library_1 = require("google-auth-library");
11
+ const BaseAuthService_1 = require("./BaseAuthService");
12
+ const models_1 = require("../../models");
13
+ const crypto_2 = require("../../utils/crypto");
14
+ const environment_1 = __importDefault(require("../../config/environment"));
15
+ const logger_1 = __importDefault(require("../../utils/logger"));
16
+ const GEMINI_CLIENT_ID = '681255809395-oo8ft2oprdrnp9e3aqf6av3hmdib135j.apps.googleusercontent.com';
17
+ const GEMINI_CLIENT_SECRET = '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';
18
+ const GEMINI_SCOPES = [
19
+ 'https://www.googleapis.com/auth/cloud-platform',
20
+ 'https://www.googleapis.com/auth/userinfo.email',
21
+ ];
22
+ class GeminiAuthService extends BaseAuthService_1.BaseAuthService {
23
+ constructor() {
24
+ super('gemini');
25
+ this.geminiHome = path_1.default.join(environment_1.default.DATA_DIR, 'gemini');
26
+ }
27
+ /**
28
+ * Start Gemini OAuth login flow
29
+ */
30
+ async startLogin() {
31
+ const codeVerifier = (0, crypto_2.generateCodeVerifier)();
32
+ const codeChallenge = (0, crypto_2.generateCodeChallenge)(codeVerifier);
33
+ const state = crypto_1.default.randomUUID();
34
+ const redirectUri = 'http://localhost:3000/oauth/callback';
35
+ const oauth2Client = new google_auth_library_1.OAuth2Client({
36
+ clientId: GEMINI_CLIENT_ID,
37
+ clientSecret: GEMINI_CLIENT_SECRET,
38
+ redirectUri,
39
+ });
40
+ const authorizeUrl = oauth2Client.generateAuthUrl({
41
+ access_type: 'offline',
42
+ scope: GEMINI_SCOPES,
43
+ state,
44
+ code_challenge: codeChallenge,
45
+ code_challenge_method: google_auth_library_1.CodeChallengeMethod.S256,
46
+ });
47
+ const sessionId = crypto_1.default.randomUUID();
48
+ await this.storeLoginSession({
49
+ sessionId,
50
+ state,
51
+ codeVerifier: this.encrypt(codeVerifier),
52
+ provider: 'gemini',
53
+ redirectUri,
54
+ expiresAt: new Date(Date.now() + 15 * 60 * 1000),
55
+ });
56
+ logger_1.default.info('Gemini OAuth login started', { sessionId });
57
+ return {
58
+ loginUrl: authorizeUrl,
59
+ sessionId,
60
+ state,
61
+ };
62
+ }
63
+ /**
64
+ * Complete Gemini OAuth login flow
65
+ */
66
+ async completeLogin(params) {
67
+ // Validate session
68
+ const session = await this.getLoginSession(params.sessionId);
69
+ if (!session || session.state !== params.state) {
70
+ throw new Error('Invalid OAuth state');
71
+ }
72
+ const codeVerifier = this.decrypt(session.codeVerifier);
73
+ const oauth2Client = new google_auth_library_1.OAuth2Client({
74
+ clientId: GEMINI_CLIENT_ID,
75
+ clientSecret: GEMINI_CLIENT_SECRET,
76
+ redirectUri: session.redirectUri || 'http://localhost:3000/oauth/callback',
77
+ });
78
+ // Exchange code for tokens
79
+ const { tokens } = await oauth2Client.getToken({
80
+ code: params.code,
81
+ codeVerifier,
82
+ });
83
+ // Fetch user info
84
+ oauth2Client.setCredentials(tokens);
85
+ const userInfo = await oauth2Client.request({
86
+ url: 'https://www.googleapis.com/oauth2/v2/userinfo',
87
+ });
88
+ const email = userInfo.data.email;
89
+ // 1. Create directory structure
90
+ await promises_1.default.mkdir(this.geminiHome, { recursive: true, mode: 0o700 });
91
+ // 2. Write oauth_creds.json (like native Gemini CLI)
92
+ const credsPath = path_1.default.join(this.geminiHome, 'oauth_creds.json');
93
+ const credsData = {
94
+ type: 'authorized_user',
95
+ client_id: GEMINI_CLIENT_ID,
96
+ client_secret: GEMINI_CLIENT_SECRET,
97
+ refresh_token: tokens.refresh_token,
98
+ token: tokens.access_token,
99
+ expiry_date: tokens.expiry_date,
100
+ };
101
+ await promises_1.default.writeFile(credsPath, JSON.stringify(credsData, null, 2), { encoding: 'utf8', mode: 0o600 });
102
+ // 3. Write google_accounts.json
103
+ const accountsPath = path_1.default.join(this.geminiHome, 'google_accounts.json');
104
+ const accountsData = {
105
+ active_account: email,
106
+ };
107
+ await promises_1.default.writeFile(accountsPath, JSON.stringify(accountsData, null, 2), { encoding: 'utf8', mode: 0o600 });
108
+ logger_1.default.info('Gemini credentials written to file');
109
+ // 4. Store in database
110
+ const authToken = await models_1.AuthToken.create({
111
+ provider: 'gemini',
112
+ accessToken: this.encrypt(tokens.access_token),
113
+ refreshToken: tokens.refresh_token ? this.encrypt(tokens.refresh_token) : undefined,
114
+ tokenType: tokens.token_type || 'Bearer',
115
+ expiresAt: tokens.expiry_date ? new Date(tokens.expiry_date) : undefined,
116
+ issuedAt: new Date(),
117
+ scopes: tokens.scope?.split(' '),
118
+ email,
119
+ isActive: true,
120
+ });
121
+ // Cleanup session
122
+ await this.deleteLoginSession(params.sessionId);
123
+ logger_1.default.info('Gemini OAuth login completed', { tokenId: authToken.id });
124
+ return authToken;
125
+ }
126
+ /**
127
+ * Load credentials from file on server startup
128
+ */
129
+ async loadFromFile() {
130
+ const credsPath = path_1.default.join(this.geminiHome, 'oauth_creds.json');
131
+ try {
132
+ const content = await promises_1.default.readFile(credsPath, 'utf8');
133
+ const creds = JSON.parse(content);
134
+ // Check if already in database
135
+ let authToken = await models_1.AuthToken.findOne({
136
+ where: { provider: 'gemini', isActive: true },
137
+ });
138
+ if (!authToken) {
139
+ // Read email from google_accounts.json
140
+ const accountsPath = path_1.default.join(this.geminiHome, 'google_accounts.json');
141
+ const accountsContent = await promises_1.default.readFile(accountsPath, 'utf8');
142
+ const accounts = JSON.parse(accountsContent);
143
+ // Create from file
144
+ authToken = await models_1.AuthToken.create({
145
+ provider: 'gemini',
146
+ accessToken: this.encrypt(creds.token),
147
+ refreshToken: creds.refresh_token ? this.encrypt(creds.refresh_token) : undefined,
148
+ tokenType: 'Bearer',
149
+ expiresAt: creds.expiry_date ? new Date(creds.expiry_date) : undefined,
150
+ issuedAt: new Date(),
151
+ email: accounts.active_account,
152
+ isActive: true,
153
+ });
154
+ logger_1.default.info('Gemini credentials loaded from file and synced to database');
155
+ }
156
+ return authToken;
157
+ }
158
+ catch (error) {
159
+ if (error instanceof Error && error.code !== 'ENOENT') {
160
+ logger_1.default.warn('Failed to load Gemini credentials from file:', error.message);
161
+ }
162
+ return null;
163
+ }
164
+ }
165
+ /**
166
+ * Get current authentication status
167
+ */
168
+ async getStatus() {
169
+ const token = await this.getActiveToken();
170
+ if (!token) {
171
+ return { loggedIn: false };
172
+ }
173
+ return {
174
+ loggedIn: true,
175
+ tokenId: token.id,
176
+ email: token.email,
177
+ expiresAt: token.expiresAt,
178
+ };
179
+ }
180
+ /**
181
+ * Start Gemini OAuth login flow with manual code redirect (for remote clients)
182
+ * Uses Google's special redirect URI that displays the code to the user
183
+ */
184
+ async startLoginWithRedirect(_redirectUri) {
185
+ // Use Google's special manual code redirect URI
186
+ const manualRedirectUri = 'https://codeassist.google.com/authcode';
187
+ const codeVerifier = (0, crypto_2.generateCodeVerifier)();
188
+ const codeChallenge = (0, crypto_2.generateCodeChallenge)(codeVerifier);
189
+ const state = crypto_1.default.randomUUID();
190
+ const oauth2Client = new google_auth_library_1.OAuth2Client({
191
+ clientId: GEMINI_CLIENT_ID,
192
+ clientSecret: GEMINI_CLIENT_SECRET,
193
+ redirectUri: manualRedirectUri,
194
+ });
195
+ const authorizeUrl = oauth2Client.generateAuthUrl({
196
+ access_type: 'offline',
197
+ scope: GEMINI_SCOPES,
198
+ state,
199
+ code_challenge: codeChallenge,
200
+ code_challenge_method: google_auth_library_1.CodeChallengeMethod.S256,
201
+ });
202
+ // Store session with state as sessionId for retrieval
203
+ await this.storeLoginSession({
204
+ sessionId: state,
205
+ state,
206
+ codeVerifier: this.encrypt(codeVerifier),
207
+ provider: 'gemini',
208
+ redirectUri: manualRedirectUri,
209
+ expiresAt: new Date(Date.now() + 15 * 60 * 1000),
210
+ });
211
+ logger_1.default.info('Gemini OAuth manual code flow started', { state });
212
+ return {
213
+ loginUrl: authorizeUrl,
214
+ state,
215
+ };
216
+ }
217
+ /**
218
+ * Complete Gemini OAuth login from manual code (for remote clients)
219
+ * User provides the authorization code shown by Google
220
+ */
221
+ async completeLoginFromCallback(code, state) {
222
+ // Validate session
223
+ const session = await this.getLoginSession(state);
224
+ if (!session || session.state !== state) {
225
+ throw new Error('Invalid OAuth state');
226
+ }
227
+ const codeVerifier = this.decrypt(session.codeVerifier);
228
+ const oauth2Client = new google_auth_library_1.OAuth2Client({
229
+ clientId: GEMINI_CLIENT_ID,
230
+ clientSecret: GEMINI_CLIENT_SECRET,
231
+ redirectUri: session.redirectUri || 'https://codeassist.google.com/authcode',
232
+ });
233
+ // Exchange code for tokens
234
+ const { tokens } = await oauth2Client.getToken({
235
+ code,
236
+ codeVerifier,
237
+ });
238
+ // Fetch user info
239
+ oauth2Client.setCredentials(tokens);
240
+ const userInfo = await oauth2Client.request({
241
+ url: 'https://www.googleapis.com/oauth2/v2/userinfo',
242
+ });
243
+ const email = userInfo.data.email;
244
+ // 1. Create directory structure
245
+ await promises_1.default.mkdir(this.geminiHome, { recursive: true, mode: 0o700 });
246
+ // 2. Write oauth_creds.json (like native Gemini CLI)
247
+ const credsPath = path_1.default.join(this.geminiHome, 'oauth_creds.json');
248
+ const credsData = {
249
+ type: 'authorized_user',
250
+ client_id: GEMINI_CLIENT_ID,
251
+ client_secret: GEMINI_CLIENT_SECRET,
252
+ refresh_token: tokens.refresh_token,
253
+ token: tokens.access_token,
254
+ expiry_date: tokens.expiry_date,
255
+ };
256
+ await promises_1.default.writeFile(credsPath, JSON.stringify(credsData, null, 2), { encoding: 'utf8', mode: 0o600 });
257
+ // 3. Write google_accounts.json
258
+ const accountsPath = path_1.default.join(this.geminiHome, 'google_accounts.json');
259
+ const accountsData = {
260
+ active_account: email,
261
+ };
262
+ await promises_1.default.writeFile(accountsPath, JSON.stringify(accountsData, null, 2), { encoding: 'utf8', mode: 0o600 });
263
+ logger_1.default.info('Gemini credentials written to file');
264
+ // 4. Store in database
265
+ const authToken = await models_1.AuthToken.create({
266
+ provider: 'gemini',
267
+ accessToken: this.encrypt(tokens.access_token),
268
+ refreshToken: tokens.refresh_token ? this.encrypt(tokens.refresh_token) : undefined,
269
+ tokenType: tokens.token_type || 'Bearer',
270
+ expiresAt: tokens.expiry_date ? new Date(tokens.expiry_date) : undefined,
271
+ issuedAt: new Date(),
272
+ scopes: tokens.scope?.split(' '),
273
+ email,
274
+ isActive: true,
275
+ });
276
+ // Cleanup session
277
+ await this.deleteLoginSession(state);
278
+ logger_1.default.info('Gemini OAuth manual code flow completed', { tokenId: authToken.id });
279
+ return authToken;
280
+ }
281
+ }
282
+ exports.GeminiAuthService = GeminiAuthService;
283
+ exports.default = GeminiAuthService;
284
+ //# sourceMappingURL=GeminiAuthService.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GeminiAuthService.js","sourceRoot":"","sources":["../../../src/services/auth/GeminiAuthService.ts"],"names":[],"mappings":";;;;;;AAAA,gDAAwB;AACxB,2DAA6B;AAC7B,oDAA4B;AAC5B,6DAAwE;AACxE,uDAAoD;AACpD,yCAAyC;AACzC,+CAAiF;AACjF,2EAA8C;AAC9C,gEAAwC;AAExC,MAAM,gBAAgB,GACpB,0EAA0E,CAAC;AAC7E,MAAM,oBAAoB,GAAG,qCAAqC,CAAC;AACnE,MAAM,aAAa,GAAG;IACpB,gDAAgD;IAChD,gDAAgD;CACjD,CAAC;AAEF,MAAa,iBAAkB,SAAQ,iCAAe;IAGpD;QACE,KAAK,CAAC,QAAQ,CAAC,CAAC;QAChB,IAAI,CAAC,UAAU,GAAG,cAAI,CAAC,IAAI,CAAC,qBAAM,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;IACzD,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,UAAU;QAKd,MAAM,YAAY,GAAG,IAAA,6BAAoB,GAAE,CAAC;QAC5C,MAAM,aAAa,GAAG,IAAA,8BAAqB,EAAC,YAAY,CAAC,CAAC;QAC1D,MAAM,KAAK,GAAG,gBAAM,CAAC,UAAU,EAAE,CAAC;QAElC,MAAM,WAAW,GAAG,sCAAsC,CAAC;QAE3D,MAAM,YAAY,GAAG,IAAI,kCAAY,CAAC;YACpC,QAAQ,EAAE,gBAAgB;YAC1B,YAAY,EAAE,oBAAoB;YAClC,WAAW;SACZ,CAAC,CAAC;QAEH,MAAM,YAAY,GAAG,YAAY,CAAC,eAAe,CAAC;YAChD,WAAW,EAAE,SAAS;YACtB,KAAK,EAAE,aAAa;YACpB,KAAK;YACL,cAAc,EAAE,aAAa;YAC7B,qBAAqB,EAAE,yCAAmB,CAAC,IAAI;SAChD,CAAC,CAAC;QAEH,MAAM,SAAS,GAAG,gBAAM,CAAC,UAAU,EAAE,CAAC;QACtC,MAAM,IAAI,CAAC,iBAAiB,CAAC;YAC3B,SAAS;YACT,KAAK;YACL,YAAY,EAAE,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC;YACxC,QAAQ,EAAE,QAAQ;YAClB,WAAW;YACX,SAAS,EAAE,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;SACjD,CAAC,CAAC;QAEH,gBAAM,CAAC,IAAI,CAAC,4BAA4B,EAAE,EAAE,SAAS,EAAE,CAAC,CAAC;QAEzD,OAAO;YACL,QAAQ,EAAE,YAAY;YACtB,SAAS;YACT,KAAK;SACN,CAAC;IACJ,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,aAAa,CAAC,MAInB;QACC,mBAAmB;QACnB,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QAC7D,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,KAAK,KAAK,MAAM,CAAC,KAAK,EAAE,CAAC;YAC/C,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAC;QACzC,CAAC;QAED,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;QAExD,MAAM,YAAY,GAAG,IAAI,kCAAY,CAAC;YACpC,QAAQ,EAAE,gBAAgB;YAC1B,YAAY,EAAE,oBAAoB;YAClC,WAAW,EAAE,OAAO,CAAC,WAAW,IAAI,sCAAsC;SAC3E,CAAC,CAAC;QAEH,2BAA2B;QAC3B,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,YAAY,CAAC,QAAQ,CAAC;YAC7C,IAAI,EAAE,MAAM,CAAC,IAAI;YACjB,YAAY;SACb,CAAC,CAAC;QAEH,kBAAkB;QAClB,YAAY,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;QACpC,MAAM,QAAQ,GAAG,MAAM,YAAY,CAAC,OAAO,CAAC;YAC1C,GAAG,EAAE,+CAA+C;SACrD,CAAC,CAAC;QAEH,MAAM,KAAK,GAAI,QAAQ,CAAC,IAAY,CAAC,KAAK,CAAC;QAE3C,gCAAgC;QAChC,MAAM,kBAAE,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QAElE,qDAAqD;QACrD,MAAM,SAAS,GAAG,cAAI,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,kBAAkB,CAAC,CAAC;QACjE,MAAM,SAAS,GAAG;YAChB,IAAI,EAAE,iBAAiB;YACvB,SAAS,EAAE,gBAAgB;YAC3B,aAAa,EAAE,oBAAoB;YACnC,aAAa,EAAE,MAAM,CAAC,aAAa;YACnC,KAAK,EAAE,MAAM,CAAC,YAAY;YAC1B,WAAW,EAAE,MAAM,CAAC,WAAW;SAChC,CAAC;QAEF,MAAM,kBAAE,CAAC,SAAS,CAChB,SAAS,EACT,IAAI,CAAC,SAAS,CAAC,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC,EAClC,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,CAClC,CAAC;QAEF,gCAAgC;QAChC,MAAM,YAAY,GAAG,cAAI,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,sBAAsB,CAAC,CAAC;QACxE,MAAM,YAAY,GAAG;YACnB,cAAc,EAAE,KAAK;SACtB,CAAC;QAEF,MAAM,kBAAE,CAAC,SAAS,CAChB,YAAY,EACZ,IAAI,CAAC,SAAS,CAAC,YAAY,EAAE,IAAI,EAAE,CAAC,CAAC,EACrC,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,CAClC,CAAC;QAEF,gBAAM,CAAC,IAAI,CAAC,oCAAoC,CAAC,CAAC;QAElD,uBAAuB;QACvB,MAAM,SAAS,GAAG,MAAM,kBAAS,CAAC,MAAM,CAAC;YACvC,QAAQ,EAAE,QAAQ;YAClB,WAAW,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,YAAa,CAAC;YAC/C,YAAY,EAAE,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,SAAS;YACnF,SAAS,EAAE,MAAM,CAAC,UAAU,IAAI,QAAQ;YACxC,SAAS,EAAE,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,SAAS;YACxE,QAAQ,EAAE,IAAI,IAAI,EAAE;YACpB,MAAM,EAAE,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC;YAChC,KAAK;YACL,QAAQ,EAAE,IAAI;SACf,CAAC,CAAC;QAEH,kBAAkB;QAClB,MAAM,IAAI,CAAC,kBAAkB,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QAEhD,gBAAM,CAAC,IAAI,CAAC,8BAA8B,EAAE,EAAE,OAAO,EAAE,SAAS,CAAC,EAAE,EAAE,CAAC,CAAC;QAEvE,OAAO,SAAS,CAAC;IACnB,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,YAAY;QAChB,MAAM,SAAS,GAAG,cAAI,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,kBAAkB,CAAC,CAAC;QAEjE,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,MAAM,kBAAE,CAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;YACrD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YAElC,+BAA+B;YAC/B,IAAI,SAAS,GAAG,MAAM,kBAAS,CAAC,OAAO,CAAC;gBACtC,KAAK,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE;aAC9C,CAAC,CAAC;YAEH,IAAI,CAAC,SAAS,EAAE,CAAC;gBACf,uCAAuC;gBACvC,MAAM,YAAY,GAAG,cAAI,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,sBAAsB,CAAC,CAAC;gBACxE,MAAM,eAAe,GAAG,MAAM,kBAAE,CAAC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;gBAChE,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC;gBAE7C,mBAAmB;gBACnB,SAAS,GAAG,MAAM,kBAAS,CAAC,MAAM,CAAC;oBACjC,QAAQ,EAAE,QAAQ;oBAClB,WAAW,EAAE,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC;oBACtC,YAAY,EAAE,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,SAAS;oBACjF,SAAS,EAAE,QAAQ;oBACnB,SAAS,EAAE,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,SAAS;oBACtE,QAAQ,EAAE,IAAI,IAAI,EAAE;oBACpB,KAAK,EAAE,QAAQ,CAAC,cAAc;oBAC9B,QAAQ,EAAE,IAAI;iBACf,CAAC,CAAC;gBAEH,gBAAM,CAAC,IAAI,CAAC,4DAA4D,CAAC,CAAC;YAC5E,CAAC;YAED,OAAO,SAAS,CAAC;QACnB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,KAAK,YAAY,KAAK,IAAK,KAAa,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBAC/D,gBAAM,CAAC,IAAI,CAAC,8CAA8C,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;YAC7E,CAAC;YACD,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,SAAS;QAMb,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,cAAc,EAAE,CAAC;QAE1C,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;QAC7B,CAAC;QAED,OAAO;YACL,QAAQ,EAAE,IAAI;YACd,OAAO,EAAE,KAAK,CAAC,EAAE;YACjB,KAAK,EAAE,KAAK,CAAC,KAAK;YAClB,SAAS,EAAE,KAAK,CAAC,SAAS;SAC3B,CAAC;IACJ,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,sBAAsB,CAAC,YAAoB;QAI/C,gDAAgD;QAChD,MAAM,iBAAiB,GAAG,wCAAwC,CAAC;QAEnE,MAAM,YAAY,GAAG,IAAA,6BAAoB,GAAE,CAAC;QAC5C,MAAM,aAAa,GAAG,IAAA,8BAAqB,EAAC,YAAY,CAAC,CAAC;QAC1D,MAAM,KAAK,GAAG,gBAAM,CAAC,UAAU,EAAE,CAAC;QAElC,MAAM,YAAY,GAAG,IAAI,kCAAY,CAAC;YACpC,QAAQ,EAAE,gBAAgB;YAC1B,YAAY,EAAE,oBAAoB;YAClC,WAAW,EAAE,iBAAiB;SAC/B,CAAC,CAAC;QAEH,MAAM,YAAY,GAAG,YAAY,CAAC,eAAe,CAAC;YAChD,WAAW,EAAE,SAAS;YACtB,KAAK,EAAE,aAAa;YACpB,KAAK;YACL,cAAc,EAAE,aAAa;YAC7B,qBAAqB,EAAE,yCAAmB,CAAC,IAAI;SAChD,CAAC,CAAC;QAEH,sDAAsD;QACtD,MAAM,IAAI,CAAC,iBAAiB,CAAC;YAC3B,SAAS,EAAE,KAAK;YAChB,KAAK;YACL,YAAY,EAAE,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC;YACxC,QAAQ,EAAE,QAAQ;YAClB,WAAW,EAAE,iBAAiB;YAC9B,SAAS,EAAE,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;SACjD,CAAC,CAAC;QAEH,gBAAM,CAAC,IAAI,CAAC,uCAAuC,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;QAEhE,OAAO;YACL,QAAQ,EAAE,YAAY;YACtB,KAAK;SACN,CAAC;IACJ,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,yBAAyB,CAAC,IAAY,EAAE,KAAa;QACzD,mBAAmB;QACnB,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC;QAClD,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,KAAK,KAAK,KAAK,EAAE,CAAC;YACxC,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAC;QACzC,CAAC;QAED,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;QAExD,MAAM,YAAY,GAAG,IAAI,kCAAY,CAAC;YACpC,QAAQ,EAAE,gBAAgB;YAC1B,YAAY,EAAE,oBAAoB;YAClC,WAAW,EAAE,OAAO,CAAC,WAAW,IAAI,wCAAwC;SAC7E,CAAC,CAAC;QAEH,2BAA2B;QAC3B,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,YAAY,CAAC,QAAQ,CAAC;YAC7C,IAAI;YACJ,YAAY;SACb,CAAC,CAAC;QAEH,kBAAkB;QAClB,YAAY,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;QACpC,MAAM,QAAQ,GAAG,MAAM,YAAY,CAAC,OAAO,CAAC;YAC1C,GAAG,EAAE,+CAA+C;SACrD,CAAC,CAAC;QAEH,MAAM,KAAK,GAAI,QAAQ,CAAC,IAAY,CAAC,KAAK,CAAC;QAE3C,gCAAgC;QAChC,MAAM,kBAAE,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QAElE,qDAAqD;QACrD,MAAM,SAAS,GAAG,cAAI,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,kBAAkB,CAAC,CAAC;QACjE,MAAM,SAAS,GAAG;YAChB,IAAI,EAAE,iBAAiB;YACvB,SAAS,EAAE,gBAAgB;YAC3B,aAAa,EAAE,oBAAoB;YACnC,aAAa,EAAE,MAAM,CAAC,aAAa;YACnC,KAAK,EAAE,MAAM,CAAC,YAAY;YAC1B,WAAW,EAAE,MAAM,CAAC,WAAW;SAChC,CAAC;QAEF,MAAM,kBAAE,CAAC,SAAS,CAChB,SAAS,EACT,IAAI,CAAC,SAAS,CAAC,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC,EAClC,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,CAClC,CAAC;QAEF,gCAAgC;QAChC,MAAM,YAAY,GAAG,cAAI,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,sBAAsB,CAAC,CAAC;QACxE,MAAM,YAAY,GAAG;YACnB,cAAc,EAAE,KAAK;SACtB,CAAC;QAEF,MAAM,kBAAE,CAAC,SAAS,CAChB,YAAY,EACZ,IAAI,CAAC,SAAS,CAAC,YAAY,EAAE,IAAI,EAAE,CAAC,CAAC,EACrC,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,CAClC,CAAC;QAEF,gBAAM,CAAC,IAAI,CAAC,oCAAoC,CAAC,CAAC;QAElD,uBAAuB;QACvB,MAAM,SAAS,GAAG,MAAM,kBAAS,CAAC,MAAM,CAAC;YACvC,QAAQ,EAAE,QAAQ;YAClB,WAAW,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,YAAa,CAAC;YAC/C,YAAY,EAAE,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,SAAS;YACnF,SAAS,EAAE,MAAM,CAAC,UAAU,IAAI,QAAQ;YACxC,SAAS,EAAE,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,SAAS;YACxE,QAAQ,EAAE,IAAI,IAAI,EAAE;YACpB,MAAM,EAAE,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC;YAChC,KAAK;YACL,QAAQ,EAAE,IAAI;SACf,CAAC,CAAC;QAEH,kBAAkB;QAClB,MAAM,IAAI,CAAC,kBAAkB,CAAC,KAAK,CAAC,CAAC;QAErC,gBAAM,CAAC,IAAI,CAAC,yCAAyC,EAAE,EAAE,OAAO,EAAE,SAAS,CAAC,EAAE,EAAE,CAAC,CAAC;QAElF,OAAO,SAAS,CAAC;IACnB,CAAC;CACF;AA5VD,8CA4VC;AAED,kBAAe,iBAAiB,CAAC"}
@@ -0,0 +1,27 @@
1
+ import { User } from '../../models';
2
+ export interface JwtPayload {
3
+ userId: string;
4
+ username: string;
5
+ role: 'admin' | 'user';
6
+ }
7
+ export declare class JwtService {
8
+ private static readonly EXPIRES_IN;
9
+ /**
10
+ * Generate JWT token for a user
11
+ */
12
+ static generateToken(user: User): string;
13
+ /**
14
+ * Verify and decode JWT token
15
+ */
16
+ static verifyToken(token: string): JwtPayload;
17
+ /**
18
+ * Decode token without verification (for debugging)
19
+ */
20
+ static decodeToken(token: string): JwtPayload | null;
21
+ /**
22
+ * Get token expiration time in seconds
23
+ */
24
+ static getExpiresIn(): number;
25
+ }
26
+ export default JwtService;
27
+ //# sourceMappingURL=JwtService.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"JwtService.d.ts","sourceRoot":"","sources":["../../../src/services/auth/JwtService.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAEpC,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,OAAO,GAAG,MAAM,CAAC;CACxB;AAED,qBAAa,UAAU;IACrB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAS;IAE3C;;OAEG;IACH,MAAM,CAAC,aAAa,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM;IAYxC;;OAEG;IACH,MAAM,CAAC,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU;IAe7C;;OAEG;IACH,MAAM,CAAC,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI;IAQpD;;OAEG;IACH,MAAM,CAAC,YAAY,IAAI,MAAM;CAK9B;AAED,eAAe,UAAU,CAAC"}
@@ -0,0 +1,65 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.JwtService = void 0;
7
+ const jsonwebtoken_1 = __importDefault(require("jsonwebtoken"));
8
+ const environment_1 = __importDefault(require("../../config/environment"));
9
+ class JwtService {
10
+ /**
11
+ * Generate JWT token for a user
12
+ */
13
+ static generateToken(user) {
14
+ const payload = {
15
+ userId: user.id,
16
+ username: user.username,
17
+ role: user.role,
18
+ };
19
+ return jsonwebtoken_1.default.sign(payload, environment_1.default.JWT_SECRET, {
20
+ expiresIn: this.EXPIRES_IN,
21
+ });
22
+ }
23
+ /**
24
+ * Verify and decode JWT token
25
+ */
26
+ static verifyToken(token) {
27
+ try {
28
+ return jsonwebtoken_1.default.verify(token, environment_1.default.JWT_SECRET);
29
+ }
30
+ catch (error) {
31
+ if (error instanceof Error) {
32
+ if (error.name === 'TokenExpiredError') {
33
+ throw new Error('Token has expired');
34
+ }
35
+ else if (error.name === 'JsonWebTokenError') {
36
+ throw new Error('Invalid token');
37
+ }
38
+ }
39
+ throw error;
40
+ }
41
+ }
42
+ /**
43
+ * Decode token without verification (for debugging)
44
+ */
45
+ static decodeToken(token) {
46
+ try {
47
+ return jsonwebtoken_1.default.decode(token);
48
+ }
49
+ catch (error) {
50
+ return null;
51
+ }
52
+ }
53
+ /**
54
+ * Get token expiration time in seconds
55
+ */
56
+ static getExpiresIn() {
57
+ // Convert '24h' to seconds
58
+ const hours = parseInt(this.EXPIRES_IN.replace('h', ''));
59
+ return hours * 60 * 60;
60
+ }
61
+ }
62
+ exports.JwtService = JwtService;
63
+ JwtService.EXPIRES_IN = '24h';
64
+ exports.default = JwtService;
65
+ //# sourceMappingURL=JwtService.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"JwtService.js","sourceRoot":"","sources":["../../../src/services/auth/JwtService.ts"],"names":[],"mappings":";;;;;;AAAA,gEAA+B;AAC/B,2EAA8C;AAS9C,MAAa,UAAU;IAGrB;;OAEG;IACH,MAAM,CAAC,aAAa,CAAC,IAAU;QAC7B,MAAM,OAAO,GAAe;YAC1B,MAAM,EAAE,IAAI,CAAC,EAAE;YACf,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,IAAI,EAAE,IAAI,CAAC,IAAI;SAChB,CAAC;QAEF,OAAO,sBAAG,CAAC,IAAI,CAAC,OAAO,EAAE,qBAAM,CAAC,UAAU,EAAE;YAC1C,SAAS,EAAE,IAAI,CAAC,UAAU;SAC3B,CAAC,CAAC;IACL,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,WAAW,CAAC,KAAa;QAC9B,IAAI,CAAC;YACH,OAAO,sBAAG,CAAC,MAAM,CAAC,KAAK,EAAE,qBAAM,CAAC,UAAU,CAAe,CAAC;QAC5D,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;gBAC3B,IAAI,KAAK,CAAC,IAAI,KAAK,mBAAmB,EAAE,CAAC;oBACvC,MAAM,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAC;gBACvC,CAAC;qBAAM,IAAI,KAAK,CAAC,IAAI,KAAK,mBAAmB,EAAE,CAAC;oBAC9C,MAAM,IAAI,KAAK,CAAC,eAAe,CAAC,CAAC;gBACnC,CAAC;YACH,CAAC;YACD,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,WAAW,CAAC,KAAa;QAC9B,IAAI,CAAC;YACH,OAAO,sBAAG,CAAC,MAAM,CAAC,KAAK,CAAe,CAAC;QACzC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,YAAY;QACjB,2BAA2B;QAC3B,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC;QACzD,OAAO,KAAK,GAAG,EAAE,GAAG,EAAE,CAAC;IACzB,CAAC;;AAtDH,gCAuDC;AAtDyB,qBAAU,GAAG,KAAK,CAAC;AAwD7C,kBAAe,UAAU,CAAC"}
@@ -0,0 +1,36 @@
1
+ export declare class TokenRefreshService {
2
+ private static instance;
3
+ private refreshIntervals;
4
+ private constructor();
5
+ static getInstance(): TokenRefreshService;
6
+ /**
7
+ * Start monitoring a token for refresh
8
+ */
9
+ start(tokenId: string): void;
10
+ /**
11
+ * Stop monitoring a token
12
+ */
13
+ stop(tokenId: string): void;
14
+ /**
15
+ * Stop all token monitoring
16
+ */
17
+ stopAll(): void;
18
+ /**
19
+ * Check if token needs refresh and refresh if needed
20
+ */
21
+ private checkAndRefresh;
22
+ /**
23
+ * Determine if token should be refreshed
24
+ */
25
+ private shouldRefresh;
26
+ /**
27
+ * Refresh token using provider-specific service
28
+ */
29
+ private refreshToken;
30
+ /**
31
+ * Update credential file with refreshed tokens
32
+ */
33
+ private updateCredentialFile;
34
+ }
35
+ export default TokenRefreshService;
36
+ //# sourceMappingURL=TokenRefreshService.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TokenRefreshService.d.ts","sourceRoot":"","sources":["../../../src/services/auth/TokenRefreshService.ts"],"names":[],"mappings":"AAWA,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAsB;IAC7C,OAAO,CAAC,gBAAgB,CAAqC;IAE7D,OAAO;IAEP,MAAM,CAAC,WAAW,IAAI,mBAAmB;IAOzC;;OAEG;IACH,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAsB5B;;OAEG;IACH,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAS3B;;OAEG;IACH,OAAO,IAAI,IAAI;IAMf;;OAEG;YACW,eAAe;IA0C7B;;OAEG;IACH,OAAO,CAAC,aAAa;IAarB;;OAEG;YACW,YAAY;IAmB1B;;OAEG;YACW,oBAAoB;CAkDnC;AAED,eAAe,mBAAmB,CAAC"}