Skip to content

Commit 921cce9

Browse files
committed
feat: React component into UI5 App
1 parent 940597e commit 921cce9

11 files changed

Lines changed: 988 additions & 305 deletions

File tree

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
/**
2+
* Shared bundler configuration for task and middleware.
3+
* SCAN_RESULT will be generated by AST scanner in production.
4+
*/
5+
6+
import {join, dirname} from "path";
7+
import {fileURLToPath} from "url";
8+
import replace from "@rollup/plugin-replace";
9+
10+
const __dirname = dirname(fileURLToPath(import.meta.url));
11+
12+
/**
13+
* Scan result - defines what to bundle and how.
14+
* Keys are package names, values define entry points and dependencies.
15+
*/
16+
export const SCAN_RESULT = {
17+
// Standalone packages (no externals)
18+
"chart.js": {
19+
imports: ["Chart", "BarController", "BarElement", "CategoryScale", "LinearScale", "Title", "Tooltip", "Legend"],
20+
entryPoints: ["chart.js"]
21+
},
22+
"validator": {
23+
imports: ["isEmail", "isURL", "escape"],
24+
entryPoints: ["validator"]
25+
},
26+
27+
// React ecosystem - ordered by dependency (react first, then react-dom, then components)
28+
"react": {
29+
imports: ["useState", "useEffect", "createElement"],
30+
entryPoints: ["react"]
31+
},
32+
"react-dom": {
33+
imports: ["createRoot"],
34+
entryPoints: ["react-dom/client"], // Actual entry differs from package name
35+
externals: ["react"],
36+
outputName: "react-dom"
37+
},
38+
"react-colorful": {
39+
imports: ["HexColorPicker"],
40+
entryPoints: ["react-colorful"],
41+
externals: ["react", "react-dom"]
42+
},
43+
44+
// App-specific React wrapper component
45+
"react-colorpicker": {
46+
imports: ["mountColorPicker"],
47+
entryPoints: [join(__dirname, "webapp/react/ColorPickerWrapper.js")],
48+
externals: ["react", "react-dom"],
49+
outputName: "react-colorpicker",
50+
outputOptions: {exports: "named"}
51+
}
52+
};
53+
54+
/** Get externals for a package (mapped to actual entry points) */
55+
export function getExternals(packageName) {
56+
const scanInfo = SCAN_RESULT[packageName];
57+
if (!scanInfo?.externals) return [];
58+
59+
// Map dependency names to their actual entry points
60+
return scanInfo.externals.flatMap((dep) => {
61+
const depInfo = SCAN_RESULT[dep];
62+
return depInfo ? depInfo.entryPoints : [dep];
63+
});
64+
}
65+
66+
/** Generate AMD paths mapping for externalized dependencies */
67+
export function getPathsMapping(packageName) {
68+
const scanInfo = SCAN_RESULT[packageName];
69+
if (!scanInfo?.externals) return {};
70+
71+
const paths = {};
72+
for (const dep of scanInfo.externals) {
73+
const depInfo = SCAN_RESULT[dep];
74+
if (depInfo) {
75+
const outputName = depInfo.outputName || sanitizePackageName(dep);
76+
for (const entry of depInfo.entryPoints) {
77+
paths[entry] = `thirdparty/${outputName}`;
78+
}
79+
}
80+
}
81+
return paths;
82+
}
83+
84+
/** Get packages in dependency order (topological sort based on externals) */
85+
export function getBundleOrder() {
86+
const result = [];
87+
const visited = new Set();
88+
89+
function visit(pkg) {
90+
if (visited.has(pkg)) return;
91+
visited.add(pkg);
92+
93+
const info = SCAN_RESULT[pkg];
94+
if (info?.externals) {
95+
for (const dep of info.externals) {
96+
if (SCAN_RESULT[dep]) visit(dep);
97+
}
98+
}
99+
result.push(pkg);
100+
}
101+
102+
Object.keys(SCAN_RESULT).forEach(visit);
103+
return result;
104+
}
105+
106+
/** Create production mode replace plugin */
107+
export function createProductionPlugin() {
108+
return replace({
109+
preventAssignment: true,
110+
"process.env.NODE_ENV": JSON.stringify("production")
111+
});
112+
}
113+
114+
/** Create development mode replace plugin */
115+
export function createDevelopmentPlugin() {
116+
return replace({
117+
preventAssignment: true,
118+
"process.env.NODE_ENV": JSON.stringify("development")
119+
});
120+
}
121+
122+
/** Sanitize package name for file path (handle scoped packages) */
123+
export function sanitizePackageName(packageName) {
124+
return packageName.replace(/^@/, "").replace(/\//g, "-");
125+
}

0 commit comments

Comments
 (0)