nodio-cli 1.1.0 → 1.1.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nodio-cli",
3
- "version": "1.1.0",
3
+ "version": "1.1.1",
4
4
  "description": "Nodio distributed storage network",
5
5
  "main": "src/server/index.js",
6
6
  "type": "commonjs",
@@ -35,7 +35,7 @@ async function startServer() {
35
35
 
36
36
  app.use(cors(corsOptions));
37
37
  app.options(/.*/, cors(corsOptions));
38
- app.use(express.json({ limit: '10mb' }));
38
+ app.use(express.json({ limit: '50mb' }));
39
39
  app.use('/api', buildRoutes(config));
40
40
 
41
41
  app.use((error, _req, res, _next) => {
@@ -9,6 +9,7 @@ const {
9
9
  ReplicationTaskModel,
10
10
  RelayTaskModel
11
11
  } = require('./models');
12
+ const { uploadToFilecoin } = require('../../services/filecoin');
12
13
  const {
13
14
  chooseDistinctOnlineNodes,
14
15
  ensureEmergencyReplicasForShard
@@ -574,6 +575,49 @@ function buildRoutes(config) {
574
575
  }
575
576
  });
576
577
 
578
+ router.post('/files/:fileId/filecoin/upload', async (req, res, next) => {
579
+ try {
580
+ const { fileId } = req.params;
581
+ const { dataBase64 } = req.body;
582
+
583
+ if (!fileId) {
584
+ return res.status(400).json({ error: 'fileId is required' });
585
+ }
586
+ if (!dataBase64 || typeof dataBase64 !== 'string') {
587
+ return res.status(400).json({ error: 'dataBase64 is required' });
588
+ }
589
+
590
+ const payload = Buffer.from(dataBase64, 'base64');
591
+ if (!payload || payload.length === 0) {
592
+ return res.status(400).json({ error: 'dataBase64 decoded to empty payload' });
593
+ }
594
+
595
+ const cid = await uploadToFilecoin(payload, fileId);
596
+ if (!cid) {
597
+ return res.status(502).json({ error: 'filecoin upload failed' });
598
+ }
599
+
600
+ const file = await FileModel.findOneAndUpdate(
601
+ { fileId },
602
+ {
603
+ $set: {
604
+ filecoinCid: cid,
605
+ filecoinBackedUp: true
606
+ }
607
+ },
608
+ { new: true }
609
+ );
610
+
611
+ if (!file) {
612
+ return res.status(404).json({ error: 'file not found' });
613
+ }
614
+
615
+ res.json({ ok: true, fileId: file.fileId, filecoinCid: cid });
616
+ } catch (error) {
617
+ next(error);
618
+ }
619
+ });
620
+
577
621
  router.post('/shards/register', async (req, res, next) => {
578
622
  try {
579
623
  const { shardId, fileId, order, sizeBytes, checksum, nodeIds } = req.body;
@@ -5,7 +5,7 @@ const axios = require('axios');
5
5
  const { v4: uuidv4 } = require('uuid');
6
6
  const { createApiClient, normalizeUrl } = require('./client');
7
7
  const { encryptAes256Gcm, decryptAes256Gcm, sha256Hex } = require('../common/crypto');
8
- const { uploadToFilecoin, retrieveFromFilecoin } = require('../../services/filecoin');
8
+ const { retrieveFromFilecoin } = require('../../services/filecoin');
9
9
 
10
10
  function splitBuffer(buffer, shardSizeBytes) {
11
11
  if (shardSizeBytes <= 0) {
@@ -88,27 +88,25 @@ function decryptShardsFromBuffers(orderedShards, shardMetaMap, encryptedShardBuf
88
88
  return Buffer.concat(plainParts);
89
89
  }
90
90
 
91
- function fireAndForgetFilecoinUpload(api, fileBuffer, fileId) {
91
+ async function requestFilecoinBackup(api, fileBuffer, fileId) {
92
92
  if (!fileBuffer || fileBuffer.length === 0) {
93
93
  return;
94
94
  }
95
95
 
96
- void (async () => {
97
- const cid = await uploadToFilecoin(fileBuffer, fileId);
98
- if (!cid) {
99
- return;
100
- }
101
-
102
- try {
103
- await api.post(`/files/${fileId}/filecoin`, {
104
- filecoinCid: cid,
105
- filecoinBackedUp: true
106
- });
107
- } catch (error) {
108
- const message = error.response?.data?.error || error.message;
109
- console.warn(`[filecoin] failed to persist cid for ${fileId}: ${message}`);
110
- }
111
- })();
96
+ try {
97
+ await api.post(
98
+ `/files/${fileId}/filecoin/upload`,
99
+ {
100
+ dataBase64: fileBuffer.toString('base64')
101
+ },
102
+ {
103
+ timeout: 180000
104
+ }
105
+ );
106
+ } catch (error) {
107
+ const message = error.response?.data?.error || error.message;
108
+ console.warn(`[filecoin] server upload failed for ${fileId}: ${message}`);
109
+ }
112
110
  }
113
111
 
114
112
  function fireAndForgetLayer1Reseed(api, fileId, orderedShards, encryptedShardBuffers, directTimeoutMs) {
@@ -427,24 +425,10 @@ async function uploadFile(options) {
427
425
  }
428
426
  });
429
427
 
430
- // Upload to Filecoin as default (synchronous with retries)
428
+ // Upload to Filecoin via the central server (uses server-side wallet key)
431
429
  const encryptedFileBuffer = Buffer.concat(encryptedShardBuffers);
432
- console.log(`[filecoin] uploading to Filecoin (this may take a while)...`);
433
- const filecoinCid = await uploadToFilecoin(encryptedFileBuffer, fileId);
434
- if (filecoinCid) {
435
- try {
436
- await api.post(`/files/${fileId}/filecoin`, {
437
- filecoinCid,
438
- filecoinBackedUp: true
439
- });
440
- console.log(`[filecoin] backup complete, cid: ${filecoinCid}`);
441
- } catch (error) {
442
- const message = error.response?.data?.error || error.message;
443
- console.warn(`[filecoin] warning: failed to persist cid: ${message}`);
444
- }
445
- } else {
446
- console.warn(`[filecoin] warning: upload to Filecoin failed, file backed up to Layer 1 only`);
447
- }
430
+ console.log(`[filecoin] uploading to Filecoin via central server (this may take a while)...`);
431
+ await requestFilecoinBackup(api, encryptedFileBuffer, fileId);
448
432
 
449
433
  console.log(`Upload complete`);
450
434
  console.log(`fileId: ${fileId}`);