ezshare-cli 1.0.1 → 1.0.3

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.
@@ -4,10 +4,23 @@ import { Box, Text } from 'ink';
4
4
  import { Spinner, ProgressBar } from '@inkjs/ui';
5
5
  import { pipeline } from 'node:stream/promises';
6
6
  import { Transform } from 'node:stream';
7
+ import { appendFileSync } from 'node:fs';
7
8
  import { parseTopicKey, deriveKey, createDecryptStream } from '../utils/crypto.js';
8
9
  import { createDecompressStream } from '../utils/compression.js';
9
10
  import { createExtractStream } from '../utils/tar.js';
10
11
  import { createReceiverSwarm, cleanupSwarm } from '../utils/network.js';
12
+ // Debug logging to file (Ink captures stdout)
13
+ const LOG_FILE = '/tmp/ezshare_debug.log';
14
+ function debugLog(message) {
15
+ const timestamp = new Date().toISOString();
16
+ const logLine = `[${timestamp}] ${message}\n`;
17
+ try {
18
+ appendFileSync(LOG_FILE, logLine);
19
+ }
20
+ catch (e) {
21
+ // Ignore file errors
22
+ }
23
+ }
11
24
  export function ReceiveCommand({ shareKey, outputPath = process.cwd(), onComplete, onError }) {
12
25
  const [state, setState] = useState('connecting');
13
26
  const [progress, setProgress] = useState(0);
@@ -26,16 +39,16 @@ export function ReceiveCommand({ shareKey, outputPath = process.cwd(), onComplet
26
39
  const { swarm, connectionPromise } = await createReceiverSwarm(topic);
27
40
  // Wait for peer connection (listener already registered)
28
41
  const socket = await connectionPromise;
29
- console.log('[Receiver] Connected to sender');
42
+ debugLog('[Receiver] Connected to sender');
30
43
  // Add socket error handler
31
44
  socket.on('error', (err) => {
32
- console.error('[Receiver] Socket error:', err);
45
+ debugLog('[Receiver] Socket error: ' + err);
33
46
  });
34
47
  socket.on('end', () => {
35
- console.log('[Receiver] Socket end event received');
48
+ debugLog('[Receiver] Socket end event received');
36
49
  });
37
50
  socket.on('close', () => {
38
- console.log('[Receiver] Socket closed');
51
+ debugLog('[Receiver] Socket closed');
39
52
  });
40
53
  // Read metadata first (JSON header followed by newline)
41
54
  const metadataBuffer = [];
@@ -52,19 +65,19 @@ export function ReceiveCommand({ shareKey, outputPath = process.cwd(), onComplet
52
65
  // Found metadata
53
66
  try {
54
67
  const metadataJson = combined.slice(0, newlineIndex).toString();
55
- console.log('[Receiver] Received metadata:', metadataJson);
68
+ debugLog('[Receiver] Received metadata: ' + metadataJson);
56
69
  transferMetadata = JSON.parse(metadataJson);
57
70
  setMetadata(transferMetadata);
58
71
  // Push remaining data after newline
59
72
  const remainingData = combined.slice(newlineIndex + 1);
60
- console.log(`[Receiver] Metadata extracted, ${remainingData.length} bytes of data after newline`);
73
+ debugLog(`[Receiver] Metadata extracted, ${remainingData.length} bytes of data after newline`);
61
74
  if (remainingData.length > 0) {
62
75
  this.push(remainingData);
63
76
  }
64
77
  metadataReceived = true;
65
78
  }
66
79
  catch (err) {
67
- console.error('[Receiver] Failed to parse metadata:', err);
80
+ debugLog('[Receiver] Failed to parse metadata: ' + err);
68
81
  callback(err);
69
82
  return;
70
83
  }
@@ -91,18 +104,18 @@ export function ReceiveCommand({ shareKey, outputPath = process.cwd(), onComplet
91
104
  });
92
105
  // Start receiving
93
106
  setState('receiving');
94
- console.log('[Receiver] Starting receive pipeline');
107
+ debugLog('[Receiver] Starting receive pipeline');
95
108
  // Build the pipeline: Socket → Metadata Extractor → Progress → Decrypt → Decompress → Tar Extract
96
109
  const decryptStream = createDecryptStream(encryptionKey);
97
110
  const decompressStream = await createDecompressStream();
98
111
  const extractStream = createExtractStream(outputPath);
99
112
  await pipeline(socket, metadataExtractor, progressTracker, decryptStream, decompressStream, extractStream);
100
- console.log('[Receiver] Pipeline completed successfully');
113
+ debugLog('[Receiver] Pipeline completed successfully');
101
114
  // Transfer complete
102
115
  setState('done');
103
116
  // Receiver cleanup - small delay to ensure socket is fully closed
104
117
  await new Promise(resolve => setTimeout(resolve, 100));
105
- console.log('[Receiver] Cleaning up receiver swarm');
118
+ debugLog('[Receiver] Cleaning up receiver swarm');
106
119
  await cleanupSwarm(swarm);
107
120
  if (onComplete) {
108
121
  onComplete();
@@ -4,10 +4,23 @@ import { Box, Text } from 'ink';
4
4
  import { Spinner, ProgressBar } from '@inkjs/ui';
5
5
  import { pipeline } from 'node:stream/promises';
6
6
  import { Transform } from 'node:stream';
7
+ import { appendFileSync } from 'node:fs';
7
8
  import { generateTopicKey, deriveKey, createEncryptStream } from '../utils/crypto.js';
8
9
  import { createCompressStream, shouldCompress } from '../utils/compression.js';
9
10
  import { createPackStream, getTransferMetadata } from '../utils/tar.js';
10
11
  import { createSenderSwarm, cleanupSwarm } from '../utils/network.js';
12
+ // Debug logging to file (Ink captures stdout)
13
+ const LOG_FILE = '/tmp/ezshare_debug.log';
14
+ function debugLog(message) {
15
+ const timestamp = new Date().toISOString();
16
+ const logLine = `[${timestamp}] ${message}\n`;
17
+ try {
18
+ appendFileSync(LOG_FILE, logLine);
19
+ }
20
+ catch (e) {
21
+ // Ignore file errors
22
+ }
23
+ }
11
24
  export function SendCommand({ path, onComplete, onError }) {
12
25
  const [state, setState] = useState('init');
13
26
  const [shareKey, setShareKey] = useState('');
@@ -32,14 +45,18 @@ export function SendCommand({ path, onComplete, onError }) {
32
45
  });
33
46
  // Create sender swarm
34
47
  setState('waiting');
48
+ debugLog('[Sender] About to call createSenderSwarm');
35
49
  const { swarm, waitForPeer } = await createSenderSwarm(topic);
50
+ debugLog('[Sender] createSenderSwarm completed, got waitForPeer function');
36
51
  // Wait for peer connection
52
+ debugLog('[Sender] Calling waitForPeer()...');
37
53
  const socket = await waitForPeer();
54
+ debugLog('[Sender] Got socket from waitForPeer');
38
55
  // Register socket close listener BEFORE pipeline starts
39
56
  // This ensures we don't miss the close event
40
57
  const socketClosed = new Promise((resolve) => {
41
58
  socket.once('close', () => {
42
- console.log('[Sender] Socket closed');
59
+ debugLog('[Sender] Socket closed');
43
60
  resolve();
44
61
  });
45
62
  });
@@ -47,9 +64,10 @@ export function SendCommand({ path, onComplete, onError }) {
47
64
  socket.on('error', (err) => {
48
65
  console.error('[Sender] Socket error:', err);
49
66
  });
67
+ debugLog('[Sender] About to set state to sending');
50
68
  // Peer connected! Start sending
51
69
  setState('sending');
52
- console.log('[Sender] Starting transfer pipeline');
70
+ debugLog('[Sender] Starting transfer pipeline');
53
71
  // Create metadata prepend stream
54
72
  const metadataJson = JSON.stringify({
55
73
  totalSize: transferMetadata.totalSize,
@@ -84,11 +102,11 @@ export function SendCommand({ path, onComplete, onError }) {
84
102
  const compressStream = await createCompressStream(shouldCompress(path));
85
103
  const encryptStream = createEncryptStream(encryptionKey);
86
104
  await pipeline(packStream, compressStream, encryptStream, metadataPrepender, progressTracker, socket);
87
- console.log('[Sender] Pipeline completed, waiting for socket to close');
105
+ debugLog('[Sender] Pipeline completed, waiting for socket to close');
88
106
  // Wait for socket to fully close before cleaning up
89
107
  // This ensures the receiver has finished and closed their end
90
108
  await socketClosed;
91
- console.log('[Sender] Socket closed, cleaning up swarm');
109
+ debugLog('[Sender] Socket closed, cleaning up swarm');
92
110
  // Transfer complete
93
111
  setState('done');
94
112
  await cleanupSwarm(swarm);
@@ -16,7 +16,14 @@
16
16
  import { Transform } from 'node:stream';
17
17
  import { extname } from 'node:path';
18
18
  import { execSync } from 'node:child_process';
19
- import { compress, decompress } from 'simple-zstd/dist/index.mjs';
19
+ // Dynamic import to handle CommonJS module from ES module context
20
+ let zstdModule = null;
21
+ async function getZstdModule() {
22
+ if (!zstdModule) {
23
+ zstdModule = await import('simple-zstd');
24
+ }
25
+ return zstdModule;
26
+ }
20
27
  // Protocol flags
21
28
  const FLAG_RAW = 0x00;
22
29
  const FLAG_COMPRESSED = 0x01;
@@ -150,6 +157,7 @@ export async function createCompressStream(shouldCompress = true) {
150
157
  ' Windows: choco install zstd');
151
158
  }
152
159
  // Get zstd compression stream
160
+ const { compress } = await getZstdModule();
153
161
  const zstdStream = await compress(COMPRESSION_LEVEL);
154
162
  // Track state
155
163
  let flagSent = false;
@@ -257,7 +265,8 @@ export async function createDecompressStream() {
257
265
  return callback(new Error('zstd is not installed but data is compressed'));
258
266
  }
259
267
  // Synchronously set up - decompress() returns Promise but we handle async carefully
260
- decompress()
268
+ getZstdModule()
269
+ .then(({ decompress }) => decompress())
261
270
  .then((stream) => {
262
271
  if (destroyed) {
263
272
  stream.destroy();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ezshare-cli",
3
- "version": "1.0.1",
3
+ "version": "1.0.3",
4
4
  "description": "Secure P2P file transfer CLI with end-to-end encryption - No servers, no signups, just share",
5
5
  "type": "module",
6
6
  "bin": {