@openedx/frontend-base 1.0.0-alpha.13 → 1.0.0-alpha.14

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 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 [test-site/tools/autoinstall/README.md](./test-site/tools/autoinstall/README.md) for details.
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 dev:pack
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 has the same tooling as [test-site/tools/autoinstall/](./test-site/tools/autoinstall/)
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
 
@@ -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;QAC/C,aAAa,EAAE,kBAAkB;KAClC;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 '^@src/(.*)$': '<rootDir>/src/$1',\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
+ {"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,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
- export default function Slot(_a) {
18
- var { id, children, layout = DefaultSlotLayout } = _a, props = __rest(_a, ["id", "children", "layout"]);
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 (_jsx(SlotContext.Provider, { value: Object.assign({ id, children }, props), children: layoutElement }));
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;AASxC,MAAM,CAAC,OAAO,UAAU,IAAI,CAAC,EAAiE;QAAjE,EAAE,EAAE,EAAE,QAAQ,EAAE,MAAM,GAAG,iBAAiB,OAAuB,EAAlB,KAAK,cAApD,4BAAsD,CAAF;IAC/E,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,CACL,KAAC,WAAW,CAAC,QAAQ,IAAC,KAAK,kBAAI,EAAE,EAAE,QAAQ,IAAK,KAAK,aAClD,aAAa,GACO,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';\n\ninterface SlotProps {\n id: string,\n children?: ReactNode,\n layout?: ComponentType | ReactNode,\n [key: string]: unknown,\n}\n\nexport default function Slot({ id, children, layout = DefaultSlotLayout, ...props }: SlotProps) {\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 (\n <SlotContext.Provider value={{ id, children, ...props }}>\n {layoutElement}\n </SlotContext.Provider>\n );\n}\n"]}
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"]}
@@ -2,6 +2,7 @@ import { ReactNode } from 'react';
2
2
  declare const SlotContext: import("react").Context<{
3
3
  [key: string]: unknown;
4
4
  id: string;
5
+ idAliases?: string[];
5
6
  children?: ReactNode;
6
7
  }>;
7
8
  export default SlotContext;
@@ -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,CAA+D;IAC9F,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, children?: ReactNode, [key: string]: unknown }>({\n id: '',\n children: null,\n});\n\nexport default SlotContext;\n"]}
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"]}
@@ -8,5 +8,6 @@ export declare function useSlotOperations(id: string): SlotOperation[];
8
8
  export declare function useSlotContext(): {
9
9
  [key: string]: unknown;
10
10
  id: string;
11
+ idAliases?: string[];
11
12
  children?: import("react").ReactNode;
12
13
  };
@@ -9,7 +9,7 @@ import { createWidgetAppendOperation } from './widget';
9
9
  * config as it changes.
10
10
  */
11
11
  export function useSlotOperations(id) {
12
- const { children } = useSlotContext();
12
+ const { children, idAliases } = useSlotContext();
13
13
  const location = useLocation();
14
14
  const [operations, setOperations] = useState([]);
15
15
  useEffect(() => {
@@ -17,10 +17,10 @@ export function useSlotOperations(id) {
17
17
  // when [children] props change. This avoids an endless render loop. After all, the whole
18
18
  // point of a slot is to modify its children via slot operations.
19
19
  const defaultOperation = createWidgetAppendOperation('defaultContent', id, children);
20
- setOperations(getSlotOperations(id, defaultOperation));
20
+ setOperations(getSlotOperations([id, ...(idAliases !== null && idAliases !== void 0 ? idAliases : [])], defaultOperation));
21
21
  // We depend on [location] to force re-renders on navigation. This guarantees changes in active
22
22
  // roles (and thus, changes in what conditional widgets are shown) properly.
23
- }, [id, children, location]);
23
+ }, [id, children, idAliases, location]);
24
24
  return operations;
25
25
  }
