aws-amplify
Version:
AWS Amplify is a JavaScript library for Frontend and mobile developers building cloud-enabled applications.
179 lines (177 loc) • 8.72 kB
JavaScript
;
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
Object.defineProperty(exports, "__esModule", { value: true });
exports.Amplify = void 0;
const core_1 = require("@aws-amplify/core");
const utils_1 = require("@aws-amplify/core/internals/utils");
const cognito_1 = require("./auth/cognito");
/**
* The `Amplify` singleton facade provides the v6-compatible, global-state
* `configure()` / `getConfig()` API. It builds a branded, frozen
* {@link AmplifyContext}, publishes it as the global context (so category APIs
* can be called without an explicit context argument), and dispatches the
* `configure` Hub event that side effects such as auth's OAuth listener depend
* on.
*
* @example
* ```ts
* import { Amplify } from 'aws-amplify';
* import config from './amplifyconfiguration.json';
*
* Amplify.configure(config);
* ```
*/
exports.Amplify = {
/**
* Configures Amplify with the {@link resourceConfig} and {@link libraryOptions},
* publishing the resulting branded context as the global {@link AmplifyContext}.
*
* If `libraryOptions` is omitted on a reconfigure, the previously configured
* non-Auth `libraryOptions` are preserved (mirroring the previous singleton
* merge behavior); when provided they replace the previous ones. When
* `resourceConfig.Auth` is present and the caller does not supply
* `libraryOptions.Auth`, the default Cognito token/credentials providers are
* wired using cookie storage (`ssr: true`) or `localStorage` (default), and
* the singleton token provider's auth config is re-synced on every call so a
* reconfigure with a new `userPoolId` retargets token refresh.
*
* @param resourceConfig The {@link ResourcesConfig} object that is typically imported from the
* `amplifyconfiguration.json` / `amplify_outputs.json` file. It can also be an object literal
* created inline when calling `Amplify.configure`.
* @param libraryOptions The {@link LibraryOptions} additional options for the library.
*
* @example
* import config from './amplifyconfiguration.json';
*
* Amplify.configure(config);
*/
configure(resourceConfig, libraryOptions) {
const resolvedResourceConfig = (0, utils_1.parseAmplifyConfig)(resourceConfig);
const previousLibraryOptions = (0, core_1.hasGlobalContext)()
? (0, core_1.getGlobalContext)().libraryOptions
: undefined;
const resolvedLibraryOptions = resolveLibraryOptions(resolvedResourceConfig, libraryOptions, previousLibraryOptions);
// Build a branded + frozen context (with a fresh per-context AuthClass)
// via the core factory, then publish it as the global context.
const ctx = (0, core_1.createAmplifyContext)(resolvedResourceConfig, resolvedLibraryOptions);
(0, utils_1.setGlobalContext)(ctx);
// Notify listeners (e.g. auth's OAuth completion side effect) that the
// library has been (re)configured. The payload `data` carries the parsed
// ResourcesConfig so listeners can read `data.Auth.Cognito`.
core_1.Hub.dispatch('core', {
event: 'configure',
data: resolvedResourceConfig,
}, 'Configure', utils_1.AMPLIFY_SYMBOL);
},
/**
* Returns the {@link ResourcesConfig} object passed in as the `resourceConfig` parameter when
* calling `Amplify.configure`.
*
* If `configure()` has not been called yet, this warns and returns an empty
* config object (`{}`) rather than throwing, preserving the historical
* pre-context singleton behavior that callers (and release-gating e2e tests)
* depend on.
*
* @returns An {@link ResourcesConfig} object.
*/
getConfig() {
if (!(0, core_1.hasGlobalContext)()) {
// Preserve the historical unconfigured UX from the core singleton:
// warn and return an empty config instead of throwing.
// eslint-disable-next-line no-console
console.warn(`Amplify has not been configured. Please call Amplify.configure() before using this service.`);
return {};
}
return (0, core_1.getGlobalContext)().resourcesConfig;
},
/**
* Fetches the current auth session from the global context.
*
* @throws If `configure()` has not been called yet.
*/
fetchAuthSession(options) {
return (0, core_1.getGlobalContext)().fetchAuthSession(options);
},
/**
* Clears cached credentials in the global context.
*
* @throws If `configure()` has not been called yet.
*/
clearCredentials() {
return (0, core_1.getGlobalContext)().clearCredentials();
},
/**
* Fetches auth tokens from the global context.
*
* @throws If `configure()` has not been called yet.
*/
getTokens(options) {
return (0, core_1.getGlobalContext)().getTokens(options);
},
};
/**
* Resolves the effective {@link LibraryOptions} for the global singleton,
* preserving the previous `DefaultAmplify`-style default-provider
* behavior (process-wide **singleton** Cognito providers, `setAuthConfig` /
* `setKeyValueStorage` refresh).
*
* - No `Auth` in the resource config → pass options through unchanged
* (preserving previously-resolved options when the caller supplies none).
* - Caller-provided `libraryOptions.Auth` → take precedence (no defaults).
* - Otherwise (Auth present, no caller-supplied Auth providers) → on **every**
* call, including reconfigures with or without other `libraryOptions`, refresh
* the singleton token provider's auth config + storage and inject the
* singleton token/credentials providers. Non-Auth library options are still
* carried forward from the previous configuration when the caller passes none.
*/
function resolveLibraryOptions(resourceConfig, libraryOptions, previousLibraryOptions) {
// Pass-through: with no Auth in the resource config the singleton token
// provider is never involved, so simply preserve the previously configured
// libraryOptions when the caller supplies none (the core AmplifyClass
// singleton used to perform this merge), otherwise use what was given.
if (!resourceConfig.Auth) {
if (!libraryOptions && previousLibraryOptions) {
return previousLibraryOptions;
}
return libraryOptions ?? {};
}
// Caller-provided Auth providers always take precedence; never touch the
// singleton token provider in that case.
if (libraryOptions?.Auth) {
return libraryOptions;
}
// Auth is present and the caller did NOT supply their own Auth providers.
// Carry non-Auth library options forward from the previous configuration
// when the caller passes none (preserving prior behavior across
// reconfigure), but ALWAYS re-sync the
// singleton token provider below so the Auth providers never go stale.
const baseLibraryOptions = libraryOptions ?? previousLibraryOptions ?? {};
// Select the storage backing the default providers via core's shared
// helper (ssr → fresh cookie storage, else the localStorage-backed
// singleton). When ssr is set, reuse the SAME cookie storage instance for
// the identity-id store so tokens and identity ids share one cookie jar.
const resolvedKeyValueStorage = (0, utils_1.selectSsrKeyValueStorage)(baseLibraryOptions.ssr);
const resolvedCredentialsProvider = baseLibraryOptions.ssr
? new cognito_1.CognitoAWSCredentialsAndIdentityIdProvider(new cognito_1.DefaultIdentityIdStore(resolvedKeyValueStorage))
: cognito_1.cognitoCredentialsProvider;
// Re-push the resolved auth config + key-value storage into the process-wide
// singleton token provider on EVERY configure call. AuthClass.getTokens
// delegates to this provider's own authConfig, which is only ever updated
// here; skipping this on a reconfigure (e.g. a new userPoolId with no
// libraryOptions) would leave token refresh pinned to the previous pool
// while getConfig()/credentials reflect the new one. Restores the #14819
// contract.
cognito_1.cognitoUserPoolsTokenProvider.setAuthConfig(resourceConfig.Auth);
cognito_1.cognitoUserPoolsTokenProvider.setKeyValueStorage(
// TODO: allow configure with a public interface
resolvedKeyValueStorage);
return {
...baseLibraryOptions,
Auth: {
tokenProvider: cognito_1.cognitoUserPoolsTokenProvider,
credentialsProvider: resolvedCredentialsProvider,
},
};
}
//# sourceMappingURL=Amplify.js.map