Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 11 additions & 8 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,21 +37,22 @@
],
"dependencies": {
"@dashlane/pqc-kem-kyber512-node": "1.0.0",
"@inquirer/prompts": "8.2.0",
"@internxt/inxt-js": "2.2.9",
"@inquirer/prompts": "8.2.1",
"@internxt/inxt-js": "2.3.0",
"@internxt/lib": "1.4.1",
"@internxt/sdk": "1.13.1",
"@internxt/sdk": "1.14.2",
"@oclif/core": "4.8.0",
"@oclif/plugin-autocomplete": "3.2.40",
"axios": "1.13.5",
"better-sqlite3": "12.6.2",
"bip39": "3.1.0",
"body-parser": "2.2.2",
"cli-progress": "3.12.0",
"dayjs": "1.11.19",
"dotenv": "17.3.1",
"express": "5.2.1",
"express-async-handler": "1.2.0",
"fast-xml-parser": "5.3.6",
"fast-xml-parser": "5.3.7",
"hash-wasm": "4.12.0",
"mime-types": "3.0.2",
"open": "11.0.0",
Expand All @@ -61,6 +62,7 @@
"range-parser": "1.2.1",
"selfsigned": "5.5.0",
"tty-table": "5.0.0",
"typeorm": "0.3.28",
"winston": "3.19.0"
},
"devDependencies": {
Expand All @@ -70,17 +72,18 @@
"@types/cli-progress": "3.11.6",
"@types/express": "5.0.6",
"@types/mime-types": "3.0.1",
"@types/node": "25.2.3",
"@types/node": "25.3.0",
"@types/range-parser": "1.2.7",
"@vitest/coverage-istanbul": "4.0.18",
"@vitest/spy": "4.0.18",
"eslint": "9.39.2",
"husky": "9.1.7",
"lint-staged": "16.2.7",
"nodemon": "3.1.11",
"oclif": "4.22.77",
"nodemon": "3.1.13",
"oclif": "4.22.79",
"prettier": "3.8.1",
"rimraf": "6.1.2",
"rimraf": "6.1.3",
"sql.js": "1.14.0",
"ts-node": "10.9.2",
"typescript": "5.9.3",
"vitest": "4.0.18",
Expand Down
3 changes: 1 addition & 2 deletions src/constants/configs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,8 @@ import os from 'node:os';

export const INTERNXT_CLI_DATA_DIR = path.join(os.homedir(), '.internxt-cli');
export const INTERNXT_CLI_LOGS_DIR = path.join(INTERNXT_CLI_DATA_DIR, 'logs');
export const INTERNXT_TMP_DIR = os.tmpdir();
export const CREDENTIALS_FILE = path.join(INTERNXT_CLI_DATA_DIR, '.inxtcli');
export const DRIVE_SQLITE_FILE = path.join(INTERNXT_CLI_DATA_DIR, 'internxt-cli-drive.sqlite');
export const DRIVE_SQLITE_FILE = path.join(INTERNXT_CLI_DATA_DIR, 'internxt-cli-drive.db');
export const WEBDAV_SSL_CERTS_DIR = path.join(INTERNXT_CLI_DATA_DIR, 'certs');
export const WEBDAV_CONFIGS_FILE = path.join(INTERNXT_CLI_DATA_DIR, 'config.webdav.inxt');
export const WEBDAV_DEFAULT_HOST = '127.0.0.1';
Expand Down
2 changes: 2 additions & 0 deletions src/hooks/prerun/auth_check.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { SdkManager } from '../../services/sdk-manager.service';
import { AuthService } from '../../services/auth.service';
import Webdav from '../../commands/webdav';
import WebDAVConfig from '../../commands/webdav-config';
import { DatabaseService } from '../../services/database/database.service';

const CommandsToSkip = [Whoami, Login, LoginLegacy, Logout, Logs, Webdav, WebDAVConfig];
const hook: Hook<'prerun'> = async function (opts) {
Expand All @@ -22,6 +23,7 @@ const hook: Hook<'prerun'> = async function (opts) {
SdkManager.init({ token, workspaceToken: workspace?.workspaceCredentials.token });
CLIUtils.done(jsonFlag);
CLIUtils.clearPreviousLine(jsonFlag);
await DatabaseService.instance.initialize();
} catch (error) {
const err = error as Error;
CLIUtils.catchError({
Expand Down
42 changes: 42 additions & 0 deletions src/services/database/database.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { DataSource } from 'typeorm';
import { DriveFileModel } from './drive-file/drive-file.model';
import { DriveFolderModel } from './drive-folder/drive-folder.model';
import { DRIVE_SQLITE_FILE } from '../../constants/configs';

export class DatabaseService {
public static readonly instance = new DatabaseService();

public dataSource = new DataSource(
process.env.NODE_ENV === 'test'
? {
type: 'sqljs',
autoSave: false,
logging: false,
synchronize: true,
entities: [DriveFileModel, DriveFolderModel],
}
: {
type: 'better-sqlite3',
database: DRIVE_SQLITE_FILE,
logging: false,
synchronize: true,
entities: [DriveFileModel, DriveFolderModel],
},
);

public initialize = () => {
return this.dataSource.initialize();
};

public destroy = () => {
return this.dataSource.destroy();
};

public clear = () => {
return this.dataSource.synchronize(true);
};

public drop = () => {
return this.dataSource.dropDatabase();
};
}
9 changes: 3 additions & 6 deletions src/services/database/drive-file/drive-file.attributes.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
export interface DriveFileAttributes {
id: number;
name: string;
type?: string;
uuid: string;
fileId: string;
folderId: number;
name: string;
type?: string | null;
fileId?: string | null;
folderUuid: string;
bucket: string;
relativePath: string;
createdAt: Date;
updatedAt: Date;
size: number;
Expand Down
18 changes: 2 additions & 16 deletions src/services/database/drive-file/drive-file.domain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,12 @@ import { DriveFileItem } from '../../../types/drive.types';
import { DriveFileAttributes } from './drive-file.attributes';

export class DriveFile implements DriveFileAttributes {
id: number;
name: string;
type?: string;
type?: string | null;
uuid: string;
fileId: string;
folderId: number;
fileId?: string | null;
folderUuid: string;
bucket: string;
relativePath: string;
createdAt: Date;
updatedAt: Date;
size: number;
Expand All @@ -19,31 +16,25 @@ export class DriveFile implements DriveFileAttributes {
modificationTime: Date;

constructor({
id,
name,
type,
uuid,
fileId,
folderId,
folderUuid,
bucket,
relativePath,
createdAt,
updatedAt,
size,
status,
creationTime,
modificationTime,
}: DriveFileAttributes) {
this.id = id;
this.name = name;
this.type = type;
this.uuid = uuid;
this.fileId = fileId;
this.folderId = folderId;
this.folderUuid = folderUuid;
this.bucket = bucket;
this.relativePath = relativePath;
this.createdAt = createdAt;
this.updatedAt = updatedAt;
this.size = size;
Expand All @@ -58,15 +49,12 @@ export class DriveFile implements DriveFileAttributes {

public toJSON(): DriveFileAttributes {
return {
id: this.id,
name: this.name,
type: this.type,
uuid: this.uuid,
fileId: this.fileId,
folderId: this.folderId,
folderUuid: this.folderUuid,
bucket: this.bucket,
relativePath: this.relativePath,
createdAt: this.createdAt,
updatedAt: this.updatedAt,
size: this.size,
Expand All @@ -79,12 +67,10 @@ export class DriveFile implements DriveFileAttributes {
public toItem(): DriveFileItem {
return {
itemType: 'file',
id: this.id,
name: this.name,
type: this.type,
uuid: this.uuid,
fileId: this.fileId,
folderId: this.folderId,
folderUuid: this.folderUuid,
bucket: this.bucket,
createdAt: this.createdAt,
Expand Down
41 changes: 41 additions & 0 deletions src/services/database/drive-file/drive-file.model.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { DriveFileAttributes } from './drive-file.attributes';
import { Column, Entity, PrimaryColumn } from 'typeorm';

@Entity('drive_file')
export class DriveFileModel implements DriveFileAttributes {
@PrimaryColumn({ nullable: false, type: 'varchar' })
declare uuid: string;

@Column({ nullable: false, type: 'varchar' })
declare name: string;

@Column({ nullable: true, type: 'varchar' })
declare type?: string | null;

@Column({ nullable: true, type: 'varchar' })
declare fileId?: string | null;

@Column({ nullable: false, type: 'varchar' })
declare folderUuid: string;

@Column({ nullable: false, type: 'varchar' })
declare bucket: string;

@Column({ nullable: false, type: 'varchar' })
declare createdAt: Date;

@Column({ nullable: false, type: 'varchar' })
declare updatedAt: Date;

@Column({ nullable: false, type: 'bigint' })
declare size: number;

@Column({ nullable: false, type: 'varchar' })
declare status: 'EXISTS' | 'TRASHED' | 'DELETED';

@Column({ nullable: false, type: 'varchar' })
declare creationTime: Date;

@Column({ nullable: false, type: 'varchar' })
declare modificationTime: Date;
}
44 changes: 44 additions & 0 deletions src/services/database/drive-file/drive-file.repository.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { ErrorUtils } from '../../../utils/errors.utils';
import { DatabaseService } from '../database.service';
import { DriveFile } from './drive-file.domain';
import { DriveFileModel } from './drive-file.model';

const BATCH_SIZE = 100;

export class FileRepository {
public static readonly instance = new FileRepository();

private fileRepository = DatabaseService.instance.dataSource.getRepository(DriveFileModel);

public createOrUpdate = async (files: DriveFileModel[]) => {
if (files.length === 0) return;

try {
for (let i = 0; i < files.length; i += BATCH_SIZE) {
const chunk = files.slice(i, i + BATCH_SIZE);

await this.fileRepository.upsert(chunk, { conflictPaths: ['uuid'] });
}

return files.map((file) => DriveFile.build(file));
} catch (error) {
ErrorUtils.report(error, { files });
}
};

public updateByUuid = async (uuid: string, update: Partial<DriveFileModel>) => {
try {
return await this.fileRepository.update({ uuid }, update);
} catch (error) {
ErrorUtils.report(error, { uuid });
}
};

public delete = async (uuids: string[]) => {
try {
return await this.fileRepository.delete(uuids);
} catch (error) {
ErrorUtils.report(error, { uuids });
}
};
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
export interface DriveFolderAttributes {
id: number;
name: string;
uuid: string;
name: string;
status: 'EXISTS' | 'TRASHED';
relativePath: string;
parentId: number | null;
parentUuid: string | null;
createdAt: Date;
updatedAt: Date;
creationTime: Date;
modificationTime: Date;
}
Loading