@husar.ai/cli 0.4.0 → 0.4.2
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/AGENTS.md +835 -0
- package/MCP_SERVER.md +92 -0
- package/dist/auth/api.d.ts +15 -0
- package/dist/auth/api.js +86 -0
- package/dist/auth/api.js.map +1 -0
- package/dist/auth/config.d.ts +32 -0
- package/dist/auth/config.js +95 -0
- package/dist/auth/config.js.map +1 -0
- package/dist/auth/login.d.ts +30 -0
- package/dist/auth/login.js +450 -0
- package/dist/auth/login.js.map +1 -0
- package/dist/cli.js +83 -3
- package/dist/cli.js.map +1 -1
- package/dist/functions/create.d.ts +6 -0
- package/dist/functions/create.js +311 -0
- package/dist/functions/create.js.map +1 -0
- package/dist/mcp.js +20 -14
- package/dist/mcp.js.map +1 -1
- package/dist/types/config.d.ts +3 -1
- package/dist/types/config.js +12 -1
- package/dist/types/config.js.map +1 -1
- package/dist/zeus/const.js +1410 -218
- package/dist/zeus/const.js.map +1 -1
- package/dist/zeus/index.d.ts +6889 -1508
- package/dist/zeus/index.js +197 -11
- package/dist/zeus/index.js.map +1 -1
- package/package.json +3 -3
- package/src/auth/api.ts +133 -0
- package/src/auth/config.ts +198 -0
- package/src/auth/login.ts +631 -0
- package/src/cli.ts +96 -4
- package/src/functions/create.ts +489 -0
- package/src/mcp.ts +47 -27
- package/src/types/config.ts +32 -1
- package/src/zeus/const.ts +1418 -218
- package/src/zeus/index.ts +6969 -1611
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auth configuration storage for Husar CLI
|
|
3
|
+
* Stores user credentials in ~/.husar/config.json
|
|
4
|
+
*
|
|
5
|
+
* SECURITY: Files are created with restrictive permissions (0o600)
|
|
6
|
+
* to prevent other users from reading sensitive tokens.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { promises as fs } from 'node:fs';
|
|
10
|
+
import { homedir } from 'node:os';
|
|
11
|
+
import { join } from 'node:path';
|
|
12
|
+
|
|
13
|
+
const CONFIG_DIR = join(homedir(), '.husar');
|
|
14
|
+
const CONFIG_FILE = join(CONFIG_DIR, 'config.json');
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* File permission modes for secure storage
|
|
18
|
+
* - 0o700: Directory - owner can read/write/execute, no access for others
|
|
19
|
+
* - 0o600: File - owner can read/write, no access for others
|
|
20
|
+
*
|
|
21
|
+
* Note: These permissions only apply on Unix-like systems (macOS, Linux).
|
|
22
|
+
* On Windows, Node.js ignores the mode parameter and uses ACLs instead.
|
|
23
|
+
*/
|
|
24
|
+
const DIR_MODE = 0o700;
|
|
25
|
+
const FILE_MODE = 0o600;
|
|
26
|
+
|
|
27
|
+
export interface AuthConfig {
|
|
28
|
+
/** User's email address */
|
|
29
|
+
email?: string;
|
|
30
|
+
/** Access token from cloud backend */
|
|
31
|
+
accessToken?: string;
|
|
32
|
+
/** Refresh token for re-authentication */
|
|
33
|
+
refreshToken?: string;
|
|
34
|
+
/** Timestamp when the token was last refreshed */
|
|
35
|
+
lastRefresh?: number;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Cloud authentication data (JWT from husar.ai OAuth)
|
|
40
|
+
*/
|
|
41
|
+
export interface CloudAuth {
|
|
42
|
+
/** User's email address */
|
|
43
|
+
email?: string;
|
|
44
|
+
/** JWT access token from cloud backend */
|
|
45
|
+
accessToken: string;
|
|
46
|
+
/** Refresh token for re-authentication (optional) */
|
|
47
|
+
refreshToken?: string;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export interface ProjectAuth {
|
|
51
|
+
/** Project name */
|
|
52
|
+
projectName: string;
|
|
53
|
+
/** CMS instance host URL */
|
|
54
|
+
host: string;
|
|
55
|
+
/** Admin token for the CMS instance */
|
|
56
|
+
adminToken: string;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export interface FullAuthConfig extends AuthConfig {
|
|
60
|
+
/** Cached project authentications */
|
|
61
|
+
projects?: Record<string, ProjectAuth>;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Ensure the config directory exists with secure permissions
|
|
66
|
+
*/
|
|
67
|
+
async function ensureConfigDir(): Promise<void> {
|
|
68
|
+
try {
|
|
69
|
+
await fs.mkdir(CONFIG_DIR, { recursive: true, mode: DIR_MODE });
|
|
70
|
+
} catch (err) {
|
|
71
|
+
// Directory already exists - verify permissions are secure
|
|
72
|
+
try {
|
|
73
|
+
await fs.chmod(CONFIG_DIR, DIR_MODE);
|
|
74
|
+
} catch {
|
|
75
|
+
// chmod may fail on some systems, continue anyway
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Read the auth configuration
|
|
82
|
+
*/
|
|
83
|
+
export async function readAuthConfig(): Promise<FullAuthConfig> {
|
|
84
|
+
try {
|
|
85
|
+
await ensureConfigDir();
|
|
86
|
+
const content = await fs.readFile(CONFIG_FILE, 'utf-8');
|
|
87
|
+
return JSON.parse(content) as FullAuthConfig;
|
|
88
|
+
} catch {
|
|
89
|
+
return {};
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Write the auth configuration with secure file permissions
|
|
95
|
+
*/
|
|
96
|
+
export async function writeAuthConfig(config: FullAuthConfig): Promise<void> {
|
|
97
|
+
await ensureConfigDir();
|
|
98
|
+
await fs.writeFile(CONFIG_FILE, JSON.stringify(config, null, 2), { encoding: 'utf-8', mode: FILE_MODE });
|
|
99
|
+
|
|
100
|
+
// Also ensure permissions are correct for existing files
|
|
101
|
+
try {
|
|
102
|
+
await fs.chmod(CONFIG_FILE, FILE_MODE);
|
|
103
|
+
} catch {
|
|
104
|
+
// chmod may fail on some systems (e.g., Windows), continue anyway
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Check if the user is logged in
|
|
110
|
+
*/
|
|
111
|
+
export async function isLoggedIn(): Promise<boolean> {
|
|
112
|
+
const config = await readAuthConfig();
|
|
113
|
+
return !!(config.accessToken && config.email);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Get the current user info
|
|
118
|
+
*/
|
|
119
|
+
export async function getCurrentUser(): Promise<{ email: string } | null> {
|
|
120
|
+
const config = await readAuthConfig();
|
|
121
|
+
if (!config.accessToken || !config.email) {
|
|
122
|
+
return null;
|
|
123
|
+
}
|
|
124
|
+
return { email: config.email };
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Save login credentials
|
|
129
|
+
*/
|
|
130
|
+
export async function saveLogin(email: string, accessToken: string, refreshToken?: string): Promise<void> {
|
|
131
|
+
const config = await readAuthConfig();
|
|
132
|
+
config.email = email;
|
|
133
|
+
config.accessToken = accessToken;
|
|
134
|
+
config.refreshToken = refreshToken;
|
|
135
|
+
config.lastRefresh = Date.now();
|
|
136
|
+
await writeAuthConfig(config);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Save cloud authentication (JWT from OAuth)
|
|
141
|
+
*/
|
|
142
|
+
export async function saveCloudAuth(cloudAuth: CloudAuth): Promise<void> {
|
|
143
|
+
const config = await readAuthConfig();
|
|
144
|
+
config.email = cloudAuth.email;
|
|
145
|
+
config.accessToken = cloudAuth.accessToken;
|
|
146
|
+
config.refreshToken = cloudAuth.refreshToken;
|
|
147
|
+
config.lastRefresh = Date.now();
|
|
148
|
+
await writeAuthConfig(config);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Get cloud authentication (JWT)
|
|
153
|
+
*/
|
|
154
|
+
export async function getCloudAuth(): Promise<CloudAuth | null> {
|
|
155
|
+
const config = await readAuthConfig();
|
|
156
|
+
if (!config.accessToken) {
|
|
157
|
+
return null;
|
|
158
|
+
}
|
|
159
|
+
return {
|
|
160
|
+
email: config.email,
|
|
161
|
+
accessToken: config.accessToken,
|
|
162
|
+
refreshToken: config.refreshToken,
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Save project authentication
|
|
168
|
+
*/
|
|
169
|
+
export async function saveProjectAuth(project: ProjectAuth): Promise<void> {
|
|
170
|
+
const config = await readAuthConfig();
|
|
171
|
+
if (!config.projects) {
|
|
172
|
+
config.projects = {};
|
|
173
|
+
}
|
|
174
|
+
config.projects[project.projectName] = project;
|
|
175
|
+
await writeAuthConfig(config);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Get project authentication
|
|
180
|
+
*/
|
|
181
|
+
export async function getProjectAuth(projectName: string): Promise<ProjectAuth | null> {
|
|
182
|
+
const config = await readAuthConfig();
|
|
183
|
+
return config.projects?.[projectName] ?? null;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Clear all auth data (logout)
|
|
188
|
+
*/
|
|
189
|
+
export async function clearAuth(): Promise<void> {
|
|
190
|
+
await writeAuthConfig({});
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Get the config file path (for display purposes)
|
|
195
|
+
*/
|
|
196
|
+
export function getConfigPath(): string {
|
|
197
|
+
return CONFIG_FILE;
|
|
198
|
+
}
|