@openedx/frontend-base 1.0.0-alpha.13 → 1.0.0-alpha.15
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/README.md +3 -3
- package/dist/runtime/config/index.js +5 -1
- package/dist/runtime/config/index.js.map +1 -1
- package/dist/runtime/index.d.ts +1 -1
- package/dist/runtime/index.js +1 -1
- package/dist/runtime/index.js.map +1 -1
- package/dist/runtime/initialize.js +4 -1
- package/dist/runtime/initialize.js.map +1 -1
- package/dist/runtime/jest.config.d.ts +0 -1
- package/dist/runtime/jest.config.js +0 -1
- package/dist/runtime/jest.config.js.map +1 -1
- package/dist/runtime/react/AuthenticatedPageRoute.d.ts +2 -0
- package/dist/runtime/react/AuthenticatedPageRoute.js +2 -0
- package/dist/runtime/react/AuthenticatedPageRoute.js.map +1 -1
- package/dist/runtime/react/NotFoundPage.d.ts +2 -0
- package/dist/runtime/react/NotFoundPage.js +14 -0
- package/dist/runtime/react/NotFoundPage.js.map +1 -0
- package/dist/runtime/react/index.d.ts +1 -0
- package/dist/runtime/react/index.js +1 -0
- package/dist/runtime/react/index.js.map +1 -1
- package/dist/runtime/routing/authenticatedLoader.d.ts +2 -0
- package/dist/runtime/routing/authenticatedLoader.js +27 -0
- package/dist/runtime/routing/authenticatedLoader.js.map +1 -0
- package/dist/runtime/routing/index.d.ts +1 -0
- package/dist/runtime/routing/index.js +1 -0
- package/dist/runtime/routing/index.js.map +1 -1
- package/dist/runtime/routing/utils.js +20 -5
- package/dist/runtime/routing/utils.js.map +1 -1
- package/dist/runtime/slots/Slot.d.ts +2 -1
- package/dist/runtime/slots/Slot.js +9 -4
- package/dist/runtime/slots/Slot.js.map +1 -1
- package/dist/runtime/slots/SlotContext.d.ts +1 -0
- package/dist/runtime/slots/SlotContext.js.map +1 -1
- package/dist/runtime/slots/hooks.d.ts +1 -0
- package/dist/runtime/slots/hooks.js +3 -3
- package/dist/runtime/slots/hooks.js.map +1 -1
- package/dist/runtime/slots/utils.d.ts +1 -1
- package/dist/runtime/slots/utils.js +2 -2
- package/dist/runtime/slots/utils.js.map +1 -1
- package/dist/runtime/slots/widget/hooks.d.ts +3 -3
- package/dist/runtime/slots/widget/hooks.js.map +1 -1
- package/dist/runtime/slots/widget/types.d.ts +8 -0
- package/dist/runtime/slots/widget/types.js.map +1 -1
- package/dist/runtime/slots/widget/utils.d.ts +2 -2
- package/dist/runtime/slots/widget/utils.js +20 -2
- package/dist/runtime/slots/widget/utils.js.map +1 -1
- package/dist/shell/Logo.js +4 -1
- package/dist/shell/Logo.js.map +1 -1
- package/dist/shell/dev/devHome/HomePage.js +3 -3
- package/dist/shell/dev/devHome/HomePage.js.map +1 -1
- package/dist/shell/dev/slotShowcase/HorizontalSlotLayout.js +2 -1
- package/dist/shell/dev/slotShowcase/HorizontalSlotLayout.js.map +1 -1
- package/dist/shell/dev/slotShowcase/LayoutWithOptions.js +2 -2
- package/dist/shell/dev/slotShowcase/LayoutWithOptions.js.map +1 -1
- package/dist/shell/dev/slotShowcase/SlotShowcasePage.d.ts +1 -0
- package/dist/shell/dev/slotShowcase/SlotShowcasePage.js +10 -1
- package/dist/shell/dev/slotShowcase/SlotShowcasePage.js.map +1 -1
- package/dist/shell/dev/slotShowcase/ToggleByRoleLayout.d.ts +1 -0
- package/dist/shell/dev/slotShowcase/ToggleByRoleLayout.js +11 -0
- package/dist/shell/dev/slotShowcase/ToggleByRoleLayout.js.map +1 -0
- package/dist/shell/dev/slotShowcase/WidgetWithOptions.js +1 -1
- package/dist/shell/dev/slotShowcase/WidgetWithOptions.js.map +1 -1
- package/dist/shell/dev/slotShowcase/app.js +76 -40
- package/dist/shell/dev/slotShowcase/app.js.map +1 -1
- package/dist/shell/header/AuthenticatedMenu.js +0 -2
- package/dist/shell/header/AuthenticatedMenu.js.map +1 -1
- package/dist/shell/jest.config.d.ts +0 -1
- package/dist/shell/jest.config.js +0 -1
- package/dist/shell/jest.config.js.map +1 -1
- package/dist/shell/router/createRouter.js +12 -1
- package/dist/shell/router/createRouter.js.map +1 -1
- package/dist/tools/babel.config.d.ts +2 -0
- package/dist/tools/babel.config.js +3 -0
- package/dist/tools/cli/openedx.js +1 -1
- package/dist/tools/cli/utils/formatter.js +1 -8
- package/dist/tools/eslint/base.eslint.config.js +4 -3
- package/dist/tools/jest/jest.config.d.ts +0 -1
- package/dist/tools/jest/jest.config.js +0 -1
- package/dist/tools/webpack/common-config/dev/getDevServer.js +1 -3
- package/dist/tools/webpack/plugins/html-webpack-new-relic-plugin/HtmlWebpackNewRelicPlugin.d.ts +1 -3
- package/dist/tools/webpack/utils/getPublicPath.js +1 -1
- package/dist/types.d.ts +2 -0
- package/dist/types.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -69,7 +69,7 @@ The development site will be available at `http://apps.local.openedx.io:8080`.
|
|
|
69
69
|
|
|
70
70
|
### Developing an app and `frontend-base` concurrently
|
|
71
71
|
|
|
72
|
-
Concurrent development with `frontend-base` uses a tarball-based workflow rather than traditional local linking approaches. See [
|
|
72
|
+
Concurrent development with `frontend-base` uses a tarball-based workflow rather than traditional local linking approaches. See the [`@openedx/frontend-dev-utils` autoinstall README](https://github.com/openedx/frontend-dev-utils/blob/main/tools/autoinstall/README.md) for details.
|
|
73
73
|
|
|
74
74
|
#### In `frontend-base`
|
|
75
75
|
|
|
@@ -78,13 +78,13 @@ This watches for changes in `frontend-base` and rebuilds the packaged tarball on
|
|
|
78
78
|
```sh
|
|
79
79
|
nvm use
|
|
80
80
|
npm ci
|
|
81
|
-
npm run
|
|
81
|
+
npm run pack:watch
|
|
82
82
|
```
|
|
83
83
|
|
|
84
84
|
#### In the consuming application
|
|
85
85
|
|
|
86
86
|
> [!NOTE]
|
|
87
|
-
> This assumes the consuming application
|
|
87
|
+
> This assumes the consuming application is using `devutils-dev-with-autoinstall` from `@openedx/frontend-dev-utils`.
|
|
88
88
|
|
|
89
89
|
This watches for changes to the generated .tgz, installs the updated package, and restarts the dev server.
|
|
90
90
|
|
|
@@ -254,7 +254,11 @@ export function addAppConfigs() {
|
|
|
254
254
|
publish(CONFIG_CHANGED);
|
|
255
255
|
}
|
|
256
256
|
export function getAppConfig(id) {
|
|
257
|
-
|
|
257
|
+
const { commonAppConfig } = getSiteConfig();
|
|
258
|
+
if (commonAppConfig === undefined) {
|
|
259
|
+
return appConfigs[id];
|
|
260
|
+
}
|
|
261
|
+
return merge({}, commonAppConfig, appConfigs[id]);
|
|
258
262
|
}
|
|
259
263
|
export function mergeAppConfig(id, newAppConfig) {
|
|
260
264
|
appConfigs[id] = merge(appConfigs[id], newAppConfig);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../runtime/config/index.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * #### Import members from **@edx/frontend-base**\n *\n * The configuration module provides utilities for working with an application's configuration\n * document (SiteConfig). Configuration variables can be supplied to the\n * application in three different ways. They are applied in the following order:\n *\n * - Site Configuration File (site.config.tsx)\n * - Initialization Config Handler\n * - Runtime Configuration\n *\n * Last one in wins, and are deep merged together. Variables with the same name defined via the\n * later methods will override any defined using an earlier method. i.e., if a variable is defined\n * in Runtime Configuration, that will override the same variable defined in either of the earlier\n * methods. Configuration defined in a JS file will override any default values below.\n *\n * ##### Site Configuration File\n *\n * Configuration variables can be supplied in a file named site.config.tsx. This file must\n * export either an Object containing configuration variables or a function. The function must\n * return an Object containing configuration variables or, alternately, a promise which resolves to\n * an Object.\n *\n * Using a function or async function allows the configuration to be resolved at runtime (because\n * the function will be executed at runtime). This is not common, and the capability is included\n * for the sake of flexibility.\n *\n * The Site Configuration File is well-suited to extensibility use cases or component overrides,\n * in that the configuration file can depend on any installed JavaScript module. It is also the\n * preferred way of doing build-time configuration if runtime configuration isn't used by your\n * deployment of the platform.\n *\n * Exporting a config object:\n * ```\n * const siteConfig = {\n * lmsBaseUrl: 'http://localhost:18000'\n * };\n *\n * export default siteConfig;\n * ```\n *\n * Exporting a function that returns an object:\n * ```\n * function getSiteConfig() {\n * return {\n * lmsBaseUrl: 'http://localhost:18000'\n * };\n * }\n * ```\n *\n * Exporting a function that returns a promise that resolves to an object:\n * ```\n * function getAsyncSiteConfig() {\n * return new Promise((resolve, reject) => {\n * resolve({\n * lmsBaseUrl: 'http://localhost:18000'\n * });\n * });\n * }\n *\n * export default getAsyncSiteConfig;\n * ```\n *\n * ##### Initialization Config Handler\n *\n * The configuration document can be extended by\n * applications at run-time using a `config` initialization handler. Please see the Initialization\n * documentation for more information on handlers and initialization phases.\n *\n * ```\n * initialize({\n * handlers: {\n * config: () => {\n * mergeSiteConfig({\n * CUSTOM_VARIABLE: 'custom value',\n * lmsBaseUrl: 'http://localhost:18001' // You can override variables, but this is uncommon.\n * }, 'App config override handler');\n * },\n * },\n * });\n * ```\n *\n * ##### Runtime Configuration\n *\n * Configuration variables can also be supplied using the \"runtime configuration\" method, taking\n * advantage of the Micro-frontend Config API in edx-platform. More information on this API can be\n * found in the ADR which introduced it:\n *\n * https://github.com/openedx/edx-platform/blob/master/lms/djangoapps/mfe_config_api/docs/decisions/0001-mfe-config-api.rst\n *\n * The runtime configuration method can be enabled by supplying a runtimeConfigJsonUrl via one of the other\n * two configuration methods above.\n *\n * Runtime configuration is particularly useful if you need to supply different configurations to\n * a single deployment of a micro-frontend, for instance. It is also a perfectly valid alternative\n * to build-time configuration, though it introduces an additional API call to edx-platform on MFE\n * initialization.\n *\n *\n * @module Config\n */\n\nimport keyBy from 'lodash.keyby';\nimport merge from 'lodash.merge';\nimport {\n AppConfig,\n EnvironmentTypes,\n SiteConfig\n} from '../../types';\nimport { ACTIVE_ROLES_CHANGED, CONFIG_CHANGED } from '../constants';\nimport { publish } from '../subscriptions';\n\nlet siteConfig: SiteConfig = {\n // Required\n siteId: '',\n baseUrl: '',\n siteName: '',\n loginUrl: '',\n logoutUrl: '',\n lmsBaseUrl: '',\n\n // Optional\n environment: EnvironmentTypes.PRODUCTION,\n apps: [],\n externalRoutes: [],\n externalLinkUrlOverrides: [],\n runtimeConfigJsonUrl: null,\n theme: {},\n accessTokenCookieName: 'edx-jwt-cookie-header-payload',\n csrfTokenApiPath: '/csrf/api/v1/token',\n ignoredErrorRegex: null,\n languagePreferenceCookieName: 'openedx-language-preference',\n refreshAccessTokenApiPath: '/login_refresh',\n userInfoCookieName: 'edx-user-info',\n segmentKey: null,\n};\n\n/**\n * Getter for the application configuration document. This is synchronous and merely returns a\n * reference to an existing object, and is thus safe to call as often as desired.\n *\n * Example:\n *\n * ```\n * import { getSiteConfig } from '@openedx/frontend-base';\n *\n * const {\n * lmsBaseUrl,\n * } = getSiteConfig();\n * ```\n *\n * @returns {SiteConfig}\n */\nexport function getSiteConfig() {\n return siteConfig;\n}\n\n/**\n * Replaces the existing SiteConfig. This is not commonly used, but can be helpful for tests.\n *\n * Example:\n *\n * ```\n * import { setSiteConfig } from '@openedx/frontend-base';\n *\n * setSiteConfig({\n * lmsBaseUrl, // This is overriding the ENTIRE document - this is not merged in!\n * });\n * ```\n *\n * @param newConfig A replacement SiteConfig which will completely override the current SiteConfig.\n */\nexport function setSiteConfig(newSiteConfig: SiteConfig) {\n siteConfig = newSiteConfig;\n publish(CONFIG_CHANGED);\n}\n\ninterface MergeSiteConfigOptions {\n limitAppMergeToConfig?: boolean,\n}\n\n/**\n * Merges additional configuration values into the site config returned by `getSiteConfig`. Will\n * override any values that exist with the same keys.\n *\n * ```\n * mergeSiteConfig({\n * NEW_KEY: 'new value',\n * OTHER_NEW_KEY: 'other new value',\n * });\n *\n * This function uses lodash.merge internally to merge configuration objects\n * which means they will be merged recursively. See https://lodash.com/docs/latest#merge for\n * documentation on the exact behavior.\n *\n * Apps are merged by appId rather than array index. By default, apps in the incoming config\n * that don't exist in the current config will be added.\n *\n * When `limitAppMergeToConfig` is true:\n * - All non-app parts of the config are still merged normally\n * - Only the `config` property of each existing app is merged\n * - Apps in the incoming config that don't exist in the current config are ignored\n *\n * @param {Object} newSiteConfig\n * @param {Object} options\n * @param {boolean} options.limitAppMergeToConfig - Limit app merging to only the config property of existing apps\n */\nexport function mergeSiteConfig(\n newSiteConfig: Partial<SiteConfig>,\n options: MergeSiteConfigOptions = {}\n) {\n const { limitAppMergeToConfig = false } = options;\n const { apps: newApps, ...restOfNewConfig } = newSiteConfig;\n\n // lodash merge the top-level (non-app) part\n siteConfig = merge(siteConfig, restOfNewConfig);\n\n // if we don't have new apps, we're done\n if (!newApps?.length) {\n publish(CONFIG_CHANGED);\n return;\n }\n\n // if we're doing a full merge, merge the objects\n if (!limitAppMergeToConfig) {\n siteConfig.apps = Object.values(merge(\n keyBy(siteConfig.apps || [], 'appId'),\n keyBy(newApps, 'appId')\n ));\n publish(CONFIG_CHANGED);\n return;\n }\n\n // we're doing a config-only merge, if we don't\n // have apps already, we can't update their configs\n if (!siteConfig.apps?.length) {\n publish(CONFIG_CHANGED);\n return;\n }\n\n // handle config-only merging\n const newAppsById = keyBy(newApps, 'appId');\n for (const app of siteConfig.apps) {\n const newApp = newAppsById[app.appId];\n if (newApp?.config) {\n app.config = merge(app.config, newApp.config);\n }\n }\n\n publish(CONFIG_CHANGED);\n}\n\nconst appConfigs: Record<string, AppConfig> = {};\n\n/**\n * addAppConfigs finds any AppConfig objects in the apps in SiteConfig and makes their config\n * available to be used by Apps via getAppConfig(appId) or useAppConfig() functions. This is\n * used at initialization time to process any AppConfigs bundled with the site.\n */\nexport function addAppConfigs() {\n const { apps } = getSiteConfig();\n if (!apps) return;\n\n for (const app of apps) {\n const { appId, config } = app;\n if (config !== undefined) {\n appConfigs[appId] = config;\n }\n }\n\n publish(CONFIG_CHANGED);\n}\n\nexport function getAppConfig(id: string) {\n return appConfigs[id];\n}\n\nexport function mergeAppConfig(id: string, newAppConfig: AppConfig) {\n appConfigs[id] = merge(appConfigs[id], newAppConfig);\n publish(CONFIG_CHANGED);\n}\n\nlet activeRouteRoles: string[] = [];\n\nexport function setActiveRouteRoles(roles: string[]) {\n activeRouteRoles = roles;\n publish(ACTIVE_ROLES_CHANGED);\n}\n\nexport function getActiveRouteRoles() {\n return activeRouteRoles;\n}\n\nconst activeWidgetRoles: Record<string, number> = {};\n\nexport function addActiveWidgetRole(role: string) {\n activeWidgetRoles[role] ??= 0;\n activeWidgetRoles[role] += 1;\n publish(ACTIVE_ROLES_CHANGED);\n}\n\nexport function removeActiveWidgetRole(role: string) {\n if (activeWidgetRoles[role] !== undefined) {\n activeWidgetRoles[role] -= 1;\n }\n if (activeWidgetRoles[role] < 1) {\n delete activeWidgetRoles[role];\n }\n publish(ACTIVE_ROLES_CHANGED);\n}\n\nexport function getActiveWidgetRoles() {\n return Object.entries(activeWidgetRoles)\n .filter(([, count]: [role: string, count: number]) => count !== undefined && count > 0)\n .map(([role]: [role: string, count: number]) => role);\n}\n\n// Gets all active roles from the route roles and widget roles.\nexport function getActiveRoles() {\n return [...getActiveRouteRoles(), ...getActiveWidgetRoles()];\n}\n\n/**\n * Get an external link URL based on the URL provided. If the passed in URL is overridden in the\n * `externalLinkUrlOverrides` object, it will return the overridden URL. Otherwise, it will return\n * the provided URL.\n *\n *\n * @param {string} url - The default URL.\n * @returns {string} - The external link URL. Defaults to the input URL if not found in the\n * `externalLinkUrlOverrides` object. If the input URL is invalid, '#' is returned.\n *\n * @example\n * import { getExternalLinkUrl } from '@openedx/frontend-base';\n *\n * <Hyperlink\n * destination={getExternalLinkUrl(data.helpLink)}\n * target=\"_blank\"\n * >\n */\nexport function getExternalLinkUrl(url: string): string {\n // Guard against whitespace-only strings\n if (typeof url !== 'string' || !url.trim()) {\n return '#';\n }\n\n const overriddenLinkUrls = getSiteConfig().externalLinkUrlOverrides ?? {};\n return overriddenLinkUrls[url] ?? url;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../runtime/config/index.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * #### Import members from **@edx/frontend-base**\n *\n * The configuration module provides utilities for working with an application's configuration\n * document (SiteConfig). Configuration variables can be supplied to the\n * application in three different ways. They are applied in the following order:\n *\n * - Site Configuration File (site.config.tsx)\n * - Initialization Config Handler\n * - Runtime Configuration\n *\n * Last one in wins, and are deep merged together. Variables with the same name defined via the\n * later methods will override any defined using an earlier method. i.e., if a variable is defined\n * in Runtime Configuration, that will override the same variable defined in either of the earlier\n * methods. Configuration defined in a JS file will override any default values below.\n *\n * ##### Site Configuration File\n *\n * Configuration variables can be supplied in a file named site.config.tsx. This file must\n * export either an Object containing configuration variables or a function. The function must\n * return an Object containing configuration variables or, alternately, a promise which resolves to\n * an Object.\n *\n * Using a function or async function allows the configuration to be resolved at runtime (because\n * the function will be executed at runtime). This is not common, and the capability is included\n * for the sake of flexibility.\n *\n * The Site Configuration File is well-suited to extensibility use cases or component overrides,\n * in that the configuration file can depend on any installed JavaScript module. It is also the\n * preferred way of doing build-time configuration if runtime configuration isn't used by your\n * deployment of the platform.\n *\n * Exporting a config object:\n * ```\n * const siteConfig = {\n * lmsBaseUrl: 'http://localhost:18000'\n * };\n *\n * export default siteConfig;\n * ```\n *\n * Exporting a function that returns an object:\n * ```\n * function getSiteConfig() {\n * return {\n * lmsBaseUrl: 'http://localhost:18000'\n * };\n * }\n * ```\n *\n * Exporting a function that returns a promise that resolves to an object:\n * ```\n * function getAsyncSiteConfig() {\n * return new Promise((resolve, reject) => {\n * resolve({\n * lmsBaseUrl: 'http://localhost:18000'\n * });\n * });\n * }\n *\n * export default getAsyncSiteConfig;\n * ```\n *\n * ##### Initialization Config Handler\n *\n * The configuration document can be extended by\n * applications at run-time using a `config` initialization handler. Please see the Initialization\n * documentation for more information on handlers and initialization phases.\n *\n * ```\n * initialize({\n * handlers: {\n * config: () => {\n * mergeSiteConfig({\n * CUSTOM_VARIABLE: 'custom value',\n * lmsBaseUrl: 'http://localhost:18001' // You can override variables, but this is uncommon.\n * }, 'App config override handler');\n * },\n * },\n * });\n * ```\n *\n * ##### Runtime Configuration\n *\n * Configuration variables can also be supplied using the \"runtime configuration\" method, taking\n * advantage of the Micro-frontend Config API in edx-platform. More information on this API can be\n * found in the ADR which introduced it:\n *\n * https://github.com/openedx/edx-platform/blob/master/lms/djangoapps/mfe_config_api/docs/decisions/0001-mfe-config-api.rst\n *\n * The runtime configuration method can be enabled by supplying a runtimeConfigJsonUrl via one of the other\n * two configuration methods above.\n *\n * Runtime configuration is particularly useful if you need to supply different configurations to\n * a single deployment of a micro-frontend, for instance. It is also a perfectly valid alternative\n * to build-time configuration, though it introduces an additional API call to edx-platform on MFE\n * initialization.\n *\n *\n * @module Config\n */\n\nimport keyBy from 'lodash.keyby';\nimport merge from 'lodash.merge';\nimport {\n AppConfig,\n EnvironmentTypes,\n SiteConfig\n} from '../../types';\nimport { ACTIVE_ROLES_CHANGED, CONFIG_CHANGED } from '../constants';\nimport { publish } from '../subscriptions';\n\nlet siteConfig: SiteConfig = {\n // Required\n siteId: '',\n baseUrl: '',\n siteName: '',\n loginUrl: '',\n logoutUrl: '',\n lmsBaseUrl: '',\n\n // Optional\n environment: EnvironmentTypes.PRODUCTION,\n apps: [],\n externalRoutes: [],\n externalLinkUrlOverrides: [],\n runtimeConfigJsonUrl: null,\n theme: {},\n accessTokenCookieName: 'edx-jwt-cookie-header-payload',\n csrfTokenApiPath: '/csrf/api/v1/token',\n ignoredErrorRegex: null,\n languagePreferenceCookieName: 'openedx-language-preference',\n refreshAccessTokenApiPath: '/login_refresh',\n userInfoCookieName: 'edx-user-info',\n segmentKey: null,\n};\n\n/**\n * Getter for the application configuration document. This is synchronous and merely returns a\n * reference to an existing object, and is thus safe to call as often as desired.\n *\n * Example:\n *\n * ```\n * import { getSiteConfig } from '@openedx/frontend-base';\n *\n * const {\n * lmsBaseUrl,\n * } = getSiteConfig();\n * ```\n *\n * @returns {SiteConfig}\n */\nexport function getSiteConfig() {\n return siteConfig;\n}\n\n/**\n * Replaces the existing SiteConfig. This is not commonly used, but can be helpful for tests.\n *\n * Example:\n *\n * ```\n * import { setSiteConfig } from '@openedx/frontend-base';\n *\n * setSiteConfig({\n * lmsBaseUrl, // This is overriding the ENTIRE document - this is not merged in!\n * });\n * ```\n *\n * @param newConfig A replacement SiteConfig which will completely override the current SiteConfig.\n */\nexport function setSiteConfig(newSiteConfig: SiteConfig) {\n siteConfig = newSiteConfig;\n publish(CONFIG_CHANGED);\n}\n\ninterface MergeSiteConfigOptions {\n limitAppMergeToConfig?: boolean,\n}\n\n/**\n * Merges additional configuration values into the site config returned by `getSiteConfig`. Will\n * override any values that exist with the same keys.\n *\n * ```\n * mergeSiteConfig({\n * NEW_KEY: 'new value',\n * OTHER_NEW_KEY: 'other new value',\n * });\n *\n * This function uses lodash.merge internally to merge configuration objects\n * which means they will be merged recursively. See https://lodash.com/docs/latest#merge for\n * documentation on the exact behavior.\n *\n * Apps are merged by appId rather than array index. By default, apps in the incoming config\n * that don't exist in the current config will be added.\n *\n * When `limitAppMergeToConfig` is true:\n * - All non-app parts of the config are still merged normally\n * - Only the `config` property of each existing app is merged\n * - Apps in the incoming config that don't exist in the current config are ignored\n *\n * @param {Object} newSiteConfig\n * @param {Object} options\n * @param {boolean} options.limitAppMergeToConfig - Limit app merging to only the config property of existing apps\n */\nexport function mergeSiteConfig(\n newSiteConfig: Partial<SiteConfig>,\n options: MergeSiteConfigOptions = {}\n) {\n const { limitAppMergeToConfig = false } = options;\n const { apps: newApps, ...restOfNewConfig } = newSiteConfig;\n\n // lodash merge the top-level (non-app) part\n siteConfig = merge(siteConfig, restOfNewConfig);\n\n // if we don't have new apps, we're done\n if (!newApps?.length) {\n publish(CONFIG_CHANGED);\n return;\n }\n\n // if we're doing a full merge, merge the objects\n if (!limitAppMergeToConfig) {\n siteConfig.apps = Object.values(merge(\n keyBy(siteConfig.apps || [], 'appId'),\n keyBy(newApps, 'appId')\n ));\n publish(CONFIG_CHANGED);\n return;\n }\n\n // we're doing a config-only merge, if we don't\n // have apps already, we can't update their configs\n if (!siteConfig.apps?.length) {\n publish(CONFIG_CHANGED);\n return;\n }\n\n // handle config-only merging\n const newAppsById = keyBy(newApps, 'appId');\n for (const app of siteConfig.apps) {\n const newApp = newAppsById[app.appId];\n if (newApp?.config) {\n app.config = merge(app.config, newApp.config);\n }\n }\n\n publish(CONFIG_CHANGED);\n}\n\nconst appConfigs: Record<string, AppConfig> = {};\n\n/**\n * addAppConfigs finds any AppConfig objects in the apps in SiteConfig and makes their config\n * available to be used by Apps via getAppConfig(appId) or useAppConfig() functions. This is\n * used at initialization time to process any AppConfigs bundled with the site.\n */\nexport function addAppConfigs() {\n const { apps } = getSiteConfig();\n if (!apps) return;\n\n for (const app of apps) {\n const { appId, config } = app;\n if (config !== undefined) {\n appConfigs[appId] = config;\n }\n }\n\n publish(CONFIG_CHANGED);\n}\n\nexport function getAppConfig(id: string) {\n const { commonAppConfig } = getSiteConfig();\n if (commonAppConfig === undefined) {\n return appConfigs[id];\n }\n return merge({}, commonAppConfig, appConfigs[id]);\n}\n\nexport function mergeAppConfig(id: string, newAppConfig: AppConfig) {\n appConfigs[id] = merge(appConfigs[id], newAppConfig);\n publish(CONFIG_CHANGED);\n}\n\nlet activeRouteRoles: string[] = [];\n\nexport function setActiveRouteRoles(roles: string[]) {\n activeRouteRoles = roles;\n publish(ACTIVE_ROLES_CHANGED);\n}\n\nexport function getActiveRouteRoles() {\n return activeRouteRoles;\n}\n\nconst activeWidgetRoles: Record<string, number> = {};\n\nexport function addActiveWidgetRole(role: string) {\n activeWidgetRoles[role] ??= 0;\n activeWidgetRoles[role] += 1;\n publish(ACTIVE_ROLES_CHANGED);\n}\n\nexport function removeActiveWidgetRole(role: string) {\n if (activeWidgetRoles[role] !== undefined) {\n activeWidgetRoles[role] -= 1;\n }\n if (activeWidgetRoles[role] < 1) {\n delete activeWidgetRoles[role];\n }\n publish(ACTIVE_ROLES_CHANGED);\n}\n\nexport function getActiveWidgetRoles() {\n return Object.entries(activeWidgetRoles)\n .filter(([, count]: [role: string, count: number]) => count !== undefined && count > 0)\n .map(([role]: [role: string, count: number]) => role);\n}\n\n// Gets all active roles from the route roles and widget roles.\nexport function getActiveRoles() {\n return [...getActiveRouteRoles(), ...getActiveWidgetRoles()];\n}\n\n/**\n * Get an external link URL based on the URL provided. If the passed in URL is overridden in the\n * `externalLinkUrlOverrides` object, it will return the overridden URL. Otherwise, it will return\n * the provided URL.\n *\n *\n * @param {string} url - The default URL.\n * @returns {string} - The external link URL. Defaults to the input URL if not found in the\n * `externalLinkUrlOverrides` object. If the input URL is invalid, '#' is returned.\n *\n * @example\n * import { getExternalLinkUrl } from '@openedx/frontend-base';\n *\n * <Hyperlink\n * destination={getExternalLinkUrl(data.helpLink)}\n * target=\"_blank\"\n * >\n */\nexport function getExternalLinkUrl(url: string): string {\n // Guard against whitespace-only strings\n if (typeof url !== 'string' || !url.trim()) {\n return '#';\n }\n\n const overriddenLinkUrls = getSiteConfig().externalLinkUrlOverrides ?? {};\n return overriddenLinkUrls[url] ?? url;\n}\n"]}
|
package/dist/runtime/index.d.ts
CHANGED
|
@@ -6,7 +6,7 @@ export { configureI18n, createIntl, defineMessages, FormattedDate, FormattedMess
|
|
|
6
6
|
export { auth, getBasename, initError, initialize } from './initialize';
|
|
7
7
|
export { configureLogging, getLoggingService, logError, logInfo, MockLoggingService, NewRelicLoggingService, resetLoggingService } from './logging';
|
|
8
8
|
export { CurrentAppContext, CurrentAppProvider, SiteContext, SiteProvider, AuthenticatedPageRoute, Divider, ErrorBoundary, ErrorPage, LoginRedirect, PageWrap, useSiteEvent, useAuthenticatedUser, useSiteConfig, useAppConfig } from './react';
|
|
9
|
-
export { getUrlByRouteRole, isRoleRouteObject } from './routing';
|
|
9
|
+
export { authenticatedLoader, getUrlByRouteRole, isRoleRouteObject } from './routing';
|
|
10
10
|
export { clearAllSubscriptions, publish, subscribe, unsubscribe } from './subscriptions';
|
|
11
11
|
export { initializeMockApp, mockMessages } from './testing';
|
|
12
12
|
export { camelCaseObject, convertKeyNames, getQueryParameters, isValidVariableName, modifyObjectKeys, snakeCaseObject } from './utils';
|
package/dist/runtime/index.js
CHANGED
|
@@ -6,7 +6,7 @@ export { configureI18n, createIntl, defineMessages, FormattedDate, FormattedMess
|
|
|
6
6
|
export { auth, getBasename, initError, initialize } from './initialize';
|
|
7
7
|
export { configureLogging, getLoggingService, logError, logInfo, MockLoggingService, NewRelicLoggingService, resetLoggingService } from './logging';
|
|
8
8
|
export { CurrentAppContext, CurrentAppProvider, SiteContext, SiteProvider, AuthenticatedPageRoute, Divider, ErrorBoundary, ErrorPage, LoginRedirect, PageWrap, useSiteEvent, useAuthenticatedUser, useSiteConfig, useAppConfig } from './react';
|
|
9
|
-
export { getUrlByRouteRole, isRoleRouteObject } from './routing';
|
|
9
|
+
export { authenticatedLoader, getUrlByRouteRole, isRoleRouteObject } from './routing';
|
|
10
10
|
export { clearAllSubscriptions, publish, subscribe, unsubscribe } from './subscriptions';
|
|
11
11
|
export { initializeMockApp, mockMessages } from './testing';
|
|
12
12
|
export { camelCaseObject, convertKeyNames, getQueryParameters, isValidVariableName, modifyObjectKeys, snakeCaseObject } from './utils';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../runtime/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAClB,mBAAmB,EACnB,qBAAqB,EACrB,yBAAyB,EACzB,oBAAoB,EACpB,qBAAqB,EACrB,uBAAuB,EACvB,aAAa,EACb,cAAc,EACd,oBAAoB,EACrB,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,0BAA0B,EAC1B,wBAAwB,EACxB,mBAAmB,EACnB,aAAa,EACb,uBAAuB,EACvB,sBAAsB,EACtB,0BAA0B,EAC1B,oBAAoB,EACpB,cAAc,EACd,aAAa,EACb,mBAAmB,EACnB,oBAAoB,EACpB,wBAAwB,EACxB,eAAe,EACf,eAAe,EACf,gBAAgB,EAChB,oBAAoB,EACrB,MAAM,QAAQ,CAAC;AAEhB,OAAO,EACL,aAAa,EACb,aAAa,EACb,eAAe,EACf,aAAa,EACb,YAAY,EACZ,cAAc,EACd,mBAAmB,EACnB,mBAAmB,EACnB,mBAAmB,EACnB,sBAAsB,EACtB,oBAAoB,EACpB,cAAc,EACd,kBAAkB,EACnB,MAAM,UAAU,CAAC;AAElB,cAAc,aAAa,CAAC;AAE5B,OAAO,EACL,aAAa,EACb,UAAU,EACV,cAAc,EACd,aAAa,EACb,gBAAgB,EAChB,eAAe,EACf,eAAe,EACf,qBAAqB,EACrB,aAAa,EACb,SAAS,EACT,wBAAwB,EACxB,WAAW,EACX,wBAAwB,EACxB,wBAAwB,EACxB,SAAS,EACT,UAAU,EACV,YAAY,EACZ,SAAS,EACT,KAAK,EACL,cAAc,EACd,YAAY,EACZ,aAAa,EACb,YAAY,EACZ,OAAO,EACR,MAAM,QAAQ,CAAC;AAEhB,OAAO,EACL,IAAI,EACJ,WAAW,EACX,SAAS,EACT,UAAU,EACX,MAAM,cAAc,CAAC;AAEtB,OAAO,EACL,gBAAgB,EAChB,iBAAiB,EACjB,QAAQ,EACR,OAAO,EACP,kBAAkB,EAClB,sBAAsB,EACtB,mBAAmB,EACpB,MAAM,WAAW,CAAC;AAEnB,OAAO,EACL,iBAAiB,EACjB,kBAAkB,EAClB,WAAW,EACX,YAAY,EACZ,sBAAsB,EACtB,OAAO,EACP,aAAa,EACb,SAAS,EACT,aAAa,EACb,QAAQ,EACR,YAAY,EACZ,oBAAoB,EACpB,aAAa,EACb,YAAY,EACb,MAAM,SAAS,CAAC;AAEjB,OAAO,EACL,iBAAiB,EACjB,iBAAiB,EAClB,MAAM,WAAW,CAAC;AAEnB,OAAO,EACL,qBAAqB,EACrB,OAAO,EACP,SAAS,EACT,WAAW,EACZ,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EACL,iBAAiB,EACjB,YAAY,EACb,MAAM,WAAW,CAAC;AAEnB,OAAO,EACL,eAAe,EACf,eAAe,EACf,kBAAkB,EAClB,mBAAmB,EACnB,gBAAgB,EAChB,eAAe,EAChB,MAAM,SAAS,CAAC;AAEjB,cAAc,SAAS,CAAC","sourcesContent":["export {\n configureAnalytics,\n getAnalyticsService,\n identifyAnonymousUser,\n identifyAuthenticatedUser,\n MockAnalyticsService,\n resetAnalyticsService,\n SegmentAnalyticsService,\n sendPageEvent,\n sendTrackEvent,\n sendTrackingLogEvent\n} from './analytics';\n\nexport {\n AUTHENTICATED_USER_CHANGED,\n AUTHENTICATED_USER_TOPIC,\n AxiosJwtAuthService,\n configureAuth,\n ensureAuthenticatedUser,\n fetchAuthenticatedUser,\n getAuthenticatedHttpClient,\n getAuthenticatedUser,\n getAuthService,\n getHttpClient,\n getLoginRedirectUrl,\n getLogoutRedirectUrl,\n hydrateAuthenticatedUser,\n MockAuthService,\n redirectToLogin,\n redirectToLogout,\n setAuthenticatedUser\n} from './auth';\n\nexport {\n getSiteConfig,\n setSiteConfig,\n mergeSiteConfig,\n addAppConfigs,\n getAppConfig,\n mergeAppConfig,\n setActiveRouteRoles,\n getActiveRouteRoles,\n addActiveWidgetRole,\n removeActiveWidgetRole,\n getActiveWidgetRoles,\n getActiveRoles,\n getExternalLinkUrl\n} from './config';\n\nexport * from './constants';\n\nexport {\n configureI18n,\n createIntl,\n defineMessages,\n FormattedDate,\n FormattedMessage,\n FormattedNumber,\n FormattedPlural,\n FormattedRelativeTime,\n FormattedTime,\n getLocale,\n getLocalizedLanguageName,\n getMessages,\n getPrimaryLanguageSubtag,\n getSupportedLanguageList,\n handleRtl,\n injectIntl,\n IntlProvider,\n intlShape,\n isRtl,\n LOCALE_CHANGED,\n LOCALE_TOPIC,\n mergeMessages,\n updateLocale,\n useIntl\n} from './i18n';\n\nexport {\n auth,\n getBasename,\n initError,\n initialize\n} from './initialize';\n\nexport {\n configureLogging,\n getLoggingService,\n logError,\n logInfo,\n MockLoggingService,\n NewRelicLoggingService,\n resetLoggingService\n} from './logging';\n\nexport {\n CurrentAppContext,\n CurrentAppProvider,\n SiteContext,\n SiteProvider,\n AuthenticatedPageRoute,\n Divider,\n ErrorBoundary,\n ErrorPage,\n LoginRedirect,\n PageWrap,\n useSiteEvent,\n useAuthenticatedUser,\n useSiteConfig,\n useAppConfig\n} from './react';\n\nexport {\n getUrlByRouteRole,\n isRoleRouteObject\n} from './routing';\n\nexport {\n clearAllSubscriptions,\n publish,\n subscribe,\n unsubscribe\n} from './subscriptions';\n\nexport {\n initializeMockApp,\n mockMessages\n} from './testing';\n\nexport {\n camelCaseObject,\n convertKeyNames,\n getQueryParameters,\n isValidVariableName,\n modifyObjectKeys,\n snakeCaseObject\n} from './utils';\n\nexport * from './slots';\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../runtime/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAClB,mBAAmB,EACnB,qBAAqB,EACrB,yBAAyB,EACzB,oBAAoB,EACpB,qBAAqB,EACrB,uBAAuB,EACvB,aAAa,EACb,cAAc,EACd,oBAAoB,EACrB,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,0BAA0B,EAC1B,wBAAwB,EACxB,mBAAmB,EACnB,aAAa,EACb,uBAAuB,EACvB,sBAAsB,EACtB,0BAA0B,EAC1B,oBAAoB,EACpB,cAAc,EACd,aAAa,EACb,mBAAmB,EACnB,oBAAoB,EACpB,wBAAwB,EACxB,eAAe,EACf,eAAe,EACf,gBAAgB,EAChB,oBAAoB,EACrB,MAAM,QAAQ,CAAC;AAEhB,OAAO,EACL,aAAa,EACb,aAAa,EACb,eAAe,EACf,aAAa,EACb,YAAY,EACZ,cAAc,EACd,mBAAmB,EACnB,mBAAmB,EACnB,mBAAmB,EACnB,sBAAsB,EACtB,oBAAoB,EACpB,cAAc,EACd,kBAAkB,EACnB,MAAM,UAAU,CAAC;AAElB,cAAc,aAAa,CAAC;AAE5B,OAAO,EACL,aAAa,EACb,UAAU,EACV,cAAc,EACd,aAAa,EACb,gBAAgB,EAChB,eAAe,EACf,eAAe,EACf,qBAAqB,EACrB,aAAa,EACb,SAAS,EACT,wBAAwB,EACxB,WAAW,EACX,wBAAwB,EACxB,wBAAwB,EACxB,SAAS,EACT,UAAU,EACV,YAAY,EACZ,SAAS,EACT,KAAK,EACL,cAAc,EACd,YAAY,EACZ,aAAa,EACb,YAAY,EACZ,OAAO,EACR,MAAM,QAAQ,CAAC;AAEhB,OAAO,EACL,IAAI,EACJ,WAAW,EACX,SAAS,EACT,UAAU,EACX,MAAM,cAAc,CAAC;AAEtB,OAAO,EACL,gBAAgB,EAChB,iBAAiB,EACjB,QAAQ,EACR,OAAO,EACP,kBAAkB,EAClB,sBAAsB,EACtB,mBAAmB,EACpB,MAAM,WAAW,CAAC;AAEnB,OAAO,EACL,iBAAiB,EACjB,kBAAkB,EAClB,WAAW,EACX,YAAY,EACZ,sBAAsB,EACtB,OAAO,EACP,aAAa,EACb,SAAS,EACT,aAAa,EACb,QAAQ,EACR,YAAY,EACZ,oBAAoB,EACpB,aAAa,EACb,YAAY,EACb,MAAM,SAAS,CAAC;AAEjB,OAAO,EACL,mBAAmB,EACnB,iBAAiB,EACjB,iBAAiB,EAClB,MAAM,WAAW,CAAC;AAEnB,OAAO,EACL,qBAAqB,EACrB,OAAO,EACP,SAAS,EACT,WAAW,EACZ,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EACL,iBAAiB,EACjB,YAAY,EACb,MAAM,WAAW,CAAC;AAEnB,OAAO,EACL,eAAe,EACf,eAAe,EACf,kBAAkB,EAClB,mBAAmB,EACnB,gBAAgB,EAChB,eAAe,EAChB,MAAM,SAAS,CAAC;AAEjB,cAAc,SAAS,CAAC","sourcesContent":["export {\n configureAnalytics,\n getAnalyticsService,\n identifyAnonymousUser,\n identifyAuthenticatedUser,\n MockAnalyticsService,\n resetAnalyticsService,\n SegmentAnalyticsService,\n sendPageEvent,\n sendTrackEvent,\n sendTrackingLogEvent\n} from './analytics';\n\nexport {\n AUTHENTICATED_USER_CHANGED,\n AUTHENTICATED_USER_TOPIC,\n AxiosJwtAuthService,\n configureAuth,\n ensureAuthenticatedUser,\n fetchAuthenticatedUser,\n getAuthenticatedHttpClient,\n getAuthenticatedUser,\n getAuthService,\n getHttpClient,\n getLoginRedirectUrl,\n getLogoutRedirectUrl,\n hydrateAuthenticatedUser,\n MockAuthService,\n redirectToLogin,\n redirectToLogout,\n setAuthenticatedUser\n} from './auth';\n\nexport {\n getSiteConfig,\n setSiteConfig,\n mergeSiteConfig,\n addAppConfigs,\n getAppConfig,\n mergeAppConfig,\n setActiveRouteRoles,\n getActiveRouteRoles,\n addActiveWidgetRole,\n removeActiveWidgetRole,\n getActiveWidgetRoles,\n getActiveRoles,\n getExternalLinkUrl\n} from './config';\n\nexport * from './constants';\n\nexport {\n configureI18n,\n createIntl,\n defineMessages,\n FormattedDate,\n FormattedMessage,\n FormattedNumber,\n FormattedPlural,\n FormattedRelativeTime,\n FormattedTime,\n getLocale,\n getLocalizedLanguageName,\n getMessages,\n getPrimaryLanguageSubtag,\n getSupportedLanguageList,\n handleRtl,\n injectIntl,\n IntlProvider,\n intlShape,\n isRtl,\n LOCALE_CHANGED,\n LOCALE_TOPIC,\n mergeMessages,\n updateLocale,\n useIntl\n} from './i18n';\n\nexport {\n auth,\n getBasename,\n initError,\n initialize\n} from './initialize';\n\nexport {\n configureLogging,\n getLoggingService,\n logError,\n logInfo,\n MockLoggingService,\n NewRelicLoggingService,\n resetLoggingService\n} from './logging';\n\nexport {\n CurrentAppContext,\n CurrentAppProvider,\n SiteContext,\n SiteProvider,\n AuthenticatedPageRoute,\n Divider,\n ErrorBoundary,\n ErrorPage,\n LoginRedirect,\n PageWrap,\n useSiteEvent,\n useAuthenticatedUser,\n useSiteConfig,\n useAppConfig\n} from './react';\n\nexport {\n authenticatedLoader,\n getUrlByRouteRole,\n isRoleRouteObject\n} from './routing';\n\nexport {\n clearAllSubscriptions,\n publish,\n subscribe,\n unsubscribe\n} from './subscriptions';\n\nexport {\n initializeMockApp,\n mockMessages\n} from './testing';\n\nexport {\n camelCaseObject,\n convertKeyNames,\n getQueryParameters,\n isValidVariableName,\n modifyObjectKeys,\n snakeCaseObject\n} from './utils';\n\nexport * from './slots';\n"]}
|
|
@@ -158,11 +158,14 @@ function runtimeConfig() {
|
|
|
158
158
|
runtimeConfigUrl.searchParams.set('timestamp', Date.now());
|
|
159
159
|
}
|
|
160
160
|
const { data } = yield apiService.get(runtimeConfigUrl.toString(), apiConfig);
|
|
161
|
+
if (!data || typeof data !== 'object' || Array.isArray(data)) {
|
|
162
|
+
throw new TypeError('Runtime config must be a valid JSON object.');
|
|
163
|
+
}
|
|
161
164
|
mergeSiteConfig(data, { limitAppMergeToConfig: true });
|
|
162
165
|
}
|
|
163
166
|
}
|
|
164
167
|
catch (error) {
|
|
165
|
-
console.error('Error with config API', error.message);
|
|
168
|
+
console.error('Error with config API:', error.message);
|
|
166
169
|
}
|
|
167
170
|
});
|
|
168
171
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"initialize.js","sourceRoot":"","sources":["../../runtime/initialize.js"],"names":[],"mappings":"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","sourcesContent":["/**\n * #### Import members from **@openedx/frontend-base**\n *\n * The initialization module provides a function for managing an application's initialization\n * lifecycle. It also provides constants and default handler implementations.\n *\n * ```\n * import {\n * initialize,\n * SITE_INIT_ERROR,\n * SITE_READY,\n * subscribe,\n * SiteProvider,\n * ErrorPage,\n * PageWrap\n * } from '@openedx/frontend-base';\n * import React from 'react';\n * import ReactDOM from 'react-dom';\n * import { Routes, Route } from 'react-router-dom';\n *\n * subscribe(SITE_READY, () => {\n * ReactDOM.render(\n * <SiteProvider>\n * <Header />\n * <main>\n * <Routes>\n * <Route path=\"/\" element={<PageWrap><PaymentPage /></PageWrap>} />\n * </Routes>\n * </main>\n * <Footer />\n * </SiteProvider>,\n * document.getElementById('root'),\n * );\n * });\n *\n * subscribe(SITE_INIT_ERROR, (error) => {\n * ReactDOM.render(<ErrorPage message={error.message} />, document.getElementById('root'));\n * });\n *\n * initialize({\n * messages: [appMessages],\n * requireAuthenticatedUser: true,\n * hydrateAuthenticatedUser: true,\n * });\n\n```\n * @module Initialization\n */\n\n/*\nThis 'site.config' package is a special 'magic' alias in our webpack configuration in the `config`\nfolder. It points at an `site.config.tsx` file in the root of a site's repository.\n*/\nimport siteConfig from 'site.config';\nimport {\n configureAnalytics,\n identifyAnonymousUser,\n identifyAuthenticatedUser,\n SegmentAnalyticsService,\n} from './analytics';\nimport {\n AxiosJwtAuthService,\n configureAuth,\n ensureAuthenticatedUser,\n fetchAuthenticatedUser,\n getAuthenticatedHttpClient,\n getAuthenticatedUser,\n hydrateAuthenticatedUser,\n} from './auth';\nimport configureCache from './auth/LocalForageCache';\nimport {\n getSiteConfig, mergeSiteConfig,\n} from './config';\nimport {\n SITE_ANALYTICS_INITIALIZED,\n SITE_AUTH_INITIALIZED,\n SITE_CONFIG_INITIALIZED,\n SITE_I18N_INITIALIZED,\n SITE_INIT_ERROR,\n SITE_LOGGING_INITIALIZED,\n SITE_PUBSUB_INITIALIZED,\n SITE_READY,\n} from './constants';\nimport { configureI18n } from './i18n';\nimport {\n configureLogging,\n getLoggingService,\n logError,\n NewRelicLoggingService,\n} from './logging';\nimport { GoogleAnalyticsLoader } from './scripts';\nimport { publish } from './subscriptions';\nimport { EnvironmentTypes } from '../types';\n\n/**\n * If set in configuration, a basename will be prepended to all relative routes under BrowserRouter.\n *\n * Unlike webpack's publicPath, the basename cannot be auto-discovered, so when publicPath is set\n * (or when it's set to 'auto' and the site is being served from a path other than '/') this\n * needs to be configured.\n */\nexport const getBasename = () => getSiteConfig().basename;\n\n/**\n * The default handler for the initialization lifecycle's `initError` phase. Logs the error to the\n * LoggingService using `logError`\n *\n * @see {@link module:frontend-base~logError}\n * @param {*} error\n */\nexport async function initError(error) {\n logError(error);\n}\n\n/**\n * The default handler for the initialization lifecycle's `auth` phase.\n *\n * The handler has several responsibilities:\n * - Determining the user's authentication state (authenticated or anonymous)\n * - Optionally redirecting to login if the application requires an authenticated user.\n * - Optionally loading additional user information via the application's user account data\n * endpoint.\n *\n * @param {boolean} requireUser Whether or not we should redirect to login if a user is not\n * authenticated.\n * @param {boolean} hydrateUser Whether or not we should fetch additional user account data.\n */\nexport async function auth(requireUser, hydrateUser) {\n if (requireUser) {\n await ensureAuthenticatedUser(globalThis.location.href);\n } else {\n await fetchAuthenticatedUser();\n }\n\n if (hydrateUser && getAuthenticatedUser() !== null) {\n // We intentionally do not await the promise returned by hydrateAuthenticatedUser. All the\n // critical data is returned as part of fetch/ensureAuthenticatedUser above, and anything else\n // is a nice-to-have for application code.\n hydrateAuthenticatedUser();\n }\n}\n\n/**\n * Set or overrides configuration via an site.config.tsx file in the consuming application.\n * This site.config.tsx is loaded at runtime and must export one of two things:\n *\n * - An object which will be merged into the application config via `mergeSiteConfig`.\n * - A function which returns an object which will be merged into the application config via\n * `mergeSiteConfig`. This function can return a promise.\n */\nasync function fileConfig() {\n let config = {};\n if (typeof siteConfig === 'function') {\n config = await siteConfig();\n } else {\n config = siteConfig;\n }\n\n mergeSiteConfig(config);\n}\n\n/*\n * Set or overrides configuration through an API.\n * This method allows runtime configuration.\n * Set a basic configuration when an error happen and allow initError and display the ErrorPage.\n */\nasync function runtimeConfig() {\n try {\n const { runtimeConfigJsonUrl, environment } = getSiteConfig();\n\n if (runtimeConfigJsonUrl) {\n const apiConfig = { headers: { accept: 'application/json' } };\n const apiService = await configureCache();\n\n const runtimeConfigUrl = new URL(runtimeConfigJsonUrl);\n\n // In development mode, add a timestamp as a cache buster\n // to support live-editing runtime config JSON\n if (environment === EnvironmentTypes.DEVELOPMENT) {\n runtimeConfigUrl.searchParams.set('timestamp', Date.now());\n }\n\n const { data } = await apiService.get(runtimeConfigUrl.toString(), apiConfig);\n mergeSiteConfig(data, { limitAppMergeToConfig: true });\n }\n } catch (error) {\n console.error('Error with config API', error.message);\n }\n}\n\nexport function loadExternalScripts(externalScripts, data) {\n externalScripts.forEach(ExternalScript => {\n const script = new ExternalScript(data);\n script.loadScript();\n });\n}\n\n/**\n * The default handler for the initialization lifecycle's `analytics` phase.\n *\n * The handler is responsible for identifying authenticated and anonymous users with the analytics\n * service. This is a pre-requisite for sending analytics events, thus, we do it during the\n * initialization sequence so that analytics is ready once the application's UI code starts to load.\n *\n */\nexport async function analytics() {\n const authenticatedUser = getAuthenticatedUser();\n if (authenticatedUser?.userId) {\n identifyAuthenticatedUser(authenticatedUser.userId);\n } else {\n await identifyAnonymousUser();\n }\n}\n\nfunction applyOverrideHandlers(overrides) {\n const noOp = async () => { };\n return {\n pubSub: noOp,\n config: noOp,\n logging: noOp,\n auth,\n analytics,\n i18n: noOp,\n ready: noOp,\n initError,\n ...overrides, // This will override any same-keyed handlers from above.\n };\n}\n\n/**\n * Invokes the application initialization sequence.\n *\n * The sequence proceeds through a number of lifecycle phases, during which pertinent services are\n * configured.\n *\n * Using the `handlers` option, lifecycle phase handlers can be overridden to perform custom\n * functionality. Note that while these override handlers _do_ replace the default handler\n * functionality for analytics, auth, and initError (the other phases have no default\n * functionality), they do _not_ override the configuration of the actual services that those\n * handlers leverage.\n *\n * Some services can be overridden via the loggingService and analyticsService options. The other\n * services (auth and i18n) cannot currently be overridden.\n *\n * The following lifecycle phases exist:\n *\n * - pubSub: A no-op by default.\n * - config: A no-op by default.\n * - logging: A no-op by default.\n * - auth: Uses the 'auth' handler defined above.\n * - analytics: Uses the 'analytics' handler defined above.\n * - i18n: A no-op by default.\n * - ready: A no-op by default.\n * - initError: Uses the 'initError' handler defined above.\n *\n * @param {Object} [options]\n * @param {*} [options.loggingService=NewRelicLoggingService] The `LoggingService` implementation\n * to use.\n * @param {*} [options.analyticsService=SegmentAnalyticsService] The `AnalyticsService`\n * implementation to use.\n * @param {*} [options.authMiddleware=[]] An array of middleware to apply to http clients in the auth service.\n * @param {*} [options.externalScripts=[GoogleAnalyticsLoader]] An array of externalScripts.\n * By default added GoogleAnalyticsLoader.\n * @param {*} [options.requireAuthenticatedUser=false] If true, turns on automatic login\n * redirection for unauthenticated users. Defaults to false, meaning that by default the\n * application will allow anonymous/unauthenticated sessions.\n * @param {*} [options.hydrateAuthenticatedUser=false] If true, makes an API call to the user\n * account endpoint (`${App.config.lmsBaseUrl}/api/user/v1/accounts/${username}`) to fetch\n * detailed account information for the authenticated user. This data is merged into the return\n * value of `getAuthenticatedUser`, overriding any duplicate keys that already exist. Defaults to\n * false, meaning that no additional account information will be loaded.\n * @param {*} [options.messages] A i18n-compatible messages object, or an array of such objects. If\n * an array is provided, duplicate keys are resolved with the last-one-in winning.\n * @param {*} [options.handlers={}] An optional object of handlers which can be used to replace the\n * default behavior of any part of the startup sequence. It can also be used to add additional\n * initialization behavior before or after the rest of the sequence.\n */\nexport async function initialize({\n loggingService = NewRelicLoggingService,\n analyticsService = SegmentAnalyticsService,\n authService = AxiosJwtAuthService,\n authMiddleware = [],\n externalScripts = [GoogleAnalyticsLoader],\n requireAuthenticatedUser: requireUser = false,\n hydrateAuthenticatedUser: hydrateUser = false,\n messages,\n handlers: overrideHandlers = {},\n}) {\n const handlers = applyOverrideHandlers(overrideHandlers);\n try {\n // Pub/Sub\n await handlers.pubSub();\n publish(SITE_PUBSUB_INITIALIZED);\n\n // Configuration\n await fileConfig();\n await handlers.config();\n await runtimeConfig();\n publish(SITE_CONFIG_INITIALIZED);\n\n loadExternalScripts(externalScripts, {\n config: getSiteConfig(),\n });\n\n // This allows us to replace the implementations of the logging, analytics, and auth services\n // based on keys in the SiteConfig. The JavaScript File Configuration method is the only\n // one capable of supplying an alternate implementation since it can import other modules.\n // If a service wasn't supplied we fall back to the default parameters on the initialize\n // function signature.\n const loggingServiceImpl = getSiteConfig().loggingService ?? loggingService;\n const analyticsServiceImpl = getSiteConfig().analyticsService ?? analyticsService;\n const authServiceImpl = getSiteConfig().authService ?? authService;\n\n // Logging\n configureLogging(loggingServiceImpl, {\n config: getSiteConfig(),\n });\n await handlers.logging();\n publish(SITE_LOGGING_INITIALIZED);\n\n // Internationalization\n configureI18n({\n messages,\n });\n await handlers.i18n();\n publish(SITE_I18N_INITIALIZED);\n\n // Authentication\n configureAuth(authServiceImpl, {\n loggingService: getLoggingService(),\n config: getSiteConfig(),\n middleware: authMiddleware,\n });\n\n await handlers.auth(requireUser, hydrateUser);\n publish(SITE_AUTH_INITIALIZED);\n\n // Analytics\n configureAnalytics(analyticsServiceImpl, {\n config: getSiteConfig(),\n loggingService: getLoggingService(),\n httpClient: getAuthenticatedHttpClient(),\n });\n await handlers.analytics();\n publish(SITE_ANALYTICS_INITIALIZED);\n\n // Application Ready\n await handlers.ready();\n publish(SITE_READY);\n } catch (error) {\n if (!error.isRedirecting) {\n // Initialization Error\n await handlers.initError(error);\n publish(SITE_INIT_ERROR, error);\n }\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"initialize.js","sourceRoot":"","sources":["../../runtime/initialize.js"],"names":[],"mappings":"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","sourcesContent":["/**\n * #### Import members from **@openedx/frontend-base**\n *\n * The initialization module provides a function for managing an application's initialization\n * lifecycle. It also provides constants and default handler implementations.\n *\n * ```\n * import {\n * initialize,\n * SITE_INIT_ERROR,\n * SITE_READY,\n * subscribe,\n * SiteProvider,\n * ErrorPage,\n * PageWrap\n * } from '@openedx/frontend-base';\n * import React from 'react';\n * import ReactDOM from 'react-dom';\n * import { Routes, Route } from 'react-router-dom';\n *\n * subscribe(SITE_READY, () => {\n * ReactDOM.render(\n * <SiteProvider>\n * <Header />\n * <main>\n * <Routes>\n * <Route path=\"/\" element={<PageWrap><PaymentPage /></PageWrap>} />\n * </Routes>\n * </main>\n * <Footer />\n * </SiteProvider>,\n * document.getElementById('root'),\n * );\n * });\n *\n * subscribe(SITE_INIT_ERROR, (error) => {\n * ReactDOM.render(<ErrorPage message={error.message} />, document.getElementById('root'));\n * });\n *\n * initialize({\n * messages: [appMessages],\n * requireAuthenticatedUser: true,\n * hydrateAuthenticatedUser: true,\n * });\n\n```\n * @module Initialization\n */\n\n/*\nThis 'site.config' package is a special 'magic' alias in our webpack configuration in the `config`\nfolder. It points at an `site.config.tsx` file in the root of a site's repository.\n*/\nimport siteConfig from 'site.config';\nimport {\n configureAnalytics,\n identifyAnonymousUser,\n identifyAuthenticatedUser,\n SegmentAnalyticsService,\n} from './analytics';\nimport {\n AxiosJwtAuthService,\n configureAuth,\n ensureAuthenticatedUser,\n fetchAuthenticatedUser,\n getAuthenticatedHttpClient,\n getAuthenticatedUser,\n hydrateAuthenticatedUser,\n} from './auth';\nimport configureCache from './auth/LocalForageCache';\nimport {\n getSiteConfig, mergeSiteConfig,\n} from './config';\nimport {\n SITE_ANALYTICS_INITIALIZED,\n SITE_AUTH_INITIALIZED,\n SITE_CONFIG_INITIALIZED,\n SITE_I18N_INITIALIZED,\n SITE_INIT_ERROR,\n SITE_LOGGING_INITIALIZED,\n SITE_PUBSUB_INITIALIZED,\n SITE_READY,\n} from './constants';\nimport { configureI18n } from './i18n';\nimport {\n configureLogging,\n getLoggingService,\n logError,\n NewRelicLoggingService,\n} from './logging';\nimport { GoogleAnalyticsLoader } from './scripts';\nimport { publish } from './subscriptions';\nimport { EnvironmentTypes } from '../types';\n\n/**\n * If set in configuration, a basename will be prepended to all relative routes under BrowserRouter.\n *\n * Unlike webpack's publicPath, the basename cannot be auto-discovered, so when publicPath is set\n * (or when it's set to 'auto' and the site is being served from a path other than '/') this\n * needs to be configured.\n */\nexport const getBasename = () => getSiteConfig().basename;\n\n/**\n * The default handler for the initialization lifecycle's `initError` phase. Logs the error to the\n * LoggingService using `logError`\n *\n * @see {@link module:frontend-base~logError}\n * @param {*} error\n */\nexport async function initError(error) {\n logError(error);\n}\n\n/**\n * The default handler for the initialization lifecycle's `auth` phase.\n *\n * The handler has several responsibilities:\n * - Determining the user's authentication state (authenticated or anonymous)\n * - Optionally redirecting to login if the application requires an authenticated user.\n * - Optionally loading additional user information via the application's user account data\n * endpoint.\n *\n * @param {boolean} requireUser Whether or not we should redirect to login if a user is not\n * authenticated.\n * @param {boolean} hydrateUser Whether or not we should fetch additional user account data.\n */\nexport async function auth(requireUser, hydrateUser) {\n if (requireUser) {\n await ensureAuthenticatedUser(globalThis.location.href);\n } else {\n await fetchAuthenticatedUser();\n }\n\n if (hydrateUser && getAuthenticatedUser() !== null) {\n // We intentionally do not await the promise returned by hydrateAuthenticatedUser. All the\n // critical data is returned as part of fetch/ensureAuthenticatedUser above, and anything else\n // is a nice-to-have for application code.\n hydrateAuthenticatedUser();\n }\n}\n\n/**\n * Set or overrides configuration via an site.config.tsx file in the consuming application.\n * This site.config.tsx is loaded at runtime and must export one of two things:\n *\n * - An object which will be merged into the application config via `mergeSiteConfig`.\n * - A function which returns an object which will be merged into the application config via\n * `mergeSiteConfig`. This function can return a promise.\n */\nasync function fileConfig() {\n let config = {};\n if (typeof siteConfig === 'function') {\n config = await siteConfig();\n } else {\n config = siteConfig;\n }\n\n mergeSiteConfig(config);\n}\n\n/*\n * Set or overrides configuration through an API.\n * This method allows runtime configuration.\n * Set a basic configuration when an error happen and allow initError and display the ErrorPage.\n */\nasync function runtimeConfig() {\n try {\n const { runtimeConfigJsonUrl, environment } = getSiteConfig();\n\n if (runtimeConfigJsonUrl) {\n const apiConfig = { headers: { accept: 'application/json' } };\n const apiService = await configureCache();\n\n const runtimeConfigUrl = new URL(runtimeConfigJsonUrl);\n\n // In development mode, add a timestamp as a cache buster\n // to support live-editing runtime config JSON\n if (environment === EnvironmentTypes.DEVELOPMENT) {\n runtimeConfigUrl.searchParams.set('timestamp', Date.now());\n }\n\n const { data } = await apiService.get(runtimeConfigUrl.toString(), apiConfig);\n if (!data || typeof data !== 'object' || Array.isArray(data)) {\n throw new TypeError('Runtime config must be a valid JSON object.');\n }\n mergeSiteConfig(data, { limitAppMergeToConfig: true });\n }\n } catch (error) {\n console.error('Error with config API:', error.message);\n }\n}\n\nexport function loadExternalScripts(externalScripts, data) {\n externalScripts.forEach(ExternalScript => {\n const script = new ExternalScript(data);\n script.loadScript();\n });\n}\n\n/**\n * The default handler for the initialization lifecycle's `analytics` phase.\n *\n * The handler is responsible for identifying authenticated and anonymous users with the analytics\n * service. This is a pre-requisite for sending analytics events, thus, we do it during the\n * initialization sequence so that analytics is ready once the application's UI code starts to load.\n *\n */\nexport async function analytics() {\n const authenticatedUser = getAuthenticatedUser();\n if (authenticatedUser?.userId) {\n identifyAuthenticatedUser(authenticatedUser.userId);\n } else {\n await identifyAnonymousUser();\n }\n}\n\nfunction applyOverrideHandlers(overrides) {\n const noOp = async () => { };\n return {\n pubSub: noOp,\n config: noOp,\n logging: noOp,\n auth,\n analytics,\n i18n: noOp,\n ready: noOp,\n initError,\n ...overrides, // This will override any same-keyed handlers from above.\n };\n}\n\n/**\n * Invokes the application initialization sequence.\n *\n * The sequence proceeds through a number of lifecycle phases, during which pertinent services are\n * configured.\n *\n * Using the `handlers` option, lifecycle phase handlers can be overridden to perform custom\n * functionality. Note that while these override handlers _do_ replace the default handler\n * functionality for analytics, auth, and initError (the other phases have no default\n * functionality), they do _not_ override the configuration of the actual services that those\n * handlers leverage.\n *\n * Some services can be overridden via the loggingService and analyticsService options. The other\n * services (auth and i18n) cannot currently be overridden.\n *\n * The following lifecycle phases exist:\n *\n * - pubSub: A no-op by default.\n * - config: A no-op by default.\n * - logging: A no-op by default.\n * - auth: Uses the 'auth' handler defined above.\n * - analytics: Uses the 'analytics' handler defined above.\n * - i18n: A no-op by default.\n * - ready: A no-op by default.\n * - initError: Uses the 'initError' handler defined above.\n *\n * @param {Object} [options]\n * @param {*} [options.loggingService=NewRelicLoggingService] The `LoggingService` implementation\n * to use.\n * @param {*} [options.analyticsService=SegmentAnalyticsService] The `AnalyticsService`\n * implementation to use.\n * @param {*} [options.authMiddleware=[]] An array of middleware to apply to http clients in the auth service.\n * @param {*} [options.externalScripts=[GoogleAnalyticsLoader]] An array of externalScripts.\n * By default added GoogleAnalyticsLoader.\n * @param {*} [options.requireAuthenticatedUser=false] If true, turns on automatic login\n * redirection for unauthenticated users. Defaults to false, meaning that by default the\n * application will allow anonymous/unauthenticated sessions.\n * @param {*} [options.hydrateAuthenticatedUser=false] If true, makes an API call to the user\n * account endpoint (`${App.config.lmsBaseUrl}/api/user/v1/accounts/${username}`) to fetch\n * detailed account information for the authenticated user. This data is merged into the return\n * value of `getAuthenticatedUser`, overriding any duplicate keys that already exist. Defaults to\n * false, meaning that no additional account information will be loaded.\n * @param {*} [options.messages] A i18n-compatible messages object, or an array of such objects. If\n * an array is provided, duplicate keys are resolved with the last-one-in winning.\n * @param {*} [options.handlers={}] An optional object of handlers which can be used to replace the\n * default behavior of any part of the startup sequence. It can also be used to add additional\n * initialization behavior before or after the rest of the sequence.\n */\nexport async function initialize({\n loggingService = NewRelicLoggingService,\n analyticsService = SegmentAnalyticsService,\n authService = AxiosJwtAuthService,\n authMiddleware = [],\n externalScripts = [GoogleAnalyticsLoader],\n requireAuthenticatedUser: requireUser = false,\n hydrateAuthenticatedUser: hydrateUser = false,\n messages,\n handlers: overrideHandlers = {},\n}) {\n const handlers = applyOverrideHandlers(overrideHandlers);\n try {\n // Pub/Sub\n await handlers.pubSub();\n publish(SITE_PUBSUB_INITIALIZED);\n\n // Configuration\n await fileConfig();\n await handlers.config();\n await runtimeConfig();\n publish(SITE_CONFIG_INITIALIZED);\n\n loadExternalScripts(externalScripts, {\n config: getSiteConfig(),\n });\n\n // This allows us to replace the implementations of the logging, analytics, and auth services\n // based on keys in the SiteConfig. The JavaScript File Configuration method is the only\n // one capable of supplying an alternate implementation since it can import other modules.\n // If a service wasn't supplied we fall back to the default parameters on the initialize\n // function signature.\n const loggingServiceImpl = getSiteConfig().loggingService ?? loggingService;\n const analyticsServiceImpl = getSiteConfig().analyticsService ?? analyticsService;\n const authServiceImpl = getSiteConfig().authService ?? authService;\n\n // Logging\n configureLogging(loggingServiceImpl, {\n config: getSiteConfig(),\n });\n await handlers.logging();\n publish(SITE_LOGGING_INITIALIZED);\n\n // Internationalization\n configureI18n({\n messages,\n });\n await handlers.i18n();\n publish(SITE_I18N_INITIALIZED);\n\n // Authentication\n configureAuth(authServiceImpl, {\n loggingService: getLoggingService(),\n config: getSiteConfig(),\n middleware: authMiddleware,\n });\n\n await handlers.auth(requireUser, hydrateUser);\n publish(SITE_AUTH_INITIALIZED);\n\n // Analytics\n configureAnalytics(analyticsServiceImpl, {\n config: getSiteConfig(),\n loggingService: getLoggingService(),\n httpClient: getAuthenticatedHttpClient(),\n });\n await handlers.analytics();\n publish(SITE_ANALYTICS_INITIALIZED);\n\n // Application Ready\n await handlers.ready();\n publish(SITE_READY);\n } catch (error) {\n if (!error.isRedirecting) {\n // Initialization Error\n await handlers.initError(error);\n publish(SITE_INIT_ERROR, error);\n }\n }\n}\n"]}
|
|
@@ -4,7 +4,6 @@ export let moduleNameMapper: {
|
|
|
4
4
|
'\\.(jpg|jpeg|png|gif|eot|otf|webp|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$': string;
|
|
5
5
|
'\\.(css|scss)$': string;
|
|
6
6
|
'site.config': string;
|
|
7
|
-
'^@src/(.*)$': string;
|
|
8
7
|
};
|
|
9
8
|
export let testEnvironment: string;
|
|
10
9
|
export namespace testEnvironmentOptions {
|
|
@@ -8,7 +8,6 @@ module.exports = {
|
|
|
8
8
|
'\\.(jpg|jpeg|png|gif|eot|otf|webp|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$': '<rootDir/__mocks__/file.js',
|
|
9
9
|
'\\.(css|scss)$': require.resolve('identity-obj-proxy'),
|
|
10
10
|
'site.config': '<rootDir>/site.config.test.tsx',
|
|
11
|
-
'^@src/(.*)$': '<rootDir>/src/$1',
|
|
12
11
|
},
|
|
13
12
|
testEnvironment: 'jsdom',
|
|
14
13
|
testEnvironmentOptions: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"jest.config.js","sourceRoot":"","sources":["../../runtime/jest.config.js"],"names":[],"mappings":";AAAA,MAAM,CAAC,OAAO,GAAG;IACf,kBAAkB,EAAE;QAClB,wBAAwB;KACzB;IACD,gBAAgB,EAAE;QAChB,SAAS,EAAE,4BAA4B;QACvC,iFAAiF,EAAE,4BAA4B;QAC/G,gBAAgB,EAAE,OAAO,CAAC,OAAO,CAAC,oBAAoB,CAAC;QACvD,aAAa,EAAE,gCAAgC;
|
|
1
|
+
{"version":3,"file":"jest.config.js","sourceRoot":"","sources":["../../runtime/jest.config.js"],"names":[],"mappings":";AAAA,MAAM,CAAC,OAAO,GAAG;IACf,kBAAkB,EAAE;QAClB,wBAAwB;KACzB;IACD,gBAAgB,EAAE;QAChB,SAAS,EAAE,4BAA4B;QACvC,iFAAiF,EAAE,4BAA4B;QAC/G,gBAAgB,EAAE,OAAO,CAAC,OAAO,CAAC,oBAAoB,CAAC;QACvD,aAAa,EAAE,gCAAgC;KAChD;IACD,eAAe,EAAE,OAAO;IACxB,sBAAsB,EAAE;QACtB,GAAG,EAAE,mBAAmB;KACzB;IACD,mBAAmB,EAAE;QACnB,gCAAgC;KACjC;IACD,0BAA0B,EAAE;QAC1B,wBAAwB;KACzB;IACD,uBAAuB,EAAE;QACvB,oCAAoC;KACrC;IACD,wBAAwB,EAAE;QACxB,QAAQ;KACT;IACD,sBAAsB,EAAE;QACtB,uBAAuB;QACvB,gBAAgB;QAChB,QAAQ;KACT;CACF,CAAC","sourcesContent":["module.exports = {\n setupFilesAfterEnv: [\n '<rootDir>/setupTest.js',\n ],\n moduleNameMapper: {\n '\\\\.svg$': '<rootDir>/__mocks__/svg.js',\n '\\\\.(jpg|jpeg|png|gif|eot|otf|webp|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$': '<rootDir/__mocks__/file.js',\n '\\\\.(css|scss)$': require.resolve('identity-obj-proxy'),\n 'site.config': '<rootDir>/site.config.test.tsx',\n },\n testEnvironment: 'jsdom',\n testEnvironmentOptions: {\n url: 'http://localhost/',\n },\n collectCoverageFrom: [\n '<rootDir>/**/*.{js,jsx,ts,tsx}',\n ],\n coveragePathIgnorePatterns: [\n '<rootDir>/setupTest.js',\n ],\n transformIgnorePatterns: [\n '/node_modules/(?!(@openedx|@edx)/)',\n ],\n modulePathIgnorePatterns: [\n '/dist/',\n ],\n testPathIgnorePatterns: [\n '/site.config.test.tsx',\n '/node_modules/',\n '/dist/',\n ],\n};\n"]}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
+
* @deprecated Use authenticatedLoader instead.
|
|
3
|
+
*
|
|
2
4
|
* A react-router route that redirects to the login page when the route becomes active and the user
|
|
3
5
|
* is not authenticated. If the application has been initialized with `requireAuthenticatedUser`
|
|
4
6
|
* false, an authenticatedPageRoute can be used to protect a subset of the application's routes,
|
|
@@ -4,6 +4,8 @@ import { getLoginRedirectUrl } from '../auth';
|
|
|
4
4
|
import PageWrap from './PageWrap';
|
|
5
5
|
import { useAuthenticatedUser } from './hooks';
|
|
6
6
|
/**
|
|
7
|
+
* @deprecated Use authenticatedLoader instead.
|
|
8
|
+
*
|
|
7
9
|
* A react-router route that redirects to the login page when the route becomes active and the user
|
|
8
10
|
* is not authenticated. If the application has been initialized with `requireAuthenticatedUser`
|
|
9
11
|
* false, an authenticatedPageRoute can be used to protect a subset of the application's routes,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AuthenticatedPageRoute.js","sourceRoot":"","sources":["../../../runtime/react/AuthenticatedPageRoute.jsx"],"names":[],"mappings":";AAAA,OAAO,SAAS,MAAM,YAAY,CAAC;AAEnC,OAAO,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAC9C,OAAO,QAAQ,MAAM,YAAY,CAAC;AAClC,OAAO,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAE/C
|
|
1
|
+
{"version":3,"file":"AuthenticatedPageRoute.js","sourceRoot":"","sources":["../../../runtime/react/AuthenticatedPageRoute.jsx"],"names":[],"mappings":";AAAA,OAAO,SAAS,MAAM,YAAY,CAAC;AAEnC,OAAO,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAC9C,OAAO,QAAQ,MAAM,YAAY,CAAC;AAClC,OAAO,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAE/C;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,CAAC,OAAO,UAAU,sBAAsB,CAAC,EAAE,WAAW,GAAG,IAAI,EAAE,QAAQ,EAAE;IAC7E,MAAM,iBAAiB,GAAG,oBAAoB,EAAE,CAAC;IACjD,IAAI,iBAAiB,KAAK,IAAI,EAAE,CAAC;QAC/B,MAAM,WAAW,GAAG,WAAW,IAAI,mBAAmB,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QAC7E,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;QAEpC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,CACL,KAAC,QAAQ,cACN,QAAQ,GACA,CACZ,CAAC;AACJ,CAAC;AAED,sBAAsB,CAAC,SAAS,GAAG;IACjC,WAAW,EAAE,SAAS,CAAC,MAAM;IAC7B,QAAQ,EAAE,SAAS,CAAC,IAAI,CAAC,UAAU;CACpC,CAAC","sourcesContent":["import PropTypes from 'prop-types';\n\nimport { getLoginRedirectUrl } from '../auth';\nimport PageWrap from './PageWrap';\nimport { useAuthenticatedUser } from './hooks';\n\n/**\n * @deprecated Use authenticatedLoader instead.\n * \n * A react-router route that redirects to the login page when the route becomes active and the user\n * is not authenticated. If the application has been initialized with `requireAuthenticatedUser`\n * false, an authenticatedPageRoute can be used to protect a subset of the application's routes,\n * rather than the entire application.\n *\n * It can optionally accept an override URL to redirect to instead of the login page.\n *\n * Like a `PageWrap`, also calls `sendPageEvent` when the route becomes active.\n *\n * @see PageWrap\n * @see {@link module:frontend-base~sendPageEvent}\n * @memberof module:React\n * @param {Object} props\n * @param {string} props.redirectUrl The URL anonymous users should be redirected to, rather than\n * viewing the route's contents.\n */\nexport default function AuthenticatedPageRoute({ redirectUrl = null, children }) {\n const authenticatedUser = useAuthenticatedUser();\n if (authenticatedUser === null) {\n const destination = redirectUrl || getLoginRedirectUrl(global.location.href);\n global.location.assign(destination);\n\n return null;\n }\n\n return (\n <PageWrap>\n {children}\n </PageWrap>\n );\n}\n\nAuthenticatedPageRoute.propTypes = {\n redirectUrl: PropTypes.string,\n children: PropTypes.node.isRequired,\n};\n"]}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import React, { useState } from 'react';
|
|
3
|
+
import { Container, Row, Col, Hyperlink, } from '@openedx/paragon';
|
|
4
|
+
import { useSiteEvent } from './hooks';
|
|
5
|
+
import { FormattedMessage, IntlProvider, getMessages, getLocale, LOCALE_CHANGED, } from '../i18n';
|
|
6
|
+
function NotFoundPage() {
|
|
7
|
+
const [locale, setLocale] = useState(getLocale());
|
|
8
|
+
useSiteEvent(LOCALE_CHANGED, () => {
|
|
9
|
+
setLocale(getLocale());
|
|
10
|
+
});
|
|
11
|
+
return (_jsx(IntlProvider, { locale: locale, messages: getMessages(), children: _jsx(Container, { fluid: true, className: "py-5 justify-content-center align-items-start text-center", children: _jsx(Row, { children: _jsxs(Col, { children: [_jsx("p", { className: "h2 mb-3", children: _jsx(FormattedMessage, { id: "not.found.page.heading", defaultMessage: "404", description: "heading for page not found" }) }), _jsx("p", { className: "text-muted", children: _jsx(FormattedMessage, { id: "not.found.page.message", defaultMessage: "The page you're looking for could not be found.", description: "message displayed when a page is not found" }) }), _jsx(Hyperlink, { destination: "/", children: _jsx(FormattedMessage, { id: "not.found.page.link.text", defaultMessage: "Go to the homepage", description: "link text to navigate to the homepage from a 404 page" }) })] }) }) }) }));
|
|
12
|
+
}
|
|
13
|
+
export default NotFoundPage;
|
|
14
|
+
//# sourceMappingURL=NotFoundPage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NotFoundPage.js","sourceRoot":"","sources":["../../../runtime/react/NotFoundPage.jsx"],"names":[],"mappings":";AAAA,OAAO,KAAK,EAAE,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACxC,OAAO,EACL,SAAS,EAAE,GAAG,EAAE,GAAG,EAAE,SAAS,GAC/B,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EACL,gBAAgB,EAChB,YAAY,EACZ,WAAW,EACX,SAAS,EACT,cAAc,GACf,MAAM,SAAS,CAAC;AAGjB,SAAS,YAAY;IACnB,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAAC,SAAS,EAAE,CAAC,CAAC;IAElD,YAAY,CAAC,cAAc,EAAE,GAAG,EAAE;QAChC,SAAS,CAAC,SAAS,EAAE,CAAC,CAAC;IACzB,CAAC,CAAC,CAAC;IAEH,OAAO,CACL,KAAC,YAAY,IAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,WAAW,EAAE,YACnD,KAAC,SAAS,IAAC,KAAK,QAAC,SAAS,EAAC,2DAA2D,YACpF,KAAC,GAAG,cACF,MAAC,GAAG,eACF,YAAG,SAAS,EAAC,SAAS,YACpB,KAAC,gBAAgB,IACf,EAAE,EAAC,wBAAwB,EAC3B,cAAc,EAAC,KAAK,EACpB,WAAW,EAAC,4BAA4B,GACxC,GACA,EACJ,YAAG,SAAS,EAAC,YAAY,YACvB,KAAC,gBAAgB,IACf,EAAE,EAAC,wBAAwB,EAC3B,cAAc,EAAC,iDAAiD,EAChE,WAAW,EAAC,4CAA4C,GACxD,GACA,EACJ,KAAC,SAAS,IAAC,WAAW,EAAC,GAAG,YACxB,KAAC,gBAAgB,IACf,EAAE,EAAC,0BAA0B,EAC7B,cAAc,EAAC,oBAAoB,EACnC,WAAW,EAAC,uDAAuD,GACnE,GACQ,IACR,GACF,GACI,GACC,CAChB,CAAC;AACJ,CAAC;AAED,eAAe,YAAY,CAAC","sourcesContent":["import React, { useState } from 'react';\nimport {\n Container, Row, Col, Hyperlink,\n} from '@openedx/paragon';\n\nimport { useSiteEvent } from './hooks';\nimport {\n FormattedMessage,\n IntlProvider,\n getMessages,\n getLocale,\n LOCALE_CHANGED,\n} from '../i18n';\n\n\nfunction NotFoundPage() {\n const [locale, setLocale] = useState(getLocale());\n\n useSiteEvent(LOCALE_CHANGED, () => {\n setLocale(getLocale());\n });\n\n return (\n <IntlProvider locale={locale} messages={getMessages()}>\n <Container fluid className=\"py-5 justify-content-center align-items-start text-center\">\n <Row>\n <Col>\n <p className=\"h2 mb-3\">\n <FormattedMessage\n id=\"not.found.page.heading\"\n defaultMessage=\"404\"\n description=\"heading for page not found\"\n />\n </p>\n <p className=\"text-muted\">\n <FormattedMessage\n id=\"not.found.page.message\"\n defaultMessage=\"The page you're looking for could not be found.\"\n description=\"message displayed when a page is not found\"\n />\n </p>\n <Hyperlink destination=\"/\">\n <FormattedMessage\n id=\"not.found.page.link.text\"\n defaultMessage=\"Go to the homepage\"\n description=\"link text to navigate to the homepage from a 404 page\"\n />\n </Hyperlink>\n </Col>\n </Row>\n </Container>\n </IntlProvider>\n );\n}\n\nexport default NotFoundPage;\n"]}
|
|
@@ -13,6 +13,7 @@ export { default as AuthenticatedPageRoute } from './AuthenticatedPageRoute';
|
|
|
13
13
|
export { default as Divider } from './Divider';
|
|
14
14
|
export { default as ErrorBoundary } from './ErrorBoundary';
|
|
15
15
|
export { default as ErrorPage } from './ErrorPage';
|
|
16
|
+
export { default as NotFoundPage } from './NotFoundPage';
|
|
16
17
|
export { useSiteEvent, useAuthenticatedUser, useSiteConfig, useAppConfig } from './hooks';
|
|
17
18
|
export { default as LoginRedirect } from './LoginRedirect';
|
|
18
19
|
export { default as PageWrap } from './PageWrap';
|
|
@@ -13,6 +13,7 @@ export { default as AuthenticatedPageRoute } from './AuthenticatedPageRoute';
|
|
|
13
13
|
export { default as Divider } from './Divider';
|
|
14
14
|
export { default as ErrorBoundary } from './ErrorBoundary';
|
|
15
15
|
export { default as ErrorPage } from './ErrorPage';
|
|
16
|
+
export { default as NotFoundPage } from './NotFoundPage';
|
|
16
17
|
export { useSiteEvent, useAuthenticatedUser, useSiteConfig, useAppConfig } from './hooks';
|
|
17
18
|
export { default as LoginRedirect } from './LoginRedirect';
|
|
18
19
|
export { default as PageWrap } from './PageWrap';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../runtime/react/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,OAAO,IAAI,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACnE,OAAO,EAAE,OAAO,IAAI,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AACrE,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,eAAe,CAAC;AACvD,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,gBAAgB,CAAC;AACzD,OAAO,EAAE,OAAO,IAAI,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAC7E,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,MAAM,WAAW,CAAC;AAC/C,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAC3D,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,YAAY,EAAE,oBAAoB,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAC1F,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAC3D,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,YAAY,CAAC","sourcesContent":["/**\n * #### Import members from **@openedx/frontend-base** React\n * The React module provides a variety of React components, hooks, and contexts for use in an\n * application.\n *\n * @module React\n */\n\nexport { default as CurrentAppContext } from './CurrentAppContext';\nexport { default as CurrentAppProvider } from './CurrentAppProvider';\nexport { default as SiteContext } from './SiteContext';\nexport { default as SiteProvider } from './SiteProvider';\nexport { default as AuthenticatedPageRoute } from './AuthenticatedPageRoute';\nexport { default as Divider } from './Divider';\nexport { default as ErrorBoundary } from './ErrorBoundary';\nexport { default as ErrorPage } from './ErrorPage';\nexport { useSiteEvent, useAuthenticatedUser, useSiteConfig, useAppConfig } from './hooks';\nexport { default as LoginRedirect } from './LoginRedirect';\nexport { default as PageWrap } from './PageWrap';\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../runtime/react/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,OAAO,IAAI,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACnE,OAAO,EAAE,OAAO,IAAI,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AACrE,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,eAAe,CAAC;AACvD,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,gBAAgB,CAAC;AACzD,OAAO,EAAE,OAAO,IAAI,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAC7E,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,MAAM,WAAW,CAAC;AAC/C,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAC3D,OAAO,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,gBAAgB,CAAC;AACzD,OAAO,EAAE,YAAY,EAAE,oBAAoB,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAC1F,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAC3D,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,YAAY,CAAC","sourcesContent":["/**\n * #### Import members from **@openedx/frontend-base** React\n * The React module provides a variety of React components, hooks, and contexts for use in an\n * application.\n *\n * @module React\n */\n\nexport { default as CurrentAppContext } from './CurrentAppContext';\nexport { default as CurrentAppProvider } from './CurrentAppProvider';\nexport { default as SiteContext } from './SiteContext';\nexport { default as SiteProvider } from './SiteProvider';\nexport { default as AuthenticatedPageRoute } from './AuthenticatedPageRoute';\nexport { default as Divider } from './Divider';\nexport { default as ErrorBoundary } from './ErrorBoundary';\nexport { default as ErrorPage } from './ErrorPage';\nexport { default as NotFoundPage } from './NotFoundPage';\nexport { useSiteEvent, useAuthenticatedUser, useSiteConfig, useAppConfig } from './hooks';\nexport { default as LoginRedirect } from './LoginRedirect';\nexport { default as PageWrap } from './PageWrap';\n"]}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { redirect } from 'react-router';
|
|
2
|
+
import { getAuthenticatedUser, getLoginRedirectUrl } from '../auth';
|
|
3
|
+
import { getUrlByRouteRole } from './utils';
|
|
4
|
+
const loginRole = 'org.openedx.frontend.role.login';
|
|
5
|
+
export default function authenticatedLoader({ request }) {
|
|
6
|
+
const authenticatedUser = getAuthenticatedUser();
|
|
7
|
+
if (authenticatedUser !== null) {
|
|
8
|
+
return null;
|
|
9
|
+
}
|
|
10
|
+
const requestUrl = new URL(request.url);
|
|
11
|
+
const loginUrl = getUrlByRouteRole(loginRole);
|
|
12
|
+
// Internal login route → SPA redirect with a relative ?next so the login
|
|
13
|
+
// page can navigate() back without a full page refresh.
|
|
14
|
+
if (loginUrl === null || loginUrl === void 0 ? void 0 : loginUrl.startsWith('/')) {
|
|
15
|
+
return redirect(`${loginUrl}?next=${encodeURIComponent(requestUrl.pathname)}`);
|
|
16
|
+
}
|
|
17
|
+
// No login role found (or it's defined as an external route, which is not
|
|
18
|
+
// supported). Use loginUrl from siteConfig and the full href for the return
|
|
19
|
+
// path so the login service redirects back to the correct origin after
|
|
20
|
+
// login.
|
|
21
|
+
const fullLoginUrl = getLoginRedirectUrl(requestUrl.href);
|
|
22
|
+
// Return a never-resolving promise so React Router keeps waiting (and does
|
|
23
|
+
// not attempt to render the route) while the browser navigates away.
|
|
24
|
+
global.location.assign(fullLoginUrl);
|
|
25
|
+
return new Promise(() => { });
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=authenticatedLoader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"authenticatedLoader.js","sourceRoot":"","sources":["../../../runtime/routing/authenticatedLoader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsB,QAAQ,EAAE,MAAM,cAAc,CAAC;AAC5D,OAAO,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AACpE,OAAO,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAE5C,MAAM,SAAS,GAAG,iCAAiC,CAAC;AAEpD,MAAM,CAAC,OAAO,UAAU,mBAAmB,CAAC,EAAE,OAAO,EAAsB;IACzE,MAAM,iBAAiB,GAAG,oBAAoB,EAAE,CAAC;IACjD,IAAI,iBAAiB,KAAK,IAAI,EAAE,CAAC;QAC/B,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACxC,MAAM,QAAQ,GAAG,iBAAiB,CAAC,SAAS,CAAC,CAAC;IAE9C,yEAAyE;IACzE,wDAAwD;IACxD,IAAI,QAAQ,aAAR,QAAQ,uBAAR,QAAQ,CAAE,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QAC9B,OAAO,QAAQ,CAAC,GAAG,QAAQ,SAAS,kBAAkB,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;IACjF,CAAC;IAED,0EAA0E;IAC1E,4EAA4E;IAC5E,uEAAuE;IACvE,SAAS;IACT,MAAM,YAAY,GAAG,mBAAmB,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;IAE1D,2EAA2E;IAC3E,qEAAqE;IACrE,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;IACrC,OAAO,IAAI,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;AAChC,CAAC","sourcesContent":["import { LoaderFunctionArgs, redirect } from 'react-router';\nimport { getAuthenticatedUser, getLoginRedirectUrl } from '../auth';\nimport { getUrlByRouteRole } from './utils';\n\nconst loginRole = 'org.openedx.frontend.role.login';\n\nexport default function authenticatedLoader({ request }: LoaderFunctionArgs) {\n const authenticatedUser = getAuthenticatedUser();\n if (authenticatedUser !== null) {\n return null;\n }\n\n const requestUrl = new URL(request.url);\n const loginUrl = getUrlByRouteRole(loginRole);\n\n // Internal login route → SPA redirect with a relative ?next so the login\n // page can navigate() back without a full page refresh.\n if (loginUrl?.startsWith('/')) {\n return redirect(`${loginUrl}?next=${encodeURIComponent(requestUrl.pathname)}`);\n }\n\n // No login role found (or it's defined as an external route, which is not\n // supported). Use loginUrl from siteConfig and the full href for the return\n // path so the login service redirects back to the correct origin after\n // login.\n const fullLoginUrl = getLoginRedirectUrl(requestUrl.href);\n\n // Return a never-resolving promise so React Router keeps waiting (and does\n // not attempt to render the route) while the browser navigates away.\n global.location.assign(fullLoginUrl);\n return new Promise(() => { });\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../runtime/routing/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC","sourcesContent":["export * from './utils';\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../runtime/routing/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AACvE,cAAc,SAAS,CAAC","sourcesContent":["export { default as authenticatedLoader } from './authenticatedLoader';\nexport * from './utils';\n"]}
|
|
@@ -1,14 +1,29 @@
|
|
|
1
1
|
import { getSiteConfig } from '../config';
|
|
2
|
-
|
|
2
|
+
function findRoleInRoutes(routes, role, prefix = '') {
|
|
3
3
|
var _a, _b;
|
|
4
|
+
for (const route of routes) {
|
|
5
|
+
const segment = (_a = route.path) !== null && _a !== void 0 ? _a : '';
|
|
6
|
+
const fullPath = segment.startsWith('/') ? segment : `${prefix}/${segment}`.replace(/\/+/g, '/');
|
|
7
|
+
if (((_b = route.handle) === null || _b === void 0 ? void 0 : _b.role) === role) {
|
|
8
|
+
return fullPath || null;
|
|
9
|
+
}
|
|
10
|
+
if (Array.isArray(route.children)) {
|
|
11
|
+
const found = findRoleInRoutes(route.children, role, fullPath);
|
|
12
|
+
if (found !== null) {
|
|
13
|
+
return found;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
export function getUrlByRouteRole(role) {
|
|
4
20
|
const { apps, externalRoutes } = getSiteConfig();
|
|
5
21
|
if (apps) {
|
|
6
22
|
for (const app of apps) {
|
|
7
23
|
if (Array.isArray(app.routes)) {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
}
|
|
24
|
+
const found = findRoleInRoutes(app.routes, role);
|
|
25
|
+
if (found !== null) {
|
|
26
|
+
return found;
|
|
12
27
|
}
|
|
13
28
|
}
|
|
14
29
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../runtime/routing/utils.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAE1C,
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../runtime/routing/utils.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAE1C,SAAS,gBAAgB,CAAC,MAAqB,EAAE,IAAY,EAAE,MAAM,GAAG,EAAE;;IACxE,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,MAAM,OAAO,GAAG,MAAA,KAAK,CAAC,IAAI,mCAAI,EAAE,CAAC;QACjC,MAAM,QAAQ,GAAG,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,MAAM,IAAI,OAAO,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;QAEjG,IAAI,CAAA,MAAA,KAAK,CAAC,MAAM,0CAAE,IAAI,MAAK,IAAI,EAAE,CAAC;YAChC,OAAO,QAAQ,IAAI,IAAI,CAAC;QAC1B,CAAC;QAED,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC;YAClC,MAAM,KAAK,GAAG,gBAAgB,CAAC,KAAK,CAAC,QAAQ,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC;YAC/D,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;gBACnB,OAAO,KAAK,CAAC;YACf,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,IAAY;IAC5C,MAAM,EAAE,IAAI,EAAE,cAAc,EAAE,GAAG,aAAa,EAAE,CAAC;IAEjD,IAAI,IAAI,EAAE,CAAC;QACT,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;YACvB,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC9B,MAAM,KAAK,GAAG,gBAAgB,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;gBACjD,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;oBACnB,OAAO,KAAK,CAAC;gBACf,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,IAAI,cAAc,EAAE,CAAC;QACnB,KAAK,MAAM,aAAa,IAAI,cAAc,EAAE,CAAC;YAC3C,IAAI,aAAa,CAAC,IAAI,KAAK,IAAI,EAAE,CAAC;gBAChC,OAAO,aAAa,CAAC,GAAG,CAAC;YAC3B,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,KAAkB;IAClD,OAAO,KAAK,CAAC,MAAM,KAAK,SAAS,IAAI,MAAM,IAAI,KAAK,CAAC,MAAM,CAAC;AAC9D,CAAC","sourcesContent":["import { RouteObject } from 'react-router';\n\nimport { RoleRouteObject } from '../../types';\nimport { getSiteConfig } from '../config';\n\nfunction findRoleInRoutes(routes: RouteObject[], role: string, prefix = ''): string | null {\n for (const route of routes) {\n const segment = route.path ?? '';\n const fullPath = segment.startsWith('/') ? segment : `${prefix}/${segment}`.replace(/\\/+/g, '/');\n\n if (route.handle?.role === role) {\n return fullPath || null;\n }\n\n if (Array.isArray(route.children)) {\n const found = findRoleInRoutes(route.children, role, fullPath);\n if (found !== null) {\n return found;\n }\n }\n }\n return null;\n}\n\nexport function getUrlByRouteRole(role: string) {\n const { apps, externalRoutes } = getSiteConfig();\n\n if (apps) {\n for (const app of apps) {\n if (Array.isArray(app.routes)) {\n const found = findRoleInRoutes(app.routes, role);\n if (found !== null) {\n return found;\n }\n }\n }\n }\n\n if (externalRoutes) {\n for (const externalRoute of externalRoutes) {\n if (externalRoute.role === role) {\n return externalRoute.url;\n }\n }\n }\n\n return null;\n}\n\nexport function isRoleRouteObject(match: RouteObject): match is RoleRouteObject {\n return match.handle !== undefined && 'role' in match.handle;\n}\n"]}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { ComponentType, ReactNode } from 'react';
|
|
2
2
|
interface SlotProps {
|
|
3
3
|
id: string;
|
|
4
|
+
idAliases?: string[];
|
|
4
5
|
children?: ReactNode;
|
|
5
6
|
layout?: ComponentType | ReactNode;
|
|
6
7
|
[key: string]: unknown;
|
|
7
8
|
}
|
|
8
|
-
export default function Slot({ id, children, layout, ...props }: SlotProps): import("react/jsx-runtime").JSX.Element;
|
|
9
|
+
export default function Slot({ id, idAliases, children, layout, ...props }: SlotProps): import("react/jsx-runtime").JSX.Element;
|
|
9
10
|
export {};
|
|
@@ -9,13 +9,14 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
9
9
|
}
|
|
10
10
|
return t;
|
|
11
11
|
};
|
|
12
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
12
|
+
import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
|
|
13
13
|
import { createElement, isValidElement } from 'react';
|
|
14
14
|
import DefaultSlotLayout from './layout/DefaultSlotLayout';
|
|
15
15
|
import { useLayoutForSlotId } from './layout/hooks';
|
|
16
16
|
import SlotContext from './SlotContext';
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
import { useSlotContext } from './hooks';
|
|
18
|
+
function SlotRenderer({ layout }) {
|
|
19
|
+
const { id } = useSlotContext();
|
|
19
20
|
let layoutElement = layout;
|
|
20
21
|
const overrideLayout = useLayoutForSlotId(id);
|
|
21
22
|
// Weed out any ReactNode types that aren't actually JSX.
|
|
@@ -25,6 +26,10 @@ export default function Slot(_a) {
|
|
|
25
26
|
if (!isValidElement(layoutElement)) {
|
|
26
27
|
layoutElement = createElement(layoutElement);
|
|
27
28
|
}
|
|
28
|
-
return
|
|
29
|
+
return _jsx(_Fragment, { children: layoutElement });
|
|
30
|
+
}
|
|
31
|
+
export default function Slot(_a) {
|
|
32
|
+
var { id, idAliases, children, layout = DefaultSlotLayout } = _a, props = __rest(_a, ["id", "idAliases", "children", "layout"]);
|
|
33
|
+
return (_jsx(SlotContext.Provider, { value: Object.assign({ id, idAliases, children }, props), children: _jsx(SlotRenderer, { layout: layout }) }));
|
|
29
34
|
}
|
|
30
35
|
//# sourceMappingURL=Slot.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Slot.js","sourceRoot":"","sources":["../../../runtime/slots/Slot.tsx"],"names":[],"mappings":";;;;;;;;;;;;AAAA,OAAO,EAAiB,aAAa,EAAE,cAAc,EAAa,MAAM,OAAO,CAAC;AAChF,OAAO,iBAAiB,MAAM,4BAA4B,CAAC;AAC3D,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,WAAW,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"Slot.js","sourceRoot":"","sources":["../../../runtime/slots/Slot.tsx"],"names":[],"mappings":";;;;;;;;;;;;AAAA,OAAO,EAAiB,aAAa,EAAE,cAAc,EAAa,MAAM,OAAO,CAAC;AAChF,OAAO,iBAAiB,MAAM,4BAA4B,CAAC;AAC3D,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,WAAW,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAUzC,SAAS,YAAY,CAAC,EAAE,MAAM,EAAyC;IACrE,MAAM,EAAE,EAAE,EAAE,GAAG,cAAc,EAAE,CAAC;IAChC,IAAI,aAAa,GAA8B,MAAM,CAAC;IAEtD,MAAM,cAAc,GAAG,kBAAkB,CAAC,EAAE,CAAC,CAAC;IAE9C,yDAAyD;IACzD,IAAI,cAAc,IAAI,cAAc,KAAK,IAAI,IAAI,cAAc,KAAK,SAAS,IAAI,OAAO,cAAc,KAAK,SAAS,EAAE,CAAC;QACrH,aAAa,GAAG,cAAc,CAAC;IACjC,CAAC;IAED,IAAI,CAAC,cAAc,CAAC,aAAa,CAAC,EAAE,CAAC;QACnC,aAAa,GAAG,aAAa,CAAC,aAA8B,CAAC,CAAC;IAChE,CAAC;IAED,OAAO,4BAAG,aAAa,GAAI,CAAC;AAC9B,CAAC;AAED,MAAM,CAAC,OAAO,UAAU,IAAI,CAAC,EAA4E;QAA5E,EAAE,EAAE,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,GAAG,iBAAiB,OAAuB,EAAlB,KAAK,cAA/D,yCAAiE,CAAF;IAC1F,OAAO,CACL,KAAC,WAAW,CAAC,QAAQ,IAAC,KAAK,kBAAI,EAAE,EAAE,SAAS,EAAE,QAAQ,IAAK,KAAK,aAC9D,KAAC,YAAY,IAAC,MAAM,EAAE,MAAM,GAAI,GACX,CACxB,CAAC;AACJ,CAAC","sourcesContent":["import { ComponentType, createElement, isValidElement, ReactNode } from 'react';\nimport DefaultSlotLayout from './layout/DefaultSlotLayout';\nimport { useLayoutForSlotId } from './layout/hooks';\nimport SlotContext from './SlotContext';\nimport { useSlotContext } from './hooks';\n\ninterface SlotProps {\n id: string,\n idAliases?: string[],\n children?: ReactNode,\n layout?: ComponentType | ReactNode,\n [key: string]: unknown,\n}\n\nfunction SlotRenderer({ layout }: { layout: ComponentType | ReactNode }) {\n const { id } = useSlotContext();\n let layoutElement: ComponentType | ReactNode = layout;\n\n const overrideLayout = useLayoutForSlotId(id);\n\n // Weed out any ReactNode types that aren't actually JSX.\n if (overrideLayout && overrideLayout !== null && overrideLayout !== undefined && typeof overrideLayout !== 'boolean') {\n layoutElement = overrideLayout;\n }\n\n if (!isValidElement(layoutElement)) {\n layoutElement = createElement(layoutElement as ComponentType);\n }\n\n return <>{layoutElement}</>;\n}\n\nexport default function Slot({ id, idAliases, children, layout = DefaultSlotLayout, ...props }: SlotProps) {\n return (\n <SlotContext.Provider value={{ id, idAliases, children, ...props }}>\n <SlotRenderer layout={layout} />\n </SlotContext.Provider>\n );\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SlotContext.js","sourceRoot":"","sources":["../../../runtime/slots/SlotContext.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAa,MAAM,OAAO,CAAC;AAEjD,MAAM,WAAW,GAAG,aAAa,
|
|
1
|
+
{"version":3,"file":"SlotContext.js","sourceRoot":"","sources":["../../../runtime/slots/SlotContext.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAa,MAAM,OAAO,CAAC;AAEjD,MAAM,WAAW,GAAG,aAAa,CAAqF;IACpH,EAAE,EAAE,EAAE;IACN,QAAQ,EAAE,IAAI;CACf,CAAC,CAAC;AAEH,eAAe,WAAW,CAAC","sourcesContent":["import { createContext, ReactNode } from 'react';\n\nconst SlotContext = createContext<{ id: string, idAliases?: string[], children?: ReactNode, [key: string]: unknown }>({\n id: '',\n children: null,\n});\n\nexport default SlotContext;\n"]}
|