faces-cli 1.5.9 → 1.5.11

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.
@@ -18,12 +18,8 @@ export default class AuthWhoami extends BaseCommand {
18
18
  api_key_configured: Boolean(apiKey),
19
19
  api_key_prefix: apiKey ? apiKey.slice(0, 12) + '...' : null,
20
20
  };
21
- // Try API key first (priority), then JWT
22
- const credential = apiKey || token;
23
- const method = apiKey ? 'api_key' : token ? 'jwt' : null;
24
- if (!credential) {
21
+ if (!apiKey && !token) {
25
22
  diag.authenticated = false;
26
- diag.auth_method = null;
27
23
  diag.error = 'No credentials configured (no API key, no JWT)';
28
24
  if (!json) {
29
25
  process.stderr.write('Auth diagnostic:\n');
@@ -32,59 +28,80 @@ export default class AuthWhoami extends BaseCommand {
32
28
  process.stderr.write(` api_key: not configured\n`);
33
29
  process.stderr.write(` status: not authenticated\n`);
34
30
  }
35
- return diag;
31
+ if (json)
32
+ process.stdout.write(JSON.stringify(diag) + '\n');
33
+ process.exit(1);
36
34
  }
37
- const client = new FacesClient(baseUrl, token, apiKey);
38
- try {
39
- const data = await client.get('/auth/me');
40
- const inner = (data.data ?? data);
41
- diag.authenticated = true;
42
- diag.auth_method = method;
43
- diag.user_id = inner.user_id;
44
- diag.username = inner.username;
45
- diag.email = inner.email;
46
- diag.name = inner.name;
47
- diag.is_admin = inner.is_admin;
48
- if (!json) {
49
- process.stderr.write('Auth diagnostic:\n');
50
- process.stderr.write(` base_url: ${baseUrl}\n`);
51
- process.stderr.write(` jwt: ${token ? 'configured' : 'not configured'}\n`);
52
- process.stderr.write(` api_key: ${apiKey ? diag.api_key_prefix : 'not configured'}\n`);
53
- process.stderr.write(` auth_method: ${method}\n`);
54
- process.stderr.write(` status: authenticated\n`);
55
- process.stderr.write('\n');
56
- process.stderr.write(` user_id: ${inner.user_id}\n`);
57
- process.stderr.write(` username: ${inner.username}\n`);
58
- process.stderr.write(` email: ${inner.email}\n`);
59
- process.stderr.write(` name: ${inner.name}\n`);
35
+ // Try API key first (priority), then JWT. Always try both and report.
36
+ let apiKeyResult = null;
37
+ let jwtResult = null;
38
+ if (apiKey) {
39
+ const client = new FacesClient(baseUrl, undefined, apiKey);
40
+ try {
41
+ const data = await client.get('/auth/me');
42
+ apiKeyResult = { ok: true, data: (data.data ?? data) };
60
43
  }
61
- return diag;
62
- }
63
- catch (err) {
64
- const errMsg = err instanceof FacesAPIError ? `${err.statusCode}: ${err.message}` : String(err);
65
- diag.authenticated = false;
66
- diag.auth_method = method;
67
- diag.error = errMsg;
68
- // If API key failed, also report JWT state
69
- if (method === 'api_key' && token) {
70
- diag.jwt_status = 'configured but not tried (API key takes priority)';
44
+ catch (err) {
45
+ const msg = err instanceof FacesAPIError ? `${err.statusCode}: ${err.message}` : String(err);
46
+ apiKeyResult = { ok: false, error: msg };
71
47
  }
72
- if (method === 'jwt') {
73
- diag.jwt_status = 'failed';
74
- if (apiKey) {
75
- diag.api_key_status = 'configured but not valid for this endpoint';
48
+ }
49
+ if (token) {
50
+ // Only try JWT if API key failed or wasn't configured
51
+ if (!apiKeyResult?.ok) {
52
+ const client = new FacesClient(baseUrl, token, undefined);
53
+ try {
54
+ const data = await client.get('/auth/me');
55
+ jwtResult = { ok: true, data: (data.data ?? data) };
56
+ }
57
+ catch (err) {
58
+ const msg = err instanceof FacesAPIError ? `${err.statusCode}: ${err.message}` : String(err);
59
+ jwtResult = { ok: false, error: msg };
76
60
  }
77
61
  }
78
- if (!json) {
79
- process.stderr.write('Auth diagnostic:\n');
80
- process.stderr.write(` base_url: ${baseUrl}\n`);
81
- process.stderr.write(` jwt: ${token ? 'configured' : 'not configured'}\n`);
82
- process.stderr.write(` api_key: ${apiKey ? diag.api_key_prefix : 'not configured'}\n`);
83
- process.stderr.write(` auth_method: ${method}\n`);
84
- process.stderr.write(` status: failed\n`);
85
- process.stderr.write(` error: ${errMsg}\n`);
62
+ else {
63
+ jwtResult = { ok: false, error: 'not tried (API key succeeded)' };
64
+ }
65
+ }
66
+ // Determine the winning result
67
+ const winner = apiKeyResult?.ok ? apiKeyResult : jwtResult?.ok ? jwtResult : null;
68
+ const winnerMethod = apiKeyResult?.ok ? 'api_key' : jwtResult?.ok ? 'jwt' : null;
69
+ diag.authenticated = Boolean(winner);
70
+ diag.auth_method = winnerMethod;
71
+ if (apiKeyResult)
72
+ diag.api_key_status = apiKeyResult.ok ? 'valid' : apiKeyResult.error;
73
+ if (jwtResult)
74
+ diag.jwt_status = jwtResult.ok ? 'valid' : jwtResult.error;
75
+ if (winner?.data) {
76
+ diag.user_id = winner.data.user_id;
77
+ diag.username = winner.data.username;
78
+ diag.email = winner.data.email;
79
+ diag.name = winner.data.name;
80
+ diag.is_admin = winner.data.is_admin;
81
+ }
82
+ else {
83
+ diag.error = 'All credentials failed';
84
+ }
85
+ if (!json) {
86
+ process.stderr.write('Auth diagnostic:\n');
87
+ process.stderr.write(` base_url: ${baseUrl}\n`);
88
+ process.stderr.write(` jwt: ${token ? (jwtResult?.ok ? 'valid' : `failed (${jwtResult?.error})`) : 'not configured'}\n`);
89
+ process.stderr.write(` api_key: ${apiKey ? (apiKeyResult?.ok ? `valid (${diag.api_key_prefix})` : `failed (${apiKeyResult?.error})`) : 'not configured'}\n`);
90
+ process.stderr.write(` auth_method: ${winnerMethod ?? 'none'}\n`);
91
+ process.stderr.write(` status: ${winner ? 'authenticated' : 'failed'}\n`);
92
+ if (winner?.data) {
93
+ process.stderr.write('\n');
94
+ process.stderr.write(` user_id: ${winner.data.user_id}\n`);
95
+ process.stderr.write(` username: ${winner.data.username}\n`);
96
+ process.stderr.write(` email: ${winner.data.email}\n`);
97
+ process.stderr.write(` name: ${winner.data.name}\n`);
86
98
  }
87
- return diag;
88
99
  }
100
+ if (!diag.authenticated) {
101
+ if (json)
102
+ process.stdout.write(JSON.stringify(diag) + '\n');
103
+ process.exit(1);
104
+ }
105
+ return diag;
89
106
  }
90
107
  }
package/dist/config.js CHANGED
@@ -50,16 +50,20 @@ export function resolveBaseUrl(override) {
50
50
  return 'https://api.faces.sh';
51
51
  }
52
52
  export function resolveToken(override) {
53
- if (override)
54
- return override;
55
- if (process.env.FACES_TOKEN)
56
- return process.env.FACES_TOKEN;
57
- return loadConfig().token;
53
+ // Empty string override means "no token" — don't fall back to config/env
54
+ if (override !== undefined)
55
+ return override || undefined;
56
+ const env = process.env.FACES_TOKEN;
57
+ if (env)
58
+ return env;
59
+ return loadConfig().token || undefined;
58
60
  }
59
61
  export function resolveApiKey(override) {
60
- if (override)
61
- return override;
62
- if (process.env.FACES_API_KEY)
63
- return process.env.FACES_API_KEY;
64
- return loadConfig().api_key;
62
+ // Empty string override means "no API key" — don't fall back to config/env
63
+ if (override !== undefined)
64
+ return override || undefined;
65
+ const env = process.env.FACES_API_KEY;
66
+ if (env)
67
+ return env;
68
+ return loadConfig().api_key || undefined;
65
69
  }