@getbrevo/cli 0.0.1-alpha.2 → 1.0.0-alpha.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 (60) hide show
  1. package/CHANGELOG.md +24 -38
  2. package/README.md +51 -5
  3. package/agent-context/AGENTS.md +59 -0
  4. package/agent-context/SKILL.md +44 -0
  5. package/dist/api/client.d.ts.map +1 -1
  6. package/dist/api/client.js +8 -5
  7. package/dist/api/client.js.map +1 -1
  8. package/dist/bin/index.js +13 -1
  9. package/dist/bin/index.js.map +1 -1
  10. package/dist/commands/app/create.d.ts.map +1 -1
  11. package/dist/commands/app/create.js +8 -3
  12. package/dist/commands/app/create.js.map +1 -1
  13. package/dist/commands/app/credentials.d.ts.map +1 -1
  14. package/dist/commands/app/credentials.js +9 -3
  15. package/dist/commands/app/credentials.js.map +1 -1
  16. package/dist/commands/app/delete.d.ts.map +1 -1
  17. package/dist/commands/app/delete.js +1 -0
  18. package/dist/commands/app/delete.js.map +1 -1
  19. package/dist/commands/app/list.d.ts.map +1 -1
  20. package/dist/commands/app/list.js +18 -1
  21. package/dist/commands/app/list.js.map +1 -1
  22. package/dist/commands/app/start.d.ts.map +1 -1
  23. package/dist/commands/app/start.js +24 -11
  24. package/dist/commands/app/start.js.map +1 -1
  25. package/dist/commands/app/update.d.ts.map +1 -1
  26. package/dist/commands/app/update.js +9 -5
  27. package/dist/commands/app/update.js.map +1 -1
  28. package/dist/commands/definitions.js +8 -8
  29. package/dist/commands/definitions.js.map +1 -1
  30. package/dist/commands/login.d.ts.map +1 -1
  31. package/dist/commands/login.js +4 -0
  32. package/dist/commands/login.js.map +1 -1
  33. package/dist/lang/en.d.ts +4 -15
  34. package/dist/lang/en.d.ts.map +1 -1
  35. package/dist/lang/en.js +10 -22
  36. package/dist/lang/en.js.map +1 -1
  37. package/dist/lib/auth-guard.d.ts.map +1 -1
  38. package/dist/lib/auth-guard.js +7 -0
  39. package/dist/lib/auth-guard.js.map +1 -1
  40. package/dist/lib/config.d.ts +3 -0
  41. package/dist/lib/config.d.ts.map +1 -1
  42. package/dist/lib/config.js +82 -0
  43. package/dist/lib/config.js.map +1 -1
  44. package/dist/lib/validators.d.ts +1 -1
  45. package/dist/lib/validators.d.ts.map +1 -1
  46. package/dist/lib/validators.js +8 -13
  47. package/dist/lib/validators.js.map +1 -1
  48. package/dist/services/app.d.ts.map +1 -1
  49. package/dist/services/app.js +26 -3
  50. package/dist/services/app.js.map +1 -1
  51. package/dist/templates/files/AGENTS.md.tmpl +18 -12
  52. package/dist/templates/files/CLAUDE.md.tmpl +22 -13
  53. package/dist/templates/files/README.md.tmpl +10 -4
  54. package/dist/templates/files/src/oauth/handler.js.tmpl +3 -0
  55. package/dist/templates/files/src/oauth/server.js.tmpl +1 -1
  56. package/package.json +2 -1
  57. package/dist/commands/app/test.d.ts +0 -6
  58. package/dist/commands/app/test.d.ts.map +0 -1
  59. package/dist/commands/app/test.js +0 -496
  60. package/dist/commands/app/test.js.map +0 -1
