UNPKG

@jsreport/jsreport-core

Version:
231 lines (172 loc) 7.33 kB
const Request = require('../../shared/request') module.exports = async (reporter) => { if ( reporter.options.migrateResourcesToAssets === false || reporter.documentStore.collection('scripts') == null || reporter.documentStore.collection('data') == null ) { return } const migrated = await reporter.settings.findValue('core-migrated-resources') if (migrated) { return } const req = Request({}) await reporter.documentStore.beginTransaction(req) try { const templateIds = await reporter.documentStore.collection('templates').find({}, { _id: 1 }, req) if (templateIds.length !== 0) { reporter.logger.debug('Running migration "resourcesToAssets"') } const templateToAssetResourcesMap = new Map() const dataToAssetMap = new Map() const dataEntitiesToRemove = [] for (const templateId of templateIds) { const template = await reporter.documentStore.collection('templates').findOne({ _id: templateId._id }, req) if (template.resources == null) { continue } if (Array.isArray(template.resources.items)) { for (const dataItem of template.resources.items) { const dataEntity = await reporter.documentStore.collection('data').findOne({ shortid: dataItem.shortid }, req) if (dataEntity) { let newAsset if (dataToAssetMap.has(dataEntity._id)) { newAsset = dataToAssetMap.get(dataEntity._id) } else { const assetProps = { content: Buffer.from(dataEntity.dataJson || ''), folder: dataEntity.folder || null } if (dataEntity.readPermissions != null) { assetProps.readPermissions = dataEntity.readPermissions } if (dataEntity.editPermissions != null) { assetProps.editPermissions = dataEntity.editPermissions } newAsset = await insertUnique(reporter, 'assets', `${dataEntity.name}.json`, assetProps, req) dataToAssetMap.set(dataEntity._id, newAsset) } const assetResources = templateToAssetResourcesMap.get(template._id) || [] assetResources.push({ ...newAsset, originalName: dataEntity.name }) templateToAssetResourcesMap.set(template._id, assetResources) dataEntitiesToRemove.push(dataEntity._id) } } } const templateAssetResources = templateToAssetResourcesMap.get(template._id) || [] if (templateAssetResources.length > 0) { const scriptProps = { content: ( ` // THIS SCRIPT WAS GENERATED BY MIGRATION IN V3, IT PROVIDES BACKWARD COMPATIBILITY // WITH THE DEPRECATED jsreport-resources https://jsreport.net/learn/resources // THE RECOMMENDATION NOW IS TO USE jsreport-localization https://jsreport.net/learn/localization // SO WHEN YOU DECIDE TO USE jsreport-localization TO FULLY REPLACE THE jsreport-resources // JUST REMOVE THIS SCRIPT FROM YOUR TEMPLATE AND DELETE IT const jsreport = require('jsreport-proxy') async function beforeRender (req, res) { req.options.language = req.options.language || req.template.localization?.language const defaultLanguage = ${template.resources.defaultLanguage != null ? '\'' + template.resources.defaultLanguage + '\'' : 'undefined'} const assetsResources = [${templateAssetResources.map(a => `{ name: '${a.originalName}', shortid: '${a.shortid}' }`).join(', ')}] const resources = await Promise.all(assetsResources.map(async (r) => { const asset = await jsreport.documentStore.collection('assets').findOne({ shortid: r.shortid }) if (asset == null) { throw new Error(\`Asset resources with shortid \${r.shortid} was not found (resource lookup)\`) } asset.resourceName = r.name asset.content = asset.content.toString() return asset })) resources.forEach((r) => { r.dataJson = r.content r.data = JSON.parse(r.content) }) req.options.resources = resources req.data.$resources = resources const resourcesByName = {} resources.forEach((r) => { resourcesByName[r.resourceName] = r.data }) req.options.resource = resourcesByName req.data.$resource = resourcesByName const isLocalizedRequest = req.options.language != null || defaultLanguage != null if (isLocalizedRequest) { let languageUsed let applicableResources = [] if (req.options.language) { languageUsed = req.options.language applicableResources = resources.filter((r) => r.resourceName.startsWith(\`\${languageUsed}-\`)) } if (!applicableResources.length && defaultLanguage) { languageUsed = defaultLanguage applicableResources = resources.filter((r) => r.resourceName.startsWith(\`\${languageUsed}-\`)) } console.log(\`Found \${applicableResources.length} resources for language "\${languageUsed}"\`) req.options.localizedResources = applicableResources req.data.$localizedResources = applicableResources const localizedResourceByName = {} applicableResources.forEach((r) => { localizedResourceByName[r.resourceName.substring(\`\${languageUsed}-\`.length)] = r.data }) req.options.localizedResource = applicableResources.length === 1 ? applicableResources[0].data : localizedResourceByName req.data.$localizedResource = req.options.localizedResource } } ` ), folder: template.folder || null } if (template.readPermissions != null) { scriptProps.readPermissions = template.readPermissions } if (template.editPermissions != null) { scriptProps.editPermissions = template.editPermissions } const newScript = await insertUnique(reporter, 'scripts', `${template.name}_resources`, scriptProps, req) template.scripts = template.scripts || [] template.scripts.unshift({ shortid: newScript.shortid }) } template.resources = null await reporter.documentStore.collection('templates').update({ _id: template._id }, { $set: template }, req) } for (const dataEntityId of dataEntitiesToRemove) { await reporter.documentStore.collection('data').remove({ _id: dataEntityId }, req) } if (templateIds.length !== 0) { reporter.logger.debug('Migration "resourcesToAssets" finished') } await reporter.documentStore.commitTransaction(req) await reporter.settings.addOrSet('core-migrated-resources', true) } catch (migrationErr) { await reporter.documentStore.rollbackTransaction(req) migrationErr.message = `Migration "resourcesToAssets" failed: ${migrationErr.message}` throw migrationErr } } async function insertUnique (reporter, collectionName, baseName, entity, req) { let newEntity let tryCount = 0 while (newEntity == null) { try { const entityName = '_'.repeat(tryCount) + baseName newEntity = await reporter.documentStore.collection(collectionName).insert({ ...entity, name: entityName }, req) return newEntity } catch (insertError) { tryCount++ if (insertError.code === 'DUPLICATED_ENTITY') { continue } else { throw insertError } } } }