Skip to content

Commit

Permalink
Merge branch 'main' into feat/nomip-tag
Browse files Browse the repository at this point in the history
  • Loading branch information
Zyie authored Feb 6, 2025
2 parents 0b32ba5 + e52a15a commit bc18475
Show file tree
Hide file tree
Showing 10 changed files with 484 additions and 55 deletions.
21 changes: 20 additions & 1 deletion packages/assetpack/src/core/Asset.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,18 @@ import { extractTagsFromFileName } from './utils/extractTagsFromFileName.js';
import { getHash } from './utils/getHash.js';
import { path } from './utils/path.js';

export interface TransformStats
{
/* The duration of the transformation */
duration: number;
/* The last time the asset was transformed */
date: number;
/* Whether the transformation was successful */
success: boolean;
/* Error message if the transformation failed */
error?: string;
}

export interface AssetOptions
{
path: string;
Expand Down Expand Up @@ -38,6 +50,8 @@ export class Asset
path = '';
skip = false;

stats?: TransformStats;

private _state: 'deleted' | 'added' | 'modified' | 'normal' = 'added';
private _buffer?: Buffer | null = null;

Expand Down Expand Up @@ -137,7 +151,12 @@ export class Asset
Logger.warn('[AssetPack] folders should not have hashes. Contact the developer of the AssetPack');
}

this._hash ??= getHash(this.buffer);
try
{
this._hash ??= getHash(this.buffer);
}
catch (error)
{ /* empty */ }

return this._hash;
}
Expand Down
44 changes: 40 additions & 4 deletions packages/assetpack/src/core/AssetCache.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,39 @@
import fs from 'fs-extra';
import { path } from './utils/path.js';

import type { Asset } from './Asset.js';
import type { Asset, TransformStats } from './Asset.js';

export interface AssetCacheOptions
{
cacheName?: string;
}

export class AssetCache
/**
* Interface representing the Asset Cache.
* This interface defines the methods required for reading from and writing to the asset cache.
*/
export interface IAssetCache
{
/**
* Reads the asset cache and returns a record of cached assets.
* @returns {Record<string, CachedAsset>} A record containing the cached assets.
*/
read(): Record<string, CachedAsset>;

/**
* Writes an asset to the cache. this is usually the root asset.
* @param {Asset} asset - The asset to be written to the cache.
*/
write(asset: Asset): void;

/**
* Checks if the asset cache exists.
* @returns {boolean} Whether the asset cache exists.
*/
exists(): boolean;
}

export class AssetCache implements IAssetCache
{
public static location = '.assetpack';
private _assetCacheData: AssetCacheData | undefined;
Expand All @@ -18,6 +43,12 @@ export class AssetCache
{
this._cacheName = cacheName ?? 'assets';
}

exists()
{
return fs.existsSync(`${AssetCache.location}/${this._cacheName}.json`);
}

// save a file to disk
read()
{
Expand All @@ -31,7 +62,7 @@ export class AssetCache
}
catch (e)
{
return null;
return {};
}
}

Expand All @@ -47,6 +78,9 @@ export class AssetCache
fs.ensureDirSync(path.joinSafe(AssetCache.location));

fs.writeJSONSync(`${AssetCache.location}/${this._cacheName}.json`, schema, { spaces: 4 });

// assign the schema to the cache data
this._assetCacheData = schema;
}

private _serializeAsset(asset: Asset, schema: AssetCacheData['assets'], saveHash = false)
Expand Down Expand Up @@ -75,7 +109,8 @@ export class AssetCache
transformParent: asset.transformParent?.path,
metaData: { ...asset.metaData },
inheritedMetaData: { ...asset.inheritedMetaData },
transformData: { ...asset.transformData }
transformData: { ...asset.transformData },
stats: asset.stats ? { ...asset.stats } : undefined
};

if (!asset.isFolder && saveHash)
Expand All @@ -96,6 +131,7 @@ export interface CachedAsset
inheritedMetaData: Record<string, any>;
transformData: Record<string, any>;
transformParent: string | undefined;
stats: TransformStats | undefined;
}

