@startanaicompany/cli 1.4.20 → 1.5.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.
@@ -3,14 +3,16 @@
3
3
  */
4
4
 
5
5
  const api = require('../lib/api');
6
- const { getProjectConfig, isAuthenticated } = require('../lib/config');
6
+ const { getProjectConfig, ensureAuthenticated } = require('../lib/config');
7
7
  const logger = require('../lib/logger');
8
8
 
9
9
  async function logs(deploymentUuidArg, options) {
10
10
  try {
11
11
  // Check authentication
12
- if (!isAuthenticated()) {
13
- logger.error('Not logged in. Run: saac login');
12
+ if (!(await ensureAuthenticated())) {
13
+ logger.error('Not logged in');
14
+ logger.info('Run: saac login -e <email> -k <api-key>');
15
+ logger.info('Or set: SAAC_USER_API_KEY and SAAC_USER_EMAIL');
14
16
  process.exit(1);
15
17
  }
16
18
 
@@ -3,7 +3,7 @@
3
3
  */
4
4
 
5
5
  const api = require('../lib/api');
6
- const { getProjectConfig, isAuthenticated } = require('../lib/config');
6
+ const { getProjectConfig, ensureAuthenticated } = require('../lib/config');
7
7
  const logger = require('../lib/logger');
8
8
  const { spawn } = require('child_process');
9
9
  const fs = require('fs');
@@ -55,8 +55,10 @@ async function getEnvironmentVariables(appUuid, forceRefresh = false) {
55
55
  async function run(command, options = {}) {
56
56
  try {
57
57
  // Check authentication
58
- if (!isAuthenticated()) {
59
- logger.error('Not logged in. Run: saac login');
58
+ if (!(await ensureAuthenticated())) {
59
+ logger.error('Not logged in');
60
+ logger.info('Run: saac login -e <email> -k <api-key>');
61
+ logger.info('Or set: SAAC_USER_API_KEY and SAAC_USER_EMAIL');
60
62
  process.exit(1);
61
63
  }
62
64
 
@@ -3,18 +3,17 @@
3
3
  */
4
4
 
5
5
  const api = require('../lib/api');
6
- const { isAuthenticated } = require('../lib/config');
6
+ const { ensureAuthenticated } = require('../lib/config');
7
7
  const logger = require('../lib/logger');
8
8
  const { table } = require('table');
9
9
 
10
10
  async function sessions() {
11
11
  try {
12
12
  // Check authentication
13
- if (!isAuthenticated()) {
13
+ if (!(await ensureAuthenticated())) {
14
14
  logger.error('Not logged in');
15
- logger.newline();
16
- logger.info('Run:');
17
- logger.log(' saac login -e <email> -k <api-key>');
15
+ logger.info('Run: saac login -e <email> -k <api-key>');
16
+ logger.info('Or set: SAAC_USER_API_KEY and SAAC_USER_EMAIL');
18
17
  process.exit(1);
19
18
  }
20
19
 
@@ -7,7 +7,7 @@
7
7
 
8
8
  const WebSocket = require('ws');
9
9
  const readline = require('readline');
10
- const { getProjectConfig, isAuthenticated, getUser, getApiUrl } = require('../lib/config');
10
+ const { getProjectConfig, ensureAuthenticated, getUser, getApiUrl } = require('../lib/config');
11
11
  const logger = require('../lib/logger');
12
12
 
13
13
  /**
@@ -320,8 +320,10 @@ class ShellClient {
320
320
  async function shell(options = {}) {
321
321
  try {
322
322
  // Check authentication
323
- if (!isAuthenticated()) {
324
- logger.error('Not logged in. Run: saac login');
323
+ if (!(await ensureAuthenticated())) {
324
+ logger.error('Not logged in');
325
+ logger.info('Run: saac login -e <email> -k <api-key>');
326
+ logger.info('Or set: SAAC_USER_API_KEY and SAAC_USER_EMAIL');
325
327
  process.exit(1);
326
328
  }
327
329
 
@@ -3,7 +3,7 @@
3
3
  */
4
4
 
5
5
  const api = require('../lib/api');
6
- const { getUser, isAuthenticated, isTokenExpiringSoon } = require('../lib/config');
6
+ const { getUser, ensureAuthenticated, isTokenExpiringSoon } = require('../lib/config');
7
7
  const logger = require('../lib/logger');
8
8
  const { table } = require('table');
9
9
 
@@ -13,11 +13,10 @@ async function status() {
13
13
  logger.newline();
14
14
 
15
15
  // Check if logged in locally (silently)
16
- if (!isAuthenticated()) {
16
+ if (!(await ensureAuthenticated())) {
17
17
  logger.error('Not logged in');
18
- logger.newline();
19
- logger.info('Run:');
20
- logger.log(' saac login -e <email> -k <api-key>');
18
+ logger.info('Run: saac login -e <email> -k <api-key>');
19
+ logger.info('Or set: SAAC_USER_API_KEY and SAAC_USER_EMAIL');
21
20
  process.exit(1);
22
21
  }
23
22
 
@@ -3,17 +3,16 @@
3
3
  */
4
4
 
5
5
  const api = require('../lib/api');
6
- const { isAuthenticated, getProjectConfig } = require('../lib/config');
6
+ const { ensureAuthenticated, getProjectConfig } = require('../lib/config');
7
7
  const logger = require('../lib/logger');
8
8
 
9
9
  async function update(options) {
10
10
  try {
11
- // Check authentication
12
- if (!isAuthenticated()) {
11
+ // Check authentication (with auto-login support)
12
+ if (!(await ensureAuthenticated())) {
13
13
  logger.error('Not logged in');
14
- logger.newline();
15
- logger.info('Run:');
16
- logger.log(' saac login -e <email> -k <api-key>');
14
+ logger.info('Run: saac login -e <email> -k <api-key>');
15
+ logger.info('Or set: SAAC_USER_API_KEY and SAAC_USER_EMAIL');
17
16
  process.exit(1);
18
17
  }
19
18
 
@@ -3,7 +3,7 @@
3
3
  */
4
4
 
5
5
  const api = require('../lib/api');
6
- const { isAuthenticated } = require('../lib/config');
6
+ const { ensureAuthenticated } = require('../lib/config');
7
7
  const logger = require('../lib/logger');
8
8
 
9
9
  /**
@@ -12,11 +12,10 @@ const logger = require('../lib/logger');
12
12
  async function whoami() {
13
13
  try {
14
14
  // Check authentication
15
- if (!isAuthenticated()) {
15
+ if (!(await ensureAuthenticated())) {
16
16
  logger.error('Not logged in');
17
- logger.newline();
18
- logger.info('Run:');
19
- logger.log(' saac login -e <email> -k <api-key>');
17
+ logger.info('Run: saac login -e <email> -k <api-key>');
18
+ logger.info('Or set: SAAC_USER_API_KEY and SAAC_USER_EMAIL');
20
19
  process.exit(1);
21
20
  }
22
21
 
package/src/lib/api.js CHANGED
@@ -290,6 +290,35 @@ async function getExecutionHistory(uuid, params = {}) {
290
290
  return response.data;
291
291
  }
292
292
 
293
+ /**
294
+ * List repositories from a connected Git host
295
+ * @param {string} gitHost - Git host domain (e.g., 'github.com', 'git.startanaicompany.com')
296
+ * @param {object} options - Query options
297
+ * @param {number} options.page - Page number for pagination (default: 1)
298
+ * @param {number} options.perPage - Results per page (default: 100, max: 100)
299
+ * @param {string} options.sort - Sort order: 'updated', 'created', 'name' (default: 'updated')
300
+ * @param {string} options.visibility - Filter: 'all', 'public', 'private' (default: 'all')
301
+ * @param {boolean} options.includeCommits - Include latest commit info (default: false)
302
+ * @returns {Promise<object>} - Repository listing response
303
+ */
304
+ async function listGitRepositories(gitHost, options = {}) {
305
+ const client = createClient();
306
+
307
+ // Build query parameters
308
+ const params = {};
309
+ if (options.page) params.page = options.page;
310
+ if (options.perPage) params.per_page = options.perPage;
311
+ if (options.sort) params.sort = options.sort;
312
+ if (options.visibility) params.visibility = options.visibility;
313
+ if (options.includeCommits) params.include_commits = true;
314
+
315
+ // URL encode the git host
316
+ const encodedHost = encodeURIComponent(gitHost);
317
+
318
+ const response = await client.get(`/git/connections/${encodedHost}/repos`, { params });
319
+ return response.data;
320
+ }
321
+
293
322
  module.exports = {
294
323
  createClient,
295
324
  login,
@@ -315,4 +344,5 @@ module.exports = {
315
344
  getDeploymentLogs,
316
345
  executeCommand,
317
346
  getExecutionHistory,
347
+ listGitRepositories,
318
348
  };
package/src/lib/config.js CHANGED
@@ -106,6 +106,52 @@ function isTokenExpiringSoon() {
106
106
  return expirationDate <= sevenDaysFromNow && !isTokenExpired();
107
107
  }
108
108
 
109
+ /**
110
+ * Ensure user is authenticated, with auto-login support via environment variables
111
+ * Checks for SAAC_USER_API_KEY and SAAC_USER_EMAIL environment variables
112
+ * If present and user is not authenticated, attempts automatic login
113
+ *
114
+ * @returns {Promise<boolean>} - True if authenticated, false otherwise
115
+ */
116
+ async function ensureAuthenticated() {
117
+ // Step 1: Check if already authenticated (fast path)
118
+ if (isAuthenticated()) {
119
+ return true;
120
+ }
121
+
122
+ // Step 2: Check for environment variables
123
+ const apiKey = process.env.SAAC_USER_API_KEY;
124
+ const email = process.env.SAAC_USER_EMAIL;
125
+
126
+ if (!apiKey || !email) {
127
+ // No environment variables - cannot auto-login
128
+ return false;
129
+ }
130
+
131
+ // Step 3: Attempt auto-login via API
132
+ try {
133
+ // Dynamically require to avoid circular dependency
134
+ const api = require('./api');
135
+ const result = await api.login(email, apiKey);
136
+
137
+ // Step 4: Save session token to config
138
+ saveUser({
139
+ email: result.user.email,
140
+ userId: result.user.id,
141
+ sessionToken: result.session_token,
142
+ expiresAt: result.expires_at,
143
+ verified: result.user.verified,
144
+ });
145
+
146
+ // Auto-login successful
147
+ return true;
148
+
149
+ } catch (error) {
150
+ // Auto-login failed (invalid key, network error, etc.)
151
+ return false;
152
+ }
153
+ }
154
+
109
155
  /**
110
156
  * Get user info
111
157
  */
@@ -146,6 +192,7 @@ module.exports = {
146
192
  getProjectConfig,
147
193
  saveProjectConfig,
148
194
  isAuthenticated,
195
+ ensureAuthenticated,
149
196
  isTokenExpired,
150
197
  isTokenExpiringSoon,
151
198
  getUser,