diff --git a/package-lock.json b/package-lock.json index e555e6aa..534a092f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12241,9 +12241,9 @@ } }, "watchpack": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.0.0.tgz", - "integrity": "sha512-xSdCxxYZWNk3VK13bZRYhsQpfa8Vg63zXG+3pyU8ouqSLRCv4IGXIp9Kr226q6GBkGRlZrST2wwKtjfKz2m7Cg==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.0.1.tgz", + "integrity": "sha512-vO8AKGX22ZRo6PiOFM9dC0re8IcKh8Kd/aH2zeqUc6w4/jBGlTy2P7fTC6ekT0NjVeGjgU2dGC5rNstKkeLEQg==", "dev": true, "requires": { "glob-to-regexp": "^0.4.1", @@ -12257,9 +12257,9 @@ "dev": true }, "webpack": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.3.0.tgz", - "integrity": "sha512-0LumZ36pDaWsh+PO3i6FpNQYVqNu5Rs/Jn5AoYQyHpUxIlzn5H7omwApiEzaIUeWDccExOpkNZGO6agCVSqXPg==", + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.3.2.tgz", + "integrity": "sha512-DXsfHoI6lQAR3KnQh7+FsRfs9fs+TEvzXCA35UbKv4kVuzslg7QCMAcpFRZNDMjdtm9N/PoO54XEzGN9TeacQg==", "dev": true, "requires": { "@types/eslint-scope": "^3.7.0", @@ -12283,9 +12283,9 @@ "pkg-dir": "^4.2.0", "schema-utils": "^3.0.0", "tapable": "^2.0.0", - "terser-webpack-plugin": "^5.0.0", + "terser-webpack-plugin": "^5.0.3", "watchpack": "^2.0.0", - "webpack-sources": "^2.1.0" + "webpack-sources": "^2.1.1" }, "dependencies": { "acorn": { @@ -12295,9 +12295,9 @@ "dev": true }, "webpack-sources": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-2.1.1.tgz", - "integrity": "sha512-hraq9n99K564zuZUsE61iATO3jvzxOmGo20UlOe3zgdHOBp8inTJgv7EY4RgvCv7Ywx0/vpQTyYSjnFpv4gNtQ==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-2.2.0.tgz", + "integrity": "sha512-bQsA24JLwcnWGArOKUxYKhX3Mz/nK1Xf6hxullKERyktjNMC4x8koOeaDNTA2fEJ09BdWLbM/iTW0ithREUP0w==", "dev": true, "requires": { "source-list-map": "^2.0.1", diff --git a/package.json b/package.json index 3d0a0f10..a849e9d4 100644 --- a/package.json +++ b/package.json @@ -79,7 +79,7 @@ "npm-run-all": "^4.1.5", "prettier": "^2.1.2", "standard-version": "^9.0.0", - "webpack": "^5.3.0" + "webpack": "^5.3.2" }, "keywords": [ "webpack", diff --git a/src/index.js b/src/index.js index f96140b8..fa49bca0 100644 --- a/src/index.js +++ b/src/index.js @@ -87,7 +87,14 @@ class CopyPlugin { }); } - static async runPattern(compiler, compilation, logger, cache, inputPattern) { + static async runPattern( + compiler, + compilation, + logger, + cache, + inputPattern, + index + ) { const pattern = typeof inputPattern === 'string' ? { from: inputPattern } @@ -357,7 +364,10 @@ class CopyPlugin { logger.debug(`getting cache for '${absoluteFilename}'...`); try { - cacheEntry = await cache.getPromise(sourceFilename, null); + cacheEntry = await cache.getPromise( + `${sourceFilename}|${index}`, + null + ); } catch (error) { compilation.errors.push(error); @@ -417,71 +427,6 @@ class CopyPlugin { logger.debug(`read '${absoluteFilename}'`); - if (pattern.transform) { - logger.log(`transforming content for '${absoluteFilename}'...`); - - if (pattern.cacheTransform) { - const cacheDirectory = pattern.cacheTransform.directory - ? pattern.cacheTransform.directory - : typeof pattern.cacheTransform === 'string' - ? pattern.cacheTransform - : findCacheDir({ name: 'copy-webpack-plugin' }) || - os.tmpdir(); - let defaultCacheKeys = { - version, - transform: pattern.transform, - contentHash: crypto - .createHash('md4') - .update(data) - .digest('hex'), - }; - - defaultCacheKeys = - typeof pattern.cacheTransform.keys === 'function' - ? await pattern.cacheTransform.keys( - defaultCacheKeys, - absoluteFilename - ) - : { - ...defaultCacheKeys, - ...pattern.cacheTransform.keys, - }; - - const cacheKeys = serialize(defaultCacheKeys); - - try { - logger.debug( - `getting transformation cache for '${absoluteFilename}'...` - ); - - const cachedResult = await cacache.get( - cacheDirectory, - cacheKeys - ); - - ({ data } = cachedResult); - } catch (_ignoreError) { - logger.debug( - `no transformation cache for '${absoluteFilename}'...` - ); - - data = await pattern.transform(data, absoluteFilename); - - logger.debug( - `caching transformation for '${absoluteFilename}'` - ); - - await cacache.put(cacheDirectory, cacheKeys, data); - - logger.debug( - `cached transformation for '${absoluteFilename}'` - ); - } - } else { - data = await pattern.transform(data, absoluteFilename); - } - } - result.source = new RawSource(data); if (cache) { @@ -506,7 +451,7 @@ class CopyPlugin { logger.debug(`storing cache for '${absoluteFilename}'...`); try { - await cache.storePromise(sourceFilename, null, { + await cache.storePromise(`${sourceFilename}|${index}`, null, { source: result.source, snapshot, }); @@ -521,6 +466,108 @@ class CopyPlugin { } } + if (pattern.transform) { + logger.log(`transforming content for '${absoluteFilename}'...`); + + const buffer = result.source.source(); + + if (pattern.cacheTransform) { + const defaultCacheKeys = { + version, + sourceFilename, + transform: pattern.transform, + contentHash: crypto + .createHash('md4') + .update(buffer) + .digest('hex'), + index, + }; + const cacheKeys = `transform|${serialize( + typeof pattern.cacheTransform.keys === 'function' + ? await pattern.cacheTransform.keys( + defaultCacheKeys, + absoluteFilename + ) + : { ...defaultCacheKeys, ...pattern.cacheTransform.keys } + )}`; + + let cacheItem; + let cacheDirectory; + + logger.debug( + `getting transformation cache for '${absoluteFilename}'...` + ); + + // webpack@5 API + if (cache) { + cacheItem = cache.getItemCache( + cacheKeys, + cache.getLazyHashedEtag(result.source) + ); + + result.source = await cacheItem.getPromise(); + } else { + cacheDirectory = pattern.cacheTransform.directory + ? pattern.cacheTransform.directory + : typeof pattern.cacheTransform === 'string' + ? pattern.cacheTransform + : findCacheDir({ name: 'copy-webpack-plugin' }) || + os.tmpdir(); + + let cached; + + try { + cached = await cacache.get(cacheDirectory, cacheKeys); + } catch (error) { + logger.debug( + `no transformation cache for '${absoluteFilename}'...` + ); + } + + // eslint-disable-next-line no-undefined + result.source = cached ? new RawSource(cached.data) : undefined; + } + + logger.debug( + result.source + ? `found transformation cache for '${absoluteFilename}'` + : `no transformation cache for '${absoluteFilename}'` + ); + + if (!result.source) { + const transformed = await pattern.transform( + buffer, + absoluteFilename + ); + + result.source = new RawSource(transformed); + + logger.debug( + `caching transformation for '${absoluteFilename}'...` + ); + + // webpack@5 API + if (cache) { + await cacheItem.storePromise(result.source); + } else { + try { + await cacache.put(cacheDirectory, cacheKeys, transformed); + } catch (error) { + compilation.errors.push(error); + + return; + } + } + + logger.debug(`cached transformation for '${absoluteFilename}'`); + } + } else { + result.source = new RawSource( + await pattern.transform(buffer, absoluteFilename) + ); + } + } + if (pattern.toType === 'template') { logger.log( `interpolating template '${filename}' for '${sourceFilename}'...` @@ -615,14 +662,15 @@ class CopyPlugin { try { assets = await Promise.all( - this.patterns.map((item) => + this.patterns.map((item, index) => limit(async () => CopyPlugin.runPattern( compiler, compilation, logger, cache, - item + item, + index ) ) ) diff --git a/test/CopyPlugin.test.js b/test/CopyPlugin.test.js index 54abf1f1..5c8c99a2 100644 --- a/test/CopyPlugin.test.js +++ b/test/CopyPlugin.test.js @@ -927,6 +927,148 @@ describe('CopyPlugin', () => { resolve(); }); }); + + it('should work with the "transform" option', async () => { + const cacheDirectory = path.resolve(__dirname, './outputs/.cache/simple'); + + await del([ + cacheDirectory, + path.resolve(__dirname, '../node_modules/.cache/copy-webpack-plugin'), + ]); + + const compiler = getCompiler({ + cache: { + type: 'filesystem', + cacheDirectory, + }, + }); + + const getMyVar = () => { + return 'baz'; + }; + + new CopyPlugin({ + patterns: [ + { + from: path.resolve( + __dirname, + './fixtures/directory/directoryfile.txt' + ), + to: 'new0.txt', + }, + { + from: path.resolve( + __dirname, + './fixtures/directory/directoryfile.txt' + ), + to: 'new1.txt', + transform: (content) => { + return `${content.toString()}added1`; + }, + cacheTransform: true, + }, + { + from: path.resolve( + __dirname, + './fixtures/directory/directoryfile.txt' + ), + to: 'new1-2.txt', + transform: (content) => { + return `${content.toString()}added1`; + }, + cacheTransform: true, + }, + { + from: path.resolve( + __dirname, + './fixtures/directory/directoryfile.txt' + ), + to: 'new2.txt', + transform: (content) => { + return `${content.toString()}added2`; + }, + cacheTransform: false, + }, + { + from: path.resolve( + __dirname, + './fixtures/directory/directoryfile.txt' + ), + to: 'new3.txt', + transform: (content) => { + return `${content.toString()}added3`; + }, + cacheTransform: true, + }, + { + from: path.resolve( + __dirname, + './fixtures/directory/directoryfile.txt' + ), + to: 'new4.txt', + transform: (content) => { + return `${content.toString()}${getMyVar()}`; + }, + cacheTransform: { + keys: { + foo: 'bar', + }, + }, + }, + { + from: path.resolve( + __dirname, + './fixtures/directory/directoryfile.txt' + ), + to: 'new5.txt', + transform: (content) => { + return `${content.toString()}${getMyVar()}`; + }, + cacheTransform: { + keys: { + foo: 'baz', + }, + }, + }, + ], + }).apply(compiler); + + const { stats } = await compile(compiler); + + if (webpack.version[0] === '4') { + expect( + Object.keys(stats.compilation.assets).filter( + (assetName) => stats.compilation.assets[assetName].emitted + ).length + ).toBe(8); + } else { + expect(stats.compilation.emittedAssets.size).toBe(8); + } + + expect(readAssets(compiler, stats)).toMatchSnapshot('assets'); + expect(stats.compilation.errors).toMatchSnapshot('errors'); + expect(stats.compilation.warnings).toMatchSnapshot('warnings'); + + await new Promise(async (resolve) => { + const { stats: newStats } = await compile(compiler); + + if (webpack.version[0] === '4') { + expect( + Object.keys(newStats.compilation.assets).filter( + (assetName) => newStats.compilation.assets[assetName].emitted + ).length + ).toBe(7); + } else { + expect(newStats.compilation.emittedAssets.size).toBe(1); + } + + expect(readAssets(compiler, newStats)).toMatchSnapshot('assets'); + expect(newStats.compilation.errors).toMatchSnapshot('errors'); + expect(newStats.compilation.warnings).toMatchSnapshot('warnings'); + + resolve(); + }); + }); }); describe('stats', () => { diff --git a/test/__snapshots__/CopyPlugin.test.js.snap b/test/__snapshots__/CopyPlugin.test.js.snap index faa46b10..b37e63fc 100644 --- a/test/__snapshots__/CopyPlugin.test.js.snap +++ b/test/__snapshots__/CopyPlugin.test.js.snap @@ -140,6 +140,38 @@ exports[`CopyPlugin cache should work with the "memory" cache: warnings 1`] = `A exports[`CopyPlugin cache should work with the "memory" cache: warnings 2`] = `Array []`; +exports[`CopyPlugin cache should work with the "transform" option: assets 1`] = ` +Object { + "new0.txt": "new", + "new1-2.txt": "newadded1", + "new1.txt": "newadded1", + "new2.txt": "newadded2", + "new3.txt": "newadded3", + "new4.txt": "newbaz", + "new5.txt": "newbaz", +} +`; + +exports[`CopyPlugin cache should work with the "transform" option: assets 2`] = ` +Object { + "new0.txt": "new", + "new1-2.txt": "newadded1", + "new1.txt": "newadded1", + "new2.txt": "newadded2", + "new3.txt": "newadded3", + "new4.txt": "newbaz", + "new5.txt": "newbaz", +} +`; + +exports[`CopyPlugin cache should work with the "transform" option: errors 1`] = `Array []`; + +exports[`CopyPlugin cache should work with the "transform" option: errors 2`] = `Array []`; + +exports[`CopyPlugin cache should work with the "transform" option: warnings 1`] = `Array []`; + +exports[`CopyPlugin cache should work with the "transform" option: warnings 2`] = `Array []`; + exports[`CopyPlugin logging should logging when "from" is a directory: logs 1`] = ` Object { "logs": Array [ diff --git a/test/cacheTransform-option.test.js b/test/cacheTransform-option.test.js index 5d405492..9f9b0db5 100644 --- a/test/cacheTransform-option.test.js +++ b/test/cacheTransform-option.test.js @@ -2,6 +2,7 @@ import fs from 'fs'; import path from 'path'; import zlib from 'zlib'; +import webpack from 'webpack'; import cacache from 'cacache'; import findCacheDir from 'find-cache-dir'; import isGzip from 'is-gzip'; @@ -10,477 +11,485 @@ import { runEmit } from './helpers/run'; const FIXTURES_DIR = path.join(__dirname, 'fixtures'); -describe('cache option', () => { - const defaultCacheDir = findCacheDir({ name: 'copy-webpack-plugin' }); - const cacheDir1 = findCacheDir({ name: 'copy-webpack-plugin-1' }); - const cacheDir2 = findCacheDir({ name: 'copy-webpack-plugin-2' }); - const cacheDir3 = findCacheDir({ name: 'copy-webpack-plugin-3' }); - const cacheDir4 = findCacheDir({ name: 'copy-webpack-plugin-4' }); - - beforeEach(() => [ - cacache.rm.all(defaultCacheDir), - cacache.rm.all(cacheDir1), - cacache.rm.all(cacheDir2), - cacache.rm.all(cacheDir3), - cacache.rm.all(cacheDir4), - ]); - - it('should cache when "from" is a file', (done) => { - const newContent = 'newchanged!'; - const from = 'file.txt'; - - runEmit({ - expectedAssetKeys: ['file.txt'], - expectedAssetContent: { - 'file.txt': newContent, - }, - patterns: [ - { - from, - cacheTransform: true, - transform: function transform(content) { - return new Promise((resolve) => { - resolve(`${content}changed!`); - }); - }, +if (webpack.version[0] === '4') { + describe('cache option', () => { + const defaultCacheDir = findCacheDir({ name: 'copy-webpack-plugin' }); + const cacheDir1 = findCacheDir({ name: 'copy-webpack-plugin-1' }); + const cacheDir2 = findCacheDir({ name: 'copy-webpack-plugin-2' }); + const cacheDir3 = findCacheDir({ name: 'copy-webpack-plugin-3' }); + const cacheDir4 = findCacheDir({ name: 'copy-webpack-plugin-4' }); + + beforeEach(() => [ + cacache.rm.all(defaultCacheDir), + cacache.rm.all(cacheDir1), + cacache.rm.all(cacheDir2), + cacache.rm.all(cacheDir3), + cacache.rm.all(cacheDir4), + ]); + + it('should cache when "from" is a file', (done) => { + const newContent = 'newchanged!'; + const from = 'file.txt'; + + runEmit({ + expectedAssetKeys: ['file.txt'], + expectedAssetContent: { + 'file.txt': newContent, }, - ], - }) - .then(() => - cacache.ls(defaultCacheDir).then((cacheEntries) => { - const cacheKeys = Object.keys(cacheEntries); - - expect(cacheKeys).toHaveLength(1); - }) - ) - .then(done) - .catch(done); - }); - - it('should cache files when "from" is a directory', (done) => { - const from = 'directory'; - - runEmit({ - expectedAssetKeys: [ - '.dottedfile', - 'directoryfile.txt', - 'nested/deep-nested/deepnested.txt', - 'nested/nestedfile.txt', - ], - expectedAssetContent: { - '.dottedfile': 'dottedfile contents\nchanged!', - 'directoryfile.txt': 'newchanged!', - 'nested/nestedfile.txt': 'changed!', - }, - patterns: [ - { - from, - cacheTransform: true, - transform: function transform(content) { - return new Promise((resolve) => { - resolve(`${content}changed!`); - }); + patterns: [ + { + from, + cacheTransform: true, + transform: function transform(content) { + return new Promise((resolve) => { + resolve(`${content}changed!`); + }); + }, }, + ], + }) + .then(() => + cacache.ls(defaultCacheDir).then((cacheEntries) => { + const cacheKeys = Object.keys(cacheEntries); + + expect(cacheKeys).toHaveLength(1); + }) + ) + .then(done) + .catch(done); + }); + + it('should cache files when "from" is a directory', (done) => { + const from = 'directory'; + + runEmit({ + expectedAssetKeys: [ + '.dottedfile', + 'directoryfile.txt', + 'nested/deep-nested/deepnested.txt', + 'nested/nestedfile.txt', + ], + expectedAssetContent: { + '.dottedfile': 'dottedfile contents\nchanged!', + 'directoryfile.txt': 'newchanged!', + 'nested/nestedfile.txt': 'changed!', }, - ], - }) - .then(() => - cacache.ls(defaultCacheDir).then((cacheEntries) => { - const cacheKeys = Object.keys(cacheEntries); - - expect(cacheKeys).toHaveLength(3); - }) - ) - .then(done) - .catch(done); - }); - - it('should cache when "from" is a glob', (done) => { - const from = 'directory/*.txt'; - - runEmit({ - expectedAssetKeys: ['directory/directoryfile.txt'], - expectedAssetContent: { - 'directory/directoryfile.txt': 'newchanged!', - }, - patterns: [ - { - from, - cacheTransform: true, - transform: function transform(content) { - return new Promise((resolve) => { - resolve(`${content}changed!`); - }); + patterns: [ + { + from, + cacheTransform: true, + transform: function transform(content) { + return new Promise((resolve) => { + resolve(`${content}changed!`); + }); + }, }, + ], + }) + .then(() => + cacache.ls(defaultCacheDir).then((cacheEntries) => { + const cacheKeys = Object.keys(cacheEntries); + + expect(cacheKeys).toHaveLength(4); + }) + ) + .then(done) + .catch(done); + }); + + it('should cache when "from" is a glob', (done) => { + const from = 'directory/*.txt'; + + runEmit({ + expectedAssetKeys: ['directory/directoryfile.txt'], + expectedAssetContent: { + 'directory/directoryfile.txt': 'newchanged!', }, - ], - }) - .then(() => - cacache.ls(defaultCacheDir).then((cacheEntries) => { - const cacheKeys = Object.keys(cacheEntries); - - expect(cacheKeys).toHaveLength(1); - }) - ) - .then(done) - .catch(done); - }); - - it('should cache file with custom cache directory', (done) => { - const newContent = 'newchanged!'; - const from = 'file.txt'; - - runEmit({ - expectedAssetKeys: ['file.txt'], - expectedAssetContent: { - 'file.txt': newContent, - }, - patterns: [ - { - from, - cacheTransform: cacheDir1, - transform: (content) => { - return new Promise((resolve) => { - resolve(`${content}changed!`); - }); + patterns: [ + { + from, + cacheTransform: true, + transform: function transform(content) { + return new Promise((resolve) => { + resolve(`${content}changed!`); + }); + }, }, + ], + }) + .then(() => + cacache.ls(defaultCacheDir).then((cacheEntries) => { + const cacheKeys = Object.keys(cacheEntries); + + expect(cacheKeys).toHaveLength(1); + }) + ) + .then(done) + .catch(done); + }); + + it('should cache file with custom cache directory', (done) => { + const newContent = 'newchanged!'; + const from = 'file.txt'; + + runEmit({ + expectedAssetKeys: ['file.txt'], + expectedAssetContent: { + 'file.txt': newContent, }, - ], - }) - .then(() => - cacache.ls(cacheDir1).then((cacheEntries) => { - const cacheKeys = Object.keys(cacheEntries); - - expect(cacheKeys).toHaveLength(1); - }) - ) - .then(done) - .catch(done); - }); - - it('should cache file with custom cache directory when "cacheTransform" is an object', (done) => { - const newContent = 'newchanged!'; - const from = 'file.txt'; - - runEmit({ - expectedAssetKeys: ['file.txt'], - expectedAssetContent: { - 'file.txt': newContent, - }, - patterns: [ - { - from, - cacheTransform: { - directory: cacheDir2, - }, - transform: (content) => { - return new Promise((resolve) => { - resolve(`${content}changed!`); - }); + patterns: [ + { + from, + cacheTransform: cacheDir1, + transform: (content) => { + return new Promise((resolve) => { + resolve(`${content}changed!`); + }); + }, }, + ], + }) + .then(() => + cacache.ls(cacheDir1).then((cacheEntries) => { + const cacheKeys = Object.keys(cacheEntries); + + expect(cacheKeys).toHaveLength(1); + }) + ) + .then(done) + .catch(done); + }); + + it('should cache file with custom cache directory when "cacheTransform" is an object', (done) => { + const newContent = 'newchanged!'; + const from = 'file.txt'; + + runEmit({ + expectedAssetKeys: ['file.txt'], + expectedAssetContent: { + 'file.txt': newContent, }, - ], - }) - .then(() => - cacache.ls(cacheDir2).then((cacheEntries) => { - const cacheKeys = Object.keys(cacheEntries); - - expect(cacheKeys).toHaveLength(1); - }) - ) - .then(done) - .catch(done); - }); - - it('should cache file with custom object cache keys when "cacheTransform" is an object', (done) => { - const newContent = 'newchanged!'; - const from = 'file.txt'; - - runEmit({ - expectedAssetKeys: ['file.txt'], - expectedAssetContent: { - 'file.txt': newContent, - }, - patterns: [ - { - from, - cacheTransform: { - keys: { - key: 'foobar', + patterns: [ + { + from, + cacheTransform: { + directory: cacheDir2, + }, + transform: (content) => { + return new Promise((resolve) => { + resolve(`${content}changed!`); + }); }, }, - transform: (content) => { - return new Promise((resolve) => { - resolve(`${content}changed!`); - }); - }, + ], + }) + .then(() => + cacache.ls(cacheDir2).then((cacheEntries) => { + const cacheKeys = Object.keys(cacheEntries); + + expect(cacheKeys).toHaveLength(1); + }) + ) + .then(done) + .catch(done); + }); + + it('should cache file with custom object cache keys when "cacheTransform" is an object', (done) => { + const newContent = 'newchanged!'; + const from = 'file.txt'; + + runEmit({ + expectedAssetKeys: ['file.txt'], + expectedAssetContent: { + 'file.txt': newContent, }, - ], - }) - .then(() => - cacache.ls(defaultCacheDir).then((cacheEntries) => { - const cacheKeys = Object.keys(cacheEntries); - - expect(cacheKeys).toHaveLength(1); - - cacheKeys.forEach((cacheKey) => { - // eslint-disable-next-line no-new-func - const cacheEntry = new Function( - `'use strict'\nreturn (${cacheKey});` - )(); - - // expect(cacheEntry.pattern.from).toBe(from); - expect(cacheEntry.key).toBe('foobar'); - }); - }) - ) - .then(done) - .catch(done); - }); - - it('should cache file with custom function cache keys when "cacheTransform" is an object', (done) => { - const newContent = 'newchanged!'; - const from = 'file.txt'; - - runEmit({ - expectedAssetKeys: ['file.txt'], - expectedAssetContent: { - 'file.txt': newContent, - }, - patterns: [ - { - from, - cacheTransform: { - keys: (defaultCacheKeys, absoluteFrom) => { - expect(absoluteFrom).toBeDefined(); - - return { - ...defaultCacheKeys, + patterns: [ + { + from, + cacheTransform: { + keys: { key: 'foobar', - }; + }, + }, + transform: (content) => { + return new Promise((resolve) => { + resolve(`${content}changed!`); + }); }, }, - transform: (content) => { - return new Promise((resolve) => { - resolve(`${content}changed!`); + ], + }) + .then(() => + cacache.ls(defaultCacheDir).then((cacheEntries) => { + const cacheKeys = Object.keys(cacheEntries); + + expect(cacheKeys).toHaveLength(1); + + cacheKeys.forEach((cacheKey) => { + // eslint-disable-next-line no-new-func + const cacheEntry = new Function( + `'use strict'\nreturn (${cacheKey.replace('transform|', '')});` + )(); + + // expect(cacheEntry.pattern.from).toBe(from); + expect(cacheEntry.key).toBe('foobar'); }); - }, + }) + ) + .then(done) + .catch(done); + }); + + it('should cache file with custom function cache keys when "cacheTransform" is an object', (done) => { + const newContent = 'newchanged!'; + const from = 'file.txt'; + + runEmit({ + expectedAssetKeys: ['file.txt'], + expectedAssetContent: { + 'file.txt': newContent, }, - ], - }) - .then(() => - cacache.ls(defaultCacheDir).then((cacheEntries) => { - const cacheKeys = Object.keys(cacheEntries); - - expect(cacheKeys).toHaveLength(1); - - cacheKeys.forEach((cacheKey) => { - // eslint-disable-next-line no-new-func - const cacheEntry = new Function( - `'use strict'\nreturn (${cacheKey});` - )(); - - // expect(cacheEntry.pattern.from).toBe(from); - expect(cacheEntry.key).toBe('foobar'); - }); - }) - ) - .then(done) - .catch(done); - }); - - it('should cache file with custom async function cache keys when "cacheTransform" is an object', (done) => { - const newContent = 'newchanged!'; - const from = 'file.txt'; - - runEmit({ - expectedAssetKeys: ['file.txt'], - expectedAssetContent: { - 'file.txt': newContent, - }, - patterns: [ - { - from, - cacheTransform: { - keys: async (defaultCacheKeys, absoluteFrom) => { - expect(absoluteFrom).toBeDefined(); - - return { - ...defaultCacheKeys, - key: 'foobar', - }; + patterns: [ + { + from, + cacheTransform: { + keys: (defaultCacheKeys, absoluteFrom) => { + expect(absoluteFrom).toBeDefined(); + + return { + ...defaultCacheKeys, + key: 'foobar', + }; + }, + }, + transform: (content) => { + return new Promise((resolve) => { + resolve(`${content}changed!`); + }); }, }, - transform: (content) => { - return new Promise((resolve) => { - resolve(`${content}changed!`); + ], + }) + .then(() => + cacache.ls(defaultCacheDir).then((cacheEntries) => { + const cacheKeys = Object.keys(cacheEntries); + + expect(cacheKeys).toHaveLength(1); + + cacheKeys.forEach((cacheKey) => { + // eslint-disable-next-line no-new-func + const cacheEntry = new Function( + `'use strict'\nreturn (${cacheKey.replace('transform|', '')});` + )(); + + // expect(cacheEntry.pattern.from).toBe(from); + expect(cacheEntry.key).toBe('foobar'); }); - }, + }) + ) + .then(done) + .catch(done); + }); + + it('should cache file with custom async function cache keys when "cacheTransform" is an object', (done) => { + const newContent = 'newchanged!'; + const from = 'file.txt'; + + runEmit({ + expectedAssetKeys: ['file.txt'], + expectedAssetContent: { + 'file.txt': newContent, }, - ], - }) - .then(() => - cacache.ls(defaultCacheDir).then((cacheEntries) => { - const cacheKeys = Object.keys(cacheEntries); - - expect(cacheKeys).toHaveLength(1); - - cacheKeys.forEach((cacheKey) => { - // eslint-disable-next-line no-new-func - const cacheEntry = new Function( - `'use strict'\nreturn (${cacheKey});` - )(); - - // expect(cacheEntry.pattern.from).toBe(from); - expect(cacheEntry.key).toBe('foobar'); - }); - }) - ) - .then(done) - .catch(done); - }); - - it('should cache file with custom object cache keys and custom cache directory when "cacheTransform" is an object', (done) => { - const newContent = 'newchanged!'; - const from = 'file.txt'; - - runEmit({ - expectedAssetKeys: ['file.txt'], - expectedAssetContent: { - 'file.txt': newContent, - }, - patterns: [ - { - from, - cacheTransform: { - directory: cacheDir3, - keys: { - key: 'foobar', + patterns: [ + { + from, + cacheTransform: { + keys: async (defaultCacheKeys, absoluteFrom) => { + expect(absoluteFrom).toBeDefined(); + + return { + ...defaultCacheKeys, + key: 'foobar', + }; + }, + }, + transform: (content) => { + return new Promise((resolve) => { + resolve(`${content}changed!`); + }); }, }, - transform(content) { - return new Promise((resolve) => { - resolve(`${content}changed!`); + ], + }) + .then(() => + cacache.ls(defaultCacheDir).then((cacheEntries) => { + const cacheKeys = Object.keys(cacheEntries); + + expect(cacheKeys).toHaveLength(1); + + cacheKeys.forEach((cacheKey) => { + // eslint-disable-next-line no-new-func + const cacheEntry = new Function( + `'use strict'\nreturn (${cacheKey.replace('transform|', '')});` + )(); + + // expect(cacheEntry.pattern.from).toBe(from); + expect(cacheEntry.key).toBe('foobar'); }); - }, + }) + ) + .then(done) + .catch(done); + }); + + it('should cache file with custom object cache keys and custom cache directory when "cacheTransform" is an object', (done) => { + const newContent = 'newchanged!'; + const from = 'file.txt'; + + runEmit({ + expectedAssetKeys: ['file.txt'], + expectedAssetContent: { + 'file.txt': newContent, }, - ], - }) - .then(() => - cacache.ls(cacheDir3).then((cacheEntries) => { - const cacheKeys = Object.keys(cacheEntries); - - expect(cacheKeys).toHaveLength(1); - - cacheKeys.forEach((cacheKey) => { - expect(cacheKey).toContain('foobar'); - }); - }) - ) - .then(done) - .catch(done); - }); - - it('should cache file with custom function cache keys and custom cache directory when "cacheTransform" is an object', (done) => { - const newContent = 'newchanged!'; - const from = 'file.txt'; - - runEmit({ - expectedAssetKeys: ['file.txt'], - expectedAssetContent: { - 'file.txt': newContent, - }, - patterns: [ - { - from, - cacheTransform: { - directory: cacheDir4, - keys: (defaultCacheKeys, absoluteFrom) => { - expect(absoluteFrom).toBeDefined(); - - return { - ...defaultCacheKeys, + patterns: [ + { + from, + cacheTransform: { + directory: cacheDir3, + keys: { key: 'foobar', - }; + }, + }, + transform(content) { + return new Promise((resolve) => { + resolve(`${content}changed!`); + }); }, }, - transform(content) { - return new Promise((resolve) => { - resolve(`${content}changed!`); + ], + }) + .then(() => + cacache.ls(cacheDir3).then((cacheEntries) => { + const cacheKeys = Object.keys(cacheEntries); + + expect(cacheKeys).toHaveLength(1); + + cacheKeys.forEach((cacheKey) => { + expect(cacheKey).toContain('foobar'); }); - }, + }) + ) + .then(done) + .catch(done); + }); + + it('should cache file with custom function cache keys and custom cache directory when "cacheTransform" is an object', (done) => { + const newContent = 'newchanged!'; + const from = 'file.txt'; + + runEmit({ + expectedAssetKeys: ['file.txt'], + expectedAssetContent: { + 'file.txt': newContent, }, - ], - }) - .then(() => - cacache.ls(cacheDir4).then((cacheEntries) => { - const cacheKeys = Object.keys(cacheEntries); - - expect(cacheKeys).toHaveLength(1); - - cacheKeys.forEach((cacheKey) => { - expect(cacheKey).toContain('foobar'); - }); - }) - ) - .then(done) - .catch(done); - }); + patterns: [ + { + from, + cacheTransform: { + directory: cacheDir4, + keys: (defaultCacheKeys, absoluteFrom) => { + expect(absoluteFrom).toBeDefined(); + + return { + ...defaultCacheKeys, + key: 'foobar', + }; + }, + }, + transform(content) { + return new Promise((resolve) => { + resolve(`${content}changed!`); + }); + }, + }, + ], + }) + .then(() => + cacache.ls(cacheDir4).then((cacheEntries) => { + const cacheKeys = Object.keys(cacheEntries); - it('should cache binary file', (done) => { - const from = 'file.txt.gz'; - const content = fs.readFileSync(path.join(FIXTURES_DIR, from)); - const expectedNewContent = zlib.gzipSync('newchanged!'); - - expect(isGzip(content)).toBe(true); - expect(isGzip(expectedNewContent)).toBe(true); - - runEmit({ - expectedAssetKeys: ['file.txt.gz'], - expectedAssetContent: { - 'file.txt.gz': expectedNewContent, - }, - patterns: [ - { - from, - cacheTransform: true, - // eslint-disable-next-line no-shadow - transform: function transform(content) { - expect(isGzip(content)).toBe(true); - - return new Promise((resolve) => { - // eslint-disable-next-line no-shadow - zlib.unzip(content, (error, content) => { - if (error) { - throw error; - } - - const newContent = Buffer.from(`${content}changed!`); + expect(cacheKeys).toHaveLength(1); + cacheKeys.forEach((cacheKey) => { + expect(cacheKey).toContain('foobar'); + }); + }) + ) + .then(done) + .catch(done); + }); + + it('should cache binary file', (done) => { + const from = 'file.txt.gz'; + const content = fs.readFileSync(path.join(FIXTURES_DIR, from)); + const expectedNewContent = zlib.gzipSync('newchanged!'); + + expect(isGzip(content)).toBe(true); + expect(isGzip(expectedNewContent)).toBe(true); + + runEmit({ + expectedAssetKeys: ['file.txt.gz'], + expectedAssetContent: { + 'file.txt.gz': expectedNewContent, + }, + patterns: [ + { + from, + cacheTransform: true, + // eslint-disable-next-line no-shadow + transform: function transform(content) { + expect(isGzip(content)).toBe(true); + + return new Promise((resolve) => { // eslint-disable-next-line no-shadow - zlib.gzip(newContent, (error, compressedData) => { + zlib.unzip(content, (error, content) => { if (error) { throw error; } - expect(isGzip(compressedData)).toBe(true); + const newContent = Buffer.from(`${content}changed!`); + + // eslint-disable-next-line no-shadow + zlib.gzip(newContent, (error, compressedData) => { + if (error) { + throw error; + } + + expect(isGzip(compressedData)).toBe(true); - return resolve(compressedData); + return resolve(compressedData); + }); }); }); - }); + }, }, - }, - ], - }) - .then(() => - cacache.ls(defaultCacheDir).then((cacheEntries) => { - const cacheKeys = Object.keys(cacheEntries); - - expect(cacheKeys).toHaveLength(1); - }) - ) - .then(done) - .catch(done); + ], + }) + .then(() => + cacache.ls(defaultCacheDir).then((cacheEntries) => { + const cacheKeys = Object.keys(cacheEntries); + + expect(cacheKeys).toHaveLength(1); + }) + ) + .then(done) + .catch(done); + }); + }); +} else { + describe('cache option', () => { + it('skip', () => { + expect(true).toBe(true); + }); }); -}); +}