imcp 0.0.13 → 0.0.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/dist/core/installers/clients/ClientInstaller.js +58 -40
- package/dist/core/onboard/FeedOnboardService.d.ts +35 -0
- package/dist/core/onboard/FeedOnboardService.js +137 -0
- package/dist/core/types.d.ts +2 -1
- package/dist/core/validators/FeedValidator.d.ts +13 -0
- package/dist/core/validators/FeedValidator.js +27 -0
- package/dist/web/contract/serverContract.d.ts +64 -0
- package/dist/web/contract/serverContract.js +2 -0
- package/dist/web/public/css/onboard.css +44 -0
- package/dist/web/public/index.html +17 -13
- package/dist/web/public/js/modal/index.js +58 -0
- package/dist/web/public/js/modal/installHandler.js +227 -0
- package/dist/web/public/js/modal/installModal.js +163 -0
- package/dist/web/public/js/modal/installation.js +281 -0
- package/dist/web/public/js/modal/loadingModal.js +52 -0
- package/dist/web/public/js/modal/loadingUI.js +74 -0
- package/dist/web/public/js/modal/messageQueue.js +112 -0
- package/dist/web/public/js/modal/modalSetup.js +512 -0
- package/dist/web/public/js/modal/modalUI.js +214 -0
- package/dist/web/public/js/modal/modalUtils.js +49 -0
- package/dist/web/public/js/modal/version.js +20 -0
- package/dist/web/public/js/modal/versionUtils.js +20 -0
- package/dist/web/public/js/modal.js +25 -1041
- package/dist/web/public/js/onboard/formProcessor.js +309 -0
- package/dist/web/public/js/onboard/index.js +131 -0
- package/dist/web/public/js/onboard/state.js +32 -0
- package/dist/web/public/js/onboard/templates.js +375 -0
- package/dist/web/public/js/onboard/uiHandlers.js +196 -0
- package/dist/web/public/js/serverCategoryDetails.js +43 -17
- package/dist/web/public/onboard.html +150 -0
- package/package.json +1 -1
- package/src/core/installers/clients/ClientInstaller.ts +66 -49
- package/src/core/types.ts +2 -1
- package/src/web/public/index.html +17 -13
- package/src/web/public/js/modal/index.js +58 -0
- package/src/web/public/js/modal/installModal.js +163 -0
- package/src/web/public/js/modal/installation.js +281 -0
- package/src/web/public/js/modal/loadingModal.js +52 -0
- package/src/web/public/js/modal/messageQueue.js +112 -0
- package/src/web/public/js/modal/modalSetup.js +512 -0
- package/src/web/public/js/modal/modalUtils.js +49 -0
- package/src/web/public/js/modal/versionUtils.js +20 -0
- package/src/web/public/js/modal.js +25 -1041
- package/src/web/public/js/serverCategoryDetails.js +43 -17
|
@@ -276,6 +276,7 @@ export class ClientInstaller {
|
|
|
276
276
|
// --- Start of new logic ---
|
|
277
277
|
// Clone the base installation configuration to avoid modifying the original serverConfig
|
|
278
278
|
const installConfig = JSON.parse(JSON.stringify(serverConfig.installation));
|
|
279
|
+
installConfig.mode = serverConfig.mode;
|
|
279
280
|
const pythonEnv = options.settings?.pythonEnv;
|
|
280
281
|
let pythonDir = null;
|
|
281
282
|
// 1. Determine which args to use and resolve npm paths
|
|
@@ -499,39 +500,48 @@ export class ClientInstaller {
|
|
|
499
500
|
if (!settings.mcpServers) {
|
|
500
501
|
settings.mcpServers = {};
|
|
501
502
|
}
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
serverConfigForClient.env
|
|
503
|
+
if (installConfig.mode === 'stdio') {
|
|
504
|
+
// Special handling for Windows when command is npx for Cline and MSROO clients
|
|
505
|
+
// Use a copy to avoid modifying the passed installConfig directly if needed elsewhere
|
|
506
|
+
const serverConfigForClient = { ...installConfig };
|
|
507
|
+
if (process.platform === 'win32' &&
|
|
508
|
+
serverConfigForClient.command === 'npx' &&
|
|
509
|
+
(clientName === 'Cline' || clientName === 'MSRooCode' || clientName === 'MSROO')) {
|
|
510
|
+
// Update command to cmd
|
|
511
|
+
serverConfigForClient.command = 'cmd';
|
|
512
|
+
// Add /c and npx at the beginning of args
|
|
513
|
+
serverConfigForClient.args = ['/c', 'npx', ...serverConfigForClient.args];
|
|
514
|
+
// Add APPDATA environment variable pointing to npm directory
|
|
515
|
+
if (!serverConfigForClient.env) {
|
|
516
|
+
serverConfigForClient.env = {};
|
|
517
|
+
}
|
|
518
|
+
// Dynamically get npm path and set APPDATA to it
|
|
519
|
+
const npmPath = await this.getNpmPath();
|
|
520
|
+
serverConfigForClient.env['APPDATA'] = npmPath;
|
|
521
|
+
Logger.debug(`Windows npx fix: command=${serverConfigForClient.command}, args=${serverConfigForClient.args.join(' ')}, env=${JSON.stringify(serverConfigForClient.env)}`);
|
|
522
|
+
}
|
|
523
|
+
// Convert backslashes to forward slashes in args paths
|
|
524
|
+
if (serverConfigForClient.args) {
|
|
525
|
+
serverConfigForClient.args = serverConfigForClient.args.map((arg) => typeof arg === 'string' ? arg.replace(/\\/g, '/') : arg);
|
|
515
526
|
}
|
|
516
|
-
//
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
527
|
+
// Add or update the server configuration
|
|
528
|
+
settings.mcpServers[serverName] = {
|
|
529
|
+
command: serverConfigForClient.command,
|
|
530
|
+
args: serverConfigForClient.args,
|
|
531
|
+
env: serverConfigForClient.env,
|
|
532
|
+
autoApprove: [],
|
|
533
|
+
disabled: false,
|
|
534
|
+
alwaysAllow: []
|
|
535
|
+
};
|
|
536
|
+
Logger.debug(`Updating ${settingPath} for ${serverName}: ${JSON.stringify(settings.mcpServers[serverName])}`);
|
|
520
537
|
}
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
538
|
+
else if (installConfig.mode === 'sse') {
|
|
539
|
+
// Handle SSE mode for Cline and MSRoo clients
|
|
540
|
+
settings.mcpServers[serverName] = {
|
|
541
|
+
type: 'sse',
|
|
542
|
+
url: installConfig.url
|
|
543
|
+
};
|
|
524
544
|
}
|
|
525
|
-
// Add or update the server configuration
|
|
526
|
-
settings.mcpServers[serverName] = {
|
|
527
|
-
command: serverConfigForClient.command,
|
|
528
|
-
args: serverConfigForClient.args,
|
|
529
|
-
env: serverConfigForClient.env,
|
|
530
|
-
autoApprove: [],
|
|
531
|
-
disabled: false,
|
|
532
|
-
alwaysAllow: []
|
|
533
|
-
};
|
|
534
|
-
Logger.debug(`Updating ${settingPath} for ${serverName}: ${JSON.stringify(settings.mcpServers[serverName])}`);
|
|
535
545
|
// Write the updated settings back to the file
|
|
536
546
|
await writeJsonFile(settingPath, settings);
|
|
537
547
|
}
|
|
@@ -551,17 +561,25 @@ export class ClientInstaller {
|
|
|
551
561
|
}
|
|
552
562
|
// Use a copy to avoid modifying the passed installConfig directly
|
|
553
563
|
const serverConfigForClient = { ...installConfig };
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
564
|
+
if (installConfig.mode === 'stdio') {
|
|
565
|
+
if (serverConfigForClient.args) {
|
|
566
|
+
serverConfigForClient.args = serverConfigForClient.args.map((arg) => typeof arg === 'string' ? arg.replace(/\\/g, '/') : arg);
|
|
567
|
+
}
|
|
568
|
+
// Add or update the server configuration
|
|
569
|
+
settings.mcp.servers[serverName] = {
|
|
570
|
+
command: serverConfigForClient.command,
|
|
571
|
+
args: serverConfigForClient.args,
|
|
572
|
+
env: serverConfigForClient.env
|
|
573
|
+
};
|
|
574
|
+
Logger.debug(`Updating ${settingPath} for ${serverName}: ${JSON.stringify(settings.mcp.servers[serverName])}`);
|
|
575
|
+
}
|
|
576
|
+
else if (installConfig.mode === 'sse') {
|
|
577
|
+
// Handle SSE mode for Github Copilot
|
|
578
|
+
settings.mcp.servers[serverName] = {
|
|
579
|
+
type: 'sse',
|
|
580
|
+
url: installConfig.url
|
|
581
|
+
};
|
|
557
582
|
}
|
|
558
|
-
// Add or update the server configuration
|
|
559
|
-
settings.mcp.servers[serverName] = {
|
|
560
|
-
command: serverConfigForClient.command,
|
|
561
|
-
args: serverConfigForClient.args,
|
|
562
|
-
env: serverConfigForClient.env
|
|
563
|
-
};
|
|
564
|
-
Logger.debug(`Updating ${settingPath} for ${serverName}: ${JSON.stringify(settings.mcp.servers[serverName])}`);
|
|
565
583
|
// Write the updated settings back to the file
|
|
566
584
|
await writeJsonFile(settingPath, settings);
|
|
567
585
|
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { FeedConfiguration } from '../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Service for handling feed onboarding operations
|
|
4
|
+
*/
|
|
5
|
+
export declare class FeedOnboardService {
|
|
6
|
+
private tempDir;
|
|
7
|
+
private repoDir;
|
|
8
|
+
constructor();
|
|
9
|
+
/**
|
|
10
|
+
* Onboard a new feed configuration
|
|
11
|
+
* @param config Feed configuration to onboard
|
|
12
|
+
*/
|
|
13
|
+
onboardFeed(config: FeedConfiguration): Promise<void>;
|
|
14
|
+
/**
|
|
15
|
+
* Fork the repository using gh CLI
|
|
16
|
+
*/
|
|
17
|
+
private forkRepo;
|
|
18
|
+
/**
|
|
19
|
+
* Clone the forked repository
|
|
20
|
+
*/
|
|
21
|
+
private cloneRepo;
|
|
22
|
+
/**
|
|
23
|
+
* Get GitHub username using gh CLI
|
|
24
|
+
*/
|
|
25
|
+
private getGitHubUsername;
|
|
26
|
+
/**
|
|
27
|
+
* Save feed configuration to file
|
|
28
|
+
*/
|
|
29
|
+
private saveFeedConfig;
|
|
30
|
+
/**
|
|
31
|
+
* Create pull request using gh CLI
|
|
32
|
+
*/
|
|
33
|
+
private createPullRequest;
|
|
34
|
+
}
|
|
35
|
+
export declare const feedOnboardService: FeedOnboardService;
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import { exec } from 'child_process';
|
|
2
|
+
import { promisify } from 'util';
|
|
3
|
+
import fs from 'fs/promises';
|
|
4
|
+
import path from 'path';
|
|
5
|
+
import { GITHUB_REPO, SETTINGS_DIR } from '../constants.js';
|
|
6
|
+
import { feedValidator } from '../validators/FeedValidator.js';
|
|
7
|
+
import { Logger } from '../../utils/logger.js';
|
|
8
|
+
const execAsync = promisify(exec);
|
|
9
|
+
/**
|
|
10
|
+
* Service for handling feed onboarding operations
|
|
11
|
+
*/
|
|
12
|
+
export class FeedOnboardService {
|
|
13
|
+
tempDir;
|
|
14
|
+
repoDir;
|
|
15
|
+
constructor() {
|
|
16
|
+
this.tempDir = path.join(SETTINGS_DIR, 'temp');
|
|
17
|
+
this.repoDir = path.join(this.tempDir, 'imcp-feed');
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Onboard a new feed configuration
|
|
21
|
+
* @param config Feed configuration to onboard
|
|
22
|
+
*/
|
|
23
|
+
async onboardFeed(config) {
|
|
24
|
+
try {
|
|
25
|
+
// Validate feed configuration
|
|
26
|
+
feedValidator.validate(config);
|
|
27
|
+
// Create temp directory
|
|
28
|
+
await fs.mkdir(this.tempDir, { recursive: true });
|
|
29
|
+
// Fork the repo
|
|
30
|
+
await this.forkRepo();
|
|
31
|
+
// Clone the forked repo
|
|
32
|
+
await this.cloneRepo();
|
|
33
|
+
// Save feed configuration
|
|
34
|
+
await this.saveFeedConfig(config);
|
|
35
|
+
// Create branch, push changes and create PR
|
|
36
|
+
await this.createPullRequest(config);
|
|
37
|
+
Logger.log(`Successfully onboarded feed: ${config.name}`);
|
|
38
|
+
}
|
|
39
|
+
catch (error) {
|
|
40
|
+
Logger.error('Feed onboarding failed:', error);
|
|
41
|
+
throw error;
|
|
42
|
+
}
|
|
43
|
+
finally {
|
|
44
|
+
// Cleanup temp directory
|
|
45
|
+
await fs.rm(this.tempDir, { recursive: true, force: true });
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Fork the repository using gh CLI
|
|
50
|
+
*/
|
|
51
|
+
async forkRepo() {
|
|
52
|
+
try {
|
|
53
|
+
await execAsync(`gh repo fork ${GITHUB_REPO.repoName} --clone=false`);
|
|
54
|
+
Logger.debug('Successfully forked repository');
|
|
55
|
+
}
|
|
56
|
+
catch (error) {
|
|
57
|
+
throw new Error(`Failed to fork repository: ${error instanceof Error ? error.message : String(error)}`);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Clone the forked repository
|
|
62
|
+
*/
|
|
63
|
+
async cloneRepo() {
|
|
64
|
+
try {
|
|
65
|
+
// Clean up existing repo directory
|
|
66
|
+
await fs.rm(this.repoDir, { recursive: true, force: true });
|
|
67
|
+
const username = await this.getGitHubUsername();
|
|
68
|
+
const repoUrl = `https://github.com/${username}/${GITHUB_REPO.repoName.split('/')[1]}.git`;
|
|
69
|
+
// Ensure temp dir exists
|
|
70
|
+
await fs.mkdir(this.tempDir, { recursive: true });
|
|
71
|
+
// Clone the repo into imcp-feed subdirectory
|
|
72
|
+
await execAsync(`git clone ${repoUrl} ${this.repoDir}`);
|
|
73
|
+
Logger.debug('Successfully cloned repository');
|
|
74
|
+
}
|
|
75
|
+
catch (error) {
|
|
76
|
+
throw new Error(`Failed to clone repository: ${error instanceof Error ? error.message : String(error)}`);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Get GitHub username using gh CLI
|
|
81
|
+
*/
|
|
82
|
+
async getGitHubUsername() {
|
|
83
|
+
try {
|
|
84
|
+
const { stdout } = await execAsync('gh api user -q .login');
|
|
85
|
+
return stdout.trim();
|
|
86
|
+
}
|
|
87
|
+
catch (error) {
|
|
88
|
+
throw new Error(`Failed to get GitHub username: ${error instanceof Error ? error.message : String(error)}`);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Save feed configuration to file
|
|
93
|
+
*/
|
|
94
|
+
async saveFeedConfig(config) {
|
|
95
|
+
try {
|
|
96
|
+
const feedsDir = path.join(this.repoDir, GITHUB_REPO.feedsPath);
|
|
97
|
+
await fs.mkdir(feedsDir, { recursive: true });
|
|
98
|
+
const configPath = path.join(feedsDir, `${config.name}.json`);
|
|
99
|
+
await fs.writeFile(configPath, JSON.stringify(config, null, 2));
|
|
100
|
+
Logger.debug(`Saved feed configuration to ${configPath}`);
|
|
101
|
+
}
|
|
102
|
+
catch (error) {
|
|
103
|
+
throw new Error(`Failed to save feed configuration: ${error instanceof Error ? error.message : String(error)}`);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Create pull request using gh CLI
|
|
108
|
+
*/
|
|
109
|
+
async createPullRequest(config) {
|
|
110
|
+
try {
|
|
111
|
+
process.chdir(this.repoDir);
|
|
112
|
+
// Ensure we're up to date with upstream main
|
|
113
|
+
await execAsync(`git remote add upstream ${GITHUB_REPO.url}`);
|
|
114
|
+
await execAsync('git fetch upstream');
|
|
115
|
+
await execAsync('git reset --hard upstream/main');
|
|
116
|
+
// Create and checkout new branch
|
|
117
|
+
const branchName = `feed/${config.name}`;
|
|
118
|
+
await execAsync(`git checkout -b ${branchName}`);
|
|
119
|
+
// Stage and commit changes
|
|
120
|
+
await execAsync('git add .');
|
|
121
|
+
await execAsync(`git commit -m "Add feed configuration for ${config.name}"`);
|
|
122
|
+
// Push to origin
|
|
123
|
+
await execAsync(`git push -f origin ${branchName}`);
|
|
124
|
+
const title = `Add feed configuration for ${config.name}`;
|
|
125
|
+
const body = `Add new feed configuration:\n\n- Name: ${config.name}\n- Display Name: ${config.displayName}\n- Description: ${config.description}`;
|
|
126
|
+
const username = await this.getGitHubUsername();
|
|
127
|
+
await execAsync(`gh pr create --title "${title}" --body "${body}" --repo ${GITHUB_REPO.repoName} --base main --head ${username}:${branchName}`);
|
|
128
|
+
Logger.debug('Successfully created pull request');
|
|
129
|
+
}
|
|
130
|
+
catch (error) {
|
|
131
|
+
throw new Error(`Failed to create pull request: ${error instanceof Error ? error.message : String(error)}`);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
// Export singleton instance
|
|
136
|
+
export const feedOnboardService = new FeedOnboardService();
|
|
137
|
+
//# sourceMappingURL=FeedOnboardService.js.map
|
package/dist/core/types.d.ts
CHANGED
|
@@ -85,6 +85,7 @@ export interface InstallationConfig {
|
|
|
85
85
|
command: string;
|
|
86
86
|
args: string[];
|
|
87
87
|
env?: Record<string, EnvVariableConfig>;
|
|
88
|
+
url?: string;
|
|
88
89
|
}
|
|
89
90
|
export interface DependencyConfig {
|
|
90
91
|
requirements?: Array<{
|
|
@@ -99,7 +100,7 @@ export interface DependencyConfig {
|
|
|
99
100
|
export interface McpConfig {
|
|
100
101
|
name: string;
|
|
101
102
|
description: string;
|
|
102
|
-
mode: 'stdio' | '
|
|
103
|
+
mode: 'stdio' | 'sse';
|
|
103
104
|
dependencies?: DependencyConfig;
|
|
104
105
|
schemas?: string;
|
|
105
106
|
repository?: string;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { FeedConfiguration } from "../types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Validates feed configurations to ensure they meet required criteria
|
|
4
|
+
*/
|
|
5
|
+
export declare class FeedValidator {
|
|
6
|
+
/**
|
|
7
|
+
* Validates a feed configuration
|
|
8
|
+
* @param config The feed configuration to validate
|
|
9
|
+
* @returns true if valid, throws error if invalid
|
|
10
|
+
*/
|
|
11
|
+
validate(config: FeedConfiguration): boolean;
|
|
12
|
+
}
|
|
13
|
+
export declare const feedValidator: FeedValidator;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validates feed configurations to ensure they meet required criteria
|
|
3
|
+
*/
|
|
4
|
+
export class FeedValidator {
|
|
5
|
+
/**
|
|
6
|
+
* Validates a feed configuration
|
|
7
|
+
* @param config The feed configuration to validate
|
|
8
|
+
* @returns true if valid, throws error if invalid
|
|
9
|
+
*/
|
|
10
|
+
validate(config) {
|
|
11
|
+
try {
|
|
12
|
+
// For now return true as requested
|
|
13
|
+
return true;
|
|
14
|
+
// TODO: Implement full validation logic:
|
|
15
|
+
// - Required fields (name, displayName, etc)
|
|
16
|
+
// - Server configuration validation
|
|
17
|
+
// - Requirements validation
|
|
18
|
+
// - Repository validation
|
|
19
|
+
}
|
|
20
|
+
catch (error) {
|
|
21
|
+
throw new Error(`Feed validation failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
// Export singleton instance
|
|
26
|
+
export const feedValidator = new FeedValidator();
|
|
27
|
+
//# sourceMappingURL=FeedValidator.js.map
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { DependencyConfig, RegistryConfig, ServerInstallOptions } from '../../core/types.js';
|
|
2
|
+
export interface OnboardServerConfig {
|
|
3
|
+
name: string;
|
|
4
|
+
description: string;
|
|
5
|
+
mode: 'stdio' | 'http';
|
|
6
|
+
schemas?: string;
|
|
7
|
+
dependencies?: DependencyConfig;
|
|
8
|
+
repository?: string;
|
|
9
|
+
installation: {
|
|
10
|
+
command: string;
|
|
11
|
+
args?: string[];
|
|
12
|
+
env?: Record<string, {
|
|
13
|
+
name: string;
|
|
14
|
+
default?: string;
|
|
15
|
+
required: boolean;
|
|
16
|
+
description?: string;
|
|
17
|
+
}>;
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
export type RequirementType = 'npm' | 'pip' | 'command' | 'extension' | 'other';
|
|
21
|
+
export interface OnboardRequirementConfig {
|
|
22
|
+
type: RequirementType;
|
|
23
|
+
name: string;
|
|
24
|
+
version: string;
|
|
25
|
+
alias?: string;
|
|
26
|
+
registry?: RegistryConfig;
|
|
27
|
+
}
|
|
28
|
+
export interface OnboardRequestBody {
|
|
29
|
+
categoryData: {
|
|
30
|
+
name: string;
|
|
31
|
+
displayName: string;
|
|
32
|
+
description?: string;
|
|
33
|
+
repository?: string;
|
|
34
|
+
requirements?: OnboardRequirementConfig[];
|
|
35
|
+
mcpServers?: OnboardServerConfig[];
|
|
36
|
+
};
|
|
37
|
+
isUpdate: boolean;
|
|
38
|
+
}
|
|
39
|
+
export interface ListQueryParams {
|
|
40
|
+
local?: string;
|
|
41
|
+
}
|
|
42
|
+
export interface UpdateRequirementsRequestBody {
|
|
43
|
+
requirements: {
|
|
44
|
+
name: string;
|
|
45
|
+
updateVersion: string;
|
|
46
|
+
}[];
|
|
47
|
+
}
|
|
48
|
+
export interface InstallServersRequestBody {
|
|
49
|
+
serverList: Record<string, ServerInstallOptions>;
|
|
50
|
+
}
|
|
51
|
+
export interface UninstallServersRequestBody {
|
|
52
|
+
serverList: Record<string, {
|
|
53
|
+
removeData?: boolean;
|
|
54
|
+
}>;
|
|
55
|
+
options: {
|
|
56
|
+
targets: string[];
|
|
57
|
+
removeData?: boolean;
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
export interface ApiResponse<T> {
|
|
61
|
+
success: boolean;
|
|
62
|
+
data?: T;
|
|
63
|
+
error?: string;
|
|
64
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/* Onboarding form styles */
|
|
2
|
+
.requirement-item,
|
|
3
|
+
.server-item {
|
|
4
|
+
background-color: #ffffff;
|
|
5
|
+
transition: all 0.2s ease;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
.requirement-item:hover,
|
|
9
|
+
.server-item:hover {
|
|
10
|
+
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
.registry-config,
|
|
14
|
+
.installation-config,
|
|
15
|
+
.env-variables {
|
|
16
|
+
background-color: #f9fafb;
|
|
17
|
+
border-radius: 0.5rem;
|
|
18
|
+
padding: 1rem;
|
|
19
|
+
margin-top: 1rem;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.registry-github,
|
|
23
|
+
.registry-artifacts {
|
|
24
|
+
background-color: #ffffff;
|
|
25
|
+
border-radius: 0.5rem;
|
|
26
|
+
padding: 1rem;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/* Order field styling */
|
|
30
|
+
input[type="number"][name$=".order"] {
|
|
31
|
+
-moz-appearance: textfield;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
input[type="number"][name$=".order"]::-webkit-outer-spin-button,
|
|
35
|
+
input[type="number"][name$=".order"]::-webkit-inner-spin-button {
|
|
36
|
+
-webkit-appearance: none;
|
|
37
|
+
margin: 0;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
input[type="number"][name$=".order"]:focus {
|
|
41
|
+
border-color: #3b82f6;
|
|
42
|
+
outline: none;
|
|
43
|
+
box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.2);
|
|
44
|
+
}
|
|
@@ -162,19 +162,23 @@
|
|
|
162
162
|
setupSearch();
|
|
163
163
|
setupModalOutsideClick();
|
|
164
164
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
165
|
+
try {
|
|
166
|
+
// First fetch categories and wait for completion
|
|
167
|
+
await fetchServerCategories();
|
|
168
|
+
|
|
169
|
+
// Check URL parameters for category
|
|
170
|
+
const urlParams = new URLSearchParams(window.location.search);
|
|
171
|
+
const categoryParam = urlParams.get('category');
|
|
172
|
+
|
|
173
|
+
// If we have a category parameter or last selected category
|
|
174
|
+
const lastSelected = categoryParam || localStorage.getItem('lastSelectedCategory');
|
|
175
|
+
|
|
176
|
+
// Only show details after data is loaded
|
|
177
|
+
if (lastSelected) {
|
|
178
|
+
await showServerDetails(lastSelected);
|
|
179
|
+
}
|
|
180
|
+
} catch (error) {
|
|
181
|
+
console.error('Error during initialization:', error);
|
|
178
182
|
}
|
|
179
183
|
});
|
|
180
184
|
</script>
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
// Import all modal-related functionality
|
|
2
|
+
import { compareVersions } from './versionUtils.js';
|
|
3
|
+
import { delayedAppendInstallLoadingMessage } from './messageQueue.js';
|
|
4
|
+
import { showInstallLoadingModal, appendInstallLoadingMessage, hideInstallLoadingModal } from './loadingModal.js';
|
|
5
|
+
import { closeModal, setupModalOutsideClick } from './modalUtils.js';
|
|
6
|
+
import { handleBulkClientInstall, uninstallTools } from './installation.js';
|
|
7
|
+
import { showInstallModal } from './installModal.js';
|
|
8
|
+
import {
|
|
9
|
+
setupClientItems,
|
|
10
|
+
setupEnvironmentVariables,
|
|
11
|
+
setupInstallationArguments,
|
|
12
|
+
setupServerRequirements,
|
|
13
|
+
setupFormSubmitHandler
|
|
14
|
+
} from './modalSetup.js';
|
|
15
|
+
|
|
16
|
+
// Export all modal functionality
|
|
17
|
+
export {
|
|
18
|
+
// Version utilities
|
|
19
|
+
compareVersions,
|
|
20
|
+
|
|
21
|
+
// Message queue
|
|
22
|
+
delayedAppendInstallLoadingMessage,
|
|
23
|
+
|
|
24
|
+
// Loading modal
|
|
25
|
+
showInstallLoadingModal,
|
|
26
|
+
appendInstallLoadingMessage,
|
|
27
|
+
hideInstallLoadingModal,
|
|
28
|
+
|
|
29
|
+
// Modal utilities
|
|
30
|
+
closeModal,
|
|
31
|
+
setupModalOutsideClick,
|
|
32
|
+
|
|
33
|
+
// Installation
|
|
34
|
+
handleBulkClientInstall,
|
|
35
|
+
uninstallTools,
|
|
36
|
+
|
|
37
|
+
// Install modal
|
|
38
|
+
showInstallModal,
|
|
39
|
+
|
|
40
|
+
// Modal setup
|
|
41
|
+
setupClientItems,
|
|
42
|
+
setupEnvironmentVariables,
|
|
43
|
+
setupInstallationArguments,
|
|
44
|
+
setupServerRequirements,
|
|
45
|
+
setupFormSubmitHandler
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
// Initialize modal functionality
|
|
49
|
+
document.addEventListener('DOMContentLoaded', () => {
|
|
50
|
+
setupModalOutsideClick();
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
// Make certain functions available globally
|
|
54
|
+
window.showInstallModal = showInstallModal;
|
|
55
|
+
window.showInstallLoadingModal = showInstallLoadingModal;
|
|
56
|
+
window.appendInstallLoadingMessage = appendInstallLoadingMessage;
|
|
57
|
+
window.hideInstallLoadingModal = hideInstallLoadingModal;
|
|
58
|
+
window.uninstallTools = uninstallTools;
|