@airmoney-degn/airmoney-cli 0.12.2 → 0.13.1

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/cli/serve.js CHANGED
@@ -1,123 +1,12 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
2
  Object.defineProperty(exports, "__esModule", { value: true });
6
3
  exports.serveCommand = serveCommand;
7
- const path_1 = __importDefault(require("path"));
8
- const open_1 = __importDefault(require("open"));
9
- // var cors = require('cors')
10
- // import * as cors from "cors"
11
- const cors_1 = __importDefault(require("cors"));
12
- const express_1 = __importDefault(require("express"));
13
- const express_ws_1 = __importDefault(require("express-ws"));
14
- const metadata_1 = require("../util/metadata");
15
- const server_1 = require("../util/server");
16
- const http_proxy_middleware_1 = require("http-proxy-middleware");
17
- const cryptoProcess_1 = require("../util/cryptoProcess");
18
- /**
19
- * Helper to get the path to the "public/simulator" folder
20
- * from the distributed code. We use __dirname, then move
21
- * up two levels to the project root, then into public/simulator.
22
- */
23
- function getSimulatorDir() {
24
- // after tsc compile, serve.js is in dist/cli/
25
- // we step up two dirs to get back to the project root
26
- // then go into public/simulator
27
- const base = path_1.default.resolve(__dirname, '..', '..');
28
- return path_1.default.join(base, 'public', 'simulator');
29
- }
4
+ const ServeOrchestrator_1 = require("../service/serve/ServeOrchestrator");
30
5
  async function serveCommand(noBrowser, locationFolder, appUrl) {
31
- const simulatorPort = 4041;
32
- const simulatorExpress = (0, express_ws_1.default)((0, express_1.default)()).app;
33
- simulatorExpress.use((0, cors_1.default)());
34
- simulatorExpress.use(express_1.default.json());
35
- let simulatorClient;
36
- simulatorExpress.ws('/ws', function (ws, req) {
37
- simulatorClient = ws;
38
- ws.on('message', function (msg) {
39
- console.log(msg);
40
- });
41
- console.log('socket', req.body);
42
- });
43
- const simulatorDir = getSimulatorDir();
44
- simulatorExpress.use('/simulator', express_1.default.static(simulatorDir));
45
- ////////////////////////////////////////////////////////////////
46
- let projectFolder = process.cwd();
47
- if (locationFolder != undefined) {
48
- projectFolder = path_1.default.join(process.cwd(), locationFolder);
49
- }
50
- const metadata = (0, metadata_1.loadMetadata)();
51
- if (!metadata) {
52
- console.log('[Warning] No metadata found. Skipping some possible checks.');
53
- }
54
- if (appUrl != undefined) {
55
- const proxyMiddleware = (0, http_proxy_middleware_1.createProxyMiddleware)({
56
- xfwd: true,
57
- target: appUrl,
58
- changeOrigin: true,
59
- pathFilter: '/',
60
- });
61
- simulatorExpress.use('/', proxyMiddleware);
62
- }
63
- else {
64
- simulatorExpress.use('/', express_1.default.static(projectFolder));
65
- }
66
- const simulatorServer = simulatorExpress.listen(simulatorPort, () => {
67
- const url = `http://localhost:${simulatorPort}/simulator`;
68
- console.log(`Starting simulator server at ${url}`);
69
- if (!noBrowser) {
70
- (0, open_1.default)(url)
71
- .then(() => {
72
- // success opening URL
73
- })
74
- .catch(err => {
75
- console.error('Failed to open web browser', err);
76
- });
77
- }
78
- });
79
- ////////////////////////////////////////////////////////////////
80
- const airmoneyServicePort = 4040;
81
- const airmoneyServiceExpress = (0, express_1.default)();
82
- airmoneyServiceExpress.use((0, cors_1.default)());
83
- airmoneyServiceExpress.use(express_1.default.json());
84
- airmoneyServiceExpress.post('/', async (req, res) => {
85
- let rpcReq = req.body;
86
- let event;
87
- let simulator = true;
88
- switch (rpcReq.method) {
89
- case 'setImage':
90
- case 'setAnimate':
91
- event = (0, server_1.displayImage)(rpcReq, metadata.name);
92
- break;
93
- }
94
- if (simulator) {
95
- if (event != null) {
96
- if (simulatorClient) {
97
- simulatorClient.send(JSON.stringify(event));
98
- res.status(200).json({ success: true });
99
- return;
100
- }
101
- else {
102
- console.log('Warning: No simulator client connected');
103
- res.status(503).json({ error: 'Simulator not connected' });
104
- return;
105
- }
106
- }
107
- else {
108
- res.status(500).json({ error: 'Failed to process request' });
109
- return;
110
- }
111
- }
112
- else {
113
- res.json({ jsonrpc: '2.0', result: event, id: 1 });
114
- return;
115
- }
116
- });
117
- const airmoneyServiceServer = airmoneyServiceExpress.listen(airmoneyServicePort, () => {
118
- const url = `http://localhost:${airmoneyServicePort}`;
119
- console.log(`Starting airmoney service server at ${url}`);
6
+ const orchestrator = new ServeOrchestrator_1.ServeOrchestrator({
7
+ noBrowser,
8
+ locationFolder,
9
+ appUrl,
120
10
  });
121
- ////////////////////////////////////////////////////////////////
122
- (0, cryptoProcess_1.startCryptoServiceSimple)();
11
+ await orchestrator.start();
123
12
  }
package/dist/config.json CHANGED
@@ -1,3 +1,3 @@
1
1
  {
2
- "version": "0.12.2"
2
+ "version": "0.13.1"
3
3
  }
@@ -0,0 +1,83 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.AirmoneyService = void 0;
7
+ const express_1 = __importDefault(require("express"));
8
+ const cors_1 = __importDefault(require("cors"));
9
+ const server_1 = require("../../util/server");
10
+ class AirmoneyService {
11
+ constructor(config) {
12
+ this.simulatorClient = null;
13
+ this.config = config;
14
+ this.app = (0, express_1.default)();
15
+ this.setupMiddleware();
16
+ this.setupRoutes();
17
+ }
18
+ setupMiddleware() {
19
+ this.app.use((0, cors_1.default)());
20
+ this.app.use(express_1.default.json());
21
+ }
22
+ setupRoutes() {
23
+ this.app.post('/', this.handleRpcRequest.bind(this));
24
+ }
25
+ async handleRpcRequest(req, res) {
26
+ const rpcReq = req.body;
27
+ let event;
28
+ const simulator = true;
29
+ switch (rpcReq.method) {
30
+ case 'setImage':
31
+ case 'setAnimate':
32
+ event = (0, server_1.displayImage)(rpcReq, this.config.metadata?.name || '');
33
+ break;
34
+ }
35
+ if (simulator) {
36
+ if (event != null) {
37
+ if (this.simulatorClient) {
38
+ this.simulatorClient.send(JSON.stringify(event));
39
+ res.status(200).json({ success: true });
40
+ return;
41
+ }
42
+ else {
43
+ console.log('\x1b[33mNo simulator client connected\x1b[0m');
44
+ res.status(503).json({ error: 'Simulator not connected' });
45
+ return;
46
+ }
47
+ }
48
+ else {
49
+ res.status(500).json({ error: 'Failed to process request' });
50
+ return;
51
+ }
52
+ }
53
+ else {
54
+ res.json({ jsonrpc: '2.0', result: event, id: 1 });
55
+ return;
56
+ }
57
+ }
58
+ setSimulatorClient(simulatorClient) {
59
+ this.simulatorClient = simulatorClient;
60
+ }
61
+ async start() {
62
+ return new Promise(resolve => {
63
+ this.server = this.app.listen(this.config.port, () => {
64
+ const url = `http://localhost:${this.config.port}`;
65
+ console.log(`\x1b[32mStarting airmoney service server at ${url}\x1b[0m`);
66
+ resolve();
67
+ });
68
+ });
69
+ }
70
+ async stop() {
71
+ return new Promise(resolve => {
72
+ if (this.server) {
73
+ this.server.close(() => {
74
+ resolve();
75
+ });
76
+ }
77
+ else {
78
+ resolve();
79
+ }
80
+ });
81
+ }
82
+ }
83
+ exports.AirmoneyService = AirmoneyService;
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PortManager = void 0;
4
+ const cryptoProcess_1 = require("../../util/cryptoProcess");
5
+ class PortManager {
6
+ /**
7
+ * Check if any of the required ports are in use
8
+ */
9
+ static async checkPortConflicts(ports = this.DEFAULT_PORTS) {
10
+ const inUsePorts = await (0, cryptoProcess_1.checkPortsInUse)(ports);
11
+ if (inUsePorts.length > 0) {
12
+ console.error('\x1b[31m❌ Port conflict detected!\x1b[0m');
13
+ console.error(`\x1b[31mThe following ports are already in use: ${inUsePorts.join(', ')}\x1b[0m`);
14
+ console.error('\x1b[31m\nPlease kill the processes using these ports before running serve:\x1b[0m');
15
+ const killCommand = `lsof -ti:${inUsePorts.join(',')} | xargs kill -9`;
16
+ console.error(`\x1b[31m ${killCommand}\x1b[0m`);
17
+ process.exit(1);
18
+ }
19
+ }
20
+ /**
21
+ * Get the default ports used by the application
22
+ */
23
+ static getDefaultPorts() {
24
+ return [...this.DEFAULT_PORTS];
25
+ }
26
+ }
27
+ exports.PortManager = PortManager;
28
+ PortManager.DEFAULT_PORTS = [4040, 4041, 5050];
@@ -0,0 +1,64 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.ServeOrchestrator = void 0;
7
+ const path_1 = __importDefault(require("path"));
8
+ const metadata_1 = require("../../util/metadata");
9
+ const cryptoProcess_1 = require("../../util/cryptoProcess");
10
+ const PortManager_1 = require("../port/PortManager");
11
+ const SimulatorService_1 = require("../simulator/SimulatorService");
12
+ const AirmoneyService_1 = require("../airmoney/AirmoneyService");
13
+ class ServeOrchestrator {
14
+ constructor(config) {
15
+ this.config = config;
16
+ this.metadata = (0, metadata_1.loadMetadata)();
17
+ this.simulatorService = this.createSimulatorService();
18
+ this.airmoneyService = this.createAirmoneyService();
19
+ }
20
+ createSimulatorService() {
21
+ const projectFolder = this.config.locationFolder
22
+ ? path_1.default.join(process.cwd(), this.config.locationFolder)
23
+ : process.cwd();
24
+ return this.config.appUrl
25
+ ? SimulatorService_1.SimulatorService.createWithProxy(this.config.appUrl, {
26
+ noBrowser: this.config.noBrowser,
27
+ })
28
+ : SimulatorService_1.SimulatorService.createWithProject(projectFolder, {
29
+ noBrowser: this.config.noBrowser,
30
+ });
31
+ }
32
+ createAirmoneyService() {
33
+ return new AirmoneyService_1.AirmoneyService({
34
+ port: 4040,
35
+ metadata: this.metadata ? { name: this.metadata.name } : undefined,
36
+ });
37
+ }
38
+ async start() {
39
+ // Check for port conflicts first
40
+ await PortManager_1.PortManager.checkPortConflicts();
41
+ // Validate metadata
42
+ if (!this.metadata) {
43
+ console.log('\x1b[33mNo metadata found. Skipping some possible checks.\x1b[0m');
44
+ }
45
+ // Start simulator service
46
+ await this.simulatorService.start();
47
+ // Connect simulator client to airmoney service
48
+ const simulatorClient = this.simulatorService.getClient();
49
+ if (simulatorClient) {
50
+ this.airmoneyService.setSimulatorClient(simulatorClient);
51
+ }
52
+ // Start airmoney service
53
+ await this.airmoneyService.start();
54
+ // Start crypto service
55
+ (0, cryptoProcess_1.startCryptoServiceSimple)();
56
+ }
57
+ async stop() {
58
+ await Promise.all([
59
+ this.simulatorService.stop(),
60
+ this.airmoneyService.stop(),
61
+ ]);
62
+ }
63
+ }
64
+ exports.ServeOrchestrator = ServeOrchestrator;
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,113 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.BaseSimulatorService = void 0;
7
+ const path_1 = __importDefault(require("path"));
8
+ const express_1 = __importDefault(require("express"));
9
+ const express_ws_1 = __importDefault(require("express-ws"));
10
+ const cors_1 = __importDefault(require("cors"));
11
+ const open_1 = __importDefault(require("open"));
12
+ const http_proxy_middleware_1 = require("http-proxy-middleware");
13
+ class BaseSimulatorService {
14
+ constructor(config) {
15
+ this.simulatorClient = null;
16
+ this.config = config;
17
+ this.app = (0, express_ws_1.default)((0, express_1.default)()).app;
18
+ this.setupMiddleware();
19
+ }
20
+ setupMiddleware() {
21
+ this.app.use((0, cors_1.default)());
22
+ this.app.use(express_1.default.json());
23
+ }
24
+ getSimulatorDir() {
25
+ // after tsc compile, serve.js is in dist/cli/
26
+ // we step up two dirs to get back to the project root
27
+ // then go into public/simulator
28
+ const base = path_1.default.resolve(__dirname, '..', '..', '..');
29
+ return path_1.default.join(base, 'public', 'simulator');
30
+ }
31
+ setupWebSocket() {
32
+ this.app.ws('/ws', (ws, req) => {
33
+ this.simulatorClient = ws;
34
+ ws.on('message', (msg) => {
35
+ console.log(msg);
36
+ });
37
+ });
38
+ }
39
+ setupStaticFiles() {
40
+ const simulatorDir = this.getSimulatorDir();
41
+ this.app.use('/simulator', express_1.default.static(simulatorDir));
42
+ }
43
+ setupProjectFiles() {
44
+ if (this.config.appUrl) {
45
+ const proxyMiddleware = (0, http_proxy_middleware_1.createProxyMiddleware)({
46
+ xfwd: true,
47
+ target: this.config.appUrl,
48
+ changeOrigin: true,
49
+ pathFilter: '/',
50
+ });
51
+ this.app.use('/', proxyMiddleware);
52
+ }
53
+ else if (this.config.projectFolder) {
54
+ this.app.use('/', express_1.default.static(this.config.projectFolder));
55
+ }
56
+ }
57
+ async openBrowser() {
58
+ if (!this.config.noBrowser) {
59
+ const url = `http://localhost:${this.config.port}/simulator`;
60
+ try {
61
+ await (0, open_1.default)(url);
62
+ }
63
+ catch (err) {
64
+ console.error('\x1b[31mFailed to open web browser\x1b[0m', err);
65
+ }
66
+ }
67
+ }
68
+ getClient() {
69
+ if (!this.simulatorClient)
70
+ return null;
71
+ return {
72
+ ws: this.simulatorClient,
73
+ send: (data) => {
74
+ if (this.simulatorClient) {
75
+ this.simulatorClient.send(data);
76
+ }
77
+ },
78
+ };
79
+ }
80
+ sendToClient(data) {
81
+ if (this.simulatorClient) {
82
+ this.simulatorClient.send(data);
83
+ return true;
84
+ }
85
+ return false;
86
+ }
87
+ async start() {
88
+ this.setupWebSocket();
89
+ this.setupStaticFiles();
90
+ this.setupProjectFiles();
91
+ return new Promise(resolve => {
92
+ this.server = this.app.listen(this.config.port, () => {
93
+ const url = `http://localhost:${this.config.port}/simulator`;
94
+ console.log(`\x1b[32mStarting simulator server at ${url}\x1b[0m`);
95
+ this.openBrowser();
96
+ resolve();
97
+ });
98
+ });
99
+ }
100
+ async stop() {
101
+ return new Promise(resolve => {
102
+ if (this.server) {
103
+ this.server.close(() => {
104
+ resolve();
105
+ });
106
+ }
107
+ else {
108
+ resolve();
109
+ }
110
+ });
111
+ }
112
+ }
113
+ exports.BaseSimulatorService = BaseSimulatorService;
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SimulatorService = void 0;
4
+ const BaseSimulatorService_1 = require("./BaseSimulatorService");
5
+ class SimulatorService extends BaseSimulatorService_1.BaseSimulatorService {
6
+ constructor(config) {
7
+ super(config);
8
+ }
9
+ /**
10
+ * Create a new SimulatorService instance with default configuration
11
+ */
12
+ static create(config = {}) {
13
+ const defaultConfig = {
14
+ port: 4041,
15
+ noBrowser: false,
16
+ ...config,
17
+ };
18
+ return new SimulatorService(defaultConfig);
19
+ }
20
+ /**
21
+ * Create a SimulatorService with project folder configuration
22
+ */
23
+ static createWithProject(projectFolder, config = {}) {
24
+ return SimulatorService.create({
25
+ projectFolder,
26
+ ...config,
27
+ });
28
+ }
29
+ /**
30
+ * Create a SimulatorService with app URL proxy configuration
31
+ */
32
+ static createWithProxy(appUrl, config = {}) {
33
+ return SimulatorService.create({
34
+ appUrl,
35
+ ...config,
36
+ });
37
+ }
38
+ }
39
+ exports.SimulatorService = SimulatorService;
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -3,6 +3,9 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.isPortInUse = isPortInUse;
7
+ exports.checkPortsInUse = checkPortsInUse;
8
+ exports.isCryptoServiceRunning = isCryptoServiceRunning;
6
9
  exports.startCryptoService = startCryptoService;
7
10
  exports.getCryptoServicePath = getCryptoServicePath;
8
11
  exports.startCryptoServiceSimple = startCryptoServiceSimple;
@@ -13,15 +16,83 @@ const path_1 = __importDefault(require("path"));
13
16
  const child_process_1 = require("child_process");
14
17
  const env_1 = require("./env");
15
18
  const CryptoService_1 = require("../service/crypto/CryptoService");
19
+ // Utility functions for port management
20
+ function isPortInUse(port) {
21
+ return new Promise(resolve => {
22
+ const net = require('net');
23
+ const socket = new net.Socket();
24
+ socket.setTimeout(1000);
25
+ socket.on('connect', () => {
26
+ socket.destroy();
27
+ resolve(true); // Port is in use
28
+ });
29
+ socket.on('timeout', () => {
30
+ socket.destroy();
31
+ resolve(false); // Port is free
32
+ });
33
+ socket.on('error', () => {
34
+ resolve(false); // Port is free
35
+ });
36
+ socket.connect(port, 'localhost');
37
+ });
38
+ }
39
+ async function checkPortsInUse(ports) {
40
+ const inUsePorts = [];
41
+ for (const port of ports) {
42
+ if (await isPortInUse(port)) {
43
+ inUsePorts.push(port);
44
+ }
45
+ }
46
+ return inUsePorts;
47
+ }
48
+ async function isCryptoServiceRunning(port = 5050) {
49
+ try {
50
+ // Check if crypto service is running by making a simple HTTP request
51
+ const response = await fetch(`http://localhost:${port}/`, {
52
+ method: 'GET',
53
+ signal: AbortSignal.timeout(1000), // 1 second timeout
54
+ });
55
+ // Accept any response (200, 404, 405, etc.) as long as we get a response
56
+ // This means the crypto service is running
57
+ return true;
58
+ }
59
+ catch {
60
+ return false;
61
+ }
62
+ }
16
63
  function startCryptoService() {
17
- return new Promise((resolve, reject) => {
64
+ return new Promise(async (resolve, reject) => {
18
65
  const bin = getCryptoServicePath();
19
66
  if (!(0, fs_1.existsSync)(bin)) {
20
67
  reject(new Error(`Crypto service binary not found: ${bin}`));
21
68
  return;
22
69
  }
70
+ // Check if port 5050 is already in use before starting the binary
71
+ const portInUse = await isPortInUse(5050);
72
+ if (portInUse) {
73
+ // Check if it's our crypto service
74
+ const isCryptoRunning = await isCryptoServiceRunning(5050);
75
+ if (isCryptoRunning) {
76
+ // console.log('Reusing existing crypto service on port 5050');
77
+ // Return a mock process that doesn't need to be killed
78
+ resolve({
79
+ process: null,
80
+ kill: () => {
81
+ // console.log('Crypto service is managed externally, not stopping');
82
+ },
83
+ });
84
+ return;
85
+ }
86
+ else {
87
+ reject(new Error('Port 5050 is already in use by another service that is not the crypto service.\n' +
88
+ 'Please free up port 5050 or kill the conflicting process:\n' +
89
+ ' lsof -ti:5050 | xargs kill -9'));
90
+ return;
91
+ }
92
+ }
23
93
  // console.log('Starting crypto service...');
24
94
  let isKilled = false;
95
+ let hasResolved = false;
25
96
  const cryptoProcess = (0, child_process_1.exec)(bin, {
26
97
  env: {
27
98
  ...process.env,
@@ -30,29 +101,46 @@ function startCryptoService() {
30
101
  },
31
102
  }, (error, stdout, stderr) => {
32
103
  // Ignore errors if the process was intentionally killed
33
- if (error && !isKilled) {
34
- console.error('Crypto service error:', error);
35
- reject(error);
104
+ if (error && !isKilled && !hasResolved) {
105
+ console.error('\x1b[31m❌ Crypto service failed to start:\x1b[0m');
106
+ console.error('\x1b[31mError details:\x1b[0m', error.message);
107
+ // Check for specific Rust panic errors
108
+ if (stderr &&
109
+ stderr.includes('Cannot drop a runtime in a context where blocking is not allowed')) {
110
+ console.error('\x1b[31m\n🔧 This appears to be a Rust/tokio runtime issue in the crypto service binary.\x1b[0m');
111
+ console.error('\x1b[31mPossible solutions:\x1b[0m');
112
+ console.error('\x1b[31m1. The binary may be corrupted - try rebuilding: npm run build\x1b[0m');
113
+ console.error('\x1b[31m2. There may be a compatibility issue with your system\x1b[0m');
114
+ console.error('\x1b[31m3. Try running the binary directly to see more details:\x1b[0m');
115
+ console.error(`\x1b[31m ${bin}\x1b[0m`);
116
+ }
117
+ else if (stderr) {
118
+ console.error('Stderr:', stderr);
119
+ }
120
+ reject(new Error(`Crypto service failed: ${error.message}`));
36
121
  return;
37
122
  }
38
- // if (stdout) {
39
- // console.log('Crypto service stdout:', stdout);
40
- // }
41
- if (stderr) {
42
- console.error('Crypto service stderr:', stderr);
123
+ if (stdout) {
124
+ // console.log('Crypto service stdout:', stdout);
125
+ }
126
+ if (stderr && !isKilled) {
127
+ console.error('\x1b[31mCrypto service stderr:\x1b[0m', stderr);
43
128
  }
44
129
  });
45
130
  // Wait 2 seconds before resolving to ensure service is ready
46
131
  setTimeout(() => {
47
- resolve({
48
- process: cryptoProcess,
49
- kill: () => {
50
- isKilled = true;
51
- if (cryptoProcess && !cryptoProcess.killed) {
52
- cryptoProcess.kill();
53
- }
54
- },
55
- });
132
+ if (!hasResolved) {
133
+ hasResolved = true;
134
+ resolve({
135
+ process: cryptoProcess,
136
+ kill: () => {
137
+ isKilled = true;
138
+ if (cryptoProcess && !cryptoProcess.killed) {
139
+ cryptoProcess.kill();
140
+ }
141
+ },
142
+ });
143
+ }
56
144
  }, 2000);
57
145
  });
58
146
  }
@@ -65,10 +153,10 @@ function getCryptoServicePath() {
65
153
  function startCryptoServiceSimple() {
66
154
  const bin = getCryptoServicePath();
67
155
  if (!(0, fs_1.existsSync)(bin)) {
68
- console.log('crypto service not found at ' + bin);
156
+ console.log('\x1b[31mcrypto service not found at ' + bin + '\x1b[0m');
69
157
  return;
70
158
  }
71
- console.log('execing crypto service at http://localhost:5050');
159
+ console.log('\x1b[32mStarting crypto service at http://localhost:5050\x1b[0m');
72
160
  (0, child_process_1.exec)(bin, { env: { SECURE_STORAGE: (0, env_1.configDir)(), RUST_BACKTRACE: '1' } }, (_, stdout, stderr) => {
73
161
  // console.log("stdout", stdout);
74
162
  // console.log("stderr", stderr);
@@ -88,8 +176,21 @@ async function withCryptoService(operation) {
88
176
  let cryptoService = null;
89
177
  let startedCryptoService = false;
90
178
  try {
91
- cryptoService = await startCryptoService();
92
- startedCryptoService = true;
179
+ // Start crypto service (this will check ports and reuse if available)
180
+ try {
181
+ cryptoService = await startCryptoService();
182
+ startedCryptoService = true;
183
+ }
184
+ catch (error) {
185
+ console.error('\x1b[31m❌ Failed to start crypto service:\x1b[0m');
186
+ console.error('\x1b[31mThis might be due to:\x1b[0m');
187
+ console.error('\x1b[31m- Missing or corrupted binary files\x1b[0m');
188
+ console.error('\x1b[31m- Insufficient permissions\x1b[0m');
189
+ console.error('\x1b[31m- System compatibility issues\x1b[0m');
190
+ console.error('\x1b[31m- Port conflicts\x1b[0m');
191
+ console.error('\x1b[31m\nTry running: npm run build\x1b[0m');
192
+ throw error;
193
+ }
93
194
  const cryptoServiceClient = new CryptoService_1.CryptoService();
94
195
  // console.log('Crypto service client created');
95
196
  return await operation(cryptoServiceClient);
@@ -42,7 +42,7 @@ function loadMetadata(projectPath = '.') {
42
42
  try {
43
43
  const filePath = path.join(projectPath, 'metadata.json');
44
44
  if (!fs.existsSync(filePath)) {
45
- console.log('Please run this command in Project directory');
45
+ console.log('\x1b[33mPlease run this command in Project directory\x1b[0m');
46
46
  return null;
47
47
  }
48
48
  const raw = fs.readFileSync(filePath, 'utf8');
@@ -50,7 +50,7 @@ function loadMetadata(projectPath = '.') {
50
50
  return data;
51
51
  }
52
52
  catch (err) {
53
- console.log('Please run this command in Project directory');
53
+ console.log('\x1b[33mError loading metadata\x1b[0m');
54
54
  return null;
55
55
  }
56
56
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@airmoney-degn/airmoney-cli",
3
- "version": "0.12.2",
3
+ "version": "0.13.1",
4
4
  "description": "airmoney-cli is a command-line interface tool designed to facilitate the development and management of decentralized applications (DApps) for Airmoney.",
5
5
  "publishConfig": {
6
6
  "access": "public"