@@ -1,496 +0,0 @@
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
- Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.testCommand = void 0;
37
- const crypto = __importStar(require("crypto"));
38
- const http = __importStar(require("http"));
39
- const fs = __importStar(require("fs"));
40
- const path = __importStar(require("path"));
41
- const logger_1 = require("../../lib/logger");
42
- const en_1 = require("../../lang/en");
43
- const errors_1 = require("../../lib/errors");
44
- const constants_1 = require("../../lib/constants");
45
- const config_1 = require("../../lib/config");
46
- const container_1 = require("../../container");
47
- const command_handler_1 = require("../../lib/command-handler");
48
- const ui_1 = require("../../lib/ui");
49
- function parseEnvFile(filePath) {
50
- const vars = {};
51
- try {
52
- if (!fs.existsSync(filePath))
53
- return vars;
54
- const content = fs.readFileSync(filePath, 'utf-8');
55
- for (const line of content.split('\n')) {
56
- const [key, ...rest] = line.split('=');
57
- const value = rest.join('=').trim();
58
- if (key?.trim() && value) {
59
- vars[key.trim()] = value;
60
- }
61
- }
62
- }
63
- catch {
64
- // ignore
65
- }
66
- return vars;
67
- }
68
- async function resolveCredentials(port, appIdOption) {
69
- let clientId = process.env.CLIENT_ID;
70
- let clientSecret = process.env.CLIENT_SECRET;
71
- let redirectUri = process.env.REDIRECT_URI || `http://localhost:${port}/auth/callback`;
72
- let scopes = ['all'];
73
- // Try .env.local file in cwd
74
- if (!clientId || !clientSecret) {
75
- const envVars = parseEnvFile(path.resolve('.env.local'));
76
- if (!clientId)
77
- clientId = envVars.CLIENT_ID;
78
- if (!clientSecret)
79
- clientSecret = envVars.CLIENT_SECRET;
80
- if (envVars.REDIRECT_URI)
81
- redirectUri = envVars.REDIRECT_URI;
82
- }
83
- // Try --app-id flag or app-config.json
84
- if (!clientId || !clientSecret) {
85
- let appId = appIdOption;
86
- if (!appId) {
87
- const projectConfig = (0, config_1.readProjectConfig)();
88
- if (projectConfig?.appId) {
89
- appId = projectConfig.appId;
90
- if (projectConfig.auth?.redirectUrls?.[0]) {
91
- redirectUri = projectConfig.auth.redirectUrls[0];
92
- }
93
- if (projectConfig.auth?.scopes?.length) {
94
- scopes = projectConfig.auth.scopes;
95
- }
96
- }
97
- }
98
- if (!appId) {
99
- if (process.stdin.isTTY) {
100
- appId = await container_1.appService.pickApp('Select an app to test:');
101
- }
102
- else {
103
- throw new errors_1.CliError('No local app found.\n' +
104
- ' Run `brevo app scaffold` to set up a project, or pass `--app-id <id>`.\n' +
105
- ' You can also set CLIENT_ID and CLIENT_SECRET in .env.local.');
106
- }
107
- }
108
- if (appId) {
109
- const credSpinner = (0, ui_1.createSpinner)('Fetching app credentials...');
110
- const result = await container_1.appService.resolveAppCredentials(appId);
111
- credSpinner.stop();
112
- if (result) {
113
- if (result.diffs.length > 0) {
114
- (0, logger_1.logWarn)(`Local credentials for app ${appId} differ from server (${result.diffs.join(', ')}). Updating local cache.`);
115
- }
116
- container_1.appService.syncAppCredentials(appId, result.app);
117
- clientId = clientId || result.app.client_id;
118
- clientSecret = clientSecret || result.app.client_secret;
119
- if (!process.env.REDIRECT_URI && result.app.redirect_uris?.[0]) {
120
- redirectUri = result.app.redirect_uris[0];
121
- }
122
- }
123
- }
124
- }
125
- if (!clientId || !clientSecret) {
126
- throw new errors_1.CliError('CLIENT_ID and CLIENT_SECRET are required.\n' +
127
- ' Set them in a .env file or as environment variables.\n' +
128
- ` ${en_1.messages.APP_TEST_MISSING_CREDENTIALS}`);
129
- }
130
- return { clientId, clientSecret, redirectUri, scopes };
131
- }
132
- function buildAuthUrl(clientId, redirectUri, state, scopes) {
133
- return (`${constants_1.API_BASE}${constants_1.ENDPOINTS.OAUTH_AUTHORIZE}` +
134
- `?client_id=${encodeURIComponent(clientId)}` +
135
- `&redirect_uri=${encodeURIComponent(redirectUri)}` +
136
- `&response_type=code` +
137
- `&state=${state}` +
138
- `&scope=${encodeURIComponent(scopes.join(' '))}`);
139
- }
140
- async function exchangeCodeForTokens(code, clientId, clientSecret, redirectUri) {
141
- const tokenResponse = await fetch(`${constants_1.API_BASE}${constants_1.ENDPOINTS.OAUTH_TOKEN}`, {
142
- method: 'POST',
143
- headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
144
- body: new URLSearchParams({
145
- grant_type: 'authorization_code',
146
- client_id: clientId,
147
- client_secret: clientSecret,
148
- code,
149
- redirect_uri: redirectUri,
150
- }).toString(),
151
- });
152
- return (await tokenResponse.json());
153
- }
154
- async function refreshAccessToken(refreshToken, clientId, clientSecret) {
155
- const tokenResponse = await fetch(`${constants_1.API_BASE}${constants_1.ENDPOINTS.OAUTH_TOKEN}`, {
156
- method: 'POST',
157
- headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
158
- body: new URLSearchParams({
159
- grant_type: 'refresh_token',
160
- client_id: clientId,
161
- client_secret: clientSecret,
162
- refresh_token: refreshToken,
163
- }).toString(),
164
- });
165
- return (await tokenResponse.json());
166
- }
167
- const browser_1 = require("../../lib/browser");
168
- // Sanitise untrusted values before embedding in HTML to prevent XSS
169
- function escapeHtml(str) {
170
- return str
171
- .replace(/&/g, '&amp;')
172
- .replace(/</g, '&lt;')
173
- .replace(/>/g, '&gt;')
174
- .replace(/"/g, '&quot;');
175
- }
176
- // Inline styles and JS for masked token display with click-to-reveal
177
- const TOKEN_STYLES = '<style>' +
178
- '*,*::before,*::after{margin:0;padding:0;box-sizing:border-box}' +
179
- 'body{font-family:"Inter",-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;background:rgb(250,245,227);min-height:100vh;display:flex;flex-direction:column;align-items:center;justify-content:center;padding:40px 16px}' +
180
- '.page-card{background:#fff;border:1px solid #e3e3e3;border-radius:16px;padding:40px;width:100%;max-width:560px;text-align:center}' +
181
- '.page-card h2{color:#1b1b1b;font-size:22px;margin-bottom:8px}' +
182
- '.page-card .subtitle{color:#696969;font-size:14px;margin-bottom:24px}' +
183
- '.btn-primary{display:inline-block;width:100%;padding:8px 16px;background:#1b1b1b;color:#fff;border:none;border-radius:16px;font-size:16px;font-weight:600;cursor:pointer;text-decoration:none;text-align:center;line-height:24px}' +
184
- '.btn-primary:hover{background:#2c2c2c}' +
185
- 'a{color:#1b1b1b}' +
186
- '.token-wrapper{position:relative;margin-top:6px}' +
187
- '.token-value{display:block;padding:10px;background:#fff;border:1px solid #cfcfcf;border-radius:8px;font-family:monospace;font-size:13px;filter:blur(5px);user-select:none;cursor:pointer;transition:filter 0.2s}' +
188
- '.token-value.revealed{filter:none;user-select:text;cursor:text}' +
189
- '.reveal-btn{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);background:#1b1b1b;color:#fff;border:none;padding:8px 16px;border-radius:16px;font-size:13px;font-weight:600;cursor:pointer}' +
190
- '.reveal-btn.hidden{display:none}' +
191
- '.request-details{text-align:left;margin:16px 0;background:#f5f5f5;border:1px solid #e3e3e3;padding:16px 20px;border-radius:16px;font-size:13px}' +
192
- '.request-details strong{color:#1b1b1b}' +
193
- '.request-details dt{font-weight:600;margin-top:8px;color:#1b1b1b}' +
194
- '.request-details dd{margin:2px 0 0 0;font-family:monospace;word-break:break-all;color:#696969}' +
195
- '.token-section{text-align:left;margin:16px 0;background:#f5f5f5;border:1px solid #e3e3e3;padding:20px;border-radius:16px;word-break:break-all}' +
196
- '.footer-text{color:#858585;font-size:12px;margin-top:16px}' +
197
- '</style>';
198
- const TOKEN_SCRIPT = '<script>' +
199
- 'document.querySelectorAll(".reveal-btn").forEach(function(btn){' +
200
- ' btn.addEventListener("click",function(){' +
201
- ' var code=btn.parentElement.querySelector(".token-value");' +
202
- ' code.classList.add("revealed");' +
203
- ' btn.classList.add("hidden");' +
204
- ' });' +
205
- '});' +
206
- '</script>';
207
- function maskedTokenBlock(label, value, extra) {
208
- const extraInfo = extra ? ` (${escapeHtml(extra)})` : '';
209
- return (`<p><strong>${escapeHtml(label)}</strong>${extraInfo}:</p>` +
210
- '<div class="token-wrapper">' +
211
- `<code class="token-value">${escapeHtml(value)}</code>` +
212
- '<button class="reveal-btn">Click to reveal</button>' +
213
- '</div>');
214
- }
215
- function requestDetailsHtml(clientId, redirectUri, scopes) {
216
- return ('<div class="request-details">' +
217
- '<strong>Authorization Request</strong>' +
218
- '<dl>' +
219
- `<dt>Client ID</dt><dd>${escapeHtml(clientId)}</dd>` +
220
- `<dt>Redirect URI</dt><dd>${escapeHtml(redirectUri)}</dd>` +
221
- `<dt>Scopes</dt><dd>${escapeHtml(scopes.join(' '))}</dd>` +
222
- '<dt>Response Type</dt><dd>code</dd>' +
223
- '</dl>' +
224
- '</div>');
225
- }
226
- // HTML page shown in the browser after a successful token exchange
227
- function successHtml(accessToken, refreshToken, expiresIn, clientId, redirectUri, scopes) {
228
- return (`<html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>Brevo OAuth — Success</title>${TOKEN_STYLES}</head>` +
229
- '<body>' +
230
- '<div class="page-card">' +
231
- '<h2>Authorization successful!</h2>' +
232
- '<p class="subtitle">Tokens are masked for security. Click to reveal.</p>' +
233
- requestDetailsHtml(clientId, redirectUri, scopes) +
234
- '<div class="token-section">' +
235
- maskedTokenBlock('Access Token', accessToken, `expires in ${expiresIn}s`) +
236
- '<div style="margin-top:16px">' +
237
- maskedTokenBlock('Refresh Token', refreshToken) +
238
- '</div>' +
239
- '</div>' +
240
- '<p style="margin-top:16px"><a href="/refresh">Refresh token</a></p>' +
241
- '</div>' +
242
- TOKEN_SCRIPT +
243
- '</body></html>');
244
- }
245
- function landingHtml(clientId, redirectUri, scopes) {
246
- return (`<html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>Brevo OAuth Test</title>${TOKEN_STYLES}</head>` +
247
- '<body>' +
248
- '<div class="page-card">' +
249
- '<h2>Brevo OAuth Test</h2>' +
250
- '<p class="subtitle">The following request will be sent to the partner login:</p>' +
251
- requestDetailsHtml(clientId, redirectUri, scopes) +
252
- '<a href="/login" class="btn-primary" style="margin-top:8px">Start OAuth Flow</a>' +
253
- '</div>' +
254
- '</body></html>');
255
- }
256
- exports.testCommand = (0, command_handler_1.withCommandHandler)(async (options) => {
257
- let port = options.port || 3009;
258
- const creds = await resolveCredentials(port, options.appId);
259
- let { redirectUri } = creds;
260
- const { clientId, clientSecret, scopes } = creds;
261
- // Generate CSRF state
262
- const state = crypto.randomBytes(16).toString('hex');
263
- // In-memory token store for the session
264
- let sessionRefreshToken;
265
- const server = http.createServer(async (req, res) => {
266
- // CORS headers for localhost dev
267
- res.setHeader('Access-Control-Allow-Origin', '*');
268
- res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
269
- res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization');
270
- // Cap request body at 1 MB. The test server only handles OAuth callbacks,
271
- // which carry everything in the query string — any real body here is
272
- // either a misconfiguration or an attempt to exhaust memory.
273
- const MAX_BODY_BYTES = 1024 * 1024;
274
- // Fast path: reject well-behaved large requests on Content-Length
275
- // before we ever start reading the body.
276
- const contentLength = Number.parseInt(req.headers['content-length'] || '', 10);
277
- if (Number.isFinite(contentLength) && contentLength > MAX_BODY_BYTES) {
278
- res.writeHead(413, { 'Content-Type': 'text/plain', Connection: 'close' });
279
- res.end('Request entity too large (max 1 MB).');
280
- req.destroy();
281
- return;
282
- }
283
- // Slow path: chunked / missing Content-Length — count bytes as they stream in.
284
- // Always count and always destroy on overflow, even if we've already
285
- // responded (e.g. /login returns 302 before the body finishes streaming).
286
- // Only gate the 413 write on the response still being open.
287
- let bodyBytes = 0;
288
- req.on('data', (chunk) => {
289
- bodyBytes += chunk.length;
290
- if (bodyBytes > MAX_BODY_BYTES) {
291
- if (!res.writableEnded && !res.headersSent) {
292
- res.writeHead(413, { 'Content-Type': 'text/plain', Connection: 'close' });
293
- res.end('Request entity too large (max 1 MB).');
294
- }
295
- req.destroy();
296
- }
297
- });
298
- if (req.method === 'OPTIONS') {
299
- res.writeHead(204);
300
- res.end();
301
- return;
302
- }
303
- const url = new URL(req.url || '/', `http://localhost:${port}`);
304
- if (url.pathname === '/login') {
305
- const authUrl = buildAuthUrl(clientId, redirectUri, state, scopes);
306
- res.writeHead(302, { Location: authUrl });
307
- res.end();
308
- return;
309
- }
310
- if (url.pathname === '/callback' || url.pathname === '/auth/callback') {
311
- const code = url.searchParams.get('code');
312
- const returnedState = url.searchParams.get('state');
313
- if (returnedState !== state) {
314
- res.writeHead(400, { 'Content-Type': 'text/plain' });
315
- res.end('Invalid state parameter. Possible CSRF attack.');
316
- return;
317
- }
318
- if (!code) {
319
- const error = url.searchParams.get('error') || 'unknown';
320
- res.writeHead(400, { 'Content-Type': 'text/plain' });
321
- res.end(`Authorization failed: ${error}`);
322
- return;
323
- }
324
- (0, logger_1.logInfo)(`\n ${en_1.messages.APP_TEST_CODE_RECEIVED}`);
325
- const tokenSpinner = (0, ui_1.createSpinner)('Exchanging code for tokens...');
326
- try {
327
- const tokens = await exchangeCodeForTokens(code, clientId, clientSecret, redirectUri);
328
- tokenSpinner.stop();
329
- // Body-limit handler or client disconnect may have ended the response
330
- // while we were awaiting the token exchange — don't write to it again.
331
- if (res.writableEnded)
332
- return;
333
- if (tokens.error || !tokens.access_token) {
334
- (0, logger_1.logError)(`Token exchange failed: ${tokens.error || 'unknown error'}`);
335
- res.writeHead(500, { 'Content-Type': 'text/plain' });
336
- res.end('Token exchange failed.');
337
- return;
338
- }
339
- // Store refresh token so the /refresh endpoint can use it later
340
- if (tokens.refresh_token) {
341
- sessionRefreshToken = tokens.refresh_token;
342
- }
343
- // Display token status in the terminal (tokens are only visible in the browser)
344
- process.stdout.write('\n');
345
- (0, logger_1.logSuccess)(` ${en_1.messages.APP_TEST_ACCESS_TOKEN(tokens.expires_in || 0)}`);
346
- (0, logger_1.logSuccess)(` ${en_1.messages.APP_TEST_REFRESH_TOKEN_RECEIVED}`);
347
- // Validate the access token by calling the account endpoint
348
- try {
349
- const accountResponse = await fetch(`${constants_1.API_BASE}/v3/account`, {
350
- headers: {
351
- Authorization: `Bearer ${tokens.access_token}`,
352
- Accept: 'application/json',
353
- },
354
- });
355
- const account = (await accountResponse.json());
356
- if (account.email) {
357
- (0, logger_1.logSuccess)(`Connection verified — ${account.email}`);
358
- }
359
- }
360
- catch {
361
- // Non-critical — verification is best-effort
362
- }
363
- // Let the user know tokens are also visible in the browser
364
- process.stdout.write('\n');
365
- (0, logger_1.logInfo)(` ${en_1.messages.APP_TEST_TOKENS_IN_BROWSER(port)}`);
366
- (0, logger_1.logInfo)(` ${en_1.messages.APP_TEST_TOKEN_REFRESH_URL(port)}`);
367
- (0, logger_1.logInfo)(` ${en_1.messages.APP_TEST_NEXT_STEPS}`);
368
- (0, logger_1.logInfo)(` ${en_1.messages.APP_TEST_COMPLETE}\n`);
369
- // Serve success page with tokens visible in the browser
370
- res.writeHead(200, {
371
- 'Content-Type': 'text/html',
372
- 'Cache-Control': 'no-store, no-cache, must-revalidate',
373
- Pragma: 'no-cache',
374
- Expires: '0',
375
- });
376
- res.end(successHtml(tokens.access_token, tokens.refresh_token || '', tokens.expires_in || 0, clientId, redirectUri, scopes));
377
- }
378
- catch (err) {
379
- tokenSpinner.stop();
380
- (0, logger_1.logError)('Token exchange failed', err);
381
- if (!res.writableEnded) {
382
- res.writeHead(500, { 'Content-Type': 'text/plain' });
383
- res.end('Token exchange failed.');
384
- }
385
- }
386
- return;
387
- }
388
- // Token refresh endpoint — exchanges the stored refresh token for a new access token
389
- if (url.pathname === '/refresh') {
390
- if (!sessionRefreshToken) {
391
- res.writeHead(400, { 'Content-Type': 'text/plain' });
392
- res.end('No refresh token available. Complete the OAuth flow first.');
393
- return;
394
- }
395
- const refreshSpinner = (0, ui_1.createSpinner)('Refreshing access token...');
396
- try {
397
- const tokens = await refreshAccessToken(sessionRefreshToken, clientId, clientSecret);
398
- refreshSpinner.stop();
399
- if (res.writableEnded)
400
- return;
401
- if (tokens.error || !tokens.access_token) {
402
- (0, logger_1.logError)(` Token refresh failed: ${tokens.error || 'unknown error'}`);
403
- (0, logger_1.logInfo)(' Re-authenticate by visiting /login\n');
404
- res.writeHead(500, { 'Content-Type': 'text/plain' });
405
- res.end(`Token refresh failed: ${tokens.error || 'unknown error'}. Re-authenticate at /login.`);
406
- return;
407
- }
408
- if (tokens.refresh_token) {
409
- sessionRefreshToken = tokens.refresh_token;
410
- }
411
- (0, logger_1.logSuccess)(` ${en_1.messages.APP_TEST_TOKEN_REFRESHED(tokens.expires_in || 0)}\n`);
412
- res.writeHead(200, {
413
- 'Content-Type': 'text/html',
414
- 'Cache-Control': 'no-store, no-cache, must-revalidate',
415
- Pragma: 'no-cache',
416
- Expires: '0',
417
- });
418
- res.end(`<html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>Brevo OAuth — Token Refreshed</title>${TOKEN_STYLES}</head>` +
419
- '<body>' +
420
- '<div class="page-card">' +
421
- '<h2>Token refreshed!</h2>' +
422
- '<p class="subtitle">Click to reveal the token.</p>' +
423
- '<div class="token-section">' +
424
- maskedTokenBlock('Access Token', tokens.access_token, `expires in ${tokens.expires_in}s`) +
425
- '</div>' +
426
- '<p class="footer-text">You can close this window and return to the terminal.</p>' +
427
- '</div>' +
428
- TOKEN_SCRIPT +
429
- '</body></html>');
430
- }
431
- catch (err) {
432
- refreshSpinner.stop();
433
- (0, logger_1.logError)(' Token refresh failed', err);
434
- (0, logger_1.logInfo)(' Re-authenticate by visiting /login\n');
435
- if (!res.writableEnded) {
436
- res.writeHead(500, { 'Content-Type': 'text/plain' });
437
- res.end('Token refresh failed. Re-authenticate at /login.');
438
- }
439
- }
440
- return;
441
- }
442
- // Default route
443
- res.writeHead(200, { 'Content-Type': 'text/html' });
444
- res.end(landingHtml(clientId, redirectUri, scopes));
445
- });
446
- server.setTimeout(30000);
447
- // Handle port in use — retry with next port
448
- server.on('error', (err) => {
449
- if (err.code === 'EADDRINUSE') {
450
- port++;
451
- (0, logger_1.logInfo)(` ${en_1.messages.APP_TEST_PORT_IN_USE(port - 1)} Trying port ${port}...`);
452
- redirectUri = `http://localhost:${port}/auth/callback`;
453
- server.listen(port, '127.0.0.1');
454
- }
455
- else {
456
- (0, logger_1.logError)(`Server error: ${err.message}`);
457
- server.close();
458
- throw new errors_1.CliError(`Server error: ${err.message}`);
459
- }
460
- });
461
- await new Promise((resolve) => {
462
- // Save and remove global signal handlers so they don't call
463
- // process.exit() while the test server is running
464
- const globalSigint = process.rawListeners('SIGINT');
465
- const globalSigterm = process.rawListeners('SIGTERM');
466
- process.removeAllListeners('SIGINT');
467
- process.removeAllListeners('SIGTERM');
468
- server.listen(port, '127.0.0.1', () => {
469
- (0, logger_1.logInfo)(`\n ${en_1.messages.APP_TEST_STARTING(port)}`);
470
- (0, logger_1.logInfo)(` ${en_1.messages.APP_TEST_REDIRECT_URI(redirectUri)}`);
471
- (0, logger_1.logInfo)(` ${en_1.messages.APP_TEST_BROWSER_OPEN}`);
472
- (0, logger_1.logInfo)(` ${en_1.messages.APP_TEST_WAITING}\n`);
473
- (0, browser_1.openBrowser)(`http://localhost:${port}/login`);
474
- });
475
- // Graceful shutdown — close server then restore global handlers
476
- const onSignal = () => {
477
- server.close(() => {
478
- process.stdout.write('\n');
479
- (0, logger_1.logInfo)(' Server stopped.\n');
480
- // Restore global signal handlers
481
- for (const fn of globalSigint)
482
- process.on('SIGINT', fn);
483
- for (const fn of globalSigterm)
484
- process.on('SIGTERM', fn);
485
- resolve();
486
- });
487
- process.removeListener('SIGINT', onSignal);
488
- process.removeListener('SIGTERM', onSignal);
489
- };
490
- process.on('SIGINT', onSignal);
491
- process.on('SIGTERM', onSignal);
492
- // Also resolve if server closes for any other reason
493
- server.on('close', () => resolve());
494
- });
495
- });
496
- //# sourceMappingURL=test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"test.js","sourceRoot":"","sources":["../../../src/commands/app/test.ts"],"names":[],"mappings":"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"}