type AssetCacheData = {
Expand Down
83 changes: 68 additions & 15 deletions packages/assetpack/src/core/AssetPack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@ import { generateCacheName } from './utils/generateCacheName.js';
import { path } from './utils/path.js';
import { promiseAllConcurrent } from './utils/promiseAllConcurrent.js';

import type { Asset } from './Asset.js';
import type { CachedAsset } from './AssetCache.js';
import type { Asset, TransformStats } from './Asset.js';
import type { AssetPackConfig } from './config.js';
import type { AssetPipe } from './pipes/AssetPipe.js';
import type { AssetSettings } from './pipes/PipeSystem.js';
Expand All @@ -34,6 +33,18 @@ export class AssetPack
private _entryPath = '';
private _outputPath = '';

/**
* Holds onto the optional onComplete callback passed in by the watch method
* will be called after each time asset pack has finished transforming the assets
*/
private _onWatchTransformComplete: ((root: Asset) => void) | undefined;

/**
* Holds a promise resolve function that will be called after the first time
* asset pack has finished transforming the assets when the watch method is called
*/
private _onWatchInitialTransformComplete: ((value: unknown) => void) | undefined;

constructor(config: AssetPackConfig = {})
{
this.config = merge.recursive(true, this._defaultConfig, config);
Expand All @@ -47,8 +58,7 @@ export class AssetPack
const { pipes, cache, cacheLocation } = this.config;

AssetCache.location = cacheLocation!;
let assetCacheData: Record<string, CachedAsset> | null = null;
let assetCache: AssetCache | null = null;
let assetCache: AssetCache | undefined;

// if there is no cache, lets just go ahead and remove the output folder
// and the cached info folder
Expand All @@ -67,9 +77,7 @@ export class AssetPack

// read the cache data, this will be used to restore the asset graph
// by the AssetWatcher
assetCacheData = assetCache.read();

if (assetCacheData)
if (assetCache.exists())
{
Logger.info('[AssetPack] cache found.');
}
Expand Down Expand Up @@ -104,7 +112,7 @@ export class AssetPack
// so it can be restored even if the process is terminated
this._assetWatcher = new AssetWatcher({
entryPath: this._entryPath,
assetCacheData,
assetCache,
ignore: this.config.ignore,
assetSettingsData: this.config.assetSettings as AssetSettings[] || [],
onUpdate: async (root: Asset) =>
Expand All @@ -119,10 +127,6 @@ export class AssetPack
{
Logger.error(`[AssetPack] Transform failed: ${e.message}`);
});

Logger.report({
type: 'buildSuccess',
});
},
onComplete: async (root: Asset) =>
{
Expand All @@ -131,11 +135,26 @@ export class AssetPack
// write back to the cache...
(assetCache as AssetCache).write(root);

// release the buffers from the cache
root.releaseChildrenBuffers();

Logger.info('cache updated.');
}

Logger.report({
type: 'buildSuccess',
});

this._onWatchTransformComplete?.(root);

// if the watch method was called, we need to resolve the promise
// that was created when the watch method was called
if (this._onWatchInitialTransformComplete)
{
this._onWatchInitialTransformComplete(root);

// clear the promise resolve function, so it only gets resolved once
this._onWatchInitialTransformComplete = undefined;
}
}
});
}
Expand All @@ -151,17 +170,37 @@ export class AssetPack
/**
* Watch the asset pack, this will watch the file system for changes and transform the assets.
* you can enable this when in development mode
*
* @param onComplete - optional callback that will be called after each time asset pack has finished transforming the assets
* @returns a promise that will resolve when the first time asset pack has finished transforming the assets
*/
public watch()
public watch(onComplete?: (root: Asset) => void)
{
return this._assetWatcher.watch();
this._onWatchTransformComplete = onComplete;

const onCompletePromise = new Promise((resolve) =>
{
this._onWatchInitialTransformComplete = resolve;
});

this._assetWatcher.watch();

return onCompletePromise;
}

/**
* Stop the asset pack, this will stop the watcher
*/
public stop()
{
return this._assetWatcher.stop();
}

public get rootAsset()
{
return this._assetWatcher.root;
}

private async _transform(asset: Asset)
{
await this._pipeSystem.start(asset);
Expand All @@ -177,11 +216,25 @@ export class AssetPack
{
if (asset.skip) return;

const stats = asset.stats = {
date: Date.now(),
duration: 0,
success: true,
} as TransformStats;

const now = performance.now();

await this._pipeSystem.transform(asset).catch((e) =>
{
stats.success = false;
stats.error = e.message;

// eslint-disable-next-line max-len
Logger.error(`[AssetPack] Transform failed:\ntransform: ${e.name}\nasset:${asset.path}\nerror:${e.message}`);
});

stats.duration = performance.now() - now;

index++;

const percent = Math.round((index / assetsToTransform.length) * 100);
Expand Down
39 changes: 23 additions & 16 deletions packages/assetpack/src/core/AssetWatcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@ import { applySettingToAsset } from './utils/applySettingToAsset.js';
import { path } from './utils/path.js';
import { syncAssetsWithCache } from './utils/syncAssetsWithCache.js';

import type { CachedAsset } from './AssetCache.js';
import type { IAssetCache } from './AssetCache.js';
import type { AssetSettings } from './pipes/PipeSystem.js';

export interface AssetWatcherOptions
{
entryPath: string;
assetCacheData?: Record<string, CachedAsset> | null;
assetCache?: IAssetCache;
assetSettingsData?: AssetSettings[];
ignore?: string | string[];
onUpdate: (root: Asset) => Promise<void>;
Expand Down Expand Up @@ -43,8 +43,8 @@ export class AssetWatcher
private _onComplete: (root: Asset) => void;
private _ignore: AssetIgnore;
private _assetSettingsData: AssetSettings[];
private _assetCacheData: Record<string, CachedAsset> | undefined | null;
private _initialised = false;
private _assetCache: IAssetCache | undefined;

constructor(options: AssetWatcherOptions)
{
Expand All @@ -59,35 +59,42 @@ export class AssetWatcher
entryPath
});

this._assetCacheData = options.assetCacheData;
this._assetCache = options.assetCache;
this._assetSettingsData = options.assetSettingsData ?? [];
}

private _init()
get root()
{
if (this._initialised) return;
this._initialised = true;
return this._root;
}

private _init()
{
Logger.report({
type: 'buildStart',
message: this._entryPath,
});

const asset = new Asset({
path: this._entryPath,
isFolder: true,
});
if (!this._initialised)
{
this._initialised = true;

this._assetHash[asset.path] = asset;
const asset = new Asset({
path: this._entryPath,
isFolder: true,
});

this._root = asset;
this._assetHash[asset.path] = asset;

this._collectAssets(asset);
this._root = asset;

this._collectAssets(this._root);
}

if (this._assetCacheData)
if (this._assetCache)
{
// now compare the cached asset with the current asset
syncAssetsWithCache(this._assetHash, this._assetCacheData);
syncAssetsWithCache(this._assetHash, this._assetCache.read());
}
}

Expand Down
1 change: 1 addition & 0 deletions packages/assetpack/src/core/utils/syncAssetsWithCache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ function syncAssetsFromCache(assetHash: Record<string, Asset>, cachedData: Recor
else
{
asset.state = 'normal';
asset.stats = cachedData[i].stats;
}
}
}
Expand Down
Loading

0 comments on commit bc18475

Please sign in to comment.