26
26
  export function useSlotContext() {
@@ -1 +1 @@
1
- {"version":3,"file":"hooks.js","sourceRoot":"","sources":["../../../runtime/slots/hooks.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACxD,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAG/C,OAAO,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,WAAW,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,2BAA2B,EAAE,MAAM,UAAU,CAAC;AAEvD;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAAC,EAAU;IAC1C,MAAM,EAAE,QAAQ,EAAE,GAAG,cAAc,EAAE,CAAC;IACtC,MAAM,QAAQ,GAAG,WAAW,EAAE,CAAC;IAC/B,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,QAAQ,CAAkB,EAAE,CAAC,CAAC;IAElE,SAAS,CAAC,GAAG,EAAE;QACb,4FAA4F;QAC5F,2FAA2F;QAC3F,iEAAiE;QACjE,MAAM,gBAAgB,GAAG,2BAA2B,CAAC,gBAAgB,EAAE,EAAE,EAAE,QAAQ,CAAC,CAAC;QACrF,aAAa,CAAC,iBAAiB,CAAC,EAAE,EAAE,gBAAgB,CAAC,CAAC,CAAC;QAEvD,gGAAgG;QAChG,4EAA4E;IAC9E,CAAC,EAAE,CAAC,EAAE,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC;IAE7B,OAAO,UAAU,CAAC;AACpB,CAAC;AAED,MAAM,UAAU,cAAc;IAC5B,OAAO,UAAU,CAAC,WAAW,CAAC,CAAC;AACjC,CAAC","sourcesContent":["import { useContext, useEffect, useState } from 'react';\nimport { useLocation } from 'react-router-dom';\n\nimport { SlotOperation } from './types';\nimport { getSlotOperations } from './utils';\nimport SlotContext from './SlotContext';\nimport { createWidgetAppendOperation } from './widget';\n\n/**\n * The useSlotOperations hook will trigger re-renders when the slot configuration changes.\n * It is a fundamental hook that is used by many of the others to ensure they're using up-to-date\n * config as it changes.\n */\nexport function useSlotOperations(id: string) {\n const { children } = useSlotContext();\n const location = useLocation();\n const [operations, setOperations] = useState<SlotOperation[]>([]);\n\n useEffect(() => {\n // Setting default content has to happen inside `useEffect()` so that re-renders only happen\n // when [children] props change. This avoids an endless render loop. After all, the whole\n // point of a slot is to modify its children via slot operations.\n const defaultOperation = createWidgetAppendOperation('defaultContent', id, children);\n setOperations(getSlotOperations(id, defaultOperation));\n\n // We depend on [location] to force re-renders on navigation. This guarantees changes in active\n // roles (and thus, changes in what conditional widgets are shown) properly.\n }, [id, children, location]);\n\n return operations;\n}\n\nexport function useSlotContext() {\n return useContext(SlotContext);\n}\n"]}
1
+ {"version":3,"file":"hooks.js","sourceRoot":"","sources":["../../../runtime/slots/hooks.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACxD,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAG/C,OAAO,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,WAAW,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,2BAA2B,EAAE,MAAM,UAAU,CAAC;AAEvD;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAAC,EAAU;IAC1C,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,cAAc,EAAE,CAAC;IACjD,MAAM,QAAQ,GAAG,WAAW,EAAE,CAAC;IAC/B,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,QAAQ,CAAkB,EAAE,CAAC,CAAC;IAElE,SAAS,CAAC,GAAG,EAAE;QACb,4FAA4F;QAC5F,2FAA2F;QAC3F,iEAAiE;QACjE,MAAM,gBAAgB,GAAG,2BAA2B,CAAC,gBAAgB,EAAE,EAAE,EAAE,QAAQ,CAAC,CAAC;QACrF,aAAa,CAAC,iBAAiB,CAAC,CAAC,EAAE,EAAE,GAAG,CAAC,SAAS,aAAT,SAAS,cAAT,SAAS,GAAI,EAAE,CAAC,CAAC,EAAE,gBAAgB,CAAC,CAAC,CAAC;QAE/E,gGAAgG;QAChG,4EAA4E;IAC9E,CAAC,EAAE,CAAC,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC,CAAC;IAExC,OAAO,UAAU,CAAC;AACpB,CAAC;AAED,MAAM,UAAU,cAAc;IAC5B,OAAO,UAAU,CAAC,WAAW,CAAC,CAAC;AACjC,CAAC","sourcesContent":["import { useContext, useEffect, useState } from 'react';\nimport { useLocation } from 'react-router-dom';\n\nimport { SlotOperation } from './types';\nimport { getSlotOperations } from './utils';\nimport SlotContext from './SlotContext';\nimport { createWidgetAppendOperation } from './widget';\n\n/**\n * The useSlotOperations hook will trigger re-renders when the slot configuration changes.\n * It is a fundamental hook that is used by many of the others to ensure they're using up-to-date\n * config as it changes.\n */\nexport function useSlotOperations(id: string) {\n const { children, idAliases } = useSlotContext();\n const location = useLocation();\n const [operations, setOperations] = useState<SlotOperation[]>([]);\n\n useEffect(() => {\n // Setting default content has to happen inside `useEffect()` so that re-renders only happen\n // when [children] props change. This avoids an endless render loop. After all, the whole\n // point of a slot is to modify its children via slot operations.\n const defaultOperation = createWidgetAppendOperation('defaultContent', id, children);\n setOperations(getSlotOperations([id, ...(idAliases ?? [])], defaultOperation));\n\n // We depend on [location] to force re-renders on navigation. This guarantees changes in active\n // roles (and thus, changes in what conditional widgets are shown) properly.\n }, [id, children, idAliases, location]);\n\n return operations;\n}\n\nexport function useSlotContext() {\n return useContext(SlotContext);\n}\n"]}
@@ -1,3 +1,3 @@
1
1
  import { SlotOperation } from './types';
2
- export declare function getSlotOperations(id: string, defaultOperation?: SlotOperation): SlotOperation[];
2
+ export declare function getSlotOperations(ids: string[], defaultOperation?: SlotOperation): SlotOperation[];
3
3
  export declare function isSlotOperationConditionSatisfied(operation: SlotOperation): boolean;
@@ -1,6 +1,6 @@
1
1
  import { getAuthenticatedUser } from '../auth';
2
2
  import { getActiveRoles, getSiteConfig } from '../config';
3
- export function getSlotOperations(id, defaultOperation) {
3
+ export function getSlotOperations(ids, defaultOperation) {
4
4
  const { apps } = getSiteConfig();
5
5
  const ops = [];
6
6
  if (defaultOperation) {
@@ -10,7 +10,7 @@ export function getSlotOperations(id, defaultOperation) {
10
10
  apps.forEach((app) => {
11
11
  if (Array.isArray(app.slots)) {
12
12
  app.slots.forEach((operation) => {
13
- if (operation.slotId === id) {
13
+ if (ids.includes(operation.slotId)) {
14
14
  ops.push(operation);
15
15
  }
16
16
  });
@@ -1 +1 @@
1
- {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../runtime/slots/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAC/C,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAG1D,MAAM,UAAU,iBAAiB,CAAC,EAAU,EAAE,gBAAgC;IAC5E,MAAM,EAAE,IAAI,EAAE,GAAG,aAAa,EAAE,CAAC;IACjC,MAAM,GAAG,GAAoB,EAAE,CAAC;IAEhC,IAAI,gBAAgB,EAAE,CAAC;QACrB,GAAG,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;IAC7B,CAAC;IAED,IAAI,IAAI,EAAE,CAAC;QACT,IAAI,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE;YACnB,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC7B,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,SAAS,EAAE,EAAE;oBAC9B,IAAI,SAAS,CAAC,MAAM,KAAK,EAAE,EAAE,CAAC;wBAC5B,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;oBACtB,CAAC;gBACH,CAAC,CAAC,CAAC;YACL,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC;IAED,OAAO,GAAG,CAAC;AACb,CAAC;AAED,MAAM,UAAU,iCAAiC,CAAC,SAAwB;IACxE,MAAM,EAAE,SAAS,EAAE,GAAG,SAAS,CAAC;IAChC,IAAI,CAAA,SAAS,aAAT,SAAS,uBAAT,SAAS,CAAE,aAAa,MAAK,SAAS,EAAE,CAAC;QAC3C,MAAM,eAAe,GAAG,oBAAoB,EAAE,KAAK,IAAI,CAAC;QACxD,0DAA0D;QAC1D,IAAI,SAAS,CAAC,aAAa,KAAK,eAAe,EAAE,CAAC;YAChD,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IAED,IAAI,CAAA,SAAS,aAAT,SAAS,uBAAT,SAAS,CAAE,MAAM,MAAK,SAAS,IAAI,CAAA,SAAS,aAAT,SAAS,uBAAT,SAAS,CAAE,QAAQ,MAAK,SAAS,EAAE,CAAC;QACzE,MAAM,WAAW,GAAa,cAAc,EAAE,CAAC;QAE/C,IAAI,CAAA,SAAS,aAAT,SAAS,uBAAT,SAAS,CAAE,MAAM,MAAK,SAAS,EAAE,CAAC;YACpC,IAAI,wBAAwB,GAAG,KAAK,CAAC;YACrC,KAAK,MAAM,aAAa,IAAI,SAAS,CAAC,MAAM,EAAE,CAAC;gBAC7C,IAAI,WAAW,CAAC,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC;oBACxC,wBAAwB,GAAG,IAAI,CAAC;oBAChC,MAAM;gBACR,CAAC;YACH,CAAC;YAED,oFAAoF;YACpF,IAAI,CAAC,wBAAwB,EAAE,CAAC;gBAC9B,OAAO,KAAK,CAAC;YACf,CAAC;QACH,CAAC;QAED,IAAI,CAAA,SAAS,aAAT,SAAS,uBAAT,SAAS,CAAE,QAAQ,MAAK,SAAS,EAAE,CAAC;YACtC,IAAI,0BAA0B,GAAG,KAAK,CAAC;YACvC,KAAK,MAAM,aAAa,IAAI,SAAS,CAAC,QAAQ,EAAE,CAAC;gBAC/C,IAAI,WAAW,CAAC,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC;oBACxC,0BAA0B,GAAG,IAAI,CAAC;oBAClC,MAAM;gBACR,CAAC;YACH,CAAC;YAED,sFAAsF;YACtF,IAAI,0BAA0B,EAAE,CAAC;gBAC/B,OAAO,KAAK,CAAC;YACf,CAAC;QACH,CAAC;IACH,CAAC;IAED,IAAI,CAAA,SAAS,aAAT,SAAS,uBAAT,SAAS,CAAE,QAAQ,MAAK,SAAS,IAAI,SAAS,CAAC,QAAQ,EAAE,KAAK,KAAK,EAAE,CAAC;QACxE,OAAO,KAAK,CAAC;IACf,CAAC;IAED,6CAA6C;IAC7C,OAAO,IAAI,CAAC;AACd,CAAC","sourcesContent":["import { getAuthenticatedUser } from '../auth';\nimport { getActiveRoles, getSiteConfig } from '../config';\nimport { SlotOperation } from './types';\n\nexport function getSlotOperations(id: string, defaultOperation?: SlotOperation) {\n const { apps } = getSiteConfig();\n const ops: SlotOperation[] = [];\n\n if (defaultOperation) {\n ops.push(defaultOperation);\n }\n\n if (apps) {\n apps.forEach((app) => {\n if (Array.isArray(app.slots)) {\n app.slots.forEach((operation) => {\n if (operation.slotId === id) {\n ops.push(operation);\n }\n });\n }\n });\n }\n\n return ops;\n}\n\nexport function isSlotOperationConditionSatisfied(operation: SlotOperation) {\n const { condition } = operation;\n if (condition?.authenticated !== undefined) {\n const isAuthenticated = getAuthenticatedUser() !== null;\n // If we failed the authenticated condition, return false.\n if (condition.authenticated !== isAuthenticated) {\n return false;\n }\n }\n\n if (condition?.active !== undefined || condition?.inactive !== undefined) {\n const activeRoles: string[] = getActiveRoles();\n\n if (condition?.active !== undefined) {\n let activeConditionRoleFound = false;\n for (const conditionRole of condition.active) {\n if (activeRoles.includes(conditionRole)) {\n activeConditionRoleFound = true;\n break;\n }\n }\n\n // If we couldn't find an active role in our list, then we've failed this condition.\n if (!activeConditionRoleFound) {\n return false;\n }\n }\n\n if (condition?.inactive !== undefined) {\n let inactiveConditionRoleFound = false;\n for (const conditionRole of condition.inactive) {\n if (activeRoles.includes(conditionRole)) {\n inactiveConditionRoleFound = true;\n break;\n }\n }\n\n // If we find an active role from our inactive list, then we've failed this condition.\n if (inactiveConditionRoleFound) {\n return false;\n }\n }\n }\n\n if (condition?.callback !== undefined && condition.callback() === false) {\n return false;\n }\n\n // If there was no condition, we return true.\n return true;\n}\n"]}
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../runtime/slots/utils.ts"],"names":[],"mappings":"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","sourcesContent":["import { getAuthenticatedUser } from '../auth';\nimport { getActiveRoles, getSiteConfig } from '../config';\nimport { SlotOperation } from './types';\n\nexport function getSlotOperations(ids: string[], defaultOperation?: SlotOperation) {\n const { apps } = getSiteConfig();\n const ops: SlotOperation[] = [];\n\n if (defaultOperation) {\n ops.push(defaultOperation);\n }\n\n if (apps) {\n apps.forEach((app) => {\n if (Array.isArray(app.slots)) {\n app.slots.forEach((operation) => {\n if (ids.includes(operation.slotId)) {\n ops.push(operation);\n }\n });\n }\n });\n }\n\n return ops;\n}\n\nexport function isSlotOperationConditionSatisfied(operation: SlotOperation) {\n const { condition } = operation;\n if (condition?.authenticated !== undefined) {\n const isAuthenticated = getAuthenticatedUser() !== null;\n // If we failed the authenticated condition, return false.\n if (condition.authenticated !== isAuthenticated) {\n return false;\n }\n }\n\n if (condition?.active !== undefined || condition?.inactive !== undefined) {\n const activeRoles: string[] = getActiveRoles();\n\n if (condition?.active !== undefined) {\n let activeConditionRoleFound = false;\n for (const conditionRole of condition.active) {\n if (activeRoles.includes(conditionRole)) {\n activeConditionRoleFound = true;\n break;\n }\n }\n\n // If we couldn't find an active role in our list, then we've failed this condition.\n if (!activeConditionRoleFound) {\n return false;\n }\n }\n\n if (condition?.inactive !== undefined) {\n let inactiveConditionRoleFound = false;\n for (const conditionRole of condition.inactive) {\n if (activeRoles.includes(conditionRole)) {\n inactiveConditionRoleFound = true;\n break;\n }\n }\n\n // If we find an active role from our inactive list, then we've failed this condition.\n if (inactiveConditionRoleFound) {\n return false;\n }\n }\n }\n\n if (condition?.callback !== undefined && condition.callback() === false) {\n return false;\n }\n\n // If there was no condition, we return true.\n return true;\n}\n"]}
@@ -1,7 +1,10 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { IntlProvider } from 'react-intl';
3
3
  import { Hyperlink, Image } from '@openedx/paragon';
4
- export default function Logo({ imageUrl = 'https://edx-cdn.org/v3/default/logo.svg', destinationUrl }) {
4
+ import { getSiteConfig } from '../runtime/config';
5
+ export default function Logo(_a) {
6
+ var _b;
7
+ var { imageUrl = (_b = getSiteConfig().headerLogoImageUrl) !== null && _b !== void 0 ? _b : 'https://edx-cdn.org/v3/default/logo.svg', destinationUrl } = _a;
5
8
  const image = (_jsx(Image, { src: imageUrl, style: { maxHeight: '2rem' } }));
6
9
  if (destinationUrl === undefined) {
7
10
  return image;
@@ -1 +1 @@
1
- {"version":3,"file":"Logo.js","sourceRoot":"","sources":["../../shell/Logo.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAOpD,MAAM,CAAC,OAAO,UAAU,IAAI,CAAC,EAC3B,QAAQ,GAAG,yCAAyC,EACpD,cAAc,EACJ;IACV,MAAM,KAAK,GAAG,CACZ,KAAC,KAAK,IAAC,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,GAAI,CACvD,CAAC;IAEF,IAAI,cAAc,KAAK,SAAS,EAAE,CAAC;QACjC,OAAO,KAAK,CAAC;IACf,CAAC;IAED,OAAO,CACL,KAAC,YAAY,IAAC,MAAM,EAAC,IAAI,YACvB,KAAC,SAAS,IAAC,WAAW,EAAE,cAAc,EAAE,SAAS,EAAC,KAAK,YACpD,KAAK,GACI,GACC,CAChB,CAAC;AACJ,CAAC","sourcesContent":["import { IntlProvider } from 'react-intl';\nimport { Hyperlink, Image } from '@openedx/paragon';\n\ninterface LogoProps {\n imageUrl?: string,\n destinationUrl?: string,\n}\n\nexport default function Logo({\n imageUrl = 'https://edx-cdn.org/v3/default/logo.svg',\n destinationUrl\n}: LogoProps) {\n const image = (\n <Image src={imageUrl} style={{ maxHeight: '2rem' }} />\n );\n\n if (destinationUrl === undefined) {\n return image;\n }\n\n return (\n <IntlProvider locale=\"en\">\n <Hyperlink destination={destinationUrl} className=\"p-0\">\n {image}\n </Hyperlink>\n </IntlProvider>\n );\n}\n"]}
1
+ {"version":3,"file":"Logo.js","sourceRoot":"","sources":["../../shell/Logo.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAOlD,MAAM,CAAC,OAAO,UAAU,IAAI,CAAC,EAGjB;;QAHiB,EAC3B,QAAQ,GAAG,MAAA,aAAa,EAAE,CAAC,kBAAkB,mCAAI,yCAAyC,EAC1F,cAAc;IAEd,MAAM,KAAK,GAAG,CACZ,KAAC,KAAK,IAAC,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,GAAI,CACvD,CAAC;IAEF,IAAI,cAAc,KAAK,SAAS,EAAE,CAAC;QACjC,OAAO,KAAK,CAAC;IACf,CAAC;IAED,OAAO,CACL,KAAC,YAAY,IAAC,MAAM,EAAC,IAAI,YACvB,KAAC,SAAS,IAAC,WAAW,EAAE,cAAc,EAAE,SAAS,EAAC,KAAK,YACpD,KAAK,GACI,GACC,CAChB,CAAC;AACJ,CAAC","sourcesContent":["import { IntlProvider } from 'react-intl';\nimport { Hyperlink, Image } from '@openedx/paragon';\nimport { getSiteConfig } from '../runtime/config';\n\ninterface LogoProps {\n imageUrl?: string,\n destinationUrl?: string,\n}\n\nexport default function Logo({\n imageUrl = getSiteConfig().headerLogoImageUrl ?? 'https://edx-cdn.org/v3/default/logo.svg',\n destinationUrl\n}: LogoProps) {\n const image = (\n <Image src={imageUrl} style={{ maxHeight: '2rem' }} />\n );\n\n if (destinationUrl === undefined) {\n return image;\n }\n\n return (\n <IntlProvider locale=\"en\">\n <Hyperlink destination={destinationUrl} className=\"p-0\">\n {image}\n </Hyperlink>\n </IntlProvider>\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":["../../shell/jest.config.js"],"names":[],"mappings":";AAAA,MAAM,CAAC,OAAO,GAAG;IACf,kBAAkB,EAAE;QAClB,gBAAgB;KACjB;IACD,gBAAgB,EAAE;QAChB,SAAS,EAAE,4BAA4B;QACvC,iFAAiF,EAAE,6BAA6B;QAChH,gBAAgB,EAAE,OAAO,CAAC,OAAO,CAAC,oBAAoB,CAAC;QACvD,aAAa,EAAE,gCAAgC;QAC/C,aAAa,EAAE,kBAAkB;KAClC;IACD,eAAe,EAAE,OAAO;IACxB,sBAAsB,EAAE;QACtB,GAAG,EAAE,mBAAmB;KACzB;IACD,mBAAmB,EAAE;QACnB,gCAAgC;KACjC;IACD,0BAA0B,EAAE;QAC1B,gBAAgB;QAChB,cAAc;KACf;IACD,uBAAuB,EAAE;QACvB,oCAAoC;KACrC;IACD,sBAAsB,EAAE;QACtB,uBAAuB;QACvB,gBAAgB;QAChB,QAAQ;KACT;CACF,CAAC","sourcesContent":["module.exports = {\n setupFilesAfterEnv: [\n './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 '^@src/(.*)$': '<rootDir>/src/$1',\n },\n testEnvironment: 'jsdom',\n testEnvironmentOptions: {\n url: 'http://localhost/',\n },\n collectCoverageFrom: [\n '<rootDir>/**/*.{js,jsx,ts,tsx}',\n ],\n coveragePathIgnorePatterns: [\n '/node_modules/',\n 'setupTest.js',\n ],\n transformIgnorePatterns: [\n '/node_modules/(?!(@openedx|@edx)/)',\n ],\n testPathIgnorePatterns: [\n '/site.config.test.tsx',\n '/node_modules/',\n '/dist/',\n ],\n};\n"]}
1
+ {"version":3,"file":"jest.config.js","sourceRoot":"","sources":["../../shell/jest.config.js"],"names":[],"mappings":";AAAA,MAAM,CAAC,OAAO,GAAG;IACf,kBAAkB,EAAE;QAClB,gBAAgB;KACjB;IACD,gBAAgB,EAAE;QAChB,SAAS,EAAE,4BAA4B;QACvC,iFAAiF,EAAE,6BAA6B;QAChH,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,gBAAgB;QAChB,cAAc;KACf;IACD,uBAAuB,EAAE;QACvB,oCAAoC;KACrC;IACD,sBAAsB,EAAE;QACtB,uBAAuB;QACvB,gBAAgB;QAChB,QAAQ;KACT;CACF,CAAC","sourcesContent":["module.exports = {\n setupFilesAfterEnv: [\n './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 '/node_modules/',\n 'setupTest.js',\n ],\n transformIgnorePatterns: [\n '/node_modules/(?!(@openedx|@edx)/)',\n ],\n testPathIgnorePatterns: [\n '/site.config.test.tsx',\n '/node_modules/',\n '/dist/',\n ],\n};\n"]}
@@ -6,7 +6,6 @@ export let rootDir: string;
6
6
  export let moduleNameMapper: {
7
7
  '\\.(css|scss)$': string;
8
8
  'site.config': string;
9
- '^@src/(.*)$': string;
10
9
  };
11
10
  export let collectCoverageFrom: string[];
12
11
  export let coveragePathIgnorePatterns: string[];
@@ -9,7 +9,6 @@ module.exports = {
9
9
  moduleNameMapper: {
10
10
  '\\.(css|scss)$': require.resolve('identity-obj-proxy'),
11
11
  'site.config': path.resolve(process.cwd(), './site.config.test.tsx'),
12
- '^@src/(.*)$': '<rootDir>/src/$1',
13
12
  },
14
13
  collectCoverageFrom: [
15
14
  'src/**/*.{js,jsx,ts,tsx}',
package/dist/types.d.ts CHANGED
@@ -42,6 +42,7 @@ export interface OptionalSiteConfig {
42
42
  externalRoutes: ExternalRoute[];
43
43
  externalLinkUrlOverrides: string[];
44
44
  runtimeConfigJsonUrl: string | null;
45
+ headerLogoImageUrl: string;
45
46
  theme: Theme;
46
47
  accessTokenCookieName: string;
47
48
  languagePreferenceCookieName: string;
package/dist/types.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../types.ts"],"names":[],"mappings":"AA8GA,MAAM,CAAN,IAAY,gBAIX;AAJD,WAAY,gBAAgB;IAC1B,6CAAyB,CAAA;IACzB,+CAA2B,CAAA;IAC3B,iCAAa,CAAA;AACf,CAAC,EAJW,gBAAgB,KAAhB,gBAAgB,QAI3B","sourcesContent":["import { FC, ReactElement, ReactNode } from 'react';\nimport { MessageDescriptor } from 'react-intl';\nimport { RouteObject } from 'react-router';\nimport { SlotOperation } from './runtime/slots/types';\n\n// Apps\n\nexport interface ExternalRoute {\n role: string,\n url: string,\n}\n\nexport type RoleRouteObject = RouteObject & {\n handle?: {\n /**\n * A route role is used to identify a route that fulfills a particular role in the site.\n */\n role?: string,\n },\n};\n\nexport type AppConfig = Record<string, unknown>;\n\nexport type AppProvider = FC<{ children?: ReactNode }>;\n\nexport interface App {\n appId: string,\n messages?: LocalizedMessages,\n routes?: RoleRouteObject[],\n providers?: AppProvider[],\n slots?: SlotOperation[],\n config?: AppConfig,\n}\n\n// Site Config\n\nexport interface RequiredSiteConfig {\n siteId: string,\n siteName: string,\n baseUrl: string,\n\n // Backends\n lmsBaseUrl: string,\n\n // Frontends\n loginUrl: string,\n logoutUrl: string,\n}\n\nexport type LocalizedMessages = Record<string, Record<string, string>>;\n\nexport interface OptionalSiteConfig {\n // Site environment\n environment: EnvironmentTypes,\n\n // Apps, routes, and URLs\n apps: App[],\n basename: string,\n externalRoutes: ExternalRoute[],\n externalLinkUrlOverrides: string[],\n runtimeConfigJsonUrl: string | null,\n\n // Theme\n theme: Theme,\n\n // Cookies\n accessTokenCookieName: string,\n languagePreferenceCookieName: string,\n userInfoCookieName: string,\n\n // Paths\n csrfTokenApiPath: string,\n refreshAccessTokenApiPath: string,\n\n // Logging\n ignoredErrorRegex: RegExp | null,\n\n // Analytics\n segmentKey: string | null,\n}\n\nexport type SiteConfig = RequiredSiteConfig & Partial<OptionalSiteConfig>;\n\nexport interface ThemeVariant {\n url: string,\n}\n\nexport interface ThemeDefaults {\n light?: string,\n dark?: string,\n}\n\nexport type ThemeVariants = Record<string, ThemeVariant>;\n\nexport interface Theme {\n core?: ThemeVariant,\n defaults?: ThemeDefaults,\n variants?: ThemeVariants,\n}\n\nexport interface User {\n administrator: boolean,\n email: string,\n name: string,\n roles: string[],\n userId: number,\n username: string,\n avatar: string,\n}\n\nexport enum EnvironmentTypes {\n PRODUCTION = 'production',\n DEVELOPMENT = 'development',\n TEST = 'test',\n}\n\n// Menu Items\n\nexport type MenuItemName = string | MessageDescriptor | ReactElement;\n"]}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../types.ts"],"names":[],"mappings":"AA+GA,MAAM,CAAN,IAAY,gBAIX;AAJD,WAAY,gBAAgB;IAC1B,6CAAyB,CAAA;IACzB,+CAA2B,CAAA;IAC3B,iCAAa,CAAA;AACf,CAAC,EAJW,gBAAgB,KAAhB,gBAAgB,QAI3B","sourcesContent":["import { FC, ReactElement, ReactNode } from 'react';\nimport { MessageDescriptor } from 'react-intl';\nimport { RouteObject } from 'react-router';\nimport { SlotOperation } from './runtime/slots/types';\n\n// Apps\n\nexport interface ExternalRoute {\n role: string,\n url: string,\n}\n\nexport type RoleRouteObject = RouteObject & {\n handle?: {\n /**\n * A route role is used to identify a route that fulfills a particular role in the site.\n */\n role?: string,\n },\n};\n\nexport type AppConfig = Record<string, unknown>;\n\nexport type AppProvider = FC<{ children?: ReactNode }>;\n\nexport interface App {\n appId: string,\n messages?: LocalizedMessages,\n routes?: RoleRouteObject[],\n providers?: AppProvider[],\n slots?: SlotOperation[],\n config?: AppConfig,\n}\n\n// Site Config\n\nexport interface RequiredSiteConfig {\n siteId: string,\n siteName: string,\n baseUrl: string,\n\n // Backends\n lmsBaseUrl: string,\n\n // Frontends\n loginUrl: string,\n logoutUrl: string,\n}\n\nexport type LocalizedMessages = Record<string, Record<string, string>>;\n\nexport interface OptionalSiteConfig {\n // Site environment\n environment: EnvironmentTypes,\n\n // Apps, routes, and URLs\n apps: App[],\n basename: string,\n externalRoutes: ExternalRoute[],\n externalLinkUrlOverrides: string[],\n runtimeConfigJsonUrl: string | null,\n headerLogoImageUrl: string,\n\n // Theme\n theme: Theme,\n\n // Cookies\n accessTokenCookieName: string,\n languagePreferenceCookieName: string,\n userInfoCookieName: string,\n\n // Paths\n csrfTokenApiPath: string,\n refreshAccessTokenApiPath: string,\n\n // Logging\n ignoredErrorRegex: RegExp | null,\n\n // Analytics\n segmentKey: string | null,\n}\n\nexport type SiteConfig = RequiredSiteConfig & Partial<OptionalSiteConfig>;\n\nexport interface ThemeVariant {\n url: string,\n}\n\nexport interface ThemeDefaults {\n light?: string,\n dark?: string,\n}\n\nexport type ThemeVariants = Record<string, ThemeVariant>;\n\nexport interface Theme {\n core?: ThemeVariant,\n defaults?: ThemeDefaults,\n variants?: ThemeVariants,\n}\n\nexport interface User {\n administrator: boolean,\n email: string,\n name: string,\n roles: string[],\n userId: number,\n username: string,\n avatar: string,\n}\n\nexport enum EnvironmentTypes {\n PRODUCTION = 'production',\n DEVELOPMENT = 'development',\n TEST = 'test',\n}\n\n// Menu Items\n\nexport type MenuItemName = string | MessageDescriptor | ReactElement;\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openedx/frontend-base",
3
- "version": "1.0.0-alpha.13",
3
+ "version": "1.0.0-alpha.14",
4
4
  "description": "Build tools, setup and config for frontend apps",
5
5
  "publishConfig": {
6
6
  "access": "public"