@ecomweb/cli 0.7.0 → 0.8.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 (76) 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/{auth/register.d.ts → stores/create.d.ts} +4 -3
  17. package/dist/commands/stores/create.js +68 -0
  18. package/dist/commands/stores/create.js.map +1 -0
  19. package/dist/commands/stores/current.js +1 -1
  20. package/dist/commands/stores/current.js.map +1 -1
  21. package/dist/commands/stores/list.js +3 -3
  22. package/dist/commands/stores/list.js.map +1 -1
  23. package/dist/commands/stores/switch.js +14 -6
  24. package/dist/commands/stores/switch.js.map +1 -1
  25. package/dist/lib/api-client.d.ts +5 -4
  26. package/dist/lib/api-client.js +32 -16
  27. package/dist/lib/api-client.js.map +1 -1
  28. package/dist/lib/codex-skill.d.ts +1 -1
  29. package/dist/lib/codex-skill.js +12 -8
  30. package/dist/lib/codex-skill.js.map +1 -1
  31. package/dist/lib/config.d.ts +6 -18
  32. package/dist/lib/config.js +35 -64
  33. package/dist/lib/config.js.map +1 -1
  34. package/dist/lib/credential-store.d.ts +44 -0
  35. package/dist/lib/credential-store.js +137 -0
  36. package/dist/lib/credential-store.js.map +1 -0
  37. package/dist/lib/device-login.d.ts +22 -0
  38. package/dist/lib/device-login.js +66 -0
  39. package/dist/lib/device-login.js.map +1 -0
  40. package/dist/lib/errors.d.ts +1 -0
  41. package/dist/lib/errors.js +6 -1
  42. package/dist/lib/errors.js.map +1 -1
  43. package/dist/lib/file-lock.d.ts +6 -0
  44. package/dist/lib/file-lock.js +66 -0
  45. package/dist/lib/file-lock.js.map +1 -0
  46. package/dist/lib/open-browser.d.ts +13 -0
  47. package/dist/lib/open-browser.js +38 -0
  48. package/dist/lib/open-browser.js.map +1 -0
  49. package/dist/lib/pending-login.d.ts +5 -0
  50. package/dist/lib/pending-login.js +39 -0
  51. package/dist/lib/pending-login.js.map +1 -0
  52. package/dist/lib/secure-file.d.ts +1 -0
  53. package/dist/lib/secure-file.js +15 -0
  54. package/dist/lib/secure-file.js.map +1 -0
  55. package/dist/lib/session.d.ts +40 -0
  56. package/dist/lib/session.js +80 -0
  57. package/dist/lib/session.js.map +1 -0
  58. package/dist/lib/store-selection.d.ts +19 -0
  59. package/dist/lib/store-selection.js +23 -0
  60. package/dist/lib/store-selection.js.map +1 -0
  61. package/oclif.manifest.json +227 -578
  62. package/package.json +2 -1
  63. package/dist/commands/auth/register.js +0 -35
  64. package/dist/commands/auth/register.js.map +0 -1
  65. package/dist/commands/auth/verify.d.ts +0 -20
  66. package/dist/commands/auth/verify.js +0 -43
  67. package/dist/commands/auth/verify.js.map +0 -1
  68. package/dist/commands/init.d.ts +0 -22
  69. package/dist/commands/init.js +0 -84
  70. package/dist/commands/init.js.map +0 -1
  71. package/dist/commands/setup.d.ts +0 -19
  72. package/dist/commands/setup.js +0 -186
  73. package/dist/commands/setup.js.map +0 -1
  74. package/dist/lib/email-login.d.ts +0 -35
  75. package/dist/lib/email-login.js +0 -86
  76. package/dist/lib/email-login.js.map +0 -1
