-
Notifications
You must be signed in to change notification settings - Fork 516
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Update Care Apps Setup; API URL on window (#9883)
- Loading branch information
Showing
4 changed files
with
131 additions
and
93 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,28 +16,70 @@ interface Plugin { | |
camelCaseName: string; | ||
} | ||
|
||
interface ParsedRemoteConfig { | ||
url: string; | ||
org: string; | ||
repo: string; | ||
} | ||
|
||
/** | ||
* Parses a remote app configuration string into its components | ||
* Supports two formats: | ||
* 1. GitHub Pages: "organization/repository" | ||
* Example: "coronasafe/care_fe" | ||
* | ||
* 2. Custom URL: "organization/repository@url" | ||
* Example: "coronasafe/care_fe@localhost:5173" | ||
* Example: "coronasafe/[email protected]" | ||
* Note: Protocol (http/https) is automatically added in the vite config: | ||
* - localhost URLs use http:// | ||
* - all other URLs use https:// | ||
* | ||
* @param appConfig - Configuration string for a remote app | ||
* @returns Parsed configuration object | ||
*/ | ||
function parseRemoteConfig(appConfig: string): ParsedRemoteConfig { | ||
// Handle custom URLs (both localhost and custom hosted) | ||
if (appConfig.includes("@")) { | ||
const [package_] = appConfig.split("@"); | ||
const [org, repo] = package_.split("/"); | ||
return { | ||
url: "", // URL not needed for plugin setup | ||
org, | ||
repo, | ||
}; | ||
} | ||
|
||
// Handle GitHub Pages URLs | ||
const [org, repo] = appConfig.split("/"); | ||
return { | ||
url: "", // URL not needed for plugin setup | ||
org, | ||
repo, | ||
}; | ||
} | ||
|
||
// Function to read enabled apps from env | ||
function readAppsConfig(): Plugin[] { | ||
const appsConfig = process.env.REACT_ENABLED_APPS | ||
? process.env.REACT_ENABLED_APPS.split(",").map((app) => { | ||
const package_ = app.includes("|") | ||
? app.split("|")[1].split("@")[0] | ||
: app.split("@")[0]; | ||
console.log(package_); | ||
const [, repo] = package_.split("/"); | ||
return { | ||
repo, | ||
// Convert repo name to camelCase for import | ||
camelCaseName: repo | ||
.replace(/[-_]/g, "") | ||
.replace(/\b\w/g, (char, index) => | ||
index === 0 ? char.toLowerCase() : char.toUpperCase(), | ||
), | ||
}; | ||
}) | ||
: []; | ||
console.log("Found plugins: ", appsConfig); | ||
return appsConfig; | ||
if (!process.env.REACT_ENABLED_APPS) { | ||
return []; | ||
} | ||
|
||
const plugins = process.env.REACT_ENABLED_APPS.split(",").map((app) => { | ||
const { repo } = parseRemoteConfig(app); | ||
return { | ||
repo, | ||
// Convert repo name to camelCase for import | ||
camelCaseName: repo | ||
.replace(/[-_]/g, "") | ||
.replace(/\b\w/g, (char, index) => | ||
index === 0 ? char.toLowerCase() : char.toUpperCase(), | ||
), | ||
}; | ||
}); | ||
|
||
console.log("Found plugins:", plugins); | ||
return plugins; | ||
} | ||
|
||
const plugins = readAppsConfig(); | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -60,66 +60,70 @@ function getPluginAliases() { | |
return aliases; | ||
} | ||
|
||
function getPluginDependencies(): string[] { | ||
const pluginsDir = path.resolve(__dirname, "apps"); | ||
// Make sure the `apps` folder exists | ||
if (!fs.existsSync(pluginsDir)) { | ||
return []; | ||
} | ||
const pluginFolders = fs.readdirSync(pluginsDir); | ||
|
||
const dependencies = new Set<string>(); | ||
|
||
pluginFolders.forEach((pluginFolder) => { | ||
const packageJsonPath = path.join(pluginsDir, pluginFolder, "package.json"); | ||
if (fs.existsSync(packageJsonPath)) { | ||
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf8")); | ||
const pluginDependencies = packageJson.dependencies | ||
? Object.keys(packageJson.dependencies) | ||
: []; | ||
pluginDependencies.forEach((dep) => dependencies.add(dep)); | ||
} | ||
}); | ||
|
||
return Array.from(dependencies); | ||
/** | ||
* Parses a remote app configuration string into its components | ||
* @param appConfig - Configuration string for a remote app | ||
* @returns Parsed configuration object | ||
*/ | ||
interface ParsedRemoteConfig { | ||
url: string; | ||
org: string; | ||
repo: string; | ||
} | ||
|
||
// Recursive function to check if the module is statically imported by an entry point | ||
function isStaticallyImportedByEntry( | ||
getModuleInfo: (moduleId: string) => any, | ||
moduleId: string, | ||
visited = new Set(), | ||
) { | ||
if (visited.has(moduleId)) return false; | ||
visited.add(moduleId); | ||
|
||
const modInfo = getModuleInfo(moduleId); | ||
if (!modInfo) return false; | ||
|
||
// Check if the module is an entry point | ||
if (modInfo.isEntry) { | ||
return true; | ||
function parseRemoteConfig(appConfig: string): ParsedRemoteConfig { | ||
if (!appConfig.includes("/")) { | ||
throw new Error( | ||
`Invalid app configuration format: ${appConfig}. Expected 'org/repo' or 'org/repo@url'.`, | ||
); | ||
} | ||
|
||
// Check all static importers | ||
for (const importerId of modInfo.importers) { | ||
if (isStaticallyImportedByEntry(getModuleInfo, importerId, visited)) { | ||
return true; | ||
// Handle custom URLs (both localhost and custom hosted) | ||
if (appConfig.includes("@")) { | ||
const [package_, url] = appConfig.split("@"); | ||
const [org, repo] = package_.split("/"); | ||
if (!org || !repo || !url) { | ||
throw new Error( | ||
`Invalid custom URL configuration: ${appConfig}. Expected 'org/repo@url'.`, | ||
); | ||
} | ||
// Add appropriate protocol based on whether it's localhost | ||
const protocol = url.includes("localhost") ? "http://" : "https://"; | ||
const fullUrl = url.startsWith("http") ? url : `${protocol}${url}`; | ||
|
||
return { | ||
url: `${fullUrl}/assets/remoteEntry.js`, | ||
org, | ||
repo, | ||
}; | ||
} | ||
|
||
return false; | ||
// Handle GitHub Pages URLs | ||
const [org, repo] = appConfig.split("/"); | ||
if (!org || !repo) { | ||
throw new Error( | ||
`Invalid GitHub Pages configuration: ${appConfig}. Expected 'org/repo'.`, | ||
); | ||
} | ||
return { | ||
url: `https://${org}.github.io/${repo}/assets/remoteEntry.js`, | ||
org, | ||
repo, | ||
}; | ||
} | ||
|
||
/** | ||
* Generates remote module configurations for Module Federation | ||
* | ||
* Supports two formats for REACT_ENABLED_APPS: | ||
* 1. GitHub Pages: "organization/repository[@branch]" | ||
* Example: "coronasafe/care_fe@main" | ||
* 1. GitHub Pages: "organization/repository" | ||
* Example: "coronasafe/care_fe" | ||
* | ||
* 2. Custom URL: "prot://localhost:port|organization/repository[@branch]" | ||
* Example: "http://localhost:5173|coronasafe/care_fe@main" | ||
* 2. Custom URL: "organization/repository@url" | ||
* Example: "coronasafe/care_fe@localhost:5173" | ||
* Example: "coronasafe/[email protected]" | ||
* Note: Protocol (http/https) is automatically added based on the URL: | ||
* - localhost URLs use http:// | ||
* - all other URLs use https:// | ||
* | ||
* @param enabledApps - Comma-separated list of enabled apps | ||
* @returns Remote module configuration object for Module Federation | ||
|
@@ -128,35 +132,13 @@ function getRemotes(enabledApps: string) { | |
if (!enabledApps) return {}; | ||
|
||
return enabledApps.split(",").reduce((acc, app) => { | ||
const [package_, branch = "main"] = app.split("@"); | ||
const { repo, url } = parseRemoteConfig(app); | ||
console.log(`Configuring Remote Module for ${repo}:`, url); | ||
|
||
// Handle custom URLs | ||
if ((package_.includes("|"))) { | ||
const [host, pathParts] = package_.split("|"); | ||
const [org, repo] = pathParts.split("/"); | ||
const remoteUrl = `"${host}/assets/remoteEntry.js"`; | ||
console.log(`Using Local Remote Module for ${org}/${repo}:`, remoteUrl); | ||
return { | ||
...acc, | ||
[repo]: { | ||
external: `Promise.resolve(${remoteUrl})`, | ||
from: "vite", | ||
externalType: "promise", | ||
}, | ||
}; | ||
} | ||
|
||
// Handle GitHub Pages URLs | ||
const [org, repo] = package_.split("/"); | ||
const remoteUrl = `"https://${org}.github.io/${repo}/assets/remoteEntry.js"`; | ||
console.log( | ||
`Using GitHub Pages Remote Module for ${org}/${repo}:`, | ||
remoteUrl, | ||
); | ||
return { | ||
...acc, | ||
[repo]: { | ||
external: `Promise.resolve(${remoteUrl})`, | ||
external: `Promise.resolve("${url}")`, | ||
from: "vite", | ||
externalType: "promise", | ||
}, | ||
|