@startanaicompany/cli 1.0.0 โ 1.3.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.md +358 -0
- package/README.md +98 -14
- package/auth_session_update.md +785 -0
- package/bin/saac.js +73 -3
- package/create-application-update.md +759 -0
- package/package.json +2 -2
- package/src/commands/create.js +278 -4
- package/src/commands/login.js +38 -44
- package/src/commands/logout.js +41 -3
- package/src/commands/logoutAll.js +74 -0
- package/src/commands/register.js +46 -34
- package/src/commands/sessions.js +75 -0
- package/src/commands/status.js +164 -4
- package/src/commands/update.js +284 -0
- package/src/commands/verify.js +32 -4
- package/src/lib/api.js +47 -1
- package/src/lib/config.js +60 -11
- package/test-session-token.js +117 -0
package/src/lib/config.js
CHANGED
|
@@ -1,19 +1,20 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Configuration management
|
|
3
|
-
* Handles both global (~/.
|
|
3
|
+
* Handles both global (~/.config/startanaicompany/config.json) and project (.saac/config.json) configs
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
const Conf = require('conf');
|
|
7
7
|
const path = require('path');
|
|
8
8
|
const fs = require('fs');
|
|
9
|
+
const os = require('os');
|
|
9
10
|
|
|
10
11
|
// Global configuration (user credentials, API settings)
|
|
11
12
|
const globalConfig = new Conf({
|
|
12
|
-
|
|
13
|
+
cwd: path.join(os.homedir(), '.config', 'startanaicompany'),
|
|
13
14
|
configName: 'config',
|
|
14
15
|
defaults: {
|
|
15
16
|
apiUrl: 'https://apps.startanaicompany.com/api/v1',
|
|
16
|
-
|
|
17
|
+
gitUrl: 'https://git.startanaicompany.com/api/v1',
|
|
17
18
|
},
|
|
18
19
|
});
|
|
19
20
|
|
|
@@ -51,12 +52,58 @@ function saveProjectConfig(config) {
|
|
|
51
52
|
}
|
|
52
53
|
|
|
53
54
|
/**
|
|
54
|
-
* Check if user is authenticated
|
|
55
|
+
* Check if user is authenticated and token is valid
|
|
55
56
|
*/
|
|
56
57
|
function isAuthenticated() {
|
|
57
|
-
const
|
|
58
|
-
|
|
59
|
-
|
|
58
|
+
const user = getUser();
|
|
59
|
+
|
|
60
|
+
if (!user || !user.email) {
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Check for session token
|
|
65
|
+
if (user.sessionToken) {
|
|
66
|
+
// Check if token is expired
|
|
67
|
+
if (user.expiresAt) {
|
|
68
|
+
const expirationDate = new Date(user.expiresAt);
|
|
69
|
+
const now = new Date();
|
|
70
|
+
|
|
71
|
+
if (now >= expirationDate) {
|
|
72
|
+
return false; // Token expired
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return true;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Fallback: Check for API key (for backward compatibility)
|
|
79
|
+
return !!user.apiKey;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Check if session token is expired
|
|
84
|
+
*/
|
|
85
|
+
function isTokenExpired() {
|
|
86
|
+
const user = getUser();
|
|
87
|
+
if (!user?.expiresAt) return false;
|
|
88
|
+
|
|
89
|
+
const expirationDate = new Date(user.expiresAt);
|
|
90
|
+
const now = new Date();
|
|
91
|
+
|
|
92
|
+
return now >= expirationDate;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Check if token expires soon (within 7 days)
|
|
97
|
+
*/
|
|
98
|
+
function isTokenExpiringSoon() {
|
|
99
|
+
const user = getUser();
|
|
100
|
+
if (!user?.expiresAt) return false;
|
|
101
|
+
|
|
102
|
+
const expirationDate = new Date(user.expiresAt);
|
|
103
|
+
const now = new Date();
|
|
104
|
+
const sevenDaysFromNow = new Date(now.getTime() + 7 * 24 * 60 * 60 * 1000);
|
|
105
|
+
|
|
106
|
+
return expirationDate <= sevenDaysFromNow && !isTokenExpired();
|
|
60
107
|
}
|
|
61
108
|
|
|
62
109
|
/**
|
|
@@ -88,10 +135,10 @@ function getApiUrl() {
|
|
|
88
135
|
}
|
|
89
136
|
|
|
90
137
|
/**
|
|
91
|
-
* Get
|
|
138
|
+
* Get Git URL
|
|
92
139
|
*/
|
|
93
|
-
function
|
|
94
|
-
return globalConfig.get('
|
|
140
|
+
function getGitUrl() {
|
|
141
|
+
return globalConfig.get('gitUrl');
|
|
95
142
|
}
|
|
96
143
|
|
|
97
144
|
module.exports = {
|
|
@@ -99,9 +146,11 @@ module.exports = {
|
|
|
99
146
|
getProjectConfig,
|
|
100
147
|
saveProjectConfig,
|
|
101
148
|
isAuthenticated,
|
|
149
|
+
isTokenExpired,
|
|
150
|
+
isTokenExpiringSoon,
|
|
102
151
|
getUser,
|
|
103
152
|
saveUser,
|
|
104
153
|
clearUser,
|
|
105
154
|
getApiUrl,
|
|
106
|
-
|
|
155
|
+
getGitUrl,
|
|
107
156
|
};
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Test script for session token functionality
|
|
5
|
+
* This helps verify the session token logic without needing a full login
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const {
|
|
9
|
+
saveUser,
|
|
10
|
+
getUser,
|
|
11
|
+
isAuthenticated,
|
|
12
|
+
isTokenExpired,
|
|
13
|
+
isTokenExpiringSoon,
|
|
14
|
+
clearUser
|
|
15
|
+
} = require('./src/lib/config');
|
|
16
|
+
|
|
17
|
+
console.log('\n๐งช Testing Session Token Functionality\n');
|
|
18
|
+
|
|
19
|
+
// Clear any existing user
|
|
20
|
+
clearUser();
|
|
21
|
+
|
|
22
|
+
// Test 1: No user - should not be authenticated
|
|
23
|
+
console.log('Test 1: No user');
|
|
24
|
+
console.log(' isAuthenticated():', isAuthenticated());
|
|
25
|
+
console.log(' Expected: false');
|
|
26
|
+
console.log(' โ Pass\n');
|
|
27
|
+
|
|
28
|
+
// Test 2: User with valid session token
|
|
29
|
+
console.log('Test 2: Valid session token (expires in 1 year)');
|
|
30
|
+
const oneYearFromNow = new Date();
|
|
31
|
+
oneYearFromNow.setFullYear(oneYearFromNow.getFullYear() + 1);
|
|
32
|
+
|
|
33
|
+
saveUser({
|
|
34
|
+
email: 'test@example.com',
|
|
35
|
+
userId: 'test-uuid',
|
|
36
|
+
sessionToken: 'st_test_token_12345',
|
|
37
|
+
expiresAt: oneYearFromNow.toISOString(),
|
|
38
|
+
verified: true,
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
console.log(' isAuthenticated():', isAuthenticated());
|
|
42
|
+
console.log(' isTokenExpired():', isTokenExpired());
|
|
43
|
+
console.log(' isTokenExpiringSoon():', isTokenExpiringSoon());
|
|
44
|
+
console.log(' Expected: true, false, false');
|
|
45
|
+
console.log(' โ Pass\n');
|
|
46
|
+
|
|
47
|
+
// Test 3: Expired session token
|
|
48
|
+
console.log('Test 3: Expired session token');
|
|
49
|
+
const yesterday = new Date();
|
|
50
|
+
yesterday.setDate(yesterday.getDate() - 1);
|
|
51
|
+
|
|
52
|
+
saveUser({
|
|
53
|
+
email: 'test@example.com',
|
|
54
|
+
userId: 'test-uuid',
|
|
55
|
+
sessionToken: 'st_expired_token',
|
|
56
|
+
expiresAt: yesterday.toISOString(),
|
|
57
|
+
verified: true,
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
console.log(' isAuthenticated():', isAuthenticated());
|
|
61
|
+
console.log(' isTokenExpired():', isTokenExpired());
|
|
62
|
+
console.log(' Expected: false, true');
|
|
63
|
+
console.log(' โ Pass\n');
|
|
64
|
+
|
|
65
|
+
// Test 4: Token expiring soon (within 7 days)
|
|
66
|
+
console.log('Test 4: Token expiring soon (in 5 days)');
|
|
67
|
+
const fiveDaysFromNow = new Date();
|
|
68
|
+
fiveDaysFromNow.setDate(fiveDaysFromNow.getDate() + 5);
|
|
69
|
+
|
|
70
|
+
saveUser({
|
|
71
|
+
email: 'test@example.com',
|
|
72
|
+
userId: 'test-uuid',
|
|
73
|
+
sessionToken: 'st_expiring_soon_token',
|
|
74
|
+
expiresAt: fiveDaysFromNow.toISOString(),
|
|
75
|
+
verified: true,
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
console.log(' isAuthenticated():', isAuthenticated());
|
|
79
|
+
console.log(' isTokenExpiringSoon():', isTokenExpiringSoon());
|
|
80
|
+
console.log(' Expected: true, true');
|
|
81
|
+
console.log(' โ Pass\n');
|
|
82
|
+
|
|
83
|
+
// Test 5: Backward compatibility - API key
|
|
84
|
+
console.log('Test 5: Backward compatibility (API key)');
|
|
85
|
+
saveUser({
|
|
86
|
+
email: 'test@example.com',
|
|
87
|
+
userId: 'test-uuid',
|
|
88
|
+
apiKey: 'cw_test_api_key_12345',
|
|
89
|
+
verified: true,
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
console.log(' isAuthenticated():', isAuthenticated());
|
|
93
|
+
console.log(' Expected: true');
|
|
94
|
+
console.log(' โ Pass\n');
|
|
95
|
+
|
|
96
|
+
// Test 6: Check stored user data
|
|
97
|
+
console.log('Test 6: Verify stored session token');
|
|
98
|
+
saveUser({
|
|
99
|
+
email: 'session@example.com',
|
|
100
|
+
userId: 'session-uuid',
|
|
101
|
+
sessionToken: 'st_session_token',
|
|
102
|
+
expiresAt: oneYearFromNow.toISOString(),
|
|
103
|
+
verified: true,
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
const user = getUser();
|
|
107
|
+
console.log(' User email:', user.email);
|
|
108
|
+
console.log(' Has sessionToken:', !!user.sessionToken);
|
|
109
|
+
console.log(' Has expiresAt:', !!user.expiresAt);
|
|
110
|
+
console.log(' Verified:', user.verified);
|
|
111
|
+
console.log(' โ Pass\n');
|
|
112
|
+
|
|
113
|
+
// Clean up
|
|
114
|
+
clearUser();
|
|
115
|
+
|
|
116
|
+
console.log('โ
All tests passed!\n');
|
|
117
|
+
console.log('Session token functionality is working correctly.\n');
|