@chalksurf/cli 0.1.0 → 0.2.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 +31 -94
- package/dist/bin/chalksurf.js +84 -10
- package/dist/commands/auth.js +43 -24
- package/dist/commands/exercise.js +428 -0
- package/dist/commands/job.js +20 -10
- package/dist/commands/org.js +20 -11
- package/dist/commands/profile.js +97 -0
- package/dist/commands/sheet.js +287 -130
- package/dist/lib/api-client.js +9 -3
- package/dist/lib/cli-error.js +37 -1
- package/dist/lib/config-store.js +188 -10
- package/dist/lib/import-files.js +120 -0
- package/dist/lib/import-output.js +67 -0
- package/dist/lib/manifest.js +183 -19
- package/dist/lib/output.js +35 -2
- package/dist/lib/prompt-secret.js +32 -0
- package/dist/lib/session.js +1 -1
- package/dist/lib/source-resolver.js +72 -10
- package/dist/lib/translation-languages.js +1 -0
- package/dist/lib/user-jobs.js +16 -1
- package/docs/agents.md +203 -0
- package/docs/examples/exercise-import-manifest.json +13 -0
- package/docs/examples/exercise-solution-import-manifest.json +13 -0
- package/docs/examples/sheet-import-manifest.json +33 -0
- package/docs/exit-codes.md +57 -0
- package/docs/manifest.md +129 -0
- package/docs/manual.md +169 -0
- package/package.json +8 -4
- package/schemas/exercise-import-manifest.schema.json +104 -0
- package/schemas/exercise-solution-import-manifest.schema.json +104 -0
- package/schemas/sheet-import-manifest.schema.json +142 -0
package/README.md
CHANGED
|
@@ -1,135 +1,72 @@
|
|
|
1
1
|
# `@chalksurf/cli`
|
|
2
2
|
|
|
3
|
-
Publishable
|
|
4
|
-
|
|
5
|
-
Current internal release line: `0.1
|
|
6
|
-
|
|
7
|
-
Current milestone scope:
|
|
8
|
-
|
|
9
|
-
- package skeleton and build output
|
|
10
|
-
- `chalksurf --help`
|
|
11
|
-
- `chalksurf --version`
|
|
12
|
-
- `chalksurf auth login --with-token`
|
|
13
|
-
- `chalksurf auth status`
|
|
14
|
-
- `chalksurf auth logout`
|
|
15
|
-
- `chalksurf org list`
|
|
16
|
-
- `chalksurf org use <organization-id>`
|
|
17
|
-
- `chalksurf sheet import [sources...]`
|
|
18
|
-
- `chalksurf job get <job-id>`
|
|
19
|
-
- `chalksurf job wait <job-id> [<job-id>...]`
|
|
20
|
-
- shared output helpers
|
|
21
|
-
- shared HTTP client wrapper
|
|
22
|
-
- secure local config persistence for CLI auth
|
|
23
|
-
- source resolution for local files, directories, and URLs
|
|
24
|
-
- manifest-driven imports and optional job waiting
|
|
3
|
+
Publishable ChalkSurf CLI package.
|
|
4
|
+
|
|
5
|
+
Current internal release line: `0.2.1`. Expect breaking changes while the CLI is still only used internally.
|
|
25
6
|
|
|
26
7
|
## Installation
|
|
27
8
|
|
|
28
9
|
Run the published CLI without a global install:
|
|
29
10
|
|
|
30
11
|
```bash
|
|
31
|
-
npx @chalksurf/cli@0.1
|
|
12
|
+
npx @chalksurf/cli@0.2.1 --help
|
|
32
13
|
```
|
|
33
14
|
|
|
34
15
|
Install it globally when you want a persistent local binary:
|
|
35
16
|
|
|
36
17
|
```bash
|
|
37
|
-
npm install -g @chalksurf/cli@0.1
|
|
18
|
+
npm install -g @chalksurf/cli@0.2.1
|
|
38
19
|
chalksurf --version
|
|
39
20
|
```
|
|
40
21
|
|
|
41
|
-
##
|
|
42
|
-
|
|
43
|
-
Pipe a CLI token into the login command:
|
|
44
|
-
|
|
45
|
-
```bash
|
|
46
|
-
printf '%s' "$CHALKSURF_TOKEN" | chalksurf auth login --with-token --base-url https://api.chalksurf.com
|
|
47
|
-
```
|
|
22
|
+
## Quick Start
|
|
48
23
|
|
|
49
|
-
|
|
24
|
+
Interactive operator flow:
|
|
50
25
|
|
|
51
26
|
```bash
|
|
52
|
-
chalksurf auth
|
|
27
|
+
chalksurf auth login --profile prod-cztamas --base-url https://chalksurf-api.fly.dev
|
|
28
|
+
chalksurf profile use prod-cztamas
|
|
53
29
|
chalksurf org list
|
|
30
|
+
chalksurf sheet import ./fixtures/algebra.pdf --wait
|
|
54
31
|
```
|
|
55
32
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
```bash
|
|
59
|
-
chalksurf org use org_123
|
|
60
|
-
```
|
|
61
|
-
|
|
62
|
-
For headless or CI usage, prefer environment variables:
|
|
63
|
-
|
|
64
|
-
```bash
|
|
65
|
-
export CHALKSURF_BASE_URL=https://api.chalksurf.com
|
|
66
|
-
export CHALKSURF_TOKEN=cs_cli_...
|
|
67
|
-
export CHALKSURF_ORGANIZATION_ID=org_123
|
|
68
|
-
chalksurf auth status --json
|
|
69
|
-
```
|
|
70
|
-
|
|
71
|
-
Use the published package directly in agent or CI runs when you do not want a global install:
|
|
33
|
+
Headless or agent flow:
|
|
72
34
|
|
|
73
35
|
```bash
|
|
74
|
-
CHALKSURF_BASE_URL=https://api.chalksurf.com \
|
|
75
36
|
CHALKSURF_TOKEN=cs_cli_... \
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
37
|
+
printf '%s' "$CHALKSURF_TOKEN" | npx @chalksurf/cli@0.2.1 auth login \
|
|
38
|
+
--profile prod-codex \
|
|
39
|
+
--base-url https://chalksurf-api.fly.dev \
|
|
40
|
+
--with-token
|
|
79
41
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
```bash
|
|
83
|
-
chalksurf sheet import ./fixtures/algebra.pdf
|
|
42
|
+
npx @chalksurf/cli@0.2.1 --profile prod-codex sheet import --manifest - --wait --json < import.json
|
|
84
43
|
```
|
|
85
44
|
|
|
86
|
-
|
|
45
|
+
Sheet import manifests use top-level `sheets[]`, where each sheet has one `targetFolderPath` and one or more ordered `sources[]`. See [the canonical example](./docs/examples/sheet-import-manifest.json).
|
|
87
46
|
|
|
88
|
-
|
|
89
|
-
chalksurf sheet import https://example.com/trig.docx \
|
|
90
|
-
--relative-path Imported/trig.docx \
|
|
91
|
-
--organization org_123
|
|
92
|
-
```
|
|
93
|
-
|
|
94
|
-
Import from a manifest and wait for the jobs to finish:
|
|
95
|
-
|
|
96
|
-
```bash
|
|
97
|
-
cat import.json | chalksurf sheet import --manifest - --wait --json
|
|
98
|
-
```
|
|
47
|
+
## Docs
|
|
99
48
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
49
|
+
- [Manual operator guide](./docs/manual.md)
|
|
50
|
+
- [Agent and Codex guide](./docs/agents.md)
|
|
51
|
+
- [Manifest reference](./docs/manifest.md)
|
|
52
|
+
- [Exit codes and JSON errors](./docs/exit-codes.md)
|
|
53
|
+
- [Sheet import schema](./schemas/sheet-import-manifest.schema.json)
|
|
54
|
+
- [Exercise import schema](./schemas/exercise-import-manifest.schema.json)
|
|
55
|
+
- [Exercise solution import schema](./schemas/exercise-solution-import-manifest.schema.json)
|
|
106
56
|
|
|
107
57
|
## Local And Staging Testing
|
|
108
58
|
|
|
109
|
-
Use separate
|
|
59
|
+
Use separate profiles so local, staging, production, human, and agent tokens do not overwrite each other:
|
|
110
60
|
|
|
111
61
|
```bash
|
|
112
|
-
npm run cli-dev -- --
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
Run the CLI directly from source during local development:
|
|
116
|
-
|
|
117
|
-
```bash
|
|
118
|
-
export CHALKSURF_CONFIG_PATH=/tmp/chalksurf-local.json
|
|
119
|
-
printf '%s' "$LOCAL_CLI_TOKEN" | npm run cli-dev -- auth login --with-token --base-url http://localhost:8080
|
|
62
|
+
npm run cli-dev -- auth login --profile dev-cztamas --base-url http://localhost:8080
|
|
63
|
+
npm run cli-dev -- profile use dev-cztamas
|
|
120
64
|
npm run cli-dev -- auth status --json
|
|
121
|
-
npm run cli-dev -- org list --json
|
|
122
65
|
npm run cli-dev -- sheet import ./fixtures/algebra.pdf --wait --json
|
|
123
|
-
npm run cli-dev -- job get job_123 --json
|
|
124
66
|
```
|
|
125
67
|
|
|
126
68
|
```bash
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
npm run cli-dev --
|
|
130
|
-
npm run cli-dev -- org list --json
|
|
131
|
-
npm run cli-dev -- sheet import https://example.com/worksheet.docx --relative-path Imported/worksheet.docx --json
|
|
132
|
-
npm run cli-dev -- job wait job_123 --json
|
|
69
|
+
npm run cli-dev -- auth login --profile staging-codex --base-url https://chalksurf-api-staging.fly.dev
|
|
70
|
+
npm run cli-dev -- --profile staging-codex auth status --json
|
|
71
|
+
npm run cli-dev -- --profile staging-codex sheet import https://example.com/worksheet.docx --single-sheet --target-folder Imported --json
|
|
133
72
|
```
|
|
134
|
-
|
|
135
|
-
For short-lived agent runs, skip local persistence and inject credentials through environment variables instead.
|
package/dist/bin/chalksurf.js
CHANGED
|
@@ -4,21 +4,24 @@ import { fileURLToPath } from 'node:url';
|
|
|
4
4
|
import { hideBin } from 'yargs/helpers';
|
|
5
5
|
import yargs from 'yargs/yargs';
|
|
6
6
|
import { registerAuthCommands } from '../commands/auth.js';
|
|
7
|
+
import { registerExerciseCommands } from '../commands/exercise.js';
|
|
7
8
|
import { registerJobCommands } from '../commands/job.js';
|
|
8
9
|
import { registerOrgCommands } from '../commands/org.js';
|
|
10
|
+
import { registerProfileCommands } from '../commands/profile.js';
|
|
9
11
|
import { registerSheetCommands } from '../commands/sheet.js';
|
|
10
|
-
import { CliCommandError } from '../lib/cli-error.js';
|
|
12
|
+
import { CliCommandError, createSerializableCliError, serializeCliError } from '../lib/cli-error.js';
|
|
11
13
|
import { createConfigStore } from '../lib/config-store.js';
|
|
12
14
|
import { createOutput } from '../lib/output.js';
|
|
15
|
+
import { createPromptSecret } from '../lib/prompt-secret.js';
|
|
13
16
|
const packageJson = JSON.parse(readFileSync(new URL('../../package.json', import.meta.url), 'utf8'));
|
|
14
|
-
const createCli = ({ cwd, configPath, env,
|
|
17
|
+
const createCli = ({ cwd, configPath, env, now, output, sleep, stdin, promptSecret, }) => {
|
|
15
18
|
const commandContext = {
|
|
16
19
|
cwd,
|
|
17
20
|
configStore: createConfigStore({ configPath, env }),
|
|
18
21
|
env,
|
|
19
|
-
fetchImpl,
|
|
20
22
|
now,
|
|
21
23
|
output,
|
|
24
|
+
promptSecret,
|
|
22
25
|
sleep,
|
|
23
26
|
stdin,
|
|
24
27
|
};
|
|
@@ -40,6 +43,11 @@ const createCli = ({ cwd, configPath, env, fetchImpl, now, output, sleep, stdin,
|
|
|
40
43
|
type: 'string',
|
|
41
44
|
global: true,
|
|
42
45
|
describe: 'Organization ID to use for this command',
|
|
46
|
+
})
|
|
47
|
+
.option('profile', {
|
|
48
|
+
type: 'string',
|
|
49
|
+
global: true,
|
|
50
|
+
describe: 'CLI profile to use for this command',
|
|
43
51
|
})
|
|
44
52
|
.option('version', {
|
|
45
53
|
type: 'boolean',
|
|
@@ -48,37 +56,84 @@ const createCli = ({ cwd, configPath, env, fetchImpl, now, output, sleep, stdin,
|
|
|
48
56
|
})
|
|
49
57
|
.command('auth <subcommand>', 'Authentication commands', (authYargs) => registerAuthCommands(authYargs, commandContext), () => { })
|
|
50
58
|
.command('org <subcommand>', 'Organization commands', (orgYargs) => registerOrgCommands(orgYargs, commandContext), () => { })
|
|
59
|
+
.command('profile <subcommand>', 'Profile commands', (profileYargs) => registerProfileCommands(profileYargs, commandContext), () => { })
|
|
60
|
+
.command('exercise <subcommand>', 'Exercise commands', (exerciseYargs) => registerExerciseCommands(exerciseYargs, commandContext), () => { })
|
|
51
61
|
.command('sheet <subcommand>', 'Exercise sheet commands', (sheetYargs) => registerSheetCommands(sheetYargs, commandContext), () => { })
|
|
52
62
|
.command('job <subcommand>', 'Job commands', (jobYargs) => registerJobCommands(jobYargs, commandContext), () => { })
|
|
53
63
|
.help()
|
|
54
64
|
.strict()
|
|
55
65
|
.exitProcess(false);
|
|
56
66
|
};
|
|
67
|
+
const parseCliWithCapturedOutput = async ({ cli, argv, stdout, }) => {
|
|
68
|
+
await new Promise((resolve, reject) => {
|
|
69
|
+
cli.parse(argv, (error, _parsedArgv, output) => {
|
|
70
|
+
if (output) {
|
|
71
|
+
stdout.write(output);
|
|
72
|
+
}
|
|
73
|
+
if (error) {
|
|
74
|
+
reject(error);
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
resolve();
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
};
|
|
57
81
|
const hasFlag = (argv, flags) => {
|
|
58
82
|
return argv.some((argument) => flags.includes(argument));
|
|
59
83
|
};
|
|
60
|
-
|
|
84
|
+
const topLevelCommands = new Set(['auth', 'org', 'profile', 'exercise', 'sheet', 'job']);
|
|
85
|
+
const hasTopLevelCommand = (argv) => {
|
|
86
|
+
return argv.some((argument) => topLevelCommands.has(argument));
|
|
87
|
+
};
|
|
88
|
+
const resolveCommandName = (argv) => {
|
|
89
|
+
for (let index = 0; index < argv.length; index += 1) {
|
|
90
|
+
const argument = argv[index];
|
|
91
|
+
if (!topLevelCommands.has(argument)) {
|
|
92
|
+
continue;
|
|
93
|
+
}
|
|
94
|
+
const subcommand = argv
|
|
95
|
+
.slice(index + 1)
|
|
96
|
+
.find((candidate) => candidate.length > 0 && !candidate.startsWith('-') && !candidate.startsWith('http'));
|
|
97
|
+
return subcommand ? `${argument} ${subcommand}` : argument;
|
|
98
|
+
}
|
|
99
|
+
if (hasFlag(argv, ['--version', '-v'])) {
|
|
100
|
+
return 'chalksurf version';
|
|
101
|
+
}
|
|
102
|
+
return 'chalksurf';
|
|
103
|
+
};
|
|
104
|
+
export const runCli = async ({ argv, cwd = process.cwd(), configPath, env = process.env, nowImpl = Date.now, promptSecretImpl = createPromptSecret(), sleepImpl = (milliseconds) => new Promise((resolve) => setTimeout(resolve, milliseconds)), stdin = process.stdin, stdout = process.stdout, stderr = process.stderr, }) => {
|
|
61
105
|
const output = createOutput({
|
|
62
106
|
json: hasFlag(argv, ['--json']),
|
|
63
107
|
stdout,
|
|
64
108
|
stderr,
|
|
65
109
|
});
|
|
110
|
+
const commandName = resolveCommandName(argv);
|
|
66
111
|
const cli = createCli({
|
|
67
112
|
cwd,
|
|
68
113
|
configPath,
|
|
69
114
|
env,
|
|
70
|
-
fetchImpl,
|
|
71
115
|
now: nowImpl,
|
|
72
116
|
output,
|
|
117
|
+
promptSecret: promptSecretImpl,
|
|
73
118
|
sleep: sleepImpl,
|
|
74
119
|
stdin,
|
|
75
120
|
});
|
|
76
|
-
if (argv.length === 0 || hasFlag(argv, ['--help', '-h'])) {
|
|
121
|
+
if (argv.length === 0 || (hasFlag(argv, ['--help', '-h']) && !hasTopLevelCommand(argv))) {
|
|
77
122
|
stdout.write(await cli.getHelp());
|
|
78
123
|
return 0;
|
|
79
124
|
}
|
|
80
|
-
if (hasFlag(argv, ['--
|
|
81
|
-
|
|
125
|
+
if (hasFlag(argv, ['--help', '-h'])) {
|
|
126
|
+
await parseCliWithCapturedOutput({
|
|
127
|
+
cli,
|
|
128
|
+
argv,
|
|
129
|
+
stdout,
|
|
130
|
+
});
|
|
131
|
+
return 0;
|
|
132
|
+
}
|
|
133
|
+
if (hasFlag(argv, ['--version', '-v']) && !hasTopLevelCommand(argv)) {
|
|
134
|
+
output.print({ version: packageJson.version }, packageJson.version, {
|
|
135
|
+
command: commandName,
|
|
136
|
+
});
|
|
82
137
|
return 0;
|
|
83
138
|
}
|
|
84
139
|
try {
|
|
@@ -88,12 +143,31 @@ export const runCli = async ({ argv, cwd = process.cwd(), configPath, env = proc
|
|
|
88
143
|
catch (error) {
|
|
89
144
|
if (error instanceof CliCommandError) {
|
|
90
145
|
if (error.shouldReport && error.message) {
|
|
91
|
-
output.
|
|
146
|
+
if (output.json) {
|
|
147
|
+
output.printError({
|
|
148
|
+
command: commandName,
|
|
149
|
+
error: serializeCliError(error),
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
else {
|
|
153
|
+
output.error(error.message);
|
|
154
|
+
}
|
|
92
155
|
}
|
|
93
156
|
return error.exitCode;
|
|
94
157
|
}
|
|
95
158
|
const message = error instanceof Error ? error.message : 'Unknown CLI error';
|
|
96
|
-
output.
|
|
159
|
+
if (output.json) {
|
|
160
|
+
output.printError({
|
|
161
|
+
command: commandName,
|
|
162
|
+
error: createSerializableCliError({
|
|
163
|
+
exitCode: 1,
|
|
164
|
+
message,
|
|
165
|
+
}),
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
else {
|
|
169
|
+
output.error(message);
|
|
170
|
+
}
|
|
97
171
|
return 1;
|
|
98
172
|
}
|
|
99
173
|
};
|
package/dist/commands/auth.js
CHANGED
|
@@ -31,30 +31,31 @@ const formatOrganizationSummary = (organization) => {
|
|
|
31
31
|
};
|
|
32
32
|
export const registerAuthCommands = (authYargs, context) => {
|
|
33
33
|
return authYargs
|
|
34
|
-
.command('login', 'Read a CLI token from stdin
|
|
35
|
-
return loginYargs
|
|
34
|
+
.command('login', 'Read a CLI token from stdin or prompt for it interactively', (loginYargs) => {
|
|
35
|
+
return loginYargs
|
|
36
|
+
.option('with-token', {
|
|
36
37
|
type: 'boolean',
|
|
37
|
-
|
|
38
|
-
describe: 'Read the token from stdin',
|
|
39
|
-
})
|
|
38
|
+
default: false,
|
|
39
|
+
describe: 'Read the token from stdin when piping input',
|
|
40
|
+
})
|
|
41
|
+
.example('chalksurf auth login --profile prod-cztamas --base-url https://chalksurf-api.fly.dev', 'Prompt for a CLI token and store it in the prod-cztamas profile')
|
|
42
|
+
.example(`printf '%s' "$CHALKSURF_TOKEN" | chalksurf auth login --profile prod-codex --base-url https://chalksurf-api.fly.dev`, 'Read a CLI token from stdin into an explicit profile');
|
|
40
43
|
}, async (argv) => {
|
|
41
|
-
const config = await context.configStore.
|
|
44
|
+
const config = await context.configStore.loadProfile({ profileName: argv.profile });
|
|
42
45
|
const resolvedBaseUrl = requireResolvedBaseUrl({
|
|
43
46
|
flagValue: argv.baseUrl,
|
|
44
47
|
env: context.env,
|
|
45
48
|
config,
|
|
46
49
|
});
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
const token = await readTokenFromStdin(context.stdin);
|
|
50
|
+
const token = (isInteractiveStdin(context.stdin)
|
|
51
|
+
? await context.promptSecret('CLI token: ')
|
|
52
|
+
: await readTokenFromStdin(context.stdin)).trim();
|
|
51
53
|
if (!token) {
|
|
52
|
-
throw new CliCommandError('No token was provided
|
|
54
|
+
throw new CliCommandError('No token was provided.', 2);
|
|
53
55
|
}
|
|
54
56
|
const apiClient = createApiClient({
|
|
55
57
|
baseUrl: resolvedBaseUrl.value,
|
|
56
58
|
token,
|
|
57
|
-
fetchImpl: context.fetchImpl,
|
|
58
59
|
});
|
|
59
60
|
let profile;
|
|
60
61
|
try {
|
|
@@ -69,7 +70,7 @@ export const registerAuthCommands = (authYargs, context) => {
|
|
|
69
70
|
config,
|
|
70
71
|
profile,
|
|
71
72
|
});
|
|
72
|
-
await context.configStore.update((currentConfig) => ({
|
|
73
|
+
await context.configStore.update({ profileName: argv.profile }, (currentConfig) => ({
|
|
73
74
|
...currentConfig,
|
|
74
75
|
token,
|
|
75
76
|
baseUrl: resolvedBaseUrl.value,
|
|
@@ -83,16 +84,28 @@ export const registerAuthCommands = (authYargs, context) => {
|
|
|
83
84
|
baseUrl: resolvedBaseUrl.value,
|
|
84
85
|
baseUrlSource: resolvedBaseUrl.source,
|
|
85
86
|
organization: serializeOrganization(resolvedOrganization.organization),
|
|
87
|
+
profile: config.profileName,
|
|
88
|
+
profileSource: config.profileSource,
|
|
86
89
|
user: {
|
|
87
90
|
email: profile.email,
|
|
88
91
|
id: profile.id,
|
|
89
92
|
name: profile.name,
|
|
90
93
|
},
|
|
91
|
-
|
|
92
|
-
|
|
94
|
+
}, (result) => `Logged in as ${formatUserIdentity(result.user)}.\n${formatOrganizationSummary(result.organization)}`, {
|
|
95
|
+
command: 'auth login',
|
|
96
|
+
});
|
|
93
97
|
})
|
|
94
|
-
.command('status', 'Show the current authentication and organization state', () =>
|
|
95
|
-
|
|
98
|
+
.command('status', 'Show the current authentication and organization state', (statusYargs) => statusYargs
|
|
99
|
+
.example('chalksurf auth status', 'Show the current authenticated user and default organization')
|
|
100
|
+
.example('chalksurf --profile prod-codex auth status --json', 'Inspect a specific profile in machine-readable mode')
|
|
101
|
+
.epilogue([
|
|
102
|
+
'Resolution order:',
|
|
103
|
+
' profile: --profile, then CHALKSURF_PROFILE, then stored default profile',
|
|
104
|
+
' base URL: --base-url, then CHALKSURF_BASE_URL, then active profile',
|
|
105
|
+
' token: CHALKSURF_TOKEN, then active profile',
|
|
106
|
+
' organization: --organization, then CHALKSURF_ORGANIZATION_ID, then active profile',
|
|
107
|
+
].join('\n')), async (argv) => {
|
|
108
|
+
const config = await context.configStore.loadProfile({ profileName: argv.profile });
|
|
96
109
|
const resolvedBaseUrl = requireResolvedBaseUrl({
|
|
97
110
|
flagValue: argv.baseUrl,
|
|
98
111
|
env: context.env,
|
|
@@ -105,7 +118,6 @@ export const registerAuthCommands = (authYargs, context) => {
|
|
|
105
118
|
const apiClient = createApiClient({
|
|
106
119
|
baseUrl: resolvedBaseUrl.value,
|
|
107
120
|
token: resolvedToken.value,
|
|
108
|
-
fetchImpl: context.fetchImpl,
|
|
109
121
|
});
|
|
110
122
|
let profile;
|
|
111
123
|
try {
|
|
@@ -129,26 +141,33 @@ export const registerAuthCommands = (authYargs, context) => {
|
|
|
129
141
|
baseUrlSource: resolvedBaseUrl.source,
|
|
130
142
|
organization: serializeOrganization(resolvedOrganization.organization),
|
|
131
143
|
organizationSource: resolvedOrganization.source,
|
|
144
|
+
profile: config.profileName,
|
|
145
|
+
profileSource: config.profileSource,
|
|
132
146
|
tokenSource: resolvedToken.source,
|
|
133
147
|
user: {
|
|
134
148
|
email: profile.email,
|
|
135
149
|
id: profile.id,
|
|
136
150
|
name: profile.name,
|
|
137
151
|
},
|
|
138
|
-
|
|
139
|
-
|
|
152
|
+
}, (result) => `Authenticated as ${formatUserIdentity(result.user)}.\n${formatOrganizationSummary(result.organization)}`, {
|
|
153
|
+
command: 'auth status',
|
|
154
|
+
});
|
|
140
155
|
})
|
|
141
|
-
.command('logout', 'Remove the locally stored CLI token', () =>
|
|
142
|
-
const config = await context.configStore.
|
|
156
|
+
.command('logout', 'Remove the locally stored CLI token', (logoutYargs) => logoutYargs.example('chalksurf auth logout', 'Remove the stored CLI token from local config'), async (argv) => {
|
|
157
|
+
const config = await context.configStore.loadProfile({ profileName: argv.profile });
|
|
143
158
|
const hadStoredToken = Boolean(config.token);
|
|
144
|
-
await context.configStore.update((currentConfig) => ({
|
|
159
|
+
await context.configStore.update({ profileName: argv.profile }, (currentConfig) => ({
|
|
145
160
|
...currentConfig,
|
|
146
161
|
token: undefined,
|
|
147
162
|
}));
|
|
148
163
|
context.output.print({
|
|
149
164
|
clearedStoredToken: hadStoredToken,
|
|
150
165
|
loggedOut: true,
|
|
151
|
-
|
|
166
|
+
profile: config.profileName,
|
|
167
|
+
profileSource: config.profileSource,
|
|
168
|
+
}, hadStoredToken ? 'Stored CLI token removed.' : 'No stored CLI token was present.', {
|
|
169
|
+
command: 'auth logout',
|
|
170
|
+
});
|
|
152
171
|
})
|
|
153
172
|
.demandCommand(1)
|
|
154
173
|
.strict();
|