@metaplay/metaplay-auth 1.7.1 → 1.7.2

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/index.ts CHANGED
@@ -107,10 +107,7 @@ async function fetchManagedEnvironmentInfoWithSlugs(
107
107
  })
108
108
 
109
109
  // Throw on server errors (eg, forbidden)
110
- if (!response.ok) {
111
- const errorData = await response.json()
112
- throw new Error(`Failed to fetch environment details with error ${response.status}: ${JSON.stringify(errorData)}`)
113
- }
110
+ await checkEnvironmentInfoResponseError(response)
114
111
 
115
112
  // \todo Validate response?
116
113
  const portalEnvInfo = (await response.json()) as PortalEnvironmentInfo
@@ -130,20 +127,30 @@ async function fetchManageEnvironmentInfoWithHumanId(tokens: TokenSet, humanId:
130
127
  })
131
128
 
132
129
  // Throw on server errors (eg, forbidden)
133
- if (!response.ok) {
134
- const errorData = await response.json()
135
- throw new Error(`Failed to fetch environment details with error ${response.status}: ${JSON.stringify(errorData)}`)
136
- }
130
+ await checkEnvironmentInfoResponseError(response)
137
131
 
138
132
  // Return the result
139
133
  const portalEnvInfos = (await response.json()) as PortalEnvironmentInfo[]
140
134
  logger.debug(`Portal returned environment infos: ${JSON.stringify(portalEnvInfos, undefined, 2)}`)
141
135
  if (portalEnvInfos.length === 0) {
142
- throw new Error(`Failed to fetch details from portal for environment ${humanId}: no matching environment found`)
136
+ throw new Error(`Environment ${humanId} does not exist or your account does not have permissions to access this environment`)
143
137
  }
144
138
  return portalEnvInfos[0]
145
139
  }
146
140
 
141
+ async function checkEnvironmentInfoResponseError(response: Response): Promise<void> {
142
+ // Throw on server errors (eg, forbidden)
143
+ // Portal returns a helpful error message in 'message' field.
144
+ if (!response.ok) {
145
+ const errorData = await response.json()
146
+ if (typeof(errorData) === 'object' && errorData !== null && 'message' in errorData && typeof(errorData.message) === 'string') {
147
+ throw new Error(errorData.message)
148
+ } else {
149
+ throw new Error(`Failed to fetch environment details with error ${response.status}: ${JSON.stringify(errorData)}`)
150
+ }
151
+ }
152
+ }
153
+
147
154
  /**
148
155
  * Resolve the target environment based on (org, proj, env) tuple. We fetch the information
149
156
  * from the portal and then construct the `TargetEnvironment` class with the required information
@@ -251,8 +258,10 @@ program
251
258
  }
252
259
 
253
260
  // Store the portal base URL for accessing globally
254
- if (opts.portalBaseUrl) {
255
- setPortalBaseUrl(opts.portalBaseUrl as string)
261
+ const overridePortalUrl: string | undefined = opts.portalBaseUrl ?? process.env.AUTHCLI_PORTAL_BASEURL
262
+ if (overridePortalUrl) {
263
+ logger.debug(`Using portal URL override: ${overridePortalUrl}`)
264
+ setPortalBaseUrl(overridePortalUrl)
256
265
  }
257
266
 
258
267
  // Store the stack API base URL for accessing globally
@@ -309,6 +318,7 @@ program
309
318
  await removeTokens()
310
319
  console.log('Done! You are now logged out.')
311
320
  } catch (error) {
321
+ logger.debug('Invocation failed with error:', error)
312
322
  if (error instanceof Error) {
313
323
  console.error(`Error logging out: ${error.message}`)
314
324
  }
@@ -328,6 +338,7 @@ program
328
338
  const tokens = await loadTokens()
329
339
  console.log(JSON.stringify(tokens, undefined, 2))
330
340
  } catch (error) {
341
+ logger.debug('Invocation failed with error:', error)
331
342
  if (error instanceof Error) {
332
343
  console.error(`Error showing tokens: ${error.message}`)
333
344
  }
@@ -381,8 +392,9 @@ program
381
392
  console.log(kubeconfigPayload)
382
393
  }
383
394
  } catch (error) {
395
+ logger.debug('Invocation failed with error:', error)
384
396
  if (error instanceof Error) {
385
- console.error('Error getting KubeConfig:', error)
397
+ console.error('Error getting KubeConfig:', error.message)
386
398
  }
387
399
  exit(1)
388
400
  }
@@ -417,6 +429,7 @@ program
417
429
  const credentials = await targetEnv.getKubeExecCredential()
418
430
  console.log(credentials)
419
431
  } catch (error) {
432
+ logger.debug('Invocation failed with error:', error)
420
433
  if (error instanceof Error) {
421
434
  console.error(`Error getting Kubernetes ExecCredential: ${error.message}`)
422
435
  }
@@ -464,6 +477,7 @@ program
464
477
  )
465
478
  }
466
479
  } catch (error) {
480
+ logger.debug('Invocation failed with error:', error)
467
481
  if (error instanceof Error) {
468
482
  console.error(`Error getting AWS credentials: ${error.message}`)
469
483
  }
@@ -522,6 +536,7 @@ program
522
536
  )
523
537
  }
524
538
  } catch (error) {
539
+ logger.debug('Invocation failed with error:', error)
525
540
  if (error instanceof Error) {
526
541
  console.error(`Error getting docker login credentials: ${error.message}`)
527
542
  }
@@ -551,6 +566,7 @@ program
551
566
  const environment = await targetEnv.getEnvironmentDetails()
552
567
  console.log(JSON.stringify(environment, undefined, 2))
553
568
  } catch (error) {
569
+ logger.debug('Invocation failed with error:', error)
554
570
  if (error instanceof Error) {
555
571
  console.error(`Error getting environment details: ${error.message}`)
556
572
  }
@@ -644,6 +660,7 @@ program
644
660
 
645
661
  console.log(`Successfully pushed docker image to ${dstImageName}!`)
646
662
  } catch (error) {
663
+ logger.debug('Invocation failed with error:', error)
647
664
  if (error instanceof Error) {
648
665
  console.error(`Failed to push docker image: ${error.message}`)
649
666
  }
@@ -886,11 +903,13 @@ program
886
903
  console.log('Validating game server deployment...')
887
904
  await checkGameServerDeployment(envInfo, kubeconfig, imageTag)
888
905
  } catch (error) {
906
+ logger.debug('Invocation failed with error:', error)
889
907
  const errMessage = error instanceof Error ? error.message : String(error)
890
908
  console.error(`Failed to resolve game server deployment status: ${errMessage}`)
891
909
  exit(2)
892
910
  }
893
911
  } catch (error) {
912
+ logger.debug('Invocation failed with error:', error)
894
913
  if (error instanceof Error) {
895
914
  console.error(`Error deploying game server into target environment: ${error.message}`)
896
915
  }
@@ -935,6 +954,7 @@ program
935
954
  // \todo Get requiredImageTag from the Helm chart
936
955
  await checkGameServerDeployment(envInfo, kubeconfig, /* requiredImageTag: */ null)
