zinkee 0.1.44 → 0.1.46
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 +4 -0
- package/dist/chunk-MHEVRMDX.js +1230 -0
- package/dist/chunk-MHEVRMDX.js.map +1 -0
- package/{src/utils/examples.ts → dist/examples-67U5IRBS.js} +866 -1141
- package/dist/examples-67U5IRBS.js.map +1 -0
- package/dist/index.js +1145 -8456
- package/dist/index.js.map +1 -1
- package/package.json +6 -3
- package/.github/workflows/npm-publish.yml +0 -77
- package/.github/workflows/pr-checks.yml +0 -36
- package/AGENTS.md +0 -110
- package/docs/cli-contract.md +0 -41
- package/docs/npm-release.md +0 -64
- package/docs/superpowers/plans/2026-03-24-zinkee-cli-implementation.md +0 -837
- package/docs/superpowers/plans/2026-03-25-cli-backend-error-contract.md +0 -503
- package/docs/superpowers/plans/2026-03-26-display-freeform-create.md +0 -389
- package/docs/superpowers/specs/2026-03-24-zinkee-cli-backend-blockers.md +0 -172
- package/docs/superpowers/specs/2026-03-24-zinkee-cli-design.md +0 -1576
- package/docs/superpowers/specs/2026-03-24-zinkee-cli-e2e-checklist.md +0 -215
- package/docs/superpowers/specs/2026-03-24-zinkee-cli-e2e-design.md +0 -492
- package/docs/superpowers/specs/2026-03-24-zinkee-cli-e2e-status.md +0 -307
- package/docs/superpowers/specs/2026-07-30-cli-pr-checks-design.md +0 -37
- package/src/api/automations.ts +0 -404
- package/src/api/comments.ts +0 -51
- package/src/api/displays.ts +0 -337
- package/src/api/document-templates.ts +0 -110
- package/src/api/files.ts +0 -50
- package/src/api/formulas.test.ts +0 -65
- package/src/api/formulas.ts +0 -67
- package/src/api/logs.ts +0 -34
- package/src/api/navigation.ts +0 -70
- package/src/api/records.ts +0 -184
- package/src/api/schemas.ts +0 -148
- package/src/api/teamspace.ts +0 -110
- package/src/cli-examples.ts +0 -130
- package/src/cli-runner.ts +0 -95
- package/src/client.test.ts +0 -189
- package/src/client.ts +0 -269
- package/src/command-registry.ts +0 -882
- package/src/commands/automations.test.ts +0 -1030
- package/src/commands/automations.ts +0 -2102
- package/src/commands/comments.test.ts +0 -214
- package/src/commands/comments.ts +0 -303
- package/src/commands/config.test.ts +0 -81
- package/src/commands/config.ts +0 -150
- package/src/commands/displays.test.ts +0 -1105
- package/src/commands/displays.ts +0 -1442
- package/src/commands/document-templates.test.ts +0 -569
- package/src/commands/document-templates.ts +0 -563
- package/src/commands/files.test.ts +0 -284
- package/src/commands/files.ts +0 -280
- package/src/commands/formulas.test.ts +0 -194
- package/src/commands/formulas.ts +0 -243
- package/src/commands/logs.test.ts +0 -123
- package/src/commands/logs.ts +0 -159
- package/src/commands/navigation.test.ts +0 -211
- package/src/commands/navigation.ts +0 -348
- package/src/commands/profiles.test.ts +0 -191
- package/src/commands/profiles.ts +0 -303
- package/src/commands/records.test.ts +0 -860
- package/src/commands/records.ts +0 -883
- package/src/commands/schemas.test.ts +0 -1252
- package/src/commands/schemas.ts +0 -890
- package/src/commands/teamspace.test.ts +0 -229
- package/src/commands/teamspace.ts +0 -546
- package/src/completion/engine.test.ts +0 -138
- package/src/completion/engine.ts +0 -168
- package/src/completion/install.test.ts +0 -179
- package/src/completion/install.ts +0 -260
- package/src/completion/runtime.ts +0 -150
- package/src/completion/scripts.ts +0 -91
- package/src/config.test.ts +0 -362
- package/src/config.ts +0 -294
- package/src/index.test.ts +0 -217
- package/src/index.ts +0 -8
- package/src/parsers/expressions.test.ts +0 -95
- package/src/parsers/expressions.ts +0 -128
- package/src/parsers/kv.test.ts +0 -35
- package/src/parsers/kv.ts +0 -49
- package/src/parsers/selectors.test.ts +0 -23
- package/src/parsers/selectors.ts +0 -29
- package/src/program.ts +0 -64
- package/src/runtime-context.ts +0 -103
- package/src/types.ts +0 -76
- package/src/utils/argv-rewrite.test.ts +0 -149
- package/src/utils/argv-rewrite.ts +0 -269
- package/src/utils/errors.test.ts +0 -85
- package/src/utils/errors.ts +0 -191
- package/src/utils/examples.test.ts +0 -374
- package/src/utils/output.test.ts +0 -65
- package/src/utils/output.ts +0 -154
- package/src/utils/schema-fields.ts +0 -1016
- package/tsconfig.json +0 -20
- package/tsup.config.ts +0 -13
|
@@ -1,191 +0,0 @@
|
|
|
1
|
-
import { mkdtempSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
|
-
import { tmpdir } from "node:os";
|
|
3
|
-
import { join } from "node:path";
|
|
4
|
-
|
|
5
|
-
import { describe, expect, it } from "vitest";
|
|
6
|
-
|
|
7
|
-
import { buildProgram } from "../index.js";
|
|
8
|
-
|
|
9
|
-
function createTempConfig(contents: string): string {
|
|
10
|
-
const dir = mkdtempSync(join(tmpdir(), "zinkee-profiles-"));
|
|
11
|
-
const filePath = join(dir, "config.toml");
|
|
12
|
-
writeFileSync(filePath, contents, "utf8");
|
|
13
|
-
return filePath;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
function createStdoutBuffer() {
|
|
17
|
-
let output = "";
|
|
18
|
-
|
|
19
|
-
return {
|
|
20
|
-
stdout: {
|
|
21
|
-
write(chunk: string) {
|
|
22
|
-
output += chunk;
|
|
23
|
-
return true;
|
|
24
|
-
},
|
|
25
|
-
},
|
|
26
|
-
read() {
|
|
27
|
-
return output;
|
|
28
|
-
},
|
|
29
|
-
};
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
describe("profiles commands", () => {
|
|
33
|
-
it("registers the profiles command group", () => {
|
|
34
|
-
const program = buildProgram();
|
|
35
|
-
|
|
36
|
-
expect(program.commands.some((command) => command.name() === "profiles")).toBe(true);
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
it("redacts secrets when showing a profile", async () => {
|
|
40
|
-
const configPath = createTempConfig(`
|
|
41
|
-
default_profile = "prod"
|
|
42
|
-
|
|
43
|
-
[profiles.prod]
|
|
44
|
-
api_key = "secret-token-1234"
|
|
45
|
-
base_url = "https://api.zinkee.test"
|
|
46
|
-
`);
|
|
47
|
-
const output = createStdoutBuffer();
|
|
48
|
-
const program = buildProgram({ configPath, stdout: output.stdout });
|
|
49
|
-
|
|
50
|
-
await program.parseAsync(["node", "zinkee", "profiles", "get", "prod"]);
|
|
51
|
-
|
|
52
|
-
expect(output.read()).toContain("apiKey");
|
|
53
|
-
expect(output.read()).toContain("********1234");
|
|
54
|
-
expect(output.read()).not.toContain("secret-token-1234");
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
it("adds a profile and writes a TOML config file", async () => {
|
|
58
|
-
const configPath = join(mkdtempSync(join(tmpdir(), "zinkee-profiles-add-")), "config.toml");
|
|
59
|
-
const output = createStdoutBuffer();
|
|
60
|
-
const program = buildProgram({ configPath, stdout: output.stdout });
|
|
61
|
-
|
|
62
|
-
await program.parseAsync([
|
|
63
|
-
"node",
|
|
64
|
-
"zinkee",
|
|
65
|
-
"profiles",
|
|
66
|
-
"add",
|
|
67
|
-
"local",
|
|
68
|
-
"--api-key",
|
|
69
|
-
"new-token-5678",
|
|
70
|
-
"--base-url",
|
|
71
|
-
"http://localhost:8088",
|
|
72
|
-
]);
|
|
73
|
-
|
|
74
|
-
const saved = readFileSync(configPath, "utf8");
|
|
75
|
-
|
|
76
|
-
expect(output.read()).toContain('Added profile "local".');
|
|
77
|
-
expect(saved).toContain('[profiles.local]');
|
|
78
|
-
expect(saved).toContain('api_key = "new-token-5678"');
|
|
79
|
-
expect(saved).toContain('base_url = "http://localhost:8088"');
|
|
80
|
-
expect(saved).toContain('default_profile = "local"');
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
it("rejects a malformed base URL when adding a profile", async () => {
|
|
84
|
-
const configPath = join(
|
|
85
|
-
mkdtempSync(join(tmpdir(), "zinkee-profiles-add-bad-url-")),
|
|
86
|
-
"config.toml",
|
|
87
|
-
);
|
|
88
|
-
const output = createStdoutBuffer();
|
|
89
|
-
const program = buildProgram({ configPath, stdout: output.stdout });
|
|
90
|
-
|
|
91
|
-
await expect(
|
|
92
|
-
program.parseAsync([
|
|
93
|
-
"node",
|
|
94
|
-
"zinkee",
|
|
95
|
-
"profiles",
|
|
96
|
-
"add",
|
|
97
|
-
"broken",
|
|
98
|
-
"--api-key",
|
|
99
|
-
"any",
|
|
100
|
-
"--base-url",
|
|
101
|
-
"api-z2.zinkee.com",
|
|
102
|
-
]),
|
|
103
|
-
).rejects.toMatchObject({
|
|
104
|
-
name: "CliError",
|
|
105
|
-
code: "configuration_error",
|
|
106
|
-
message: '"--base-url" must be an absolute http(s) URL.',
|
|
107
|
-
});
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
it("rejects a non-http(s) base URL when adding a profile", async () => {
|
|
111
|
-
const configPath = join(
|
|
112
|
-
mkdtempSync(join(tmpdir(), "zinkee-profiles-add-ftp-")),
|
|
113
|
-
"config.toml",
|
|
114
|
-
);
|
|
115
|
-
const output = createStdoutBuffer();
|
|
116
|
-
const program = buildProgram({ configPath, stdout: output.stdout });
|
|
117
|
-
|
|
118
|
-
await expect(
|
|
119
|
-
program.parseAsync([
|
|
120
|
-
"node",
|
|
121
|
-
"zinkee",
|
|
122
|
-
"profiles",
|
|
123
|
-
"add",
|
|
124
|
-
"broken",
|
|
125
|
-
"--api-key",
|
|
126
|
-
"any",
|
|
127
|
-
"--base-url",
|
|
128
|
-
"ftp://api-z2.zinkee.com",
|
|
129
|
-
]),
|
|
130
|
-
).rejects.toMatchObject({
|
|
131
|
-
name: "CliError",
|
|
132
|
-
code: "configuration_error",
|
|
133
|
-
message: '"--base-url" must be an absolute http(s) URL.',
|
|
134
|
-
});
|
|
135
|
-
});
|
|
136
|
-
|
|
137
|
-
it("normalizes trailing slashes when adding a profile", async () => {
|
|
138
|
-
const configPath = join(
|
|
139
|
-
mkdtempSync(join(tmpdir(), "zinkee-profiles-add-slash-")),
|
|
140
|
-
"config.toml",
|
|
141
|
-
);
|
|
142
|
-
const output = createStdoutBuffer();
|
|
143
|
-
const program = buildProgram({ configPath, stdout: output.stdout });
|
|
144
|
-
|
|
145
|
-
await program.parseAsync([
|
|
146
|
-
"node",
|
|
147
|
-
"zinkee",
|
|
148
|
-
"profiles",
|
|
149
|
-
"add",
|
|
150
|
-
"local",
|
|
151
|
-
"--api-key",
|
|
152
|
-
"any",
|
|
153
|
-
"--base-url",
|
|
154
|
-
"https://api-z2.zinkee.com///",
|
|
155
|
-
]);
|
|
156
|
-
|
|
157
|
-
const saved = readFileSync(configPath, "utf8");
|
|
158
|
-
|
|
159
|
-
expect(saved).toContain('base_url = "https://api-z2.zinkee.com"');
|
|
160
|
-
});
|
|
161
|
-
|
|
162
|
-
it("rejects a malformed base URL when updating a profile", async () => {
|
|
163
|
-
const configPath = createTempConfig(`
|
|
164
|
-
[profiles.prod]
|
|
165
|
-
api_key = "secret"
|
|
166
|
-
base_url = "https://api-z2.zinkee.com"
|
|
167
|
-
`);
|
|
168
|
-
const output = createStdoutBuffer();
|
|
169
|
-
const program = buildProgram({ configPath, stdout: output.stdout });
|
|
170
|
-
|
|
171
|
-
await expect(
|
|
172
|
-
program.parseAsync([
|
|
173
|
-
"node",
|
|
174
|
-
"zinkee",
|
|
175
|
-
"profiles",
|
|
176
|
-
"update",
|
|
177
|
-
"prod",
|
|
178
|
-
"--base-url",
|
|
179
|
-
"not a url",
|
|
180
|
-
]),
|
|
181
|
-
).rejects.toMatchObject({
|
|
182
|
-
name: "CliError",
|
|
183
|
-
code: "configuration_error",
|
|
184
|
-
message: '"--base-url" must be an absolute http(s) URL.',
|
|
185
|
-
});
|
|
186
|
-
|
|
187
|
-
const saved = readFileSync(configPath, "utf8");
|
|
188
|
-
|
|
189
|
-
expect(saved).toContain('base_url = "https://api-z2.zinkee.com"');
|
|
190
|
-
});
|
|
191
|
-
});
|
package/src/commands/profiles.ts
DELETED
|
@@ -1,303 +0,0 @@
|
|
|
1
|
-
import type { Writable } from "node:stream";
|
|
2
|
-
|
|
3
|
-
import { Command } from "commander";
|
|
4
|
-
|
|
5
|
-
import {
|
|
6
|
-
defaultConfigPath,
|
|
7
|
-
ProfileResolutionError,
|
|
8
|
-
readConfigIfExists,
|
|
9
|
-
redactProfile,
|
|
10
|
-
removeProfileConfig,
|
|
11
|
-
setDefaultProfile,
|
|
12
|
-
setProfileConfig,
|
|
13
|
-
validateBaseUrl,
|
|
14
|
-
writeConfig,
|
|
15
|
-
} from "../config.js";
|
|
16
|
-
import type { AppConfig, ProfileConfig } from "../types.js";
|
|
17
|
-
import { CliError } from "../utils/errors.js";
|
|
18
|
-
import { buildJsonSuccess, printTable } from "../utils/output.js";
|
|
19
|
-
|
|
20
|
-
interface CommandIo {
|
|
21
|
-
write(chunk: string): unknown;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export interface RegisterProfilesCommandsOptions {
|
|
25
|
-
configPath?: string;
|
|
26
|
-
stdout?: CommandIo;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
interface GlobalOptions {
|
|
30
|
-
json?: boolean;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export interface DisplayProfile extends ProfileConfig {
|
|
34
|
-
name: string;
|
|
35
|
-
isDefault: boolean;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
function getCommandIo(stdout: CommandIo | undefined): CommandIo {
|
|
39
|
-
return stdout ?? (process.stdout as Writable);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
function writeLine(stdout: CommandIo, value: string): void {
|
|
43
|
-
stdout.write(`${value}\n`);
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
function getGlobalOptions(command: Command): GlobalOptions {
|
|
47
|
-
return command.optsWithGlobals<GlobalOptions>();
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
function emitJson(
|
|
51
|
-
stdout: CommandIo,
|
|
52
|
-
commandName: string,
|
|
53
|
-
data: unknown,
|
|
54
|
-
configPath: string,
|
|
55
|
-
): void {
|
|
56
|
-
writeLine(
|
|
57
|
-
stdout,
|
|
58
|
-
JSON.stringify(buildJsonSuccess(data, { command: commandName, configPath })),
|
|
59
|
-
);
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
function readRequiredConfig(filePath: string): AppConfig {
|
|
63
|
-
const config = readConfigIfExists(filePath);
|
|
64
|
-
|
|
65
|
-
if (config) {
|
|
66
|
-
return config;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
throw new CliError("configuration_error", `Config file not found at ${filePath}.`);
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
function getRequiredProfile(config: AppConfig, profileName: string): ProfileConfig {
|
|
73
|
-
const profile = config.profiles[profileName];
|
|
74
|
-
|
|
75
|
-
if (profile) {
|
|
76
|
-
return profile;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
throw new CliError("configuration_error", `Profile "${profileName}" not found in config.`);
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
function toDisplayProfile(
|
|
83
|
-
profileName: string,
|
|
84
|
-
profile: ProfileConfig,
|
|
85
|
-
defaultProfile: string | undefined,
|
|
86
|
-
): DisplayProfile {
|
|
87
|
-
return {
|
|
88
|
-
name: profileName,
|
|
89
|
-
isDefault: defaultProfile === profileName,
|
|
90
|
-
...redactProfile(profile),
|
|
91
|
-
};
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
function loadConfigForAdd(filePath: string): AppConfig {
|
|
95
|
-
return readConfigIfExists(filePath) ?? { profiles: {} };
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
function normalizeProfileBaseUrl(baseUrl: string | undefined): string | undefined {
|
|
99
|
-
if (baseUrl === undefined) {
|
|
100
|
-
return undefined;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
try {
|
|
104
|
-
return validateBaseUrl(baseUrl, '"--base-url"');
|
|
105
|
-
} catch (error) {
|
|
106
|
-
if (error instanceof ProfileResolutionError) {
|
|
107
|
-
throw new CliError("configuration_error", error.message);
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
throw error;
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
function emitProfilesTable(stdout: CommandIo, data: readonly DisplayProfile[]): void {
|
|
115
|
-
printTable(
|
|
116
|
-
data.map((profile) => ({
|
|
117
|
-
name: profile.name,
|
|
118
|
-
default: profile.isDefault ? "yes" : "",
|
|
119
|
-
baseUrl: profile.baseUrl ?? "",
|
|
120
|
-
apiKey: profile.apiKey ?? "",
|
|
121
|
-
})),
|
|
122
|
-
["name", "default", "baseUrl", "apiKey"],
|
|
123
|
-
stdout,
|
|
124
|
-
);
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
export function registerProfilesCommands(
|
|
128
|
-
program: Command,
|
|
129
|
-
options: RegisterProfilesCommandsOptions = {},
|
|
130
|
-
): void {
|
|
131
|
-
const filePath = options.configPath ?? defaultConfigPath;
|
|
132
|
-
const stdout = getCommandIo(options.stdout);
|
|
133
|
-
const profiles = program.command("profiles").description("Manage local CLI profiles");
|
|
134
|
-
|
|
135
|
-
profiles
|
|
136
|
-
.command("list")
|
|
137
|
-
.description("List configured profiles")
|
|
138
|
-
.action(function action(this: Command) {
|
|
139
|
-
const config = readRequiredConfig(filePath);
|
|
140
|
-
const data = Object.entries(config.profiles).map(([name, profile]) =>
|
|
141
|
-
toDisplayProfile(name, profile, config.defaultProfile),
|
|
142
|
-
);
|
|
143
|
-
|
|
144
|
-
if (getGlobalOptions(this).json) {
|
|
145
|
-
emitJson(stdout, "profiles list", data, filePath);
|
|
146
|
-
return;
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
emitProfilesTable(stdout, data);
|
|
150
|
-
});
|
|
151
|
-
|
|
152
|
-
profiles
|
|
153
|
-
.command("get")
|
|
154
|
-
.description("Show a single configured profile")
|
|
155
|
-
.argument("<profile>", "profile name")
|
|
156
|
-
.action(function action(this: Command, profileName: string) {
|
|
157
|
-
const config = readRequiredConfig(filePath);
|
|
158
|
-
const profile = getRequiredProfile(config, profileName);
|
|
159
|
-
const data = toDisplayProfile(profileName, profile, config.defaultProfile);
|
|
160
|
-
|
|
161
|
-
if (getGlobalOptions(this).json) {
|
|
162
|
-
emitJson(stdout, "profiles get", data, filePath);
|
|
163
|
-
return;
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
emitProfilesTable(stdout, [data]);
|
|
167
|
-
});
|
|
168
|
-
|
|
169
|
-
profiles
|
|
170
|
-
.command("use")
|
|
171
|
-
.description("Set the default profile")
|
|
172
|
-
.argument("<profile>", "profile name")
|
|
173
|
-
.action(function action(this: Command, profileName: string) {
|
|
174
|
-
const config = readRequiredConfig(filePath);
|
|
175
|
-
getRequiredProfile(config, profileName);
|
|
176
|
-
|
|
177
|
-
const nextConfig = setDefaultProfile(config, profileName);
|
|
178
|
-
writeConfig(nextConfig, filePath);
|
|
179
|
-
const data = {
|
|
180
|
-
profile: profileName,
|
|
181
|
-
defaultProfile: nextConfig.defaultProfile,
|
|
182
|
-
};
|
|
183
|
-
|
|
184
|
-
if (getGlobalOptions(this).json) {
|
|
185
|
-
emitJson(stdout, "profiles use", data, filePath);
|
|
186
|
-
return;
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
writeLine(stdout, `Using profile "${profileName}".`);
|
|
190
|
-
});
|
|
191
|
-
|
|
192
|
-
profiles
|
|
193
|
-
.command("add")
|
|
194
|
-
.description("Add a profile to the local config")
|
|
195
|
-
.argument("<profile>", "profile name")
|
|
196
|
-
.requiredOption("--api-key <token>", "API key")
|
|
197
|
-
.option("--base-url <url>", "base URL")
|
|
198
|
-
.action(function action(
|
|
199
|
-
this: Command,
|
|
200
|
-
profileName: string,
|
|
201
|
-
commandOptions: { apiKey: string; baseUrl?: string },
|
|
202
|
-
) {
|
|
203
|
-
const config = loadConfigForAdd(filePath);
|
|
204
|
-
|
|
205
|
-
if (config.profiles[profileName]) {
|
|
206
|
-
throw new CliError(
|
|
207
|
-
"configuration_error",
|
|
208
|
-
`Profile "${profileName}" already exists in config.`,
|
|
209
|
-
);
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
const baseUrl = normalizeProfileBaseUrl(commandOptions.baseUrl);
|
|
213
|
-
|
|
214
|
-
let nextConfig = setProfileConfig(config, profileName, {
|
|
215
|
-
apiKey: commandOptions.apiKey,
|
|
216
|
-
baseUrl,
|
|
217
|
-
});
|
|
218
|
-
|
|
219
|
-
if (!nextConfig.defaultProfile) {
|
|
220
|
-
nextConfig = setDefaultProfile(nextConfig, profileName);
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
writeConfig(nextConfig, filePath);
|
|
224
|
-
const data = toDisplayProfile(
|
|
225
|
-
profileName,
|
|
226
|
-
nextConfig.profiles[profileName] ?? {},
|
|
227
|
-
nextConfig.defaultProfile,
|
|
228
|
-
);
|
|
229
|
-
|
|
230
|
-
if (getGlobalOptions(this).json) {
|
|
231
|
-
emitJson(stdout, "profiles add", data, filePath);
|
|
232
|
-
return;
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
writeLine(stdout, `Added profile "${profileName}".`);
|
|
236
|
-
});
|
|
237
|
-
|
|
238
|
-
profiles
|
|
239
|
-
.command("update")
|
|
240
|
-
.description("Update an existing profile")
|
|
241
|
-
.argument("<profile>", "profile name")
|
|
242
|
-
.option("--api-key <token>", "API key")
|
|
243
|
-
.option("--base-url <url>", "base URL")
|
|
244
|
-
.action(function action(
|
|
245
|
-
this: Command,
|
|
246
|
-
profileName: string,
|
|
247
|
-
commandOptions: { apiKey?: string; baseUrl?: string },
|
|
248
|
-
) {
|
|
249
|
-
if (commandOptions.apiKey === undefined && commandOptions.baseUrl === undefined) {
|
|
250
|
-
throw new CliError(
|
|
251
|
-
"configuration_error",
|
|
252
|
-
'Provide at least one of "--api-key" or "--base-url".',
|
|
253
|
-
);
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
const config = readRequiredConfig(filePath);
|
|
257
|
-
getRequiredProfile(config, profileName);
|
|
258
|
-
|
|
259
|
-
const baseUrl = normalizeProfileBaseUrl(commandOptions.baseUrl);
|
|
260
|
-
|
|
261
|
-
const nextConfig = setProfileConfig(config, profileName, {
|
|
262
|
-
apiKey: commandOptions.apiKey,
|
|
263
|
-
baseUrl,
|
|
264
|
-
});
|
|
265
|
-
|
|
266
|
-
writeConfig(nextConfig, filePath);
|
|
267
|
-
const data = toDisplayProfile(
|
|
268
|
-
profileName,
|
|
269
|
-
nextConfig.profiles[profileName] ?? {},
|
|
270
|
-
nextConfig.defaultProfile,
|
|
271
|
-
);
|
|
272
|
-
|
|
273
|
-
if (getGlobalOptions(this).json) {
|
|
274
|
-
emitJson(stdout, "profiles update", data, filePath);
|
|
275
|
-
return;
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
writeLine(stdout, `Updated profile "${profileName}".`);
|
|
279
|
-
});
|
|
280
|
-
|
|
281
|
-
profiles
|
|
282
|
-
.command("remove")
|
|
283
|
-
.description("Remove a profile from the local config")
|
|
284
|
-
.argument("<profile>", "profile name")
|
|
285
|
-
.action(function action(this: Command, profileName: string) {
|
|
286
|
-
const config = readRequiredConfig(filePath);
|
|
287
|
-
getRequiredProfile(config, profileName);
|
|
288
|
-
|
|
289
|
-
const nextConfig = removeProfileConfig(config, profileName);
|
|
290
|
-
writeConfig(nextConfig, filePath);
|
|
291
|
-
const data = {
|
|
292
|
-
profile: profileName,
|
|
293
|
-
defaultProfile: nextConfig.defaultProfile,
|
|
294
|
-
};
|
|
295
|
-
|
|
296
|
-
if (getGlobalOptions(this).json) {
|
|
297
|
-
emitJson(stdout, "profiles remove", data, filePath);
|
|
298
|
-
return;
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
writeLine(stdout, `Removed profile "${profileName}".`);
|
|
302
|
-
});
|
|
303
|
-
}
|