@agentuity/cli 0.1.32 → 0.1.33
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/dist/cmd/cloud/deploy.d.ts.map +1 -1
- package/dist/cmd/cloud/deploy.js +52 -2
- package/dist/cmd/cloud/deploy.js.map +1 -1
- package/dist/cmd/cloud/env/delete.d.ts.map +1 -1
- package/dist/cmd/cloud/env/delete.js +3 -4
- package/dist/cmd/cloud/env/delete.js.map +1 -1
- package/dist/cmd/cloud/env/import.d.ts.map +1 -1
- package/dist/cmd/cloud/env/import.js +4 -6
- package/dist/cmd/cloud/env/import.js.map +1 -1
- package/dist/cmd/cloud/env/pull.d.ts.map +1 -1
- package/dist/cmd/cloud/env/pull.js +17 -25
- package/dist/cmd/cloud/env/pull.js.map +1 -1
- package/dist/cmd/cloud/env/set.d.ts.map +1 -1
- package/dist/cmd/cloud/env/set.js +3 -6
- package/dist/cmd/cloud/env/set.js.map +1 -1
- package/dist/cmd/cloud/region-lookup.d.ts +2 -2
- package/dist/cmd/cloud/region-lookup.d.ts.map +1 -1
- package/dist/cmd/cloud/region-lookup.js +7 -3
- package/dist/cmd/cloud/region-lookup.js.map +1 -1
- package/dist/cmd/cloud/scp/download.d.ts.map +1 -1
- package/dist/cmd/cloud/scp/download.js +1 -1
- package/dist/cmd/cloud/scp/download.js.map +1 -1
- package/dist/cmd/cloud/scp/upload.d.ts.map +1 -1
- package/dist/cmd/cloud/scp/upload.js +1 -1
- package/dist/cmd/cloud/scp/upload.js.map +1 -1
- package/dist/cmd/cloud/ssh.d.ts.map +1 -1
- package/dist/cmd/cloud/ssh.js +1 -1
- package/dist/cmd/cloud/ssh.js.map +1 -1
- package/dist/cmd/cloud/storage/create.d.ts.map +1 -1
- package/dist/cmd/cloud/storage/create.js +7 -2
- package/dist/cmd/cloud/storage/create.js.map +1 -1
- package/dist/cmd/cloud/storage/get.d.ts.map +1 -1
- package/dist/cmd/cloud/storage/get.js +6 -0
- package/dist/cmd/cloud/storage/get.js.map +1 -1
- package/dist/cmd/cloud/storage/list.d.ts.map +1 -1
- package/dist/cmd/cloud/storage/list.js +6 -0
- package/dist/cmd/cloud/storage/list.js.map +1 -1
- package/dist/cmd/project/auth/init.d.ts.map +1 -1
- package/dist/cmd/project/auth/init.js +10 -21
- package/dist/cmd/project/auth/init.js.map +1 -1
- package/dist/config.d.ts +2 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +7 -2
- package/dist/config.js.map +1 -1
- package/dist/env-util.d.ts +8 -1
- package/dist/env-util.d.ts.map +1 -1
- package/dist/env-util.js +12 -3
- package/dist/env-util.js.map +1 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +4 -1
- package/dist/types.js.map +1 -1
- package/package.json +6 -6
- package/src/cmd/cloud/deploy.ts +71 -1
- package/src/cmd/cloud/env/delete.ts +2 -4
- package/src/cmd/cloud/env/import.ts +3 -8
- package/src/cmd/cloud/env/pull.ts +17 -26
- package/src/cmd/cloud/env/set.ts +2 -8
- package/src/cmd/cloud/region-lookup.ts +19 -4
- package/src/cmd/cloud/scp/download.ts +2 -1
- package/src/cmd/cloud/scp/upload.ts +2 -1
- package/src/cmd/cloud/ssh.ts +2 -1
- package/src/cmd/cloud/storage/create.ts +7 -2
- package/src/cmd/cloud/storage/get.ts +6 -0
- package/src/cmd/cloud/storage/list.ts +6 -0
- package/src/cmd/project/auth/init.ts +10 -22
- package/src/config.ts +10 -2
- package/src/env-util.ts +20 -3
- package/src/types.ts +4 -1
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
generateAuthSchemaSql,
|
|
13
13
|
getGeneratedSqlDir,
|
|
14
14
|
} from './shared';
|
|
15
|
+
import { readEnvFile, writeEnvFile } from '../../../env-util';
|
|
15
16
|
import enquirer from 'enquirer';
|
|
16
17
|
import * as fs from 'fs';
|
|
17
18
|
import * as path from 'path';
|
|
@@ -96,32 +97,23 @@ export const initSubcommand = createSubcommand({
|
|
|
96
97
|
|
|
97
98
|
const databaseName = dbInfo.name;
|
|
98
99
|
|
|
99
|
-
// Update .env with database URL
|
|
100
|
+
// Update .env with database URL using proper parsing
|
|
100
101
|
const envPath = path.join(projectDir, '.env');
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
if (fs.existsSync(envPath)) {
|
|
104
|
-
envContent = fs.readFileSync(envPath, 'utf-8');
|
|
105
|
-
if (!envContent.endsWith('\n') && envContent.length > 0) {
|
|
106
|
-
envContent += '\n';
|
|
107
|
-
}
|
|
108
|
-
}
|
|
102
|
+
const existingEnv = await readEnvFile(envPath);
|
|
109
103
|
|
|
110
104
|
// Check if DATABASE_URL already exists
|
|
111
|
-
const hasDatabaseUrl =
|
|
105
|
+
const hasDatabaseUrl = 'DATABASE_URL' in existingEnv;
|
|
112
106
|
|
|
113
107
|
if (dbInfo.url !== databaseUrl || !hasDatabaseUrl) {
|
|
114
108
|
if (hasDatabaseUrl) {
|
|
115
109
|
// DATABASE_URL exists, use AUTH_DATABASE_URL instead
|
|
116
|
-
|
|
117
|
-
fs.writeFileSync(envPath, envContent);
|
|
110
|
+
await writeEnvFile(envPath, { AUTH_DATABASE_URL: dbInfo.url });
|
|
118
111
|
tui.success('AUTH_DATABASE_URL added to .env');
|
|
119
112
|
tui.warning(
|
|
120
113
|
`DATABASE_URL already exists. Update your ${tui.bold('src/auth.ts')} to use AUTH_DATABASE_URL.`
|
|
121
114
|
);
|
|
122
115
|
} else {
|
|
123
|
-
|
|
124
|
-
fs.writeFileSync(envPath, envContent);
|
|
116
|
+
await writeEnvFile(envPath, { DATABASE_URL: dbInfo.url });
|
|
125
117
|
tui.success('DATABASE_URL added to .env');
|
|
126
118
|
}
|
|
127
119
|
} else {
|
|
@@ -129,18 +121,14 @@ export const initSubcommand = createSubcommand({
|
|
|
129
121
|
}
|
|
130
122
|
|
|
131
123
|
// Add AGENTUITY_AUTH_SECRET if not present
|
|
132
|
-
// Re-read
|
|
133
|
-
|
|
134
|
-
if (!envContent.endsWith('\n') && envContent.length > 0) {
|
|
135
|
-
envContent += '\n';
|
|
136
|
-
}
|
|
124
|
+
// Re-read env to get latest state
|
|
125
|
+
const currentEnv = await readEnvFile(envPath);
|
|
137
126
|
|
|
138
127
|
const hasAuthSecret =
|
|
139
|
-
|
|
128
|
+
'AGENTUITY_AUTH_SECRET' in currentEnv || 'BETTER_AUTH_SECRET' in currentEnv;
|
|
140
129
|
if (!hasAuthSecret) {
|
|
141
130
|
const devSecret = `dev-${crypto.randomUUID()}-CHANGE-ME`;
|
|
142
|
-
|
|
143
|
-
fs.writeFileSync(envPath, envContent);
|
|
131
|
+
await writeEnvFile(envPath, { AGENTUITY_AUTH_SECRET: devSecret });
|
|
144
132
|
tui.success('AGENTUITY_AUTH_SECRET added to .env (development default)');
|
|
145
133
|
tui.warning(
|
|
146
134
|
`Replace ${tui.bold('AGENTUITY_AUTH_SECRET')} with a secure value before deploying.`
|
package/src/config.ts
CHANGED
|
@@ -809,14 +809,16 @@ export async function getDefaultRegion(
|
|
|
809
809
|
* @param auth - Authentication data
|
|
810
810
|
* @param profileName - Profile name (default: 'production')
|
|
811
811
|
* @param orgId - Optional organization ID for CLI key authentication
|
|
812
|
+
* @param config - Optional config for region preference lookup
|
|
812
813
|
*/
|
|
813
814
|
export async function getGlobalCatalystAPIClient(
|
|
814
815
|
logger: Logger,
|
|
815
816
|
auth: AuthData,
|
|
816
817
|
profileName = 'production',
|
|
817
|
-
orgId?: string
|
|
818
|
+
orgId?: string,
|
|
819
|
+
config?: Config | null
|
|
818
820
|
) {
|
|
819
|
-
const region = await getDefaultRegion(profileName);
|
|
821
|
+
const region = await getDefaultRegion(profileName, config);
|
|
820
822
|
return getCatalystAPIClient(logger, auth, region, orgId);
|
|
821
823
|
}
|
|
822
824
|
|
|
@@ -828,6 +830,12 @@ export function getIONHost(config: Config | null, region: string) {
|
|
|
828
830
|
if (config?.name === 'local' || region === 'local') {
|
|
829
831
|
return 'ion.agentuity.io';
|
|
830
832
|
}
|
|
833
|
+
// Validate region is a non-empty string to prevent malformed hostnames
|
|
834
|
+
if (!region || typeof region !== 'string' || region.trim() === '') {
|
|
835
|
+
throw new Error(
|
|
836
|
+
`Invalid region: '${region}'. Region must be a non-empty string. Use --region flag to specify a valid region.`
|
|
837
|
+
);
|
|
838
|
+
}
|
|
831
839
|
return `ion-${region}.agentuity.cloud`;
|
|
832
840
|
}
|
|
833
841
|
|
package/src/env-util.ts
CHANGED
|
@@ -149,7 +149,8 @@ export async function readEnvFile(path: string): Promise<EnvVars> {
|
|
|
149
149
|
|
|
150
150
|
/**
|
|
151
151
|
* Write environment variables to an .env file
|
|
152
|
-
*
|
|
152
|
+
* By default, preserves existing keys that are not in the new vars.
|
|
153
|
+
* Use preserveExisting: false to completely overwrite the file.
|
|
153
154
|
*/
|
|
154
155
|
export async function writeEnvFile(
|
|
155
156
|
path: string,
|
|
@@ -157,20 +158,36 @@ export async function writeEnvFile(
|
|
|
157
158
|
options?: {
|
|
158
159
|
skipKeys?: string[];
|
|
159
160
|
addComment?: (key: string) => string | null;
|
|
161
|
+
/**
|
|
162
|
+
* When true (default), reads existing file first and merges with new vars.
|
|
163
|
+
* New vars take priority for matching keys, but all existing keys are preserved.
|
|
164
|
+
* When false, completely overwrites the file with only the provided vars.
|
|
165
|
+
*/
|
|
166
|
+
preserveExisting?: boolean;
|
|
160
167
|
}
|
|
161
168
|
): Promise<void> {
|
|
162
169
|
const skipKeys = options?.skipKeys || [];
|
|
170
|
+
const preserveExisting = options?.preserveExisting ?? true;
|
|
171
|
+
|
|
172
|
+
// If preserveExisting is true, read existing file and merge
|
|
173
|
+
let finalVars = vars;
|
|
174
|
+
if (preserveExisting) {
|
|
175
|
+
const existing = await readEnvFile(path);
|
|
176
|
+
// Merge: existing as base, new vars override
|
|
177
|
+
finalVars = { ...existing, ...vars };
|
|
178
|
+
}
|
|
179
|
+
|
|
163
180
|
const lines: string[] = [];
|
|
164
181
|
|
|
165
182
|
// Sort keys for consistent output
|
|
166
|
-
const sortedKeys = Object.keys(
|
|
183
|
+
const sortedKeys = Object.keys(finalVars).sort();
|
|
167
184
|
|
|
168
185
|
for (const key of sortedKeys) {
|
|
169
186
|
if (skipKeys.includes(key)) {
|
|
170
187
|
continue;
|
|
171
188
|
}
|
|
172
189
|
|
|
173
|
-
const value =
|
|
190
|
+
const value = finalVars[key];
|
|
174
191
|
|
|
175
192
|
// Add comment if provided
|
|
176
193
|
if (options?.addComment) {
|
package/src/types.ts
CHANGED
|
@@ -24,7 +24,10 @@ export const ConfigSchema = zod.object({
|
|
|
24
24
|
devmode: zod
|
|
25
25
|
.object({
|
|
26
26
|
hostname: zod.string().optional().describe('Development mode hostname'),
|
|
27
|
-
privateKey: zod
|
|
27
|
+
privateKey: zod
|
|
28
|
+
.string()
|
|
29
|
+
.optional()
|
|
30
|
+
.describe('Development mode private key (base64-encoded PEM)'),
|
|
28
31
|
})
|
|
29
32
|
.optional()
|
|
30
33
|
.describe('Development mode configuration'),
|