@eve-horizon/cli 0.2.11 → 0.2.13

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.
@@ -1,155 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.handleProfile = handleProfile;
4
- const context_1 = require("../lib/context");
5
- const output_1 = require("../lib/output");
6
- function handleProfile(subcommand, positionals, flags) {
7
- const json = Boolean(flags.json);
8
- if (flags.global) {
9
- throw new Error('Global profiles have been removed. Profiles are repo-local; remove --global.');
10
- }
11
- switch (subcommand) {
12
- case 'list': {
13
- const repoProfiles = (0, context_1.loadRepoProfiles)();
14
- const profiles = Object.entries(repoProfiles.profiles).map(([name, profile]) => ({
15
- name,
16
- active: name === repoProfiles.activeProfile,
17
- ...profile,
18
- }));
19
- (0, output_1.outputJson)({ active_profile: repoProfiles.activeProfile ?? null, profiles }, json);
20
- return;
21
- }
22
- case 'show': {
23
- const requestedName = positionals[0];
24
- const repoProfiles = (0, context_1.loadRepoProfiles)();
25
- const name = resolveProfileName(repoProfiles, requestedName);
26
- if (!name) {
27
- throw new Error('No local profiles configured. Use `eve profile set` to create one.');
28
- }
29
- const profile = repoProfiles.profiles[name];
30
- if (!profile) {
31
- throw new Error(`Profile ${name} not found`);
32
- }
33
- const active = repoProfiles.activeProfile === name;
34
- (0, output_1.outputJson)({ name, active, ...profile }, json, `${name} (local)`);
35
- return;
36
- }
37
- case 'use': {
38
- const isClear = Boolean(flags.clear);
39
- // Handle --clear: remove local profile
40
- if (isClear) {
41
- const removed = (0, context_1.removeRepoProfile)();
42
- if (removed) {
43
- (0, output_1.outputJson)({ cleared: true, path: (0, context_1.getRepoProfilePath)() }, json, `✓ Removed local profile store (${(0, context_1.getRepoProfilePath)()})`);
44
- }
45
- else {
46
- (0, output_1.outputJson)({ cleared: false }, json, `No local profile to remove`);
47
- }
48
- return;
49
- }
50
- const name = positionals[0];
51
- if (!name) {
52
- throw new Error('Usage: eve profile use <name>');
53
- }
54
- const repoProfiles = (0, context_1.loadRepoProfiles)();
55
- if (!repoProfiles.profiles[name]) {
56
- repoProfiles.profiles[name] = {};
57
- }
58
- repoProfiles.profiles[name] = applyProfileFlags(repoProfiles.profiles[name], flags);
59
- repoProfiles.activeProfile = name;
60
- (0, context_1.saveRepoProfiles)(repoProfiles);
61
- (0, output_1.outputJson)({ active_profile: name, path: (0, context_1.getRepoProfilePath)(), ...repoProfiles.profiles[name] }, json, `✓ Active profile: ${name} (${(0, context_1.getRepoProfilePath)()})`);
62
- return;
63
- }
64
- case 'create': {
65
- const name = positionals[0];
66
- if (!name) {
67
- throw new Error('Usage: eve profile create <name> [--api-url <url> ...]');
68
- }
69
- const repoProfiles = (0, context_1.loadRepoProfiles)();
70
- if (repoProfiles.profiles[name]) {
71
- throw new Error(`Profile ${name} already exists`);
72
- }
73
- repoProfiles.profiles[name] = applyProfileFlags({}, flags);
74
- if (!repoProfiles.activeProfile) {
75
- repoProfiles.activeProfile = name;
76
- }
77
- (0, context_1.saveRepoProfiles)(repoProfiles);
78
- (0, output_1.outputJson)({ name, ...repoProfiles.profiles[name] }, json, `✓ Profile created: ${name}`);
79
- return;
80
- }
81
- case 'set': {
82
- const repoProfiles = (0, context_1.loadRepoProfiles)();
83
- const name = resolveProfileName(repoProfiles, positionals[0]) ?? 'default';
84
- if (!repoProfiles.profiles[name]) {
85
- repoProfiles.profiles[name] = {};
86
- }
87
- repoProfiles.profiles[name] = applyProfileFlags(repoProfiles.profiles[name], flags);
88
- repoProfiles.activeProfile = name;
89
- (0, context_1.saveRepoProfiles)(repoProfiles);
90
- (0, output_1.outputJson)({ active_profile: name, ...repoProfiles.profiles[name], path: (0, context_1.getRepoProfilePath)() }, json, `✓ Profile set: ${name} (${(0, context_1.getRepoProfilePath)()})`);
91
- return;
92
- }
93
- case 'remove': {
94
- const name = positionals[0];
95
- if (!name) {
96
- throw new Error('Usage: eve profile remove <name>');
97
- }
98
- const repoProfiles = (0, context_1.loadRepoProfiles)();
99
- if (!repoProfiles.profiles[name]) {
100
- throw new Error(`Profile ${name} not found`);
101
- }
102
- delete repoProfiles.profiles[name];
103
- if (repoProfiles.activeProfile === name) {
104
- const [first] = Object.keys(repoProfiles.profiles);
105
- repoProfiles.activeProfile = first;
106
- }
107
- if (!repoProfiles.activeProfile && Object.keys(repoProfiles.profiles).length === 0) {
108
- (0, context_1.removeRepoProfile)();
109
- (0, output_1.outputJson)({ removed: name, cleared: true }, json, `✓ Removed profile ${name} (store cleared)`);
110
- return;
111
- }
112
- (0, context_1.saveRepoProfiles)(repoProfiles);
113
- (0, output_1.outputJson)({ removed: name, active_profile: repoProfiles.activeProfile ?? null }, json, `✓ Removed profile ${name}`);
114
- return;
115
- }
116
- default:
117
- throw new Error('Usage: eve profile <list|show|use|create|set|remove>');
118
- }
119
- }
120
- function applyProfileFlags(profile, flags) {
121
- const updated = { ...profile };
122
- if (typeof flags['api-url'] === 'string')
123
- updated.api_url = flags['api-url'];
124
- if (typeof flags.org === 'string')
125
- updated.org_id = flags.org;
126
- if (typeof flags.project === 'string')
127
- updated.project_id = flags.project;
128
- if (typeof flags['supabase-url'] === 'string')
129
- updated.supabase_url = flags['supabase-url'];
130
- if (typeof flags['supabase-anon-key'] === 'string')
131
- updated.supabase_anon_key = flags['supabase-anon-key'];
132
- // --harness accepts "harness" or "harness:variant" format
133
- if (typeof flags.harness === 'string')
134
- updated.default_harness = flags.harness;
135
- // Auth defaults
136
- if (typeof flags['default-email'] === 'string')
137
- updated.default_email = flags['default-email'];
138
- if (typeof flags['default-ssh-key'] === 'string')
139
- updated.default_ssh_key = flags['default-ssh-key'];
140
- return updated;
141
- }
142
- function resolveProfileName(repoProfiles, requestedName) {
143
- if (requestedName)
144
- return requestedName;
145
- if (repoProfiles.activeProfile)
146
- return repoProfiles.activeProfile;
147
- const names = Object.keys(repoProfiles.profiles);
148
- if (names.length === 0)
149
- return undefined;
150
- if (names.length === 1)
151
- return names[0];
152
- if (names.includes('default'))
153
- return 'default';
154
- return names[0];
155
- }
@@ -1,212 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.handleProject = handleProject;
4
- const args_1 = require("../lib/args");
5
- const client_1 = require("../lib/client");
6
- const output_1 = require("../lib/output");
7
- const node_fs_1 = require("node:fs");
8
- const node_path_1 = require("node:path");
9
- const node_child_process_1 = require("node:child_process");
10
- async function handleProject(subcommand, positionals, flags, context) {
11
- const json = Boolean(flags.json);
12
- switch (subcommand) {
13
- case 'ensure': {
14
- const name = typeof flags.name === 'string' ? flags.name : '';
15
- const repoUrl = typeof flags['repo-url'] === 'string' ? flags['repo-url'] : '';
16
- const branch = typeof flags.branch === 'string' ? flags.branch : 'main';
17
- const slug = typeof flags.slug === 'string' ? flags.slug : undefined;
18
- const orgIdRaw = typeof flags.org === 'string' ? flags.org : context.orgId;
19
- const force = (0, args_1.toBoolean)(flags.force) ?? false;
20
- if (!name || !repoUrl) {
21
- throw new Error('Usage: eve project ensure --name <name> --repo-url <url> [--branch <branch>] [--slug <slug>]');
22
- }
23
- if (!orgIdRaw) {
24
- throw new Error('Missing org id. Provide --org or set a profile default.');
25
- }
26
- const body = { org_id: orgIdRaw, name, repo_url: repoUrl, branch, force };
27
- if (slug)
28
- body.slug = slug;
29
- const project = await (0, client_1.requestJson)(context, '/projects/ensure', {
30
- method: 'POST',
31
- body,
32
- });
33
- (0, output_1.outputJson)(project, json, `✓ Project ready: ${project.id} (${name})`);
34
- return;
35
- }
36
- case 'list': {
37
- const all = Boolean(flags.all);
38
- const includeDeletedFlag = flags.include_deleted ?? flags['include-deleted'];
39
- // When --all is set, don't require org context
40
- const orgId = all
41
- ? (typeof flags.org === 'string' ? flags.org : undefined)
42
- : (typeof flags.org === 'string' ? flags.org : context.orgId);
43
- const query = buildQuery({
44
- limit: typeof flags.limit === 'string' ? flags.limit : (all ? '50' : undefined),
45
- offset: typeof flags.offset === 'string' ? flags.offset : undefined,
46
- include_deleted: (0, args_1.toBoolean)(includeDeletedFlag) ? 'true' : undefined,
47
- org_id: orgId,
48
- name: typeof flags.name === 'string' ? flags.name : undefined,
49
- });
50
- const response = await (0, client_1.requestJson)(context, `/projects${query}`);
51
- if (json) {
52
- (0, output_1.outputJson)(response, json);
53
- }
54
- else if (all) {
55
- console.log('All projects (admin view):');
56
- console.log('');
57
- (0, output_1.outputJson)(response, json);
58
- }
59
- else {
60
- (0, output_1.outputJson)(response, json);
61
- }
62
- return;
63
- }
64
- case 'get': {
65
- const projectId = positionals[0];
66
- if (!projectId)
67
- throw new Error('Usage: eve project get <project_id>');
68
- const includeDeletedFlag = flags.include_deleted ?? flags['include-deleted'];
69
- const query = buildQuery({
70
- include_deleted: (0, args_1.toBoolean)(includeDeletedFlag) ? 'true' : undefined,
71
- });
72
- const response = await (0, client_1.requestJson)(context, `/projects/${projectId}${query}`);
73
- (0, output_1.outputJson)(response, json);
74
- return;
75
- }
76
- case 'update': {
77
- const projectId = positionals[0];
78
- if (!projectId) {
79
- throw new Error('Usage: eve project update <project_id> [--name <name>] [--repo-url <url>]');
80
- }
81
- const body = {};
82
- if (typeof flags.name === 'string')
83
- body.name = flags.name;
84
- if (typeof flags['repo-url'] === 'string')
85
- body.repo_url = flags['repo-url'];
86
- if (typeof flags.branch === 'string')
87
- body.branch = flags.branch;
88
- const deleted = (0, args_1.toBoolean)(flags.deleted);
89
- if (deleted !== undefined)
90
- body.deleted = deleted;
91
- const response = await (0, client_1.requestJson)(context, `/projects/${projectId}`, { method: 'PATCH', body });
92
- (0, output_1.outputJson)(response, json);
93
- return;
94
- }
95
- case 'sync': {
96
- const dir = typeof flags.dir === 'string' ? flags.dir : process.cwd();
97
- const manifestPath = (0, node_path_1.join)(dir, '.eve', 'manifest.yaml');
98
- const validateSecretsFlag = flags['validate-secrets'] ?? flags.validate_secrets;
99
- const validateSecrets = (0, args_1.toBoolean)(validateSecretsFlag) ?? false;
100
- const strict = (0, args_1.toBoolean)(flags.strict) ?? false;
101
- // Read manifest file
102
- let yaml;
103
- try {
104
- yaml = (0, node_fs_1.readFileSync)(manifestPath, 'utf-8');
105
- }
106
- catch (error) {
107
- throw new Error(`Failed to read manifest at ${manifestPath}: ${error.message}`);
108
- }
109
- // Get git info
110
- let gitSha;
111
- let branch;
112
- try {
113
- gitSha = (0, node_child_process_1.execSync)('git rev-parse HEAD', { cwd: dir, encoding: 'utf-8' }).trim();
114
- branch = (0, node_child_process_1.execSync)('git branch --show-current', { cwd: dir, encoding: 'utf-8' }).trim();
115
- }
116
- catch (error) {
117
- // Git info is optional, continue without it
118
- console.warn('Warning: Could not get git info:', error.message);
119
- }
120
- // Determine project ID
121
- const projectIdRaw = typeof flags.project === 'string' ? flags.project : context.projectId;
122
- if (!projectIdRaw) {
123
- // Try to parse project ID from manifest
124
- const projectMatch = yaml.match(/^project:\s*(\S+)/m);
125
- if (projectMatch) {
126
- const projectIdFromManifest = projectMatch[1];
127
- const response = await (0, client_1.requestJson)(context, `/projects/${projectIdFromManifest}/manifest`, {
128
- method: 'POST',
129
- body: {
130
- yaml,
131
- git_sha: gitSha,
132
- branch,
133
- validate_secrets: validateSecrets || strict,
134
- strict,
135
- },
136
- });
137
- if (json) {
138
- (0, output_1.outputJson)(response, json);
139
- }
140
- else {
141
- console.log(`✓ Manifest synced to ${projectIdFromManifest}`);
142
- console.log(` Hash: ${response.manifest_hash.substring(0, 12)}...`);
143
- if (gitSha)
144
- console.log(` Git SHA: ${gitSha.substring(0, 8)}`);
145
- if (branch)
146
- console.log(` Branch: ${branch}`);
147
- if (response.parsed_defaults && Object.keys(response.parsed_defaults).length > 0) {
148
- console.log('\nParsed defaults.env:');
149
- Object.entries(response.parsed_defaults).forEach(([key, value]) => {
150
- console.log(` ${key}: ${JSON.stringify(value)}`);
151
- });
152
- }
153
- if (response.warnings && response.warnings.length > 0) {
154
- console.log('\nWarnings:');
155
- response.warnings.forEach((warning) => {
156
- console.log(` - ${warning}`);
157
- });
158
- }
159
- }
160
- return;
161
- }
162
- throw new Error('Missing project id. Provide --project or set a profile default, or add "project: proj_xxx" to manifest.');
163
- }
164
- const response = await (0, client_1.requestJson)(context, `/projects/${projectIdRaw}/manifest`, {
165
- method: 'POST',
166
- body: {
167
- yaml,
168
- git_sha: gitSha,
169
- branch,
170
- validate_secrets: validateSecrets || strict,
171
- strict,
172
- },
173
- });
174
- if (json) {
175
- (0, output_1.outputJson)(response, json);
176
- }
177
- else {
178
- console.log(`✓ Manifest synced to ${projectIdRaw}`);
179
- console.log(` Hash: ${response.manifest_hash.substring(0, 12)}...`);
180
- if (gitSha)
181
- console.log(` Git SHA: ${gitSha.substring(0, 8)}`);
182
- if (branch)
183
- console.log(` Branch: ${branch}`);
184
- if (response.parsed_defaults && Object.keys(response.parsed_defaults).length > 0) {
185
- console.log('\nParsed defaults.env:');
186
- Object.entries(response.parsed_defaults).forEach(([key, value]) => {
187
- console.log(` ${key}: ${JSON.stringify(value)}`);
188
- });
189
- }
190
- if (response.warnings && response.warnings.length > 0) {
191
- console.log('\nWarnings:');
192
- response.warnings.forEach((warning) => {
193
- console.log(` - ${warning}`);
194
- });
195
- }
196
- }
197
- return;
198
- }
199
- default:
200
- throw new Error('Usage: eve project <ensure|list|get|update|sync>');
201
- }
202
- }
203
- function buildQuery(params) {
204
- const search = new URLSearchParams();
205
- Object.entries(params).forEach(([key, value]) => {
206
- if (value === undefined || value === '')
207
- return;
208
- search.set(key, String(value));
209
- });
210
- const query = search.toString();
211
- return query ? `?${query}` : '';
212
- }
@@ -1,69 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.handleRelease = handleRelease;
4
- const client_1 = require("../lib/client");
5
- const output_1 = require("../lib/output");
6
- const node_fs_1 = require("node:fs");
7
- const node_path_1 = require("node:path");
8
- async function handleRelease(subcommand, positionals, flags, context) {
9
- const json = Boolean(flags.json);
10
- switch (subcommand) {
11
- case 'resolve': {
12
- const tag = positionals[0];
13
- if (!tag) {
14
- throw new Error('Usage: eve release resolve <tag> [--project <id>]');
15
- }
16
- // Determine project ID
17
- let projectId = typeof flags.project === 'string' ? flags.project : context.projectId;
18
- // If no project ID provided, try to detect from local .eve/manifest.yaml
19
- if (!projectId) {
20
- const dir = typeof flags.dir === 'string' ? flags.dir : process.cwd();
21
- const manifestPath = (0, node_path_1.join)(dir, '.eve', 'manifest.yaml');
22
- try {
23
- const yaml = (0, node_fs_1.readFileSync)(manifestPath, 'utf-8');
24
- const projectMatch = yaml.match(/^project:\s*(\S+)/m);
25
- if (projectMatch) {
26
- projectId = projectMatch[1];
27
- }
28
- }
29
- catch (error) {
30
- // Manifest file not found or not readable, continue without it
31
- }
32
- }
33
- if (!projectId) {
34
- throw new Error('Missing project id. Provide --project, set a profile default, or add "project: proj_xxx" to .eve/manifest.yaml');
35
- }
36
- // Call the API endpoint
37
- try {
38
- const release = await (0, client_1.requestJson)(context, `/projects/${projectId}/releases/by-tag/${encodeURIComponent(tag)}`);
39
- if (json) {
40
- // Output full JSON
41
- (0, output_1.outputJson)(release, json);
42
- }
43
- else {
44
- // Human-readable format
45
- const displayTag = release.tag || tag;
46
- const displayVersion = release.version || 'N/A';
47
- const shortSha = release.git_sha.substring(0, 8);
48
- const shortHash = release.manifest_hash.substring(0, 12);
49
- console.log(`Release ${displayTag}`);
50
- console.log(` ID: ${release.id}`);
51
- console.log(` SHA: ${shortSha}...`);
52
- console.log(` Manifest: ${shortHash}...`);
53
- console.log(` Version: ${displayVersion}`);
54
- }
55
- }
56
- catch (error) {
57
- // Enhance 404 errors with more context
58
- if (error instanceof Error && error.message.includes('HTTP 404')) {
59
- throw new Error(`Release with tag "${tag}" not found for project ${projectId}\n\n` +
60
- `Make sure the release exists and the tag is correct.`);
61
- }
62
- throw error;
63
- }
64
- return;
65
- }
66
- default:
67
- throw new Error('Usage: eve release <resolve>');
68
- }
69
- }
@@ -1,218 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.handleSecrets = handleSecrets;
4
- const node_fs_1 = require("node:fs");
5
- const client_1 = require("../lib/client");
6
- const output_1 = require("../lib/output");
7
- async function handleSecrets(subcommand, positionals, flags, context) {
8
- const json = Boolean(flags.json);
9
- switch (subcommand) {
10
- case 'set': {
11
- const scope = resolveScope(flags, context);
12
- const key = positionals[0] ?? (typeof flags.key === 'string' ? flags.key : undefined);
13
- const value = positionals[1] ?? (typeof flags.value === 'string' ? flags.value : undefined);
14
- const type = typeof flags.type === 'string' ? flags.type : undefined;
15
- if (!key || !value) {
16
- throw new Error('Usage: eve secrets set <key> <value> [--project <id>|--org <id>|--user <id>|--system] [--type <type>]');
17
- }
18
- const body = { key, value };
19
- if (type)
20
- body.type = type;
21
- const response = await (0, client_1.requestJson)(context, `${scopeBasePath(scope)}`, {
22
- method: 'POST',
23
- body,
24
- });
25
- (0, output_1.outputJson)(response, json, `✓ Secret set: ${key}`);
26
- return;
27
- }
28
- case 'list': {
29
- const scope = resolveScope(flags, context);
30
- const query = buildQuery({
31
- limit: typeof flags.limit === 'string' ? flags.limit : undefined,
32
- offset: typeof flags.offset === 'string' ? flags.offset : undefined,
33
- });
34
- const response = await (0, client_1.requestJson)(context, `${scopeBasePath(scope)}${query}`);
35
- (0, output_1.outputJson)(response, json);
36
- return;
37
- }
38
- case 'show': {
39
- const scope = resolveScope(flags, context);
40
- const key = positionals[0] ?? (typeof flags.key === 'string' ? flags.key : undefined);
41
- if (!key) {
42
- throw new Error('Usage: eve secrets show <key> [--project <id>|--org <id>|--user <id>|--system]');
43
- }
44
- const response = await (0, client_1.requestJson)(context, `${scopeBasePath(scope)}/${encodeURIComponent(key)}`);
45
- (0, output_1.outputJson)(response, json);
46
- return;
47
- }
48
- case 'delete': {
49
- const scope = resolveScope(flags, context);
50
- const key = positionals[0] ?? (typeof flags.key === 'string' ? flags.key : undefined);
51
- if (!key) {
52
- throw new Error('Usage: eve secrets delete <key> [--project <id>|--org <id>|--user <id>|--system]');
53
- }
54
- await (0, client_1.requestJson)(context, `${scopeBasePath(scope)}/${encodeURIComponent(key)}`, { method: 'DELETE' });
55
- (0, output_1.outputJson)({ ok: true }, json, `✓ Secret deleted: ${key}`);
56
- return;
57
- }
58
- case 'import': {
59
- const scope = resolveScope(flags, context);
60
- const filePath = typeof flags.file === 'string' ? flags.file : '.env';
61
- const fileContents = (0, node_fs_1.readFileSync)(filePath, 'utf8');
62
- const entries = parseEnvFile(fileContents);
63
- if (entries.length === 0) {
64
- throw new Error(`No entries found in ${filePath}`);
65
- }
66
- for (const [key, value] of entries) {
67
- await (0, client_1.requestJson)(context, `${scopeBasePath(scope)}`, {
68
- method: 'POST',
69
- body: { key, value },
70
- });
71
- }
72
- (0, output_1.outputJson)({ imported: entries.length }, json, `✓ Imported ${entries.length} secrets`);
73
- return;
74
- }
75
- case 'validate': {
76
- const projectId = resolveProjectScope(flags, context);
77
- const keys = parseKeys(positionals, flags);
78
- const body = {};
79
- if (keys.length > 0)
80
- body.keys = keys;
81
- const response = await (0, client_1.requestJson)(context, `/projects/${projectId}/secrets/validate`, {
82
- method: 'POST',
83
- body,
84
- });
85
- if (json) {
86
- (0, output_1.outputJson)(response, json);
87
- }
88
- else if (response.missing.length === 0) {
89
- console.log('✓ All required secrets are present');
90
- }
91
- else {
92
- console.log('Missing secrets:');
93
- response.missing.forEach((item) => {
94
- console.log(`- ${item.key}`);
95
- item.hints.forEach((hint) => console.log(` ${hint}`));
96
- });
97
- }
98
- return;
99
- }
100
- case 'ensure': {
101
- const projectId = resolveProjectScope(flags, context);
102
- const keys = parseKeys(positionals, flags);
103
- if (keys.length === 0) {
104
- throw new Error('Usage: eve secrets ensure --project <id> --keys <key1,key2>');
105
- }
106
- const response = await (0, client_1.requestJson)(context, `/projects/${projectId}/secrets/ensure`, {
107
- method: 'POST',
108
- body: { keys },
109
- });
110
- (0, output_1.outputJson)(response, json, `✓ Secrets ensured (${response.created.length} created)`);
111
- return;
112
- }
113
- case 'export': {
114
- const projectId = resolveProjectScope(flags, context);
115
- const keys = parseKeys(positionals, flags);
116
- if (keys.length === 0) {
117
- throw new Error('Usage: eve secrets export --project <id> --keys <key1,key2>');
118
- }
119
- const response = await (0, client_1.requestJson)(context, `/projects/${projectId}/secrets/export`, {
120
- method: 'POST',
121
- body: { keys },
122
- });
123
- if (json) {
124
- (0, output_1.outputJson)(response, json);
125
- }
126
- else {
127
- console.log('Exported secrets (handle carefully):');
128
- response.data.forEach((item) => {
129
- console.log(`${item.key}=${item.value}`);
130
- });
131
- }
132
- return;
133
- }
134
- default:
135
- throw new Error('Usage: eve secrets <set|list|show|delete|import|validate|ensure|export>');
136
- }
137
- }
138
- function resolveScope(flags, context) {
139
- // Explicit flags take priority in the order: system > project > org > user
140
- const explicitSystem = Boolean(flags.system);
141
- const explicitProject = typeof flags.project === 'string' ? flags.project : undefined;
142
- const explicitOrg = typeof flags.org === 'string' ? flags.org : undefined;
143
- const explicitUser = typeof flags.user === 'string' ? flags.user : undefined;
144
- // Check for mutual exclusivity
145
- const explicitFlags = [explicitSystem, explicitProject, explicitOrg, explicitUser].filter(Boolean);
146
- if (explicitFlags.length > 1) {
147
- throw new Error('Cannot specify multiple scope flags. Use only one of: --system, --project, --org, or --user');
148
- }
149
- // If explicit flags are provided, use them in priority order
150
- if (explicitSystem)
151
- return { scopeType: 'system', scopeId: 'system' };
152
- if (explicitProject)
153
- return { scopeType: 'project', scopeId: explicitProject };
154
- if (explicitOrg)
155
- return { scopeType: 'org', scopeId: explicitOrg };
156
- if (explicitUser)
157
- return { scopeType: 'user', scopeId: explicitUser };
158
- // Fall back to profile defaults
159
- if (context.projectId)
160
- return { scopeType: 'project', scopeId: context.projectId };
161
- if (context.orgId)
162
- return { scopeType: 'org', scopeId: context.orgId };
163
- throw new Error('Missing scope. Provide --system, --project, --org, or --user (or set profile defaults).');
164
- }
165
- function scopeBasePath(scope) {
166
- switch (scope.scopeType) {
167
- case 'system':
168
- return `/system/secrets`;
169
- case 'project':
170
- return `/projects/${scope.scopeId}/secrets`;
171
- case 'org':
172
- return `/orgs/${scope.scopeId}/secrets`;
173
- case 'user':
174
- return `/users/${scope.scopeId}/secrets`;
175
- }
176
- }
177
- function resolveProjectScope(flags, context) {
178
- const scope = resolveScope(flags, context);
179
- if (scope.scopeType !== 'project') {
180
- throw new Error('This command requires --project (or a project default profile).');
181
- }
182
- return scope.scopeId;
183
- }
184
- function buildQuery(params) {
185
- const search = new URLSearchParams();
186
- Object.entries(params).forEach(([key, value]) => {
187
- if (value === undefined || value === '')
188
- return;
189
- search.set(key, String(value));
190
- });
191
- const query = search.toString();
192
- return query ? `?${query}` : '';
193
- }
194
- function parseEnvFile(contents) {
195
- const lines = contents.split(/\r?\n/);
196
- const entries = [];
197
- for (const line of lines) {
198
- const trimmed = line.trim();
199
- if (!trimmed || trimmed.startsWith('#'))
200
- continue;
201
- const eqIndex = trimmed.indexOf('=');
202
- if (eqIndex === -1)
203
- continue;
204
- const key = trimmed.slice(0, eqIndex).trim();
205
- const value = trimmed.slice(eqIndex + 1).trim();
206
- if (!key)
207
- continue;
208
- entries.push([key, value]);
209
- }
210
- return entries;
211
- }
212
- function parseKeys(positionals, flags) {
213
- const positionalKeys = positionals.filter((value) => typeof value === 'string' && value.length > 0);
214
- const flagKeys = typeof flags.keys === 'string'
215
- ? flags.keys.split(',').map((value) => value.trim()).filter(Boolean)
216
- : [];
217
- return Array.from(new Set([...positionalKeys, ...flagKeys]));
218
- }