Files
lobe-chat/scripts/electronWorkflow/modifiers/routes.mts
T
Innei ad32a61704 perf(electron): add codemods to convert dynamic imports to static (#11690)
*  feat(electron): add codemods to convert dynamic imports to static

Add multiple modifiers for Electron build workflow:
- dynamicToStatic: Convert dynamicElement() to static imports
- nextDynamicToStatic: Convert next/dynamic (ssr: false) to static
- wrapChildrenWithClientOnly: Wrap layout children with ClientOnly + Loading fallback
- settingsContentToStatic: Handle SettingsContent componentMap pattern
- removeSuspense: Remove Suspense wrappers from components
- routes: Delete loading.tsx files and (mobile) directory

Also add fallback prop support to ClientOnly component for better UX during hydration.

*  feat(electron): enhance settingsContentToStatic with business features support

- Introduced a new function to check if business features are enabled via environment variables.
- Updated import generation functions to conditionally include business-related imports based on the new feature flag.
- Improved regex patterns for better matching of dynamic imports.
- Added logging to indicate when business features are active, enhancing debugging and user awareness.

Signed-off-by: Innei <tukon479@gmail.com>

---------

Signed-off-by: Innei <tukon479@gmail.com>
2026-01-22 17:18:06 +08:00

110 lines
3.0 KiB
TypeScript

import { Lang, parse } from '@ast-grep/napi';
import path from 'node:path';
import { isDirectRun, removePathEnsuring, runStandalone, updateFile } from './utils.mjs';
export const modifyRoutes = async (TEMP_DIR: string) => {
// 1. Delete routes
const filesToDelete = [
// Backend API routes
'src/app/(backend)/api',
'src/app/(backend)/webapi',
'src/app/(backend)/trpc',
'src/app/(backend)/oidc',
'src/app/(backend)/middleware',
'src/app/(backend)/f',
'src/app/(backend)/market',
// Auth & User routes
'src/app/[variants]/(auth)',
'src/app/[variants]/(mobile)',
'src/app/[variants]/(main)/(mobile)/me',
'src/app/[variants]/(main)/changelog',
'src/app/[variants]/oauth',
// Other app roots
'src/app/market-auth-callback',
'src/app/manifest.ts',
'src/app/robots.tsx',
'src/app/sitemap.tsx',
'src/app/sw.ts',
// Config files
'src/instrumentation.ts',
'src/instrumentation.node.ts',
// Desktop specific routes
'src/app/desktop/devtools',
'src/app/desktop/layout.tsx',
];
for (const file of filesToDelete) {
const fullPath = path.join(TEMP_DIR, file);
await removePathEnsuring({
name: `modifyRoutes:delete:${file}`,
path: fullPath,
});
}
// 2. Delete root loading.tsx files(not needed in Electron SPA)
const loadingFiles = ['src/app/loading.tsx', 'src/app/[variants]/loading.tsx'];
console.log(` Removing ${loadingFiles.length} root loading.tsx files...`);
for (const file of loadingFiles) {
const fullPath = path.join(TEMP_DIR, file);
await removePathEnsuring({
name: `modifyRoutes:delete:loading:${file}`,
path: fullPath,
});
}
// 3. Modify desktopRouter.config.tsx
const routerConfigPath = path.join(
TEMP_DIR,
'src/app/[variants]/router/desktopRouter.config.tsx',
);
console.log(' Processing src/app/[variants]/router/desktopRouter.config.tsx...');
await updateFile({
assertAfter: (code) => !/\bchangelog\b/.test(code),
filePath: routerConfigPath,
name: 'modifyRoutes:desktopRouterConfig',
transformer: (code) => {
const ast = parse(Lang.Tsx, code);
const root = ast.root();
const changelogNode = root.find({
rule: {
pattern: "{ path: 'changelog', $$$ }",
},
});
if (changelogNode) {
changelogNode.replace('');
}
const changelogImport = root.find({
rule: {
pattern: "import('../(main)/changelog')",
},
});
if (changelogImport) {
// Find the closest object (route definition) and remove it
let curr = changelogImport.parent();
while (curr) {
if (curr.kind() === 'object') {
curr.replace('');
break;
}
curr = curr.parent();
}
}
return root.text();
},
});
};
if (isDirectRun(import.meta.url)) {
await runStandalone('modifyRoutes', modifyRoutes, [
{ lang: Lang.Tsx, path: 'src/app/[variants]/router/desktopRouter.config.tsx' },
]);
}