seamless-cli 0.5.1 → 0.6.0
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 +133 -0
- package/dist/commands/adminShared.js +23 -0
- package/dist/commands/adminShared.js.map +1 -0
- package/dist/commands/config.js +187 -0
- package/dist/commands/config.js.map +1 -0
- package/dist/commands/help.js +98 -0
- package/dist/commands/help.js.map +1 -1
- package/dist/commands/login.js +86 -0
- package/dist/commands/login.js.map +1 -0
- package/dist/commands/logout.js +43 -0
- package/dist/commands/logout.js.map +1 -0
- package/dist/commands/org.js +249 -0
- package/dist/commands/org.js.map +1 -0
- package/dist/commands/profile.js +150 -0
- package/dist/commands/profile.js.map +1 -0
- package/dist/commands/sessions.js +112 -0
- package/dist/commands/sessions.js.map +1 -0
- package/dist/commands/users.js +147 -0
- package/dist/commands/users.js.map +1 -0
- package/dist/commands/verify.js +133 -9
- package/dist/commands/verify.js.map +1 -1
- package/dist/commands/whoami.js +29 -0
- package/dist/commands/whoami.js.map +1 -0
- package/dist/core/admin.js +142 -0
- package/dist/core/admin.js.map +1 -0
- package/dist/core/args.js +19 -0
- package/dist/core/args.js.map +1 -0
- package/dist/core/authClient.js +113 -0
- package/dist/core/authClient.js.map +1 -0
- package/dist/core/config.js +146 -0
- package/dist/core/config.js.map +1 -0
- package/dist/core/http.js +34 -0
- package/dist/core/http.js.map +1 -0
- package/dist/core/images.js +1 -1
- package/dist/core/keychain.js +112 -0
- package/dist/core/keychain.js.map +1 -0
- package/dist/core/loginFlow.js +143 -0
- package/dist/core/loginFlow.js.map +1 -0
- package/dist/core/session.js +30 -0
- package/dist/core/session.js.map +1 -0
- package/dist/core/sessions.js +41 -0
- package/dist/core/sessions.js.map +1 -0
- package/dist/core/systemConfig.js +125 -0
- package/dist/core/systemConfig.js.map +1 -0
- package/dist/index.js +40 -0
- package/dist/index.js.map +1 -1
- package/package.json +8 -2
package/README.md
CHANGED
|
@@ -120,6 +120,139 @@ npm run dev
|
|
|
120
120
|
|
|
121
121
|
---
|
|
122
122
|
|
|
123
|
+
## Authenticating against an instance
|
|
124
|
+
|
|
125
|
+
Beyond scaffolding, the CLI can log in to a Seamless Auth instance (self-hosted, a managed
|
|
126
|
+
tenant, or local dev) and call its authenticated and admin endpoints from the terminal. It talks
|
|
127
|
+
to the instance directly over Bearer and JSON, so no server or contract changes are required.
|
|
128
|
+
|
|
129
|
+
### Profiles
|
|
130
|
+
|
|
131
|
+
The CLI targets instances through named profiles stored at `~/.config/seamless/config.json`
|
|
132
|
+
(respecting `XDG_CONFIG_HOME`). Profiles hold no secrets; tokens live in the OS keychain (see
|
|
133
|
+
below). Pick the active profile per command with `--profile <name>` or the `SEAMLESS_PROFILE`
|
|
134
|
+
environment variable, otherwise the `default` profile is used.
|
|
135
|
+
|
|
136
|
+
```bash
|
|
137
|
+
# Add a profile (prompts if you omit the flags)
|
|
138
|
+
seamless profile add prod --instance-url https://auth.example.com
|
|
139
|
+
seamless profile add local --instance-url http://localhost:5312
|
|
140
|
+
|
|
141
|
+
seamless profile list # active profile is marked with *
|
|
142
|
+
seamless profile use local # switch the active profile
|
|
143
|
+
seamless profile remove local # delete a profile (also clears its keychain tokens)
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
`instanceUrl` is normalized: the trailing slash is stripped and `https` is required for any host
|
|
147
|
+
other than `localhost`, `127.0.0.1`, or `::1`.
|
|
148
|
+
|
|
149
|
+
### Logging in
|
|
150
|
+
|
|
151
|
+
Login uses email OTP: you paste the code from your inbox, so nothing needs to be delivered to the
|
|
152
|
+
CLI and no service token is required.
|
|
153
|
+
|
|
154
|
+
```bash
|
|
155
|
+
seamless login # prompts for the identifier, then the code
|
|
156
|
+
seamless login you@example.com # identifier as an argument
|
|
157
|
+
seamless login --identifier you@example.com --profile prod
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
The command honors the instance's advertised login methods, caps local retries so it does not trip
|
|
161
|
+
the OTP rate limiter, and refreshes the code automatically if the five minute window lapses.
|
|
162
|
+
|
|
163
|
+
### Identity and sessions
|
|
164
|
+
|
|
165
|
+
```bash
|
|
166
|
+
seamless whoami # sub, email, roles, active profile, and instance URL
|
|
167
|
+
seamless logout # end the current session and clear local tokens
|
|
168
|
+
seamless logout --all # revoke every session for the user, then clear local tokens
|
|
169
|
+
|
|
170
|
+
seamless sessions # list active sessions (current one marked)
|
|
171
|
+
seamless sessions revoke <id> # revoke one session (confirms if it is the current one)
|
|
172
|
+
seamless sessions revoke --all # revoke every session (confirms, then clears local tokens)
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### Configuration as code
|
|
176
|
+
|
|
177
|
+
Read and write the instance system configuration (requires an admin role). This turns the
|
|
178
|
+
dashboard's config panel into something you can version, diff, and apply in CI.
|
|
179
|
+
|
|
180
|
+
```bash
|
|
181
|
+
seamless config get # print the whole config
|
|
182
|
+
seamless config get access_token_ttl # print a single key
|
|
183
|
+
seamless config get --json > config.json # capture as JSON
|
|
184
|
+
|
|
185
|
+
# Values are parsed as JSON, falling back to a string, so every shape works:
|
|
186
|
+
seamless config set access_token_ttl 15m
|
|
187
|
+
seamless config set rate_limit 250
|
|
188
|
+
seamless config set passkey_login_fallback_enabled false
|
|
189
|
+
seamless config set login_methods '["email_otp","passkey"]'
|
|
190
|
+
|
|
191
|
+
seamless config roles # list the instance's roles
|
|
192
|
+
|
|
193
|
+
seamless config diff config.json # show how a local file differs from the instance
|
|
194
|
+
seamless config apply config.json --dry-run # preview the delta
|
|
195
|
+
seamless config apply config.json # apply after a confirmation prompt
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
`apply` sends only the changed keys and ignores read-only or unknown keys, so a full config
|
|
199
|
+
captured with `config get --json` can be edited and applied directly. Token TTLs, origins, login
|
|
200
|
+
methods, and the WebAuthn RP id are all readable and writable.
|
|
201
|
+
|
|
202
|
+
### Admin: users and organizations
|
|
203
|
+
|
|
204
|
+
Manage users and organizations from the terminal (requires an admin role).
|
|
205
|
+
|
|
206
|
+
```bash
|
|
207
|
+
seamless users list --limit 50 --offset 0
|
|
208
|
+
seamless users delete <id> # confirms first
|
|
209
|
+
seamless users credentials <id> # registered credentials for a user
|
|
210
|
+
seamless users prepare-device-replacement <id> # admin-assisted recovery
|
|
211
|
+
|
|
212
|
+
seamless org list
|
|
213
|
+
seamless org create "Acme Inc" --slug acme
|
|
214
|
+
seamless org get <id>
|
|
215
|
+
seamless org update <id> --name "Acme" --slug acme
|
|
216
|
+
|
|
217
|
+
seamless org members list <orgId>
|
|
218
|
+
seamless org members add <orgId> --email person@example.com --roles member,billing
|
|
219
|
+
seamless org members update <orgId> <userId> --roles admin
|
|
220
|
+
seamless org members remove <orgId> <userId>
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
A non-admin user receives a clear permission error rather than a stack trace.
|
|
224
|
+
|
|
225
|
+
### Token storage and the keychain
|
|
226
|
+
|
|
227
|
+
The refresh token is the durable secret, so sessions are stored in the operating system keychain,
|
|
228
|
+
never in a plaintext file:
|
|
229
|
+
|
|
230
|
+
- macOS: Keychain
|
|
231
|
+
- Windows: Credential Manager
|
|
232
|
+
- Linux: Secret Service (libsecret, for example GNOME Keyring or KWallet)
|
|
233
|
+
|
|
234
|
+
Tokens are keyed per profile (by name and instance URL) so multiple instances never collide, and
|
|
235
|
+
they are removed when you log out or remove the profile. Access tokens are refreshed transparently:
|
|
236
|
+
on a `401` the CLI rotates the pair via `/refresh`, stores the new tokens, and retries once. A
|
|
237
|
+
rotated or reused refresh token clears the local session and prompts a fresh login.
|
|
238
|
+
|
|
239
|
+
### Headless and CI
|
|
240
|
+
|
|
241
|
+
When no OS keychain is available (for example a headless CI runner), the CLI does not fall back to
|
|
242
|
+
a plaintext file. Instead, set `SEAMLESS_REFRESH_TOKEN` to a valid refresh token and the CLI will
|
|
243
|
+
use it to obtain an access token for the run:
|
|
244
|
+
|
|
245
|
+
```bash
|
|
246
|
+
export SEAMLESS_PROFILE=prod
|
|
247
|
+
export SEAMLESS_REFRESH_TOKEN=<refresh-token>
|
|
248
|
+
seamless whoami
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
Because `/refresh` rotates the refresh token on every call, this path is best for a single
|
|
252
|
+
invocation; the rotated token is held only in memory for that process.
|
|
253
|
+
|
|
254
|
+
---
|
|
255
|
+
|
|
123
256
|
## What is configured for you
|
|
124
257
|
|
|
125
258
|
Seamless CLI handles the parts that are usually difficult to get right:
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import kleur from "kleur";
|
|
2
|
+
import { ReauthRequiredError } from "../core/authClient.js";
|
|
3
|
+
import { AdminApiError, PermissionError } from "../core/admin.js";
|
|
4
|
+
export function reportAdminError(err) {
|
|
5
|
+
if (err instanceof ReauthRequiredError) {
|
|
6
|
+
console.log(kleur.yellow(err.message));
|
|
7
|
+
process.exit(1);
|
|
8
|
+
}
|
|
9
|
+
if (err instanceof PermissionError || err instanceof AdminApiError) {
|
|
10
|
+
console.error(kleur.red(err.message));
|
|
11
|
+
process.exit(1);
|
|
12
|
+
}
|
|
13
|
+
throw err;
|
|
14
|
+
}
|
|
15
|
+
export function parseList(value) {
|
|
16
|
+
if (value === undefined)
|
|
17
|
+
return undefined;
|
|
18
|
+
return value
|
|
19
|
+
.split(",")
|
|
20
|
+
.map((item) => item.trim())
|
|
21
|
+
.filter((item) => item.length > 0);
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=adminShared.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adminShared.js","sourceRoot":"","sources":["../../src/commands/adminShared.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAElE,MAAM,UAAU,gBAAgB,CAAC,GAAY;IAC3C,IAAI,GAAG,YAAY,mBAAmB,EAAE,CAAC;QACvC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC;QACvC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IACD,IAAI,GAAG,YAAY,eAAe,IAAI,GAAG,YAAY,aAAa,EAAE,CAAC;QACnE,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC;QACtC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IACD,MAAM,GAAG,CAAC;AACZ,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,KAAc;IACtC,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IAC1C,OAAO,KAAK;SACT,KAAK,CAAC,GAAG,CAAC;SACV,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;SAC1B,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;AACvC,CAAC"}
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
import { confirm, isCancel } from "@clack/prompts";
|
|
3
|
+
import kleur from "kleur";
|
|
4
|
+
import { extractFlag } from "../core/args.js";
|
|
5
|
+
import { createAuthClient, ReauthRequiredError } from "../core/authClient.js";
|
|
6
|
+
import { ConfigApiError, diffConfig, filterWritable, getRoles, getSystemConfig, parseValue, patchSystemConfig, PermissionError, } from "../core/systemConfig.js";
|
|
7
|
+
export async function runConfig(args) {
|
|
8
|
+
const sub = args[0];
|
|
9
|
+
const { value: profileFlag, rest } = extractFlag(args.slice(1), "profile");
|
|
10
|
+
try {
|
|
11
|
+
const client = await createAuthClient({ profileFlag });
|
|
12
|
+
switch (sub) {
|
|
13
|
+
case "get":
|
|
14
|
+
await configGet(client, rest);
|
|
15
|
+
return;
|
|
16
|
+
case "set":
|
|
17
|
+
await configSet(client, rest);
|
|
18
|
+
return;
|
|
19
|
+
case "roles":
|
|
20
|
+
await configRoles(client, rest);
|
|
21
|
+
return;
|
|
22
|
+
case "diff":
|
|
23
|
+
await configDiff(client, rest);
|
|
24
|
+
return;
|
|
25
|
+
case "apply":
|
|
26
|
+
await configApply(client, rest);
|
|
27
|
+
return;
|
|
28
|
+
default:
|
|
29
|
+
console.error(kleur.red(`Unknown config subcommand: ${sub ?? "(none)"}`));
|
|
30
|
+
console.log("Usage: seamless config <get|set|roles|diff|apply>");
|
|
31
|
+
process.exit(1);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
catch (err) {
|
|
35
|
+
if (err instanceof ReauthRequiredError) {
|
|
36
|
+
console.log(kleur.yellow(err.message));
|
|
37
|
+
process.exit(1);
|
|
38
|
+
}
|
|
39
|
+
if (err instanceof PermissionError || err instanceof ConfigApiError) {
|
|
40
|
+
console.error(kleur.red(err.message));
|
|
41
|
+
process.exit(1);
|
|
42
|
+
}
|
|
43
|
+
throw err;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
async function configGet(client, rest) {
|
|
47
|
+
const json = rest.includes("--json");
|
|
48
|
+
const key = rest.find((arg) => !arg.startsWith("--"));
|
|
49
|
+
const config = await getSystemConfig(client);
|
|
50
|
+
if (key) {
|
|
51
|
+
if (!(key in config)) {
|
|
52
|
+
console.error(kleur.red(`No such config key: ${key}`));
|
|
53
|
+
process.exit(1);
|
|
54
|
+
}
|
|
55
|
+
const value = config[key];
|
|
56
|
+
console.log(json
|
|
57
|
+
? JSON.stringify(value, null, 2)
|
|
58
|
+
: typeof value === "string"
|
|
59
|
+
? value
|
|
60
|
+
: JSON.stringify(value, null, 2));
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
if (json) {
|
|
64
|
+
console.log(JSON.stringify(config, null, 2));
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
printConfig(config);
|
|
68
|
+
}
|
|
69
|
+
async function configSet(client, rest) {
|
|
70
|
+
const positional = rest.filter((arg) => !arg.startsWith("--"));
|
|
71
|
+
const [key, ...valueParts] = positional;
|
|
72
|
+
if (!key || valueParts.length === 0) {
|
|
73
|
+
console.error(kleur.red("Usage: seamless config set <key> <value>"));
|
|
74
|
+
process.exit(1);
|
|
75
|
+
}
|
|
76
|
+
const value = parseValue(valueParts.join(" "));
|
|
77
|
+
const result = await patchSystemConfig(client, { [key]: value });
|
|
78
|
+
if (result.updatedKeys.length) {
|
|
79
|
+
console.log(kleur.green(`Updated: ${result.updatedKeys.join(", ")}`));
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
console.log(kleur.dim("No changes."));
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
async function configRoles(client, rest) {
|
|
86
|
+
const json = rest.includes("--json");
|
|
87
|
+
const roles = await getRoles(client);
|
|
88
|
+
if (json) {
|
|
89
|
+
console.log(JSON.stringify(roles, null, 2));
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
if (roles.length === 0) {
|
|
93
|
+
console.log(kleur.dim("No roles."));
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
for (const role of roles) {
|
|
97
|
+
console.log(" " + role);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
async function configDiff(client, rest) {
|
|
101
|
+
const file = rest.find((arg) => !arg.startsWith("--"));
|
|
102
|
+
if (!file) {
|
|
103
|
+
console.error(kleur.red("Usage: seamless config diff <file>"));
|
|
104
|
+
process.exit(1);
|
|
105
|
+
}
|
|
106
|
+
const local = readConfigFile(file);
|
|
107
|
+
const remote = await getSystemConfig(client);
|
|
108
|
+
const changes = diffConfig(local, remote);
|
|
109
|
+
if (changes.length === 0) {
|
|
110
|
+
console.log(kleur.green("In sync. No differences."));
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
printChanges(changes);
|
|
114
|
+
}
|
|
115
|
+
async function configApply(client, rest) {
|
|
116
|
+
const dryRun = rest.includes("--dry-run");
|
|
117
|
+
const file = rest.find((arg) => !arg.startsWith("--"));
|
|
118
|
+
if (!file) {
|
|
119
|
+
console.error(kleur.red("Usage: seamless config apply <file> [--dry-run]"));
|
|
120
|
+
process.exit(1);
|
|
121
|
+
}
|
|
122
|
+
const local = readConfigFile(file);
|
|
123
|
+
const { patch, dropped } = filterWritable(local);
|
|
124
|
+
if (dropped.length) {
|
|
125
|
+
console.log(kleur.dim(`Ignoring read-only or unknown keys: ${dropped.join(", ")}`));
|
|
126
|
+
}
|
|
127
|
+
const remote = await getSystemConfig(client);
|
|
128
|
+
const changes = diffConfig(patch, remote);
|
|
129
|
+
if (changes.length === 0) {
|
|
130
|
+
console.log(kleur.green("Already in sync. Nothing to apply."));
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
printChanges(changes);
|
|
134
|
+
if (dryRun) {
|
|
135
|
+
console.log(kleur.dim("Dry run: no changes applied."));
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
const proceed = await confirm({
|
|
139
|
+
message: `Apply ${changes.length} change${changes.length === 1 ? "" : "s"} to ${client.profile.instanceUrl}?`,
|
|
140
|
+
initialValue: false,
|
|
141
|
+
});
|
|
142
|
+
if (isCancel(proceed) || !proceed) {
|
|
143
|
+
console.log("Cancelled.");
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
const body = Object.fromEntries(changes.map((change) => [change.key, change.to]));
|
|
147
|
+
const result = await patchSystemConfig(client, body);
|
|
148
|
+
console.log(kleur.green(`Applied. Updated: ${result.updatedKeys.join(", ") || "(none reported)"}`));
|
|
149
|
+
}
|
|
150
|
+
function readConfigFile(file) {
|
|
151
|
+
let raw;
|
|
152
|
+
try {
|
|
153
|
+
raw = fs.readFileSync(file, "utf-8");
|
|
154
|
+
}
|
|
155
|
+
catch {
|
|
156
|
+
throw new ConfigApiError(`Could not read file: ${file}`);
|
|
157
|
+
}
|
|
158
|
+
let parsed;
|
|
159
|
+
try {
|
|
160
|
+
parsed = JSON.parse(raw);
|
|
161
|
+
}
|
|
162
|
+
catch {
|
|
163
|
+
throw new ConfigApiError(`${file} is not valid JSON.`);
|
|
164
|
+
}
|
|
165
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
166
|
+
throw new ConfigApiError(`${file} must contain a JSON object.`);
|
|
167
|
+
}
|
|
168
|
+
return parsed;
|
|
169
|
+
}
|
|
170
|
+
function inline(value) {
|
|
171
|
+
return value === undefined ? "(unset)" : JSON.stringify(value);
|
|
172
|
+
}
|
|
173
|
+
function printConfig(config) {
|
|
174
|
+
const keys = Object.keys(config).sort();
|
|
175
|
+
const width = keys.reduce((max, key) => Math.max(max, key.length), 0);
|
|
176
|
+
for (const key of keys) {
|
|
177
|
+
console.log(kleur.dim(key.padEnd(width) + " ") + inline(config[key]));
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
function printChanges(changes) {
|
|
181
|
+
for (const change of changes) {
|
|
182
|
+
console.log(kleur.bold(change.key));
|
|
183
|
+
console.log(" " + kleur.red(`- ${inline(change.from)}`));
|
|
184
|
+
console.log(" " + kleur.green(`+ ${inline(change.to)}`));
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/commands/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAAE,gBAAgB,EAAE,mBAAmB,EAAmB,MAAM,uBAAuB,CAAC;AAC/F,OAAO,EACL,cAAc,EACd,UAAU,EACV,cAAc,EACd,QAAQ,EACR,eAAe,EACf,UAAU,EACV,iBAAiB,EACjB,eAAe,GAGhB,MAAM,yBAAyB,CAAC;AAEjC,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,IAAc;IAC5C,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IACpB,MAAM,EAAE,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,GAAG,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC;IAE3E,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,gBAAgB,CAAC,EAAE,WAAW,EAAE,CAAC,CAAC;QACvD,QAAQ,GAAG,EAAE,CAAC;YACZ,KAAK,KAAK;gBACR,MAAM,SAAS,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;gBAC9B,OAAO;YACT,KAAK,KAAK;gBACR,MAAM,SAAS,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;gBAC9B,OAAO;YACT,KAAK,OAAO;gBACV,MAAM,WAAW,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;gBAChC,OAAO;YACT,KAAK,MAAM;gBACT,MAAM,UAAU,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;gBAC/B,OAAO;YACT,KAAK,OAAO;gBACV,MAAM,WAAW,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;gBAChC,OAAO;YACT;gBACE,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,8BAA8B,GAAG,IAAI,QAAQ,EAAE,CAAC,CAAC,CAAC;gBAC1E,OAAO,CAAC,GAAG,CAAC,mDAAmD,CAAC,CAAC;gBACjE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACpB,CAAC;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,GAAG,YAAY,mBAAmB,EAAE,CAAC;YACvC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC;YACvC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QACD,IAAI,GAAG,YAAY,eAAe,IAAI,GAAG,YAAY,cAAc,EAAE,CAAC;YACpE,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC;YACtC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QACD,MAAM,GAAG,CAAC;IACZ,CAAC;AACH,CAAC;AAED,KAAK,UAAU,SAAS,CAAC,MAAkB,EAAE,IAAc;IACzD,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IACrC,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC;IACtD,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC,MAAM,CAAC,CAAC;IAE7C,IAAI,GAAG,EAAE,CAAC;QACR,IAAI,CAAC,CAAC,GAAG,IAAI,MAAM,CAAC,EAAE,CAAC;YACrB,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,uBAAuB,GAAG,EAAE,CAAC,CAAC,CAAC;YACvD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QACD,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;QAC1B,OAAO,CAAC,GAAG,CACT,IAAI;YACF,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;YAChC,CAAC,CAAC,OAAO,KAAK,KAAK,QAAQ;gBACzB,CAAC,CAAC,KAAK;gBACP,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CACrC,CAAC;QACF,OAAO;IACT,CAAC;IAED,IAAI,IAAI,EAAE,CAAC;QACT,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAC7C,OAAO;IACT,CAAC;IAED,WAAW,CAAC,MAAM,CAAC,CAAC;AACtB,CAAC;AAED,KAAK,UAAU,SAAS,CAAC,MAAkB,EAAE,IAAc;IACzD,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC;IAC/D,MAAM,CAAC,GAAG,EAAE,GAAG,UAAU,CAAC,GAAG,UAAU,CAAC;IACxC,IAAI,CAAC,GAAG,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACpC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,0CAA0C,CAAC,CAAC,CAAC;QACrE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,KAAK,GAAG,UAAU,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IAC/C,MAAM,MAAM,GAAG,MAAM,iBAAiB,CAAC,MAAM,EAAE,EAAE,CAAC,GAAG,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;IAEjE,IAAI,MAAM,CAAC,WAAW,CAAC,MAAM,EAAE,CAAC;QAC9B,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,YAAY,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;IACxE,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC;IACxC,CAAC;AACH,CAAC;AAED,KAAK,UAAU,WAAW,CAAC,MAAkB,EAAE,IAAc;IAC3D,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IACrC,MAAM,KAAK,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAC,CAAC;IAErC,IAAI,IAAI,EAAE,CAAC;QACT,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAC5C,OAAO;IACT,CAAC;IACD,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC;QACpC,OAAO;IACT,CAAC;IACD,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,OAAO,CAAC,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC;IAC3B,CAAC;AACH,CAAC;AAED,KAAK,UAAU,UAAU,CAAC,MAAkB,EAAE,IAAc;IAC1D,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC;IACvD,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,oCAAoC,CAAC,CAAC,CAAC;QAC/D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,KAAK,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC;IACnC,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC,MAAM,CAAC,CAAC;IAC7C,MAAM,OAAO,GAAG,UAAU,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;IAE1C,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,0BAA0B,CAAC,CAAC,CAAC;QACrD,OAAO;IACT,CAAC;IACD,YAAY,CAAC,OAAO,CAAC,CAAC;AACxB,CAAC;AAED,KAAK,UAAU,WAAW,CAAC,MAAkB,EAAE,IAAc;IAC3D,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;IAC1C,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC;IACvD,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,iDAAiD,CAAC,CAAC,CAAC;QAC5E,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,KAAK,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC;IACnC,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC;IACjD,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;QACnB,OAAO,CAAC,GAAG,CACT,KAAK,CAAC,GAAG,CAAC,uCAAuC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CACvE,CAAC;IACJ,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC,MAAM,CAAC,CAAC;IAC7C,MAAM,OAAO,GAAG,UAAU,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;IAE1C,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,oCAAoC,CAAC,CAAC,CAAC;QAC/D,OAAO;IACT,CAAC;IAED,YAAY,CAAC,OAAO,CAAC,CAAC;IAEtB,IAAI,MAAM,EAAE,CAAC;QACX,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,8BAA8B,CAAC,CAAC,CAAC;QACvD,OAAO;IACT,CAAC;IAED,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC;QAC5B,OAAO,EAAE,SAAS,OAAO,CAAC,MAAM,UAC9B,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAC9B,OAAO,MAAM,CAAC,OAAO,CAAC,WAAW,GAAG;QACpC,YAAY,EAAE,KAAK;KACpB,CAAC,CAAC;IACH,IAAI,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;QAClC,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;QAC1B,OAAO;IACT,CAAC;IAED,MAAM,IAAI,GAAG,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAClF,MAAM,MAAM,GAAG,MAAM,iBAAiB,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IACrD,OAAO,CAAC,GAAG,CACT,KAAK,CAAC,KAAK,CACT,qBAAqB,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,iBAAiB,EAAE,CAC1E,CACF,CAAC;AACJ,CAAC;AAED,SAAS,cAAc,CAAC,IAAY;IAClC,IAAI,GAAW,CAAC;IAChB,IAAI,CAAC;QACH,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IACvC,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,cAAc,CAAC,wBAAwB,IAAI,EAAE,CAAC,CAAC;IAC3D,CAAC;IAED,IAAI,MAAe,CAAC;IACpB,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC3B,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,cAAc,CAAC,GAAG,IAAI,qBAAqB,CAAC,CAAC;IACzD,CAAC;IAED,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QACnE,MAAM,IAAI,cAAc,CAAC,GAAG,IAAI,8BAA8B,CAAC,CAAC;IAClE,CAAC;IACD,OAAO,MAAsB,CAAC;AAChC,CAAC;AAED,SAAS,MAAM,CAAC,KAAc;IAC5B,OAAO,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;AACjE,CAAC;AAED,SAAS,WAAW,CAAC,MAAoB;IACvC,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC;IACxC,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;IACtE,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IACzE,CAAC;AACH,CAAC;AAED,SAAS,YAAY,CAAC,OAAuB;IAC3C,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;QACpC,OAAO,CAAC,GAAG,CAAC,IAAI,GAAG,KAAK,CAAC,GAAG,CAAC,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;QAC1D,OAAO,CAAC,GAAG,CAAC,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,KAAK,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;IAC5D,CAAC;AACH,CAAC"}
|
package/dist/commands/help.js
CHANGED
|
@@ -13,6 +13,16 @@ USAGE
|
|
|
13
13
|
seamless check
|
|
14
14
|
seamless bootstrap-admin [email]
|
|
15
15
|
seamless verify [--api-only] [--filter=<flow>] [--keep-up]
|
|
16
|
+
seamless profile <list|add|use|remove>
|
|
17
|
+
seamless login [identifier] [--identifier <email>] [--profile <name>]
|
|
18
|
+
seamless whoami [--profile <name>]
|
|
19
|
+
seamless logout [--all] [--profile <name>]
|
|
20
|
+
seamless sessions [list]
|
|
21
|
+
seamless sessions revoke <id | --all>
|
|
22
|
+
seamless config <get|set|roles|diff|apply>
|
|
23
|
+
seamless users <list|delete|credentials|prepare-device-replacement>
|
|
24
|
+
seamless org <list|create|get|update>
|
|
25
|
+
seamless org members <list|add|update|remove>
|
|
16
26
|
seamless --help
|
|
17
27
|
seamless --version
|
|
18
28
|
|
|
@@ -35,6 +45,94 @@ COMMANDS
|
|
|
35
45
|
GitLab) and wires the ones you configure into the auth server
|
|
36
46
|
• Run an unknown flag to see the available examples
|
|
37
47
|
|
|
48
|
+
profile <list|add|use|remove>
|
|
49
|
+
Manage the Seamless Auth instances the CLI targets, stored as named
|
|
50
|
+
profiles in ~/.config/seamless/config.json (respects XDG_CONFIG_HOME).
|
|
51
|
+
|
|
52
|
+
profile list
|
|
53
|
+
• Show configured profiles; the active one is marked with *
|
|
54
|
+
|
|
55
|
+
profile add <name> --instance-url <url> [--identifier-type email|phone]
|
|
56
|
+
• Create or update a profile (prompts interactively if flags are omitted)
|
|
57
|
+
|
|
58
|
+
profile use <name>
|
|
59
|
+
• Switch the active profile for subsequent commands
|
|
60
|
+
|
|
61
|
+
profile remove <name>
|
|
62
|
+
• Delete a profile
|
|
63
|
+
|
|
64
|
+
The active profile can also be chosen per command with --profile <name> or
|
|
65
|
+
the SEAMLESS_PROFILE environment variable.
|
|
66
|
+
|
|
67
|
+
login [identifier]
|
|
68
|
+
Log in to the active profile's Seamless Auth instance using email OTP.
|
|
69
|
+
Prompts for the identifier (or pass it positionally or with --identifier)
|
|
70
|
+
and the code sent to your inbox, then stores the session in the OS keychain.
|
|
71
|
+
|
|
72
|
+
--profile <name>
|
|
73
|
+
• Log in against a specific profile instead of the active one
|
|
74
|
+
• Also selectable with the SEAMLESS_PROFILE environment variable
|
|
75
|
+
|
|
76
|
+
whoami
|
|
77
|
+
Show the identity behind the active profile's session (sub, email, roles),
|
|
78
|
+
alongside the profile name and instance URL. Fails cleanly if not logged in.
|
|
79
|
+
|
|
80
|
+
logout [--all]
|
|
81
|
+
End the current session on the instance and clear the local keychain tokens.
|
|
82
|
+
--all revokes every session for the user before clearing local tokens.
|
|
83
|
+
|
|
84
|
+
sessions [list]
|
|
85
|
+
List the active sessions for the logged-in user, with the current session
|
|
86
|
+
marked. Shows the session id, device or user agent, IP, and last-used time.
|
|
87
|
+
|
|
88
|
+
sessions revoke <id | --all>
|
|
89
|
+
Revoke one session by id, or every session with --all. Revoking the current
|
|
90
|
+
session (or --all) prompts for confirmation and then clears local tokens.
|
|
91
|
+
|
|
92
|
+
config <get|set|roles|diff|apply>
|
|
93
|
+
Read and write the instance system configuration (requires an admin role).
|
|
94
|
+
|
|
95
|
+
config get [key] [--json]
|
|
96
|
+
• Print the whole config or a single key
|
|
97
|
+
|
|
98
|
+
config set <key> <value>
|
|
99
|
+
• Update one key; the value is parsed as JSON, falling back to a string
|
|
100
|
+
(for example: config set access_token_ttl 15m,
|
|
101
|
+
config set login_methods '["email_otp","passkey"]')
|
|
102
|
+
|
|
103
|
+
config roles [--json]
|
|
104
|
+
• List the instance's available roles
|
|
105
|
+
|
|
106
|
+
config diff <file>
|
|
107
|
+
• Show how a local JSON config file differs from the instance
|
|
108
|
+
|
|
109
|
+
config apply <file> [--dry-run]
|
|
110
|
+
• Apply a local JSON config file after a confirmation prompt
|
|
111
|
+
|
|
112
|
+
users <list|delete|credentials|prepare-device-replacement>
|
|
113
|
+
Admin user management (requires an admin role).
|
|
114
|
+
|
|
115
|
+
users list [--limit <n>] [--offset <n>] [--json]
|
|
116
|
+
• List users
|
|
117
|
+
users delete <id>
|
|
118
|
+
• Delete a user (asks for confirmation)
|
|
119
|
+
users credentials <id> [--json]
|
|
120
|
+
• Show a user's registered credentials
|
|
121
|
+
users prepare-device-replacement <id> [--keep-sessions] [--keep-passkeys] [--keep-totp]
|
|
122
|
+
• Admin-assisted account recovery (needs an elevated session)
|
|
123
|
+
|
|
124
|
+
org <list|create|get|update>, org members <list|add|update|remove>
|
|
125
|
+
Admin organization management (requires an admin role).
|
|
126
|
+
|
|
127
|
+
org list [--json]
|
|
128
|
+
org create <name> [--slug <slug>]
|
|
129
|
+
org get <id> [--json]
|
|
130
|
+
org update <id> [--name <name>] [--slug <slug>]
|
|
131
|
+
org members list <orgId> [--json]
|
|
132
|
+
org members add <orgId> (--user <id> | --email <email>) [--roles a,b] [--scopes a,b]
|
|
133
|
+
org members update <orgId> <userId> [--roles a,b] [--scopes a,b]
|
|
134
|
+
org members remove <orgId> <userId>
|
|
135
|
+
|
|
38
136
|
check
|
|
39
137
|
Validate project setup, Docker, and running services
|
|
40
138
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"help.js","sourceRoot":"","sources":["../../src/commands/help.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAEtC,MAAM,UAAU,SAAS;IACvB,OAAO,CAAC,GAAG,CAAC;YACF,OAAO
|
|
1
|
+
{"version":3,"file":"help.js","sourceRoot":"","sources":["../../src/commands/help.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAEtC,MAAM,UAAU,SAAS;IACvB,OAAO,CAAC,GAAG,CAAC;YACF,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAsNlB,CAAC,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { intro, outro, text, isCancel, cancel } from "@clack/prompts";
|
|
2
|
+
import kleur from "kleur";
|
|
3
|
+
import { extractFlag } from "../core/args.js";
|
|
4
|
+
import { getActiveProfile, upsertProfile } from "../core/config.js";
|
|
5
|
+
import { KeychainUnavailableError, saveTokens } from "../core/keychain.js";
|
|
6
|
+
import { completeLogin, LoginError } from "../core/loginFlow.js";
|
|
7
|
+
export async function runLogin(args) {
|
|
8
|
+
const profileFlag = extractFlag(args, "profile");
|
|
9
|
+
const idFlag = extractFlag(profileFlag.rest, "identifier");
|
|
10
|
+
const profile = getActiveProfile({ profileFlag: profileFlag.value });
|
|
11
|
+
if (!profile) {
|
|
12
|
+
console.error(kleur.red("No active profile is configured."));
|
|
13
|
+
console.log("Add one with: " +
|
|
14
|
+
kleur.cyan("seamless profile add <name> --instance-url <url>"));
|
|
15
|
+
process.exit(1);
|
|
16
|
+
}
|
|
17
|
+
intro(`Log in to ${kleur.bold(profile.name)} (${profile.instanceUrl})`);
|
|
18
|
+
let identifier = (idFlag.value ?? idFlag.rest[0])?.trim();
|
|
19
|
+
if (!identifier) {
|
|
20
|
+
const answer = await text({
|
|
21
|
+
message: "Email or phone",
|
|
22
|
+
placeholder: profile.email ?? "you@example.com",
|
|
23
|
+
initialValue: profile.email ?? "",
|
|
24
|
+
validate: (value) => value && value.trim() ? undefined : "An identifier is required",
|
|
25
|
+
});
|
|
26
|
+
if (isCancel(answer)) {
|
|
27
|
+
cancel("Cancelled.");
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
identifier = answer.trim();
|
|
31
|
+
}
|
|
32
|
+
try {
|
|
33
|
+
const result = await completeLogin({
|
|
34
|
+
instanceUrl: profile.instanceUrl,
|
|
35
|
+
identifier,
|
|
36
|
+
getCode: async ({ resent }) => {
|
|
37
|
+
const answer = await text({
|
|
38
|
+
message: resent ? "Enter the new code" : "Enter the code we sent you",
|
|
39
|
+
placeholder: "123456",
|
|
40
|
+
validate: (value) => /^\d{4,8}$/.test((value ?? "").trim())
|
|
41
|
+
? undefined
|
|
42
|
+
: "Enter the numeric code from the message",
|
|
43
|
+
});
|
|
44
|
+
if (isCancel(answer))
|
|
45
|
+
return null;
|
|
46
|
+
return answer.trim();
|
|
47
|
+
},
|
|
48
|
+
notify: (event) => {
|
|
49
|
+
switch (event.type) {
|
|
50
|
+
case "code_sent":
|
|
51
|
+
console.log(kleur.dim(`A code was sent to ${identifier}.`));
|
|
52
|
+
break;
|
|
53
|
+
case "code_resent":
|
|
54
|
+
console.log(kleur.dim("Your previous code expired, so we sent a new one."));
|
|
55
|
+
break;
|
|
56
|
+
case "incorrect":
|
|
57
|
+
console.log(kleur.yellow(`That code was not accepted. ${event.attemptsLeft} attempt${event.attemptsLeft === 1 ? "" : "s"} left.`));
|
|
58
|
+
break;
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
});
|
|
62
|
+
if (!result) {
|
|
63
|
+
cancel("Cancelled.");
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
await persistSession(profile, result);
|
|
67
|
+
outro(kleur.green(`Logged in as ${result.identity.email ?? identifier}.`));
|
|
68
|
+
}
|
|
69
|
+
catch (err) {
|
|
70
|
+
if (err instanceof LoginError || err instanceof KeychainUnavailableError) {
|
|
71
|
+
outro(kleur.red(err.message));
|
|
72
|
+
process.exit(1);
|
|
73
|
+
}
|
|
74
|
+
throw err;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
async function persistSession(profile, result) {
|
|
78
|
+
await saveTokens(profile, result.tokens);
|
|
79
|
+
upsertProfile({
|
|
80
|
+
...profile,
|
|
81
|
+
sub: result.identity.sub ?? profile.sub,
|
|
82
|
+
email: result.identity.email ?? profile.email,
|
|
83
|
+
identifierType: result.identity.identifierType,
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=login.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import kleur from "kleur";
|
|
2
|
+
import { extractFlag } from "../core/args.js";
|
|
3
|
+
import { createAuthClient, ReauthRequiredError } from "../core/authClient.js";
|
|
4
|
+
import { getActiveProfile } from "../core/config.js";
|
|
5
|
+
import { clearLocalSession, revokeSession } from "../core/session.js";
|
|
6
|
+
export async function runLogout(args) {
|
|
7
|
+
const all = args.includes("--all");
|
|
8
|
+
const { value: profileFlag } = extractFlag(args.filter((a) => a !== "--all"), "profile");
|
|
9
|
+
const profile = getActiveProfile({ profileFlag });
|
|
10
|
+
if (!profile) {
|
|
11
|
+
console.log(kleur.yellow("No active profile. Nothing to log out of."));
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
let client;
|
|
15
|
+
try {
|
|
16
|
+
client = await createAuthClient({ profileFlag });
|
|
17
|
+
}
|
|
18
|
+
catch (err) {
|
|
19
|
+
if (err instanceof ReauthRequiredError) {
|
|
20
|
+
await clearLocalSession(profile);
|
|
21
|
+
console.log(kleur.green("You are already logged out."));
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
throw err;
|
|
25
|
+
}
|
|
26
|
+
let revoked = false;
|
|
27
|
+
try {
|
|
28
|
+
revoked = await revokeSession(client, { all });
|
|
29
|
+
}
|
|
30
|
+
catch (err) {
|
|
31
|
+
if (!(err instanceof ReauthRequiredError))
|
|
32
|
+
throw err;
|
|
33
|
+
revoked = true;
|
|
34
|
+
}
|
|
35
|
+
await clearLocalSession(profile);
|
|
36
|
+
if (revoked) {
|
|
37
|
+
console.log(kleur.green(all ? "Logged out of all sessions." : "Logged out."));
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
console.log(kleur.yellow("Cleared the local session. The instance reported a problem revoking the session."));
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=logout.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logout.js","sourceRoot":"","sources":["../../src/commands/logout.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC9E,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAEtE,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,IAAc;IAC5C,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;IACnC,MAAM,EAAE,KAAK,EAAE,WAAW,EAAE,GAAG,WAAW,CACxC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,OAAO,CAAC,EACjC,SAAS,CACV,CAAC;IAEF,MAAM,OAAO,GAAG,gBAAgB,CAAC,EAAE,WAAW,EAAE,CAAC,CAAC;IAClD,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,2CAA2C,CAAC,CAAC,CAAC;QACvE,OAAO;IACT,CAAC;IAED,IAAI,MAAM,CAAC;IACX,IAAI,CAAC;QACH,MAAM,GAAG,MAAM,gBAAgB,CAAC,EAAE,WAAW,EAAE,CAAC,CAAC;IACnD,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,GAAG,YAAY,mBAAmB,EAAE,CAAC;YACvC,MAAM,iBAAiB,CAAC,OAAO,CAAC,CAAC;YACjC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,6BAA6B,CAAC,CAAC,CAAC;YACxD,OAAO;QACT,CAAC;QACD,MAAM,GAAG,CAAC;IACZ,CAAC;IAED,IAAI,OAAO,GAAG,KAAK,CAAC;IACpB,IAAI,CAAC;QACH,OAAO,GAAG,MAAM,aAAa,CAAC,MAAM,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC;IACjD,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,CAAC,CAAC,GAAG,YAAY,mBAAmB,CAAC;YAAE,MAAM,GAAG,CAAC;QACrD,OAAO,GAAG,IAAI,CAAC;IACjB,CAAC;IAED,MAAM,iBAAiB,CAAC,OAAO,CAAC,CAAC;IAEjC,IAAI,OAAO,EAAE,CAAC;QACZ,OAAO,CAAC,GAAG,CACT,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,6BAA6B,CAAC,CAAC,CAAC,aAAa,CAAC,CACjE,CAAC;IACJ,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,GAAG,CACT,KAAK,CAAC,MAAM,CACV,kFAAkF,CACnF,CACF,CAAC;IACJ,CAAC;AACH,CAAC"}
|