@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.
Files changed (82) hide show
  1. package/README.md +56 -32
  2. package/dist/base-command.d.ts +8 -0
  3. package/dist/base-command.js +43 -4
  4. package/dist/base-command.js.map +1 -1
  5. package/dist/commands/auth/login.d.ts +6 -4
  6. package/dist/commands/auth/login.js +117 -89
  7. package/dist/commands/auth/login.js.map +1 -1
  8. package/dist/commands/auth/logout.js +28 -9
  9. package/dist/commands/auth/logout.js.map +1 -1
  10. package/dist/commands/auth/profiles/delete.js +11 -0
  11. package/dist/commands/auth/profiles/delete.js.map +1 -1
  12. package/dist/commands/auth/profiles/list.js +2 -2
  13. package/dist/commands/auth/profiles/list.js.map +1 -1
  14. package/dist/commands/auth/status.js +17 -9
  15. package/dist/commands/auth/status.js.map +1 -1
  16. package/dist/commands/storefront/init.d.ts +2 -1
  17. package/dist/commands/storefront/init.js +10 -5
  18. package/dist/commands/storefront/init.js.map +1 -1
  19. package/dist/commands/{auth/register.d.ts → stores/create.d.ts} +4 -3
  20. package/dist/commands/stores/create.js +68 -0
  21. package/dist/commands/stores/create.js.map +1 -0
  22. package/dist/commands/stores/current.js +1 -1
  23. package/dist/commands/stores/current.js.map +1 -1
  24. package/dist/commands/stores/list.js +3 -3
  25. package/dist/commands/stores/list.js.map +1 -1
  26. package/dist/commands/stores/switch.js +14 -6
  27. package/dist/commands/stores/switch.js.map +1 -1
  28. package/dist/lib/api-client.d.ts +5 -4
  29. package/dist/lib/api-client.js +32 -16
  30. package/dist/lib/api-client.js.map +1 -1
  31. package/dist/lib/codex-skill.d.ts +1 -1
  32. package/dist/lib/codex-skill.js +12 -8
  33. package/dist/lib/codex-skill.js.map +1 -1
  34. package/dist/lib/config.d.ts +6 -18
  35. package/dist/lib/config.js +35 -64
  36. package/dist/lib/config.js.map +1 -1
  37. package/dist/lib/credential-store.d.ts +44 -0
  38. package/dist/lib/credential-store.js +137 -0
  39. package/dist/lib/credential-store.js.map +1 -0
  40. package/dist/lib/device-login.d.ts +22 -0
  41. package/dist/lib/device-login.js +66 -0
  42. package/dist/lib/device-login.js.map +1 -0
  43. package/dist/lib/errors.d.ts +1 -0
  44. package/dist/lib/errors.js +6 -1
  45. package/dist/lib/errors.js.map +1 -1
  46. package/dist/lib/file-lock.d.ts +6 -0
  47. package/dist/lib/file-lock.js +66 -0
  48. package/dist/lib/file-lock.js.map +1 -0
  49. package/dist/lib/open-browser.d.ts +13 -0
  50. package/dist/lib/open-browser.js +38 -0
  51. package/dist/lib/open-browser.js.map +1 -0
  52. package/dist/lib/pending-login.d.ts +5 -0
  53. package/dist/lib/pending-login.js +39 -0
  54. package/dist/lib/pending-login.js.map +1 -0
  55. package/dist/lib/project-setup.d.ts +1 -0
  56. package/dist/lib/project-setup.js +12 -0
  57. package/dist/lib/project-setup.js.map +1 -1
  58. package/dist/lib/secure-file.d.ts +1 -0
  59. package/dist/lib/secure-file.js +15 -0
  60. package/dist/lib/secure-file.js.map +1 -0
  61. package/dist/lib/session.d.ts +40 -0
  62. package/dist/lib/session.js +80 -0
  63. package/dist/lib/session.js.map +1 -0
  64. package/dist/lib/store-selection.d.ts +19 -0
  65. package/dist/lib/store-selection.js +23 -0
  66. package/dist/lib/store-selection.js.map +1 -0
  67. package/oclif.manifest.json +1482 -1833
  68. package/package.json +2 -1
  69. package/dist/commands/auth/register.js +0 -35
  70. package/dist/commands/auth/register.js.map +0 -1
  71. package/dist/commands/auth/verify.d.ts +0 -20
  72. package/dist/commands/auth/verify.js +0 -43
  73. package/dist/commands/auth/verify.js.map +0 -1
  74. package/dist/commands/init.d.ts +0 -22
  75. package/dist/commands/init.js +0 -84
  76. package/dist/commands/init.js.map +0 -1
  77. package/dist/commands/setup.d.ts +0 -19
  78. package/dist/commands/setup.js +0 -186
  79. package/dist/commands/setup.js.map +0 -1
  80. package/dist/lib/email-login.d.ts +0 -35
  81. package/dist/lib/email-login.js +0 -86
  82. 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
