-
Notifications
You must be signed in to change notification settings - Fork 47
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix/server web implement config #3368
base: develop
Are you sure you want to change the base?
Changes from all commits
e47b321
fc16b31
dbb8c89
10f062c
48e6cbd
65147c4
9d07de3
985b768
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
import * as fs from 'fs'; | ||
import * as path from 'path'; | ||
import { hideBin } from 'yargs/helpers'; | ||
import yargs from 'yargs'; | ||
|
||
interface Arguments { | ||
type: 'server' | 'constant' | ||
} | ||
const argv = yargs(hideBin(process.argv)) | ||
.options({ | ||
type: { | ||
type: 'string', | ||
choices: ['server', 'constant'], | ||
demandOption: true, | ||
description: 'Type of configuration to modify' | ||
} | ||
}) | ||
.parseSync() as Arguments; | ||
|
||
function modifiedNextServer() { | ||
const filePath = path.resolve(__dirname, '../apps/server-web/release/app/dist/standalone/apps/web/server.js'); | ||
try { | ||
let fileContent = fs.readFileSync(filePath, 'utf8'); | ||
const searchString = 'process.env.__NEXT_PRIVATE_STANDALONE_CONFIG'; | ||
const codeToInsert = ` | ||
nextConfig.serverRuntimeConfig = { | ||
"GAUZY_API_SERVER_URL": process.env.GAUZY_API_SERVER_URL, | ||
"NEXT_PUBLIC_GAUZY_API_SERVER_URL": process.env.NEXT_PUBLIC_GAUZY_API_SERVER_URL | ||
} | ||
`; | ||
|
||
let lines = fileContent.split('\n'); | ||
const index = lines.findIndex((line) => line.includes(searchString)); | ||
|
||
if (index !== -1) { | ||
lines.splice(index - 1, 0, codeToInsert); | ||
|
||
fileContent = lines.join('\n'); | ||
fs.writeFileSync(filePath, fileContent, 'utf8'); | ||
console.log('Line of code successfully inserted.'); | ||
} else { | ||
console.log(`The string "${searchString}" was not found in the file.`); | ||
} | ||
} catch (error) { | ||
console.error('Failed to change static server configuration'); | ||
} | ||
} | ||
|
||
function updateWebConstant(setDesktopApp) { | ||
const filePath = path.resolve(__dirname, '../apps/web/app/constants.ts'); | ||
try { | ||
let fileContent = fs.readFileSync(filePath, 'utf8'); | ||
const envCheck = `export const IS_DESKTOP_APP = process.env.IS_DESKTOP_APP === 'true';`; | ||
const hardcoded = `export const IS_DESKTOP_APP = true;`; | ||
|
||
const [from, to] = setDesktopApp ? [envCheck, hardcoded] : [hardcoded, envCheck]; | ||
|
||
if (!fileContent.includes(from)) { | ||
throw new Error(`Expected content not found in ${filePath}`); | ||
} | ||
|
||
fileContent = fileContent.replace(from, to); | ||
fs.writeFileSync(filePath, fileContent, 'utf8'); | ||
console.log(`Successfully ${setDesktopApp ? 'set' : 'reverted'} IS_DESKTOP_APP`); | ||
} catch (error) { | ||
console.error('Failed to update constants:', error); | ||
process.exit(1); | ||
} | ||
} | ||
|
||
|
||
if (argv.type === 'server') { | ||
modifiedNextServer(); | ||
updateWebConstant(false); | ||
} else if (argv.type === 'constant') { | ||
updateWebConstant(true); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
import { copy } from 'fs-extra'; | ||
import { join } from 'path'; | ||
|
||
async function copyWebBuild() { | ||
const webDir = join(process.cwd(), 'apps/web'); | ||
const distDir = join(process.cwd(), 'apps/server-web/release/app/dist'); | ||
|
||
try { | ||
// Copy standalone build | ||
await copy( | ||
join(webDir, '.next/standalone'), | ||
join(distDir, 'standalone') | ||
); | ||
|
||
// Copy static files | ||
await copy( | ||
join(webDir, '.next/static'), | ||
join(distDir, 'standalone/apps/web/.next/static') | ||
); | ||
|
||
// Copy public files | ||
await copy( | ||
join(webDir, 'public'), | ||
join(distDir, 'standalone/apps/web/public') | ||
); | ||
|
||
console.log('Build files copied successfully'); | ||
} catch (error) { | ||
console.error('Failed to copy build files:', error); | ||
process.exit(1); | ||
} | ||
} | ||
|
||
copyWebBuild(); |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,19 +15,19 @@ | |
"SERVER_WINDOW": "Прозорец на сървъра" | ||
}, | ||
"MENU_APP": { | ||
"ABOUT": "Относно", | ||
"QUIT": "Изход", | ||
"WINDOW": "Прозорец", | ||
"SUBMENU": { | ||
"SETTING": "Настройки", | ||
"SERVER_WINDOW": "Сървърен прозорец", | ||
"LEARN_MORE": "Научете повече", | ||
"DOC": "Документация", | ||
"SETTING_DEV": "Настройки за разработчици", | ||
"SERVER_DEV": "Сървър за разработчици" | ||
"APP_ABOUT": "Относно", | ||
"APP_QUIT": "Изход", | ||
"APP_WINDOW": "Прозорец", | ||
"APP_SUBMENU": { | ||
"APP_SETTING": "Настройки", | ||
"APP_SERVER_WINDOW": "Сървърен прозорец", | ||
"APP_LEARN_MORE": "Научете повече", | ||
"APP_DOC": "Документация", | ||
"APP_SETTING_DEV": "Настройки за разработчици", | ||
"APP_SERVER_DEV": "Сървър за разработчици" | ||
}, | ||
"DEV": "Разработчик", | ||
"HELP": "Помощ" | ||
"APP_DEV": "Разработчик", | ||
"APP_HELP": "Помощ" | ||
Comment on lines
+18
to
+30
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Remove duplicate translation keys and improve consistency. There are several issues with the translations:
Suggested fixes:
{
"MENU": {
"SERVER": "Сървър",
- "APP_ABOUT": "относно",
- "APP_QUIT": "Откажете се",
// ... other MENU translations
},
"MENU_APP": {
"APP_ABOUT": "Относно",
"APP_QUIT": "Изход",
// ... rest of MENU_APP translations
}
}
|
||
}, | ||
"FORM": { | ||
"FIELDS": { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
export type Channels = 'setting-page' | 'ipc-renderer' | 'language-set' | 'updater-page' | 'server-page' | 'theme-change' | 'current-theme'; | ||
export type Channels = 'setting-page' | 'ipc-renderer' | 'language-set' | 'updater-page' | 'server-page' | 'theme-change' | 'current-theme' | 'current-language'; |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,15 @@ | ||||||
import { MenuItemConstructorOptions } from 'electron'; | ||||||
export interface AppMenu { | ||||||
id?: string; | ||||||
label: string; // Menu label | ||||||
submenu?: (AppMenu | ElectronMenuItem)[]; // Nested menus or Electron menu items | ||||||
role?: 'appMenu' | 'fileMenu' | 'editMenu' | 'viewMenu' | 'windowMenu' | 'help'; // Predefined menu roles | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 💡 Codebase verification Menu roles defined in interface are not utilized in implementation The interface
Consider either:
🔗 Analysis chainVerify menu role support in the application. Let's verify that all specified menu roles are actually supported in the implementation. Let me try a different search strategy to verify the menu roles usage. Let me check the menu builder implementation to complete the verification. 🏁 Scripts executedThe following scripts were executed for the analysis: Script: #!/bin/bash
# Search for usage of menu roles in the codebase
echo "Searching for menu role usage..."
rg -t typescript "role: ['\"](?:appMenu|fileMenu|editMenu|viewMenu|windowMenu|help)['\"]" ./apps/server-web/src/
# Search for MenuBuilder implementation
echo "Checking MenuBuilder implementation..."
ast-grep --pattern 'class MenuBuilder {
$$$
buildMenu() {
$$$
}
$$$
}'
Length of output: 400 Script: #!/bin/bash
# Search for any mentions of these menu roles in the codebase
echo "Searching for menu role mentions..."
rg "appMenu|fileMenu|editMenu|viewMenu|windowMenu" ./apps/server-web/src/
# Look for menu-related files
echo "Looking for menu-related files..."
fd -t f menu ./apps/server-web/src/
# Check the content of the interface file
echo "Checking interface file content..."
cat ./apps/server-web/src/main/helpers/interfaces/i-menu.ts
Length of output: 2074 Script: #!/bin/bash
# Check the menu builder implementation
echo "Checking menu builder implementation..."
cat ./apps/server-web/src/main/menu.ts
# Search for any usage of these roles in the menu builder
echo "Searching for role usage in menu builder..."
rg "role.*:|\.role\s*=" ./apps/server-web/src/main/menu.ts
Length of output: 4491 |
||||||
type?: 'normal' | 'separator' | 'submenu' | 'checkbox' | 'radio'; // Menu item type | ||||||
click?: () => void; // Click handler for the menu item | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Add event parameter to click handler. The click handler should include the event parameter for consistency with Electron's API. - click?: () => void; // Click handler for the menu item
+ click?: (event: Electron.KeyboardEvent) => void; // Click handler for the menu item 📝 Committable suggestion
Suggested change
|
||||||
accelerator?: string; // Keyboard shortcut | ||||||
enabled?: boolean; // Whether the item is enabled | ||||||
visible?: boolean; // Whether the item is visible | ||||||
checked?: boolean; // For 'checkbox' or 'radio' type | ||||||
} | ||||||
|
||||||
export type ElectronMenuItem = MenuItemConstructorOptions; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
export * from './i-server'; | ||
export * from './i-desktop-dialog'; | ||
export * from './i-constant'; | ||
export * from './i-menu'; |
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -1,7 +1,7 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import Store from 'electron-store'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import { WebServer } from '../../interfaces'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import { WebServer, ServerConfig } from '../../interfaces'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const store = new Store(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const DEFAULT_CONFIG:any = { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const DEFAULT_CONFIG:WebServer = { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
server: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
PORT: 3002, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
GAUZY_API_SERVER_URL: 'http://localhost:3000', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -11,7 +11,7 @@ const DEFAULT_CONFIG:any = { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
general: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
lang: 'en', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
autoUpdate: true, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
updateCheckPeriode: '1140' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
updateCheckPeriod: '1140' // Time in minutes | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
export const LocalStore = { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -35,17 +35,41 @@ export const LocalStore = { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
deepMerge<T>(target: T, source: Partial<T>): T { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const result: T = { ...target }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Object.keys(source).forEach(key => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const value = source[key as keyof T]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (value && typeof value === 'object') { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
result[key as keyof T] = this.deepMerge( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
target[key as keyof T], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
value as any | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} else if (value !== undefined) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
result[key as keyof T] = value as any; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return result; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+38
to
+52
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Ensure the The Consider modifying the method to correctly handle arrays. For example: - if (value && typeof value === 'object') {
+ if (value && typeof value === 'object' && !Array.isArray(value)) { This change prevents recursive merging of arrays, allowing you to decide whether to replace or concatenate arrays based on your requirements. 📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
setDefaultServerConfig: () => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const defaultConfig: WebServer | any = store.get('config') || {}; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Object.keys(DEFAULT_CONFIG).forEach((key) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Object.keys(DEFAULT_CONFIG[key]).forEach((keySub) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
defaultConfig[key] = defaultConfig[key] || {}; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
defaultConfig[key][keySub] = defaultConfig[key][keySub] || DEFAULT_CONFIG[key][keySub]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
store.set({ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
config: defaultConfig | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
validateConfig(config: WebServer): void { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const required = ['PORT', 'GAUZY_API_SERVER_URL']; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
required.forEach(field => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (!config || !config.server || !config?.server[field as keyof ServerConfig]) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
throw new Error(`Missing required field: ${field}`); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
setDefaultServerConfig() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
try { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const storedConfig = store.get('config') as Partial<WebServer> || {}; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const mergedConfig = this.deepMerge<WebServer>(DEFAULT_CONFIG, storedConfig) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
this.validateConfig(mergedConfig || {}); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
store.set({ config: mergedConfig }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} catch (error) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
console.error('Failed to set default configuration:', error); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
store.set({ config: DEFAULT_CONFIG }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Enhance error handling and consider parallel operations.
The current implementation has room for improvement in terms of performance and error handling:
Here's a suggested improvement: