@cortexmemory/cli 0.1.1 → 0.22.1
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/README.md +8 -0
- package/dist/commands/conversations.d.ts +1 -1
- package/dist/commands/conversations.d.ts.map +1 -1
- package/dist/commands/conversations.js +57 -27
- package/dist/commands/conversations.js.map +1 -1
- package/dist/commands/convex.d.ts +1 -1
- package/dist/commands/convex.d.ts.map +1 -1
- package/dist/commands/convex.js +237 -64
- package/dist/commands/convex.js.map +1 -1
- package/dist/commands/db.d.ts +1 -1
- package/dist/commands/db.d.ts.map +1 -1
- package/dist/commands/db.js +59 -109
- package/dist/commands/db.js.map +1 -1
- package/dist/commands/dev.d.ts +8 -8
- package/dist/commands/dev.d.ts.map +1 -1
- package/dist/commands/dev.js +734 -513
- package/dist/commands/dev.js.map +1 -1
- package/dist/commands/facts.d.ts +1 -1
- package/dist/commands/facts.d.ts.map +1 -1
- package/dist/commands/facts.js +50 -21
- package/dist/commands/facts.js.map +1 -1
- package/dist/commands/init.d.ts +28 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +895 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/memory.d.ts +1 -1
- package/dist/commands/memory.d.ts.map +1 -1
- package/dist/commands/memory.js +64 -27
- package/dist/commands/memory.js.map +1 -1
- package/dist/commands/setup.d.ts +4 -5
- package/dist/commands/setup.d.ts.map +1 -1
- package/dist/commands/setup.js +428 -250
- package/dist/commands/setup.js.map +1 -1
- package/dist/commands/spaces.d.ts +1 -1
- package/dist/commands/spaces.d.ts.map +1 -1
- package/dist/commands/spaces.js +100 -43
- package/dist/commands/spaces.js.map +1 -1
- package/dist/commands/status.d.ts +17 -0
- package/dist/commands/status.d.ts.map +1 -0
- package/dist/commands/status.js +314 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/commands/users.d.ts +1 -1
- package/dist/commands/users.d.ts.map +1 -1
- package/dist/commands/users.js +80 -42
- package/dist/commands/users.js.map +1 -1
- package/dist/index.js +42 -14
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +11 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/__tests__/client.test.d.ts +5 -0
- package/dist/utils/__tests__/client.test.d.ts.map +1 -0
- package/dist/utils/__tests__/client.test.js +88 -0
- package/dist/utils/__tests__/client.test.js.map +1 -0
- package/dist/utils/__tests__/env-file.test.d.ts +7 -0
- package/dist/utils/__tests__/env-file.test.d.ts.map +1 -0
- package/dist/utils/__tests__/env-file.test.js +196 -0
- package/dist/utils/__tests__/env-file.test.js.map +1 -0
- package/dist/utils/__tests__/shell.test.d.ts +7 -0
- package/dist/utils/__tests__/shell.test.d.ts.map +1 -0
- package/dist/utils/__tests__/shell.test.js +89 -0
- package/dist/utils/__tests__/shell.test.js.map +1 -0
- package/dist/utils/config.d.ts.map +1 -1
- package/dist/utils/config.js +12 -39
- package/dist/utils/config.js.map +1 -1
- package/dist/utils/deployment-selector.d.ts +50 -0
- package/dist/utils/deployment-selector.d.ts.map +1 -0
- package/dist/utils/deployment-selector.js +129 -0
- package/dist/utils/deployment-selector.js.map +1 -0
- package/dist/utils/init/convex-setup.d.ts +30 -0
- package/dist/utils/init/convex-setup.d.ts.map +1 -0
- package/dist/utils/init/convex-setup.js +225 -0
- package/dist/utils/init/convex-setup.js.map +1 -0
- package/dist/utils/init/env-generator.d.ts +32 -0
- package/dist/utils/init/env-generator.d.ts.map +1 -0
- package/dist/utils/init/env-generator.js +210 -0
- package/dist/utils/init/env-generator.js.map +1 -0
- package/dist/utils/init/file-operations.d.ts +22 -0
- package/dist/utils/init/file-operations.d.ts.map +1 -0
- package/dist/utils/init/file-operations.js +211 -0
- package/dist/utils/init/file-operations.js.map +1 -0
- package/dist/utils/init/graph-setup.d.ts +35 -0
- package/dist/utils/init/graph-setup.d.ts.map +1 -0
- package/dist/utils/init/graph-setup.js +413 -0
- package/dist/utils/init/graph-setup.js.map +1 -0
- package/dist/utils/init/index.d.ts +11 -0
- package/dist/utils/init/index.d.ts.map +1 -0
- package/dist/utils/init/index.js +11 -0
- package/dist/utils/init/index.js.map +1 -0
- package/dist/utils/init/types.d.ts +73 -0
- package/dist/utils/init/types.d.ts.map +1 -0
- package/dist/utils/init/types.js +5 -0
- package/dist/utils/init/types.js.map +1 -0
- package/dist/utils/shell.d.ts +60 -0
- package/dist/utils/shell.d.ts.map +1 -0
- package/dist/utils/shell.js +188 -0
- package/dist/utils/shell.js.map +1 -0
- package/package.json +25 -20
- package/templates/basic/README.md +105 -0
- package/templates/basic/dev-runner.mjs +215 -0
- package/templates/basic/package-lock.json +1263 -0
- package/templates/basic/package.json +22 -0
- package/templates/basic/src/index.ts +85 -0
- package/templates/basic/tsconfig.json +17 -0
package/dist/commands/setup.js
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Configuration Commands
|
|
3
3
|
*
|
|
4
|
-
* Commands for
|
|
5
|
-
* - setup: Interactive setup wizard
|
|
4
|
+
* Commands for managing CLI configuration:
|
|
6
5
|
* - config: Configuration management
|
|
7
6
|
*/
|
|
8
7
|
import prompts from "prompts";
|
|
@@ -13,138 +12,13 @@ import { testConnection } from "../utils/client.js";
|
|
|
13
12
|
import { printSuccess, printError, printWarning, printInfo, printSection, formatOutput, } from "../utils/formatting.js";
|
|
14
13
|
import { validateUrl } from "../utils/validation.js";
|
|
15
14
|
import { addDeploymentToEnv, removeDeploymentFromEnv, getDeploymentEnvKeys, } from "../utils/env-file.js";
|
|
15
|
+
import { getCurrentDeployment, setCurrentDeployment, clearCurrentDeployment, } from "../utils/deployment-selector.js";
|
|
16
16
|
import { existsSync } from "fs";
|
|
17
|
-
import { join } from "path";
|
|
17
|
+
import { join, resolve } from "path";
|
|
18
18
|
/**
|
|
19
|
-
* Register
|
|
19
|
+
* Register config commands
|
|
20
20
|
*/
|
|
21
|
-
export function
|
|
22
|
-
// setup command
|
|
23
|
-
program
|
|
24
|
-
.command("setup")
|
|
25
|
-
.description("Interactive setup wizard")
|
|
26
|
-
.option("--auto", "Auto-configure from environment variables", false)
|
|
27
|
-
.option("--local", "Set up local Convex development", false)
|
|
28
|
-
.option("--cloud", "Set up cloud Convex deployment", false)
|
|
29
|
-
.action(async (options) => {
|
|
30
|
-
console.log();
|
|
31
|
-
console.log(pc.bold(pc.cyan("🧠 Cortex CLI Setup")));
|
|
32
|
-
console.log(pc.dim("Configure your Cortex Memory deployment\n"));
|
|
33
|
-
try {
|
|
34
|
-
let config = await loadConfig();
|
|
35
|
-
if (options.auto) {
|
|
36
|
-
// Auto mode: configure from environment variables
|
|
37
|
-
await autoSetup(config);
|
|
38
|
-
return;
|
|
39
|
-
}
|
|
40
|
-
// Interactive setup
|
|
41
|
-
const setupMode = await prompts({
|
|
42
|
-
type: "select",
|
|
43
|
-
name: "mode",
|
|
44
|
-
message: "What would you like to set up?",
|
|
45
|
-
choices: [
|
|
46
|
-
{
|
|
47
|
-
title: "Local development",
|
|
48
|
-
description: "Configure local Convex instance",
|
|
49
|
-
value: "local",
|
|
50
|
-
},
|
|
51
|
-
{
|
|
52
|
-
title: "Cloud deployment",
|
|
53
|
-
description: "Configure Convex cloud deployment",
|
|
54
|
-
value: "cloud",
|
|
55
|
-
},
|
|
56
|
-
{
|
|
57
|
-
title: "Both",
|
|
58
|
-
description: "Configure local and cloud deployments",
|
|
59
|
-
value: "both",
|
|
60
|
-
},
|
|
61
|
-
{
|
|
62
|
-
title: "View current configuration",
|
|
63
|
-
description: "Show existing configuration",
|
|
64
|
-
value: "view",
|
|
65
|
-
},
|
|
66
|
-
],
|
|
67
|
-
initial: options.local ? 0 : options.cloud ? 1 : 2,
|
|
68
|
-
});
|
|
69
|
-
if (!setupMode.mode) {
|
|
70
|
-
printWarning("Setup cancelled");
|
|
71
|
-
return;
|
|
72
|
-
}
|
|
73
|
-
if (setupMode.mode === "view") {
|
|
74
|
-
await showConfiguration(config);
|
|
75
|
-
return;
|
|
76
|
-
}
|
|
77
|
-
// Set up local deployment
|
|
78
|
-
if (setupMode.mode === "local" || setupMode.mode === "both") {
|
|
79
|
-
config = await setupLocalDeployment(config);
|
|
80
|
-
}
|
|
81
|
-
// Set up cloud deployment
|
|
82
|
-
if (setupMode.mode === "cloud" || setupMode.mode === "both") {
|
|
83
|
-
config = await setupCloudDeployment(config);
|
|
84
|
-
}
|
|
85
|
-
// Set default deployment
|
|
86
|
-
if (setupMode.mode === "both") {
|
|
87
|
-
const defaultChoice = await prompts({
|
|
88
|
-
type: "select",
|
|
89
|
-
name: "default",
|
|
90
|
-
message: "Which deployment should be the default?",
|
|
91
|
-
choices: [
|
|
92
|
-
{ title: "Local", value: "local" },
|
|
93
|
-
{ title: "Cloud", value: "cloud" },
|
|
94
|
-
],
|
|
95
|
-
});
|
|
96
|
-
if (defaultChoice.default) {
|
|
97
|
-
config.default = defaultChoice.default;
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
else {
|
|
101
|
-
config.default = setupMode.mode;
|
|
102
|
-
}
|
|
103
|
-
// Set output format
|
|
104
|
-
const formatChoice = await prompts({
|
|
105
|
-
type: "select",
|
|
106
|
-
name: "format",
|
|
107
|
-
message: "Preferred output format?",
|
|
108
|
-
choices: [
|
|
109
|
-
{ title: "Table (human-readable)", value: "table" },
|
|
110
|
-
{ title: "JSON (machine-readable)", value: "json" },
|
|
111
|
-
],
|
|
112
|
-
initial: 0,
|
|
113
|
-
});
|
|
114
|
-
if (formatChoice.format) {
|
|
115
|
-
config.format = formatChoice.format;
|
|
116
|
-
}
|
|
117
|
-
// Confirm dangerous operations
|
|
118
|
-
const confirmChoice = await prompts({
|
|
119
|
-
type: "confirm",
|
|
120
|
-
name: "confirm",
|
|
121
|
-
message: "Require confirmation for dangerous operations (delete, clear)?",
|
|
122
|
-
initial: true,
|
|
123
|
-
});
|
|
124
|
-
config.confirmDangerous = confirmChoice.confirm ?? true;
|
|
125
|
-
// Save configuration
|
|
126
|
-
await saveUserConfig(config);
|
|
127
|
-
console.log();
|
|
128
|
-
printSuccess(`Configuration saved to ${getUserConfigPath()}`);
|
|
129
|
-
// Test connection
|
|
130
|
-
const testChoice = await prompts({
|
|
131
|
-
type: "confirm",
|
|
132
|
-
name: "test",
|
|
133
|
-
message: "Would you like to test the connection?",
|
|
134
|
-
initial: true,
|
|
135
|
-
});
|
|
136
|
-
if (testChoice.test) {
|
|
137
|
-
await testAndShowConnection(config, config.default);
|
|
138
|
-
}
|
|
139
|
-
console.log();
|
|
140
|
-
printSuccess("Setup complete! 🎉");
|
|
141
|
-
printInfo("Run 'cortex --help' to see available commands");
|
|
142
|
-
}
|
|
143
|
-
catch (error) {
|
|
144
|
-
printError(error instanceof Error ? error.message : "Setup failed");
|
|
145
|
-
process.exit(1);
|
|
146
|
-
}
|
|
147
|
-
});
|
|
21
|
+
export function registerConfigCommands(program, _config) {
|
|
148
22
|
// config command group
|
|
149
23
|
const configCmd = program
|
|
150
24
|
.command("config")
|
|
@@ -166,6 +40,75 @@ export function registerSetupCommands(program, _config) {
|
|
|
166
40
|
process.exit(1);
|
|
167
41
|
}
|
|
168
42
|
});
|
|
43
|
+
// config list - Table view of deployments
|
|
44
|
+
configCmd
|
|
45
|
+
.command("list")
|
|
46
|
+
.description("List all deployments in table format")
|
|
47
|
+
.action(async () => {
|
|
48
|
+
try {
|
|
49
|
+
const config = await loadConfig();
|
|
50
|
+
const deployments = Object.entries(config.deployments);
|
|
51
|
+
if (deployments.length === 0) {
|
|
52
|
+
console.log(pc.yellow("\n No deployments configured\n"));
|
|
53
|
+
printInfo("To get started:");
|
|
54
|
+
console.log(pc.dim(" • Run 'cortex init' to create a new project"));
|
|
55
|
+
console.log(pc.dim(" • Run 'cortex config add-deployment' to add an existing deployment"));
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
console.log();
|
|
59
|
+
// Table header
|
|
60
|
+
const nameWidth = 20;
|
|
61
|
+
const statusWidth = 10;
|
|
62
|
+
const urlWidth = 40;
|
|
63
|
+
const keyWidth = 6;
|
|
64
|
+
const pathWidth = 35;
|
|
65
|
+
console.log(pc.bold(" " +
|
|
66
|
+
"NAME".padEnd(nameWidth) +
|
|
67
|
+
"STATUS".padEnd(statusWidth) +
|
|
68
|
+
"URL".padEnd(urlWidth) +
|
|
69
|
+
"KEY".padEnd(keyWidth) +
|
|
70
|
+
"PROJECT PATH"));
|
|
71
|
+
console.log(pc.dim(" " + "─".repeat(nameWidth + statusWidth + urlWidth + keyWidth + pathWidth)));
|
|
72
|
+
for (const [name, deployment] of deployments) {
|
|
73
|
+
const isDefault = name === config.default;
|
|
74
|
+
// Default deployment is implicitly enabled; others check enabled field
|
|
75
|
+
const isEnabled = deployment.enabled === true || (deployment.enabled === undefined && isDefault);
|
|
76
|
+
const prefix = isDefault ? pc.green("→ ") : " ";
|
|
77
|
+
// Pad BEFORE applying color to avoid ANSI escape code length issues
|
|
78
|
+
const namePadded = name.padEnd(nameWidth - 2);
|
|
79
|
+
const nameDisplay = isDefault ? pc.cyan(namePadded) : namePadded;
|
|
80
|
+
const statusText = isEnabled ? "enabled" : "disabled";
|
|
81
|
+
const statusPadded = statusText.padEnd(statusWidth);
|
|
82
|
+
const statusDisplay = isEnabled ? pc.green(statusPadded) : pc.dim(statusPadded);
|
|
83
|
+
const keyText = deployment.key ? "yes" : "no";
|
|
84
|
+
const keyPadded = keyText.padEnd(keyWidth);
|
|
85
|
+
const keyStatus = deployment.key ? pc.green(keyPadded) : pc.dim(keyPadded);
|
|
86
|
+
const urlDisplay = (deployment.url.length > urlWidth - 2
|
|
87
|
+
? deployment.url.substring(0, urlWidth - 5) + "..."
|
|
88
|
+
: deployment.url).padEnd(urlWidth);
|
|
89
|
+
const pathDisplay = deployment.projectPath
|
|
90
|
+
? (deployment.projectPath.length > pathWidth - 2
|
|
91
|
+
? "..." + deployment.projectPath.slice(-(pathWidth - 5))
|
|
92
|
+
: deployment.projectPath)
|
|
93
|
+
: pc.dim("--");
|
|
94
|
+
console.log(prefix +
|
|
95
|
+
nameDisplay +
|
|
96
|
+
statusDisplay +
|
|
97
|
+
urlDisplay +
|
|
98
|
+
keyStatus +
|
|
99
|
+
pathDisplay);
|
|
100
|
+
}
|
|
101
|
+
console.log();
|
|
102
|
+
if (config.default) {
|
|
103
|
+
console.log(pc.dim(` Default: ${config.default} (→) • Enabled deployments started with 'cortex start'`));
|
|
104
|
+
}
|
|
105
|
+
console.log();
|
|
106
|
+
}
|
|
107
|
+
catch (error) {
|
|
108
|
+
printError(error instanceof Error ? error.message : "Failed to load config");
|
|
109
|
+
process.exit(1);
|
|
110
|
+
}
|
|
111
|
+
});
|
|
169
112
|
// config set
|
|
170
113
|
configCmd
|
|
171
114
|
.command("set <key> <value>")
|
|
@@ -196,6 +139,101 @@ export function registerSetupCommands(program, _config) {
|
|
|
196
139
|
process.exit(1);
|
|
197
140
|
}
|
|
198
141
|
});
|
|
142
|
+
// config set-path - Set project path for a deployment
|
|
143
|
+
configCmd
|
|
144
|
+
.command("set-path <deployment> [path]")
|
|
145
|
+
.description("Set project path for a deployment (enables 'cortex start -d <name>' from anywhere)")
|
|
146
|
+
.action(async (deploymentName, pathArg) => {
|
|
147
|
+
try {
|
|
148
|
+
const config = await loadConfig();
|
|
149
|
+
if (!config.deployments[deploymentName]) {
|
|
150
|
+
printError(`Deployment "${deploymentName}" not found`);
|
|
151
|
+
const names = Object.keys(config.deployments);
|
|
152
|
+
if (names.length > 0) {
|
|
153
|
+
printInfo(`Available deployments: ${names.join(", ")}`);
|
|
154
|
+
}
|
|
155
|
+
process.exit(1);
|
|
156
|
+
}
|
|
157
|
+
// If no path provided, use current directory
|
|
158
|
+
const projectPath = pathArg ? resolve(pathArg) : process.cwd();
|
|
159
|
+
// Verify path exists
|
|
160
|
+
if (!existsSync(projectPath)) {
|
|
161
|
+
printError(`Path does not exist: ${projectPath}`);
|
|
162
|
+
process.exit(1);
|
|
163
|
+
}
|
|
164
|
+
// Update deployment with projectPath
|
|
165
|
+
config.deployments[deploymentName] = {
|
|
166
|
+
...config.deployments[deploymentName],
|
|
167
|
+
projectPath,
|
|
168
|
+
};
|
|
169
|
+
await saveUserConfig(config);
|
|
170
|
+
printSuccess(`Set project path for "${deploymentName}"`);
|
|
171
|
+
console.log(pc.dim(` Path: ${projectPath}`));
|
|
172
|
+
console.log();
|
|
173
|
+
printInfo(`You can now run: cortex start -d ${deploymentName}`);
|
|
174
|
+
console.log(pc.dim(" This will work from any directory"));
|
|
175
|
+
}
|
|
176
|
+
catch (error) {
|
|
177
|
+
printError(error instanceof Error ? error.message : "Failed to set project path");
|
|
178
|
+
process.exit(1);
|
|
179
|
+
}
|
|
180
|
+
});
|
|
181
|
+
// config enable - Enable a deployment for `cortex start`
|
|
182
|
+
configCmd
|
|
183
|
+
.command("enable <deployment>")
|
|
184
|
+
.description("Enable a deployment (will be started with 'cortex start')")
|
|
185
|
+
.action(async (deploymentName) => {
|
|
186
|
+
try {
|
|
187
|
+
const config = await loadConfig();
|
|
188
|
+
if (!config.deployments[deploymentName]) {
|
|
189
|
+
printError(`Deployment "${deploymentName}" not found`);
|
|
190
|
+
const names = Object.keys(config.deployments);
|
|
191
|
+
if (names.length > 0) {
|
|
192
|
+
printInfo(`Available deployments: ${names.join(", ")}`);
|
|
193
|
+
}
|
|
194
|
+
process.exit(1);
|
|
195
|
+
}
|
|
196
|
+
config.deployments[deploymentName] = {
|
|
197
|
+
...config.deployments[deploymentName],
|
|
198
|
+
enabled: true,
|
|
199
|
+
};
|
|
200
|
+
await saveUserConfig(config);
|
|
201
|
+
printSuccess(`Enabled deployment "${deploymentName}"`);
|
|
202
|
+
console.log(pc.dim(" Will be started with 'cortex start'"));
|
|
203
|
+
}
|
|
204
|
+
catch (error) {
|
|
205
|
+
printError(error instanceof Error ? error.message : "Failed to enable deployment");
|
|
206
|
+
process.exit(1);
|
|
207
|
+
}
|
|
208
|
+
});
|
|
209
|
+
// config disable - Disable a deployment
|
|
210
|
+
configCmd
|
|
211
|
+
.command("disable <deployment>")
|
|
212
|
+
.description("Disable a deployment (will not be started with 'cortex start')")
|
|
213
|
+
.action(async (deploymentName) => {
|
|
214
|
+
try {
|
|
215
|
+
const config = await loadConfig();
|
|
216
|
+
if (!config.deployments[deploymentName]) {
|
|
217
|
+
printError(`Deployment "${deploymentName}" not found`);
|
|
218
|
+
const names = Object.keys(config.deployments);
|
|
219
|
+
if (names.length > 0) {
|
|
220
|
+
printInfo(`Available deployments: ${names.join(", ")}`);
|
|
221
|
+
}
|
|
222
|
+
process.exit(1);
|
|
223
|
+
}
|
|
224
|
+
config.deployments[deploymentName] = {
|
|
225
|
+
...config.deployments[deploymentName],
|
|
226
|
+
enabled: false,
|
|
227
|
+
};
|
|
228
|
+
await saveUserConfig(config);
|
|
229
|
+
printSuccess(`Disabled deployment "${deploymentName}"`);
|
|
230
|
+
console.log(pc.dim(" Will NOT be started with 'cortex start'"));
|
|
231
|
+
}
|
|
232
|
+
catch (error) {
|
|
233
|
+
printError(error instanceof Error ? error.message : "Failed to disable deployment");
|
|
234
|
+
process.exit(1);
|
|
235
|
+
}
|
|
236
|
+
});
|
|
199
237
|
// config deployments
|
|
200
238
|
configCmd
|
|
201
239
|
.command("deployments")
|
|
@@ -431,6 +469,176 @@ export function registerSetupCommands(program, _config) {
|
|
|
431
469
|
process.exit(1);
|
|
432
470
|
}
|
|
433
471
|
});
|
|
472
|
+
// config set-key
|
|
473
|
+
configCmd
|
|
474
|
+
.command("set-key [deployment]")
|
|
475
|
+
.description("Set or update the deploy key for a deployment")
|
|
476
|
+
.option("-k, --key <key>", "Deploy key (will prompt if not provided)")
|
|
477
|
+
.option("--json-only", "Only update ~/.cortexrc (skip .env.local)", false)
|
|
478
|
+
.action(async (deploymentArg, options) => {
|
|
479
|
+
try {
|
|
480
|
+
const config = await loadConfig();
|
|
481
|
+
let name = deploymentArg;
|
|
482
|
+
// If no name provided, show interactive selection
|
|
483
|
+
if (!name) {
|
|
484
|
+
const deploymentNames = Object.keys(config.deployments);
|
|
485
|
+
if (deploymentNames.length === 0) {
|
|
486
|
+
printWarning("No deployments configured");
|
|
487
|
+
console.log(pc.dim(" Run 'cortex config add-deployment' to add one\n"));
|
|
488
|
+
return;
|
|
489
|
+
}
|
|
490
|
+
const response = await prompts({
|
|
491
|
+
type: "select",
|
|
492
|
+
name: "name",
|
|
493
|
+
message: "Select deployment to set key for:",
|
|
494
|
+
choices: deploymentNames.map((n) => {
|
|
495
|
+
const dep = config.deployments[n];
|
|
496
|
+
const keyStatus = dep.key ? pc.green("(key set)") : pc.dim("(no key)");
|
|
497
|
+
return {
|
|
498
|
+
title: `${n} ${keyStatus}`,
|
|
499
|
+
description: dep.url,
|
|
500
|
+
value: n,
|
|
501
|
+
};
|
|
502
|
+
}),
|
|
503
|
+
});
|
|
504
|
+
if (!response.name) {
|
|
505
|
+
printWarning("Cancelled");
|
|
506
|
+
return;
|
|
507
|
+
}
|
|
508
|
+
name = response.name;
|
|
509
|
+
}
|
|
510
|
+
if (!config.deployments[name]) {
|
|
511
|
+
printError(`Deployment "${name}" not found`);
|
|
512
|
+
console.log(pc.dim(" Run 'cortex config list' to see available deployments\n"));
|
|
513
|
+
process.exit(1);
|
|
514
|
+
}
|
|
515
|
+
// Get key from option or prompt
|
|
516
|
+
let key = options.key;
|
|
517
|
+
if (!key) {
|
|
518
|
+
const response = await prompts({
|
|
519
|
+
type: "password",
|
|
520
|
+
name: "key",
|
|
521
|
+
message: `Enter deploy key for "${name}":`,
|
|
522
|
+
validate: (v) => v.length > 0 || "Key cannot be empty",
|
|
523
|
+
});
|
|
524
|
+
if (!response.key) {
|
|
525
|
+
printWarning("Cancelled");
|
|
526
|
+
return;
|
|
527
|
+
}
|
|
528
|
+
key = response.key;
|
|
529
|
+
}
|
|
530
|
+
// Update the deployment with the new key
|
|
531
|
+
const deployment = config.deployments[name];
|
|
532
|
+
deployment.key = key;
|
|
533
|
+
await updateDeployment(name, deployment);
|
|
534
|
+
// Also update .env.local (unless --json-only)
|
|
535
|
+
if (!options.jsonOnly) {
|
|
536
|
+
await addDeploymentToEnv(name, deployment.url, key);
|
|
537
|
+
const envKeys = getDeploymentEnvKeys(name);
|
|
538
|
+
printSuccess(`Set deploy key for "${name}"`);
|
|
539
|
+
printInfo(`Updated .env.local: ${envKeys.keyKey}=***`);
|
|
540
|
+
}
|
|
541
|
+
else {
|
|
542
|
+
printSuccess(`Set deploy key for "${name}" in ~/.cortexrc`);
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
catch (error) {
|
|
546
|
+
printError(error instanceof Error ? error.message : "Failed to set key");
|
|
547
|
+
process.exit(1);
|
|
548
|
+
}
|
|
549
|
+
});
|
|
550
|
+
// config set-url
|
|
551
|
+
configCmd
|
|
552
|
+
.command("set-url [deployment]")
|
|
553
|
+
.description("Set or update the URL for a deployment")
|
|
554
|
+
.option("-u, --url <url>", "Deployment URL (will prompt if not provided)")
|
|
555
|
+
.option("--json-only", "Only update ~/.cortexrc (skip .env.local)", false)
|
|
556
|
+
.action(async (deploymentArg, options) => {
|
|
557
|
+
try {
|
|
558
|
+
const config = await loadConfig();
|
|
559
|
+
let name = deploymentArg;
|
|
560
|
+
// If no name provided, show interactive selection
|
|
561
|
+
if (!name) {
|
|
562
|
+
const deploymentNames = Object.keys(config.deployments);
|
|
563
|
+
if (deploymentNames.length === 0) {
|
|
564
|
+
printWarning("No deployments configured");
|
|
565
|
+
console.log(pc.dim(" Run 'cortex config add-deployment' to add one\n"));
|
|
566
|
+
return;
|
|
567
|
+
}
|
|
568
|
+
const response = await prompts({
|
|
569
|
+
type: "select",
|
|
570
|
+
name: "name",
|
|
571
|
+
message: "Select deployment to set URL for:",
|
|
572
|
+
choices: deploymentNames.map((n) => {
|
|
573
|
+
const dep = config.deployments[n];
|
|
574
|
+
return {
|
|
575
|
+
title: n,
|
|
576
|
+
description: dep.url,
|
|
577
|
+
value: n,
|
|
578
|
+
};
|
|
579
|
+
}),
|
|
580
|
+
});
|
|
581
|
+
if (!response.name) {
|
|
582
|
+
printWarning("Cancelled");
|
|
583
|
+
return;
|
|
584
|
+
}
|
|
585
|
+
name = response.name;
|
|
586
|
+
}
|
|
587
|
+
if (!config.deployments[name]) {
|
|
588
|
+
printError(`Deployment "${name}" not found`);
|
|
589
|
+
console.log(pc.dim(" Run 'cortex config list' to see available deployments\n"));
|
|
590
|
+
process.exit(1);
|
|
591
|
+
}
|
|
592
|
+
// Get URL from option or prompt
|
|
593
|
+
let url = options.url;
|
|
594
|
+
if (!url) {
|
|
595
|
+
const currentUrl = config.deployments[name].url;
|
|
596
|
+
const response = await prompts({
|
|
597
|
+
type: "text",
|
|
598
|
+
name: "url",
|
|
599
|
+
message: `Enter URL for "${name}":`,
|
|
600
|
+
initial: currentUrl,
|
|
601
|
+
validate: (v) => {
|
|
602
|
+
try {
|
|
603
|
+
new URL(v);
|
|
604
|
+
return true;
|
|
605
|
+
}
|
|
606
|
+
catch {
|
|
607
|
+
return "Please enter a valid URL";
|
|
608
|
+
}
|
|
609
|
+
},
|
|
610
|
+
});
|
|
611
|
+
if (!response.url) {
|
|
612
|
+
printWarning("Cancelled");
|
|
613
|
+
return;
|
|
614
|
+
}
|
|
615
|
+
url = response.url;
|
|
616
|
+
}
|
|
617
|
+
// Validate URL
|
|
618
|
+
validateUrl(url);
|
|
619
|
+
// Update the deployment with the new URL
|
|
620
|
+
const deployment = config.deployments[name];
|
|
621
|
+
const oldUrl = deployment.url;
|
|
622
|
+
deployment.url = url;
|
|
623
|
+
await updateDeployment(name, deployment);
|
|
624
|
+
// Also update .env.local (unless --json-only)
|
|
625
|
+
if (!options.jsonOnly) {
|
|
626
|
+
await addDeploymentToEnv(name, url, deployment.key);
|
|
627
|
+
const envKeys = getDeploymentEnvKeys(name);
|
|
628
|
+
printSuccess(`Updated URL for "${name}"`);
|
|
629
|
+
printInfo(`${oldUrl} → ${url}`);
|
|
630
|
+
printInfo(`Updated .env.local: ${envKeys.urlKey}=${url}`);
|
|
631
|
+
}
|
|
632
|
+
else {
|
|
633
|
+
printSuccess(`Updated URL for "${name}" in ~/.cortexrc`);
|
|
634
|
+
printInfo(`${oldUrl} → ${url}`);
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
catch (error) {
|
|
638
|
+
printError(error instanceof Error ? error.message : "Failed to set URL");
|
|
639
|
+
process.exit(1);
|
|
640
|
+
}
|
|
641
|
+
});
|
|
434
642
|
// config path
|
|
435
643
|
configCmd
|
|
436
644
|
.command("path")
|
|
@@ -484,134 +692,88 @@ export function registerSetupCommands(program, _config) {
|
|
|
484
692
|
}
|
|
485
693
|
}
|
|
486
694
|
const defaultConfig = {
|
|
487
|
-
deployments: {
|
|
488
|
-
|
|
489
|
-
url: "http://127.0.0.1:3210",
|
|
490
|
-
deployment: "anonymous:anonymous-cortex-sdk-local",
|
|
491
|
-
},
|
|
492
|
-
},
|
|
493
|
-
default: "local",
|
|
695
|
+
deployments: {},
|
|
696
|
+
default: "",
|
|
494
697
|
format: "table",
|
|
495
698
|
confirmDangerous: true,
|
|
496
699
|
};
|
|
497
700
|
await saveUserConfig(defaultConfig);
|
|
498
701
|
printSuccess("Configuration reset to defaults");
|
|
702
|
+
console.log();
|
|
703
|
+
printInfo("No deployments configured. To get started:");
|
|
704
|
+
console.log(pc.dim(" • Run 'cortex init' to create a new project"));
|
|
705
|
+
console.log(pc.dim(" • Run 'cortex config add-deployment' to add an existing deployment"));
|
|
499
706
|
}
|
|
500
707
|
catch (error) {
|
|
501
708
|
printError(error instanceof Error ? error.message : "Reset failed");
|
|
502
709
|
process.exit(1);
|
|
503
710
|
}
|
|
504
711
|
});
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
async function setupLocalDeployment(config) {
|
|
548
|
-
console.log();
|
|
549
|
-
console.log(pc.bold("Local Development Setup"));
|
|
550
|
-
console.log(pc.dim("Configure connection to local Convex instance\n"));
|
|
551
|
-
const urlPrompt = await prompts({
|
|
552
|
-
type: "text",
|
|
553
|
-
name: "url",
|
|
554
|
-
message: "Local Convex URL:",
|
|
555
|
-
initial: config.deployments.local?.url ?? "http://127.0.0.1:3210",
|
|
556
|
-
validate: (value) => {
|
|
557
|
-
try {
|
|
558
|
-
new URL(value);
|
|
559
|
-
return true;
|
|
560
|
-
}
|
|
561
|
-
catch {
|
|
562
|
-
return "Please enter a valid URL";
|
|
563
|
-
}
|
|
564
|
-
},
|
|
565
|
-
});
|
|
566
|
-
const deploymentPrompt = await prompts({
|
|
567
|
-
type: "text",
|
|
568
|
-
name: "deployment",
|
|
569
|
-
message: "Local deployment name (optional):",
|
|
570
|
-
initial: config.deployments.local?.deployment ??
|
|
571
|
-
"anonymous:anonymous-cortex-sdk-local",
|
|
572
|
-
});
|
|
573
|
-
config.deployments.local = {
|
|
574
|
-
url: urlPrompt.url,
|
|
575
|
-
deployment: deploymentPrompt.deployment || undefined,
|
|
576
|
-
};
|
|
577
|
-
return config;
|
|
578
|
-
}
|
|
579
|
-
/**
|
|
580
|
-
* Set up cloud deployment
|
|
581
|
-
*/
|
|
582
|
-
async function setupCloudDeployment(config) {
|
|
583
|
-
console.log();
|
|
584
|
-
console.log(pc.bold("Cloud Deployment Setup"));
|
|
585
|
-
console.log(pc.dim("Configure connection to Convex cloud\n"));
|
|
586
|
-
const urlPrompt = await prompts({
|
|
587
|
-
type: "text",
|
|
588
|
-
name: "url",
|
|
589
|
-
message: "Convex cloud URL:",
|
|
590
|
-
initial: config.deployments.cloud?.url ?? "https://your-deployment.convex.cloud",
|
|
591
|
-
validate: (value) => {
|
|
592
|
-
try {
|
|
593
|
-
const url = new URL(value);
|
|
594
|
-
if (!url.hostname.includes("convex")) {
|
|
595
|
-
return "URL should be a Convex cloud URL";
|
|
712
|
+
// Top-level 'use' command for quick deployment switching
|
|
713
|
+
program
|
|
714
|
+
.command("use [deployment]")
|
|
715
|
+
.description("Set current deployment for all commands (session context)")
|
|
716
|
+
.option("--clear", "Clear the current deployment setting")
|
|
717
|
+
.action(async (deploymentName, options) => {
|
|
718
|
+
try {
|
|
719
|
+
const config = await loadConfig();
|
|
720
|
+
const deployments = Object.keys(config.deployments);
|
|
721
|
+
// Handle --clear flag
|
|
722
|
+
if (options.clear) {
|
|
723
|
+
await clearCurrentDeployment();
|
|
724
|
+
printSuccess("Cleared current deployment");
|
|
725
|
+
console.log(pc.dim(" Commands will now prompt for deployment selection\n"));
|
|
726
|
+
return;
|
|
727
|
+
}
|
|
728
|
+
// If no deployment specified, show current and list available
|
|
729
|
+
if (!deploymentName) {
|
|
730
|
+
const current = await getCurrentDeployment();
|
|
731
|
+
console.log();
|
|
732
|
+
if (current && config.deployments[current]) {
|
|
733
|
+
console.log(pc.bold(" Current deployment: ") + pc.cyan(current));
|
|
734
|
+
}
|
|
735
|
+
else if (current) {
|
|
736
|
+
console.log(pc.yellow(` Current deployment "${current}" no longer exists`));
|
|
737
|
+
}
|
|
738
|
+
else {
|
|
739
|
+
console.log(pc.dim(" No current deployment set"));
|
|
740
|
+
}
|
|
741
|
+
console.log();
|
|
742
|
+
console.log(pc.bold(" Available deployments:"));
|
|
743
|
+
if (deployments.length === 0) {
|
|
744
|
+
console.log(pc.yellow(" No deployments configured"));
|
|
745
|
+
}
|
|
746
|
+
else {
|
|
747
|
+
for (const name of deployments) {
|
|
748
|
+
const isCurrent = name === current;
|
|
749
|
+
const isDefault = name === config.default;
|
|
750
|
+
const prefix = isCurrent ? pc.green("→") : " ";
|
|
751
|
+
const suffix = isDefault ? pc.dim(" (default)") : "";
|
|
752
|
+
console.log(` ${prefix} ${pc.cyan(name)}${suffix}`);
|
|
753
|
+
}
|
|
596
754
|
}
|
|
597
|
-
|
|
755
|
+
console.log();
|
|
756
|
+
console.log(pc.dim(" Usage: cortex use <deployment>"));
|
|
757
|
+
console.log(pc.dim(" cortex use --clear"));
|
|
758
|
+
console.log();
|
|
759
|
+
return;
|
|
598
760
|
}
|
|
599
|
-
|
|
600
|
-
|
|
761
|
+
// Validate deployment exists
|
|
762
|
+
if (!config.deployments[deploymentName]) {
|
|
763
|
+
printError(`Deployment "${deploymentName}" not found`);
|
|
764
|
+
console.log(pc.dim(` Available: ${deployments.join(", ")}\n`));
|
|
765
|
+
process.exit(1);
|
|
601
766
|
}
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
767
|
+
// Set the current deployment
|
|
768
|
+
await setCurrentDeployment(deploymentName);
|
|
769
|
+
printSuccess(`Now using: ${deploymentName}`);
|
|
770
|
+
console.log(pc.dim(` All commands will target this deployment until changed\n`));
|
|
771
|
+
}
|
|
772
|
+
catch (error) {
|
|
773
|
+
printError(error instanceof Error ? error.message : "Failed to set deployment");
|
|
774
|
+
process.exit(1);
|
|
775
|
+
}
|
|
609
776
|
});
|
|
610
|
-
config.deployments.cloud = {
|
|
611
|
-
url: urlPrompt.url,
|
|
612
|
-
key: keyPrompt.key || undefined,
|
|
613
|
-
};
|
|
614
|
-
return config;
|
|
615
777
|
}
|
|
616
778
|
/**
|
|
617
779
|
* Show current configuration
|
|
@@ -637,11 +799,27 @@ async function showConfiguration(config, format) {
|
|
|
637
799
|
"Confirm dangerous ops": config.confirmDangerous ? "Yes" : "No",
|
|
638
800
|
});
|
|
639
801
|
console.log(" Deployments:");
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
802
|
+
const deploymentEntries = Object.entries(config.deployments);
|
|
803
|
+
if (deploymentEntries.length === 0) {
|
|
804
|
+
console.log(pc.yellow(" No deployments configured"));
|
|
805
|
+
console.log();
|
|
806
|
+
printInfo("To get started:");
|
|
807
|
+
console.log(pc.dim(" • Run 'cortex init' to create a new project"));
|
|
808
|
+
console.log(pc.dim(" • Run 'cortex config add-deployment' to add an existing deployment"));
|
|
809
|
+
}
|
|
810
|
+
else {
|
|
811
|
+
for (const [name, deployment] of deploymentEntries) {
|
|
812
|
+
const isDefault = name === config.default;
|
|
813
|
+
// Default deployment is implicitly enabled; others check enabled field
|
|
814
|
+
const isEnabled = deployment.enabled === true || (deployment.enabled === undefined && isDefault);
|
|
815
|
+
const prefix = isDefault ? pc.green("→") : " ";
|
|
816
|
+
const statusBadge = isEnabled ? pc.green("[enabled]") : pc.dim("[disabled]");
|
|
817
|
+
const keyStatus = deployment.key ? pc.green("(key set)") : "";
|
|
818
|
+
console.log(` ${prefix} ${pc.cyan(name)}: ${deployment.url} ${statusBadge} ${keyStatus}`);
|
|
819
|
+
if (deployment.projectPath) {
|
|
820
|
+
console.log(pc.dim(` Project: ${deployment.projectPath}`));
|
|
821
|
+
}
|
|
822
|
+
}
|
|
645
823
|
}
|
|
646
824
|
console.log();
|
|
647
825
|
}
|