- # Interactive setup wizard (recommended for first-time users)
9
- npx @ecomweb/cli setup
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 setup
13
+ ecomweb auth login
14
14
  ```
15
15
 
16
- The setup wizard walks you through:
17
-
18
- 1. **Create account** — enter your email, receive a verification code
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 with your
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 --email you@shop.vn # asks for the code, then your store
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), run `auth login --email` once to get the
74
- code, then `auth login --email you@shop.vn --code <code> [--store-ref <ref>]`.
75
- No store yet? Add `--store-name "My Store"` to both runs: the store is
76
- created as you log in (in a terminal you are asked for the name). If the
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 --email <your email> # then choose the store
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
- ## Non-Interactive Auth
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 register --email user@example.com
332
- ecomweb auth verify --email user@example.com --code 123456
333
- ecomweb init --store-name "My Store"
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 setup --profile staging # Create a named profile
364
- ecomweb products list --profile staging # Use it
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 (overrides config) |
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
- > export ECOMWEB_API_URL=http://localhost:3001
394
- > export ECOMWEB_STORE_REF=<your-store-ref>
395
- > export ECOMWEB_API_KEY=<a-store-api-key>
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.
@@ -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>;
@@ -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.apiClient = new api_client_1.ApiClient({
33
- baseUrl: apiUrl,
34
- apiKey,
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);
@@ -1 +1 @@
1
- {"version":3,"file":"base-command.js","sourceRoot":"","sources":["../src/base-command.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"base-command.js","sourceRoot":"","sources":["../src/base-command.ts"],"names":[],"mappings":";;;;;;AAAA,sCAA6C;AAC7C,0DAA6B;AAC7B,yCAA8D;AAC9D,6DAAkH;AAClH,2CAA8D;AAC9D,iDAA6C;AAC7C,uDAAsD;AACtD,yCAA+D;AAC/D,yCAAyF;AAEzF,MAAsB,WAAY,SAAQ,cAAO;IAAjD;;QAsGU,gBAAW,GAAQ,EAAE,CAAC;IA4GhC,CAAC;IAjKC,IAAc,WAAW;QACvB,OAAO,IAAI,CAAC,aAAa,CAAC,cAAc,EAAE,CAAC;IAC7C,CAAC;IAGS,WAAW,CAAC,OAAe;QACnC,OAAO,mBAAI,CAAC,IAAI,CAAC,wBAAe,EAAE,GAAG,OAAO,OAAO,CAAC,CAAC;IACvD,CAAC;IAGD,IAAc,MAAM;QAClB,OAAO,IAAI,CAAC,aAAa,CAAC,aAAa,CAAC,IAAI,CAAC,OAAO,CAAS,SAAS,CAAC,CAAC,CAAC;IAC3E,CAAC;IAMS,KAAK,CAAC,aAAa,CAAC,OAAsB,EAAE,OAAgB;QACpE,IAAI,CAAC;YAGH,MAAM,QAAQ,GAAG,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC;YACxF,MAAM,IAAI,sBAAS,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,IAAI,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,cAAc,EAAE;gBAClG,aAAa,EAAE,OAAO,CAAC,aAAa;aACrC,CAAC,CAAC;YACH,OAAO,SAAS,CAAC;QACnB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,KAAK,IAAI,IAAI,KAAK,CAAC,eAAe,CAAC,CAAC;QAC7C,CAAC;IACH,CAAC;IAGS,GAAG;QACX,OAAO,IAAI,CAAC,GAAG,EAAE,CAAC;IACpB,CAAC;IAES,KAAK,CAAC,EAAU;QACxB,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;IAC3D,CAAC;IAED,IAAc,aAAa;QACzB,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW,CAAC;QAC/B,OAAO;YACL,MAAM,EAAE,CAAC,KAAK,CAAC,MAAM,IAAI,MAAM,CAAiB;YAChD,KAAK,EAAE,KAAK,CAAC,KAAK,IAAI,KAAK;YAC3B,IAAI,EAAE,KAAK,CAAC,IAAI,IAAI,KAAK;YACzB,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS;YACvF,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS;SAC3F,CAAC;IACJ,CAAC;IAKD,KAAK,CAAC,IAAI;QACR,MAAM,KAAK,CAAC,IAAI,EAAE,CAAC;QAGnB,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,WAAkB,CAAC,CAAC;QAC5D,IAAI,CAAC,WAAW,GAAG,KAAK,CAAC;QAGzB,IAAI,CAAC,aAAa,GAAG,IAAI,sBAAa,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAGtD,MAAM,MAAM,GAAG,IAAI,CAAC,aAAa,CAAC,aAAa,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC;QAClE,MAAM,MAAM,GAAG,IAAI,CAAC,aAAa,CAAC,aAAa,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC;QAClE,IAAI,CAAC,WAAW,GAAG,IAAA,sCAAmB,EAAC,GAAG,EAAE,CAAC,IAAA,sCAAmB,EAAC,EAAE,GAAG,EAAE,wBAAe,EAAE,CAAC,CAAC,CAAC;QAC5F,MAAM,SAAS,GAAG,IAAI,sBAAS,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;QACrD,MAAM,OAAO,GAAG,IAAI,wBAAc,CAAC;YACjC,KAAK,EAAE,IAAI,CAAC,WAAW;YACvB,OAAO,EAAE,IAAI,CAAC,WAAW;YACzB,QAAQ,EAAE,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,WAAW,CAAC;YAC5C,MAAM;YACN,OAAO,EAAE,CAAC,aAAa,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,CAAgB,uBAAuB,EAAE,EAAE,aAAa,EAAE,CAAC;SACtG,CAAC,CAAC;QACH,IAAI,CAAC,SAAS,GAAG,IAAI,sBAAS,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC;QAGrE,MAAM,QAAQ,GAAG,IAAI,CAAC,YAAY,EAAE,CAAC;QACrC,IAAI,QAAQ,EAAE,CAAC;YACb,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;QACvC,CAAC;IACH,CAAC;IASS,YAAY,CAAC,aAAqB,OAAO,CAAC,GAAG,EAAE;QACvD,OAAO,CACL,IAAI,CAAC,WAAW,CAAC,WAAW,CAAC;YAC7B,IAAA,+BAAe,EAAC,UAAU,CAAC;YAC3B,IAAI,CAAC,aAAa,CAAC,eAAe,CAAC,SAAS,CAAC,CAC9C,CAAC;IACJ,CAAC;IAES,YAAY,CAAC,UAAmB;QACxC,MAAM,QAAQ,GAAG,IAAI,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC;QAC/C,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,MAAM,IAAI,iBAAQ,CAChB,mBAAmB,EACnB,oBAAoB,EACpB,iBAAQ,CAAC,UAAU,EACnB,EAAE,IAAI,EAAE,kCAAkC,EAAE,CAC7C,CAAC;QACJ,CAAC;QACD,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;QACrC,OAAO,QAAQ,CAAC;IAClB,CAAC;IAKS,WAAW;QACnB,OAAO,IAAI,CAAC,aAAa,CAAC,eAAe,CAAC,IAAI,CAAC,WAAW,CAAC,WAAW,CAAC,CAAC,CAAC;IAC3E,CAAC;IAKS,YAAY,CAAC,QAAwB;QAC7C,MAAM,SAAS,GAAG,IAAA,qBAAY,EAAC,QAAQ,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC;QAC7D,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IACtB,CAAC;IAKS,UAAU,CAAC,IAAS;QAC5B,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IAC1C,CAAC;IAKD,IAAc,QAAQ;QACpB,OAAO,IAAI,CAAC,WAAW,CAAC,SAAS,CAAC,IAAI,KAAK,CAAC;IAC9C,CAAC;IAKS,OAAO,CAAU,IAAY;QACrC,OAAO,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;IAChC,CAAC;IAKD,KAAK,CAAC,KAAK,CAAC,KAA+D;QAEzE,IAAI,KAAK,CAAC,KAAK,EAAE,IAAI,KAAK,SAAS;YAAE,MAAM,KAAK,CAAC;QACjD,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,IAAA,oBAAW,EAAC,KAAK,CAAC,CAAC;QAC9C,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QACxC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACtB,CAAC;;AAjNH,kCAkNC;AAjNQ,qBAAS,GAAG;IACjB,WAAW,EAAE,YAAK,CAAC,MAAM,CAAC;QACxB,WAAW,EAAE,sCAAsC;QACnD,GAAG,EAAE,mBAAmB;KACzB,CAAC;IACF,SAAS,EAAE,YAAK,CAAC,MAAM,CAAC;QACtB,WAAW,EAAE,kCAAkC;QAC/C,GAAG,EAAE,iBAAiB;KACvB,CAAC;IACF,SAAS,EAAE,YAAK,CAAC,MAAM,CAAC;QACtB,WAAW,EAAE,uCAAuC;QACpD,GAAG,EAAE,iBAAiB;KACvB,CAAC;IACF,MAAM,EAAE,YAAK,CAAC,MAAM,CAAC;QACnB,WAAW,EAAE,eAAe;QAC5B,OAAO,EAAE,CAAC,MAAM,EAAE,OAAO,EAAE,KAAK,CAAC;QACjC,OAAO,EAAE,MAAM;KAChB,CAAC;IACF,KAAK,EAAE,YAAK,CAAC,OAAO,CAAC;QACnB,WAAW,EAAE,0BAA0B;QACvC,OAAO,EAAE,KAAK;KACf,CAAC;IACF,SAAS,EAAE,YAAK,CAAC,OAAO,CAAC;QACvB,WAAW,EAAE,2BAA2B;QACxC,OAAO,EAAE,KAAK;KACf,CAAC;IACF,OAAO,EAAE,YAAK,CAAC,MAAM,CAAC;QACpB,WAAW,EAAE,sBAAsB;KACpC,CAAC;IACF,IAAI,EAAE,YAAK,CAAC,OAAO,CAAC;QAClB,WAAW,EAAE,yCAAyC;QACtD,OAAO,EAAE,KAAK;KACf,CAAC;IACF,MAAM,EAAE,YAAK,CAAC,MAAM,CAAC;QACnB,WAAW,EAAE,wCAAwC;KACtD,CAAC;IACF,OAAO,EAAE,YAAK,CAAC,MAAM,CAAC;QACpB,WAAW,EAAE,wCAAwC;KACtD,CAAC;CACH,AAvCe,CAuCd"}
@@ -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
- email: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
7
- code: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
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
- private loginWithEmail;
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 email_login_1 = require("../../lib/email-login");
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 apiUrl = this.getFlag("api-url");
11
- const apiKey = this.getFlag("api-key");
12
- const email = this.getFlag("email");
13
- if (email && !apiKey)
14
- return this.loginWithEmail(email, apiUrl);
15
- if (!apiKey) {
16
- this.outputJson({
17
- error: {
18
- code: "MISSING_API_KEY",
19
- message: "Say how to log in: --email (we email you a code) or --api-key.",
20
- hint: "Run: ecomweb auth login --email you@shop.vn",
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
- const profileName = this.getFlag("profile") || this.configManager.getActiveProfileName();
27
- this.configManager.setApiKey(apiKey, profileName);
28
- if (apiUrl) {
29
- this.configManager.setProfile(profileName, { api_url: apiUrl });
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.apiClient.health();
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
- this.outputJson({
42
- message: "Credentials saved (API connection failed — verify API is running).",
43
- profile: profileName,
44
- api_url: this.configManager.getProfile(profileName).api_url,
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
- async loginWithEmail(email, apiUrl) {
50
- const profileName = this.getFlag("profile") || this.configManager.getActiveProfileName();
51
- if (apiUrl)
52
- this.configManager.setProfile(profileName, { api_url: apiUrl });
53
- const interactive = Boolean(process.stdin.isTTY && process.stderr.isTTY);
54
- const prompt = { output: process.stderr };
55
- const sameEmail = (other) => other?.trim().toLowerCase() === email.trim().toLowerCase();
56
- const kept = this.configManager.getJwtTokens(profileName);
57
- const keptSession = kept && sameEmail(kept.email) ? kept : undefined;
58
- const result = await (0, email_login_1.emailLogin)(this.apiClient, {
59
- email,
60
- code: this.getFlag("code"),
61
- session: keptSession,
62
- onSession: ({ access_token, refresh_token, expires_at }) => this.configManager.setJwtTokens({ access_token, refresh_token, expires_at, email }, profileName),
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
- storeName: this.getFlag("store-name"),
65
- keyName: `CLI (${(0, node_os_1.hostname)()})`,
66
- askStoreName: interactive
67
- ? () => {
68
- this.logToStderr("This account has no store yet: name one to create it.");
69
- return (0, prompts_1.input)({ message: "Store name:" }, prompt);
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
- if (result.status === "code_sent") {
83
- if (keptSession)
84
- this.configManager.removeJwtTokens(profileName);
85
- this.outputJson({
86
- status: "code_sent",
87
- email,
88
- hint: `Check your email, then run: ecomweb auth login --email ${email} --code <code>${this.getFlag("store-name") ? ` --store-name ${JSON.stringify(this.getFlag("store-name"))}` : ""}`,
89
- });
90
- return;
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: with --email (a code is emailed to you; no API key needed), or with --api-key";
127
+ AuthLogin.description = "Log in by approving this CLI in your browser";
106
128
  AuthLogin.examples = [
107
- "ecomweb auth login --email you@shop.vn",
108
- "ecomweb auth login --email you@shop.vn --code 123456 --store-ref abc123",
109
- "ecomweb auth login --api-url http://localhost:3001 --api-key sk_live_abc123",
110
- "ECOMWEB_API_KEY=sk_live_abc123 ecomweb auth login",
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
- email: core_1.Flags.string({ description: "Log in with a code emailed to this address" }),
115
- code: core_1.Flags.string({ description: "The emailed code (when not asked for in a terminal)" }),
116
- "store-name": core_1.Flags.string({ description: "Create a store with this name (a new merchant) and log in to it" }),
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":"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"}
1
+ {"version":3,"file":"login.js","sourceRoot":"","sources":["../../../src/commands/auth/login.ts"],"names":[],"mappings":";;;AAAA,qCAAmC;AACnC,sCAAoC;AACpC,+CAA2C;AAC3C,qDAAiD;AACjD,6CAAmD;AACnD,6CAAyD;AACzD,mDAAmD;AACnD,yDAAuG;AACvG,yDAAqD;AACrD,2DAAmF;AACnF,+CAAqE;AACrE,+DAAsE;AAGzD,QAAA,aAAa,GAAG,OAAO,CAAC;AAErC,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC,CAAC,oBAAoB,EAAE,qBAAqB,CAAC,CAAC,CAAC;AAE3E,MAAqB,SAAU,SAAQ,0BAAW;IAuBhD,KAAK,CAAC,GAAG;QACP,MAAM,OAAO,GAAG,IAAI,CAAC,WAAW,CAAC;QAEjC,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAS,SAAS,CAAC,CAAC;QACpD,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;QAC3B,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,SAAS,EAAE,CAAC;QACvC,MAAM,WAAW,GAAG,IAAI,CAAC,aAAa,EAAE,CAAC;QACzC,IAAI,CAAC,aAAa,CAAC,uBAAuB,CAAC,OAAO,CAAC,CAAC;QAEpD,MAAM,QAAQ,GAAG,IAAA,2BAAW,EAAC,wBAAe,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;QAC3E,IAAI,OAAO,GAAiB,QAAQ,IAAI,CAAC,MAAM,IAAA,gCAAiB,EAAC,GAAG,EAAE,IAAA,kBAAQ,GAAE,EAAE,MAAM,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;QACvG,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,IAAA,4BAAY,EAAC,wBAAe,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;YAChD,IAAI,IAAI,CAAC,OAAO,CAAU,SAAS,CAAC;gBAAE,IAAA,0BAAW,EAAC,OAAO,CAAC,yBAAyB,CAAC,CAAC;QACvF,CAAC;QAGD,IAAI,CAAC,WAAW,IAAI,CAAC,CAAC,IAAI,CAAC,OAAO,CAAU,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC;YAAE,OAAO,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;QAEtG,IAAI,WAAW,EAAE,CAAC;YAChB,IAAI,CAAC,WAAW,CAAC,cAAc,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC;YACpD,IAAI,CAAC,WAAW,CAAC,wBAAwB,OAAO,CAAC,yBAAyB,EAAE,CAAC,CAAC;YAC9E,IAAI,CAAC,WAAW,CAAC,yBAAyB,CAAC,CAAC;QAC9C,CAAC;QAED,MAAM,QAAQ,GAAG,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,qBAAa,CAAC,CAAC;QAC7G,IAAI,MAAiC,CAAC;QACtC,IAAI,CAAC;YACH,MAAM,GAAG,MAAM,IAAA,wBAAS,EAAC,GAAG,EAAE,OAAO,EAAE;gBACrC,QAAQ;gBACR,GAAG,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE;gBACrB,KAAK,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC7B,UAAU,EAAE,CAAC,QAAQ,EAAE,EAAE;oBACvB,OAAO,GAAG,EAAE,GAAG,OAAO,EAAE,QAAQ,EAAE,CAAC;oBACnC,IAAA,4BAAY,EAAC,wBAAe,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;gBAClD,CAAC;aACF,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAEf,IAAI,KAAK,YAAY,iBAAQ,IAAI,WAAW,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC;gBAAE,IAAA,6BAAa,EAAC,wBAAe,EAAE,OAAO,CAAC,CAAC;YAC9G,MAAM,KAAK,CAAC;QACd,CAAC;QAED,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,IAAI,CAAC,WAAW;gBAAE,OAAO,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;YACrD,IAAA,6BAAa,EAAC,wBAAe,EAAE,OAAO,CAAC,CAAC;YACxC,MAAM,IAAA,gCAAiB,GAAE,CAAC;QAC5B,CAAC;QAED,IAAA,6BAAa,EAAC,wBAAe,EAAE,OAAO,CAAC,CAAC;QACxC,MAAM,OAAO,GAAG,IAAA,2BAAiB,EAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAElD,MAAM,QAAQ,GAAG,MAAM,IAAA,wBAAY,EAAC,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,EAAE,KAAK,IAAI,EAAE;YACxE,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YAC/C,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YAIvC,IAAI,CAAC,aAAa,CAAC,UAAU,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YACpF,OAAO,QAAQ,CAAC;QAClB,CAAC,CAAC,CAAC;QAEH,IAAI,QAAQ,IAAI,QAAQ,CAAC,aAAa,KAAK,OAAO,CAAC,aAAa;YAAE,MAAM,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;QAErG,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,WAAW,CAAC,OAAO,EAAE,OAAO,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC;QAC9D,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAEf,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,IAAA,oBAAW,EAAC,KAAK,CAAC,CAAC;YAC9C,MAAM,IAAI,iBAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,2CAA2C,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,EAAE,QAAQ,EAAE;gBAC7G,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI;gBACrB,OAAO,EAAE,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE;aAC7D,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAES,aAAa;QACrB,OAAO,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,IAAI,OAAO,CAAC,MAAM,CAAC,KAAK,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IACjF,CAAC;IAEO,aAAa,CAAC,OAAqB;QACzC,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAS,SAAS,CAAC,CAAC;QAE7C,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAS,SAAS,CAAC,CAAC;QACnD,MAAM,KAAK,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,cAAc,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,UAAU,CAAC,CAAC,CAAC,cAAc,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;QACnG,IAAI,CAAC,UAAU,CAAC;YACd,MAAM,EAAE,uBAAuB;YAC/B,yBAAyB,EAAE,OAAO,CAAC,yBAAyB;YAC5D,SAAS,EAAE,OAAO,CAAC,SAAS;YAC5B,UAAU,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC;YAC7E,IAAI,EAAE,iEAAiE,KAAK,EAAE;SAC/E,CAAC,CAAC;IACL,CAAC;IAEO,KAAK,CAAC,WAAW,CAAC,OAAe,EAAE,KAAoB,EAAE,WAAoB;QACnF,MAAM,MAAM,GAAmB,CAAC,MAAM,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;QACjI,MAAM,MAAM,GAAG,MAAM,IAAA,6BAAW,EAAC;YAC/B,MAAM;YACN,QAAQ,EAAE,IAAI,CAAC,OAAO,CAAS,WAAW,CAAC;YAC3C,UAAU,EAAE,IAAI,CAAC,aAAa,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,SAAS;YAC5D,MAAM,EAAE,WAAW;gBACjB,CAAC,CAAC,CAAC,IAAI,EAAE,UAAU,EAAE,EAAE,CACnB,IAAA,gBAAM,EACJ;oBACE,OAAO,EAAE,cAAc;oBACvB,OAAO,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,GAAG,GAAG,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC;oBACtE,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,KAAK,UAAU,CAAC;iBAChD,EACD,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAC3B;gBACL,CAAC,CAAC,SAAS;SACd,CAAC,CAAC;QAEH,MAAM,IAAI,GAAG,EAAE,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;QACrD,IAAI,MAAM,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;YAC/B,IAAI,CAAC,aAAa,CAAC,WAAW,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;YAC7E,IAAI,CAAC,UAAU,CAAC,EAAE,GAAG,IAAI,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC;QACpD,CAAC;aAAM,IAAI,MAAM,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YACpC,IAAI,CAAC,UAAU,CAAC,EAAE,GAAG,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,IAAI,EAAE,kCAAkC,EAAE,CAAC,CAAC;QAC7G,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,UAAU,CAAC,EAAE,GAAG,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,8CAA8C,EAAE,CAAC,CAAC;QAClG,CAAC;IACH,CAAC;;AAhJM,qBAAW,GAAG,8CAA8C,CAAC;AAE7D,kBAAQ,GAAG;IAChB,oBAAoB;IACpB,2BAA2B;IAC3B,iCAAiC;IACjC,uCAAuC;CACxC,CAAC;AAEK,eAAK,GAAG;IACb,GAAG,0BAAW,CAAC,SAAS;IACxB,IAAI,EAAE,YAAK,CAAC,OAAO,CAAC;QAClB,WAAW,EAAE,8EAA8E;QAC3F,OAAO,EAAE,KAAK;KACf,CAAC;IACF,OAAO,EAAE,YAAK,CAAC,OAAO,CAAC;QACrB,WAAW,EAAE,qEAAqE;QAClF,OAAO,EAAE,IAAI;QACb,OAAO,EAAE,IAAI;KACd,CAAC;CACH,CAAC;kBArBiB,SAAS"}
@@ -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 profileName = this.getFlag("profile") || "default";
7
- this.configManager.removeApiKey(profileName);
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: "Credentials removed.",
10
- profile: profileName,
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 = "Clear stored API credentials";
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
  };