937
956
  } catch (error: any) {
957
+ logger.debug('Invocation failed with error:', error)
938
958
  console.error(`Failed to check deployment status: ${error.message}`)
939
959
  exit(1)
940
960
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@metaplay/metaplay-auth",
3
3
  "description": "Utility CLI for authenticating with the Metaplay Auth and making authenticated calls to infrastructure endpoints.",
4
- "version": "1.7.1",
4
+ "version": "1.7.2",
5
5
  "type": "module",
6
6
  "license": "SEE LICENSE IN LICENSE",
7
7
  "homepage": "https://metaplay.io",
@@ -25,10 +25,10 @@
25
25
  "@types/node": "20.16.10",
26
26
  "@types/semver": "7.5.8",
27
27
  "esbuild": "0.24.0",
28
- "tsx": "4.19.1",
28
+ "tsx": "4.19.2",
29
29
  "typescript": "5.6.3",
30
- "vitest": "2.1.3",
31
- "@aws-sdk/client-ecr": "3.675.0",
30
+ "vitest": "2.1.4",
31
+ "@aws-sdk/client-ecr": "3.682.0",
32
32
  "@kubernetes/client-node": "1.0.0-rc7",
33
33
  "@ory/client": "1.15.7",
34
34
  "commander": "12.1.0",
package/src/config.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  /**
2
- * Base URL to the Metaplay developer portal. Override with global flag --portal-base-url.
2
+ * Base URL to the Metaplay developer portal. Override with global flag --portal-base-url
3
+ * or environment variable `AUTHCLI_PORTAL_BASEURL'.
3
4
  */
4
5
  export let portalBaseUrl = 'https://portal.metaplay.dev'
5
6
 
@@ -85,6 +85,14 @@ export interface DockerCredentials {
85
85
  registryUrl: string
86
86
  }
87
87
 
88
+ class FetchJsonHttpError extends Error {
89
+ response: Response;
90
+ constructor(method: string, url: string, response: Response) {
91
+ super(`Failed to fetch ${method} ${url}: ${response.statusText}, response code=${response.status}`)
92
+ this.response = response;
93
+ }
94
+ }
95
+
88
96
  export class TargetEnvironment {
89
97
  private readonly accessToken: string
90
98
  private readonly humanId: string
@@ -106,7 +114,7 @@ export class TargetEnvironment {
106
114
  })
107
115
 
108
116
  if (response.status !== 200) {
109
- throw new Error(`Failed to fetch ${method} ${url}: ${response.statusText}, response code=${response.status}`)
117
+ throw new FetchJsonHttpError(method, url, response)
110
118
  }
111
119
 
112
120
  return (await response.json()) as T
@@ -172,8 +180,17 @@ export class TargetEnvironment {
172
180
  let kubeExecCredential: KubeExecCredential
173
181
  try {
174
182
  kubeExecCredential = await this.fetchJson<KubeExecCredential>(url, 'POST')
175
- } catch {
176
- throw new Error(`Failed to fetch Kubernetes KubeConfig from ${url}`)
183
+ } catch (error) {
184
+ // User-friendly error messages for well-known HTTP errors.
185
+ if (error instanceof FetchJsonHttpError) {
186
+ if (error.response.status === 404) {
187
+ throw new Error(`Environment ${this.humanId} does not exist.`)
188
+ } else if (error.response.status === 403) {
189
+ throw new Error(`Your account does not have permissions to access environment ${this.humanId}.`)
190
+ }
191
+ }
192
+ const errorMessage = (error instanceof Error) ? error.message : String(error)
193
+ throw new Error(`Failed to fetch Kubernetes KubeConfig: ${errorMessage}`)
177
194
  }
178
195
 
179
196
  if (!kubeExecCredential.spec.cluster) {
package/src/version.ts CHANGED
@@ -1 +1 @@
1
- export const PACKAGE_VERSION = "1.7.1"
1
+ export const PACKAGE_VERSION = "1.7.2"