diff --git a/src/core/Asset.ts b/src/core/Asset.ts index 77e9f43..1ea3fb1 100644 --- a/src/core/Asset.ts +++ b/src/core/Asset.ts @@ -76,6 +76,8 @@ export class Asset this.children.splice(index, 1); asset.parent = null; } + + asset.releaseChildrenBuffers(); } addTransformChild(asset: Asset) diff --git a/src/core/AssetPack.ts b/src/core/AssetPack.ts index 89a5488..9215a32 100644 --- a/src/core/AssetPack.ts +++ b/src/core/AssetPack.ts @@ -203,7 +203,7 @@ export class AssetPack { if (asset.state === 'deleted') { - deleteAsset(asset); + deleteAssetFiles(asset); } else { @@ -218,7 +218,7 @@ export class AssetPack } } -async function deleteAsset(asset: Asset) +export async function deleteAssetFiles(asset: Asset) { asset.transformChildren.forEach((child) => { diff --git a/src/core/AssetWatcher.ts b/src/core/AssetWatcher.ts index 551b427..3bf8f7e 100644 --- a/src/core/AssetWatcher.ts +++ b/src/core/AssetWatcher.ts @@ -2,6 +2,7 @@ import chokidar from 'chokidar'; import fs from 'fs-extra'; import { Asset } from './Asset.js'; import { AssetIgnore } from './AssetIgnore.js'; +import { deleteAssetFiles } from './AssetPack.js'; import { Logger } from './logger/Logger.js'; import { applySettingToAsset } from './utils/applySettingToAsset.js'; import { path } from './utils/path.js'; @@ -222,6 +223,7 @@ export class AssetWatcher else if (asset.state === 'normal') { asset.state = 'modified'; + deleteAssetFiles(asset); } // flag all folders as modified.. diff --git a/src/manifest/pixiManifest.ts b/src/manifest/pixiManifest.ts index 9f3437a..9fc4f2e 100644 --- a/src/manifest/pixiManifest.ts +++ b/src/manifest/pixiManifest.ts @@ -102,6 +102,8 @@ function collectAssets( ) { if (asset.skip) return; + // an item may have been deleted, so we don't want to add it to the manifest! + if (asset.state === 'deleted') return; let localBundle = bundle; diff --git a/test/core/Assetpack.test.ts b/test/core/Assetpack.test.ts index ea9016d..e54e18c 100644 --- a/test/core/Assetpack.test.ts +++ b/test/core/Assetpack.test.ts @@ -2,8 +2,11 @@ import fs from 'fs-extra'; import { existsSync } from 'node:fs'; import { join } from 'path'; import { describe, expect, it } from 'vitest'; +import { cacheBuster } from '../../src/cache-buster/cacheBuster.js'; import { AssetPack } from '../../src/core/AssetPack.js'; +import { getHash } from '../../src/core/index.js'; import { logAssetGraph } from '../../src/core/utils/logAssetGraph.js'; +import { pixiManifest } from '../../src/manifest/pixiManifest.js'; import { assetPath, createAssetPipe, @@ -125,6 +128,73 @@ describe('Core', () => expect(fs.readJSONSync(join(outputDir, 'json.json'))).toStrictEqual({ nice: 'test' }); }); + it('should delete previously hashed versions of an asset', { timeout: 10000 }, async () => + { + const testName = 'watch-delete-hash'; + const inputDir = `${getInputDir(pkg, testName)}/`; + const outputDir = getOutputDir(pkg, testName); + + createFolder( + pkg, + { + name: testName, + files: [{ + name: 'json.json', + content: assetPath('json/json.json'), + }], + folders: [], + }); + + const testFile = join(inputDir, 'json.json'); + + const assetpack = new AssetPack({ + entry: inputDir, cacheLocation: getCacheDir(pkg, testName), + output: outputDir, + cache: true, + pipes: [ + cacheBuster(), + pixiManifest(), + ] + }); + + await assetpack.watch(); + + const origHash = getHash(join(inputDir, 'json.json')); + + expect(existsSync(join(outputDir, `json-${origHash}.json`))).toBe(true); + + fs.writeJSONSync(testFile, { nice: 'test' }); + + await new Promise((resolve) => + { + setTimeout(resolve, 1500); + }); + + expect(existsSync(join(outputDir, `json-${origHash}.json`))).toBe(false); + const newHash = getHash(join(inputDir, 'json.json')); + + expect(existsSync(join(outputDir, `json-${newHash}.json`))).toBe(true); + + fs.removeSync(testFile); + + await new Promise((resolve) => + { + setTimeout(resolve, 1500); + }); + + await assetpack.stop(); + + expect(existsSync(join(outputDir, `json-${origHash}.json`))).toBe(false); + expect(existsSync(join(outputDir, `json-${newHash}.json`))).toBe(false); + expect(fs.readJSONSync(join(outputDir, 'manifest.json'))).toStrictEqual({ + bundles: [ + { + name: 'default', + assets: [] + }] + }); + }); + it('should ignore specified files when watching', async () => { const testName = 'watch-ignore';