@@ -33,13 +33,15 @@ var __importStar = (this && this.__importStar) || (function () {
33
33
  };
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.ConfigManager = void 0;
36
+ exports.ConfigManager = exports.CREDENTIALS_DIR = void 0;
37
+ exports.assertValidProfileName = assertValidProfileName;
37
38
  const fs = __importStar(require("fs"));
38
39
  const path = __importStar(require("path"));
39
40
  const os = __importStar(require("os"));
41
+ const errors_1 = require("./errors");
40
42
  const CONFIG_DIR = path.join(os.homedir(), ".config", "ecomweb");
41
43
  const CONFIG_FILE = path.join(CONFIG_DIR, "config.json");
42
- const CREDENTIALS_DIR = path.join(CONFIG_DIR, "credentials");
44
+ exports.CREDENTIALS_DIR = path.join(CONFIG_DIR, "credentials");
43
45
  const DEFAULT_PROFILE = {
44
46
  api_url: "https://apibase.ecomweb.app/api/v1",
45
47
  default_output: "json",
@@ -50,9 +52,24 @@ const DEFAULT_CONFIG = {
50
52
  default: { ...DEFAULT_PROFILE },
51
53
  },
52
54
  };
55
+ function assertValidProfileName(name, source) {
56
+ if (!/^[A-Za-z0-9._-]+$/.test(name) || name === "." || name.includes("..")) {
57
+ const allowed = "Use only letters, digits, dot, underscore and hyphen (no \"..\").";
58
+ const from = source === "flag"
59
+ ? " (from --profile)"
60
+ : source === "config"
61
+ ? ` (from active_profile in ${CONFIG_FILE})`
62
+ : "";
63
+ throw new errors_1.CliError("INVALID_PROFILE_NAME", `Invalid profile name: ${JSON.stringify(name)}${from}`, errors_1.ExitCode.VALIDATION, {
64
+ hint: source === "config" ? `${allowed} Fix active_profile in ${CONFIG_FILE}, or pass --profile default.` : allowed,
65
+ });
66
+ }
67
+ }
53
68
  class ConfigManager {
54
- constructor() {
69
+ constructor(selectedProfile) {
55
70
  this.config = this.loadConfig();
71
+ this.selected = selectedProfile || this.config.active_profile;
72
+ assertValidProfileName(this.selected, selectedProfile ? "flag" : "config");
56
73
  }
57
74
  ensureDir(dir) {
58
75
  if (!fs.existsSync(dir)) {
@@ -68,7 +85,7 @@ class ConfigManager {
68
85
  }
69
86
  catch {
70
87
  }
71
- return { ...DEFAULT_CONFIG };
88
+ return structuredClone(DEFAULT_CONFIG);
72
89
  }
73
90
  save() {
74
91
  this.ensureDir(CONFIG_DIR);
@@ -77,11 +94,15 @@ class ConfigManager {
77
94
  getActiveProfileName() {
78
95
  return this.config.active_profile;
79
96
  }
97
+ getProfileName() {
98
+ return this.selected;
99
+ }
80
100
  getProfile(name) {
81
- const profileName = name || this.config.active_profile;
101
+ const profileName = name || this.selected;
82
102
  return this.config.profiles[profileName] || { ...DEFAULT_PROFILE };
83
103
  }
84
104
  setProfile(name, profile) {
105
+ assertValidProfileName(name);
85
106
  this.config.profiles[name] = {
86
107
  ...DEFAULT_PROFILE,
87
108
  ...this.config.profiles[name],
@@ -90,11 +111,12 @@ class ConfigManager {
90
111
  this.save();
91
112
  }
92
113
  setActiveProfile(name) {
114
+ assertValidProfileName(name);
93
115
  this.config.active_profile = name;
94
116
  this.save();
95
117
  }
96
118
  setStoreRef(storeRef, storeName, profileName) {
97
- const name = profileName || this.config.active_profile;
119
+ const name = profileName || this.selected;
98
120
  const profile = this.getProfile(name);
99
121
  profile.store_ref = storeRef;
100
122
  if (storeName)
@@ -105,62 +127,6 @@ class ConfigManager {
105
127
  getStoreRef() {
106
128
  return this.getProfile().store_ref;
107
129
  }
108
- getApiKey(profileName) {
109
- const name = profileName || this.config.active_profile;
110
- const keyFile = path.join(CREDENTIALS_DIR, `${name}.key`);
111
- try {
112
- if (fs.existsSync(keyFile)) {
113
- return fs.readFileSync(keyFile, "utf-8").trim();
114
- }
115
- }
116
- catch {
117
- }
118
- return undefined;
119
- }
120
- setApiKey(key, profileName) {
121
- const name = profileName || this.config.active_profile;
122
- this.ensureDir(CREDENTIALS_DIR);
123
- const keyFile = path.join(CREDENTIALS_DIR, `${name}.key`);
124
- fs.writeFileSync(keyFile, key, { mode: 0o600 });
125
- }
126
- removeApiKey(profileName) {
127
- const name = profileName || this.config.active_profile;
128
- const keyFile = path.join(CREDENTIALS_DIR, `${name}.key`);
129
- if (fs.existsSync(keyFile)) {
130
- fs.unlinkSync(keyFile);
131
- }
132
- }
133
- getJwtTokens(profileName) {
134
- const name = profileName || this.config.active_profile;
135
- const tokenFile = path.join(CREDENTIALS_DIR, `${name}.jwt`);
136
- try {
137
- if (fs.existsSync(tokenFile)) {
138
- return JSON.parse(fs.readFileSync(tokenFile, "utf-8"));
139
- }
140
- }
141
- catch {
142
- }
143
- return undefined;
144
- }
145
- setJwtTokens(tokens, profileName) {
146
- const name = profileName || this.config.active_profile;
147
- this.ensureDir(CREDENTIALS_DIR);
148
- const tokenFile = path.join(CREDENTIALS_DIR, `${name}.jwt`);
149
- fs.writeFileSync(tokenFile, JSON.stringify(tokens), { mode: 0o600 });
150
- }
151
- removeJwtTokens(profileName) {
152
- const name = profileName || this.config.active_profile;
153
- const tokenFile = path.join(CREDENTIALS_DIR, `${name}.jwt`);
154
- if (fs.existsSync(tokenFile)) {
155
- fs.unlinkSync(tokenFile);
156
- }
157
- }
158
- isJwtExpired(profileName) {
159
- const tokens = this.getJwtTokens(profileName);
160
- if (!tokens)
161
- return true;
162
- return Date.now() / 1000 >= tokens.expires_at - 60;
163
- }
164
130
  getProfileNames() {
165
131
  return Object.keys(this.config.profiles);
166
132
  }
@@ -170,7 +136,7 @@ class ConfigManager {
170
136
  this.config.active_profile = "default";
171
137
  }
172
138
  this.save();
173
- this.removeApiKey(name);
139
+ this.removeLegacyCredentials(name);
174
140
  }
175
141
  resolve(flag, envVar, profileValue, defaultValue) {
176
142
  if (flag !== undefined)
@@ -186,7 +152,12 @@ class ConfigManager {
186
152
  return this.resolve(flag, "ECOMWEB_API_URL", this.getProfile().api_url, "https://apibase.ecomweb.app/api/v1");
187
153
  }
188
154
  resolveApiKey(flag) {
189
- return this.resolve(flag, "ECOMWEB_API_KEY", this.getApiKey(), undefined);
155
+ return this.resolve(flag, "ECOMWEB_API_KEY", undefined, undefined);
156
+ }
157
+ removeLegacyCredentials(profileName) {
158
+ for (const ext of ["key", "jwt"]) {
159
+ fs.rmSync(path.join(exports.CREDENTIALS_DIR, `${profileName}.${ext}`), { force: true });
160
+ }
190
161
  }
191
162
  resolveStoreRef(flag) {
192
163
  const envVal = process.env["ECOMWEB_STORE_REF"];
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,44 @@
1
+ export interface StoredSession {
2
+ access_token: string;
3
+ refresh_token: string;
4
+ expires_at: number;
5
+ email: string | null;
6
+ user_id: string;
7
+ api_url?: string;
8
+ }
9
+ export interface CredentialStore {
10
+ readonly kind: "keychain" | "file";
11
+ get(profile: string): StoredSession | undefined;
12
+ set(profile: string, session: StoredSession): void;
13
+ delete(profile: string): void;
14
+ }
15
+ export declare const KEYCHAIN_SERVICE = "ecomweb-cli";
16
+ export interface KeyringEntry {
17
+ getPassword(): string | null;
18
+ setPassword(password: string): void;
19
+ deletePassword(): boolean;
20
+ }
21
+ export type EntryFactory = (service: string, account: string) => KeyringEntry;
22
+ export declare class FileCredentialStore implements CredentialStore {
23
+ private readonly dir;
24
+ readonly kind: "file";
25
+ constructor(dir: string);
26
+ private file;
27
+ get(profile: string): StoredSession | undefined;
28
+ set(profile: string, session: StoredSession): void;
29
+ delete(profile: string): void;
30
+ }
31
+ export declare class KeychainCredentialStore implements CredentialStore {
32
+ private readonly entry;
33
+ readonly kind: "keychain";
34
+ constructor(entry: EntryFactory);
35
+ get(profile: string): StoredSession | undefined;
36
+ set(profile: string, session: StoredSession): void;
37
+ delete(profile: string): void;
38
+ }
39
+ export declare function openCredentialStore(opts: {
40
+ dir: string;
41
+ env?: NodeJS.ProcessEnv;
42
+ loadEntry?: () => EntryFactory;
43
+ }): CredentialStore;
44
+ export declare function lazyCredentialStore(open: () => CredentialStore): CredentialStore;
@@ -0,0 +1,137 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.KeychainCredentialStore = exports.FileCredentialStore = exports.KEYCHAIN_SERVICE = void 0;
7
+ exports.openCredentialStore = openCredentialStore;
8
+ exports.lazyCredentialStore = lazyCredentialStore;
9
+ const node_fs_1 = require("node:fs");
10
+ const node_path_1 = __importDefault(require("node:path"));
11
+ const errors_1 = require("./errors");
12
+ const secure_file_1 = require("./secure-file");
13
+ exports.KEYCHAIN_SERVICE = "ecomweb-cli";
14
+ function parseSession(raw) {
15
+ try {
16
+ const s = JSON.parse(raw);
17
+ if (typeof s?.access_token === "string" &&
18
+ typeof s.refresh_token === "string" &&
19
+ typeof s.expires_at === "number" &&
20
+ typeof s.user_id === "string") {
21
+ return {
22
+ access_token: s.access_token,
23
+ refresh_token: s.refresh_token,
24
+ expires_at: s.expires_at,
25
+ email: s.email ?? null,
26
+ user_id: s.user_id,
27
+ ...(typeof s.api_url === "string" && { api_url: s.api_url }),
28
+ };
29
+ }
30
+ }
31
+ catch {
32
+ }
33
+ return undefined;
34
+ }
35
+ class FileCredentialStore {
36
+ constructor(dir) {
37
+ this.dir = dir;
38
+ this.kind = "file";
39
+ }
40
+ file(profile) {
41
+ return node_path_1.default.join(this.dir, `${profile}.session.json`);
42
+ }
43
+ get(profile) {
44
+ try {
45
+ return parseSession((0, node_fs_1.readFileSync)(this.file(profile), "utf8"));
46
+ }
47
+ catch {
48
+ return undefined;
49
+ }
50
+ }
51
+ set(profile, session) {
52
+ (0, secure_file_1.writePrivateFile)(this.file(profile), JSON.stringify(session));
53
+ }
54
+ delete(profile) {
55
+ (0, node_fs_1.rmSync)(this.file(profile), { force: true });
56
+ }
57
+ }
58
+ exports.FileCredentialStore = FileCredentialStore;
59
+ function keychainRefused(error) {
60
+ return new errors_1.CliError("CREDENTIAL_STORE_UNAVAILABLE", `The OS keychain refused access: ${error instanceof Error ? error.message : String(error)}`, errors_1.ExitCode.AUTH_FAILURE, { hint: "Unlock the keychain, or keep the login in a file instead: export ECOMWEB_CREDENTIAL_STORE=file" });
61
+ }
62
+ class KeychainCredentialStore {
63
+ constructor(entry) {
64
+ this.entry = entry;
65
+ this.kind = "keychain";
66
+ }
67
+ get(profile) {
68
+ let raw;
69
+ try {
70
+ raw = this.entry(exports.KEYCHAIN_SERVICE, profile).getPassword();
71
+ }
72
+ catch (error) {
73
+ throw keychainRefused(error);
74
+ }
75
+ return raw ? parseSession(raw) : undefined;
76
+ }
77
+ set(profile, session) {
78
+ try {
79
+ this.entry(exports.KEYCHAIN_SERVICE, profile).setPassword(JSON.stringify(session));
80
+ }
81
+ catch (error) {
82
+ throw keychainRefused(error);
83
+ }
84
+ }
85
+ delete(profile) {
86
+ try {
87
+ this.entry(exports.KEYCHAIN_SERVICE, profile).deletePassword();
88
+ }
89
+ catch {
90
+ }
91
+ }
92
+ }
93
+ exports.KeychainCredentialStore = KeychainCredentialStore;
94
+ function loadNapiKeyring() {
95
+ const { Entry } = require("@napi-rs/keyring");
96
+ return (service, account) => new Entry(service, account);
97
+ }
98
+ function probeKeychain(load) {
99
+ try {
100
+ const entry = load();
101
+ entry(exports.KEYCHAIN_SERVICE, "__probe__").getPassword();
102
+ return entry;
103
+ }
104
+ catch {
105
+ return undefined;
106
+ }
107
+ }
108
+ function openCredentialStore(opts) {
109
+ const forced = (opts.env ?? process.env).ECOMWEB_CREDENTIAL_STORE;
110
+ if (forced !== undefined && forced !== "file" && forced !== "keychain") {
111
+ throw new errors_1.CliError("INVALID_CREDENTIAL_STORE", `ECOMWEB_CREDENTIAL_STORE must be "file" or "keychain", not "${forced}"`, errors_1.ExitCode.VALIDATION);
112
+ }
113
+ if (forced === "file")
114
+ return new FileCredentialStore(opts.dir);
115
+ const entry = probeKeychain(opts.loadEntry ?? loadNapiKeyring);
116
+ if (entry)
117
+ return new KeychainCredentialStore(entry);
118
+ if (forced === "keychain") {
119
+ throw new errors_1.CliError("KEYCHAIN_UNAVAILABLE", "No OS keychain is available on this machine", errors_1.ExitCode.ERROR, {
120
+ hint: "Unset ECOMWEB_CREDENTIAL_STORE to keep the login in a file instead",
121
+ });
122
+ }
123
+ return new FileCredentialStore(opts.dir);
124
+ }
125
+ function lazyCredentialStore(open) {
126
+ let inner;
127
+ const store = () => (inner ??= open());
128
+ return {
129
+ get kind() {
130
+ return store().kind;
131
+ },
132
+ get: (profile) => store().get(profile),
133
+ set: (profile, session) => store().set(profile, session),
134
+ delete: (profile) => store().delete(profile),
135
+ };
136
+ }
137
+ //# sourceMappingURL=credential-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"credential-store.js","sourceRoot":"","sources":["../../src/lib/credential-store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ import { CliError } from "./errors";
2
+ import { TokenResponse } from "./session";
3
+ export interface PendingLogin {
4
+ device_code: string;
5
+ user_code: string;
6
+ verification_uri_complete: string;
7
+ interval: number;
8
+ expires_at: number;
9
+ api_url: string;
10
+ }
11
+ export interface DevicePoster {
12
+ post<T = any>(path: string, body?: unknown): Promise<T>;
13
+ }
14
+ export declare function deviceAuthExpired(): CliError;
15
+ export declare function deviceAuthDenied(): CliError;
16
+ export declare function requestDeviceCode(api: DevicePoster, deviceName: string, apiUrl: string, now: number): Promise<PendingLogin>;
17
+ export declare function pollUntil(api: DevicePoster, pending: PendingLogin, opts: {
18
+ deadline: number;
19
+ now: () => number;
20
+ sleep: (ms: number) => Promise<void>;
21
+ onInterval?: (interval: number) => void;
22
+ }): Promise<TokenResponse | undefined>;
@@ -0,0 +1,66 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.deviceAuthExpired = deviceAuthExpired;
4
+ exports.deviceAuthDenied = deviceAuthDenied;
5
+ exports.requestDeviceCode = requestDeviceCode;
6
+ exports.pollUntil = pollUntil;
7
+ const errors_1 = require("./errors");
8
+ function deviceAuthExpired() {
9
+ return new errors_1.CliError("DEVICE_AUTH_EXPIRED", "The sign-in code expired before it was approved", errors_1.ExitCode.AUTH_FAILURE, {
10
+ hint: "Run: ecomweb auth login",
11
+ });
12
+ }
13
+ function deviceAuthDenied() {
14
+ return new errors_1.CliError("DEVICE_AUTH_DENIED", "The sign-in was denied in the browser", errors_1.ExitCode.AUTH_FAILURE, {
15
+ hint: "Run: ecomweb auth login",
16
+ });
17
+ }
18
+ async function requestDeviceCode(api, deviceName, apiUrl, now) {
19
+ const r = await api.post("/auth/device/code", { device_name: deviceName.slice(0, 100) });
20
+ return {
21
+ device_code: r.device_code,
22
+ user_code: r.user_code,
23
+ verification_uri_complete: r.verification_uri_complete,
24
+ interval: r.interval,
25
+ expires_at: now + r.expires_in * 1000,
26
+ api_url: apiUrl,
27
+ };
28
+ }
29
+ async function pollOnce(api, deviceCode, interval) {
30
+ try {
31
+ return { status: "approved", tokens: await api.post("/auth/device/token", { device_code: deviceCode }) };
32
+ }
33
+ catch (error) {
34
+ switch ((0, errors_1.apiErrorCode)(error)) {
35
+ case "DEVICE_AUTH_PENDING":
36
+ return { status: "pending", interval };
37
+ case "DEVICE_AUTH_SLOW_DOWN":
38
+ return { status: "pending", interval: interval + 5 };
39
+ case "DEVICE_AUTH_DENIED":
40
+ throw deviceAuthDenied();
41
+ case "DEVICE_AUTH_EXPIRED":
42
+ case "DEVICE_AUTH_INVALID_CODE":
43
+ throw deviceAuthExpired();
44
+ default:
45
+ throw error;
46
+ }
47
+ }
48
+ }
49
+ async function pollUntil(api, pending, opts) {
50
+ let interval = pending.interval;
51
+ for (;;) {
52
+ if (opts.now() >= pending.expires_at)
53
+ throw deviceAuthExpired();
54
+ const outcome = await pollOnce(api, pending.device_code, interval);
55
+ if (outcome.status === "approved")
56
+ return outcome.tokens;
57
+ if (outcome.interval !== interval) {
58
+ interval = outcome.interval;
59
+ opts.onInterval?.(interval);
60
+ }
61
+ if (opts.now() + interval * 1000 > opts.deadline)
62
+ return undefined;
63
+ await opts.sleep(interval * 1000);
64
+ }
65
+ }
66
+ //# sourceMappingURL=device-login.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"device-login.js","sourceRoot":"","sources":["../../src/lib/device-login.ts"],"names":[],"mappings":"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"}
@@ -30,3 +30,4 @@ export declare function formatError(error: unknown): {
30
30
  };
31
31
  exitCode: ExitCode;
32
32
  };
33
+ export declare function apiErrorCode(error: unknown): string | undefined;
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.CliError = exports.ExitCode = void 0;
4
4
  exports.formatError = formatError;
5
+ exports.apiErrorCode = apiErrorCode;
5
6
  var ExitCode;
6
7
  (function (ExitCode) {
7
8
  ExitCode[ExitCode["SUCCESS"] = 0] = "SUCCESS";
@@ -67,7 +68,7 @@ function mapHttpError(err) {
67
68
  error: {
68
69
  code: "FORBIDDEN",
69
70
  message: serverMessage || "Insufficient permissions.",
70
- hint: "Check your API key scopes.",
71
+ hint: "Your role in this store (or your API key's scopes) does not allow this.",
71
72
  },
72
73
  },
73
74
  exitCode: ExitCode.AUTH_FAILURE,
@@ -115,4 +116,8 @@ function mapHttpError(err) {
115
116
  };
116
117
  }
117
118
  }
119
+ function apiErrorCode(error) {
120
+ const code = error?.response?.data?.code;
121
+ return typeof code === "string" ? code : undefined;
122
+ }
118
123
  //# sourceMappingURL=errors.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/lib/errors.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/lib/errors.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ export interface FileLockOptions {
2
+ staleMs?: number;
3
+ timeoutMs?: number;
4
+ pollMs?: number;
5
+ }
6
+ export declare function withFileLock<T>(lockPath: string, fn: () => Promise<T>, opts?: FileLockOptions): Promise<T>;
@@ -0,0 +1,66 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.withFileLock = withFileLock;
7
+ const node_crypto_1 = require("node:crypto");
8
+ const node_fs_1 = require("node:fs");
9
+ const node_path_1 = __importDefault(require("node:path"));
10
+ const errors_1 = require("./errors");
11
+ function isStale(lockPath, staleMs) {
12
+ try {
13
+ return Date.now() - (0, node_fs_1.statSync)(lockPath).mtimeMs > staleMs;
14
+ }
15
+ catch {
16
+ return false;
17
+ }
18
+ }
19
+ function release(lockPath, token) {
20
+ let content;
21
+ try {
22
+ content = (0, node_fs_1.readFileSync)(lockPath, "utf8");
23
+ }
24
+ catch {
25
+ return;
26
+ }
27
+ if (content.includes(token))
28
+ (0, node_fs_1.rmSync)(lockPath, { force: true });
29
+ }
30
+ async function withFileLock(lockPath, fn, opts = {}) {
31
+ const staleMs = opts.staleMs ?? 30_000;
32
+ const timeoutMs = opts.timeoutMs ?? 10_000;
33
+ const pollMs = opts.pollMs ?? 100;
34
+ (0, node_fs_1.mkdirSync)(node_path_1.default.dirname(lockPath), { recursive: true, mode: 0o700 });
35
+ const token = (0, node_crypto_1.randomBytes)(16).toString("hex");
36
+ const deadline = Date.now() + timeoutMs;
37
+ let fd;
38
+ while (fd === undefined) {
39
+ try {
40
+ fd = (0, node_fs_1.openSync)(lockPath, "wx", 0o600);
41
+ }
42
+ catch (error) {
43
+ if (error.code !== "EEXIST")
44
+ throw error;
45
+ if (isStale(lockPath, staleMs)) {
46
+ (0, node_fs_1.rmSync)(lockPath, { force: true });
47
+ continue;
48
+ }
49
+ if (Date.now() >= deadline) {
50
+ throw new errors_1.CliError("CREDENTIAL_LOCK_TIMEOUT", `Another ecomweb command is holding ${lockPath}`, errors_1.ExitCode.ERROR, {
51
+ hint: `If no other ecomweb command is running, delete ${lockPath}`,
52
+ });
53
+ }
54
+ await new Promise((r) => setTimeout(r, pollMs));
55
+ }
56
+ }
57
+ try {
58
+ (0, node_fs_1.writeSync)(fd, `${process.pid} ${new Date().toISOString()} ${token}\n`);
59
+ return await fn();
60
+ }
61
+ finally {
62
+ (0, node_fs_1.closeSync)(fd);
63
+ release(lockPath, token);
64
+ }
65
+ }
66
+ //# sourceMappingURL=file-lock.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-lock.js","sourceRoot":"","sources":["../../src/lib/file-lock.ts"],"names":[],"mappings":";;;;;AAoCA,oCA2CC;AA/ED,6CAA0C;AAC1C,qCAAoG;AACpG,0DAA6B;AAC7B,qCAA8C;AAS9C,SAAS,OAAO,CAAC,QAAgB,EAAE,OAAe;IAChD,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,IAAA,kBAAQ,EAAC,QAAQ,CAAC,CAAC,OAAO,GAAG,OAAO,CAAC;IAC3D,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAGD,SAAS,OAAO,CAAC,QAAgB,EAAE,KAAa;IAC9C,IAAI,OAAe,CAAC;IACpB,IAAI,CAAC;QACH,OAAO,GAAG,IAAA,sBAAY,EAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IAC3C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO;IACT,CAAC;IACD,IAAI,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,IAAA,gBAAM,EAAC,QAAQ,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;AACjE,CAAC;AAOM,KAAK,UAAU,YAAY,CAAI,QAAgB,EAAE,EAAoB,EAAE,OAAwB,EAAE;IACtG,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,MAAM,CAAC;IACvC,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,IAAI,MAAM,CAAC;IAC3C,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,GAAG,CAAC;IAClC,IAAA,mBAAS,EAAC,mBAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IAGpE,MAAM,KAAK,GAAG,IAAA,yBAAW,EAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC9C,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC;IACxC,IAAI,EAAsB,CAAC;IAC3B,OAAO,EAAE,KAAK,SAAS,EAAE,CAAC;QACxB,IAAI,CAAC;YACH,EAAE,GAAG,IAAA,kBAAQ,EAAC,QAAQ,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;QACvC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAK,KAA+B,CAAC,IAAI,KAAK,QAAQ;gBAAE,MAAM,KAAK,CAAC;YACpE,IAAI,OAAO,CAAC,QAAQ,EAAE,OAAO,CAAC,EAAE,CAAC;gBAC/B,IAAA,gBAAM,EAAC,QAAQ,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;gBAClC,SAAS;YACX,CAAC;YACD,IAAI,IAAI,CAAC,GAAG,EAAE,IAAI,QAAQ,EAAE,CAAC;gBAC3B,MAAM,IAAI,iBAAQ,CAAC,yBAAyB,EAAE,sCAAsC,QAAQ,EAAE,EAAE,iBAAQ,CAAC,KAAK,EAAE;oBAC9G,IAAI,EAAE,kDAAkD,QAAQ,EAAE;iBACnE,CAAC,CAAC;YACL,CAAC;YACD,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;QAClD,CAAC;IACH,CAAC;IAED,IAAI,CAAC;QACH,IAAA,mBAAS,EAAC,EAAE,EAAE,GAAG,OAAO,CAAC,GAAG,IAAI,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,IAAI,KAAK,IAAI,CAAC,CAAC;QACvE,OAAO,MAAM,EAAE,EAAE,CAAC;IACpB,CAAC;YAAS,CAAC;QACT,IAAA,mBAAS,EAAC,EAAE,CAAC,CAAC;QASd,OAAO,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;IAC3B,CAAC;AACH,CAAC"}
@@ -0,0 +1,13 @@
1
+ type SpawnLike = (command: string, args: string[], options: {
2
+ detached: boolean;
3
+ stdio: "ignore";
4
+ }) => {
5
+ on(event: "error", listener: () => void): unknown;
6
+ unref(): void;
7
+ };
8
+ export declare function openBrowser(url: string, deps?: {
9
+ platform?: NodeJS.Platform;
10
+ env?: NodeJS.ProcessEnv;
11
+ spawn?: SpawnLike;
12
+ }): boolean;
13
+ export {};