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.
Files changed (42) hide show
  1. package/README.md +471 -79
  2. package/cli.cjs +106 -78
  3. package/package.json +1 -1
  4. package/scripts/install.sh +1 -1
  5. package/scripts/postinstall.cjs +66 -58
  6. package/server/methods/program/get-token-accounts-by-owner.ts +7 -2
  7. package/server/ws-server.ts +4 -1
  8. package/src/api-server-entry.ts +91 -91
  9. package/src/cli/commands/rpc-start.ts +4 -1
  10. package/src/cli/main.ts +7 -3
  11. package/src/cli/run-solforge.ts +20 -6
  12. package/src/commands/add-program.ts +324 -328
  13. package/src/commands/init.ts +106 -106
  14. package/src/commands/list.ts +125 -125
  15. package/src/commands/mint.ts +246 -246
  16. package/src/commands/start.ts +834 -831
  17. package/src/commands/status.ts +80 -80
  18. package/src/commands/stop.ts +381 -382
  19. package/src/config/manager.ts +149 -149
  20. package/src/gui/public/app.css +1556 -1
  21. package/src/gui/public/build/main.css +1569 -1
  22. package/src/gui/server.ts +20 -21
  23. package/src/gui/src/app.tsx +56 -37
  24. package/src/gui/src/components/airdrop-mint-form.tsx +17 -11
  25. package/src/gui/src/components/clone-program-modal.tsx +6 -6
  26. package/src/gui/src/components/clone-token-modal.tsx +7 -7
  27. package/src/gui/src/components/modal.tsx +13 -11
  28. package/src/gui/src/components/programs-panel.tsx +27 -15
  29. package/src/gui/src/components/status-panel.tsx +31 -17
  30. package/src/gui/src/components/tokens-panel.tsx +25 -19
  31. package/src/gui/src/index.css +491 -463
  32. package/src/index.ts +161 -146
  33. package/src/rpc/start.ts +1 -1
  34. package/src/services/api-server.ts +470 -473
  35. package/src/services/port-manager.ts +167 -167
  36. package/src/services/process-registry.ts +143 -143
  37. package/src/services/program-cloner.ts +312 -312
  38. package/src/services/token-cloner.ts +799 -797
  39. package/src/services/validator.ts +288 -288
  40. package/src/types/config.ts +71 -71
  41. package/src/utils/shell.ts +75 -75
  42. package/src/utils/token-loader.ts +77 -77
@@ -1,156 +1,156 @@
1
- import { readFileSync, writeFileSync, existsSync } from "fs";
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
- 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
- }
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