@startanaicompany/cli 1.4.21 → 1.6.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.
- package/.claude/settings.local.json +10 -0
- package/CLAUDE.md +67 -7
- package/README.md +453 -18
- package/bin/saac.js +2 -6
- package/package.json +1 -1
- package/src/commands/create.js +13 -12
- package/src/commands/delete.js +6 -4
- package/src/commands/deploy.js +6 -4
- package/src/commands/deployments.js +5 -3
- package/src/commands/domain.js +9 -5
- package/src/commands/env.js +9 -5
- package/src/commands/exec.js +9 -5
- package/src/commands/git.js +13 -17
- package/src/commands/init.js +116 -20
- package/src/commands/keys.js +6 -57
- package/src/commands/list.js +5 -6
- package/src/commands/logs.js +142 -15
- package/src/commands/run.js +5 -3
- package/src/commands/sessions.js +4 -5
- package/src/commands/shell.js +5 -3
- package/src/commands/status.js +4 -5
- package/src/commands/update.js +5 -6
- package/src/commands/whoami.js +5 -6
- package/src/lib/config.js +47 -0
package/src/commands/create.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
const api = require('../lib/api');
|
|
6
|
-
const {
|
|
6
|
+
const { ensureAuthenticated, saveProjectConfig, getUser, getProjectConfig } = require('../lib/config');
|
|
7
7
|
const logger = require('../lib/logger');
|
|
8
8
|
const oauth = require('../lib/oauth');
|
|
9
9
|
const inquirer = require('inquirer');
|
|
@@ -12,12 +12,11 @@ const errorDisplay = require('../lib/errorDisplay');
|
|
|
12
12
|
|
|
13
13
|
async function create(name, options) {
|
|
14
14
|
try {
|
|
15
|
-
// Check authentication
|
|
16
|
-
if (!
|
|
15
|
+
// Check authentication (with auto-login support)
|
|
16
|
+
if (!(await ensureAuthenticated())) {
|
|
17
17
|
logger.error('Not logged in');
|
|
18
|
-
logger.
|
|
19
|
-
logger.info('
|
|
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
|
|
|
@@ -90,6 +89,7 @@ async function create(name, options) {
|
|
|
90
89
|
logger.info('Required options:');
|
|
91
90
|
logger.log(' -s, --subdomain <subdomain> Subdomain for your app');
|
|
92
91
|
logger.log(' -r, --repository <url> Git repository URL (SSH format)');
|
|
92
|
+
logger.log(' --org <organization_id> Organization ID');
|
|
93
93
|
logger.newline();
|
|
94
94
|
logger.info('Optional options:');
|
|
95
95
|
logger.log(' -b, --branch <branch> Git branch (default: master)');
|
|
@@ -111,17 +111,17 @@ async function create(name, options) {
|
|
|
111
111
|
logger.log(' --env <KEY=VALUE> Environment variable (can be used multiple times)');
|
|
112
112
|
logger.newline();
|
|
113
113
|
logger.info('Example:');
|
|
114
|
-
logger.log(' saac create my-app -s myapp -r git@git.startanaicompany.com:user/repo.git');
|
|
115
|
-
logger.log(' saac create api -s api -r git@git... --build-pack nixpacks --port 8080');
|
|
116
|
-
logger.log(' saac create web -s web -r git@git... --health-check --pre-deploy-cmd "npm run migrate"');
|
|
114
|
+
logger.log(' saac create my-app -s myapp -r git@git.startanaicompany.com:user/repo.git --org <org_id>');
|
|
115
|
+
logger.log(' saac create api -s api -r git@git... --org <org_id> --build-pack nixpacks --port 8080');
|
|
116
|
+
logger.log(' saac create web -s web -r git@git... --org <org_id> --health-check --pre-deploy-cmd "npm run migrate"');
|
|
117
117
|
process.exit(1);
|
|
118
118
|
}
|
|
119
119
|
|
|
120
|
-
if (!options.subdomain || !options.repository) {
|
|
121
|
-
logger.error('Missing required options: subdomain and
|
|
120
|
+
if (!options.subdomain || !options.repository || !options.org) {
|
|
121
|
+
logger.error('Missing required options: subdomain, repository, and organization ID are required');
|
|
122
122
|
logger.newline();
|
|
123
123
|
logger.info('Example:');
|
|
124
|
-
logger.log(` saac create ${name} -s myapp -r git@git.startanaicompany.com:user/repo.git
|
|
124
|
+
logger.log(` saac create ${name} -s myapp -r git@git.startanaicompany.com:user/repo.git --org <org_id>`);
|
|
125
125
|
logger.newline();
|
|
126
126
|
logger.info('Note: Git OAuth connection required. Connect with: saac git connect');
|
|
127
127
|
process.exit(1);
|
|
@@ -157,6 +157,7 @@ async function create(name, options) {
|
|
|
157
157
|
domain_suffix: options.domainSuffix || 'startanaicompany.com',
|
|
158
158
|
git_repository: options.repository,
|
|
159
159
|
git_branch: options.branch || 'master',
|
|
160
|
+
organization_id: options.org,
|
|
160
161
|
};
|
|
161
162
|
|
|
162
163
|
// OAuth tokens are retrieved from database by wrapper
|
package/src/commands/delete.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
const api = require('../lib/api');
|
|
6
|
-
const { getProjectConfig,
|
|
6
|
+
const { getProjectConfig, ensureAuthenticated } = require('../lib/config');
|
|
7
7
|
const logger = require('../lib/logger');
|
|
8
8
|
const inquirer = require('inquirer');
|
|
9
9
|
const fs = require('fs');
|
|
@@ -16,8 +16,10 @@ const path = require('path');
|
|
|
16
16
|
async function deleteApp(options) {
|
|
17
17
|
try {
|
|
18
18
|
// Check authentication
|
|
19
|
-
if (!
|
|
20
|
-
logger.error('Not logged in
|
|
19
|
+
if (!(await ensureAuthenticated())) {
|
|
20
|
+
logger.error('Not logged in');
|
|
21
|
+
logger.info('Run: saac login -e <email> -k <api-key>');
|
|
22
|
+
logger.info('Or set: SAAC_USER_API_KEY and SAAC_USER_EMAIL');
|
|
21
23
|
process.exit(1);
|
|
22
24
|
}
|
|
23
25
|
|
|
@@ -111,7 +113,7 @@ async function deleteApp(options) {
|
|
|
111
113
|
|
|
112
114
|
logger.newline();
|
|
113
115
|
|
|
114
|
-
logger.success(`Application '${
|
|
116
|
+
logger.success(`Application '${app.name}' has been permanently deleted.`);
|
|
115
117
|
|
|
116
118
|
logger.newline();
|
|
117
119
|
|
package/src/commands/deploy.js
CHANGED
|
@@ -3,15 +3,17 @@
|
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
const api = require('../lib/api');
|
|
6
|
-
const { getProjectConfig,
|
|
6
|
+
const { getProjectConfig, ensureAuthenticated } = require('../lib/config');
|
|
7
7
|
const logger = require('../lib/logger');
|
|
8
8
|
const errorDisplay = require('../lib/errorDisplay');
|
|
9
9
|
|
|
10
10
|
async function deploy(options) {
|
|
11
11
|
try {
|
|
12
|
-
// Check authentication
|
|
13
|
-
if (!
|
|
14
|
-
logger.error('Not logged in
|
|
12
|
+
// Check authentication (with auto-login support)
|
|
13
|
+
if (!(await ensureAuthenticated())) {
|
|
14
|
+
logger.error('Not logged in');
|
|
15
|
+
logger.info('Run: saac login -e <email> -k <api-key>');
|
|
16
|
+
logger.info('Or set: SAAC_USER_API_KEY and SAAC_USER_EMAIL');
|
|
15
17
|
process.exit(1);
|
|
16
18
|
}
|
|
17
19
|
|
|
@@ -3,15 +3,17 @@
|
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
const api = require('../lib/api');
|
|
6
|
-
const { getProjectConfig,
|
|
6
|
+
const { getProjectConfig, ensureAuthenticated } = require('../lib/config');
|
|
7
7
|
const logger = require('../lib/logger');
|
|
8
8
|
const { table } = require('table');
|
|
9
9
|
|
|
10
10
|
async function deployments(options) {
|
|
11
11
|
try {
|
|
12
12
|
// Check authentication
|
|
13
|
-
if (!
|
|
14
|
-
logger.error('Not logged in
|
|
13
|
+
if (!(await ensureAuthenticated())) {
|
|
14
|
+
logger.error('Not logged in');
|
|
15
|
+
logger.info('Run: saac login -e <email> -k <api-key>');
|
|
16
|
+
logger.info('Or set: SAAC_USER_API_KEY and SAAC_USER_EMAIL');
|
|
15
17
|
process.exit(1);
|
|
16
18
|
}
|
|
17
19
|
|
package/src/commands/domain.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
const api = require('../lib/api');
|
|
6
|
-
const { getProjectConfig,
|
|
6
|
+
const { getProjectConfig, ensureAuthenticated, saveProjectConfig } = require('../lib/config');
|
|
7
7
|
const logger = require('../lib/logger');
|
|
8
8
|
|
|
9
9
|
/**
|
|
@@ -14,8 +14,10 @@ const logger = require('../lib/logger');
|
|
|
14
14
|
async function set(subdomain, options) {
|
|
15
15
|
try {
|
|
16
16
|
// Check authentication
|
|
17
|
-
if (!
|
|
18
|
-
logger.error('Not logged in
|
|
17
|
+
if (!(await ensureAuthenticated())) {
|
|
18
|
+
logger.error('Not logged in');
|
|
19
|
+
logger.info('Run: saac login -e <email> -k <api-key>');
|
|
20
|
+
logger.info('Or set: SAAC_USER_API_KEY and SAAC_USER_EMAIL');
|
|
19
21
|
process.exit(1);
|
|
20
22
|
}
|
|
21
23
|
|
|
@@ -149,8 +151,10 @@ async function set(subdomain, options) {
|
|
|
149
151
|
async function show() {
|
|
150
152
|
try {
|
|
151
153
|
// Check authentication
|
|
152
|
-
if (!
|
|
153
|
-
logger.error('Not logged in
|
|
154
|
+
if (!(await ensureAuthenticated())) {
|
|
155
|
+
logger.error('Not logged in');
|
|
156
|
+
logger.info('Run: saac login -e <email> -k <api-key>');
|
|
157
|
+
logger.info('Or set: SAAC_USER_API_KEY and SAAC_USER_EMAIL');
|
|
154
158
|
process.exit(1);
|
|
155
159
|
}
|
|
156
160
|
|
package/src/commands/env.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
const api = require('../lib/api');
|
|
6
|
-
const { getProjectConfig,
|
|
6
|
+
const { getProjectConfig, ensureAuthenticated } = require('../lib/config');
|
|
7
7
|
const logger = require('../lib/logger');
|
|
8
8
|
const { table } = require('table');
|
|
9
9
|
|
|
@@ -14,8 +14,10 @@ const { table } = require('table');
|
|
|
14
14
|
async function get(key) {
|
|
15
15
|
try {
|
|
16
16
|
// Check authentication
|
|
17
|
-
if (!
|
|
18
|
-
logger.error('Not logged in
|
|
17
|
+
if (!(await ensureAuthenticated())) {
|
|
18
|
+
logger.error('Not logged in');
|
|
19
|
+
logger.info('Run: saac login -e <email> -k <api-key>');
|
|
20
|
+
logger.info('Or set: SAAC_USER_API_KEY and SAAC_USER_EMAIL');
|
|
19
21
|
process.exit(1);
|
|
20
22
|
}
|
|
21
23
|
|
|
@@ -108,8 +110,10 @@ async function list() {
|
|
|
108
110
|
async function set(vars) {
|
|
109
111
|
try {
|
|
110
112
|
// Check authentication
|
|
111
|
-
if (!
|
|
112
|
-
logger.error('Not logged in
|
|
113
|
+
if (!(await ensureAuthenticated())) {
|
|
114
|
+
logger.error('Not logged in');
|
|
115
|
+
logger.info('Run: saac login -e <email> -k <api-key>');
|
|
116
|
+
logger.info('Or set: SAAC_USER_API_KEY and SAAC_USER_EMAIL');
|
|
113
117
|
process.exit(1);
|
|
114
118
|
}
|
|
115
119
|
|
package/src/commands/exec.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
const api = require('../lib/api');
|
|
6
|
-
const { getProjectConfig,
|
|
6
|
+
const { getProjectConfig, ensureAuthenticated } = require('../lib/config');
|
|
7
7
|
const logger = require('../lib/logger');
|
|
8
8
|
const { table } = require('table');
|
|
9
9
|
|
|
@@ -15,8 +15,10 @@ const { table } = require('table');
|
|
|
15
15
|
async function exec(command, options = {}) {
|
|
16
16
|
try {
|
|
17
17
|
// Check authentication
|
|
18
|
-
if (!
|
|
19
|
-
logger.error('Not logged in
|
|
18
|
+
if (!(await ensureAuthenticated())) {
|
|
19
|
+
logger.error('Not logged in');
|
|
20
|
+
logger.info('Run: saac login -e <email> -k <api-key>');
|
|
21
|
+
logger.info('Or set: SAAC_USER_API_KEY and SAAC_USER_EMAIL');
|
|
20
22
|
process.exit(1);
|
|
21
23
|
}
|
|
22
24
|
|
|
@@ -156,8 +158,10 @@ async function exec(command, options = {}) {
|
|
|
156
158
|
async function history(options = {}) {
|
|
157
159
|
try {
|
|
158
160
|
// Check authentication
|
|
159
|
-
if (!
|
|
160
|
-
logger.error('Not logged in
|
|
161
|
+
if (!(await ensureAuthenticated())) {
|
|
162
|
+
logger.error('Not logged in');
|
|
163
|
+
logger.info('Run: saac login -e <email> -k <api-key>');
|
|
164
|
+
logger.info('Or set: SAAC_USER_API_KEY and SAAC_USER_EMAIL');
|
|
161
165
|
process.exit(1);
|
|
162
166
|
}
|
|
163
167
|
|
package/src/commands/git.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
const oauth = require('../lib/oauth');
|
|
6
6
|
const api = require('../lib/api');
|
|
7
|
-
const {
|
|
7
|
+
const { ensureAuthenticated, getUser } = require('../lib/config');
|
|
8
8
|
const logger = require('../lib/logger');
|
|
9
9
|
const { table } = require('table');
|
|
10
10
|
const inquirer = require('inquirer');
|
|
@@ -15,11 +15,10 @@ const inquirer = require('inquirer');
|
|
|
15
15
|
async function connect(host) {
|
|
16
16
|
try {
|
|
17
17
|
// Check authentication
|
|
18
|
-
if (!
|
|
18
|
+
if (!(await ensureAuthenticated())) {
|
|
19
19
|
logger.error('Not logged in');
|
|
20
|
-
logger.
|
|
21
|
-
logger.info('
|
|
22
|
-
logger.log(' saac login -e <email> -k <api-key>');
|
|
20
|
+
logger.info('Run: saac login -e <email> -k <api-key>');
|
|
21
|
+
logger.info('Or set: SAAC_USER_API_KEY and SAAC_USER_EMAIL');
|
|
23
22
|
process.exit(1);
|
|
24
23
|
}
|
|
25
24
|
|
|
@@ -116,11 +115,10 @@ async function connect(host) {
|
|
|
116
115
|
async function list() {
|
|
117
116
|
try {
|
|
118
117
|
// Check authentication
|
|
119
|
-
if (!
|
|
118
|
+
if (!(await ensureAuthenticated())) {
|
|
120
119
|
logger.error('Not logged in');
|
|
121
|
-
logger.
|
|
122
|
-
logger.info('
|
|
123
|
-
logger.log(' saac login -e <email> -k <api-key>');
|
|
120
|
+
logger.info('Run: saac login -e <email> -k <api-key>');
|
|
121
|
+
logger.info('Or set: SAAC_USER_API_KEY and SAAC_USER_EMAIL');
|
|
124
122
|
process.exit(1);
|
|
125
123
|
}
|
|
126
124
|
|
|
@@ -193,11 +191,10 @@ async function list() {
|
|
|
193
191
|
async function disconnect(host) {
|
|
194
192
|
try {
|
|
195
193
|
// Check authentication
|
|
196
|
-
if (!
|
|
194
|
+
if (!(await ensureAuthenticated())) {
|
|
197
195
|
logger.error('Not logged in');
|
|
198
|
-
logger.
|
|
199
|
-
logger.info('
|
|
200
|
-
logger.log(' saac login -e <email> -k <api-key>');
|
|
196
|
+
logger.info('Run: saac login -e <email> -k <api-key>');
|
|
197
|
+
logger.info('Or set: SAAC_USER_API_KEY and SAAC_USER_EMAIL');
|
|
201
198
|
process.exit(1);
|
|
202
199
|
}
|
|
203
200
|
|
|
@@ -254,11 +251,10 @@ async function disconnect(host) {
|
|
|
254
251
|
async function repos(gitHost, options) {
|
|
255
252
|
try {
|
|
256
253
|
// Check authentication
|
|
257
|
-
if (!
|
|
254
|
+
if (!(await ensureAuthenticated())) {
|
|
258
255
|
logger.error('Not logged in');
|
|
259
|
-
logger.
|
|
260
|
-
logger.info('
|
|
261
|
-
logger.log(' saac login -e <email> -k <api-key>');
|
|
256
|
+
logger.info('Run: saac login -e <email> -k <api-key>');
|
|
257
|
+
logger.info('Or set: SAAC_USER_API_KEY and SAAC_USER_EMAIL');
|
|
262
258
|
process.exit(1);
|
|
263
259
|
}
|
|
264
260
|
|
package/src/commands/init.js
CHANGED
|
@@ -7,18 +7,20 @@
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
const api = require('../lib/api');
|
|
10
|
-
const {
|
|
10
|
+
const { ensureAuthenticated, saveProjectConfig, getProjectConfig } = require('../lib/config');
|
|
11
11
|
const logger = require('../lib/logger');
|
|
12
12
|
const inquirer = require('inquirer');
|
|
13
|
+
const { execSync } = require('child_process');
|
|
14
|
+
const fs = require('fs');
|
|
15
|
+
const path = require('path');
|
|
13
16
|
|
|
14
17
|
async function init(options) {
|
|
15
18
|
try {
|
|
16
|
-
// Check authentication
|
|
17
|
-
if (!
|
|
19
|
+
// Check authentication (with auto-login support)
|
|
20
|
+
if (!(await ensureAuthenticated())) {
|
|
18
21
|
logger.error('Not logged in');
|
|
19
|
-
logger.
|
|
20
|
-
logger.info('
|
|
21
|
-
logger.log(' saac login -e <email> -k <api-key>');
|
|
22
|
+
logger.info('Run: saac login -e <email> -k <api-key>');
|
|
23
|
+
logger.info('Or set: SAAC_USER_API_KEY and SAAC_USER_EMAIL');
|
|
22
24
|
process.exit(1);
|
|
23
25
|
}
|
|
24
26
|
|
|
@@ -86,11 +88,58 @@ async function createAndInitialize(options) {
|
|
|
86
88
|
// This would call the create command functionality, then save the config
|
|
87
89
|
}
|
|
88
90
|
|
|
91
|
+
/**
|
|
92
|
+
* Get Git remote URL from current directory
|
|
93
|
+
* @returns {string|null} - Git remote URL or null if not a git repo
|
|
94
|
+
*/
|
|
95
|
+
function getGitRemoteUrl() {
|
|
96
|
+
try {
|
|
97
|
+
// Check if .git directory exists
|
|
98
|
+
if (!fs.existsSync(path.join(process.cwd(), '.git'))) {
|
|
99
|
+
return null;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Get remote.origin.url
|
|
103
|
+
const remoteUrl = execSync('git config --get remote.origin.url', {
|
|
104
|
+
encoding: 'utf8',
|
|
105
|
+
stdio: ['pipe', 'pipe', 'ignore'] // Suppress stderr
|
|
106
|
+
}).trim();
|
|
107
|
+
|
|
108
|
+
return remoteUrl || null;
|
|
109
|
+
} catch (error) {
|
|
110
|
+
// Not a git repo or no remote configured
|
|
111
|
+
return null;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Normalize Git URLs for comparison
|
|
117
|
+
* Converts both SSH and HTTPS URLs to a comparable format
|
|
118
|
+
*/
|
|
119
|
+
function normalizeGitUrl(url) {
|
|
120
|
+
if (!url) return '';
|
|
121
|
+
|
|
122
|
+
// Remove .git suffix
|
|
123
|
+
let normalized = url.replace(/\.git$/, '');
|
|
124
|
+
|
|
125
|
+
// Convert SSH to HTTPS-like format for comparison
|
|
126
|
+
// git@github.com:user/repo -> github.com/user/repo
|
|
127
|
+
normalized = normalized.replace(/^git@([^:]+):/, '$1/');
|
|
128
|
+
|
|
129
|
+
// Remove https:// or http://
|
|
130
|
+
normalized = normalized.replace(/^https?:\/\//, '');
|
|
131
|
+
|
|
132
|
+
return normalized.toLowerCase();
|
|
133
|
+
}
|
|
134
|
+
|
|
89
135
|
/**
|
|
90
136
|
* Link an existing application to current directory (interactive)
|
|
91
137
|
*/
|
|
92
138
|
async function linkExistingApplication() {
|
|
93
139
|
|
|
140
|
+
// Try to auto-detect Git repository
|
|
141
|
+
const gitRemoteUrl = getGitRemoteUrl();
|
|
142
|
+
|
|
94
143
|
// Fetch user's applications
|
|
95
144
|
const spin = logger.spinner('Fetching your applications...').start();
|
|
96
145
|
|
|
@@ -111,20 +160,67 @@ async function linkExistingApplication() {
|
|
|
111
160
|
|
|
112
161
|
logger.newline();
|
|
113
162
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
163
|
+
let selectedApp = null;
|
|
164
|
+
|
|
165
|
+
// Try to auto-match based on Git remote URL
|
|
166
|
+
if (gitRemoteUrl) {
|
|
167
|
+
const normalizedRemote = normalizeGitUrl(gitRemoteUrl);
|
|
168
|
+
|
|
169
|
+
const matchedApp = applications.find(app => {
|
|
170
|
+
if (!app.git_repository) return false;
|
|
171
|
+
const normalizedAppRepo = normalizeGitUrl(app.git_repository);
|
|
172
|
+
return normalizedAppRepo === normalizedRemote;
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
if (matchedApp) {
|
|
176
|
+
// Found matching application!
|
|
177
|
+
logger.info(`Auto-detected Git repository: ${gitRemoteUrl}`);
|
|
178
|
+
logger.newline();
|
|
179
|
+
logger.field('Matched Application', matchedApp.name);
|
|
180
|
+
logger.field('Domain', matchedApp.domain || `${matchedApp.subdomain}.startanaicompany.com`);
|
|
181
|
+
logger.field('Status', matchedApp.status);
|
|
182
|
+
logger.newline();
|
|
183
|
+
|
|
184
|
+
const { confirm } = await inquirer.prompt([
|
|
185
|
+
{
|
|
186
|
+
type: 'confirm',
|
|
187
|
+
name: 'confirm',
|
|
188
|
+
message: 'Link this application to the current directory?',
|
|
189
|
+
default: true,
|
|
190
|
+
},
|
|
191
|
+
]);
|
|
192
|
+
|
|
193
|
+
if (confirm) {
|
|
194
|
+
selectedApp = matchedApp;
|
|
195
|
+
} else {
|
|
196
|
+
logger.newline();
|
|
197
|
+
logger.info('Please select a different application:');
|
|
198
|
+
logger.newline();
|
|
199
|
+
}
|
|
200
|
+
} else {
|
|
201
|
+
logger.warn(`No application found matching Git remote: ${gitRemoteUrl}`);
|
|
202
|
+
logger.newline();
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// If no auto-match or user declined, show interactive selection
|
|
207
|
+
if (!selectedApp) {
|
|
208
|
+
const choices = applications.map(app => ({
|
|
209
|
+
name: `${app.name} - ${app.domain || `${app.subdomain}.startanaicompany.com`} (${app.status})`,
|
|
210
|
+
value: app,
|
|
211
|
+
}));
|
|
212
|
+
|
|
213
|
+
const answer = await inquirer.prompt([
|
|
214
|
+
{
|
|
215
|
+
type: 'list',
|
|
216
|
+
name: 'selectedApp',
|
|
217
|
+
message: 'Select application to link to this directory:',
|
|
218
|
+
choices: choices,
|
|
219
|
+
},
|
|
220
|
+
]);
|
|
221
|
+
|
|
222
|
+
selectedApp = answer.selectedApp;
|
|
223
|
+
}
|
|
128
224
|
|
|
129
225
|
logger.newline();
|
|
130
226
|
|
package/src/commands/keys.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
const api = require('../lib/api');
|
|
6
|
-
const { getUser,
|
|
6
|
+
const { getUser, ensureAuthenticated } = require('../lib/config');
|
|
7
7
|
const logger = require('../lib/logger');
|
|
8
8
|
const inquirer = require('inquirer');
|
|
9
9
|
|
|
@@ -13,7 +13,7 @@ const inquirer = require('inquirer');
|
|
|
13
13
|
async function regenerate() {
|
|
14
14
|
try {
|
|
15
15
|
// Must be authenticated (via session token)
|
|
16
|
-
if (!
|
|
16
|
+
if (!(await ensureAuthenticated())) {
|
|
17
17
|
logger.error('Not logged in');
|
|
18
18
|
logger.newline();
|
|
19
19
|
logger.info('You must be logged in to regenerate your API key');
|
|
@@ -21,6 +21,10 @@ async function regenerate() {
|
|
|
21
21
|
logger.info('Login using email verification:');
|
|
22
22
|
logger.log(' saac login -e <email> # Request OTP');
|
|
23
23
|
logger.log(' saac login -e <email> --otp <code> # Verify OTP');
|
|
24
|
+
logger.newline();
|
|
25
|
+
logger.info('Or set environment variables:');
|
|
26
|
+
logger.log(' export SAAC_USER_API_KEY=your_api_key');
|
|
27
|
+
logger.log(' export SAAC_USER_EMAIL=your_email');
|
|
24
28
|
process.exit(1);
|
|
25
29
|
}
|
|
26
30
|
|
|
@@ -83,61 +87,6 @@ async function regenerate() {
|
|
|
83
87
|
}
|
|
84
88
|
}
|
|
85
89
|
|
|
86
|
-
/**
|
|
87
|
-
* Show API key info (without revealing full key)
|
|
88
|
-
*/
|
|
89
|
-
async function show() {
|
|
90
|
-
try {
|
|
91
|
-
if (!isAuthenticated()) {
|
|
92
|
-
logger.error('Not logged in');
|
|
93
|
-
logger.newline();
|
|
94
|
-
logger.info('Login first:');
|
|
95
|
-
logger.log(' saac login -e <email>');
|
|
96
|
-
process.exit(1);
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
logger.section('API Key Information');
|
|
100
|
-
logger.newline();
|
|
101
|
-
|
|
102
|
-
const spin = logger.spinner('Fetching API key info...').start();
|
|
103
|
-
|
|
104
|
-
try {
|
|
105
|
-
const result = await api.getApiKeyInfo();
|
|
106
|
-
|
|
107
|
-
spin.succeed('API key info retrieved');
|
|
108
|
-
|
|
109
|
-
logger.newline();
|
|
110
|
-
logger.field('Key Prefix', result.key_prefix); // e.g., "cw_RJ1gH8..."
|
|
111
|
-
logger.field('Created', new Date(result.created_at).toLocaleDateString());
|
|
112
|
-
logger.field('Last Used', result.last_used_at
|
|
113
|
-
? new Date(result.last_used_at).toLocaleString()
|
|
114
|
-
: 'Never');
|
|
115
|
-
|
|
116
|
-
logger.newline();
|
|
117
|
-
logger.info('Commands:');
|
|
118
|
-
logger.log(' saac keys regenerate Generate new API key');
|
|
119
|
-
logger.log(' saac sessions View active sessions');
|
|
120
|
-
|
|
121
|
-
} catch (error) {
|
|
122
|
-
spin.fail('Failed to fetch API key info');
|
|
123
|
-
|
|
124
|
-
// If endpoint doesn't exist yet, show helpful message
|
|
125
|
-
if (error.response?.status === 404) {
|
|
126
|
-
logger.newline();
|
|
127
|
-
logger.warn('API key info endpoint not available yet');
|
|
128
|
-
logger.info('You can still regenerate your key with:');
|
|
129
|
-
logger.log(' saac keys regenerate');
|
|
130
|
-
} else {
|
|
131
|
-
throw error;
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
} catch (error) {
|
|
135
|
-
logger.error(error.response?.data?.message || error.message);
|
|
136
|
-
process.exit(1);
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
|
|
140
90
|
module.exports = {
|
|
141
91
|
regenerate,
|
|
142
|
-
show,
|
|
143
92
|
};
|
package/src/commands/list.js
CHANGED
|
@@ -3,18 +3,17 @@
|
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
const api = require('../lib/api');
|
|
6
|
-
const {
|
|
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 list() {
|
|
11
11
|
try {
|
|
12
|
-
// Check authentication
|
|
13
|
-
if (!
|
|
12
|
+
// Check authentication (with auto-login support)
|
|
13
|
+
if (!(await ensureAuthenticated())) {
|
|
14
14
|
logger.error('Not logged in');
|
|
15
|
-
logger.
|
|
16
|
-
logger.info('
|
|
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
|
|