@globus/sdk 6.0.1 → 6.2.0-next.9.9c8bf24
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/dist/cjs/core/authorization/index.js +1 -1
- package/dist/cjs/core/authorization/index.js.map +1 -1
- package/dist/cjs/core/info/index.js +1 -1
- package/dist/cjs/core/info/index.js.map +1 -1
- package/dist/cjs/index.js +332 -143
- package/dist/cjs/index.js.map +4 -4
- package/dist/cjs/services/globus-connect-server/client.js +1 -1
- package/dist/cjs/services/globus-connect-server/client.js.map +1 -1
- package/dist/esm/core/info/version.d.ts +1 -1
- package/dist/esm/core/info/version.js +1 -1
- package/dist/esm/open-api/types/compute.d.ts +370 -90
- package/dist/esm/open-api/types/compute.d.ts.map +1 -1
- package/dist/esm/open-api/types/flows.d.ts +210 -262
- package/dist/esm/open-api/types/flows.d.ts.map +1 -1
- package/dist/esm/open-api/types/gcs/v5.4.d.ts +2536 -2276
- package/dist/esm/open-api/types/gcs/v5.4.d.ts.map +1 -1
- package/dist/esm/open-api/types/search.d.ts +131 -65
- package/dist/esm/open-api/types/search.d.ts.map +1 -1
- package/dist/esm/open-api/types/timers.d.ts +17 -7
- package/dist/esm/open-api/types/timers.d.ts.map +1 -1
- package/dist/esm/open-api/types/transfer.d.ts +798 -0
- package/dist/esm/open-api/types/transfer.d.ts.map +1 -0
- package/dist/esm/open-api/types/transfer.js +2 -0
- package/dist/esm/open-api/types/transfer.js.map +1 -0
- package/dist/esm/package.json +1 -1
- package/dist/esm/services/compute/index.d.ts +1 -1
- package/dist/esm/services/compute/index.js +1 -1
- package/dist/esm/services/globus-connect-server/client.d.ts +4 -4
- package/dist/esm/services/globus-connect-server/client.d.ts.map +1 -1
- package/dist/esm/services/groups/service/groups.d.ts +38 -0
- package/dist/esm/services/groups/service/groups.d.ts.map +1 -1
- package/dist/esm/services/groups/service/groups.js +53 -5
- package/dist/esm/services/groups/service/groups.js.map +1 -1
- package/dist/esm/services/groups/service/membership.d.ts +1 -0
- package/dist/esm/services/groups/service/membership.d.ts.map +1 -1
- package/dist/esm/services/groups/service/membership.js +3 -4
- package/dist/esm/services/groups/service/membership.js.map +1 -1
- package/dist/esm/services/groups/service/policies.d.ts +12 -0
- package/dist/esm/services/groups/service/policies.d.ts.map +1 -1
- package/dist/esm/services/groups/service/policies.js +17 -3
- package/dist/esm/services/groups/service/policies.js.map +1 -1
- package/dist/esm/services/search/service/query.d.ts +15 -22
- package/dist/esm/services/search/service/query.d.ts.map +1 -1
- package/dist/esm/services/search/service/query.js.map +1 -1
- package/dist/esm/services/transfer/index.d.ts +2 -0
- package/dist/esm/services/transfer/index.d.ts.map +1 -1
- package/dist/esm/services/transfer/index.js +2 -0
- package/dist/esm/services/transfer/index.js.map +1 -1
- package/dist/esm/services/transfer/service/endpoint-search.d.ts +5 -3
- package/dist/esm/services/transfer/service/endpoint-search.d.ts.map +1 -1
- package/dist/esm/services/transfer/service/endpoint-search.js.map +1 -1
- package/dist/esm/services/transfer/service/stream-access-point.d.ts +23 -0
- package/dist/esm/services/transfer/service/stream-access-point.d.ts.map +1 -0
- package/dist/esm/services/transfer/service/stream-access-point.js +26 -0
- package/dist/esm/services/transfer/service/stream-access-point.js.map +1 -0
- package/dist/esm/services/transfer/service/tunnel.d.ts +75 -0
- package/dist/esm/services/transfer/service/tunnel.d.ts.map +1 -0
- package/dist/esm/services/transfer/service/tunnel.js +80 -0
- package/dist/esm/services/transfer/service/tunnel.js.map +1 -0
- package/dist/umd/globus.production.js +2 -2
- package/dist/umd/globus.production.js.map +4 -4
- package/package.json +2 -2
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/core/authorization/index.ts", "../../../../src/core/authorization/AuthorizationManager.ts", "../../../../src/services/auth/config.ts", "../../../../src/services/transfer/config.ts", "../../../../src/services/flows/config.ts", "../../../../src/services/timers/config.ts", "../../../../src/services/groups/config.ts", "../../../../src/services/search/config.ts", "../../../../src/services/compute/config.ts", "../../../../src/core/errors.ts", "../../../../src/core/logger.ts", "../../../../src/core/global.ts", "../../../../src/core/url.ts", "../../../../src/services/shared.ts", "../../../../src/core/info/private.ts", "../../../../src/core/info/version.ts", "../../../../src/core/info/index.ts", "../../../../src/services/auth/service/oauth2/index.ts", "../../../../src/services/auth/service/oauth2/token.ts", "../../../../src/services/auth/index.ts", "../../../../src/core/authorization/Event.ts", "../../../../src/core/authorization/pkce.ts", "../../../../src/core/authorization/RedirectTransport.ts", "../../../../src/core/authorization/TokenManager.ts", "../../../../src/core/storage/memory.ts", "../../../../src/core/authorization/PopupTransport.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * @module Authorization\n * @description Provides modules for interacting with Globus-related authorization contexts in your application.\n * @example\n * import { authorization } from \"globus/sdk\";\n * const manager = authorization.create(...);\n */\nimport {\n AuthorizationManager,\n type AuthorizationManagerConfiguration,\n} from './AuthorizationManager.js';\n\n/**\n * Create an instance of the {@link AuthorizationManager}.\n */\nexport function create(configuration: AuthorizationManagerConfiguration) {\n return new AuthorizationManager(configuration);\n}\n\nexport { AuthorizationManager, AuthorizationManagerConfiguration };\n", "import { jwtDecode } from 'jwt-decode';\n\nimport { isGlobusAuthTokenResponse, isRefreshToken, oauth2 } from '../../services/auth/index.js';\nimport { RESOURCE_SERVERS } from '../../services/auth/config.js';\n\nimport { log } from '../logger.js';\n\nimport { Event } from './Event.js';\nimport { GetTokenOptions, RedirectTransport, TransportOptions } from './RedirectTransport.js';\nimport { TokenManager } from './TokenManager.js';\n\nimport {\n isConsentRequiredError,\n isAuthorizationRequirementsError,\n AuthorizationRequirementsError,\n ConsentRequiredError,\n toAuthorizationQueryParams,\n} from '../errors.js';\n\nimport type {\n JwtUserInfo,\n Token,\n TokenResponse,\n TokenWithRefresh,\n} from '../../services/auth/types.js';\nimport { MemoryStorage } from '../storage/memory.js';\nimport { PopupTransport } from './PopupTransport.js';\n\nconst TRANSPORTS = {\n redirect: RedirectTransport,\n popup: PopupTransport,\n};\n\nexport type AuthorizationManagerConfiguration = {\n client: string;\n scopes?: string;\n redirect: string;\n /**\n * The storage system used by the `AuthorizationManager`.\n *\n * By default, the `AuthorizationManager` uses an in-memory storage, this option is secure by default.\n *\n * If you want to persist the state of the `AuthorizationManager`, you can use `localStorage`, or provide your own storage system.\n * **It is important to note that using the `localStorage`, or any persistant storage option will preserve authorization and refresh tokens of users.**\n * Best practices for ensuring the security of your application should be followed to protect this data (e.g., ensuring XSS protection).\n *\n * @default MemoryStorage\n */\n storage?: Storage;\n /**\n * The transport method to use for the authorization flow.\n * @default 'redirect'\n */\n transport?: keyof typeof TRANSPORTS;\n /**\n * @private\n * @default DEFAULT_CONFIGURATION.useRefreshTokens\n */\n useRefreshTokens?: boolean;\n /**\n * @private\n * @default DEFAULT_CONFIGURATION.defaultScopes\n */\n defaultScopes?: string | false;\n /**\n * Provide an object with event listeners to attach to the instance.\n * This is useful if you need to listen to events that might dispatch immediately\n * after the creation of the instance (constructor), e.g., the `authenticated`.\n */\n events?: Partial<{\n [Event in keyof AuthorizationManager['events']]: Parameters<\n AuthorizationManager['events'][Event]['addListener']\n >[0];\n }>;\n};\n\nconst DEFAULT_CONFIGURATION = {\n useRefreshTokens: false,\n defaultScopes: 'openid profile email',\n transport: 'redirect' as const,\n};\n\nconst DEFAULT_HANDLE_ERROR_OPTIONS = {\n execute: true,\n additionalParams: undefined,\n};\n\n/**\n * Provides management of Globus authorization context for your application.\n * - Handles the OAuth protcol flow (via PKCE)\n * - Token lifecycle management\n * - Common errors (e.g., `ConsentRequired`, `authorization_requirements`)\n *\n * Once you configure your instance, you can determine the authenticated state using `manager.authenticated`.\n *\n * To prompt a user to authenticate, call `manager.login()` on user interaction \u2013 this will initiate the OAuth protocol flow with your configured client and scopes, resulting in an initial redirect to Globus Auth.\n *\n * Once the user authenticates with Globus Auth, they will be redirected to your application using the configured `redirect` URL. On this URL, you will need to call `manager.handleCodeRedirect` (using a manager instance configured in the same manner that initiated the `manager.login()` call) to complete the PKCE flow, exchanging the provided code for a valid token, or tokens.\n *\n * All tokens managed by the `AuthorizationManager` instance can be found on `manager.token`.\n *\n * ### Registering your Globus Application\n *\n * The `AuthorizationManager` expects your Globus Application to be registered as an OAuth public client.\n * In this Globus Web Application, this option is referenced as \"_Register a thick client or script that will be installed and run by users on their devices_\".\n *\n * @example Creating an AuthorizationManager instance.\n * ```ts\n * import { authorization } from \"globus/sdk\";\n *\n * const manager = authorization.create({\n * // Your registered Globus Application client ID.\n * client: '...',\n * // The redirect URL for your application; Where you will call `manager.handleCodeRedirect()`\n * redirect: 'https://example.com/callback',\n * // Known scopes required by your application.\n * scopes: 'urn:globus:auth:scope:transfer.api.globus.org:all',\n * });\n * ```\n *\n * ### Usage with Service Methods\n *\n * Once you have an instance of an `AuthorizationManager`, it can be passed to any service method as `ServiceMethodOptions.manager` or `SDKOptions.manager` option.\n * The service method will determine if a token is required to make the request and will use the `AuthorizationManager` to retrieve the token.\n *\n * @example Using the AuthorizationManager with a service method.\n *```ts\n * import { transfer } from \"globus/sdk\";\n * const manager = authorization.create({ ... });\n * const result = await (\n * await globus.transfer.endpointSearch({\n * query: { filter_fulltext: \"Globus\"},\n * manager\n * })\n * ).json();\n *```\n */\nexport class AuthorizationManager {\n #transport!: RedirectTransport | PopupTransport;\n\n configuration: AuthorizationManagerConfiguration;\n\n /**\n * The storage system used by the `AuthorizationManager`.\n * @implements Storage\n */\n storage: Storage;\n\n #authenticated = false;\n\n /**\n * The `AuthorizationManager` is considered `authenticated` if it has a valid Globus Auth token.\n * It does not necessarily mean that it has a valid token for a specific resource server.\n */\n get authenticated() {\n return this.#authenticated;\n }\n\n /**\n * Set the authenticated state and emit the `authenticated` event.\n */\n set authenticated(value: boolean) {\n /**\n * Avoid emitting the event if the value hasn't changed.\n */\n if (value === this.#authenticated) {\n return;\n }\n this.#authenticated = value;\n this.#emitAuthenticatedState();\n }\n\n tokens: TokenManager;\n\n events = {\n /**\n * Emitted when the authenticated state changes.\n * @event AuthorizationManager.events#authenticated\n * @type {object}\n * @property {boolean} isAuthenticated - Whether the `AuthorizationManager` is authenticated.\n * @property {TokenResponse} [token] - The token response if the `AuthorizationManager` is authenticated.\n */\n authenticated: new Event<\n 'authenticated',\n {\n /**\n * Whether the `AuthorizationManager` is authenticated.\n * @see {@link AuthorizationManager.authenticated}\n */\n isAuthenticated: boolean;\n token?: TokenResponse;\n }\n >('authenticated'),\n /**\n * Emitted when the user revokes their authentication.\n * @event AuthorizationManager.events#revoke\n */\n revoke: new Event('revoke'),\n };\n\n constructor(configuration: AuthorizationManagerConfiguration) {\n /**\n * Configure the storage system for the instance, defaulting to an in-memory storage system.\n */\n\n if (!configuration.client) {\n throw new Error('You must provide a `client` for your application.');\n }\n /**\n * Inject the `openid`, `profile`, `email`, and `offline_access` scopes by default unless\n * explicitly opted out of.\n */\n const scopes =\n configuration.defaultScopes === false\n ? ''\n : (configuration.defaultScopes ?? DEFAULT_CONFIGURATION.defaultScopes);\n\n this.configuration = {\n ...DEFAULT_CONFIGURATION,\n ...configuration,\n scopes: [configuration.scopes ? configuration.scopes : '', scopes]\n .filter((s) => s.length)\n .join(' '),\n };\n\n this.storage = configuration.storage || new MemoryStorage();\n\n /**\n * If an `events` object is provided, add the listeners to the instance before\n * any event might be dispatched.\n */\n if (this.configuration.events) {\n Object.entries(this.configuration.events).forEach(([name, callback]) => {\n if (name in this.events) {\n this.events[name as keyof AuthorizationManager['events']].addListener(callback);\n }\n });\n }\n\n this.tokens = new TokenManager({\n manager: this,\n });\n this.#checkAuthorizationState();\n }\n\n get storageKeyPrefix() {\n return `${this.configuration.client}:`;\n }\n\n /**\n * The user information decoded from the `id_token` (JWT) of the current Globus Auth token.\n * This method can be used instead of `auth.oauth2.userinfo` to get the user information without an additional request.\n *\n * **IMPORTANT**: The `id_token` can only be processed if the `openid` scope is requested during the authorization process.\n *\n * Additionally, the `profile` and `email` scopes are required to get the full user information.\n *\n * @see {@link https://docs.globus.org/api/auth/reference/#oidc_userinfo_endpoint}\n */\n get user() {\n const token = this.getGlobusAuthToken();\n return token && token.id_token ? jwtDecode<JwtUserInfo>(token.id_token) : null;\n }\n\n /**\n * Attempt to refresh all of the tokens managed by the instance.\n * This method will only attempt to refresh tokens that have a `refresh_token` attribute.\n */\n async refreshTokens() {\n log('debug', 'AuthorizationManager.refreshTokens');\n const tokens = await Promise.allSettled(\n this.tokens.getAll().map((token) => {\n if (isRefreshToken(token)) {\n return this.refreshToken(token);\n }\n return Promise.resolve(null);\n }),\n );\n this.#checkAuthorizationState();\n return tokens;\n }\n\n /**\n * Use the `refresh_token` attribute of a token to obtain a new access token.\n * @param token The well-formed token with a `refresh_token` attribute.\n */\n async refreshToken(token: TokenWithRefresh) {\n log('debug', `AuthorizationManager.refreshToken | resource_server=${token.resource_server}`);\n try {\n const response = await (\n await oauth2.token.refresh({\n payload: {\n client_id: this.configuration.client,\n refresh_token: token.refresh_token,\n grant_type: 'refresh_token',\n },\n })\n ).json();\n if (isGlobusAuthTokenResponse(response)) {\n this.addTokenResponse(response);\n return response;\n }\n } catch (error) {\n log('error', `AuthorizationManager.refreshToken | resource_server=${token.resource_server}`);\n }\n return null;\n }\n\n /**\n * Whether or not the instance has a reference to a Globus Auth token.\n */\n hasGlobusAuthToken() {\n return this.getGlobusAuthToken() !== null;\n }\n\n /**\n * Retrieve the Globus Auth token managed by the instance.\n */\n getGlobusAuthToken() {\n const entry = this.storage.getItem(`${this.storageKeyPrefix}${RESOURCE_SERVERS.AUTH}`);\n return entry ? JSON.parse(entry) : null;\n }\n\n #checkAuthorizationState() {\n log('debug', 'AuthorizationManager.#checkAuthorizationState');\n if (this.hasGlobusAuthToken()) {\n this.authenticated = true;\n }\n }\n\n async #emitAuthenticatedState() {\n const isAuthenticated = this.authenticated;\n const token = this.getGlobusAuthToken() ?? undefined;\n await this.events.authenticated.dispatch({\n isAuthenticated,\n token,\n });\n }\n\n /**\n * Reset the authenticated state and clear all tokens from storage.\n * This method **does not** emit the `revoke` event. If you need to emit the `revoke` event, use the `AuthorizationManager.revoke` method.\n */\n reset() {\n Object.keys(this.storage).forEach((key) => {\n if (key.startsWith(this.storageKeyPrefix)) {\n this.storage.removeItem(key);\n }\n });\n this.authenticated = false;\n }\n\n /**\n * A private utility method to add the `offline_access` scope to a scope string if the `useRefreshTokens` configuration is set to `true`.\n * @param scopes The scope string to modify.\n */\n #withOfflineAccess(scopes: string) {\n return `${scopes}${this.configuration.useRefreshTokens ? ' offline_access' : ''}`;\n }\n\n #buildTransport(options?: Partial<TransportOptions>) {\n const { scopes, ...overrides } = options ?? {};\n const TransportFactory = TRANSPORTS[this.configuration.transport || 'redirect'];\n\n let scopesToRequest = this.#withOfflineAccess(scopes ?? (this.configuration.scopes || ''));\n\n if (this.storage instanceof MemoryStorage) {\n /**\n * If the in-memory storage is used, we have to make sure when requesting additional\n * consent the original configured scopes are included in the request.\n *\n * This will ensure we recieve a token for all of resource servers that were originally requested,\n * in addition to any new scopes that are requested.\n */\n scopesToRequest = [\n // Use a Set to deduplicate the scopes.\n ...new Set(\n scopesToRequest.split(' ').concat((this.configuration?.scopes || '').split(' ')),\n ),\n ].join(' ');\n }\n\n return new TransportFactory({\n client: this.configuration.client,\n redirect: this.configuration.redirect,\n scopes: scopesToRequest,\n ...overrides,\n params: {\n ...overrides?.params,\n },\n });\n }\n\n /**\n * Initiate the login process by redirecting to the Globus Auth login page.\n *\n * **IMPORTANT**: This method will **reset the instance state before initiating the login process,\n * including clearing all tokens from storage**. If you need to maintain the current state,\n * use the `AuthorizationManager.prompt()` method.\n *\n * @example Passing parameters to the transport.\n * const result = await manager.login({\n * additionalParams: {\n * redirect_uri: '/oauth/redirect-uri-runtime-override',\n * },\n * });\n */\n async login(options = { additionalParams: {} }) {\n log('debug', 'AuthorizationManager.login');\n this.reset();\n /**\n * In the future, it's possible that we may want to support different types of transports.\n */\n const transport = this.#buildTransport({ params: options?.additionalParams });\n const result = await transport.send();\n if (isGlobusAuthTokenResponse(result)) {\n this.addTokenResponse(result);\n }\n return result;\n }\n\n /**\n * Prompt the user to authenticate with Globus Auth.\n *\n * @example Passing parameters to the transport.\n * const result = await manager.prompt({\n * additionalParams: {\n * redirect_uri: '/oauth/redirect-uri-runtime-override',\n * },\n * });\n */\n async prompt(options?: Partial<TransportOptions>) {\n log('debug', 'AuthorizationManager.prompt');\n const transport = this.#buildTransport(options);\n const result = await transport.send();\n if (isGlobusAuthTokenResponse(result)) {\n this.addTokenResponse(result);\n }\n return result;\n }\n\n /**\n * This method will attempt to complete the PKCE protocol flow.\n */\n async handleCodeRedirect(\n options: {\n shouldReplace?: GetTokenOptions['shouldReplace'];\n includeConsentedScopes?: GetTokenOptions['includeConsentedScopes'];\n additionalParams?: TransportOptions['params'];\n } = { shouldReplace: true, additionalParams: {} },\n ) {\n log('debug', 'AuthorizationManager.handleCodeRedirect');\n const response = await this.#buildTransport({ params: options?.additionalParams }).getToken({\n shouldReplace: options?.shouldReplace,\n includeConsentedScopes: options?.includeConsentedScopes,\n });\n if (isGlobusAuthTokenResponse(response)) {\n log(\n 'debug',\n `AuthorizationManager.handleCodeRedirect | response=${JSON.stringify(response)}`,\n );\n this.addTokenResponse(response);\n }\n return response;\n }\n\n /**\n * Handle an error response from a Globus service in the context of this `AuthorizationManager`.\n * This method will introspect the response and attempt to handle any errors that should result\n * in some additional Globus Auth interaction.\n * @param response The error response from a Globus service.\n * @param {object|boolean} options Options for handling the error response. If a boolean is provided, this will be treated as the `options.execute` value.\n * @param options.execute Whether to execute the handler immediately.\n * @param options.additionalParams Additional query parameters to be included with the transport generated URL.\n */\n async handleErrorResponse(\n response: Record<string, unknown>,\n options?: { execute?: true; additionalParams?: TransportOptions['params'] } | true,\n ): Promise<void>;\n async handleErrorResponse(\n response: Record<string, unknown>,\n options?: { execute?: false; additionalParams?: TransportOptions['params'] } | false,\n ): Promise<() => Promise<void>>;\n async handleErrorResponse(\n response: Record<string, unknown>,\n options?: { execute?: boolean; additionalParams?: TransportOptions['params'] } | boolean,\n ) {\n const opts =\n typeof options === 'boolean'\n ? {\n ...DEFAULT_HANDLE_ERROR_OPTIONS,\n execute: options,\n }\n : {\n ...DEFAULT_HANDLE_ERROR_OPTIONS,\n ...options,\n };\n log(\n 'debug',\n `AuthorizationManager.handleErrorResponse | response=${JSON.stringify(response)} execute=${opts.execute}`,\n );\n let handler = async () => {};\n if (isAuthorizationRequirementsError(response)) {\n log(\n 'debug',\n 'AuthorizationManager.handleErrorResponse | error=AuthorizationRequirementsError',\n );\n handler = async () => {\n await this.handleAuthorizationRequirementsError(response, {\n additionalParams: opts.additionalParams,\n });\n };\n }\n if (isConsentRequiredError(response)) {\n log('debug', 'AuthorizationManager.handleErrorResponse | error=ConsentRequiredError');\n handler = async () => {\n await this.handleConsentRequiredError(response, {\n additionalParams: opts.additionalParams,\n });\n };\n }\n if ('code' in response && response['code'] === 'AuthenticationFailed') {\n log('debug', 'AuthorizationManager.handleErrorResponse | error=AuthenticationFailed');\n handler = async () => {\n await this.revoke();\n };\n }\n\n const returnValue = opts.execute === true ? await handler() : handler;\n return returnValue;\n }\n\n /**\n * Process a well-formed Authorization Requirements error response from a Globus service\n * and redirect the user to the Globus Auth login page with the necessary parameters.\n */\n async handleAuthorizationRequirementsError(\n response: AuthorizationRequirementsError,\n options?: { additionalParams?: TransportOptions['params'] },\n ) {\n this.#transport = this.#buildTransport({\n params: {\n prompt: 'login',\n ...toAuthorizationQueryParams(response),\n ...options?.additionalParams,\n },\n });\n await this.#transport.send();\n }\n\n /**\n * Process a well-formed `ConsentRequired` error response from a Globus service\n * and redirect the user to the Globus Auth login page with the necessary parameters.\n */\n async handleConsentRequiredError(\n response: ConsentRequiredError,\n options?: { additionalParams?: TransportOptions['params'] },\n ) {\n this.#transport = this.#buildTransport({\n scopes: this.#withOfflineAccess(response.required_scopes.join(' ')),\n params: {\n ...options?.additionalParams,\n },\n });\n await this.#transport.send();\n }\n\n /**\n * Add a Globus Auth token response to storage, if `other_tokens` are present they are also added.\n * This method is mostly used internally by the `AuthorizationManager`, but can be used by downstream\n * consumers to add tokens to storage if necessary.\n */\n addTokenResponse = (token: Token | TokenResponse) => {\n this.tokens.add(token);\n this.#checkAuthorizationState();\n };\n\n /**\n * Call `AuthroizationManager.reset`, revoke all of the available tokns, and emit the `revoke` event.\n * @emits AuthorizationManager.events#revoke\n * @see AuthorizationManager.reset\n */\n async revoke() {\n log('debug', 'AuthorizationManager.revoke');\n const revocation = Promise.all(this.tokens.getAll().map(this.#revokeToken.bind(this)));\n this.reset();\n await revocation;\n await this.events.revoke.dispatch();\n }\n\n /**\n * Revoke a token from a resource server.\n */\n #revokeToken(token: Token) {\n log('debug', `AuthorizationManager.revokeToken | resource_server=${token.resource_server}`);\n return oauth2.token.revoke({\n payload: {\n client_id: this.configuration.client,\n token: token.access_token,\n },\n });\n }\n}\n", "import { ID as TRANSFER } from '../transfer/config.js';\nimport { ID as FLOWS } from '../flows/config.js';\nimport { ID as TIMERS } from '../timers/config.js';\nimport { ID as GROUPS } from '../groups/config.js';\nimport { ID as SEARCH } from '../search/config.js';\nimport { ID as COMPUTE } from '../compute/config.js';\n\nimport type { Environment } from '../../core/global.js';\n\nexport const ID = 'AUTH' as const;\nexport const HOSTS: Partial<Record<Environment, string>> = {\n integration: 'auth.integration.globuscs.info',\n sandbox: 'auth.sandbox.globuscs.info',\n production: 'auth.globus.org',\n test: 'auth.test.globuscs.info',\n staging: 'auth.staging.globuscs.info',\n preview: 'auth.preview.globus.org',\n};\n\nexport const SCOPES = {\n VIEW_IDENTITIES: 'urn:globus:auth:scope:auth.globus.org:view_identities',\n};\n\nexport const RESOURCE_SERVERS = {\n [ID]: 'auth.globus.org',\n [TRANSFER]: 'transfer.api.globus.org',\n [FLOWS]: 'flows.globus.org',\n [GROUPS]: 'groups.api.globus.org',\n [SEARCH]: 'search.api.globus.org',\n [TIMERS]: '524230d7-ea86-4a52-8312-86065a9e0417',\n [COMPUTE]: 'funcx_service',\n};\n", "import type { Environment } from '../../core/global.js';\n\nexport const ID = 'TRANSFER' as const;\n\nexport const SCOPES = {\n ALL: 'urn:globus:auth:scope:transfer.api.globus.org:all',\n};\n\nexport const HOSTS: Partial<Record<Environment, string>> = {\n sandbox: 'transfer.api.sandbox.globuscs.info',\n production: 'transfer.api.globusonline.org',\n staging: 'transfer.api.staging.globuscs.info',\n integration: 'transfer.api.integration.globuscs.info',\n test: 'transfer.api.test.globuscs.info',\n preview: 'transfer.api.preview.globus.org',\n};\n", "import type { Environment } from '../../core/global.js';\n\nexport const ID = 'FLOWS' as const;\nexport const HOSTS: Partial<Record<Environment, string>> = {\n sandbox: 'sandbox.flows.automate.globus.org',\n production: 'flows.globus.org',\n staging: 'staging.flows.automate.globus.org',\n integration: 'integration.flows.automate.globus.org',\n test: 'test.flows.automate.globus.org',\n preview: 'preview.flows.automate.globus.org',\n};\n\n/**\n * @see https://docs.globus.org/api/flows/overview/#scopes\n */\nexport const SCOPES = {\n MANAGE_FLOWS: 'https://auth.globus.org/scopes/eec9b274-0c81-4334-bdc2-54e90e689b9a/manage_flows',\n VIEW_FLOWS: 'https://auth.globus.org/scopes/eec9b274-0c81-4334-bdc2-54e90e689b9a/view_flows',\n RUN: 'https://auth.globus.org/scopes/eec9b274-0c81-4334-bdc2-54e90e689b9a/run',\n RUN_STATUS: 'https://auth.globus.org/scopes/eec9b274-0c81-4334-bdc2-54e90e689b9a/run_status',\n RUN_MANAGE: 'https://auth.globus.org/scopes/eec9b274-0c81-4334-bdc2-54e90e689b9a/run_manage',\n};\n", "import type { Environment } from '../../core/global.js';\n\nexport const ID = 'TIMERS' as const;\nexport const HOSTS: Partial<Record<Environment, string>> = {\n sandbox: 'sandbox.timer.automate.globus.org',\n production: 'timer.automate.globus.org',\n staging: 'staging.timer.automate.globus.org',\n integration: 'integration.timer.automate.globus.org',\n test: 'test.timer.automate.globus.org',\n preview: 'preview.timer.automate.globus.org',\n};\n", "import type { Environment } from '../../core/global.js';\n\nexport const ID = 'GROUPS' as const;\nexport const HOSTS: Partial<Record<Environment, string>> = {\n sandbox: 'groups.api.sandbox.globuscs.info',\n production: 'groups.api.globus.org',\n staging: 'groups.api.staging.globuscs.info',\n integration: 'groups.api.integration.globuscs.info',\n test: 'groups.api.test.globuscs.info',\n preview: 'groups.api.preview.globuscs.info',\n};\n\n/**\n * @see https://docs.globus.org/api/groups/#scopes\n */\nexport const SCOPES = {\n ALL: 'urn:globus:auth:scope:groups.api.globus.org:all',\n VIEW_MY: 'urn:globus:auth:scope:groups.api.globus.org:view_my_groups_and_membership',\n};\n", "import type { Environment } from '../../core/global.js';\n\nexport const ID = 'SEARCH' as const;\nexport const HOSTS: Partial<Record<Environment, string>> = {\n sandbox: 'search.api.sandbox.globuscs.info',\n production: 'search.api.globus.org',\n staging: 'search.api.staging.globuscs.info',\n integration: 'search.api.integration.globuscs.info',\n test: 'search.api.test.globuscs.info',\n preview: 'search.api.preview.globus.org',\n};\n\n/**\n * @see https://docs.globus.org/api/search/api_usage/#scopes\n */\nexport const SCOPES = {\n ALL: 'urn:globus:auth:scope:search.api.globus.org:all',\n INGEST: 'urn:globus:auth:scope:search.api.globus.org:ingest',\n SEARCH: 'urn:globus:auth:scope:search.api.globus.org:search',\n};\n", "import type { Environment } from '../../core/global.js';\n\nexport const ID = 'COMPUTE' as const;\nexport const HOSTS: Partial<Record<Environment, string>> = {\n sandbox: 'compute.api.sandbox.globuscs.info',\n production: 'compute.api.globus.org',\n staging: 'compute.api.staging.globuscs.info',\n integration: 'compute.api.integration.globuscs.info',\n test: 'compute.api.test.globuscs.info',\n preview: 'compute.api.preview.globus.org',\n};\n\nexport const SCOPES = {\n ALL: 'https://auth.globus.org/scopes/facd7ccc-c5f4-42aa-916b-a0e270e2c2a9/all',\n};\n", "/**\n * @module Errors\n * @example\n * import { errors } from \"globus/sdk\";\n * if (errors.isConsentRequiredError(...)) { ... }\n */\nimport type { AuthorizationQueryParameters } from '../services/auth/index.js';\nimport type { AuthorizationRequestParameters } from './authorization/pkce.js';\n\nexport class EnvironmentConfigurationError extends Error {\n override name = 'EnvironmentConfigurationError';\n\n constructor(variable: string, value: unknown) {\n super();\n // eslint-disable-next-line @typescript-eslint/restrict-template-expressions\n this.message = `Invalid configuration value provided for ${variable} (${value}).`;\n }\n}\n\nexport type WellFormedError = {\n code: string;\n message: string;\n};\n\n/**\n * Test an unknown argument to determine if it can be further parsed as a potentnial known error.\n */\nexport function isErrorWellFormed(test: unknown): test is WellFormedError {\n return typeof test === 'object' && test !== null && 'code' in test && 'message' in test;\n}\n\n/**\n * An error that indicates that the user must provide consent for additional scopes.\n * - This error typically encountered when interacting with Globus Transfer or Globus Connect Server.\n * - Many instances of `code: \"ConsentRequire\"` in the Globus platform are being migrated to `AuthorizationRequirementsError`.\n */\nexport type ConsentRequiredError = {\n code: 'ConsentRequired';\n required_scopes: string[];\n [key: string]: unknown;\n};\n\n/**\n * Whether or not the provide object is recognized as a `ConsentRequiredError`.\n * @see {@link ConsentRequiredError}\n */\nexport function isConsentRequiredError(test: unknown): test is ConsentRequiredError {\n return (\n isErrorWellFormed(test) &&\n test.code === 'ConsentRequired' &&\n 'required_scopes' in test &&\n Array.isArray(test.required_scopes)\n );\n}\n\n/**\n * An error that includes an `authorization_parameters` property, a.k.a \"G.A.R.E\".\n *\n * A well-known error shape is provided by services when additional authorization requirements must be met by the session.\n * This object can be converted to parameters accepted by Globus Auth using `sdk.errors.toAuthorizationQueryParams()`.\n */\nexport type AuthorizationRequirementsError = {\n authorization_parameters: {\n session_message?: string;\n session_required_identities?: string[];\n session_required_mfa?: boolean;\n session_required_single_domain?: string[];\n session_required_policies?: string[];\n prompt?: string;\n required_scopes?: string[];\n };\n /**\n * @todo At the moment, most Globus services do not guarentee a `code` property for this error type.\n * Once it becomes more common, this type (and the `isAuthorizationRequirementsError` function) should be updated.\n * @see https://globus-sdk-python.readthedocs.io/en/stable/experimental/auth_requirements_errors.html\n */\n // code: string;\n [key: string]: unknown;\n};\n/**\n * Keys that should not be included in the query string object (not recognized by Globus Auth),\n * but are found on the `AuthorizationRequirementsError` object.\n */\nconst NO_OP_KEYS: (keyof AuthorizationRequirementsError)[] = ['required_scopes'];\n/**\n * Convert an `AuthorizationRequirementsError` to a query string object accepted by Globus Auth.\n */\nexport function toAuthorizationQueryParams(\n error: AuthorizationRequirementsError,\n): AuthorizationQueryParameters & Partial<AuthorizationRequestParameters> {\n /**\n * Map properties from the `AuthorizationRequirementsError` to accepted query parameters.\n */\n const mapped = {\n /**\n * `required_scopes` isn't a query parameter accepted by Globus Auth, but\n * in most cases the `required_scopes` represented in the error are intended\n * to be included in the `scopes` (OAuth) parameter.\n * @see https://docs.globus.org/api/auth/sessions/#client-initiated-authns\n */\n scope: error.authorization_parameters.required_scopes?.join(' '),\n /**\n * We still include the entire `authorization_parameters` object in addition to the mapped values for parsing.\n */\n ...error.authorization_parameters,\n };\n\n return Object.entries(mapped).reduce((acc, [key, v]) => {\n /**\n * Remove keys that are not recognized by Globus Auth and empty values.\n */\n if (NO_OP_KEYS.includes(key) || v === undefined || v === null) {\n return acc;\n }\n /**\n * All other values are converted to strings.\n */\n let value = v;\n if (Array.isArray(value)) {\n value = value.join(',');\n } else if (typeof v === 'boolean') {\n value = value ? 'true' : 'false';\n }\n return { ...acc, [key]: value };\n }, {});\n}\n\n/**\n * Check if an object is an `AuthorizationRequirementsError`.\n * @see {@link AuthorizationRequirementsError}\n */\nexport function isAuthorizationRequirementsError(\n test: unknown,\n): test is AuthorizationRequirementsError {\n return (\n typeof test === 'object' &&\n test !== null &&\n 'authorization_parameters' in test &&\n typeof test.authorization_parameters === 'object' &&\n test.authorization_parameters !== null\n );\n}\n", "const LOG_LEVELS = ['debug', 'info', 'warn', 'error'] as const;\n\ntype LogLevel = (typeof LOG_LEVELS)[number];\n\ntype LogHandler = (...args: unknown[]) => void;\n\ntype Logger = {\n log: LogHandler;\n error?: LogHandler;\n warn?: LogHandler;\n info?: LogHandler;\n debug?: LogHandler;\n};\n/**\n * No logger is set by default.\n */\nlet logger: Logger | undefined;\n/**\n * By default, the logger is set to `error`.\n */\nlet level: number = LOG_LEVELS.indexOf('error');\n/**\n * Set the global logger for the SDK.\n * @param logMechanism The logger to use.\n * @example `log.setLogger(console)`\n */\nexport function setLogger(logMechanism: Logger) {\n logger = logMechanism;\n}\n/**\n * Set the global log level for the logger.\n * @param severity The severity to set the logger to.\n * @example `log.setLogLevel('info')`\n */\nexport function setLogLevel(severity: LogLevel) {\n level = LOG_LEVELS.indexOf(severity);\n}\n/**\n * Log a message to the logger.\n * @param severity The severity of the log entry.\n * @param args The message to log.\n * @private\n */\nexport function log(severity: LogLevel, ...args: unknown[]) {\n if (!logger) return;\n /**\n * If the severity of the entry is less than the logger's configured severity, do not log.\n */\n if (LOG_LEVELS.indexOf(severity) < level) {\n return;\n }\n /**\n * If the logger does not have a handler for the specified severity, use the default `log` handler.\n */\n const handler = logger[severity] ?? logger.log;\n handler(...args);\n}\n", "import * as AUTH from '../services/auth/config.js';\nimport * as TRANSFER from '../services/transfer/config.js';\nimport * as FLOWS from '../services/flows/config.js';\nimport * as GROUPS from '../services/groups/config.js';\nimport * as SEARCH from '../services/search/config.js';\nimport * as TIMERS from '../services/timers/config.js';\nimport * as COMPUTE from '../services/compute/config.js';\n\nimport { EnvironmentConfigurationError } from './errors.js';\nimport { SDKOptions } from '../services/types.js';\nimport { log } from './logger.js';\n\nfunction getRuntime() {\n return typeof window !== 'undefined' ? window : process;\n}\n\nfunction isBrowser(runtime: Window | NodeJS.Process): runtime is Window {\n return typeof window === typeof runtime;\n}\n\nfunction env<T>(key: string, fallback: T): T {\n const runtime = getRuntime();\n let envConfiguration;\n if (isBrowser(runtime)) {\n envConfiguration = runtime;\n } else {\n envConfiguration = runtime.env;\n }\n if (key in envConfiguration) {\n return (envConfiguration as Record<typeof key, T>)[key];\n }\n return fallback;\n}\n\n/**\n * Handlers for: GLOBUS_SDK_ENVIRONMENT\n */\nexport const ENVIRONMENTS = {\n PRODUCTION: 'production',\n PREVIEW: 'preview',\n STAGING: 'staging',\n SANDBOX: 'sandbox',\n INTEGRATION: 'integration',\n TEST: 'test',\n} as const;\n\nexport type Environment = (typeof ENVIRONMENTS)[keyof typeof ENVIRONMENTS];\n\nexport const SERVICES = {\n [AUTH.ID]: AUTH.ID,\n [TRANSFER.ID]: TRANSFER.ID,\n [FLOWS.ID]: FLOWS.ID,\n [GROUPS.ID]: GROUPS.ID,\n [SEARCH.ID]: SEARCH.ID,\n [TIMERS.ID]: TIMERS.ID,\n [COMPUTE.ID]: COMPUTE.ID,\n};\n\nexport type Service = keyof typeof SERVICES;\n\nexport const SERVICE_HOSTS: Record<Service, Partial<Record<Environment, string>>> = {\n [AUTH.ID]: AUTH.HOSTS,\n [TRANSFER.ID]: TRANSFER.HOSTS,\n [FLOWS.ID]: FLOWS.HOSTS,\n [GROUPS.ID]: GROUPS.HOSTS,\n [SEARCH.ID]: SEARCH.HOSTS,\n [TIMERS.ID]: TIMERS.HOSTS,\n [COMPUTE.ID]: COMPUTE.HOSTS,\n};\n\n/**\n * Get the computed SDK options based on the runtime.\n * This should be used any time we're referencing the SDK options in\n * methods to ensure we're including any global overrides.\n */\nexport function getSDKOptions(options?: SDKOptions) {\n let globalOptions = env<string | SDKOptions>('GLOBUS_SDK_OPTIONS', {});\n if (typeof globalOptions === 'string') {\n globalOptions = JSON.parse(globalOptions) as SDKOptions;\n }\n return {\n ...globalOptions,\n ...options,\n fetch: {\n ...globalOptions?.fetch,\n ...options?.fetch,\n options: {\n ...globalOptions?.fetch?.options,\n ...options?.fetch?.options,\n headers: {\n ...globalOptions?.fetch?.options?.headers,\n ...options?.fetch?.options?.headers,\n },\n },\n },\n };\n}\n\nexport function getEnvironment(): Environment {\n const globalOptions = getSDKOptions();\n const environment = env<Environment>(\n 'GLOBUS_SDK_ENVIRONMENT',\n globalOptions?.environment ?? ENVIRONMENTS.PRODUCTION,\n );\n if (globalOptions?.environment && environment !== globalOptions.environment) {\n log(\n 'debug',\n 'GLOBUS_SDK_ENVIRONMENT and GLOBUS_SDK_OPTIONS.environment are set to different values. GLOBUS_SDK_ENVIRONMENT will take precedence',\n );\n }\n if (!environment || !Object.values(ENVIRONMENTS).includes(environment)) {\n throw new EnvironmentConfigurationError('GLOBUS_SDK_ENVIRONMENT', environment);\n }\n return environment;\n}\n\n/**\n * Handlers for: GLOBUS_SDK_VERIFY_SSL\n * Since disabling SSL is at least not-recommended, we consider\n * this value to always be true, but provide a warning when it set\n * to one of the falsey values for informational purposes.\n *\n * Taking direction from `globus-sdk-python` for possible false values\n * @see https://github.com/globus/globus-sdk-python/blob/18eced9c12e2ec41745d1be183148845198b999c/src/globus_sdk/config/env_vars.py#L20\n */\nexport function getVerifySSL(): boolean {\n const verifySSLTemp = env<string>('GLOBUS_SDK_VERIFY_SSL', 'true').toLowerCase();\n if (['n', 'no', 'f', 'false', 'off', '0'].includes(verifySSLTemp)) {\n log(\n 'warn',\n 'Setting GLOBUS_SDK_VERIFY_SSL to false is disallowed in the Globus JavaScript SDK. It will always true in this context',\n );\n }\n return true;\n}\n\n/**\n * Handlers for: GLOBUS_SDK_HTTP_TIMEOUT\n */\nexport function getHttpTimeout() {\n const timeout = Number(env<string | number>('GLOBUS_SDK_HTTP_TIMEOUT', 60));\n if (timeout === -1) {\n return null;\n }\n return timeout;\n}\n\nexport function getServiceHost(service: Service, environment: Environment = getEnvironment()) {\n return SERVICE_HOSTS[service][environment];\n}\n\nexport function getServiceBaseUrl(service: Service, environment: Environment = getEnvironment()) {\n const host = getServiceHost(service, environment);\n return env(`GLOBUS_SDK_SERVICE_URL_${service}`, host ? `https://${host}` : undefined);\n}\n", "import { getServiceBaseUrl, getEnvironment, Environment, Service } from './global.js';\nimport type {\n GCSConfiguration,\n UnauthenticatedGCSConfiguration,\n} from '../services/globus-connect-server/index.js';\nimport { SDKOptions } from '../services/types.js';\n\n/**\n * An extremely simplified parameter serializer based on our current needs.\n *\n * **This is intended for internal @globus/sdk use only.**\n *\n * @private\n */\nexport function stringifyParameters(parameters: {\n [key: string]:\n | string\n | number\n | boolean\n | Array<string | number | null | undefined>\n | null\n | undefined;\n}) {\n const search = new URLSearchParams();\n\n Array.from(Object.entries(parameters)).forEach(([key, value]) => {\n if (Array.isArray(value)) {\n /**\n * Arrays are converted to comma-separated strings.\n */\n search.set(key, value.join(','));\n } else if (value !== undefined) {\n search.set(key, String(value));\n }\n });\n\n return search.toString();\n}\n\n/**\n * Return the base URL for a service (based on the environment).\n * @param service The service to build the URL for.\n * @param path The path to the resource.\n * @param environment The environment to use.\n */\nexport function getServiceURL(\n service: Service,\n path = '',\n environment: Environment = getEnvironment(),\n): URL {\n const base = getServiceBaseUrl(service, environment);\n return new URL(path, base);\n}\n\n/**\n * Build a URL for a service or GCSConfiguration.\n *\n * @param service The service identifier or GCSConfiguration object to build the URL for.\n * @param path The path to the resource.\n * @param options Additional options for the URL.\n */\nexport function build(\n serviceOrConfiguration: Service | GCSConfiguration | UnauthenticatedGCSConfiguration,\n path: string,\n options?: {\n search?: Parameters<typeof stringifyParameters>[0];\n },\n sdkOptions?: SDKOptions,\n): string {\n let url;\n if (typeof serviceOrConfiguration === 'object') {\n url = new URL(path, serviceOrConfiguration.host);\n } else {\n url = getServiceURL(serviceOrConfiguration, path, sdkOptions?.environment);\n }\n if (options && options.search) {\n url.search = stringifyParameters(options.search);\n }\n return url.toString();\n}\n", "import _fetch from 'cross-fetch';\nimport { getClientInfoRequestHeaders } from '../core/info/index.js';\nimport { build } from '../core/url.js';\nimport { getSDKOptions, Service } from '../core/global.js';\nimport { isAuthorizationRequirementsError } from '../core/errors.js';\nimport { RESOURCE_SERVERS } from './auth/config.js';\nimport { isRefreshToken } from './auth/index.js';\nimport type { ServiceMethodOptions, SDKOptions } from './types.js';\nimport type {\n GCSConfiguration,\n UnauthenticatedGCSConfiguration,\n} from '../services/globus-connect-server/index.js';\n\n// eslint-disable-next-line @typescript-eslint/naming-convention\nexport enum HTTP_METHODS {\n POST = 'POST',\n GET = 'GET',\n DELETE = 'DELETE',\n PUT = 'PUT',\n PATCH = 'PATCH',\n}\n\n/**\n * Our domain-specific language for describing service requests.\n * @private\n */\ntype ServiceRequestDSL = {\n /**\n * The service that the request will be made to.\n */\n service: Service | GCSConfiguration | UnauthenticatedGCSConfiguration;\n /**\n * A specific scope that is required for the request. If a scope is provided,\n * the `serviceRequest` function will attempt to get a token for the request\n * based on the the `service` => `resource_server` mapping.\n * @deprecated Define using `resource_server` instead.\n */\n scope?: string;\n /**\n * The resource server that the request will be made to. This can be provided\n * instead of (or addition to) the `scope` property. If this is provided, the\n * `serviceRequest` function will attempt to get a token for the resource server\n * when a `manager` instance is provided in the SDK options.\n */\n resource_server?: string;\n /**\n * The path of the resource (appended to the service's host).\n */\n path: string;\n /**\n * The HTTP method to use for the request.\n */\n method?: HTTP_METHODS;\n /**\n * For some resources, it doesn't make sense for requests to be retried.\n * Setting this to `true` will prevent any retry logic from being applied.\n */\n preventRetry?: boolean;\n};\n\n/**\n * A helper function for making service requests that will handle the arguments\n * of `ServiceMethod` and `ServiceMethodDynamicSegments` functions in a uniform\n * way.\n *\n * @example\n * ```ts\n * export const get = function (flow_id, options?, sdkOptions?) {\n * return serviceRequest({\n * service: FLOWS.ID,\n * scope: SCOPES.VIEW_FLOWS,\n * path: `/flows/${flow_id}`,\n * }, options, sdkOptions);\n * } satisfies ServiceMethodDynamicSegments<string, Record<string, any>>;\n * ```\n *\n * @private\n * @param config The ServiceRequestDSL for the request.\n * @param options The options passed to the service method.\n * @param passedSdkOptions The SDK options passed to the service method.\n * @returns\n */\nexport async function serviceRequest(\n this: unknown,\n config: ServiceRequestDSL,\n options?: ServiceMethodOptions,\n passedSdkOptions?: SDKOptions,\n): Promise<Response> {\n /**\n * Get the SDK options, merging any passed options with the global options.\n */\n const sdkOptions = getSDKOptions(passedSdkOptions);\n const injectedFetchOptions = sdkOptions?.fetch?.options || {};\n\n const headers: Record<string, string> = {\n ...getClientInfoRequestHeaders(),\n ...options?.headers,\n /**\n * Key/value pairs found in the `fetch` options override those found in the\n * service method options.\n */\n ...injectedFetchOptions.headers,\n };\n\n /**\n * The `AuthorizationManager` instance provided with the call.\n */\n const manager = options?.manager || sdkOptions?.manager;\n\n let token;\n /**\n * If a `resource_server` was provided, and the SDK is configured with a `manager`\n * instance, we'll try to get a token for the resource server and use it.\n */\n if (config.resource_server && manager) {\n token = manager.tokens.getByResourceServer(config.resource_server);\n if (token) {\n headers['Authorization'] = `Bearer ${token.access_token}`;\n }\n }\n /**\n * If the `scope` property is provided, and the SDK is configured with a `manager`,\n * we'll try to map the service to a resource server. This is mostly to support\n * backwards compatibility of the `scope` property being used in the `ServiceRequestDSL`.\n *\n * @todo This condition will likely be removed in a future version in favor of using `resource_server` to\n * configure a service request.\n */\n if (\n config.scope &&\n manager &&\n /**\n * Only attempt to get a token if the `service` property is a string or has an `endpoint_id` property (GCSConfiguration).\n */\n (typeof config.service === 'string' || 'endpoint_id' in config.service)\n ) {\n const resourceServer =\n typeof config.service === 'string'\n ? RESOURCE_SERVERS[config.service]\n : // For `GCSConfiguration` objects, the `endpoint_id` is the resource server.\n config.service.endpoint_id;\n\n token = manager.tokens.getByResourceServer(resourceServer);\n if (token) {\n headers['Authorization'] = `Bearer ${token.access_token}`;\n }\n }\n\n /**\n * If a raw body was provided, use that. Otherwise, if a payload was provided, serialize it.\n */\n let body = options?.body;\n if (!body && options?.payload) {\n body = JSON.stringify(options.payload);\n }\n\n /**\n * If `Content-Type` header was not provided, and there is a body, we assume it is JSON.\n */\n if (!headers?.['Content-Type'] && body) {\n headers['Content-Type'] = 'application/json';\n }\n\n const url = build(\n config.service,\n config.path,\n {\n search: options?.query,\n },\n sdkOptions,\n );\n\n const init = {\n method: config.method,\n body,\n ...injectedFetchOptions,\n /**\n * Merge the headers from the options and SDK options.\n */\n headers,\n };\n\n /**\n * The request handler for the fetch call. This can be overridden by providing a\n * `__callable` property in the `fetch` options.\n */\n let handler = _fetch;\n /* eslint-disable no-underscore-dangle */\n if (injectedFetchOptions?.__callable) {\n handler = injectedFetchOptions.__callable.bind(this);\n /**\n * Remove the `__callable` property from the `fetch` options before passing the options along.\n */\n delete init.__callable;\n }\n /* eslint-enable no-underscore-dangle */\n\n /**\n * If the resource is configured to prevent retries, there is no `manager` instance,\n * or token, the request will be made as-is.\n */\n if (config.preventRetry || !manager || !token || !isRefreshToken(token)) {\n return handler(url, init);\n }\n\n /**\n * Automatic Retry Handling\n */\n\n const initialResponse = await handler(url, init);\n /**\n * If the response is \"ok\", we can return it as-is.\n */\n if (initialResponse.ok) {\n return initialResponse;\n }\n /**\n * Do a safe check to see if the response contains any authorization requirements.\n */\n let hasAuthorizationRequirements;\n try {\n hasAuthorizationRequirements = isAuthorizationRequirementsError(\n /**\n * It is important to clone the response before calling `json` avoid\n * `body used already for [...]` errors when the initial response is\n * returned.\n */\n await initialResponse.clone().json(),\n );\n } catch (_e) {\n hasAuthorizationRequirements = false;\n }\n /**\n * We only attempt to refresh the original token supplied with teh request, if the\n * response status is 401 and the response does not contain any authorization requirements.\n */\n const shouldAttemptTokenRefresh = initialResponse.status === 401 && !hasAuthorizationRequirements;\n if (shouldAttemptTokenRefresh) {\n const newToken = await manager.refreshToken(token);\n if (!newToken) {\n return initialResponse;\n }\n /**\n * Retry the request with the new token.\n */\n return handler(url, {\n ...init,\n headers: {\n ...init.headers,\n Authorization: `Bearer ${newToken.access_token}`,\n },\n });\n }\n /**\n * No retry was attempted, return the initial response.\n */\n return initialResponse;\n}\n", "import type { Info } from './index.js';\n\n/**\n * @private\n */\nexport const CLIENT_INFO_HEADER = `X-Globus-Client-Info`;\n\nlet ENABLED = true;\n/**\n * Disable the client information header from being included in requests (enabled by default).\n * @private\n */\nexport function disable() {\n ENABLED = false;\n}\n\n/**\n * Enables the client information header to be included in requests.\n * @private\n */\nexport function enable() {\n ENABLED = true;\n}\n\n/**\n * Whether or not the client information header should be sent with requests.\n * @private\n */\nexport function isEnabled() {\n return ENABLED;\n}\n\nconst INFOS_SEPERATOR = ';';\nconst INFO_ITEM_SEPARATOR = ',';\n\n/**\n * Exported for test purposes only.\n * @private\n */\nexport function toString(info: Info | Info[]) {\n const infos = Array.isArray(info) ? info : [info];\n return infos\n .map((i) =>\n Object.entries(i)\n .map(([key, value]) => `${key}=${value}`)\n .join(INFO_ITEM_SEPARATOR),\n )\n .join(INFOS_SEPERATOR);\n}\n", "// x-release-please-start-version\nexport const VERSION = '6.0.1';\n// x-release-please-end\n", "/**\n * @module Information\n * @description This module is mostly intended for internal use, but can be helpful\n * identifying information about the SDK package you are using at runtime.\n */\nimport { toString, isEnabled, CLIENT_INFO_HEADER } from './private.js';\nimport { VERSION as _VERSION } from './version.js';\n\nexport type Version = string;\n\n/**\n * The version of the `@globus/sdk` package that is in use.\n */\nexport const VERSION: Version = _VERSION;\n\nexport type Info = {\n product: string;\n version: Version;\n};\n\n/**\n * The client information identifier for this package.\n */\nexport const CLIENT_INFO: Info = {\n product: 'javascript-sdk',\n version: VERSION,\n};\n\nlet INFOS: Info[] = [CLIENT_INFO];\n\n/**\n * Add a client information identifier to the existing SDK information.\n */\nexport function addClientInfo(info: Info) {\n INFOS = INFOS.concat(info);\n}\n/**\n * Get the current client information as a string.\n */\nexport function getClientInfo(): string {\n return toString(INFOS);\n}\n\nexport function getClientInfoRequestHeaders(): Record<string, string> {\n if (!isEnabled()) {\n return {};\n }\n return {\n [CLIENT_INFO_HEADER]: getClientInfo(),\n };\n}\n", "import { ID } from '../../config.js';\nimport { HTTP_METHODS, serviceRequest } from '../../../../services/shared.js';\n\nimport type { ServiceMethod } from '../../../types.js';\n\nexport const userinfo = function (options?, sdkOptions?) {\n return serviceRequest(\n {\n service: ID,\n scope: undefined,\n path: `/v2/oauth2/userinfo`,\n method: HTTP_METHODS.GET,\n },\n options,\n sdkOptions,\n );\n} satisfies ServiceMethod<{\n payload: never;\n}>;\n\nexport * as token from './token.js';\n", "import { ID } from '../../config.js';\nimport { HTTP_METHODS, serviceRequest } from '../../../../services/shared.js';\n\nimport type { ServiceMethod, ServiceMethodOptions } from '../../../types.js';\n\ntype IntrospectPayload = {\n token: string;\n include?: string;\n};\n\ntype RevokePayload = {\n token: string;\n /**\n * This is an undocumented property that is required for the request to be successful.\n */\n client_id: string;\n};\n\ntype ValidatePayload = {\n token: string;\n client_id: string;\n};\n\ntype RefreshPayload = {\n refresh_token: string;\n grant_type: 'refresh_token';\n /**\n * This is an undocumented property that is required for the request to be successful.\n */\n client_id: string;\n};\n\ntype ExchangePayload = {\n grant_type: 'authorization_code';\n code: string;\n client_id: string;\n code_verifier: string;\n redirect_uri: string;\n};\n\ntype SupportedPayloads =\n | IntrospectPayload\n | RevokePayload\n | ValidatePayload\n | RefreshPayload\n | ExchangePayload;\n\nfunction serialize(payload?: SupportedPayloads) {\n return new URLSearchParams(payload);\n}\n\n/**\n * Format and inject properties that are specific to the `/token` resources.\n */\nfunction injectServiceOptions(\n options: ServiceMethodOptions & {\n payload?: SupportedPayloads;\n },\n): ServiceMethodOptions {\n return {\n ...options,\n /**\n * The `token` service methods always expect a form-encoded body. We still allow\n * end-consumers to pass a raw body, but if `payload` is provided it is serialized.\n */\n body: options.payload ? serialize(options.payload) : undefined,\n headers: {\n ...(options?.headers || {}),\n Accept: 'application/json',\n /**\n * Force the `Content-Type` header to be `application/x-www-form-urlencoded` and `charset=UTF-8`.\n */\n 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',\n },\n };\n}\n\n/**\n * @see https://docs.globus.org/api/auth/reference/#dependent_token_grant_post_v2oauth2token\n */\nexport const token = function (options = {}, sdkOptions?) {\n return serviceRequest(\n {\n service: ID,\n scope: undefined,\n path: `/v2/oauth2/token`,\n method: HTTP_METHODS.POST,\n preventRetry: true,\n },\n injectServiceOptions(options),\n sdkOptions,\n );\n} satisfies ServiceMethod<{\n payload?: ExchangePayload;\n query?: {\n /**\n * Include tokens for all scopes that the user has consented to, for the requesting client.\n * @private\n */\n include_consented_scopes?: boolean;\n };\n}>;\n\n/**\n * @see https://docs.globus.org/api/auth/developer-guide/#obtaining-authorization\n */\nexport const exchange = token;\n\n/**\n * Token Introspection\n * @see https://docs.globus.org/api/auth/reference/#token-introspect\n */\nexport const introspect = function (options, sdkOptions?) {\n if (!options?.payload) {\n throw new Error(`'payload' is required for introspect`);\n }\n return serviceRequest(\n {\n service: ID,\n scope: undefined,\n path: `/v2/oauth2/token/introspect`,\n method: HTTP_METHODS.POST,\n preventRetry: true,\n },\n injectServiceOptions(options),\n sdkOptions,\n );\n} satisfies ServiceMethod<{\n payload: IntrospectPayload;\n}>;\n\n/**\n * Token Revocation\n * @see https://docs.globus.org/api/auth/reference/#token-revoke\n */\nexport const revoke = function (options, sdkOptions?) {\n if (!options?.payload) {\n throw new Error(`'payload' is required for revoke`);\n }\n return serviceRequest(\n {\n service: ID,\n scope: undefined,\n path: `/v2/oauth2/token/revoke`,\n method: HTTP_METHODS.POST,\n preventRetry: true,\n },\n injectServiceOptions(options),\n sdkOptions,\n );\n} satisfies ServiceMethod<{\n payload: RevokePayload;\n}>;\n\n/**\n * Token Refresh\n * @see https://docs.globus.org/api/auth/reference/#refresh_token_grant\n */\nexport const refresh = function (options, sdkOptions?) {\n if (!options?.payload) {\n throw new Error(`'payload' is required for revoke`);\n }\n return serviceRequest(\n {\n service: ID,\n scope: undefined,\n path: `/v2/oauth2/token`,\n method: HTTP_METHODS.POST,\n preventRetry: true,\n },\n injectServiceOptions(options),\n sdkOptions,\n );\n} satisfies ServiceMethod<{\n payload: RefreshPayload;\n}>;\n\n/**\n * @private\n * @deprecated Rather than using `validate` to check if a token is valid, it is recommended to make a request to the resource server with the token and handle the error response.\n */\nexport const validate = function (options, sdkOptions?) {\n if (!options?.payload) {\n throw new Error(`'payload' is required for validate`);\n }\n return serviceRequest(\n {\n service: ID,\n scope: undefined,\n path: `/v2/oauth2/token/validate`,\n method: HTTP_METHODS.POST,\n preventRetry: true,\n },\n injectServiceOptions(options),\n sdkOptions,\n );\n} satisfies ServiceMethod<{\n payload: ValidatePayload;\n}>;\n", "/**\n * @description A wrapper around the Globus Auth service.\n * @group Service\n * @see [Globus Auth API Documentation](https://docs.globus.org/api/auth/)\n * @module\n */\nimport { build } from '../../core/url.js';\n\nimport * as AUTH from './config.js';\n\nimport type { Token, TokenWithRefresh, TokenResponse } from './types.js';\n\n/**\n * @private\n * @internal\n */\nexport const CONFIG = AUTH;\n\nexport type * from './types.js';\n\n/**\n * Query parameters that can be passed to the authorization endpoint.\n * @see https://docs.globus.org/api/auth/reference/#authorization_code_grant_preferred\n * @see https://docs.globus.org/api/auth/sessions/#client-initiated-authns\n */\nexport type AuthorizationQueryParameters = {\n prompt?: string;\n session_message?: string;\n session_required_identities?: string;\n session_required_single_domain?: string;\n session_required_mfa?: 'true' | 'false';\n session_required_policies?: string;\n};\n\nexport function getAuthorizationEndpoint() {\n return build(AUTH.ID, '/v2/oauth2/authorize');\n}\n\nexport function getTokenEndpoint() {\n return build(AUTH.ID, '/v2/oauth2/token');\n}\n\nexport * as identities from './service/identities/index.js';\nexport * as oauth2 from './service/oauth2/index.js';\n\nexport function isToken(check: unknown): check is Token {\n return typeof check === 'object' && check !== null && 'access_token' in check;\n}\n\nexport function isRefreshToken(check: unknown): check is TokenWithRefresh {\n return isToken(check) && check !== null && 'refresh_token' in check;\n}\n\nexport function isGlobusAuthTokenResponse(check: unknown): check is TokenResponse {\n /**\n * @todo This could be made more robust by checking whether the `resource_server` is a well-known value.\n */\n return isToken(check) && check !== null && 'resource_server' in check;\n}\n\nexport * as utils from './utils.js';\n", "/**\n * @todo It would be nice to not `| any` here, but ideally callers do not need to\n * fully type the payload to attach listeners.\n */\ntype ListenerCallback<P> = (payload?: P | any) => Promise<void> | void;\n\nexport class Event<EventName extends string, Payload extends unknown> {\n #callbacks: ListenerCallback<Payload>[] = [];\n\n constructor(readonly name: EventName) {}\n\n addListener(callback: ListenerCallback<Payload>) {\n this.#callbacks.push(callback);\n return () => this.removeListener(callback);\n }\n\n removeListener(callback: ListenerCallback<Payload>) {\n this.#callbacks = this.#callbacks.filter((cb) => cb !== callback);\n }\n\n clearListeners() {\n this.#callbacks = [];\n }\n\n async dispatch(payload?: Payload) {\n await Promise.all(this.#callbacks.map((callback) => callback(payload)));\n }\n}\n", "export function isSupported() {\n return 'crypto' in globalThis;\n}\n\nfunction getCrypto(): Crypto {\n return 'webcrypto' in globalThis.crypto\n ? (globalThis.crypto.webcrypto as unknown as Crypto)\n : globalThis.crypto;\n}\n\n/**\n * Base64 URL encode a string.\n * @see https://www.oauth.com/oauth2-servers/pkce/authorization-request/\n */\nconst encode = (value: string) =>\n btoa(value).replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '');\n\nasync function sha256(input: string) {\n const hashBuffer = await getCrypto().subtle.digest('SHA-256', new TextEncoder().encode(input));\n return String.fromCharCode(...new Uint8Array(hashBuffer));\n}\n\n/**\n * Character set for generating random alpha-numeric strings.\n */\nconst CHARSET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';\n\n/**\n * Character set allowed to be used in the PKCE `code_verifier`\n * @see https://www.rfc-editor.org/rfc/rfc7636#section-4.1\n */\nconst PKCE_SAFE_CHARSET = `${CHARSET}-._~`;\n/**\n * Create a Code Verifier for PKCE\n * @see https://www.rfc-editor.org/rfc/rfc7636#section-4.1\n */\nexport function generateCodeVerifier() {\n /**\n * @todo Make length random between 43 and 128 characters\n */\n return Array.from(getCrypto().getRandomValues(new Uint8Array(43)))\n .map((v) => PKCE_SAFE_CHARSET[v % PKCE_SAFE_CHARSET.length])\n .join('');\n}\n\n/**\n * Create a Code Challenge from a provided Code Verifier (assumes S256 `code_challenge_method`).\n * @see https://www.rfc-editor.org/rfc/rfc7636#section-4.2\n */\nexport async function generateCodeChallenge(verifier: string) {\n const hashed = await sha256(verifier);\n return encode(hashed);\n}\n\nexport function generateState() {\n return Array.from(getCrypto().getRandomValues(new Uint8Array(16)))\n .map((v) => CHARSET[v % CHARSET.length])\n .join('');\n}\n\n/**\n * @see https://www.oauth.com/oauth2-servers/pkce/authorization-code-exchange/\n */\nexport type AuthorizationCodeExchangeParameters = {\n code: string;\n code_verifier: string;\n client_id: string;\n client_secret?: string;\n redirect_uri: string;\n grant_type: 'authorization_code';\n};\n\n/**\n * @see https://www.oauth.com/oauth2-servers/pkce/authorization-request/\n */\nexport type AuthorizationRequestParameters = {\n client_id: string;\n redirect_uri: string;\n response_type: 'code';\n scope: string;\n state: string;\n code_challenge: string;\n code_challenge_method: 'S256' | 'plain';\n};\n\n/**\n * @private\n */\nexport const KEYS = {\n PKCE_STATE: 'pkce_state',\n PKCE_CODE_VERIFIER: 'pkce_code_verifier',\n};\n\ntype Entries = 'state' | 'code_verifier';\n\nexport const store = {\n getKey(key: Entries) {\n return key === 'state' ? KEYS.PKCE_STATE : KEYS.PKCE_CODE_VERIFIER;\n },\n get: (entry: Entries) => sessionStorage.getItem(store.getKey(entry)),\n set: (entry: Entries, value: string) => sessionStorage.setItem(store.getKey(entry), value),\n reset: () => {\n sessionStorage.removeItem(KEYS.PKCE_STATE);\n sessionStorage.removeItem(KEYS.PKCE_CODE_VERIFIER);\n },\n};\n", "import { getAuthorizationEndpoint, oauth2 } from '../../services/auth/index.js';\nimport {\n generateCodeChallenge,\n generateCodeVerifier,\n generateState,\n AuthorizationRequestParameters,\n AuthorizationCodeExchangeParameters,\n isSupported,\n store,\n} from './pkce.js';\n\nimport type { AuthorizationManagerConfiguration } from './AuthorizationManager.js';\n\nexport type GetTokenOptions = {\n /**\n * Whether or not the URL should be replaced after processing the token.\n * This is used to remove the `?code=...&state=...` parameters from the URL after the token is retrieved.\n * If set to `false`, the URL will remain unchanged.\n * @default true\n */\n shouldReplace?: boolean;\n /**\n * When set to `true` in addition to the `scope` values originally requested, Globus Auth\n * will return tokens for **all** of the scopes that the user has consented to, for\n * the requesting client.\n * @default false\n * @private\n */\n includeConsentedScopes?: boolean;\n};\n\nexport type TransportOptions = Pick<\n AuthorizationManagerConfiguration,\n 'client' | 'redirect' | 'scopes'\n> & {\n /**\n * Query parameters to include in the authorization request.\n *\n * The transport will include all parameters required for a default OAuth PKCE flow, but\n * these parameters can be overridden or extended with this option.\n */\n params?: {\n [key: string]: string;\n };\n};\n\nexport type RedirectTransportOptions = TransportOptions;\nexport class RedirectTransport {\n #options: RedirectTransportOptions;\n\n constructor(options: RedirectTransportOptions) {\n this.#options = options;\n if (RedirectTransport.supported === false) {\n throw new Error('RedirectTransport is not supported in this environment.');\n }\n }\n\n static supported = isSupported();\n\n /**\n * For the redirect transport, sending the request will redirect the user to the authorization endpoint, initiating the OAuth flow.\n */\n async send() {\n /**\n * Since we'll be using PKCE, we need to generate a code verifier and challenge\n * for the OAuth handshake.\n */\n const verifier = generateCodeVerifier();\n const challenge = await generateCodeChallenge(verifier);\n /**\n * If there is caller-provided `state`, use it; Otherwise, generate a state parameter.\n */\n const state = this.#options.params?.['state'] ?? generateState();\n /**\n * The verifier and state are stored in session storage so that we can validate\n * the response when we receive it.\n */\n store.set('code_verifier', verifier);\n store.set('state', state);\n\n const params: AuthorizationRequestParameters = {\n response_type: 'code',\n client_id: this.#options.client,\n scope: this.#options.scopes || '',\n redirect_uri: this.#options.redirect,\n state,\n code_challenge: challenge,\n code_challenge_method: 'S256',\n ...(this.#options.params || {}),\n };\n\n const url = new URL(getAuthorizationEndpoint());\n url.search = new URLSearchParams(params).toString();\n\n window.location.assign(url.toString());\n }\n\n /**\n * Parse the current URL for the authorization code (`?code=...`) and exchange it for an access token when available.\n * - When the URL is processed and exchanged for an access token, the page is redirected to the current URL without the `?code=...&state=...` parameters.\n */\n async getToken(\n options: GetTokenOptions = { shouldReplace: true, includeConsentedScopes: false },\n ) {\n const url = new URL(window.location.href);\n const params = new URLSearchParams(url.search);\n /**\n * Check for an error in the OAuth flow.\n * @see https://www.oauth.com/oauth2-servers/pkce/authorization-request/\n */\n if (params.get('error')) {\n throw new Error(\n params.get('error_description') || 'An error occurred during the authorization process.',\n );\n }\n\n const code = params.get('code');\n\n /**\n * If we don't have a `code` parameter, we can't exchange it for an access token.\n */\n if (!code) return undefined;\n\n /**\n * Grab the PKCE information from session storage.\n */\n const state = store.get('state');\n const verifier = store.get('code_verifier');\n /**\n * Now that we have the values in memory, we can remove them from session storage.\n */\n store.reset();\n\n /**\n * Validate the `state` parameter matches the preserved state (to prevent CSRF attacks).\n */\n if (params.get('state') !== state) {\n throw new Error(\n 'Invalid State. The received \"state\" parameter does not match the expected state.',\n );\n }\n /**\n * Ensure we have a valid code verifier.\n */\n if (!verifier) {\n throw new Error('Invalid Code Verifier');\n }\n\n /**\n * Prepare the payload for the PKCE token exchange.\n */\n const payload: AuthorizationCodeExchangeParameters = {\n code,\n client_id: this.#options.client,\n /**\n * Retrieve the code verifier from session storage.\n */\n code_verifier: verifier,\n redirect_uri: this.#options.redirect,\n grant_type: 'authorization_code',\n };\n\n const response = await (\n await oauth2.token.exchange({\n query: options.includeConsentedScopes\n ? {\n include_consented_scopes: true,\n }\n : undefined,\n payload,\n })\n ).json();\n\n if (options.shouldReplace) {\n /**\n * Remove the `code` and `state` parameters from the URL.\n */\n params.delete('code');\n params.delete('state');\n /**\n * Update the URL with the new query string.\n */\n url.search = params.toString();\n /**\n * Redirect the page to the new URL (without the `code` and `state` parameters)/\n */\n window.location.replace(url);\n }\n return response;\n }\n}\n", "import { CONFIG, isToken } from '../../services/auth/index.js';\n\nimport { SERVICES, type Service } from '../global.js';\nimport { AuthorizationManager } from './AuthorizationManager.js';\n\nimport type { Token, TokenResponse } from '../../services/auth/types.js';\n\nexport type StoredToken = Token & {\n /**\n * Tokens stored before the introduction of the `__metadata` field will be missing this property.\n * @since 4.3.0\n */\n __metadata?: {\n /**\n * The timestamp when the token was added to the storage as a number of milliseconds since the Unix epoch.\n *\n * **IMPORTANT**: This value might **not** represent the time when the token was created by the authorization server.\n */\n created: number;\n /**\n * The timestamp when the token will expire as a number of milliseconds since the Unix epoch, based\n * on the `expires_in` value from the token response and the time when the token was stored.\n */\n expires: number | null;\n };\n};\n\nexport class TokenManager {\n #manager: AuthorizationManager;\n\n constructor(options: { manager: AuthorizationManager }) {\n this.#manager = options.manager;\n }\n\n /**\n * Retrieve and parse an item from the storage.\n */\n #getTokenFromStorage(key: string) {\n const raw = this.#manager.storage.getItem(key) || 'null';\n let token: StoredToken | null = null;\n try {\n const parsed = JSON.parse(raw);\n if (isToken(parsed)) {\n token = parsed;\n }\n } catch (e) {\n // no-op\n }\n return token;\n }\n\n #getTokenForService(service: Service) {\n const resourceServer = CONFIG.RESOURCE_SERVERS?.[service];\n return this.getByResourceServer(resourceServer);\n }\n\n getByResourceServer(resourceServer: string): StoredToken | null {\n return this.#getTokenFromStorage(`${this.#manager.storageKeyPrefix}${resourceServer}`);\n }\n\n get auth(): StoredToken | null {\n return this.#getTokenForService(SERVICES.AUTH);\n }\n\n get transfer(): StoredToken | null {\n return this.#getTokenForService(SERVICES.TRANSFER);\n }\n\n get flows(): StoredToken | null {\n return this.#getTokenForService(SERVICES.FLOWS);\n }\n\n get groups(): StoredToken | null {\n return this.#getTokenForService(SERVICES.GROUPS);\n }\n\n get search(): StoredToken | null {\n return this.#getTokenForService(SERVICES.SEARCH);\n }\n\n get timer(): StoredToken | null {\n return this.#getTokenForService(SERVICES.TIMERS);\n }\n\n get compute(): StoredToken | null {\n return this.#getTokenForService(SERVICES.COMPUTE);\n }\n\n gcs(endpoint: string): StoredToken | null {\n return this.getByResourceServer(endpoint);\n }\n\n getAll(): StoredToken[] {\n const entries = Object.keys(this.#manager.storage).reduce(\n (acc: (StoredToken | null)[], key) => {\n if (key.startsWith(this.#manager.storageKeyPrefix)) {\n acc.push(this.#getTokenFromStorage(key));\n }\n return acc;\n },\n [],\n );\n return entries.filter(isToken);\n }\n\n /**\n * Add a token to the storage.\n */\n add(token: Token | TokenResponse) {\n const created = Date.now();\n const expires = created + token.expires_in * 1000;\n this.#manager.storage.setItem(\n `${this.#manager.storageKeyPrefix}${token.resource_server}`,\n JSON.stringify({\n ...token,\n /**\n * Add metadata to the token to track when it was created and when it expires.\n */\n __metadata: {\n created,\n expires,\n },\n }),\n );\n if ('other_tokens' in token) {\n token.other_tokens?.forEach((t) => {\n this.add(t);\n });\n }\n }\n\n remove(token: Token | TokenResponse) {\n this.#manager.storage.removeItem(`${this.#manager.storageKeyPrefix}${token.resource_server}`);\n }\n\n /**\n * Determines whether or not a stored token is expired.\n * @param token The token to check.\n * @param augment An optional number of milliseconds to add to the current time when checking the expiration.\n * @returns `true` if the token is expired, `false` if it is not expired, and `undefined` if the expiration status cannot be determined\n * based on the token's metadata. This can happen if the token is missing the `__metadata` field or the `expires` field.\n */\n static isTokenExpired(token: StoredToken | null, augment: number = 0): boolean | undefined {\n /* eslint-disable no-underscore-dangle */\n if (!token || !token.__metadata || typeof token.__metadata.expires !== 'number') {\n return undefined;\n }\n return Date.now() + augment >= token.__metadata.expires;\n /* eslint-enable no-underscore-dangle */\n }\n}\n", "/**\n * An in-memory implementation of the `Storage` interface.\n * @see https://developer.mozilla.org/en-US/docs/Web/API/Storage\n */\nexport class MemoryStorage implements Storage {\n #storage: Record<string, string | null> = {};\n\n getItem(key: string) {\n return this.#storage[key] !== undefined ? this.#storage[key] : null;\n }\n\n setItem(key: string, value: string) {\n this.#storage[key] = value;\n }\n\n removeItem(key: string) {\n delete this.#storage[key];\n }\n\n key(index: number) {\n return Object.keys(this.#storage)[index];\n }\n\n clear() {\n this.#storage = {};\n }\n\n get length() {\n return Object.keys(this.#storage).length;\n }\n}\n", "import { getAuthorizationEndpoint, oauth2 } from '../../services/auth/index.js';\nimport {\n generateCodeChallenge,\n generateCodeVerifier,\n generateState,\n AuthorizationRequestParameters,\n AuthorizationCodeExchangeParameters,\n isSupported,\n store,\n} from './pkce.js';\n\nimport type { TransportOptions } from './RedirectTransport.js';\n\nexport type PopupTransportOptions = TransportOptions;\n\nconst MESSAGE_SOURCE = 'globus-sdk';\n\n/**\n * The `PopupTransport` (`popup`) uses a popup window to initiate the OAuth 2.0 using PKCE.\n *\n * When using the `PopupTransport`, the `redirect` parameter should be to a location\n * that will transmit the URL back to the opener. This can be done using `AuthorizationManager.handleCodeRedirect()`, or\n * manually by calling `window.opener.postMessage()`.\n *\n * @experimental\n */\nexport class PopupTransport {\n #options: PopupTransportOptions;\n\n #window: Window | null = null;\n\n constructor(options: PopupTransportOptions) {\n this.#options = options;\n if (PopupTransport.supported === false) {\n throw new Error('PopupTransport is not supported in this environment.');\n }\n }\n\n /**\n * The `PopupTransport` is supported in environments where the `window` object is available.\n */\n static supported =\n isSupported() && 'window' in globalThis && typeof globalThis.window.open === 'function';\n\n /**\n * For the redirect transport, sending the request will redirect the user to the authorization endpoint, initiating the OAuth flow.\n */\n async send() {\n /**\n * Since we'll be using PKCE, we need to generate a code verifier and challenge\n * for the OAuth handshake.\n */\n const verifier = generateCodeVerifier();\n const challenge = await generateCodeChallenge(verifier);\n /**\n * If there is caller-provided `state`, use it; Otherwise, generate a state parameter.\n */\n const state = this.#options.params?.['state'] ?? generateState();\n /**\n * The verifier and state are stored in session storage so that we can validate\n * the response when we receive it.\n */\n store.set('code_verifier', verifier);\n store.set('state', state);\n\n const params: AuthorizationRequestParameters = {\n response_type: 'code',\n client_id: this.#options.client,\n scope: this.#options.scopes || '',\n redirect_uri: this.#options.redirect,\n state,\n code_challenge: challenge,\n code_challenge_method: 'S256',\n ...(this.#options.params || {}),\n };\n\n const url = new URL(getAuthorizationEndpoint());\n url.search = new URLSearchParams(params).toString();\n\n const promise = new Promise((resolve) => {\n window.addEventListener(\n 'message',\n async (e) => {\n const { data } = e;\n if (e.origin !== window.location.origin || data?.source !== MESSAGE_SOURCE) {\n return;\n }\n this.#window?.close();\n const response = await this.#getToken(data.url);\n resolve(response);\n },\n false,\n );\n });\n\n this.#window = window.open(url.toString(), '_blank', 'width=800,height=600');\n\n if (!this.#window) {\n throw new Error('Unable to open window for PopupTransport.');\n }\n\n this.#window.focus();\n return promise;\n }\n\n async #getToken(href: string) {\n const url = new URL(href);\n const params = new URLSearchParams(url.search);\n /**\n * Check for an error in the OAuth flow.\n * @see https://www.oauth.com/oauth2-servers/pkce/authorization-request/\n */\n if (params.get('error')) {\n throw new Error(\n params.get('error_description') || 'An error occurred during the authorization process.',\n );\n }\n\n const code = params.get('code');\n\n /**\n * If we don't have a `code` parameter, we can't exchange it for an access token.\n */\n if (!code) return undefined;\n\n /**\n * Grab the PKCE information from session storage.\n */\n const state = store.get('state');\n const verifier = store.get('code_verifier');\n /**\n * Now that we have the values in memory, we can remove them from session storage.\n */\n store.reset();\n\n /**\n * Validate the `state` parameter matches the preserved state (to prevent CSRF attacks).\n */\n if (params.get('state') !== state) {\n throw new Error(\n 'Invalid State. The received \"state\" parameter does not match the expected state.',\n );\n }\n /**\n * Ensure we have a valid code verifier.\n */\n if (!verifier) {\n throw new Error('Invalid Code Verifier');\n }\n /**\n * Prepare the payload for the PKCE token exchange.\n */\n const payload: AuthorizationCodeExchangeParameters = {\n code,\n client_id: this.#options.client,\n /**\n * Retrieve the code verifier from session storage.\n */\n code_verifier: verifier,\n redirect_uri: this.#options.redirect,\n grant_type: 'authorization_code',\n };\n const response = await (\n await oauth2.token.exchange({\n payload,\n })\n ).json();\n return response;\n }\n\n // eslint-disable-next-line class-methods-use-this\n getToken() {\n if (!window.opener) {\n return;\n }\n\n window.opener.postMessage(\n {\n source: MESSAGE_SOURCE,\n url: window.location.href,\n },\n window.location.origin,\n );\n }\n}\n"],
|
|
4
|
+
"sourcesContent": ["/**\n * @module Authorization\n * @description Provides modules for interacting with Globus-related authorization contexts in your application.\n * @example\n * import { authorization } from \"globus/sdk\";\n * const manager = authorization.create(...);\n */\nimport {\n AuthorizationManager,\n type AuthorizationManagerConfiguration,\n} from './AuthorizationManager.js';\n\n/**\n * Create an instance of the {@link AuthorizationManager}.\n */\nexport function create(configuration: AuthorizationManagerConfiguration) {\n return new AuthorizationManager(configuration);\n}\n\nexport { AuthorizationManager, AuthorizationManagerConfiguration };\n", "import { jwtDecode } from 'jwt-decode';\n\nimport { isGlobusAuthTokenResponse, isRefreshToken, oauth2 } from '../../services/auth/index.js';\nimport { RESOURCE_SERVERS } from '../../services/auth/config.js';\n\nimport { log } from '../logger.js';\n\nimport { Event } from './Event.js';\nimport { GetTokenOptions, RedirectTransport, TransportOptions } from './RedirectTransport.js';\nimport { TokenManager } from './TokenManager.js';\n\nimport {\n isConsentRequiredError,\n isAuthorizationRequirementsError,\n AuthorizationRequirementsError,\n ConsentRequiredError,\n toAuthorizationQueryParams,\n} from '../errors.js';\n\nimport type {\n JwtUserInfo,\n Token,\n TokenResponse,\n TokenWithRefresh,\n} from '../../services/auth/types.js';\nimport { MemoryStorage } from '../storage/memory.js';\nimport { PopupTransport } from './PopupTransport.js';\n\nconst TRANSPORTS = {\n redirect: RedirectTransport,\n popup: PopupTransport,\n};\n\nexport type AuthorizationManagerConfiguration = {\n client: string;\n scopes?: string;\n redirect: string;\n /**\n * The storage system used by the `AuthorizationManager`.\n *\n * By default, the `AuthorizationManager` uses an in-memory storage, this option is secure by default.\n *\n * If you want to persist the state of the `AuthorizationManager`, you can use `localStorage`, or provide your own storage system.\n * **It is important to note that using the `localStorage`, or any persistant storage option will preserve authorization and refresh tokens of users.**\n * Best practices for ensuring the security of your application should be followed to protect this data (e.g., ensuring XSS protection).\n *\n * @default MemoryStorage\n */\n storage?: Storage;\n /**\n * The transport method to use for the authorization flow.\n * @default 'redirect'\n */\n transport?: keyof typeof TRANSPORTS;\n /**\n * @private\n * @default DEFAULT_CONFIGURATION.useRefreshTokens\n */\n useRefreshTokens?: boolean;\n /**\n * @private\n * @default DEFAULT_CONFIGURATION.defaultScopes\n */\n defaultScopes?: string | false;\n /**\n * Provide an object with event listeners to attach to the instance.\n * This is useful if you need to listen to events that might dispatch immediately\n * after the creation of the instance (constructor), e.g., the `authenticated`.\n */\n events?: Partial<{\n [Event in keyof AuthorizationManager['events']]: Parameters<\n AuthorizationManager['events'][Event]['addListener']\n >[0];\n }>;\n};\n\nconst DEFAULT_CONFIGURATION = {\n useRefreshTokens: false,\n defaultScopes: 'openid profile email',\n transport: 'redirect' as const,\n};\n\nconst DEFAULT_HANDLE_ERROR_OPTIONS = {\n execute: true,\n additionalParams: undefined,\n};\n\n/**\n * Provides management of Globus authorization context for your application.\n * - Handles the OAuth protcol flow (via PKCE)\n * - Token lifecycle management\n * - Common errors (e.g., `ConsentRequired`, `authorization_requirements`)\n *\n * Once you configure your instance, you can determine the authenticated state using `manager.authenticated`.\n *\n * To prompt a user to authenticate, call `manager.login()` on user interaction \u2013 this will initiate the OAuth protocol flow with your configured client and scopes, resulting in an initial redirect to Globus Auth.\n *\n * Once the user authenticates with Globus Auth, they will be redirected to your application using the configured `redirect` URL. On this URL, you will need to call `manager.handleCodeRedirect` (using a manager instance configured in the same manner that initiated the `manager.login()` call) to complete the PKCE flow, exchanging the provided code for a valid token, or tokens.\n *\n * All tokens managed by the `AuthorizationManager` instance can be found on `manager.token`.\n *\n * ### Registering your Globus Application\n *\n * The `AuthorizationManager` expects your Globus Application to be registered as an OAuth public client.\n * In this Globus Web Application, this option is referenced as \"_Register a thick client or script that will be installed and run by users on their devices_\".\n *\n * @example Creating an AuthorizationManager instance.\n * ```ts\n * import { authorization } from \"globus/sdk\";\n *\n * const manager = authorization.create({\n * // Your registered Globus Application client ID.\n * client: '...',\n * // The redirect URL for your application; Where you will call `manager.handleCodeRedirect()`\n * redirect: 'https://example.com/callback',\n * // Known scopes required by your application.\n * scopes: 'urn:globus:auth:scope:transfer.api.globus.org:all',\n * });\n * ```\n *\n * ### Usage with Service Methods\n *\n * Once you have an instance of an `AuthorizationManager`, it can be passed to any service method as `ServiceMethodOptions.manager` or `SDKOptions.manager` option.\n * The service method will determine if a token is required to make the request and will use the `AuthorizationManager` to retrieve the token.\n *\n * @example Using the AuthorizationManager with a service method.\n *```ts\n * import { transfer } from \"globus/sdk\";\n * const manager = authorization.create({ ... });\n * const result = await (\n * await globus.transfer.endpointSearch({\n * query: { filter_fulltext: \"Globus\"},\n * manager\n * })\n * ).json();\n *```\n */\nexport class AuthorizationManager {\n #transport!: RedirectTransport | PopupTransport;\n\n configuration: AuthorizationManagerConfiguration;\n\n /**\n * The storage system used by the `AuthorizationManager`.\n * @implements Storage\n */\n storage: Storage;\n\n #authenticated = false;\n\n /**\n * The `AuthorizationManager` is considered `authenticated` if it has a valid Globus Auth token.\n * It does not necessarily mean that it has a valid token for a specific resource server.\n */\n get authenticated() {\n return this.#authenticated;\n }\n\n /**\n * Set the authenticated state and emit the `authenticated` event.\n */\n set authenticated(value: boolean) {\n /**\n * Avoid emitting the event if the value hasn't changed.\n */\n if (value === this.#authenticated) {\n return;\n }\n this.#authenticated = value;\n this.#emitAuthenticatedState();\n }\n\n tokens: TokenManager;\n\n events = {\n /**\n * Emitted when the authenticated state changes.\n * @event AuthorizationManager.events#authenticated\n * @type {object}\n * @property {boolean} isAuthenticated - Whether the `AuthorizationManager` is authenticated.\n * @property {TokenResponse} [token] - The token response if the `AuthorizationManager` is authenticated.\n */\n authenticated: new Event<\n 'authenticated',\n {\n /**\n * Whether the `AuthorizationManager` is authenticated.\n * @see {@link AuthorizationManager.authenticated}\n */\n isAuthenticated: boolean;\n token?: TokenResponse;\n }\n >('authenticated'),\n /**\n * Emitted when the user revokes their authentication.\n * @event AuthorizationManager.events#revoke\n */\n revoke: new Event('revoke'),\n };\n\n constructor(configuration: AuthorizationManagerConfiguration) {\n /**\n * Configure the storage system for the instance, defaulting to an in-memory storage system.\n */\n\n if (!configuration.client) {\n throw new Error('You must provide a `client` for your application.');\n }\n /**\n * Inject the `openid`, `profile`, `email`, and `offline_access` scopes by default unless\n * explicitly opted out of.\n */\n const scopes =\n configuration.defaultScopes === false\n ? ''\n : (configuration.defaultScopes ?? DEFAULT_CONFIGURATION.defaultScopes);\n\n this.configuration = {\n ...DEFAULT_CONFIGURATION,\n ...configuration,\n scopes: [configuration.scopes ? configuration.scopes : '', scopes]\n .filter((s) => s.length)\n .join(' '),\n };\n\n this.storage = configuration.storage || new MemoryStorage();\n\n /**\n * If an `events` object is provided, add the listeners to the instance before\n * any event might be dispatched.\n */\n if (this.configuration.events) {\n Object.entries(this.configuration.events).forEach(([name, callback]) => {\n if (name in this.events) {\n this.events[name as keyof AuthorizationManager['events']].addListener(callback);\n }\n });\n }\n\n this.tokens = new TokenManager({\n manager: this,\n });\n this.#checkAuthorizationState();\n }\n\n get storageKeyPrefix() {\n return `${this.configuration.client}:`;\n }\n\n /**\n * The user information decoded from the `id_token` (JWT) of the current Globus Auth token.\n * This method can be used instead of `auth.oauth2.userinfo` to get the user information without an additional request.\n *\n * **IMPORTANT**: The `id_token` can only be processed if the `openid` scope is requested during the authorization process.\n *\n * Additionally, the `profile` and `email` scopes are required to get the full user information.\n *\n * @see {@link https://docs.globus.org/api/auth/reference/#oidc_userinfo_endpoint}\n */\n get user() {\n const token = this.getGlobusAuthToken();\n return token && token.id_token ? jwtDecode<JwtUserInfo>(token.id_token) : null;\n }\n\n /**\n * Attempt to refresh all of the tokens managed by the instance.\n * This method will only attempt to refresh tokens that have a `refresh_token` attribute.\n */\n async refreshTokens() {\n log('debug', 'AuthorizationManager.refreshTokens');\n const tokens = await Promise.allSettled(\n this.tokens.getAll().map((token) => {\n if (isRefreshToken(token)) {\n return this.refreshToken(token);\n }\n return Promise.resolve(null);\n }),\n );\n this.#checkAuthorizationState();\n return tokens;\n }\n\n /**\n * Use the `refresh_token` attribute of a token to obtain a new access token.\n * @param token The well-formed token with a `refresh_token` attribute.\n */\n async refreshToken(token: TokenWithRefresh) {\n log('debug', `AuthorizationManager.refreshToken | resource_server=${token.resource_server}`);\n try {\n const response = await (\n await oauth2.token.refresh({\n payload: {\n client_id: this.configuration.client,\n refresh_token: token.refresh_token,\n grant_type: 'refresh_token',\n },\n })\n ).json();\n if (isGlobusAuthTokenResponse(response)) {\n this.addTokenResponse(response);\n return response;\n }\n } catch (error) {\n log('error', `AuthorizationManager.refreshToken | resource_server=${token.resource_server}`);\n }\n return null;\n }\n\n /**\n * Whether or not the instance has a reference to a Globus Auth token.\n */\n hasGlobusAuthToken() {\n return this.getGlobusAuthToken() !== null;\n }\n\n /**\n * Retrieve the Globus Auth token managed by the instance.\n */\n getGlobusAuthToken() {\n const entry = this.storage.getItem(`${this.storageKeyPrefix}${RESOURCE_SERVERS.AUTH}`);\n return entry ? JSON.parse(entry) : null;\n }\n\n #checkAuthorizationState() {\n log('debug', 'AuthorizationManager.#checkAuthorizationState');\n if (this.hasGlobusAuthToken()) {\n this.authenticated = true;\n }\n }\n\n async #emitAuthenticatedState() {\n const isAuthenticated = this.authenticated;\n const token = this.getGlobusAuthToken() ?? undefined;\n await this.events.authenticated.dispatch({\n isAuthenticated,\n token,\n });\n }\n\n /**\n * Reset the authenticated state and clear all tokens from storage.\n * This method **does not** emit the `revoke` event. If you need to emit the `revoke` event, use the `AuthorizationManager.revoke` method.\n */\n reset() {\n Object.keys(this.storage).forEach((key) => {\n if (key.startsWith(this.storageKeyPrefix)) {\n this.storage.removeItem(key);\n }\n });\n this.authenticated = false;\n }\n\n /**\n * A private utility method to add the `offline_access` scope to a scope string if the `useRefreshTokens` configuration is set to `true`.\n * @param scopes The scope string to modify.\n */\n #withOfflineAccess(scopes: string) {\n return `${scopes}${this.configuration.useRefreshTokens ? ' offline_access' : ''}`;\n }\n\n #buildTransport(options?: Partial<TransportOptions>) {\n const { scopes, ...overrides } = options ?? {};\n const TransportFactory = TRANSPORTS[this.configuration.transport || 'redirect'];\n\n let scopesToRequest = this.#withOfflineAccess(scopes ?? (this.configuration.scopes || ''));\n\n if (this.storage instanceof MemoryStorage) {\n /**\n * If the in-memory storage is used, we have to make sure when requesting additional\n * consent the original configured scopes are included in the request.\n *\n * This will ensure we recieve a token for all of resource servers that were originally requested,\n * in addition to any new scopes that are requested.\n */\n scopesToRequest = [\n // Use a Set to deduplicate the scopes.\n ...new Set(\n scopesToRequest.split(' ').concat((this.configuration?.scopes || '').split(' ')),\n ),\n ].join(' ');\n }\n\n return new TransportFactory({\n client: this.configuration.client,\n redirect: this.configuration.redirect,\n scopes: scopesToRequest,\n ...overrides,\n params: {\n ...overrides?.params,\n },\n });\n }\n\n /**\n * Initiate the login process by redirecting to the Globus Auth login page.\n *\n * **IMPORTANT**: This method will **reset the instance state before initiating the login process,\n * including clearing all tokens from storage**. If you need to maintain the current state,\n * use the `AuthorizationManager.prompt()` method.\n *\n * @example Passing parameters to the transport.\n * const result = await manager.login({\n * additionalParams: {\n * redirect_uri: '/oauth/redirect-uri-runtime-override',\n * },\n * });\n */\n async login(options = { additionalParams: {} }) {\n log('debug', 'AuthorizationManager.login');\n this.reset();\n /**\n * In the future, it's possible that we may want to support different types of transports.\n */\n const transport = this.#buildTransport({ params: options?.additionalParams });\n const result = await transport.send();\n if (isGlobusAuthTokenResponse(result)) {\n this.addTokenResponse(result);\n }\n return result;\n }\n\n /**\n * Prompt the user to authenticate with Globus Auth.\n *\n * @example Passing parameters to the transport.\n * const result = await manager.prompt({\n * additionalParams: {\n * redirect_uri: '/oauth/redirect-uri-runtime-override',\n * },\n * });\n */\n async prompt(options?: Partial<TransportOptions>) {\n log('debug', 'AuthorizationManager.prompt');\n const transport = this.#buildTransport(options);\n const result = await transport.send();\n if (isGlobusAuthTokenResponse(result)) {\n this.addTokenResponse(result);\n }\n return result;\n }\n\n /**\n * This method will attempt to complete the PKCE protocol flow.\n */\n async handleCodeRedirect(\n options: {\n shouldReplace?: GetTokenOptions['shouldReplace'];\n includeConsentedScopes?: GetTokenOptions['includeConsentedScopes'];\n additionalParams?: TransportOptions['params'];\n } = { shouldReplace: true, additionalParams: {} },\n ) {\n log('debug', 'AuthorizationManager.handleCodeRedirect');\n const response = await this.#buildTransport({ params: options?.additionalParams }).getToken({\n shouldReplace: options?.shouldReplace,\n includeConsentedScopes: options?.includeConsentedScopes,\n });\n if (isGlobusAuthTokenResponse(response)) {\n log(\n 'debug',\n `AuthorizationManager.handleCodeRedirect | response=${JSON.stringify(response)}`,\n );\n this.addTokenResponse(response);\n }\n return response;\n }\n\n /**\n * Handle an error response from a Globus service in the context of this `AuthorizationManager`.\n * This method will introspect the response and attempt to handle any errors that should result\n * in some additional Globus Auth interaction.\n * @param response The error response from a Globus service.\n * @param {object|boolean} options Options for handling the error response. If a boolean is provided, this will be treated as the `options.execute` value.\n * @param options.execute Whether to execute the handler immediately.\n * @param options.additionalParams Additional query parameters to be included with the transport generated URL.\n */\n async handleErrorResponse(\n response: Record<string, unknown>,\n options?: { execute?: true; additionalParams?: TransportOptions['params'] } | true,\n ): Promise<void>;\n async handleErrorResponse(\n response: Record<string, unknown>,\n options?: { execute?: false; additionalParams?: TransportOptions['params'] } | false,\n ): Promise<() => Promise<void>>;\n async handleErrorResponse(\n response: Record<string, unknown>,\n options?: { execute?: boolean; additionalParams?: TransportOptions['params'] } | boolean,\n ) {\n const opts =\n typeof options === 'boolean'\n ? {\n ...DEFAULT_HANDLE_ERROR_OPTIONS,\n execute: options,\n }\n : {\n ...DEFAULT_HANDLE_ERROR_OPTIONS,\n ...options,\n };\n log(\n 'debug',\n `AuthorizationManager.handleErrorResponse | response=${JSON.stringify(response)} execute=${opts.execute}`,\n );\n let handler = async () => {};\n if (isAuthorizationRequirementsError(response)) {\n log(\n 'debug',\n 'AuthorizationManager.handleErrorResponse | error=AuthorizationRequirementsError',\n );\n handler = async () => {\n await this.handleAuthorizationRequirementsError(response, {\n additionalParams: opts.additionalParams,\n });\n };\n }\n if (isConsentRequiredError(response)) {\n log('debug', 'AuthorizationManager.handleErrorResponse | error=ConsentRequiredError');\n handler = async () => {\n await this.handleConsentRequiredError(response, {\n additionalParams: opts.additionalParams,\n });\n };\n }\n if ('code' in response && response['code'] === 'AuthenticationFailed') {\n log('debug', 'AuthorizationManager.handleErrorResponse | error=AuthenticationFailed');\n handler = async () => {\n await this.revoke();\n };\n }\n\n const returnValue = opts.execute === true ? await handler() : handler;\n return returnValue;\n }\n\n /**\n * Process a well-formed Authorization Requirements error response from a Globus service\n * and redirect the user to the Globus Auth login page with the necessary parameters.\n */\n async handleAuthorizationRequirementsError(\n response: AuthorizationRequirementsError,\n options?: { additionalParams?: TransportOptions['params'] },\n ) {\n this.#transport = this.#buildTransport({\n params: {\n prompt: 'login',\n ...toAuthorizationQueryParams(response),\n ...options?.additionalParams,\n },\n });\n await this.#transport.send();\n }\n\n /**\n * Process a well-formed `ConsentRequired` error response from a Globus service\n * and redirect the user to the Globus Auth login page with the necessary parameters.\n */\n async handleConsentRequiredError(\n response: ConsentRequiredError,\n options?: { additionalParams?: TransportOptions['params'] },\n ) {\n this.#transport = this.#buildTransport({\n scopes: this.#withOfflineAccess(response.required_scopes.join(' ')),\n params: {\n ...options?.additionalParams,\n },\n });\n await this.#transport.send();\n }\n\n /**\n * Add a Globus Auth token response to storage, if `other_tokens` are present they are also added.\n * This method is mostly used internally by the `AuthorizationManager`, but can be used by downstream\n * consumers to add tokens to storage if necessary.\n */\n addTokenResponse = (token: Token | TokenResponse) => {\n this.tokens.add(token);\n this.#checkAuthorizationState();\n };\n\n /**\n * Call `AuthroizationManager.reset`, revoke all of the available tokns, and emit the `revoke` event.\n * @emits AuthorizationManager.events#revoke\n * @see AuthorizationManager.reset\n */\n async revoke() {\n log('debug', 'AuthorizationManager.revoke');\n const revocation = Promise.all(this.tokens.getAll().map(this.#revokeToken.bind(this)));\n this.reset();\n await revocation;\n await this.events.revoke.dispatch();\n }\n\n /**\n * Revoke a token from a resource server.\n */\n #revokeToken(token: Token) {\n log('debug', `AuthorizationManager.revokeToken | resource_server=${token.resource_server}`);\n return oauth2.token.revoke({\n payload: {\n client_id: this.configuration.client,\n token: token.access_token,\n },\n });\n }\n}\n", "import { ID as TRANSFER } from '../transfer/config.js';\nimport { ID as FLOWS } from '../flows/config.js';\nimport { ID as TIMERS } from '../timers/config.js';\nimport { ID as GROUPS } from '../groups/config.js';\nimport { ID as SEARCH } from '../search/config.js';\nimport { ID as COMPUTE } from '../compute/config.js';\n\nimport type { Environment } from '../../core/global.js';\n\nexport const ID = 'AUTH' as const;\nexport const HOSTS: Partial<Record<Environment, string>> = {\n integration: 'auth.integration.globuscs.info',\n sandbox: 'auth.sandbox.globuscs.info',\n production: 'auth.globus.org',\n test: 'auth.test.globuscs.info',\n staging: 'auth.staging.globuscs.info',\n preview: 'auth.preview.globus.org',\n};\n\nexport const SCOPES = {\n VIEW_IDENTITIES: 'urn:globus:auth:scope:auth.globus.org:view_identities',\n};\n\nexport const RESOURCE_SERVERS = {\n [ID]: 'auth.globus.org',\n [TRANSFER]: 'transfer.api.globus.org',\n [FLOWS]: 'flows.globus.org',\n [GROUPS]: 'groups.api.globus.org',\n [SEARCH]: 'search.api.globus.org',\n [TIMERS]: '524230d7-ea86-4a52-8312-86065a9e0417',\n [COMPUTE]: 'funcx_service',\n};\n", "import type { Environment } from '../../core/global.js';\n\nexport const ID = 'TRANSFER' as const;\n\nexport const SCOPES = {\n ALL: 'urn:globus:auth:scope:transfer.api.globus.org:all',\n};\n\nexport const HOSTS: Partial<Record<Environment, string>> = {\n sandbox: 'transfer.api.sandbox.globuscs.info',\n production: 'transfer.api.globusonline.org',\n staging: 'transfer.api.staging.globuscs.info',\n integration: 'transfer.api.integration.globuscs.info',\n test: 'transfer.api.test.globuscs.info',\n preview: 'transfer.api.preview.globus.org',\n};\n", "import type { Environment } from '../../core/global.js';\n\nexport const ID = 'FLOWS' as const;\nexport const HOSTS: Partial<Record<Environment, string>> = {\n sandbox: 'sandbox.flows.automate.globus.org',\n production: 'flows.globus.org',\n staging: 'staging.flows.automate.globus.org',\n integration: 'integration.flows.automate.globus.org',\n test: 'test.flows.automate.globus.org',\n preview: 'preview.flows.automate.globus.org',\n};\n\n/**\n * @see https://docs.globus.org/api/flows/overview/#scopes\n */\nexport const SCOPES = {\n MANAGE_FLOWS: 'https://auth.globus.org/scopes/eec9b274-0c81-4334-bdc2-54e90e689b9a/manage_flows',\n VIEW_FLOWS: 'https://auth.globus.org/scopes/eec9b274-0c81-4334-bdc2-54e90e689b9a/view_flows',\n RUN: 'https://auth.globus.org/scopes/eec9b274-0c81-4334-bdc2-54e90e689b9a/run',\n RUN_STATUS: 'https://auth.globus.org/scopes/eec9b274-0c81-4334-bdc2-54e90e689b9a/run_status',\n RUN_MANAGE: 'https://auth.globus.org/scopes/eec9b274-0c81-4334-bdc2-54e90e689b9a/run_manage',\n};\n", "import type { Environment } from '../../core/global.js';\n\nexport const ID = 'TIMERS' as const;\nexport const HOSTS: Partial<Record<Environment, string>> = {\n sandbox: 'sandbox.timer.automate.globus.org',\n production: 'timer.automate.globus.org',\n staging: 'staging.timer.automate.globus.org',\n integration: 'integration.timer.automate.globus.org',\n test: 'test.timer.automate.globus.org',\n preview: 'preview.timer.automate.globus.org',\n};\n", "import type { Environment } from '../../core/global.js';\n\nexport const ID = 'GROUPS' as const;\nexport const HOSTS: Partial<Record<Environment, string>> = {\n sandbox: 'groups.api.sandbox.globuscs.info',\n production: 'groups.api.globus.org',\n staging: 'groups.api.staging.globuscs.info',\n integration: 'groups.api.integration.globuscs.info',\n test: 'groups.api.test.globuscs.info',\n preview: 'groups.api.preview.globuscs.info',\n};\n\n/**\n * @see https://docs.globus.org/api/groups/#scopes\n */\nexport const SCOPES = {\n ALL: 'urn:globus:auth:scope:groups.api.globus.org:all',\n VIEW_MY: 'urn:globus:auth:scope:groups.api.globus.org:view_my_groups_and_membership',\n};\n", "import type { Environment } from '../../core/global.js';\n\nexport const ID = 'SEARCH' as const;\nexport const HOSTS: Partial<Record<Environment, string>> = {\n sandbox: 'search.api.sandbox.globuscs.info',\n production: 'search.api.globus.org',\n staging: 'search.api.staging.globuscs.info',\n integration: 'search.api.integration.globuscs.info',\n test: 'search.api.test.globuscs.info',\n preview: 'search.api.preview.globus.org',\n};\n\n/**\n * @see https://docs.globus.org/api/search/api_usage/#scopes\n */\nexport const SCOPES = {\n ALL: 'urn:globus:auth:scope:search.api.globus.org:all',\n INGEST: 'urn:globus:auth:scope:search.api.globus.org:ingest',\n SEARCH: 'urn:globus:auth:scope:search.api.globus.org:search',\n};\n", "import type { Environment } from '../../core/global.js';\n\nexport const ID = 'COMPUTE' as const;\nexport const HOSTS: Partial<Record<Environment, string>> = {\n sandbox: 'compute.api.sandbox.globuscs.info',\n production: 'compute.api.globus.org',\n staging: 'compute.api.staging.globuscs.info',\n integration: 'compute.api.integration.globuscs.info',\n test: 'compute.api.test.globuscs.info',\n preview: 'compute.api.preview.globus.org',\n};\n\nexport const SCOPES = {\n ALL: 'https://auth.globus.org/scopes/facd7ccc-c5f4-42aa-916b-a0e270e2c2a9/all',\n};\n", "/**\n * @module Errors\n * @example\n * import { errors } from \"globus/sdk\";\n * if (errors.isConsentRequiredError(...)) { ... }\n */\nimport type { AuthorizationQueryParameters } from '../services/auth/index.js';\nimport type { AuthorizationRequestParameters } from './authorization/pkce.js';\n\nexport class EnvironmentConfigurationError extends Error {\n override name = 'EnvironmentConfigurationError';\n\n constructor(variable: string, value: unknown) {\n super();\n // eslint-disable-next-line @typescript-eslint/restrict-template-expressions\n this.message = `Invalid configuration value provided for ${variable} (${value}).`;\n }\n}\n\nexport type WellFormedError = {\n code: string;\n message: string;\n};\n\n/**\n * Test an unknown argument to determine if it can be further parsed as a potentnial known error.\n */\nexport function isErrorWellFormed(test: unknown): test is WellFormedError {\n return typeof test === 'object' && test !== null && 'code' in test && 'message' in test;\n}\n\n/**\n * An error that indicates that the user must provide consent for additional scopes.\n * - This error typically encountered when interacting with Globus Transfer or Globus Connect Server.\n * - Many instances of `code: \"ConsentRequire\"` in the Globus platform are being migrated to `AuthorizationRequirementsError`.\n */\nexport type ConsentRequiredError = {\n code: 'ConsentRequired';\n required_scopes: string[];\n [key: string]: unknown;\n};\n\n/**\n * Whether or not the provide object is recognized as a `ConsentRequiredError`.\n * @see {@link ConsentRequiredError}\n */\nexport function isConsentRequiredError(test: unknown): test is ConsentRequiredError {\n return (\n isErrorWellFormed(test) &&\n test.code === 'ConsentRequired' &&\n 'required_scopes' in test &&\n Array.isArray(test.required_scopes)\n );\n}\n\n/**\n * An error that includes an `authorization_parameters` property, a.k.a \"G.A.R.E\".\n *\n * A well-known error shape is provided by services when additional authorization requirements must be met by the session.\n * This object can be converted to parameters accepted by Globus Auth using `sdk.errors.toAuthorizationQueryParams()`.\n */\nexport type AuthorizationRequirementsError = {\n authorization_parameters: {\n session_message?: string;\n session_required_identities?: string[];\n session_required_mfa?: boolean;\n session_required_single_domain?: string[];\n session_required_policies?: string[];\n prompt?: string;\n required_scopes?: string[];\n };\n /**\n * @todo At the moment, most Globus services do not guarentee a `code` property for this error type.\n * Once it becomes more common, this type (and the `isAuthorizationRequirementsError` function) should be updated.\n * @see https://globus-sdk-python.readthedocs.io/en/stable/experimental/auth_requirements_errors.html\n */\n // code: string;\n [key: string]: unknown;\n};\n/**\n * Keys that should not be included in the query string object (not recognized by Globus Auth),\n * but are found on the `AuthorizationRequirementsError` object.\n */\nconst NO_OP_KEYS: (keyof AuthorizationRequirementsError)[] = ['required_scopes'];\n/**\n * Convert an `AuthorizationRequirementsError` to a query string object accepted by Globus Auth.\n */\nexport function toAuthorizationQueryParams(\n error: AuthorizationRequirementsError,\n): AuthorizationQueryParameters & Partial<AuthorizationRequestParameters> {\n /**\n * Map properties from the `AuthorizationRequirementsError` to accepted query parameters.\n */\n const mapped = {\n /**\n * `required_scopes` isn't a query parameter accepted by Globus Auth, but\n * in most cases the `required_scopes` represented in the error are intended\n * to be included in the `scopes` (OAuth) parameter.\n * @see https://docs.globus.org/api/auth/sessions/#client-initiated-authns\n */\n scope: error.authorization_parameters.required_scopes?.join(' '),\n /**\n * We still include the entire `authorization_parameters` object in addition to the mapped values for parsing.\n */\n ...error.authorization_parameters,\n };\n\n return Object.entries(mapped).reduce((acc, [key, v]) => {\n /**\n * Remove keys that are not recognized by Globus Auth and empty values.\n */\n if (NO_OP_KEYS.includes(key) || v === undefined || v === null) {\n return acc;\n }\n /**\n * All other values are converted to strings.\n */\n let value = v;\n if (Array.isArray(value)) {\n value = value.join(',');\n } else if (typeof v === 'boolean') {\n value = value ? 'true' : 'false';\n }\n return { ...acc, [key]: value };\n }, {});\n}\n\n/**\n * Check if an object is an `AuthorizationRequirementsError`.\n * @see {@link AuthorizationRequirementsError}\n */\nexport function isAuthorizationRequirementsError(\n test: unknown,\n): test is AuthorizationRequirementsError {\n return (\n typeof test === 'object' &&\n test !== null &&\n 'authorization_parameters' in test &&\n typeof test.authorization_parameters === 'object' &&\n test.authorization_parameters !== null\n );\n}\n", "const LOG_LEVELS = ['debug', 'info', 'warn', 'error'] as const;\n\ntype LogLevel = (typeof LOG_LEVELS)[number];\n\ntype LogHandler = (...args: unknown[]) => void;\n\ntype Logger = {\n log: LogHandler;\n error?: LogHandler;\n warn?: LogHandler;\n info?: LogHandler;\n debug?: LogHandler;\n};\n/**\n * No logger is set by default.\n */\nlet logger: Logger | undefined;\n/**\n * By default, the logger is set to `error`.\n */\nlet level: number = LOG_LEVELS.indexOf('error');\n/**\n * Set the global logger for the SDK.\n * @param logMechanism The logger to use.\n * @example `log.setLogger(console)`\n */\nexport function setLogger(logMechanism: Logger) {\n logger = logMechanism;\n}\n/**\n * Set the global log level for the logger.\n * @param severity The severity to set the logger to.\n * @example `log.setLogLevel('info')`\n */\nexport function setLogLevel(severity: LogLevel) {\n level = LOG_LEVELS.indexOf(severity);\n}\n/**\n * Log a message to the logger.\n * @param severity The severity of the log entry.\n * @param args The message to log.\n * @private\n */\nexport function log(severity: LogLevel, ...args: unknown[]) {\n if (!logger) return;\n /**\n * If the severity of the entry is less than the logger's configured severity, do not log.\n */\n if (LOG_LEVELS.indexOf(severity) < level) {\n return;\n }\n /**\n * If the logger does not have a handler for the specified severity, use the default `log` handler.\n */\n const handler = logger[severity] ?? logger.log;\n handler(...args);\n}\n", "import * as AUTH from '../services/auth/config.js';\nimport * as TRANSFER from '../services/transfer/config.js';\nimport * as FLOWS from '../services/flows/config.js';\nimport * as GROUPS from '../services/groups/config.js';\nimport * as SEARCH from '../services/search/config.js';\nimport * as TIMERS from '../services/timers/config.js';\nimport * as COMPUTE from '../services/compute/config.js';\n\nimport { EnvironmentConfigurationError } from './errors.js';\nimport { SDKOptions } from '../services/types.js';\nimport { log } from './logger.js';\n\nfunction getRuntime() {\n return typeof window !== 'undefined' ? window : process;\n}\n\nfunction isBrowser(runtime: Window | NodeJS.Process): runtime is Window {\n return typeof window === typeof runtime;\n}\n\nfunction env<T>(key: string, fallback: T): T {\n const runtime = getRuntime();\n let envConfiguration;\n if (isBrowser(runtime)) {\n envConfiguration = runtime;\n } else {\n envConfiguration = runtime.env;\n }\n if (key in envConfiguration) {\n return (envConfiguration as Record<typeof key, T>)[key];\n }\n return fallback;\n}\n\n/**\n * Handlers for: GLOBUS_SDK_ENVIRONMENT\n */\nexport const ENVIRONMENTS = {\n PRODUCTION: 'production',\n PREVIEW: 'preview',\n STAGING: 'staging',\n SANDBOX: 'sandbox',\n INTEGRATION: 'integration',\n TEST: 'test',\n} as const;\n\nexport type Environment = (typeof ENVIRONMENTS)[keyof typeof ENVIRONMENTS];\n\nexport const SERVICES = {\n [AUTH.ID]: AUTH.ID,\n [TRANSFER.ID]: TRANSFER.ID,\n [FLOWS.ID]: FLOWS.ID,\n [GROUPS.ID]: GROUPS.ID,\n [SEARCH.ID]: SEARCH.ID,\n [TIMERS.ID]: TIMERS.ID,\n [COMPUTE.ID]: COMPUTE.ID,\n};\n\nexport type Service = keyof typeof SERVICES;\n\nexport const SERVICE_HOSTS: Record<Service, Partial<Record<Environment, string>>> = {\n [AUTH.ID]: AUTH.HOSTS,\n [TRANSFER.ID]: TRANSFER.HOSTS,\n [FLOWS.ID]: FLOWS.HOSTS,\n [GROUPS.ID]: GROUPS.HOSTS,\n [SEARCH.ID]: SEARCH.HOSTS,\n [TIMERS.ID]: TIMERS.HOSTS,\n [COMPUTE.ID]: COMPUTE.HOSTS,\n};\n\n/**\n * Get the computed SDK options based on the runtime.\n * This should be used any time we're referencing the SDK options in\n * methods to ensure we're including any global overrides.\n */\nexport function getSDKOptions(options?: SDKOptions) {\n let globalOptions = env<string | SDKOptions>('GLOBUS_SDK_OPTIONS', {});\n if (typeof globalOptions === 'string') {\n globalOptions = JSON.parse(globalOptions) as SDKOptions;\n }\n return {\n ...globalOptions,\n ...options,\n fetch: {\n ...globalOptions?.fetch,\n ...options?.fetch,\n options: {\n ...globalOptions?.fetch?.options,\n ...options?.fetch?.options,\n headers: {\n ...globalOptions?.fetch?.options?.headers,\n ...options?.fetch?.options?.headers,\n },\n },\n },\n };\n}\n\nexport function getEnvironment(): Environment {\n const globalOptions = getSDKOptions();\n const environment = env<Environment>(\n 'GLOBUS_SDK_ENVIRONMENT',\n globalOptions?.environment ?? ENVIRONMENTS.PRODUCTION,\n );\n if (globalOptions?.environment && environment !== globalOptions.environment) {\n log(\n 'debug',\n 'GLOBUS_SDK_ENVIRONMENT and GLOBUS_SDK_OPTIONS.environment are set to different values. GLOBUS_SDK_ENVIRONMENT will take precedence',\n );\n }\n if (!environment || !Object.values(ENVIRONMENTS).includes(environment)) {\n throw new EnvironmentConfigurationError('GLOBUS_SDK_ENVIRONMENT', environment);\n }\n return environment;\n}\n\n/**\n * Handlers for: GLOBUS_SDK_VERIFY_SSL\n * Since disabling SSL is at least not-recommended, we consider\n * this value to always be true, but provide a warning when it set\n * to one of the falsey values for informational purposes.\n *\n * Taking direction from `globus-sdk-python` for possible false values\n * @see https://github.com/globus/globus-sdk-python/blob/18eced9c12e2ec41745d1be183148845198b999c/src/globus_sdk/config/env_vars.py#L20\n */\nexport function getVerifySSL(): boolean {\n const verifySSLTemp = env<string>('GLOBUS_SDK_VERIFY_SSL', 'true').toLowerCase();\n if (['n', 'no', 'f', 'false', 'off', '0'].includes(verifySSLTemp)) {\n log(\n 'warn',\n 'Setting GLOBUS_SDK_VERIFY_SSL to false is disallowed in the Globus JavaScript SDK. It will always true in this context',\n );\n }\n return true;\n}\n\n/**\n * Handlers for: GLOBUS_SDK_HTTP_TIMEOUT\n */\nexport function getHttpTimeout() {\n const timeout = Number(env<string | number>('GLOBUS_SDK_HTTP_TIMEOUT', 60));\n if (timeout === -1) {\n return null;\n }\n return timeout;\n}\n\nexport function getServiceHost(service: Service, environment: Environment = getEnvironment()) {\n return SERVICE_HOSTS[service][environment];\n}\n\nexport function getServiceBaseUrl(service: Service, environment: Environment = getEnvironment()) {\n const host = getServiceHost(service, environment);\n return env(`GLOBUS_SDK_SERVICE_URL_${service}`, host ? `https://${host}` : undefined);\n}\n", "import { getServiceBaseUrl, getEnvironment, Environment, Service } from './global.js';\nimport type {\n GCSConfiguration,\n UnauthenticatedGCSConfiguration,\n} from '../services/globus-connect-server/index.js';\nimport { SDKOptions } from '../services/types.js';\n\n/**\n * An extremely simplified parameter serializer based on our current needs.\n *\n * **This is intended for internal @globus/sdk use only.**\n *\n * @private\n */\nexport function stringifyParameters(parameters: {\n [key: string]:\n | string\n | number\n | boolean\n | Array<string | number | null | undefined>\n | null\n | undefined;\n}) {\n const search = new URLSearchParams();\n\n Array.from(Object.entries(parameters)).forEach(([key, value]) => {\n if (Array.isArray(value)) {\n /**\n * Arrays are converted to comma-separated strings.\n */\n search.set(key, value.join(','));\n } else if (value !== undefined) {\n search.set(key, String(value));\n }\n });\n\n return search.toString();\n}\n\n/**\n * Return the base URL for a service (based on the environment).\n * @param service The service to build the URL for.\n * @param path The path to the resource.\n * @param environment The environment to use.\n */\nexport function getServiceURL(\n service: Service,\n path = '',\n environment: Environment = getEnvironment(),\n): URL {\n const base = getServiceBaseUrl(service, environment);\n return new URL(path, base);\n}\n\n/**\n * Build a URL for a service or GCSConfiguration.\n *\n * @param service The service identifier or GCSConfiguration object to build the URL for.\n * @param path The path to the resource.\n * @param options Additional options for the URL.\n */\nexport function build(\n serviceOrConfiguration: Service | GCSConfiguration | UnauthenticatedGCSConfiguration,\n path: string,\n options?: {\n search?: Parameters<typeof stringifyParameters>[0];\n },\n sdkOptions?: SDKOptions,\n): string {\n let url;\n if (typeof serviceOrConfiguration === 'object') {\n url = new URL(path, serviceOrConfiguration.host);\n } else {\n url = getServiceURL(serviceOrConfiguration, path, sdkOptions?.environment);\n }\n if (options && options.search) {\n url.search = stringifyParameters(options.search);\n }\n return url.toString();\n}\n", "import _fetch from 'cross-fetch';\nimport { getClientInfoRequestHeaders } from '../core/info/index.js';\nimport { build } from '../core/url.js';\nimport { getSDKOptions, Service } from '../core/global.js';\nimport { isAuthorizationRequirementsError } from '../core/errors.js';\nimport { RESOURCE_SERVERS } from './auth/config.js';\nimport { isRefreshToken } from './auth/index.js';\nimport type { ServiceMethodOptions, SDKOptions } from './types.js';\nimport type {\n GCSConfiguration,\n UnauthenticatedGCSConfiguration,\n} from '../services/globus-connect-server/index.js';\n\n// eslint-disable-next-line @typescript-eslint/naming-convention\nexport enum HTTP_METHODS {\n POST = 'POST',\n GET = 'GET',\n DELETE = 'DELETE',\n PUT = 'PUT',\n PATCH = 'PATCH',\n}\n\n/**\n * Our domain-specific language for describing service requests.\n * @private\n */\ntype ServiceRequestDSL = {\n /**\n * The service that the request will be made to.\n */\n service: Service | GCSConfiguration | UnauthenticatedGCSConfiguration;\n /**\n * A specific scope that is required for the request. If a scope is provided,\n * the `serviceRequest` function will attempt to get a token for the request\n * based on the the `service` => `resource_server` mapping.\n * @deprecated Define using `resource_server` instead.\n */\n scope?: string;\n /**\n * The resource server that the request will be made to. This can be provided\n * instead of (or addition to) the `scope` property. If this is provided, the\n * `serviceRequest` function will attempt to get a token for the resource server\n * when a `manager` instance is provided in the SDK options.\n */\n resource_server?: string;\n /**\n * The path of the resource (appended to the service's host).\n */\n path: string;\n /**\n * The HTTP method to use for the request.\n */\n method?: HTTP_METHODS;\n /**\n * For some resources, it doesn't make sense for requests to be retried.\n * Setting this to `true` will prevent any retry logic from being applied.\n */\n preventRetry?: boolean;\n};\n\n/**\n * A helper function for making service requests that will handle the arguments\n * of `ServiceMethod` and `ServiceMethodDynamicSegments` functions in a uniform\n * way.\n *\n * @example\n * ```ts\n * export const get = function (flow_id, options?, sdkOptions?) {\n * return serviceRequest({\n * service: FLOWS.ID,\n * scope: SCOPES.VIEW_FLOWS,\n * path: `/flows/${flow_id}`,\n * }, options, sdkOptions);\n * } satisfies ServiceMethodDynamicSegments<string, Record<string, any>>;\n * ```\n *\n * @private\n * @param config The ServiceRequestDSL for the request.\n * @param options The options passed to the service method.\n * @param passedSdkOptions The SDK options passed to the service method.\n * @returns\n */\nexport async function serviceRequest(\n this: unknown,\n config: ServiceRequestDSL,\n options?: ServiceMethodOptions,\n passedSdkOptions?: SDKOptions,\n): Promise<Response> {\n /**\n * Get the SDK options, merging any passed options with the global options.\n */\n const sdkOptions = getSDKOptions(passedSdkOptions);\n const injectedFetchOptions = sdkOptions?.fetch?.options || {};\n\n const headers: Record<string, string> = {\n ...getClientInfoRequestHeaders(),\n ...options?.headers,\n /**\n * Key/value pairs found in the `fetch` options override those found in the\n * service method options.\n */\n ...injectedFetchOptions.headers,\n };\n\n /**\n * The `AuthorizationManager` instance provided with the call.\n */\n const manager = options?.manager || sdkOptions?.manager;\n\n let token;\n /**\n * If a `resource_server` was provided, and the SDK is configured with a `manager`\n * instance, we'll try to get a token for the resource server and use it.\n */\n if (config.resource_server && manager) {\n token = manager.tokens.getByResourceServer(config.resource_server);\n if (token) {\n headers['Authorization'] = `Bearer ${token.access_token}`;\n }\n }\n /**\n * If the `scope` property is provided, and the SDK is configured with a `manager`,\n * we'll try to map the service to a resource server. This is mostly to support\n * backwards compatibility of the `scope` property being used in the `ServiceRequestDSL`.\n *\n * @todo This condition will likely be removed in a future version in favor of using `resource_server` to\n * configure a service request.\n */\n if (\n config.scope &&\n manager &&\n /**\n * Only attempt to get a token if the `service` property is a string or has an `endpoint_id` property (GCSConfiguration).\n */\n (typeof config.service === 'string' || 'endpoint_id' in config.service)\n ) {\n const resourceServer =\n typeof config.service === 'string'\n ? RESOURCE_SERVERS[config.service]\n : // For `GCSConfiguration` objects, the `endpoint_id` is the resource server.\n config.service.endpoint_id;\n\n token = manager.tokens.getByResourceServer(resourceServer);\n if (token) {\n headers['Authorization'] = `Bearer ${token.access_token}`;\n }\n }\n\n /**\n * If a raw body was provided, use that. Otherwise, if a payload was provided, serialize it.\n */\n let body = options?.body;\n if (!body && options?.payload) {\n body = JSON.stringify(options.payload);\n }\n\n /**\n * If `Content-Type` header was not provided, and there is a body, we assume it is JSON.\n */\n if (!headers?.['Content-Type'] && body) {\n headers['Content-Type'] = 'application/json';\n }\n\n const url = build(\n config.service,\n config.path,\n {\n search: options?.query,\n },\n sdkOptions,\n );\n\n const init = {\n method: config.method,\n body,\n ...injectedFetchOptions,\n /**\n * Merge the headers from the options and SDK options.\n */\n headers,\n };\n\n /**\n * The request handler for the fetch call. This can be overridden by providing a\n * `__callable` property in the `fetch` options.\n */\n let handler = _fetch;\n /* eslint-disable no-underscore-dangle */\n if (injectedFetchOptions?.__callable) {\n handler = injectedFetchOptions.__callable.bind(this);\n /**\n * Remove the `__callable` property from the `fetch` options before passing the options along.\n */\n delete init.__callable;\n }\n /* eslint-enable no-underscore-dangle */\n\n /**\n * If the resource is configured to prevent retries, there is no `manager` instance,\n * or token, the request will be made as-is.\n */\n if (config.preventRetry || !manager || !token || !isRefreshToken(token)) {\n return handler(url, init);\n }\n\n /**\n * Automatic Retry Handling\n */\n\n const initialResponse = await handler(url, init);\n /**\n * If the response is \"ok\", we can return it as-is.\n */\n if (initialResponse.ok) {\n return initialResponse;\n }\n /**\n * Do a safe check to see if the response contains any authorization requirements.\n */\n let hasAuthorizationRequirements;\n try {\n hasAuthorizationRequirements = isAuthorizationRequirementsError(\n /**\n * It is important to clone the response before calling `json` avoid\n * `body used already for [...]` errors when the initial response is\n * returned.\n */\n await initialResponse.clone().json(),\n );\n } catch (_e) {\n hasAuthorizationRequirements = false;\n }\n /**\n * We only attempt to refresh the original token supplied with teh request, if the\n * response status is 401 and the response does not contain any authorization requirements.\n */\n const shouldAttemptTokenRefresh = initialResponse.status === 401 && !hasAuthorizationRequirements;\n if (shouldAttemptTokenRefresh) {\n const newToken = await manager.refreshToken(token);\n if (!newToken) {\n return initialResponse;\n }\n /**\n * Retry the request with the new token.\n */\n return handler(url, {\n ...init,\n headers: {\n ...init.headers,\n Authorization: `Bearer ${newToken.access_token}`,\n },\n });\n }\n /**\n * No retry was attempted, return the initial response.\n */\n return initialResponse;\n}\n", "import type { Info } from './index.js';\n\n/**\n * @private\n */\nexport const CLIENT_INFO_HEADER = `X-Globus-Client-Info`;\n\nlet ENABLED = true;\n/**\n * Disable the client information header from being included in requests (enabled by default).\n * @private\n */\nexport function disable() {\n ENABLED = false;\n}\n\n/**\n * Enables the client information header to be included in requests.\n * @private\n */\nexport function enable() {\n ENABLED = true;\n}\n\n/**\n * Whether or not the client information header should be sent with requests.\n * @private\n */\nexport function isEnabled() {\n return ENABLED;\n}\n\nconst INFOS_SEPERATOR = ';';\nconst INFO_ITEM_SEPARATOR = ',';\n\n/**\n * Exported for test purposes only.\n * @private\n */\nexport function toString(info: Info | Info[]) {\n const infos = Array.isArray(info) ? info : [info];\n return infos\n .map((i) =>\n Object.entries(i)\n .map(([key, value]) => `${key}=${value}`)\n .join(INFO_ITEM_SEPARATOR),\n )\n .join(INFOS_SEPERATOR);\n}\n", "// x-release-please-start-version\nexport const VERSION = '6.2.0';\n// x-release-please-end\n", "/**\n * @module Information\n * @description This module is mostly intended for internal use, but can be helpful\n * identifying information about the SDK package you are using at runtime.\n */\nimport { toString, isEnabled, CLIENT_INFO_HEADER } from './private.js';\nimport { VERSION as _VERSION } from './version.js';\n\nexport type Version = string;\n\n/**\n * The version of the `@globus/sdk` package that is in use.\n */\nexport const VERSION: Version = _VERSION;\n\nexport type Info = {\n product: string;\n version: Version;\n};\n\n/**\n * The client information identifier for this package.\n */\nexport const CLIENT_INFO: Info = {\n product: 'javascript-sdk',\n version: VERSION,\n};\n\nlet INFOS: Info[] = [CLIENT_INFO];\n\n/**\n * Add a client information identifier to the existing SDK information.\n */\nexport function addClientInfo(info: Info) {\n INFOS = INFOS.concat(info);\n}\n/**\n * Get the current client information as a string.\n */\nexport function getClientInfo(): string {\n return toString(INFOS);\n}\n\nexport function getClientInfoRequestHeaders(): Record<string, string> {\n if (!isEnabled()) {\n return {};\n }\n return {\n [CLIENT_INFO_HEADER]: getClientInfo(),\n };\n}\n", "import { ID } from '../../config.js';\nimport { HTTP_METHODS, serviceRequest } from '../../../../services/shared.js';\n\nimport type { ServiceMethod } from '../../../types.js';\n\nexport const userinfo = function (options?, sdkOptions?) {\n return serviceRequest(\n {\n service: ID,\n scope: undefined,\n path: `/v2/oauth2/userinfo`,\n method: HTTP_METHODS.GET,\n },\n options,\n sdkOptions,\n );\n} satisfies ServiceMethod<{\n payload: never;\n}>;\n\nexport * as token from './token.js';\n", "import { ID } from '../../config.js';\nimport { HTTP_METHODS, serviceRequest } from '../../../../services/shared.js';\n\nimport type { ServiceMethod, ServiceMethodOptions } from '../../../types.js';\n\ntype IntrospectPayload = {\n token: string;\n include?: string;\n};\n\ntype RevokePayload = {\n token: string;\n /**\n * This is an undocumented property that is required for the request to be successful.\n */\n client_id: string;\n};\n\ntype ValidatePayload = {\n token: string;\n client_id: string;\n};\n\ntype RefreshPayload = {\n refresh_token: string;\n grant_type: 'refresh_token';\n /**\n * This is an undocumented property that is required for the request to be successful.\n */\n client_id: string;\n};\n\ntype ExchangePayload = {\n grant_type: 'authorization_code';\n code: string;\n client_id: string;\n code_verifier: string;\n redirect_uri: string;\n};\n\ntype SupportedPayloads =\n | IntrospectPayload\n | RevokePayload\n | ValidatePayload\n | RefreshPayload\n | ExchangePayload;\n\nfunction serialize(payload?: SupportedPayloads) {\n return new URLSearchParams(payload);\n}\n\n/**\n * Format and inject properties that are specific to the `/token` resources.\n */\nfunction injectServiceOptions(\n options: ServiceMethodOptions & {\n payload?: SupportedPayloads;\n },\n): ServiceMethodOptions {\n return {\n ...options,\n /**\n * The `token` service methods always expect a form-encoded body. We still allow\n * end-consumers to pass a raw body, but if `payload` is provided it is serialized.\n */\n body: options.payload ? serialize(options.payload) : undefined,\n headers: {\n ...(options?.headers || {}),\n Accept: 'application/json',\n /**\n * Force the `Content-Type` header to be `application/x-www-form-urlencoded` and `charset=UTF-8`.\n */\n 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',\n },\n };\n}\n\n/**\n * @see https://docs.globus.org/api/auth/reference/#dependent_token_grant_post_v2oauth2token\n */\nexport const token = function (options = {}, sdkOptions?) {\n return serviceRequest(\n {\n service: ID,\n scope: undefined,\n path: `/v2/oauth2/token`,\n method: HTTP_METHODS.POST,\n preventRetry: true,\n },\n injectServiceOptions(options),\n sdkOptions,\n );\n} satisfies ServiceMethod<{\n payload?: ExchangePayload;\n query?: {\n /**\n * Include tokens for all scopes that the user has consented to, for the requesting client.\n * @private\n */\n include_consented_scopes?: boolean;\n };\n}>;\n\n/**\n * @see https://docs.globus.org/api/auth/developer-guide/#obtaining-authorization\n */\nexport const exchange = token;\n\n/**\n * Token Introspection\n * @see https://docs.globus.org/api/auth/reference/#token-introspect\n */\nexport const introspect = function (options, sdkOptions?) {\n if (!options?.payload) {\n throw new Error(`'payload' is required for introspect`);\n }\n return serviceRequest(\n {\n service: ID,\n scope: undefined,\n path: `/v2/oauth2/token/introspect`,\n method: HTTP_METHODS.POST,\n preventRetry: true,\n },\n injectServiceOptions(options),\n sdkOptions,\n );\n} satisfies ServiceMethod<{\n payload: IntrospectPayload;\n}>;\n\n/**\n * Token Revocation\n * @see https://docs.globus.org/api/auth/reference/#token-revoke\n */\nexport const revoke = function (options, sdkOptions?) {\n if (!options?.payload) {\n throw new Error(`'payload' is required for revoke`);\n }\n return serviceRequest(\n {\n service: ID,\n scope: undefined,\n path: `/v2/oauth2/token/revoke`,\n method: HTTP_METHODS.POST,\n preventRetry: true,\n },\n injectServiceOptions(options),\n sdkOptions,\n );\n} satisfies ServiceMethod<{\n payload: RevokePayload;\n}>;\n\n/**\n * Token Refresh\n * @see https://docs.globus.org/api/auth/reference/#refresh_token_grant\n */\nexport const refresh = function (options, sdkOptions?) {\n if (!options?.payload) {\n throw new Error(`'payload' is required for revoke`);\n }\n return serviceRequest(\n {\n service: ID,\n scope: undefined,\n path: `/v2/oauth2/token`,\n method: HTTP_METHODS.POST,\n preventRetry: true,\n },\n injectServiceOptions(options),\n sdkOptions,\n );\n} satisfies ServiceMethod<{\n payload: RefreshPayload;\n}>;\n\n/**\n * @private\n * @deprecated Rather than using `validate` to check if a token is valid, it is recommended to make a request to the resource server with the token and handle the error response.\n */\nexport const validate = function (options, sdkOptions?) {\n if (!options?.payload) {\n throw new Error(`'payload' is required for validate`);\n }\n return serviceRequest(\n {\n service: ID,\n scope: undefined,\n path: `/v2/oauth2/token/validate`,\n method: HTTP_METHODS.POST,\n preventRetry: true,\n },\n injectServiceOptions(options),\n sdkOptions,\n );\n} satisfies ServiceMethod<{\n payload: ValidatePayload;\n}>;\n", "/**\n * @description A wrapper around the Globus Auth service.\n * @group Service\n * @see [Globus Auth API Documentation](https://docs.globus.org/api/auth/)\n * @module\n */\nimport { build } from '../../core/url.js';\n\nimport * as AUTH from './config.js';\n\nimport type { Token, TokenWithRefresh, TokenResponse } from './types.js';\n\n/**\n * @private\n * @internal\n */\nexport const CONFIG = AUTH;\n\nexport type * from './types.js';\n\n/**\n * Query parameters that can be passed to the authorization endpoint.\n * @see https://docs.globus.org/api/auth/reference/#authorization_code_grant_preferred\n * @see https://docs.globus.org/api/auth/sessions/#client-initiated-authns\n */\nexport type AuthorizationQueryParameters = {\n prompt?: string;\n session_message?: string;\n session_required_identities?: string;\n session_required_single_domain?: string;\n session_required_mfa?: 'true' | 'false';\n session_required_policies?: string;\n};\n\nexport function getAuthorizationEndpoint() {\n return build(AUTH.ID, '/v2/oauth2/authorize');\n}\n\nexport function getTokenEndpoint() {\n return build(AUTH.ID, '/v2/oauth2/token');\n}\n\nexport * as identities from './service/identities/index.js';\nexport * as oauth2 from './service/oauth2/index.js';\n\nexport function isToken(check: unknown): check is Token {\n return typeof check === 'object' && check !== null && 'access_token' in check;\n}\n\nexport function isRefreshToken(check: unknown): check is TokenWithRefresh {\n return isToken(check) && check !== null && 'refresh_token' in check;\n}\n\nexport function isGlobusAuthTokenResponse(check: unknown): check is TokenResponse {\n /**\n * @todo This could be made more robust by checking whether the `resource_server` is a well-known value.\n */\n return isToken(check) && check !== null && 'resource_server' in check;\n}\n\nexport * as utils from './utils.js';\n", "/**\n * @todo It would be nice to not `| any` here, but ideally callers do not need to\n * fully type the payload to attach listeners.\n */\ntype ListenerCallback<P> = (payload?: P | any) => Promise<void> | void;\n\nexport class Event<EventName extends string, Payload extends unknown> {\n #callbacks: ListenerCallback<Payload>[] = [];\n\n constructor(readonly name: EventName) {}\n\n addListener(callback: ListenerCallback<Payload>) {\n this.#callbacks.push(callback);\n return () => this.removeListener(callback);\n }\n\n removeListener(callback: ListenerCallback<Payload>) {\n this.#callbacks = this.#callbacks.filter((cb) => cb !== callback);\n }\n\n clearListeners() {\n this.#callbacks = [];\n }\n\n async dispatch(payload?: Payload) {\n await Promise.all(this.#callbacks.map((callback) => callback(payload)));\n }\n}\n", "export function isSupported() {\n return 'crypto' in globalThis;\n}\n\nfunction getCrypto(): Crypto {\n return 'webcrypto' in globalThis.crypto\n ? (globalThis.crypto.webcrypto as unknown as Crypto)\n : globalThis.crypto;\n}\n\n/**\n * Base64 URL encode a string.\n * @see https://www.oauth.com/oauth2-servers/pkce/authorization-request/\n */\nconst encode = (value: string) =>\n btoa(value).replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '');\n\nasync function sha256(input: string) {\n const hashBuffer = await getCrypto().subtle.digest('SHA-256', new TextEncoder().encode(input));\n return String.fromCharCode(...new Uint8Array(hashBuffer));\n}\n\n/**\n * Character set for generating random alpha-numeric strings.\n */\nconst CHARSET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';\n\n/**\n * Character set allowed to be used in the PKCE `code_verifier`\n * @see https://www.rfc-editor.org/rfc/rfc7636#section-4.1\n */\nconst PKCE_SAFE_CHARSET = `${CHARSET}-._~`;\n/**\n * Create a Code Verifier for PKCE\n * @see https://www.rfc-editor.org/rfc/rfc7636#section-4.1\n */\nexport function generateCodeVerifier() {\n /**\n * @todo Make length random between 43 and 128 characters\n */\n return Array.from(getCrypto().getRandomValues(new Uint8Array(43)))\n .map((v) => PKCE_SAFE_CHARSET[v % PKCE_SAFE_CHARSET.length])\n .join('');\n}\n\n/**\n * Create a Code Challenge from a provided Code Verifier (assumes S256 `code_challenge_method`).\n * @see https://www.rfc-editor.org/rfc/rfc7636#section-4.2\n */\nexport async function generateCodeChallenge(verifier: string) {\n const hashed = await sha256(verifier);\n return encode(hashed);\n}\n\nexport function generateState() {\n return Array.from(getCrypto().getRandomValues(new Uint8Array(16)))\n .map((v) => CHARSET[v % CHARSET.length])\n .join('');\n}\n\n/**\n * @see https://www.oauth.com/oauth2-servers/pkce/authorization-code-exchange/\n */\nexport type AuthorizationCodeExchangeParameters = {\n code: string;\n code_verifier: string;\n client_id: string;\n client_secret?: string;\n redirect_uri: string;\n grant_type: 'authorization_code';\n};\n\n/**\n * @see https://www.oauth.com/oauth2-servers/pkce/authorization-request/\n */\nexport type AuthorizationRequestParameters = {\n client_id: string;\n redirect_uri: string;\n response_type: 'code';\n scope: string;\n state: string;\n code_challenge: string;\n code_challenge_method: 'S256' | 'plain';\n};\n\n/**\n * @private\n */\nexport const KEYS = {\n PKCE_STATE: 'pkce_state',\n PKCE_CODE_VERIFIER: 'pkce_code_verifier',\n};\n\ntype Entries = 'state' | 'code_verifier';\n\nexport const store = {\n getKey(key: Entries) {\n return key === 'state' ? KEYS.PKCE_STATE : KEYS.PKCE_CODE_VERIFIER;\n },\n get: (entry: Entries) => sessionStorage.getItem(store.getKey(entry)),\n set: (entry: Entries, value: string) => sessionStorage.setItem(store.getKey(entry), value),\n reset: () => {\n sessionStorage.removeItem(KEYS.PKCE_STATE);\n sessionStorage.removeItem(KEYS.PKCE_CODE_VERIFIER);\n },\n};\n", "import { getAuthorizationEndpoint, oauth2 } from '../../services/auth/index.js';\nimport {\n generateCodeChallenge,\n generateCodeVerifier,\n generateState,\n AuthorizationRequestParameters,\n AuthorizationCodeExchangeParameters,\n isSupported,\n store,\n} from './pkce.js';\n\nimport type { AuthorizationManagerConfiguration } from './AuthorizationManager.js';\n\nexport type GetTokenOptions = {\n /**\n * Whether or not the URL should be replaced after processing the token.\n * This is used to remove the `?code=...&state=...` parameters from the URL after the token is retrieved.\n * If set to `false`, the URL will remain unchanged.\n * @default true\n */\n shouldReplace?: boolean;\n /**\n * When set to `true` in addition to the `scope` values originally requested, Globus Auth\n * will return tokens for **all** of the scopes that the user has consented to, for\n * the requesting client.\n * @default false\n * @private\n */\n includeConsentedScopes?: boolean;\n};\n\nexport type TransportOptions = Pick<\n AuthorizationManagerConfiguration,\n 'client' | 'redirect' | 'scopes'\n> & {\n /**\n * Query parameters to include in the authorization request.\n *\n * The transport will include all parameters required for a default OAuth PKCE flow, but\n * these parameters can be overridden or extended with this option.\n */\n params?: {\n [key: string]: string;\n };\n};\n\nexport type RedirectTransportOptions = TransportOptions;\nexport class RedirectTransport {\n #options: RedirectTransportOptions;\n\n constructor(options: RedirectTransportOptions) {\n this.#options = options;\n if (RedirectTransport.supported === false) {\n throw new Error('RedirectTransport is not supported in this environment.');\n }\n }\n\n static supported = isSupported();\n\n /**\n * For the redirect transport, sending the request will redirect the user to the authorization endpoint, initiating the OAuth flow.\n */\n async send() {\n /**\n * Since we'll be using PKCE, we need to generate a code verifier and challenge\n * for the OAuth handshake.\n */\n const verifier = generateCodeVerifier();\n const challenge = await generateCodeChallenge(verifier);\n /**\n * If there is caller-provided `state`, use it; Otherwise, generate a state parameter.\n */\n const state = this.#options.params?.['state'] ?? generateState();\n /**\n * The verifier and state are stored in session storage so that we can validate\n * the response when we receive it.\n */\n store.set('code_verifier', verifier);\n store.set('state', state);\n\n const params: AuthorizationRequestParameters = {\n response_type: 'code',\n client_id: this.#options.client,\n scope: this.#options.scopes || '',\n redirect_uri: this.#options.redirect,\n state,\n code_challenge: challenge,\n code_challenge_method: 'S256',\n ...(this.#options.params || {}),\n };\n\n const url = new URL(getAuthorizationEndpoint());\n url.search = new URLSearchParams(params).toString();\n\n window.location.assign(url.toString());\n }\n\n /**\n * Parse the current URL for the authorization code (`?code=...`) and exchange it for an access token when available.\n * - When the URL is processed and exchanged for an access token, the page is redirected to the current URL without the `?code=...&state=...` parameters.\n */\n async getToken(\n options: GetTokenOptions = { shouldReplace: true, includeConsentedScopes: false },\n ) {\n const url = new URL(window.location.href);\n const params = new URLSearchParams(url.search);\n /**\n * Check for an error in the OAuth flow.\n * @see https://www.oauth.com/oauth2-servers/pkce/authorization-request/\n */\n if (params.get('error')) {\n throw new Error(\n params.get('error_description') || 'An error occurred during the authorization process.',\n );\n }\n\n const code = params.get('code');\n\n /**\n * If we don't have a `code` parameter, we can't exchange it for an access token.\n */\n if (!code) return undefined;\n\n /**\n * Grab the PKCE information from session storage.\n */\n const state = store.get('state');\n const verifier = store.get('code_verifier');\n /**\n * Now that we have the values in memory, we can remove them from session storage.\n */\n store.reset();\n\n /**\n * Validate the `state` parameter matches the preserved state (to prevent CSRF attacks).\n */\n if (params.get('state') !== state) {\n throw new Error(\n 'Invalid State. The received \"state\" parameter does not match the expected state.',\n );\n }\n /**\n * Ensure we have a valid code verifier.\n */\n if (!verifier) {\n throw new Error('Invalid Code Verifier');\n }\n\n /**\n * Prepare the payload for the PKCE token exchange.\n */\n const payload: AuthorizationCodeExchangeParameters = {\n code,\n client_id: this.#options.client,\n /**\n * Retrieve the code verifier from session storage.\n */\n code_verifier: verifier,\n redirect_uri: this.#options.redirect,\n grant_type: 'authorization_code',\n };\n\n const response = await (\n await oauth2.token.exchange({\n query: options.includeConsentedScopes\n ? {\n include_consented_scopes: true,\n }\n : undefined,\n payload,\n })\n ).json();\n\n if (options.shouldReplace) {\n /**\n * Remove the `code` and `state` parameters from the URL.\n */\n params.delete('code');\n params.delete('state');\n /**\n * Update the URL with the new query string.\n */\n url.search = params.toString();\n /**\n * Redirect the page to the new URL (without the `code` and `state` parameters)/\n */\n window.location.replace(url);\n }\n return response;\n }\n}\n", "import { CONFIG, isToken } from '../../services/auth/index.js';\n\nimport { SERVICES, type Service } from '../global.js';\nimport { AuthorizationManager } from './AuthorizationManager.js';\n\nimport type { Token, TokenResponse } from '../../services/auth/types.js';\n\nexport type StoredToken = Token & {\n /**\n * Tokens stored before the introduction of the `__metadata` field will be missing this property.\n * @since 4.3.0\n */\n __metadata?: {\n /**\n * The timestamp when the token was added to the storage as a number of milliseconds since the Unix epoch.\n *\n * **IMPORTANT**: This value might **not** represent the time when the token was created by the authorization server.\n */\n created: number;\n /**\n * The timestamp when the token will expire as a number of milliseconds since the Unix epoch, based\n * on the `expires_in` value from the token response and the time when the token was stored.\n */\n expires: number | null;\n };\n};\n\nexport class TokenManager {\n #manager: AuthorizationManager;\n\n constructor(options: { manager: AuthorizationManager }) {\n this.#manager = options.manager;\n }\n\n /**\n * Retrieve and parse an item from the storage.\n */\n #getTokenFromStorage(key: string) {\n const raw = this.#manager.storage.getItem(key) || 'null';\n let token: StoredToken | null = null;\n try {\n const parsed = JSON.parse(raw);\n if (isToken(parsed)) {\n token = parsed;\n }\n } catch (e) {\n // no-op\n }\n return token;\n }\n\n #getTokenForService(service: Service) {\n const resourceServer = CONFIG.RESOURCE_SERVERS?.[service];\n return this.getByResourceServer(resourceServer);\n }\n\n getByResourceServer(resourceServer: string): StoredToken | null {\n return this.#getTokenFromStorage(`${this.#manager.storageKeyPrefix}${resourceServer}`);\n }\n\n get auth(): StoredToken | null {\n return this.#getTokenForService(SERVICES.AUTH);\n }\n\n get transfer(): StoredToken | null {\n return this.#getTokenForService(SERVICES.TRANSFER);\n }\n\n get flows(): StoredToken | null {\n return this.#getTokenForService(SERVICES.FLOWS);\n }\n\n get groups(): StoredToken | null {\n return this.#getTokenForService(SERVICES.GROUPS);\n }\n\n get search(): StoredToken | null {\n return this.#getTokenForService(SERVICES.SEARCH);\n }\n\n get timer(): StoredToken | null {\n return this.#getTokenForService(SERVICES.TIMERS);\n }\n\n get compute(): StoredToken | null {\n return this.#getTokenForService(SERVICES.COMPUTE);\n }\n\n gcs(endpoint: string): StoredToken | null {\n return this.getByResourceServer(endpoint);\n }\n\n getAll(): StoredToken[] {\n const entries = Object.keys(this.#manager.storage).reduce(\n (acc: (StoredToken | null)[], key) => {\n if (key.startsWith(this.#manager.storageKeyPrefix)) {\n acc.push(this.#getTokenFromStorage(key));\n }\n return acc;\n },\n [],\n );\n return entries.filter(isToken);\n }\n\n /**\n * Add a token to the storage.\n */\n add(token: Token | TokenResponse) {\n const created = Date.now();\n const expires = created + token.expires_in * 1000;\n this.#manager.storage.setItem(\n `${this.#manager.storageKeyPrefix}${token.resource_server}`,\n JSON.stringify({\n ...token,\n /**\n * Add metadata to the token to track when it was created and when it expires.\n */\n __metadata: {\n created,\n expires,\n },\n }),\n );\n if ('other_tokens' in token) {\n token.other_tokens?.forEach((t) => {\n this.add(t);\n });\n }\n }\n\n remove(token: Token | TokenResponse) {\n this.#manager.storage.removeItem(`${this.#manager.storageKeyPrefix}${token.resource_server}`);\n }\n\n /**\n * Determines whether or not a stored token is expired.\n * @param token The token to check.\n * @param augment An optional number of milliseconds to add to the current time when checking the expiration.\n * @returns `true` if the token is expired, `false` if it is not expired, and `undefined` if the expiration status cannot be determined\n * based on the token's metadata. This can happen if the token is missing the `__metadata` field or the `expires` field.\n */\n static isTokenExpired(token: StoredToken | null, augment: number = 0): boolean | undefined {\n /* eslint-disable no-underscore-dangle */\n if (!token || !token.__metadata || typeof token.__metadata.expires !== 'number') {\n return undefined;\n }\n return Date.now() + augment >= token.__metadata.expires;\n /* eslint-enable no-underscore-dangle */\n }\n}\n", "/**\n * An in-memory implementation of the `Storage` interface.\n * @see https://developer.mozilla.org/en-US/docs/Web/API/Storage\n */\nexport class MemoryStorage implements Storage {\n #storage: Record<string, string | null> = {};\n\n getItem(key: string) {\n return this.#storage[key] !== undefined ? this.#storage[key] : null;\n }\n\n setItem(key: string, value: string) {\n this.#storage[key] = value;\n }\n\n removeItem(key: string) {\n delete this.#storage[key];\n }\n\n key(index: number) {\n return Object.keys(this.#storage)[index];\n }\n\n clear() {\n this.#storage = {};\n }\n\n get length() {\n return Object.keys(this.#storage).length;\n }\n}\n", "import { getAuthorizationEndpoint, oauth2 } from '../../services/auth/index.js';\nimport {\n generateCodeChallenge,\n generateCodeVerifier,\n generateState,\n AuthorizationRequestParameters,\n AuthorizationCodeExchangeParameters,\n isSupported,\n store,\n} from './pkce.js';\n\nimport type { TransportOptions } from './RedirectTransport.js';\n\nexport type PopupTransportOptions = TransportOptions;\n\nconst MESSAGE_SOURCE = 'globus-sdk';\n\n/**\n * The `PopupTransport` (`popup`) uses a popup window to initiate the OAuth 2.0 using PKCE.\n *\n * When using the `PopupTransport`, the `redirect` parameter should be to a location\n * that will transmit the URL back to the opener. This can be done using `AuthorizationManager.handleCodeRedirect()`, or\n * manually by calling `window.opener.postMessage()`.\n *\n * @experimental\n */\nexport class PopupTransport {\n #options: PopupTransportOptions;\n\n #window: Window | null = null;\n\n constructor(options: PopupTransportOptions) {\n this.#options = options;\n if (PopupTransport.supported === false) {\n throw new Error('PopupTransport is not supported in this environment.');\n }\n }\n\n /**\n * The `PopupTransport` is supported in environments where the `window` object is available.\n */\n static supported =\n isSupported() && 'window' in globalThis && typeof globalThis.window.open === 'function';\n\n /**\n * For the redirect transport, sending the request will redirect the user to the authorization endpoint, initiating the OAuth flow.\n */\n async send() {\n /**\n * Since we'll be using PKCE, we need to generate a code verifier and challenge\n * for the OAuth handshake.\n */\n const verifier = generateCodeVerifier();\n const challenge = await generateCodeChallenge(verifier);\n /**\n * If there is caller-provided `state`, use it; Otherwise, generate a state parameter.\n */\n const state = this.#options.params?.['state'] ?? generateState();\n /**\n * The verifier and state are stored in session storage so that we can validate\n * the response when we receive it.\n */\n store.set('code_verifier', verifier);\n store.set('state', state);\n\n const params: AuthorizationRequestParameters = {\n response_type: 'code',\n client_id: this.#options.client,\n scope: this.#options.scopes || '',\n redirect_uri: this.#options.redirect,\n state,\n code_challenge: challenge,\n code_challenge_method: 'S256',\n ...(this.#options.params || {}),\n };\n\n const url = new URL(getAuthorizationEndpoint());\n url.search = new URLSearchParams(params).toString();\n\n const promise = new Promise((resolve) => {\n window.addEventListener(\n 'message',\n async (e) => {\n const { data } = e;\n if (e.origin !== window.location.origin || data?.source !== MESSAGE_SOURCE) {\n return;\n }\n this.#window?.close();\n const response = await this.#getToken(data.url);\n resolve(response);\n },\n false,\n );\n });\n\n this.#window = window.open(url.toString(), '_blank', 'width=800,height=600');\n\n if (!this.#window) {\n throw new Error('Unable to open window for PopupTransport.');\n }\n\n this.#window.focus();\n return promise;\n }\n\n async #getToken(href: string) {\n const url = new URL(href);\n const params = new URLSearchParams(url.search);\n /**\n * Check for an error in the OAuth flow.\n * @see https://www.oauth.com/oauth2-servers/pkce/authorization-request/\n */\n if (params.get('error')) {\n throw new Error(\n params.get('error_description') || 'An error occurred during the authorization process.',\n );\n }\n\n const code = params.get('code');\n\n /**\n * If we don't have a `code` parameter, we can't exchange it for an access token.\n */\n if (!code) return undefined;\n\n /**\n * Grab the PKCE information from session storage.\n */\n const state = store.get('state');\n const verifier = store.get('code_verifier');\n /**\n * Now that we have the values in memory, we can remove them from session storage.\n */\n store.reset();\n\n /**\n * Validate the `state` parameter matches the preserved state (to prevent CSRF attacks).\n */\n if (params.get('state') !== state) {\n throw new Error(\n 'Invalid State. The received \"state\" parameter does not match the expected state.',\n );\n }\n /**\n * Ensure we have a valid code verifier.\n */\n if (!verifier) {\n throw new Error('Invalid Code Verifier');\n }\n /**\n * Prepare the payload for the PKCE token exchange.\n */\n const payload: AuthorizationCodeExchangeParameters = {\n code,\n client_id: this.#options.client,\n /**\n * Retrieve the code verifier from session storage.\n */\n code_verifier: verifier,\n redirect_uri: this.#options.redirect,\n grant_type: 'authorization_code',\n };\n const response = await (\n await oauth2.token.exchange({\n payload,\n })\n ).json();\n return response;\n }\n\n // eslint-disable-next-line class-methods-use-this\n getToken() {\n if (!window.opener) {\n return;\n }\n\n window.opener.postMessage(\n {\n source: MESSAGE_SOURCE,\n url: window.location.href,\n },\n window.location.origin,\n );\n }\n}\n"],
|
|
5
5
|
"mappings": "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",
|
|
6
6
|
"names": ["HOSTS", "ID", "ID", "HOSTS", "ID", "HOSTS", "ID", "HOSTS", "ID", "HOSTS", "ID", "HOSTS", "ID", "HOSTS", "ID", "HOSTS", "VERSION", "token", "_fetch", "ID", "ID", "ID", "token", "token"]
|
|
7
7
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/core/info/index.ts", "../../../../src/core/info/private.ts", "../../../../src/core/info/version.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * @module Information\n * @description This module is mostly intended for internal use, but can be helpful\n * identifying information about the SDK package you are using at runtime.\n */\nimport { toString, isEnabled, CLIENT_INFO_HEADER } from './private.js';\nimport { VERSION as _VERSION } from './version.js';\n\nexport type Version = string;\n\n/**\n * The version of the `@globus/sdk` package that is in use.\n */\nexport const VERSION: Version = _VERSION;\n\nexport type Info = {\n product: string;\n version: Version;\n};\n\n/**\n * The client information identifier for this package.\n */\nexport const CLIENT_INFO: Info = {\n product: 'javascript-sdk',\n version: VERSION,\n};\n\nlet INFOS: Info[] = [CLIENT_INFO];\n\n/**\n * Add a client information identifier to the existing SDK information.\n */\nexport function addClientInfo(info: Info) {\n INFOS = INFOS.concat(info);\n}\n/**\n * Get the current client information as a string.\n */\nexport function getClientInfo(): string {\n return toString(INFOS);\n}\n\nexport function getClientInfoRequestHeaders(): Record<string, string> {\n if (!isEnabled()) {\n return {};\n }\n return {\n [CLIENT_INFO_HEADER]: getClientInfo(),\n };\n}\n", "import type { Info } from './index.js';\n\n/**\n * @private\n */\nexport const CLIENT_INFO_HEADER = `X-Globus-Client-Info`;\n\nlet ENABLED = true;\n/**\n * Disable the client information header from being included in requests (enabled by default).\n * @private\n */\nexport function disable() {\n ENABLED = false;\n}\n\n/**\n * Enables the client information header to be included in requests.\n * @private\n */\nexport function enable() {\n ENABLED = true;\n}\n\n/**\n * Whether or not the client information header should be sent with requests.\n * @private\n */\nexport function isEnabled() {\n return ENABLED;\n}\n\nconst INFOS_SEPERATOR = ';';\nconst INFO_ITEM_SEPARATOR = ',';\n\n/**\n * Exported for test purposes only.\n * @private\n */\nexport function toString(info: Info | Info[]) {\n const infos = Array.isArray(info) ? info : [info];\n return infos\n .map((i) =>\n Object.entries(i)\n .map(([key, value]) => `${key}=${value}`)\n .join(INFO_ITEM_SEPARATOR),\n )\n .join(INFOS_SEPERATOR);\n}\n", "// x-release-please-start-version\nexport const VERSION = '6.0
|
|
4
|
+
"sourcesContent": ["/**\n * @module Information\n * @description This module is mostly intended for internal use, but can be helpful\n * identifying information about the SDK package you are using at runtime.\n */\nimport { toString, isEnabled, CLIENT_INFO_HEADER } from './private.js';\nimport { VERSION as _VERSION } from './version.js';\n\nexport type Version = string;\n\n/**\n * The version of the `@globus/sdk` package that is in use.\n */\nexport const VERSION: Version = _VERSION;\n\nexport type Info = {\n product: string;\n version: Version;\n};\n\n/**\n * The client information identifier for this package.\n */\nexport const CLIENT_INFO: Info = {\n product: 'javascript-sdk',\n version: VERSION,\n};\n\nlet INFOS: Info[] = [CLIENT_INFO];\n\n/**\n * Add a client information identifier to the existing SDK information.\n */\nexport function addClientInfo(info: Info) {\n INFOS = INFOS.concat(info);\n}\n/**\n * Get the current client information as a string.\n */\nexport function getClientInfo(): string {\n return toString(INFOS);\n}\n\nexport function getClientInfoRequestHeaders(): Record<string, string> {\n if (!isEnabled()) {\n return {};\n }\n return {\n [CLIENT_INFO_HEADER]: getClientInfo(),\n };\n}\n", "import type { Info } from './index.js';\n\n/**\n * @private\n */\nexport const CLIENT_INFO_HEADER = `X-Globus-Client-Info`;\n\nlet ENABLED = true;\n/**\n * Disable the client information header from being included in requests (enabled by default).\n * @private\n */\nexport function disable() {\n ENABLED = false;\n}\n\n/**\n * Enables the client information header to be included in requests.\n * @private\n */\nexport function enable() {\n ENABLED = true;\n}\n\n/**\n * Whether or not the client information header should be sent with requests.\n * @private\n */\nexport function isEnabled() {\n return ENABLED;\n}\n\nconst INFOS_SEPERATOR = ';';\nconst INFO_ITEM_SEPARATOR = ',';\n\n/**\n * Exported for test purposes only.\n * @private\n */\nexport function toString(info: Info | Info[]) {\n const infos = Array.isArray(info) ? info : [info];\n return infos\n .map((i) =>\n Object.entries(i)\n .map(([key, value]) => `${key}=${value}`)\n .join(INFO_ITEM_SEPARATOR),\n )\n .join(INFOS_SEPERATOR);\n}\n", "// x-release-please-start-version\nexport const VERSION = '6.2.0';\n// x-release-please-end\n"],
|
|
5
5
|
"mappings": ";;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA,iBAAAA;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;;;ACKO,IAAM,qBAAqB;AAElC,IAAI,UAAU;AAqBP,SAAS,YAAY;AAC1B,SAAO;AACT;AAEA,IAAM,kBAAkB;AACxB,IAAM,sBAAsB;AAMrB,SAAS,SAAS,MAAqB;AAC5C,QAAM,QAAQ,MAAM,QAAQ,IAAI,IAAI,OAAO,CAAC,IAAI;AAChD,SAAO,MACJ;AAAA,IAAI,CAAC,MACJ,OAAO,QAAQ,CAAC,EACb,IAAI,CAAC,CAAC,KAAK,KAAK,MAAM,GAAG,GAAG,IAAI,KAAK,EAAE,EACvC,KAAK,mBAAmB;AAAA,EAC7B,EACC,KAAK,eAAe;AACzB;;;AC/CO,IAAM,UAAU;;;AFYhB,IAAMC,WAAmB;AAUzB,IAAM,cAAoB;AAAA,EAC/B,SAAS;AAAA,EACT,SAASA;AACX;AAEA,IAAI,QAAgB,CAAC,WAAW;AAKzB,SAAS,cAAc,MAAY;AACxC,UAAQ,MAAM,OAAO,IAAI;AAC3B;AAIO,SAAS,gBAAwB;AACtC,SAAO,SAAS,KAAK;AACvB;AAEO,SAAS,8BAAsD;AACpE,MAAI,CAAC,UAAU,GAAG;AAChB,WAAO,CAAC;AAAA,EACV;AACA,SAAO;AAAA,IACL,CAAC,kBAAkB,GAAG,cAAc;AAAA,EACtC;AACF;",
|
|
6
6
|
"names": ["VERSION", "VERSION"]
|
|
7
7
|
}
|