Create the assets stream

This commit is contained in:
Christian Capeans 2022-12-05 11:44:48 +01:00
parent 589a06ab58
commit a2d04fdad2
3 changed files with 74 additions and 5 deletions

View File

@ -0,0 +1,19 @@
import type { ILocalFileSourceProviderOptions } from '..';
import { Readable } from 'stream';
import { createLocalFileSourceProvider } from '..';
describe('Stream assets', () => {
test('returns a stream', () => {
const options: ILocalFileSourceProviderOptions = {
backupFilePath: './test-file',
compressed: false,
encrypted: false,
};
const provider = createLocalFileSourceProvider(options);
const stream = provider.streamAssets();
expect(stream instanceof Readable).toBeTruthy();
});
});

View File

@ -1,17 +1,18 @@
import type { Readable } from 'stream';
import type { IMetadata, ISourceProvider, ProviderType } from '../../types';
import type { IMetadata, ISourceProvider, ProviderType } from '../../../types';
import fs from 'fs';
import zip from 'zlib';
import tar from 'tar';
import path from 'path';
import { keyBy } from 'lodash/fp';
import { chain } from 'stream-chain';
import { pipeline, PassThrough } from 'stream';
import { pipeline, PassThrough, Readable as ReadStream } from 'stream';
import { parser } from 'stream-json/jsonl/Parser';
import { createDecryptionCipher } from '../encryption';
import { collect } from '../utils';
import { createDecryptionCipher } from '../../encryption';
import { collect } from '../../utils';
type StreamItemArray = Parameters<typeof chain>[0];
@ -109,6 +110,35 @@ class LocalFileSourceProvider implements ISourceProvider {
return this.#streamJsonlDirectory('configuration');
}
streamAssets(): NodeJS.ReadableStream {
const inStream = this.#getBackupStream();
const outStream = new PassThrough({ objectMode: true });
pipeline(
[
inStream,
new tar.Parse({
filter(path, entry) {
if (entry.type !== 'File') {
return false;
}
const parts = path.split('/');
return parts[0] === 'assets' && parts[1] == 'uploads';
},
onentry(entry) {
const { path: filePath, size } = entry;
const file = path.basename(filePath);
outStream.write({ file, path: filePath, stats: { size }, stream: entry });
},
}),
],
() => outStream.end()
);
return outStream;
}
#getBackupStream(decompress: boolean = true) {
const path = this.options.backupFilePath;
const readStream = fs.createReadStream(path);

View File

@ -2,7 +2,9 @@
import type { IDestinationProvider, IMetadata, ProviderType } from '../../types';
import chalk from 'chalk';
import { Duplex } from 'stream';
import { Duplex, Writable } from 'stream';
import path from 'path';
import * as fse from 'fs-extra';
import { mapSchemasValues } from '../utils';
@ -57,6 +59,24 @@ class LocalStrapiDestinationProvider implements IDestinationProvider {
return mapSchemasValues(schemas);
}
getAssetsStream(): NodeJS.WritableStream {
if (!this.strapi) {
throw new Error('Not able to stream Assets. Strapi instance not found');
}
const assetsDirectory = path.join(this.strapi.dirs.static.public, 'uploads');
return new Writable({
objectMode: true,
write(chunk, _encoding, callback) {
const entryPath = path.join(assetsDirectory, chunk.file);
const writableStream = fse.createWriteStream(entryPath);
chunk.stream
.pipe(writableStream)
.on('close', () => callback())
.on('error', callback);
},
});
}
getEntitiesStream(): Duplex {
const self = this;