UNPKG

@fontoxml/fontoxml-development-tools

Version:

Development tools for Fonto.

201 lines (171 loc) 4.45 kB
import fs from 'fs-extra'; import path from 'path'; import utf8 from 'to-utf-8'; import mergeItems from './mergeItems.js'; /** @typedef {import('../../../src/getAppConfig.js').DevCmsConfig} DevCmsConfig */ /** * File extensions to use for specific fileType requests. * This is used to construct the query string in the browse endpoint to retrieve the correct files from Google Drive. * * @type {Object} */ const ASSET_TYPE_BY_EXTENSION = { xml: 'document', dita: 'document', ditamap: 'document', template: 'document-template', bmp: 'image', gif: 'image', jpeg: 'image', jpg: 'image', png: 'image', svg: 'image', mp3: 'audio', wav: 'audio', aac: 'audio', ogg: 'audio', }; export default class FileSystemStore { /** * @param {DevCmsConfig} config */ constructor(config) { this._filesRootPath = path.join(config.root, 'dev-cms', 'files'); this._uploadsRootPath = path.join(config.root, 'dev-cms', 'uploads'); this._assetTypeByExtension = { ...ASSET_TYPE_BY_EXTENSION, ...config.assetTypeByExtension, }; this._documentTemplateMetadataByFilename = {}; const documentTemplateMetadataJsonPath = path.join( config.root, 'dev-cms', 'stubs', 'document-template-metadata.json' ); if (fs.existsSync(documentTemplateMetadataJsonPath)) { try { this._documentTemplateMetadataByFilename = fs.readJsonSync( documentTemplateMetadataJsonPath ); } catch (error) { console.error( `\nError reading history.json file at "${documentTemplateMetadataJsonPath}"`, error ); throw error; } } } _getPathForFile(fileRelativePath) { if (!fileRelativePath || fileRelativePath === '.') { return null; } const pathInUploads = path.join( this._uploadsRootPath, fileRelativePath ); if (fs.existsSync(pathInUploads)) { return pathInUploads; } const pathInFiles = path.join(this._filesRootPath, fileRelativePath); if (fs.existsSync(pathInFiles)) { return pathInFiles; } return null; } getPath(documentId) { return this._getPathForFile(documentId); } existsSync(documentId) { return !!this.getPath(documentId); } load(documentId, callback) { const filePath = this.getPath(documentId); if (!filePath) { const error = new Error('File does not exist.'); error.status = 404; callback(error); return; } const stream = fs.createReadStream(filePath); let isDone = false; let data = ''; stream.on('data', (dataPart) => (data += dataPart)); stream.on('end', () => { if (isDone) { return; } isDone = true; callback(undefined, data); }); // Register the `error` event handler before starting the stream: stream.on('error', (error) => { if (isDone) { return; } isDone = true; callback(error) }); stream.pipe(utf8({ newline: false, detectSize: 10485760 })); } save(documentId, content, callback) { // Save file to disk (in dev-cms/uploads) const filePath = path.join(this._uploadsRootPath, documentId); fs.outputFile(filePath, content, callback); } removeSync(documentId) { // Only remove from uploads, files is read-only fs.removeSync(path.join(this._uploadsRootPath, documentId)); } _getFileType(filePath) { if (fs.lstatSync(filePath).isDirectory()) { return 'folder'; } const fileExtension = path.extname(filePath).substring(1).toLowerCase(); return this._assetTypeByExtension[fileExtension] || 'unknown'; } _listPathSync(rootPath, folderId, metadata) { const folderPath = path.join(rootPath, folderId); if (!fs.existsSync(folderPath)) { return null; } return fs .readdirSync(folderPath) .filter((filename) => !filename.startsWith('.')) .map((filename) => { const filePath = path.join(folderPath, filename); let fileId = path.relative(rootPath, filePath); if (path.sep === '\\') { fileId = fileId.replace(/\\/g, '/'); } return { id: fileId, type: this._getFileType(filePath), label: filename, metadata: { ...metadata, ...this._documentTemplateMetadataByFilename[filename], }, }; }); } listSync(folderId) { const filesItems = this._listPathSync( this._filesRootPath, folderId, {} ); const uploadsItems = this._listPathSync( this._uploadsRootPath, folderId, { isCmsUpload: true, } ); if (!filesItems && !uploadsItems) { return null; } return mergeItems(filesItems, uploadsItems); } }