solforge 0.2.4 → 0.2.5
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/README.md +471 -79
- package/cli.cjs +106 -78
- package/package.json +1 -1
- package/scripts/install.sh +1 -1
- package/scripts/postinstall.cjs +66 -58
- package/server/methods/program/get-token-accounts-by-owner.ts +7 -2
- package/server/ws-server.ts +4 -1
- package/src/api-server-entry.ts +91 -91
- package/src/cli/commands/rpc-start.ts +4 -1
- package/src/cli/main.ts +7 -3
- package/src/cli/run-solforge.ts +20 -6
- package/src/commands/add-program.ts +324 -328
- package/src/commands/init.ts +106 -106
- package/src/commands/list.ts +125 -125
- package/src/commands/mint.ts +246 -246
- package/src/commands/start.ts +834 -831
- package/src/commands/status.ts +80 -80
- package/src/commands/stop.ts +381 -382
- package/src/config/manager.ts +149 -149
- package/src/gui/public/app.css +1556 -1
- package/src/gui/public/build/main.css +1569 -1
- package/src/gui/server.ts +20 -21
- package/src/gui/src/app.tsx +56 -37
- package/src/gui/src/components/airdrop-mint-form.tsx +17 -11
- package/src/gui/src/components/clone-program-modal.tsx +6 -6
- package/src/gui/src/components/clone-token-modal.tsx +7 -7
- package/src/gui/src/components/modal.tsx +13 -11
- package/src/gui/src/components/programs-panel.tsx +27 -15
- package/src/gui/src/components/status-panel.tsx +31 -17
- package/src/gui/src/components/tokens-panel.tsx +25 -19
- package/src/gui/src/index.css +491 -463
- package/src/index.ts +161 -146
- package/src/rpc/start.ts +1 -1
- package/src/services/api-server.ts +470 -473
- package/src/services/port-manager.ts +167 -167
- package/src/services/process-registry.ts +143 -143
- package/src/services/program-cloner.ts +312 -312
- package/src/services/token-cloner.ts +799 -797
- package/src/services/validator.ts +288 -288
- package/src/types/config.ts +71 -71
- package/src/utils/shell.ts +75 -75
- package/src/utils/token-loader.ts +77 -77
package/src/config/manager.ts
CHANGED
|
@@ -1,156 +1,156 @@
|
|
|
1
|
-
import { readFileSync, writeFileSync
|
|
1
|
+
import { existsSync, readFileSync, writeFileSync } from "fs";
|
|
2
2
|
import { join, resolve } from "path";
|
|
3
|
-
import { ConfigSchema } from "../types/config.js";
|
|
4
3
|
import type { Config, ValidationResult } from "../types/config.js";
|
|
4
|
+
import { ConfigSchema } from "../types/config.js";
|
|
5
5
|
|
|
6
6
|
export class ConfigManager {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
7
|
+
private config: Config | null = null;
|
|
8
|
+
private configPath: string | null = null;
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Load configuration from a file path
|
|
12
|
+
*/
|
|
13
|
+
async load(configPath: string): Promise<Config> {
|
|
14
|
+
try {
|
|
15
|
+
const fullPath = resolve(configPath);
|
|
16
|
+
|
|
17
|
+
if (!existsSync(fullPath)) {
|
|
18
|
+
throw new Error(`Configuration file not found: ${fullPath}`);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const configContent = readFileSync(fullPath, "utf-8");
|
|
22
|
+
const rawConfig = JSON.parse(configContent);
|
|
23
|
+
|
|
24
|
+
// Validate and parse with Zod
|
|
25
|
+
const result = ConfigSchema.safeParse(rawConfig);
|
|
26
|
+
|
|
27
|
+
if (!result.success) {
|
|
28
|
+
const errors = result.error.issues.map((issue) => ({
|
|
29
|
+
path: issue.path.join("."),
|
|
30
|
+
message: issue.message,
|
|
31
|
+
}));
|
|
32
|
+
throw new Error(
|
|
33
|
+
`Configuration validation failed:\n${errors
|
|
34
|
+
.map((e) => ` - ${e.path}: ${e.message}`)
|
|
35
|
+
.join("\n")}`,
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
this.config = result.data;
|
|
40
|
+
this.configPath = fullPath;
|
|
41
|
+
|
|
42
|
+
return this.config;
|
|
43
|
+
} catch (error) {
|
|
44
|
+
if (error instanceof SyntaxError) {
|
|
45
|
+
throw new Error(`Invalid JSON in configuration file: ${error.message}`);
|
|
46
|
+
}
|
|
47
|
+
throw error;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Save current configuration to file
|
|
53
|
+
*/
|
|
54
|
+
async save(configPath?: string): Promise<void> {
|
|
55
|
+
if (!this.config) {
|
|
56
|
+
throw new Error("No configuration loaded");
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const targetPath = configPath || this.configPath;
|
|
60
|
+
if (!targetPath) {
|
|
61
|
+
throw new Error("No configuration path specified");
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
try {
|
|
65
|
+
const configContent = JSON.stringify(this.config, null, 2);
|
|
66
|
+
writeFileSync(targetPath, configContent, "utf-8");
|
|
67
|
+
this.configPath = targetPath;
|
|
68
|
+
} catch (error) {
|
|
69
|
+
throw new Error(
|
|
70
|
+
`Failed to save configuration: ${
|
|
71
|
+
error instanceof Error ? error.message : String(error)
|
|
72
|
+
}`,
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Validate a configuration object
|
|
79
|
+
*/
|
|
80
|
+
validate(config: any): ValidationResult {
|
|
81
|
+
const result = ConfigSchema.safeParse(config);
|
|
82
|
+
|
|
83
|
+
if (result.success) {
|
|
84
|
+
return { valid: true, errors: [] };
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const errors = result.error.issues.map((issue) => ({
|
|
88
|
+
path: issue.path.join("."),
|
|
89
|
+
message: issue.message,
|
|
90
|
+
}));
|
|
91
|
+
|
|
92
|
+
return { valid: false, errors };
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Create a default configuration
|
|
97
|
+
*/
|
|
98
|
+
createDefault(): Config {
|
|
99
|
+
const defaultConfig = ConfigSchema.parse({});
|
|
100
|
+
this.config = defaultConfig;
|
|
101
|
+
return defaultConfig;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Get current configuration
|
|
106
|
+
*/
|
|
107
|
+
getConfig(): Config {
|
|
108
|
+
if (!this.config) {
|
|
109
|
+
throw new Error("No configuration loaded. Call load() first.");
|
|
110
|
+
}
|
|
111
|
+
return this.config;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Update configuration
|
|
116
|
+
*/
|
|
117
|
+
updateConfig(updates: Partial<Config>): Config {
|
|
118
|
+
if (!this.config) {
|
|
119
|
+
throw new Error("No configuration loaded. Call load() first.");
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const updated = { ...this.config, ...updates };
|
|
123
|
+
const result = ConfigSchema.safeParse(updated);
|
|
124
|
+
|
|
125
|
+
if (!result.success) {
|
|
126
|
+
const errors = result.error.issues.map((issue) => ({
|
|
127
|
+
path: issue.path.join("."),
|
|
128
|
+
message: issue.message,
|
|
129
|
+
}));
|
|
130
|
+
throw new Error(
|
|
131
|
+
`Configuration update validation failed:\n${errors
|
|
132
|
+
.map((e) => ` - ${e.path}: ${e.message}`)
|
|
133
|
+
.join("\n")}`,
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
this.config = result.data;
|
|
138
|
+
return this.config;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Get configuration file path
|
|
143
|
+
*/
|
|
144
|
+
getConfigPath(): string | null {
|
|
145
|
+
return this.configPath;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Check if configuration is loaded
|
|
150
|
+
*/
|
|
151
|
+
isLoaded(): boolean {
|
|
152
|
+
return this.config !== null;
|
|
153
|
+
}
|
|
154
154
|
}
|
|
155
155
|
|
|
156
156
|
// Singleton instance
|