Skip to content

Commit e2e2c3f

Browse files
authored
Merge pull request #586 from internxt/deps/update-inxt-js
[_]: deps/update-inxt-js
2 parents cedfc7e + 6a50933 commit e2e2c3f

19 files changed

Lines changed: 1026 additions & 1612 deletions

package.json

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -37,22 +37,22 @@
3737
],
3838
"dependencies": {
3939
"@dashlane/pqc-kem-kyber512-node": "1.0.0",
40-
"@inquirer/prompts": "8.4.2",
41-
"@internxt/inxt-js": "3.1.1",
40+
"@inquirer/prompts": "8.4.3",
41+
"@internxt/inxt-js": "3.2.2",
4242
"@internxt/lib": "1.4.2",
43-
"@internxt/sdk": "1.16.2",
44-
"@oclif/core": "4.11.1",
45-
"@oclif/plugin-autocomplete": "3.2.47",
46-
"axios": "1.16.0",
47-
"better-sqlite3": "12.9.0",
43+
"@internxt/sdk": "1.17.0",
44+
"@oclif/core": "4.11.3",
45+
"@oclif/plugin-autocomplete": "3.2.49",
46+
"axios": "1.16.1",
47+
"better-sqlite3": "12.10.0",
4848
"bip39": "3.1.0",
4949
"body-parser": "2.2.2",
5050
"cli-progress": "3.12.0",
5151
"dayjs": "1.11.20",
5252
"dotenv": "17.4.2",
5353
"express": "5.2.1",
5454
"express-async-handler": "1.2.0",
55-
"fast-xml-parser": "5.7.3",
55+
"fast-xml-parser": "5.8.0",
5656
"hash-wasm": "4.12.0",
5757
"mime-types": "3.0.2",
5858
"open": "11.0.0",
@@ -62,7 +62,7 @@
6262
"range-parser": "1.2.1",
6363
"selfsigned": "5.5.0",
6464
"tty-table": "5.0.0",
65-
"typeorm": "0.3.29",
65+
"typeorm": "1.0.0",
6666
"winston": "3.19.0"
6767
},
6868
"devDependencies": {
@@ -72,28 +72,28 @@
7272
"@types/cli-progress": "^3.11.6",
7373
"@types/express": "^5.0.6",
7474
"@types/mime-types": "^3.0.1",
75-
"@types/node": "^25.6.0",
75+
"@types/node": "^25.9.1",
7676
"@types/range-parser": "^1.2.7",
77-
"@vitest/coverage-istanbul": "^4.1.5",
78-
"@vitest/spy": "^4.1.5",
79-
"eslint": "^10.3.0",
77+
"@vitest/coverage-istanbul": "^4.1.7",
78+
"@vitest/spy": "^4.1.7",
79+
"eslint": "^10.4.0",
8080
"husky": "^9.1.7",
81-
"lint-staged": "^17.0.3",
81+
"lint-staged": "^17.0.5",
8282
"nodemon": "^3.1.14",
83-
"oclif": "^4.23.0",
83+
"oclif": "^4.23.7",
8484
"prettier": "^3.8.3",
8585
"rimraf": "^6.1.3",
8686
"sql.js": "^1.14.1",
8787
"ts-node": "^10.9.2",
8888
"typescript": "^6.0.3",
89-
"vitest": "^4.1.5",
89+
"vitest": "^4.1.7",
9090
"vitest-mock-express": "^2.2.0"
9191
},
9292
"optionalDependencies": {
9393
"sharp": "^0.34.5"
9494
},
9595
"engines": {
96-
"node": ">=22.13.0"
96+
"node": "^22.13.0 || >=24.11.0"
9797
},
9898
"bin": {
9999
"internxt": "./bin/run.js"

src/commands/login-legacy.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { ValidationService } from '../services/validation.service';
66
import { CLIUtils } from '../utils/cli.utils';
77
import { SdkManager } from '../services/sdk-manager.service';
88
import * as OTPAuth from 'otpauth';
9+
import { CacheService } from '../services/cache.service';
910

1011
export default class LoginLegacy extends Command {
1112
static readonly args = {};
@@ -77,7 +78,10 @@ export default class LoginLegacy extends Command {
7778

7879
SdkManager.init({ token: loginCredentials.token });
7980

81+
CacheService.instance.clearCaches();
82+
8083
await ConfigService.instance.saveUser(loginCredentials);
84+
8185
const message = `Succesfully logged in to: ${loginCredentials.user.email}`;
8286
CLIUtils.success(this.log.bind(this), message);
8387
return {

src/commands/login.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { Command, Flags } from '@oclif/core';
2+
import { CacheService } from '../services/cache.service';
23
import { ConfigService } from '../services/config.service';
34
import { CLIUtils } from '../utils/cli.utils';
45
import { SdkManager } from '../services/sdk-manager.service';
@@ -48,7 +49,10 @@ export default class Login extends Command {
4849

4950
SdkManager.init({ token: loginCredentials.token });
5051

52+
CacheService.instance.clearCaches();
53+
5154
await ConfigService.instance.saveUser(loginCredentials);
55+
5256
const message = `Succesfully logged in to: ${loginCredentials.user.email}`;
5357
CLIUtils.success(this.log.bind(this), message);
5458
return {

src/services/auth.service.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { LoginDetails } from '@internxt/sdk';
22
import { SdkManager } from './sdk-manager.service';
3+
import { CacheService } from './cache.service';
34
import { CryptoService } from './crypto.service';
45
import { ConfigService } from './config.service';
56
import {
@@ -217,6 +218,8 @@ export class AuthService {
217218
* @returns A promise that resolves when the logout process is complete.
218219
*/
219220
public logout = async (): Promise<void> => {
221+
CacheService.instance.clearCaches();
222+
220223
try {
221224
const user = await ConfigService.instance.readUser();
222225
if (!user?.token) {

src/services/cache.service.ts

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
const FIFTEEN_MINUTES = 15 * 60 * 1000;
2+
3+
interface CacheEntry<T> {
4+
data: T;
5+
timestamp: number;
6+
ttl: number;
7+
}
8+
9+
export class CacheService {
10+
public static readonly instance: CacheService = new CacheService();
11+
private readonly store = new Map<string, CacheEntry<unknown>>();
12+
private readonly defaultTtl = FIFTEEN_MINUTES;
13+
14+
public get = <T>(key: string): T | null => {
15+
const entry = this.store.get(key);
16+
if (!entry) return null;
17+
18+
const isExpired = Date.now() - entry.timestamp > entry.ttl;
19+
if (isExpired) {
20+
this.store.delete(key);
21+
return null;
22+
}
23+
24+
return entry.data as T;
25+
};
26+
27+
public set = <T>(key: string, data: T, ttl?: number): void => {
28+
this.store.set(key, {
29+
data,
30+
timestamp: Date.now(),
31+
ttl: ttl ?? this.defaultTtl,
32+
});
33+
};
34+
35+
public clearCaches = (): void => {
36+
this.store.clear();
37+
};
38+
}

src/services/network/network-facade.service.ts

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,16 @@ import { Network } from '@internxt/sdk';
22
import * as NetworkDownload from '@internxt/sdk/dist/network/download';
33
import { DecryptFileFunction, DownloadFileFunction } from '@internxt/sdk/dist/network';
44
import { Environment } from '@internxt/inxt-js';
5+
import { GenerateFileKey } from '@internxt/inxt-js/build/lib/utils/crypto';
56
import { randomBytes } from 'node:crypto';
67
import { Readable } from 'node:stream';
78
import { DownloadOptions, DownloadProgressCallback } from '../../types/network.types';
89
import { CryptoService } from '../crypto.service';
910
import { DownloadService } from './download.service';
1011
import { ValidationService } from '../validation.service';
1112
import { RangeOptions } from '../../utils/network.utils';
12-
import { EncryptProgressCallback } from '@internxt/inxt-js/build/lib/core';
13+
import { UsageService } from '../usage.service';
14+
import { FormatUtils } from '../../utils/format.utils';
1315

1416
const FORTY_GIGABYTES = 40 * 1024 * 1024 * 1024;
1517

@@ -26,7 +28,7 @@ export class NetworkFacade {
2628
return ValidationService.instance.validateMnemonic(mnemonic);
2729
},
2830
generateFileKey: (mnemonic, bucketId, index) => {
29-
return Environment.utils.generateFileKey(mnemonic, bucketId, index as Buffer);
31+
return GenerateFileKey(mnemonic, bucketId, index as Buffer);
3032
},
3133
randomBytes: randomBytes,
3234
};
@@ -123,21 +125,26 @@ export class NetworkFacade {
123125
* @param encryptProgressCallback A callback to update the encryption progress
124126
* @returns A promise to execute the upload
125127
*/
126-
public uploadFile = ({
128+
public uploadFile = async ({
127129
from,
128130
size,
129131
bucketId,
130132
progressCallback,
131133
abortSignal,
132-
encryptProgressCallback,
133134
}: {
134135
from: Readable;
135136
size: number;
136137
bucketId: string;
137138
progressCallback: (progress: number) => void;
138139
abortSignal?: AbortSignal;
139-
encryptProgressCallback?: EncryptProgressCallback;
140140
}): Promise<string> => {
141+
const limits = await UsageService.instance.fetchLimits();
142+
if (limits?.maxUploadFileSize && size > limits.maxUploadFileSize) {
143+
const formattedSize = FormatUtils.humanFileSize(size);
144+
const formattedLimit = FormatUtils.humanFileSize(limits.maxUploadFileSize);
145+
throw new Error(`File is too big (${formattedSize} exceeds account upload limit of ${formattedLimit})`);
146+
}
147+
141148
if (size > FORTY_GIGABYTES) {
142149
throw new Error('File is too big (more than 40 GB)');
143150
}
@@ -147,7 +154,6 @@ export class NetworkFacade {
147154
fileSize: size,
148155
progressCallback,
149156
abortSignal,
150-
encryptProgressCallback,
151157
});
152158
};
153159
}

src/services/network/upload/upload-file.service.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import { BufferStream } from '../../../utils/stream.utils';
1515
import { DriveFileItem } from '../../../types/drive.types';
1616
import { CLIUtils } from '../../../utils/cli.utils';
1717
import { ThumbnailService } from '../../thumbnail.service';
18+
import { FormatUtils } from '../../../utils/format.utils';
1819

1920
export class UploadFileService {
2021
static readonly instance = new UploadFileService();
@@ -139,7 +140,7 @@ export class UploadFileService {
139140
if (debugMode) {
140141
const totalTime = Object.values(timings).reduce((sum, time) => sum + time, 0);
141142
const throughputMBps = CLIUtils.calculateThroughputMBps(stats.size, timings.networkUpload);
142-
CLIUtils.success(reporter, `Uploaded '${file.name}' (${CLIUtils.formatBytesToString(stats.size)})`);
143+
CLIUtils.success(reporter, `Uploaded '${file.name}' (${FormatUtils.humanFileSize(stats.size)})`);
143144
CLIUtils.log(
144145
reporter,
145146
'Timing breakdown:\n' +

src/services/usage.service.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,44 @@
11
import { SdkManager } from './sdk-manager.service';
2+
import { CacheService } from './cache.service';
3+
import { StorageTypes } from '@internxt/sdk/dist/drive/storage';
24

35
export class UsageService {
46
public static readonly instance: UsageService = new UsageService();
57
public static readonly INFINITE_LIMIT = 99 * Math.pow(1024, 4);
8+
private static readonly FETCH_USAGE_CACHE_KEY = 'usage:fetchUsage';
9+
private static readonly FETCH_SPACE_LIMIT_CACHE_KEY = 'usage:fetchSpaceLimit';
10+
private static readonly FETCH_LIMITS_CACHE_KEY = 'usage:fetchLimits';
611

712
public fetchUsage = async (): Promise<number> => {
13+
const cached = CacheService.instance.get<number>(UsageService.FETCH_USAGE_CACHE_KEY);
14+
if (cached !== null) return cached;
15+
816
const storageClient = SdkManager.instance.getStorage();
917
const driveUsage = await storageClient.spaceUsageV2();
1018

19+
CacheService.instance.set(UsageService.FETCH_USAGE_CACHE_KEY, driveUsage.total);
1120
return driveUsage.total;
1221
};
1322

1423
public fetchSpaceLimit = async (): Promise<number> => {
24+
const cached = CacheService.instance.get<number>(UsageService.FETCH_SPACE_LIMIT_CACHE_KEY);
25+
if (cached !== null) return cached;
26+
1527
const storageClient = SdkManager.instance.getStorage();
1628
const spaceLimit = await storageClient.spaceLimitV2();
29+
30+
CacheService.instance.set(UsageService.FETCH_SPACE_LIMIT_CACHE_KEY, spaceLimit.maxSpaceBytes);
1731
return spaceLimit.maxSpaceBytes;
1832
};
33+
34+
public fetchLimits = async (): Promise<StorageTypes.FileLimitsResponse> => {
35+
const cached = CacheService.instance.get<StorageTypes.FileLimitsResponse>(UsageService.FETCH_LIMITS_CACHE_KEY);
36+
if (cached !== null) return cached;
37+
38+
const storageClient = SdkManager.instance.getStorage();
39+
const limits = await storageClient.getFileVersionLimits();
40+
41+
CacheService.instance.set(UsageService.FETCH_LIMITS_CACHE_KEY, limits);
42+
return limits;
43+
};
1944
}

src/utils/cli.utils.ts

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -236,18 +236,6 @@ export class CLIUtils {
236236
return `${hoursFormated}:${minutesFormated}:${secondsFormated}.${msFormated}`;
237237
};
238238

239-
static readonly formatBytesToString = (bytes: number): string => {
240-
if (bytes <= 0) {
241-
return '0.00 KB';
242-
}
243-
const kb = bytes / 1024;
244-
if (kb < 1024) {
245-
return `${kb.toFixed(2)} KB`;
246-
}
247-
const mb = kb / 1024;
248-
return `${mb.toFixed(2)} MB`;
249-
};
250-
251239
static readonly calculateThroughputMBps = (bytes: number, milliseconds: number): number => {
252240
if (bytes <= 0 || milliseconds <= 0) {
253241
return 0;

src/utils/format.utils.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,9 @@ import { UsageService } from '../services/usage.service';
55
dayjs.extend(utc);
66
export class FormatUtils {
77
static readonly humanFileSize = (size: number) => {
8-
const i = size == 0 ? 0 : Math.floor(Math.log(size) / Math.log(1024));
9-
return Number((size / Math.pow(1024, i)).toFixed(2)) * 1 + ' ' + ['B', 'kB', 'MB', 'GB', 'TB'][i];
8+
const units = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
9+
const unitIndex = size === 0 ? 0 : Math.min(Math.floor(Math.log(size) / Math.log(1024)), units.length - 1);
10+
return Number((size / Math.pow(1024, unitIndex)).toFixed(2)) + ' ' + units[unitIndex];
1011
};
1112

1213
static readonly formatDate = (date: string | Date) => {

0 commit comments

Comments
 (0)