diff --git a/src/cli/commands/import.command.ts b/src/cli/commands/import.command.ts index 8e9763c..109c389 100644 --- a/src/cli/commands/import.command.ts +++ b/src/cli/commands/import.command.ts @@ -1,4 +1,5 @@ import { TSVFileReader } from '../../shared/libs/file-reader/tsv-file-reader.js'; +import { Offer } from '../../shared/types/offer-type.js'; import { Command } from './command.interface.js'; export class ImportCommand implements Command { @@ -6,13 +7,23 @@ export class ImportCommand implements Command { return '--import'; } - public execute(...parameters: string[]): void { + private onImportedOffer(offer: Offer): void { + console.info(offer); + } + + private onCompleteImport(count: number) { + console.info(`${count} rows imported`); + } + + public async execute(...parameters: string[]): Promise { const [filename] = parameters; const fileReader = new TSVFileReader(filename.trim()); + fileReader.on('line', this.onImportedOffer); + fileReader.once('end', this.onCompleteImport); + try { fileReader.read(); - console.log(fileReader.toArray()); } catch (err) { if (!(err instanceof Error)) { throw err; diff --git a/src/shared/libs/file-reader/tsv-file-reader.ts b/src/shared/libs/file-reader/tsv-file-reader.ts index 2ab334b..87c0d1c 100644 --- a/src/shared/libs/file-reader/tsv-file-reader.ts +++ b/src/shared/libs/file-reader/tsv-file-reader.ts @@ -1,18 +1,15 @@ -import { readFileSync } from 'node:fs'; +import EventEmitter from 'node:events'; +import { createReadStream } from 'node:fs'; + import { FileReader } from './index.js'; import { Offer, TypeUser } from '../../types/index.js'; -export class TSVFileReader implements FileReader { - private rawData = ''; +export class TSVFileReader extends EventEmitter implements FileReader { + private CHUNK_SIZE = 16384; constructor( private readonly filename: string - ) {} - - private parseRawDataToOffers(): Offer[] { - return this.rawData - .split('\n') - .filter((row) => row.trim().length > 0) - .map((line) => this.parseLineToOffer(line)); + ) { + super(); } private parseLineToOffer(line: string): Offer { @@ -80,18 +77,30 @@ export class TSVFileReader implements FileReader { return {name, email, avatarUser, password, typeUser:TypeUser[typeUser as 'Pro' | 'Usual']}; } - private validateRawData(): void { - if (! this.rawData) { - throw new Error('File was not read'); - } - } + public async read(): Promise { + const readStream = createReadStream(this.filename, { + highWaterMark: this.CHUNK_SIZE, + encoding: 'utf-8' + }); - public read(): void { - this.rawData = readFileSync(this.filename, 'utf-8'); - } + let remainingData = ''; + let nextLinePosititon = -1; + let importedRowCouint = 0; - public toArray(): Offer[] { - this.validateRawData(); - return this.parseRawDataToOffers(); + for await (const chunk of readStream) { + remainingData += chunk.toString(); + + while((nextLinePosititon = remainingData.indexOf('\n')) >= 0) { + const completeRow = remainingData.slice(0, nextLinePosititon + 1); + remainingData = remainingData.slice(++nextLinePosititon); + importedRowCouint++; + + const parsedOffer = this.parseLineToOffer(completeRow); + this.emit('line', parsedOffer); + } + } + + this.emit('end', importedRowCouint); } } + diff --git a/src/shared/libs/file-writer/file-writer.interface.ts b/src/shared/libs/file-writer/file-writer.interface.ts new file mode 100644 index 0000000..6d8afaa --- /dev/null +++ b/src/shared/libs/file-writer/file-writer.interface.ts @@ -0,0 +1,3 @@ +export interface FileWriter { + write(row: string): void; +} diff --git a/src/shared/libs/file-writer/index.ts b/src/shared/libs/file-writer/index.ts new file mode 100644 index 0000000..22c2b5c --- /dev/null +++ b/src/shared/libs/file-writer/index.ts @@ -0,0 +1 @@ +export { FileWriter } from './file-writer.interface.js'; diff --git a/src/shared/libs/file-writer/tsv-file-wtiter.ts b/src/shared/libs/file-writer/tsv-file-wtiter.ts new file mode 100644 index 0000000..9038213 --- /dev/null +++ b/src/shared/libs/file-writer/tsv-file-wtiter.ts @@ -0,0 +1,28 @@ +import { FileWriter } from './index.js'; +import { WriteStream } from 'node:fs'; +import { createWriteStream } from 'node:fs'; + +export class TSVFileWriter implements FileWriter { + + private stream: WriteStream; + + constructor(filename: string) { + this.stream = createWriteStream(filename, { + flags: 'w', + encoding: 'utf-8', + autoClose: true + }); + } + + public async write(row: string): Promise { + const writeSuccess = this.stream.write(`${row}\n`); + + if (! writeSuccess) { + return new Promise((resolve) => { + this.stream.once('drain', () => resolve(true)); + }); + } + + return Promise.resolve(); + } +}