@ecomweb/cli 0.7.0 → 0.9.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 +56 -32
- package/dist/base-command.d.ts +8 -0
- package/dist/base-command.js +43 -4
- package/dist/base-command.js.map +1 -1
- package/dist/commands/auth/login.d.ts +6 -4
- package/dist/commands/auth/login.js +117 -89
- package/dist/commands/auth/login.js.map +1 -1
- package/dist/commands/auth/logout.js +28 -9
- package/dist/commands/auth/logout.js.map +1 -1
- package/dist/commands/auth/profiles/delete.js +11 -0
- package/dist/commands/auth/profiles/delete.js.map +1 -1
- package/dist/commands/auth/profiles/list.js +2 -2
- package/dist/commands/auth/profiles/list.js.map +1 -1
- package/dist/commands/auth/status.js +17 -9
- package/dist/commands/auth/status.js.map +1 -1
- package/dist/commands/storefront/init.d.ts +2 -1
- package/dist/commands/storefront/init.js +10 -5
- package/dist/commands/storefront/init.js.map +1 -1
- package/dist/commands/{auth/register.d.ts → stores/create.d.ts} +4 -3
- package/dist/commands/stores/create.js +68 -0
- package/dist/commands/stores/create.js.map +1 -0
- package/dist/commands/stores/current.js +1 -1
- package/dist/commands/stores/current.js.map +1 -1
- package/dist/commands/stores/list.js +3 -3
- package/dist/commands/stores/list.js.map +1 -1
- package/dist/commands/stores/switch.js +14 -6
- package/dist/commands/stores/switch.js.map +1 -1
- package/dist/lib/api-client.d.ts +5 -4
- package/dist/lib/api-client.js +32 -16
- package/dist/lib/api-client.js.map +1 -1
- package/dist/lib/codex-skill.d.ts +1 -1
- package/dist/lib/codex-skill.js +12 -8
- package/dist/lib/codex-skill.js.map +1 -1
- package/dist/lib/config.d.ts +6 -18
- package/dist/lib/config.js +35 -64
- package/dist/lib/config.js.map +1 -1
- package/dist/lib/credential-store.d.ts +44 -0
- package/dist/lib/credential-store.js +137 -0
- package/dist/lib/credential-store.js.map +1 -0
- package/dist/lib/device-login.d.ts +22 -0
- package/dist/lib/device-login.js +66 -0
- package/dist/lib/device-login.js.map +1 -0
- package/dist/lib/errors.d.ts +1 -0
- package/dist/lib/errors.js +6 -1
- package/dist/lib/errors.js.map +1 -1
- package/dist/lib/file-lock.d.ts +6 -0
- package/dist/lib/file-lock.js +66 -0
- package/dist/lib/file-lock.js.map +1 -0
- package/dist/lib/open-browser.d.ts +13 -0
- package/dist/lib/open-browser.js +38 -0
- package/dist/lib/open-browser.js.map +1 -0
- package/dist/lib/pending-login.d.ts +5 -0
- package/dist/lib/pending-login.js +39 -0
- package/dist/lib/pending-login.js.map +1 -0
- package/dist/lib/project-setup.d.ts +1 -0
- package/dist/lib/project-setup.js +12 -0
- package/dist/lib/project-setup.js.map +1 -1
- package/dist/lib/secure-file.d.ts +1 -0
- package/dist/lib/secure-file.js +15 -0
- package/dist/lib/secure-file.js.map +1 -0
- package/dist/lib/session.d.ts +40 -0
- package/dist/lib/session.js +80 -0
- package/dist/lib/session.js.map +1 -0
- package/dist/lib/store-selection.d.ts +19 -0
- package/dist/lib/store-selection.js +23 -0
- package/dist/lib/store-selection.js.map +1 -0
- package/oclif.manifest.json +1482 -1833
- package/package.json +2 -1
- package/dist/commands/auth/register.js +0 -35
- package/dist/commands/auth/register.js.map +0 -1
- package/dist/commands/auth/verify.d.ts +0 -20
- package/dist/commands/auth/verify.js +0 -43
- package/dist/commands/auth/verify.js.map +0 -1
- package/dist/commands/init.d.ts +0 -22
- package/dist/commands/init.js +0 -84
- package/dist/commands/init.js.map +0 -1
- package/dist/commands/setup.d.ts +0 -19
- package/dist/commands/setup.js +0 -186
- package/dist/commands/setup.js.map +0 -1
- package/dist/lib/email-login.d.ts +0 -35
- package/dist/lib/email-login.js +0 -86
- package/dist/lib/email-login.js.map +0 -1
package/README.md
CHANGED
|
@@ -5,20 +5,17 @@ Agent-friendly CLI for the ecomweb platform. Manage your store, products, orders
|
|
|
5
5
|
## Quick Start
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
|
-
#
|
|
9
|
-
npx @ecomweb/cli
|
|
8
|
+
npx @ecomweb/cli auth login # approve this CLI in your browser
|
|
9
|
+
npx @ecomweb/cli stores list # every store you belong to
|
|
10
10
|
|
|
11
11
|
# Or install globally
|
|
12
12
|
npm install -g @ecomweb/cli
|
|
13
|
-
ecomweb
|
|
13
|
+
ecomweb auth login
|
|
14
14
|
```
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
2. **Verify email** — enter the 6-digit code
|
|
20
|
-
3. **Set up store** — pick an existing store or create a new one
|
|
21
|
-
4. **Ready!** — API key is generated and saved automatically
|
|
16
|
+
`auth login` shows a short code and opens the dashboard. Check the code matches,
|
|
17
|
+
press **Approve**, and the CLI is logged in as you: your role in each of your
|
|
18
|
+
stores, no API key. No store yet? `ecomweb stores create --name "My Store"`.
|
|
22
19
|
|
|
23
20
|
## Usage
|
|
24
21
|
|
|
@@ -60,23 +57,19 @@ ecomweb <topic> --help
|
|
|
60
57
|
|
|
61
58
|
## Start with an AI agent
|
|
62
59
|
|
|
63
|
-
Build your store's storefront with Claude Code or Codex. Log in
|
|
64
|
-
ecomweb email (we email you a 6-digit code; no API key needed), then create the
|
|
60
|
+
Build your store's storefront with Claude Code or Codex. Log in, then create the
|
|
65
61
|
project:
|
|
66
62
|
|
|
67
63
|
```bash
|
|
68
|
-
npx @ecomweb/cli auth login
|
|
64
|
+
npx @ecomweb/cli auth login # approve in the browser
|
|
69
65
|
npx @ecomweb/cli storefront init # create, install and run it
|
|
70
66
|
npx @ecomweb/cli storefront init --github # the same, as a new GitHub repository
|
|
71
67
|
```
|
|
72
68
|
|
|
73
|
-
Without a terminal (agents, scripts),
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
code was already used without a name, run `auth login --email you@shop.vn
|
|
78
|
-
--store-name "My Store"` again: the verified session is kept, so no new code
|
|
79
|
-
is sent.
|
|
69
|
+
Without a terminal (agents, scripts), `auth login` prints the link and the code
|
|
70
|
+
as JSON and exits. After the user approves, `auth login --wait` finishes the
|
|
71
|
+
login (it waits up to 100 seconds per run; run it again while it answers
|
|
72
|
+
`authorization_pending`). Nothing secret passes through the chat.
|
|
80
73
|
|
|
81
74
|
Inside a storefront project, commands use that project's store (its
|
|
82
75
|
`.ecomweb.json`) unless you pass `--store-ref`.
|
|
@@ -251,7 +244,7 @@ plan with storefront hosting.
|
|
|
251
244
|
|
|
252
245
|
```bash
|
|
253
246
|
npm i -g @ecomweb/cli
|
|
254
|
-
ecomweb auth login
|
|
247
|
+
ecomweb auth login # approve in the browser, then choose the store
|
|
255
248
|
```
|
|
256
249
|
|
|
257
250
|
2. **Copy the theme to work on.** Your shop keeps running the original while
|
|
@@ -323,14 +316,14 @@ ecomweb theme link 54 --url https://shop.example.com
|
|
|
323
316
|
ecomweb theme schema push --theme 54
|
|
324
317
|
```
|
|
325
318
|
|
|
326
|
-
##
|
|
327
|
-
|
|
328
|
-
For CI/CD or scripting, use the flag-based commands instead of the wizard:
|
|
319
|
+
## Authentication
|
|
329
320
|
|
|
330
321
|
```bash
|
|
331
|
-
ecomweb auth
|
|
332
|
-
ecomweb auth
|
|
333
|
-
ecomweb
|
|
322
|
+
ecomweb auth login # browser approval; --no-browser prints the link only
|
|
323
|
+
ecomweb auth logout # revokes this CLI's session
|
|
324
|
+
ecomweb auth status # who you are, and the credential in use
|
|
325
|
+
ecomweb stores create --name "My Store"
|
|
326
|
+
ecomweb stores switch <ref>
|
|
334
327
|
```
|
|
335
328
|
|
|
336
329
|
## Output Formats
|
|
@@ -360,15 +353,40 @@ ecomweb auth status # Check auth status, and which API URL is in u
|
|
|
360
353
|
### Profiles
|
|
361
354
|
|
|
362
355
|
```bash
|
|
363
|
-
ecomweb
|
|
364
|
-
ecomweb products list --profile staging
|
|
356
|
+
ecomweb auth login --profile staging --api-url <staging-api-url> # Create (or update) the profile and sign in
|
|
357
|
+
ecomweb products list --profile staging # Use it: same API, same session
|
|
365
358
|
```
|
|
366
359
|
|
|
360
|
+
`auth login` saves the profile, with the API URL it used when one was given
|
|
361
|
+
by `--api-url` or `ECOMWEB_API_URL`, only once the login is approved, in the
|
|
362
|
+
same step that saves the session. A login that fails or is abandoned changes
|
|
363
|
+
nothing. Without either, a new profile gets the production API.
|
|
364
|
+
|
|
365
|
+
A login is bound to the API that issued it. If a command resolves another API
|
|
366
|
+
URL (say `ECOMWEB_API_URL` is set in one shell and not the other), it fails
|
|
367
|
+
with `SESSION_FOR_OTHER_API` and sends no token: pass `--api-url` with the
|
|
368
|
+
session's URL, or sign in to the other API under its own `--profile`.
|
|
369
|
+
|
|
370
|
+
### Where the login is kept
|
|
371
|
+
|
|
372
|
+
In the OS keychain (macOS Keychain, Windows Credential Manager, the Linux
|
|
373
|
+
Secret Service), under the service `ecomweb-cli`. Where there is none, in
|
|
374
|
+
`~/.config/ecomweb/credentials/<profile>.session.json` (mode 0600). Force one
|
|
375
|
+
with `ECOMWEB_CREDENTIAL_STORE=file` or `keychain`.
|
|
376
|
+
|
|
377
|
+
### CI and servers
|
|
378
|
+
|
|
379
|
+
Use a store API key from the dashboard (Settings, API keys), with only the
|
|
380
|
+
scopes the job needs and an expiry. Pass it as `ECOMWEB_API_KEY` (or
|
|
381
|
+
`--api-key`); it is never written to disk and wins over a login.
|
|
382
|
+
|
|
367
383
|
### Environment Variables
|
|
368
384
|
|
|
369
385
|
| Variable | Description |
|
|
370
386
|
|----------|-------------|
|
|
371
|
-
| `ECOMWEB_API_KEY` | API key (
|
|
387
|
+
| `ECOMWEB_API_KEY` | Store API key for CI and servers (wins over a login) |
|
|
388
|
+
| `ECOMWEB_CREDENTIAL_STORE` | `keychain` or `file`: where the login is kept |
|
|
389
|
+
| `ECOMWEB_NO_BROWSER` | Set to never open a browser (same as `--no-browser`) |
|
|
372
390
|
| `ECOMWEB_STORE_REF` | Store ref (overrides config) |
|
|
373
391
|
| `ECOMWEB_API_URL` | API base URL (overrides default) |
|
|
374
392
|
|
|
@@ -390,11 +408,17 @@ node ./bin/run.js --help
|
|
|
390
408
|
> a local API explicitly:
|
|
391
409
|
>
|
|
392
410
|
> ```bash
|
|
393
|
-
>
|
|
394
|
-
>
|
|
395
|
-
>
|
|
411
|
+
> ecomweb auth login --profile local --api-url http://localhost:3001 # approve on your local dashboard
|
|
412
|
+
> ecomweb auth profiles use local # make it the default
|
|
413
|
+
> ecomweb stores list # now talks to localhost:3001
|
|
396
414
|
> ```
|
|
397
415
|
>
|
|
416
|
+
> The login saves `http://localhost:3001` as the `local` profile's API URL, so
|
|
417
|
+
> later commands need neither the flag nor `ECOMWEB_API_URL`. Switch back with
|
|
418
|
+
> `ecomweb auth profiles use default`. (Logging in with `ECOMWEB_API_URL`
|
|
419
|
+
> exported and no `--profile` also works, but rewrites the `default` profile's
|
|
420
|
+
> URL.)
|
|
421
|
+
>
|
|
398
422
|
> Note the missing `/api/v1` on the local URL. The API sets **no global
|
|
399
423
|
> prefix** — routes hang directly off the origin. The production default
|
|
400
424
|
> includes the prefix because the ingress adds it there.
|
package/dist/base-command.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Command } from "@oclif/core";
|
|
2
2
|
import { ConfigManager } from "./lib/config";
|
|
3
|
+
import { CredentialStore, StoredSession } from "./lib/credential-store";
|
|
3
4
|
import { ApiClient } from "./lib/api-client";
|
|
4
5
|
import { OutputEnvelope, OutputOptions } from "./lib/output";
|
|
5
6
|
export declare abstract class BaseCommand extends Command {
|
|
@@ -17,6 +18,13 @@ export declare abstract class BaseCommand extends Command {
|
|
|
17
18
|
};
|
|
18
19
|
protected configManager: ConfigManager;
|
|
19
20
|
protected apiClient: ApiClient;
|
|
21
|
+
protected credentials: CredentialStore;
|
|
22
|
+
protected get profileName(): string;
|
|
23
|
+
protected lockPathFor(profile: string): string;
|
|
24
|
+
protected get apiUrl(): string;
|
|
25
|
+
protected revokeSession(session: StoredSession, profile?: string): Promise<unknown | undefined>;
|
|
26
|
+
protected now(): number;
|
|
27
|
+
protected sleep(ms: number): Promise<void>;
|
|
20
28
|
protected get outputOptions(): OutputOptions;
|
|
21
29
|
private parsedFlags;
|
|
22
30
|
init(): Promise<void>;
|
package/dist/base-command.js
CHANGED
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
6
|
exports.BaseCommand = void 0;
|
|
4
7
|
const core_1 = require("@oclif/core");
|
|
8
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
5
9
|
const config_1 = require("./lib/config");
|
|
10
|
+
const credential_store_1 = require("./lib/credential-store");
|
|
11
|
+
const session_1 = require("./lib/session");
|
|
6
12
|
const api_client_1 = require("./lib/api-client");
|
|
7
13
|
const project_setup_1 = require("./lib/project-setup");
|
|
8
14
|
const errors_1 = require("./lib/errors");
|
|
@@ -12,6 +18,33 @@ class BaseCommand extends core_1.Command {
|
|
|
12
18
|
super(...arguments);
|
|
13
19
|
this.parsedFlags = {};
|
|
14
20
|
}
|
|
21
|
+
get profileName() {
|
|
22
|
+
return this.configManager.getProfileName();
|
|
23
|
+
}
|
|
24
|
+
lockPathFor(profile) {
|
|
25
|
+
return node_path_1.default.join(config_1.CREDENTIALS_DIR, `${profile}.lock`);
|
|
26
|
+
}
|
|
27
|
+
get apiUrl() {
|
|
28
|
+
return this.configManager.resolveApiUrl(this.getFlag("api-url"));
|
|
29
|
+
}
|
|
30
|
+
async revokeSession(session, profile) {
|
|
31
|
+
try {
|
|
32
|
+
const fallback = profile ? this.configManager.getProfile(profile).api_url : this.apiUrl;
|
|
33
|
+
await new api_client_1.ApiClient({ baseUrl: session.api_url ?? fallback, timeout: 10_000 }).post("/auth/logout", {
|
|
34
|
+
refresh_token: session.refresh_token,
|
|
35
|
+
});
|
|
36
|
+
return undefined;
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
return error ?? new Error("revoke failed");
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
now() {
|
|
43
|
+
return Date.now();
|
|
44
|
+
}
|
|
45
|
+
sleep(ms) {
|
|
46
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
47
|
+
}
|
|
15
48
|
get outputOptions() {
|
|
16
49
|
const flags = this.parsedFlags;
|
|
17
50
|
return {
|
|
@@ -26,13 +59,19 @@ class BaseCommand extends core_1.Command {
|
|
|
26
59
|
await super.init();
|
|
27
60
|
const { flags } = await this.parse(this.constructor);
|
|
28
61
|
this.parsedFlags = flags;
|
|
29
|
-
this.configManager = new config_1.ConfigManager();
|
|
62
|
+
this.configManager = new config_1.ConfigManager(flags.profile);
|
|
30
63
|
const apiUrl = this.configManager.resolveApiUrl(flags["api-url"]);
|
|
31
64
|
const apiKey = this.configManager.resolveApiKey(flags["api-key"]);
|
|
32
|
-
this.
|
|
33
|
-
|
|
34
|
-
|
|
65
|
+
this.credentials = (0, credential_store_1.lazyCredentialStore)(() => (0, credential_store_1.openCredentialStore)({ dir: config_1.CREDENTIALS_DIR }));
|
|
66
|
+
const anonymous = new api_client_1.ApiClient({ baseUrl: apiUrl });
|
|
67
|
+
const session = new session_1.SessionManager({
|
|
68
|
+
store: this.credentials,
|
|
69
|
+
profile: this.profileName,
|
|
70
|
+
lockPath: this.lockPathFor(this.profileName),
|
|
71
|
+
apiUrl,
|
|
72
|
+
refresh: (refresh_token) => anonymous.post("/auth/session/refresh", { refresh_token }),
|
|
35
73
|
});
|
|
74
|
+
this.apiClient = new api_client_1.ApiClient({ baseUrl: apiUrl, apiKey, session });
|
|
36
75
|
const storeRef = this.resolveStore();
|
|
37
76
|
if (storeRef) {
|
|
38
77
|
this.apiClient.setStoreRef(storeRef);
|
package/dist/base-command.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base-command.js","sourceRoot":"","sources":["../src/base-command.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"base-command.js","sourceRoot":"","sources":["../src/base-command.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { BaseCommand } from "../../base-command";
|
|
2
|
+
export declare const WAIT_LIMIT_MS = 100000;
|
|
2
3
|
export default class AuthLogin extends BaseCommand {
|
|
3
4
|
static description: string;
|
|
4
5
|
static examples: string[];
|
|
5
6
|
static flags: {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
"store-name": import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
7
|
+
wait: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
8
|
+
browser: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
9
9
|
"store-ref": import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
10
10
|
"api-key": import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
11
11
|
"api-url": import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
@@ -18,5 +18,7 @@ export default class AuthLogin extends BaseCommand {
|
|
|
18
18
|
exclude: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
19
19
|
};
|
|
20
20
|
run(): Promise<void>;
|
|
21
|
-
|
|
21
|
+
protected isInteractive(): boolean;
|
|
22
|
+
private outputPending;
|
|
23
|
+
private selectStore;
|
|
22
24
|
}
|
|
@@ -1,119 +1,147 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.WAIT_LIMIT_MS = void 0;
|
|
3
4
|
const node_os_1 = require("node:os");
|
|
4
5
|
const core_1 = require("@oclif/core");
|
|
5
6
|
const prompts_1 = require("@inquirer/prompts");
|
|
6
7
|
const base_command_1 = require("../../base-command");
|
|
7
|
-
const
|
|
8
|
+
const config_1 = require("../../lib/config");
|
|
9
|
+
const errors_1 = require("../../lib/errors");
|
|
10
|
+
const file_lock_1 = require("../../lib/file-lock");
|
|
11
|
+
const device_login_1 = require("../../lib/device-login");
|
|
12
|
+
const open_browser_1 = require("../../lib/open-browser");
|
|
13
|
+
const pending_login_1 = require("../../lib/pending-login");
|
|
14
|
+
const session_1 = require("../../lib/session");
|
|
15
|
+
const store_selection_1 = require("../../lib/store-selection");
|
|
16
|
+
exports.WAIT_LIMIT_MS = 100_000;
|
|
17
|
+
const FINAL_CODES = new Set(["DEVICE_AUTH_DENIED", "DEVICE_AUTH_EXPIRED"]);
|
|
8
18
|
class AuthLogin extends base_command_1.BaseCommand {
|
|
9
19
|
async run() {
|
|
10
|
-
const
|
|
11
|
-
const
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
20
|
+
const profile = this.profileName;
|
|
21
|
+
const givenApiUrl = this.getFlag("api-url");
|
|
22
|
+
const apiUrl = this.apiUrl;
|
|
23
|
+
const api = this.apiClient.anonymous();
|
|
24
|
+
const interactive = this.isInteractive();
|
|
25
|
+
this.configManager.removeLegacyCredentials(profile);
|
|
26
|
+
const existing = (0, pending_login_1.readPending)(config_1.CREDENTIALS_DIR, profile, apiUrl, this.now());
|
|
27
|
+
let pending = existing ?? (await (0, device_login_1.requestDeviceCode)(api, (0, node_os_1.hostname)(), apiUrl, this.now()));
|
|
28
|
+
if (!existing) {
|
|
29
|
+
(0, pending_login_1.writePending)(config_1.CREDENTIALS_DIR, profile, pending);
|
|
30
|
+
if (this.getFlag("browser"))
|
|
31
|
+
(0, open_browser_1.openBrowser)(pending.verification_uri_complete);
|
|
32
|
+
}
|
|
33
|
+
if (!interactive && (!this.getFlag("wait") || !existing))
|
|
34
|
+
return this.outputPending(pending);
|
|
35
|
+
if (interactive) {
|
|
36
|
+
this.logToStderr(`Your code: ${pending.user_code}`);
|
|
37
|
+
this.logToStderr(`Approve this CLI at: ${pending.verification_uri_complete}`);
|
|
38
|
+
this.logToStderr("Waiting for approval...");
|
|
39
|
+
}
|
|
40
|
+
const deadline = interactive ? pending.expires_at : Math.min(pending.expires_at, this.now() + exports.WAIT_LIMIT_MS);
|
|
41
|
+
let tokens;
|
|
42
|
+
try {
|
|
43
|
+
tokens = await (0, device_login_1.pollUntil)(api, pending, {
|
|
44
|
+
deadline,
|
|
45
|
+
now: () => this.now(),
|
|
46
|
+
sleep: (ms) => this.sleep(ms),
|
|
47
|
+
onInterval: (interval) => {
|
|
48
|
+
pending = { ...pending, interval };
|
|
49
|
+
(0, pending_login_1.writePending)(config_1.CREDENTIALS_DIR, profile, pending);
|
|
21
50
|
},
|
|
22
51
|
});
|
|
23
|
-
this.exit(2);
|
|
24
|
-
return;
|
|
25
52
|
}
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
53
|
+
catch (error) {
|
|
54
|
+
if (error instanceof errors_1.CliError && FINAL_CODES.has(error.payload.code))
|
|
55
|
+
(0, pending_login_1.deletePending)(config_1.CREDENTIALS_DIR, profile);
|
|
56
|
+
throw error;
|
|
30
57
|
}
|
|
58
|
+
if (!tokens) {
|
|
59
|
+
if (!interactive)
|
|
60
|
+
return this.outputPending(pending);
|
|
61
|
+
(0, pending_login_1.deletePending)(config_1.CREDENTIALS_DIR, profile);
|
|
62
|
+
throw (0, device_login_1.deviceAuthExpired)();
|
|
63
|
+
}
|
|
64
|
+
(0, pending_login_1.deletePending)(config_1.CREDENTIALS_DIR, profile);
|
|
65
|
+
const session = (0, session_1.sessionFromTokens)(tokens, apiUrl);
|
|
66
|
+
const previous = await (0, file_lock_1.withFileLock)(this.lockPathFor(profile), async () => {
|
|
67
|
+
const previous = this.credentials.get(profile);
|
|
68
|
+
this.credentials.set(profile, session);
|
|
69
|
+
this.configManager.setProfile(profile, givenApiUrl ? { api_url: givenApiUrl } : {});
|
|
70
|
+
return previous;
|
|
71
|
+
});
|
|
72
|
+
if (previous && previous.refresh_token !== session.refresh_token)
|
|
73
|
+
await this.revokeSession(previous);
|
|
31
74
|
try {
|
|
32
|
-
await this.
|
|
33
|
-
this.outputJson({
|
|
34
|
-
message: "Login successful.",
|
|
35
|
-
profile: profileName,
|
|
36
|
-
api_url: this.configManager.getProfile(profileName).api_url,
|
|
37
|
-
hint: "Run: ecomweb stores list to see available stores",
|
|
38
|
-
});
|
|
75
|
+
await this.selectStore(profile, session.email, interactive);
|
|
39
76
|
}
|
|
40
|
-
catch {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
hint: "Run: ecomweb health check to verify connectivity",
|
|
77
|
+
catch (error) {
|
|
78
|
+
const { json, exitCode } = (0, errors_1.formatError)(error);
|
|
79
|
+
throw new errors_1.CliError(json.error.code, `Signed in, but choosing a store failed: ${json.error.message}`, exitCode, {
|
|
80
|
+
hint: json.error.hint,
|
|
81
|
+
details: { ...json.error.details, logged_in: true, profile },
|
|
46
82
|
});
|
|
47
83
|
}
|
|
48
84
|
}
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
const
|
|
54
|
-
const
|
|
55
|
-
const
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
85
|
+
isInteractive() {
|
|
86
|
+
return Boolean(process.stdin.isTTY && process.stderr.isTTY && !process.env.CI);
|
|
87
|
+
}
|
|
88
|
+
outputPending(pending) {
|
|
89
|
+
const flag = this.getFlag("profile");
|
|
90
|
+
const apiUrlFlag = this.getFlag("api-url");
|
|
91
|
+
const again = `${flag ? ` --profile ${flag}` : ""}${apiUrlFlag ? ` --api-url ${apiUrlFlag}` : ""}`;
|
|
92
|
+
this.outputJson({
|
|
93
|
+
status: "authorization_pending",
|
|
94
|
+
verification_uri_complete: pending.verification_uri_complete,
|
|
95
|
+
user_code: pending.user_code,
|
|
96
|
+
expires_in: Math.max(0, Math.round((pending.expires_at - this.now()) / 1000)),
|
|
97
|
+
hint: `Open the link and approve, then run: ecomweb auth login --wait${again}`,
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
async selectStore(profile, email, interactive) {
|
|
101
|
+
const stores = (await this.apiClient.listStores({ limit: 100 })).map((s) => ({ ref: s.ref, name: s.name }));
|
|
102
|
+
const choice = await (0, store_selection_1.chooseStore)({
|
|
103
|
+
stores,
|
|
63
104
|
storeRef: this.getFlag("store-ref"),
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
}
|
|
71
|
-
: undefined,
|
|
72
|
-
askCode: interactive
|
|
73
|
-
? () => {
|
|
74
|
-
this.logToStderr(`We emailed a 6-digit code to ${email}.`);
|
|
75
|
-
return (0, prompts_1.input)({ message: "Code:" }, prompt);
|
|
76
|
-
}
|
|
77
|
-
: undefined,
|
|
78
|
-
chooseStore: interactive
|
|
79
|
-
? (stores) => (0, prompts_1.select)({ message: "Which store?", choices: stores.map((s) => ({ name: `${s.name} (${s.ref})`, value: s })) }, prompt)
|
|
105
|
+
currentRef: this.configManager.getProfile(profile).store_ref,
|
|
106
|
+
prompt: interactive
|
|
107
|
+
? (list, currentRef) => (0, prompts_1.select)({
|
|
108
|
+
message: "Which store?",
|
|
109
|
+
choices: list.map((s) => ({ name: `${s.name} (${s.ref})`, value: s })),
|
|
110
|
+
default: list.find((s) => s.ref === currentRef),
|
|
111
|
+
}, { output: process.stderr })
|
|
80
112
|
: undefined,
|
|
81
113
|
});
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
this.outputJson({
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
114
|
+
const done = { status: "logged_in", email, profile };
|
|
115
|
+
if (choice.kind === "selected") {
|
|
116
|
+
this.configManager.setStoreRef(choice.store.ref, choice.store.name, profile);
|
|
117
|
+
this.outputJson({ ...done, store: choice.store });
|
|
118
|
+
}
|
|
119
|
+
else if (choice.kind === "choose") {
|
|
120
|
+
this.outputJson({ ...done, store: null, stores: choice.stores, hint: "Run: ecomweb stores switch <ref>" });
|
|
121
|
+
}
|
|
122
|
+
else {
|
|
123
|
+
this.outputJson({ ...done, store: null, hint: 'Run: ecomweb stores create --name "My Store"' });
|
|
91
124
|
}
|
|
92
|
-
this.configManager.setApiKey(result.apiKey, profileName);
|
|
93
|
-
this.configManager.setStoreRef(result.store.ref, result.store.name, profileName);
|
|
94
|
-
if (sameEmail(this.configManager.getJwtTokens(profileName)?.email))
|
|
95
|
-
this.configManager.removeJwtTokens(profileName);
|
|
96
|
-
this.outputJson({
|
|
97
|
-
status: "logged_in",
|
|
98
|
-
email,
|
|
99
|
-
profile: profileName,
|
|
100
|
-
store: { ref: result.store.ref, name: result.store.name },
|
|
101
|
-
...(result.created && { created: true }),
|
|
102
|
-
});
|
|
103
125
|
}
|
|
104
126
|
}
|
|
105
|
-
AuthLogin.description = "Log in
|
|
127
|
+
AuthLogin.description = "Log in by approving this CLI in your browser";
|
|
106
128
|
AuthLogin.examples = [
|
|
107
|
-
"ecomweb auth login
|
|
108
|
-
"ecomweb auth login --
|
|
109
|
-
"ecomweb auth login --
|
|
110
|
-
"
|
|
129
|
+
"ecomweb auth login",
|
|
130
|
+
"ecomweb auth login --wait",
|
|
131
|
+
"ecomweb auth login --no-browser",
|
|
132
|
+
"ecomweb auth login --store-ref abc123",
|
|
111
133
|
];
|
|
112
134
|
AuthLogin.flags = {
|
|
113
135
|
...base_command_1.BaseCommand.baseFlags,
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
136
|
+
wait: core_1.Flags.boolean({
|
|
137
|
+
description: "Wait (up to 100 seconds) for the approval of the code an earlier run printed",
|
|
138
|
+
default: false,
|
|
139
|
+
}),
|
|
140
|
+
browser: core_1.Flags.boolean({
|
|
141
|
+
description: "Open the approval link in the browser (--no-browser only prints it)",
|
|
142
|
+
default: true,
|
|
143
|
+
allowNo: true,
|
|
144
|
+
}),
|
|
117
145
|
};
|
|
118
146
|
exports.default = AuthLogin;
|
|
119
147
|
//# sourceMappingURL=login.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"login.js","sourceRoot":"","sources":["../../../src/commands/auth/login.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"login.js","sourceRoot":"","sources":["../../../src/commands/auth/login.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,21 +1,40 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const base_command_1 = require("../../base-command");
|
|
4
|
+
const config_1 = require("../../lib/config");
|
|
5
|
+
const file_lock_1 = require("../../lib/file-lock");
|
|
6
|
+
const pending_login_1 = require("../../lib/pending-login");
|
|
4
7
|
class AuthLogout extends base_command_1.BaseCommand {
|
|
5
8
|
async run() {
|
|
6
|
-
const
|
|
7
|
-
this.
|
|
9
|
+
const profile = this.profileName;
|
|
10
|
+
const { session, failure } = await (0, file_lock_1.withFileLock)(this.lockPathFor(profile), async () => {
|
|
11
|
+
const session = this.credentials.get(profile);
|
|
12
|
+
const failure = session ? await this.revokeSession(session) : undefined;
|
|
13
|
+
this.credentials.delete(profile);
|
|
14
|
+
return { session, failure };
|
|
15
|
+
});
|
|
16
|
+
const revoked = Boolean(session) && !failure;
|
|
17
|
+
const warning = failure
|
|
18
|
+
? `Could not revoke the session on the server (${failure instanceof Error ? failure.message : String(failure)}). ` +
|
|
19
|
+
"It was forgotten here; it ends by itself after 30 days unused, or revoke it now on your profile page in the dashboard."
|
|
20
|
+
: undefined;
|
|
21
|
+
(0, pending_login_1.deletePending)(config_1.CREDENTIALS_DIR, profile);
|
|
22
|
+
this.configManager.removeLegacyCredentials(profile);
|
|
23
|
+
const usingApiKey = !session && this.configManager.resolveApiKey(this.getFlag("api-key")) !== undefined;
|
|
8
24
|
this.outputJson({
|
|
9
|
-
message:
|
|
10
|
-
|
|
25
|
+
message: session
|
|
26
|
+
? "Logged out."
|
|
27
|
+
: usingApiKey
|
|
28
|
+
? "No session to log out of: this command is using an API key from --api-key or ECOMWEB_API_KEY."
|
|
29
|
+
: "Not logged in.",
|
|
30
|
+
profile,
|
|
31
|
+
server_session_revoked: revoked,
|
|
32
|
+
...(warning && { warning }),
|
|
11
33
|
});
|
|
12
34
|
}
|
|
13
35
|
}
|
|
14
|
-
AuthLogout.description = "
|
|
15
|
-
AuthLogout.examples = [
|
|
16
|
-
"ecomweb auth logout",
|
|
17
|
-
"ecomweb auth logout --profile production",
|
|
18
|
-
];
|
|
36
|
+
AuthLogout.description = "Log out: revoke this CLI's session and forget it";
|
|
37
|
+
AuthLogout.examples = ["ecomweb auth logout", "ecomweb auth logout --profile staging"];
|
|
19
38
|
AuthLogout.flags = {
|
|
20
39
|
...base_command_1.BaseCommand.baseFlags,
|
|
21
40
|
};
|